]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EmbeddedPkg/Library/AcpiLib/AcpiLib.c
EmbeddedPkg/AcpiLib: Add more helper functions
[mirror_edk2.git] / EmbeddedPkg / Library / AcpiLib / AcpiLib.c
index 740872ac3e2062d728b27337818078f709bb2c77..ea2ad63b20396eee9651f8be344062b394cf1dd8 100644 (file)
@@ -1,6 +1,7 @@
 /** @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
@@ -9,9 +10,12 @@
 #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
@@ -173,3 +177,216 @@ LocateAndInstallAcpiFromFv (
 {\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