3 * Copyright (c) 2014-2015, ARM Limited. All rights reserved.
4 * Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
6 * SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Library/AcpiLib.h>
13 #include <Library/BaseLib.h>
14 #include <Library/BaseMemoryLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
18 #include <Protocol/AcpiSystemDescriptionTable.h>
19 #include <Protocol/AcpiTable.h>
20 #include <Protocol/FirmwareVolume2.h>
22 #include <IndustryStandard/Acpi.h>
25 Locate and Install the ACPI tables from the Firmware Volume if it verifies
26 the function condition.
28 @param AcpiFile Guid of the ACPI file into the Firmware Volume
29 @param CheckAcpiTableFunction Function that checks if the ACPI table should be installed
31 @return EFI_SUCCESS The function completed successfully.
32 @return EFI_NOT_FOUND The protocol could not be located.
33 @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
37 LocateAndInstallAcpiFromFvConditional (
38 IN CONST EFI_GUID
*AcpiFile
,
39 IN EFI_LOCATE_ACPI_CHECK CheckAcpiTableFunction
43 EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
;
44 EFI_HANDLE
*HandleBuffer
;
45 UINTN NumberOfHandles
;
48 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FvInstance
;
51 EFI_ACPI_COMMON_HEADER
*AcpiTable
;
56 // Ensure the ACPI Table is present
57 Status
= gBS
->LocateProtocol (
58 &gEfiAcpiTableProtocolGuid
,
60 (VOID
**)&AcpiProtocol
62 if (EFI_ERROR (Status
)) {
69 // Locate all the Firmware Volume protocols.
70 Status
= gBS
->LocateHandleBuffer (
72 &gEfiFirmwareVolume2ProtocolGuid
,
77 if (EFI_ERROR (Status
)) {
81 // Looking for FV with ACPI storage file
82 for (Index
= 0; Index
< NumberOfHandles
; Index
++) {
84 // Get the protocol on this handle
85 // This should not fail because of LocateHandleBuffer
87 Status
= gBS
->HandleProtocol (
89 &gEfiFirmwareVolume2ProtocolGuid
,
92 if (EFI_ERROR (Status
)) {
93 goto FREE_HANDLE_BUFFER
;
96 while (Status
== EFI_SUCCESS
) {
97 // AcpiTable must be allocated by ReadSection (ie: AcpiTable == NULL)
100 // See if it has the ACPI storage file
101 Status
= FvInstance
->ReadSection (
110 if (!EFI_ERROR (Status
)) {
112 AcpiTableSize
= ((EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
)->Length
;
113 ASSERT (SectionSize
>= AcpiTableSize
);
117 "- Found '%c%c%c%c' ACPI Table\n",
118 (((EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
)->Signature
& 0xFF),
119 ((((EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
)->Signature
>> 8) & 0xFF),
120 ((((EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
)->Signature
>> 16) & 0xFF),
121 ((((EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
)->Signature
>> 24) & 0xFF)
124 // Is the ACPI table valid?
125 if (CheckAcpiTableFunction
) {
126 Valid
= CheckAcpiTableFunction ((EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTable
);
131 // Install the ACPI Table
133 Status
= AcpiProtocol
->InstallAcpiTable (
141 // Free memory allocated by ReadSection
142 gBS
->FreePool (AcpiTable
);
144 if (EFI_ERROR (Status
)) {
148 // Increment the section instance
156 // Free any allocated buffers
158 gBS
->FreePool (HandleBuffer
);
164 Locate and Install the ACPI tables from the Firmware Volume
166 @param AcpiFile Guid of the ACPI file into the Firmware Volume
168 @return EFI_SUCCESS The function completed successfully.
169 @return EFI_NOT_FOUND The protocol could not be located.
170 @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
174 LocateAndInstallAcpiFromFv (
175 IN CONST EFI_GUID
*AcpiFile
178 return LocateAndInstallAcpiFromFvConditional (AcpiFile
, NULL
);
182 This function calculates and updates a UINT8 checksum
183 in an ACPI description table header.
185 @param Buffer Pointer to buffer to checksum
186 @param Size Number of bytes to checksum
188 @retval EFI_SUCCESS The function completed successfully.
189 @retval EFI_INVALID_PARAMETER Invalid parameter.
195 IN OUT UINT8
*Buffer
,
199 UINTN ChecksumOffset
;
201 if ((Buffer
== NULL
) || (Size
== 0)) {
202 return EFI_INVALID_PARAMETER
;
205 ChecksumOffset
= OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER
, Checksum
);
208 // Set checksum to 0 first
210 Buffer
[ChecksumOffset
] = 0;
213 // Update checksum value
215 Buffer
[ChecksumOffset
] = CalculateCheckSum8 (Buffer
, Size
);
221 This function uses the ACPI SDT protocol to search an ACPI table
222 with a given signature.
224 @param AcpiTableSdtProtocol Pointer to ACPI SDT protocol.
225 @param TableSignature ACPI table signature.
226 @param Index The zero-based index of the table where to search the table.
227 The index will be updated to the next instance if the table
228 is found with the matched TableSignature.
229 @param Table Pointer to the table.
230 @param TableKey Pointer to the table key.
232 @return EFI_SUCCESS The function completed successfully.
233 @return EFI_INVALID_PARAMETER At least one of parameters is invalid.
234 @retval EFI_NOT_FOUND The requested index is too large and a table was not found.
239 AcpiLocateTableBySignature (
240 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdtProtocol
,
241 IN UINT32 TableSignature
,
243 OUT EFI_ACPI_DESCRIPTION_HEADER
**Table
,
248 EFI_ACPI_SDT_HEADER
*TempTable
;
249 EFI_ACPI_TABLE_VERSION TableVersion
;
252 if ( (AcpiSdtProtocol
== NULL
)
254 || (TableKey
== NULL
))
256 return EFI_INVALID_PARAMETER
;
259 Status
= EFI_SUCCESS
;
262 // Search for ACPI Table with matching signature
266 while (!EFI_ERROR (Status
)) {
267 Status
= AcpiSdtProtocol
->GetAcpiTable (
273 if (!EFI_ERROR (Status
)) {
276 if (((EFI_ACPI_DESCRIPTION_HEADER
*)TempTable
)->Signature
== TableSignature
) {
277 *Table
= (EFI_ACPI_DESCRIPTION_HEADER
*)TempTable
;
288 This function updates the integer value of an AML Object.
290 @param AcpiTableSdtProtocol Pointer to ACPI SDT protocol.
291 @param TableHandle Points to the table representing the starting point
292 for the object path search.
293 @param AsciiObjectPath Pointer to the ACPI path of the object being updated.
294 @param Value New value to write to the object.
296 @return EFI_SUCCESS The function completed successfully.
297 @return EFI_INVALID_PARAMETER At least one of parameters is invalid or the data type
298 of the ACPI object is not an integer value.
299 @retval EFI_NOT_FOUND The object is not found with the given path.
304 AcpiAmlObjectUpdateInteger (
305 IN EFI_ACPI_SDT_PROTOCOL
*AcpiSdtProtocol
,
306 IN EFI_ACPI_HANDLE TableHandle
,
307 IN CHAR8
*AsciiObjectPath
,
312 EFI_ACPI_HANDLE ObjectHandle
;
313 EFI_ACPI_HANDLE DataHandle
;
314 EFI_ACPI_DATA_TYPE DataType
;
319 if ((AcpiSdtProtocol
== NULL
) || (AsciiObjectPath
== NULL
)) {
320 return EFI_INVALID_PARAMETER
;
326 Status
= AcpiSdtProtocol
->FindPath (TableHandle
, AsciiObjectPath
, &ObjectHandle
);
327 if (EFI_ERROR (Status
)) {
331 Status
= AcpiSdtProtocol
->GetOption (ObjectHandle
, 0, &DataType
, (VOID
*)&Buffer
, &BufferSize
);
332 if (EFI_ERROR (Status
)) {
333 Status
= EFI_NOT_FOUND
;
337 ASSERT (DataType
== EFI_ACPI_DATA_TYPE_OPCODE
);
338 ASSERT (Buffer
!= NULL
);
340 if (Buffer
[0] != AML_NAME_OP
) {
341 Status
= EFI_NOT_FOUND
;
346 // Get handle of data object
348 Status
= AcpiSdtProtocol
->GetChild (ObjectHandle
, &DataHandle
);
349 ASSERT_EFI_ERROR (Status
);
351 Status
= AcpiSdtProtocol
->GetOption (DataHandle
, 0, &DataType
, (VOID
*)&Buffer
, &BufferSize
);
352 ASSERT (DataType
== EFI_ACPI_DATA_TYPE_OPCODE
);
353 ASSERT (Buffer
!= NULL
);
355 if ((Buffer
[0] == AML_ZERO_OP
) || (Buffer
[0] == AML_ONE_OP
)) {
356 Status
= AcpiSdtProtocol
->SetOption (DataHandle
, 0, (VOID
*)&Value
, sizeof (UINT8
));
357 ASSERT_EFI_ERROR (Status
);
360 // Check the size of data object
363 case AML_BYTE_PREFIX
:
364 DataSize
= sizeof (UINT8
);
367 case AML_WORD_PREFIX
:
368 DataSize
= sizeof (UINT16
);
371 case AML_DWORD_PREFIX
:
372 DataSize
= sizeof (UINT32
);
375 case AML_QWORD_PREFIX
:
376 DataSize
= sizeof (UINT64
);
380 // The data type of the ACPI object is not an integer
381 Status
= EFI_INVALID_PARAMETER
;
385 Status
= AcpiSdtProtocol
->SetOption (DataHandle
, 1, (VOID
*)&Value
, DataSize
);
386 ASSERT_EFI_ERROR (Status
);
390 AcpiSdtProtocol
->Close (DataHandle
);
391 AcpiSdtProtocol
->Close (ObjectHandle
);