This adds more helper functions that assist in calculating the checksum, locating an ACPI table by signature, and updating an AML integer object.
Cc: Leif Lindholm <l...@nuviainc.com> Cc: Ard Biesheuvel <ardb+tianoc...@kernel.org> Cc: Abner Chang <abner.ch...@hpe.com> Cc: Daniel Schaefer <daniel.schae...@hpe.com> Signed-off-by: Nhi Pham <n...@os.amperecomputing.com> --- EmbeddedPkg/Library/AcpiLib/AcpiLib.inf | 2 + EmbeddedPkg/Include/Library/AcpiLib.h | 68 ++++++++ EmbeddedPkg/Library/AcpiLib/AcpiLib.c | 183 ++++++++++++++++++++ 3 files changed, 253 insertions(+) diff --git a/EmbeddedPkg/Library/AcpiLib/AcpiLib.inf b/EmbeddedPkg/Library/AcpiLib/AcpiLib.inf index 538fe09cca29..154cb1eebc80 100644 --- a/EmbeddedPkg/Library/AcpiLib/AcpiLib.inf +++ b/EmbeddedPkg/Library/AcpiLib/AcpiLib.inf @@ -23,6 +23,8 @@ [Packages] EmbeddedPkg/EmbeddedPkg.dec [LibraryClasses] + BaseLib + BaseMemoryLib DebugLib UefiBootServicesTableLib diff --git a/EmbeddedPkg/Include/Library/AcpiLib.h b/EmbeddedPkg/Include/Library/AcpiLib.h index c142446d9d59..cdb6ea410c54 100644 --- a/EmbeddedPkg/Include/Library/AcpiLib.h +++ b/EmbeddedPkg/Include/Library/AcpiLib.h @@ -13,6 +13,7 @@ #include <Uefi.h> #include <IndustryStandard/Acpi10.h> +#include <Protocol/AcpiSystemDescriptionTable.h> // // Macros for the Generic Address Space @@ -128,4 +129,71 @@ LocateAndInstallAcpiFromFv ( IN CONST EFI_GUID* AcpiFile ); +/** + This function calculates and updates an UINT8 checksum. + + @param Buffer Pointer to buffer to checksum + @param Size Number of bytes to checksum + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + +**/ +EFI_STATUS +EFIAPI +AcpiUpdateChecksum ( + IN UINT8 *Buffer, + IN UINTN Size + ); + +/** + This function uses the ACPI SDT protocol to locate an ACPI table + with a given signature that only have a single instance. + + Caution: This function does not act correctly with tables having + more than 2 instances like SSDT table. + + @param AcpiTableSdtProtocol Pointer to ACPI SDT protocol. + @param TableSignature ACPI table signature. + @param Table Pointer to the table. + @param TableKey Pointer to the table key. + + @return EFI_SUCCESS The function completed successfully. + @return EFI_INVALID_PARAMETER At least one of parameters is invalid. + @retval EFI_NOT_FOUND The requested index is too large and a table was not found. + +**/ +EFI_STATUS +EFIAPI +AcpiLocateTableBySignature ( + IN EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol, + IN UINT32 TableSignature, + OUT EFI_ACPI_DESCRIPTION_HEADER **Table, + OUT UINTN *TableKey + ); + +/** + This function updates the integer value of an AML Object. + + @param AcpiTableSdtProtocol Pointer to ACPI SDT protocol. + @param TableHandle Points to the table representing the starting point + for the object path search. + @param AsciiObjectPath Pointer to the ACPI path of the object being updated. + @param Value New value to write to the object. + + @return EFI_SUCCESS The function completed successfully. + @return EFI_INVALID_PARAMETER At least one of parameters is invalid or the data type + of the ACPI object is not an integer value. + @retval EFI_NOT_FOUND The object is not found with the given path. + +**/ +EFI_STATUS +EFIAPI +AcpiAmlObjectUpdateInteger ( + IN EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol, + IN EFI_ACPI_HANDLE TableHandle, + IN CHAR8 *AsciiObjectPath, + IN UINTN Value + ); + #endif // __ACPI_LIB_H__ diff --git a/EmbeddedPkg/Library/AcpiLib/AcpiLib.c b/EmbeddedPkg/Library/AcpiLib/AcpiLib.c index ff7d678433d5..e07919ae323f 100644 --- a/EmbeddedPkg/Library/AcpiLib/AcpiLib.c +++ b/EmbeddedPkg/Library/AcpiLib/AcpiLib.c @@ -9,9 +9,12 @@ #include <Uefi.h> #include <Library/AcpiLib.h> +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> #include <Library/DebugLib.h> #include <Library/UefiBootServicesTableLib.h> +#include <Protocol/AcpiSystemDescriptionTable.h> #include <Protocol/AcpiTable.h> #include <Protocol/FirmwareVolume2.h> @@ -170,3 +173,183 @@ LocateAndInstallAcpiFromFv ( { return LocateAndInstallAcpiFromFvConditional (AcpiFile, NULL); } + +/** + This function calculates and updates an UINT8 checksum. + + @param Buffer Pointer to buffer to checksum + @param Size Number of bytes to checksum + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER Invalid parameter. + +**/ +EFI_STATUS +EFIAPI +AcpiUpdateChecksum ( + IN UINT8 *Buffer, + IN UINTN Size + ) +{ + UINTN ChecksumOffset; + + if (Buffer == NULL || Size == 0) { + return EFI_INVALID_PARAMETER; + } + + ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum); + + // + // Set checksum to 0 first + // + Buffer[ChecksumOffset] = 0; + + // + // Update checksum value + // + Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Size); + + return EFI_SUCCESS; +} + +/** + This function uses the ACPI SDT protocol to locate an ACPI table + with a given signature that only have a single instance. + + Caution: This function does not act correctly with tables having + more than 2 instances like SSDT table. + + @param AcpiTableSdtProtocol Pointer to ACPI SDT protocol. + @param TableSignature ACPI table signature. + @param Table Pointer to the table. + @param TableKey Pointer to the table key. + + @return EFI_SUCCESS The function completed successfully. + @return EFI_INVALID_PARAMETER At least one of parameters is invalid. + @retval EFI_NOT_FOUND The requested index is too large and a table was not found. + +**/ +EFI_STATUS +EFIAPI +AcpiLocateTableBySignature ( + IN EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol, + IN UINT32 TableSignature, + OUT EFI_ACPI_DESCRIPTION_HEADER **Table, + OUT UINTN *TableKey + ) +{ + EFI_STATUS Status; + EFI_ACPI_SDT_HEADER *TempTable; + EFI_ACPI_TABLE_VERSION TableVersion; + UINTN TableIndex; + + if (AcpiSdtProtocol == NULL + || Table == NULL + || TableKey == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_SUCCESS; + + // + // Search for ACPI Table with matching signature + // + TableVersion = 0; + TableIndex = 0; + while (!EFI_ERROR (Status)) { + Status = AcpiSdtProtocol->GetAcpiTable ( + TableIndex, + &TempTable, + &TableVersion, + TableKey + ); + if (!EFI_ERROR (Status)) { + TableIndex++; + + if (((EFI_ACPI_DESCRIPTION_HEADER *)TempTable)->Signature == TableSignature) { + *Table = (EFI_ACPI_DESCRIPTION_HEADER *)TempTable; + break; + } + } + } + + return Status; +} + +/** + This function updates the integer value of an AML Object. + + @param AcpiTableSdtProtocol Pointer to ACPI SDT protocol. + @param TableHandle Points to the table representing the starting point + for the object path search. + @param AsciiObjectPath Pointer to the ACPI path of the object being updated. + @param Value New value to write to the object. + + @return EFI_SUCCESS The function completed successfully. + @return EFI_INVALID_PARAMETER At least one of parameters is invalid or the data type + of the ACPI object is not an integer value. + @retval EFI_NOT_FOUND The object is not found with the given path. + +**/ +EFI_STATUS +EFIAPI +AcpiAmlObjectUpdateInteger ( + IN EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol, + IN EFI_ACPI_HANDLE TableHandle, + IN CHAR8 *AsciiObjectPath, + IN UINTN Value + ) +{ + EFI_STATUS Status; + EFI_ACPI_HANDLE ObjectHandle; + EFI_ACPI_DATA_TYPE DataType; + UINT8 *Buffer; + UINTN BufferSize; + + if (AcpiSdtProtocol == NULL || AsciiObjectPath == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = AcpiSdtProtocol->FindPath (TableHandle, AsciiObjectPath, &ObjectHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = AcpiSdtProtocol->GetOption (ObjectHandle, 0, &DataType, (VOID *)&Buffer, &BufferSize); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Buffer[0] != AML_NAME_OP) { + return EFI_NOT_FOUND; + } + + switch (Buffer[5]) { + case AML_ZERO_OP: + case AML_ONE_OP: + Buffer[5] = (UINT8)Value; + break; + + case AML_BYTE_PREFIX: + Buffer[6] = (UINT8)Value; + break; + + case AML_WORD_PREFIX: + CopyMem ((VOID *)&Buffer[6], (VOID *)&Buffer, sizeof (UINT16)); + break; + + case AML_DWORD_PREFIX: + CopyMem ((VOID *)&Buffer[6], (VOID *)&Buffer, sizeof (UINT32)); + break; + + case AML_QWORD_PREFIX: + CopyMem ((VOID *)&Buffer[6], (VOID *)&Buffer, sizeof (UINT64)); + break; + + default: + // The data type of the ACPI object is not an integer value. + return EFI_INVALID_PARAMETER; + } + + return Status; +} -- 2.17.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#79424): https://edk2.groups.io/g/devel/message/79424 Mute This Topic: https://groups.io/mt/84947529/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-