/** @file\r
*\r
* Copyright (c) 2014-2015, ARM Limited. All rights reserved.\r
+* Copyright (c) 2021, Ampere Computing LLC. All rights reserved.\r
*\r
* SPDX-License-Identifier: BSD-2-Clause-Patent\r
*\r
#include <Uefi.h>\r
\r
#include <Library/AcpiLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
\r
+#include <Protocol/AcpiSystemDescriptionTable.h>\r
#include <Protocol/AcpiTable.h>\r
#include <Protocol/FirmwareVolume2.h>\r
\r
{\r
return LocateAndInstallAcpiFromFvConditional (AcpiFile, NULL);\r
}\r
+\r
+/**\r
+ This function calculates and updates a UINT8 checksum\r
+ in an ACPI description table header.\r
+\r
+ @param Buffer Pointer to buffer to checksum\r
+ @param Size Number of bytes to checksum\r
+\r
+ @retval EFI_SUCCESS The function completed successfully.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AcpiUpdateChecksum (\r
+ IN OUT UINT8 *Buffer,\r
+ IN UINTN Size\r
+ )\r
+{\r
+ UINTN ChecksumOffset;\r
+\r
+ if (Buffer == NULL || Size == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ChecksumOffset = OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, Checksum);\r
+\r
+ //\r
+ // Set checksum to 0 first\r
+ //\r
+ Buffer[ChecksumOffset] = 0;\r
+\r
+ //\r
+ // Update checksum value\r
+ //\r
+ Buffer[ChecksumOffset] = CalculateCheckSum8 (Buffer, Size);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function uses the ACPI SDT protocol to search an ACPI table\r
+ with a given signature.\r
+\r
+ @param AcpiTableSdtProtocol Pointer to ACPI SDT protocol.\r
+ @param TableSignature ACPI table signature.\r
+ @param Index The zero-based index of the table where to search the table.\r
+ The index will be updated to the next instance if the table\r
+ is found with the matched TableSignature.\r
+ @param Table Pointer to the table.\r
+ @param TableKey Pointer to the table key.\r
+\r
+ @return EFI_SUCCESS The function completed successfully.\r
+ @return EFI_INVALID_PARAMETER At least one of parameters is invalid.\r
+ @retval EFI_NOT_FOUND The requested index is too large and a table was not found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AcpiLocateTableBySignature (\r
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol,\r
+ IN UINT32 TableSignature,\r
+ IN OUT UINTN *Index,\r
+ OUT EFI_ACPI_DESCRIPTION_HEADER **Table,\r
+ OUT UINTN *TableKey\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_SDT_HEADER *TempTable;\r
+ EFI_ACPI_TABLE_VERSION TableVersion;\r
+ UINTN TableIndex;\r
+\r
+ if (AcpiSdtProtocol == NULL\r
+ || Table == NULL\r
+ || TableKey == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // Search for ACPI Table with matching signature\r
+ //\r
+ TableVersion = 0;\r
+ TableIndex = *Index;\r
+ while (!EFI_ERROR (Status)) {\r
+ Status = AcpiSdtProtocol->GetAcpiTable (\r
+ TableIndex,\r
+ &TempTable,\r
+ &TableVersion,\r
+ TableKey\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ TableIndex++;\r
+\r
+ if (((EFI_ACPI_DESCRIPTION_HEADER *)TempTable)->Signature == TableSignature) {\r
+ *Table = (EFI_ACPI_DESCRIPTION_HEADER *)TempTable;\r
+ *Index = TableIndex;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function updates the integer value of an AML Object.\r
+\r
+ @param AcpiTableSdtProtocol Pointer to ACPI SDT protocol.\r
+ @param TableHandle Points to the table representing the starting point\r
+ for the object path search.\r
+ @param AsciiObjectPath Pointer to the ACPI path of the object being updated.\r
+ @param Value New value to write to the object.\r
+\r
+ @return EFI_SUCCESS The function completed successfully.\r
+ @return EFI_INVALID_PARAMETER At least one of parameters is invalid or the data type\r
+ of the ACPI object is not an integer value.\r
+ @retval EFI_NOT_FOUND The object is not found with the given path.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AcpiAmlObjectUpdateInteger (\r
+ IN EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol,\r
+ IN EFI_ACPI_HANDLE TableHandle,\r
+ IN CHAR8 *AsciiObjectPath,\r
+ IN UINTN Value\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_ACPI_HANDLE ObjectHandle;\r
+ EFI_ACPI_HANDLE DataHandle;\r
+ EFI_ACPI_DATA_TYPE DataType;\r
+ UINT8 *Buffer;\r
+ UINTN BufferSize;\r
+ UINTN DataSize;\r
+\r
+ if (AcpiSdtProtocol == NULL || AsciiObjectPath == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ObjectHandle = NULL;\r
+ DataHandle = NULL;\r
+\r
+ Status = AcpiSdtProtocol->FindPath (TableHandle, AsciiObjectPath, &ObjectHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = AcpiSdtProtocol->GetOption (ObjectHandle, 0, &DataType, (VOID *)&Buffer, &BufferSize);\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Exit;\r
+ }\r
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);\r
+ ASSERT (Buffer != NULL);\r
+\r
+ if (Buffer[0] != AML_NAME_OP) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Get handle of data object\r
+ //\r
+ Status = AcpiSdtProtocol->GetChild (ObjectHandle, &DataHandle);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = AcpiSdtProtocol->GetOption (DataHandle, 0, &DataType, (VOID *)&Buffer, &BufferSize);\r
+ ASSERT (DataType == EFI_ACPI_DATA_TYPE_OPCODE);\r
+ ASSERT (Buffer != NULL);\r
+\r
+ if (Buffer[0] == AML_ZERO_OP || Buffer[0] == AML_ONE_OP) {\r
+ Status = AcpiSdtProtocol->SetOption (DataHandle, 0, (VOID *)&Value, sizeof (UINT8));\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ //\r
+ // Check the size of data object\r
+ //\r
+ switch (Buffer[0]) {\r
+ case AML_BYTE_PREFIX:\r
+ DataSize = sizeof (UINT8);\r
+ break;\r
+\r
+ case AML_WORD_PREFIX:\r
+ DataSize = sizeof (UINT16);\r
+ break;\r
+\r
+ case AML_DWORD_PREFIX:\r
+ DataSize = sizeof (UINT32);\r
+ break;\r
+\r
+ case AML_QWORD_PREFIX:\r
+ DataSize = sizeof (UINT64);\r
+ break;\r
+\r
+ default:\r
+ // The data type of the ACPI object is not an integer\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto Exit;\r
+ }\r
+\r
+ Status = AcpiSdtProtocol->SetOption (DataHandle, 1, (VOID *)&Value, DataSize);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+Exit:\r
+ AcpiSdtProtocol->Close (DataHandle);\r
+ AcpiSdtProtocol->Close (ObjectHandle);\r
+\r
+ return Status;\r
+}\r