From c63a10ecb7d66904f04fe65b0cef49c095ce49a6 Mon Sep 17 00:00:00 2001 From: Nhi Pham Date: Thu, 9 Sep 2021 15:24:26 +0700 Subject: EmbeddedPkg/AcpiLib: Add more helper functions This adds more helper functions that assist in calculating the checksum, locating an ACPI table by signature, and updating an AML integer object. Cc: Ard Biesheuvel Cc: Daniel Schaefer Signed-off-by: Nhi Pham Acked-by: Leif Lindholm Reviewed-by: Abner Chang --- EmbeddedPkg/Include/Library/AcpiLib.h | 71 +++++++++++ EmbeddedPkg/Library/AcpiLib/AcpiLib.c | 217 ++++++++++++++++++++++++++++++++ EmbeddedPkg/Library/AcpiLib/AcpiLib.inf | 3 + 3 files changed, 291 insertions(+) (limited to 'EmbeddedPkg') diff --git a/EmbeddedPkg/Include/Library/AcpiLib.h b/EmbeddedPkg/Include/Library/AcpiLib.h index 4f2001bfc8..9dbacd85b0 100644 --- a/EmbeddedPkg/Include/Library/AcpiLib.h +++ b/EmbeddedPkg/Include/Library/AcpiLib.h @@ -2,6 +2,7 @@ Helper Library for ACPI Copyright (c) 2014-2016, ARM Ltd. All rights reserved. + Copyright (c) 2021, Ampere Computing LLC. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent @@ -13,6 +14,7 @@ #include #include +#include // // Macros for the Generic Address Space @@ -128,4 +130,73 @@ LocateAndInstallAcpiFromFv ( IN CONST EFI_GUID *AcpiFile ); +/** + This function calculates and updates a UINT8 checksum + in an ACPI description table header. + + @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 OUT UINT8 *Buffer, + IN UINTN Size + ); + +/** + This function uses the ACPI SDT protocol to search an ACPI table + with a given signature. + + @param AcpiTableSdtProtocol Pointer to ACPI SDT protocol. + @param TableSignature ACPI table signature. + @param Index The zero-based index of the table where to search the table. + The index will be updated to the next instance if the table + is found with the matched TableSignature. + @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, + IN OUT UINTN *Index, + 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 740872ac3e..ea2ad63b20 100644 --- a/EmbeddedPkg/Library/AcpiLib/AcpiLib.c +++ b/EmbeddedPkg/Library/AcpiLib/AcpiLib.c @@ -1,6 +1,7 @@ /** @file * * Copyright (c) 2014-2015, ARM Limited. All rights reserved. +* Copyright (c) 2021, Ampere Computing LLC. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause-Patent * @@ -9,9 +10,12 @@ #include #include +#include +#include #include #include +#include #include #include @@ -173,3 +177,216 @@ LocateAndInstallAcpiFromFv ( { return LocateAndInstallAcpiFromFvConditional (AcpiFile, NULL); } + +/** + This function calculates and updates a UINT8 checksum + in an ACPI description table header. + + @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 OUT 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 search an ACPI table + with a given signature. + + @param AcpiTableSdtProtocol Pointer to ACPI SDT protocol. + @param TableSignature ACPI table signature. + @param Index The zero-based index of the table where to search the table. + The index will be updated to the next instance if the table + is found with the matched TableSignature. + @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, + IN OUT UINTN *Index, + 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 = *Index; + 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; + *Index = TableIndex; + 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_HANDLE DataHandle; + EFI_ACPI_DATA_TYPE DataType; + UINT8 *Buffer; + UINTN BufferSize; + UINTN DataSize; + + if (AcpiSdtProtocol == NULL || AsciiObjectPath == NULL) { + return EFI_INVALID_PARAMETER; + } + + ObjectHandle = NULL; + DataHandle = NULL; + + 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)) { + Status = EFI_NOT_FOUND; + goto Exit; + } + ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE); + ASSERT (Buffer != NULL); + + if (Buffer[0] != AML_NAME_OP) { + Status = EFI_NOT_FOUND; + goto Exit; + } + + // + // Get handle of data object + // + Status = AcpiSdtProtocol->GetChild (ObjectHandle, &DataHandle); + ASSERT_EFI_ERROR (Status); + + Status = AcpiSdtProtocol->GetOption (DataHandle, 0, &DataType, (VOID *)&Buffer, &BufferSize); + ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE); + ASSERT (Buffer != NULL); + + if (Buffer[0] == AML_ZERO_OP || Buffer[0] == AML_ONE_OP) { + Status = AcpiSdtProtocol->SetOption (DataHandle, 0, (VOID *)&Value, sizeof (UINT8)); + ASSERT_EFI_ERROR (Status); + } else { + // + // Check the size of data object + // + switch (Buffer[0]) { + case AML_BYTE_PREFIX: + DataSize = sizeof (UINT8); + break; + + case AML_WORD_PREFIX: + DataSize = sizeof (UINT16); + break; + + case AML_DWORD_PREFIX: + DataSize = sizeof (UINT32); + break; + + case AML_QWORD_PREFIX: + DataSize = sizeof (UINT64); + break; + + default: + // The data type of the ACPI object is not an integer + Status = EFI_INVALID_PARAMETER; + goto Exit; + } + + Status = AcpiSdtProtocol->SetOption (DataHandle, 1, (VOID *)&Value, DataSize); + ASSERT_EFI_ERROR (Status); + } + +Exit: + AcpiSdtProtocol->Close (DataHandle); + AcpiSdtProtocol->Close (ObjectHandle); + + return Status; +} diff --git a/EmbeddedPkg/Library/AcpiLib/AcpiLib.inf b/EmbeddedPkg/Library/AcpiLib/AcpiLib.inf index 538fe09cca..01b12c9423 100644 --- a/EmbeddedPkg/Library/AcpiLib/AcpiLib.inf +++ b/EmbeddedPkg/Library/AcpiLib/AcpiLib.inf @@ -1,6 +1,7 @@ #/** @file # # Copyright (c) 2014, ARM Ltd. All rights reserved. +# Copyright (c) 2021, Ampere Computing LLC. All rights reserved. # # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -23,6 +24,8 @@ EmbeddedPkg/EmbeddedPkg.dec [LibraryClasses] + BaseLib + BaseMemoryLib DebugLib UefiBootServicesTableLib -- cgit v1.2.3