/** @file\r
ACPI Table Protocol Implementation\r
\r
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>\r
Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
@param Table Table to add.\r
@param Checksum Does the table require checksumming.\r
@param Version The version of the list to add the table to.\r
+ @param IsFromHob True, if add Apci Table from Hob List.\r
@param Handle Pointer for returning the handle.\r
\r
@return EFI_SUCCESS The function completed successfully.\r
IN VOID *Table,\r
IN BOOLEAN Checksum,\r
IN EFI_ACPI_TABLE_VERSION Version,\r
+ IN BOOLEAN IsFromHob,\r
OUT UINTN *Handle\r
);\r
\r
AcpiTableBufferConst,\r
TRUE,\r
Version,\r
+ FALSE,\r
TableKey\r
);\r
if (!EFI_ERROR (Status)) {\r
@param Table Table to add.\r
@param Checksum Does the table require checksumming.\r
@param Version The version of the list to add the table to.\r
+ @param IsFromHob True, if add Apci Table from Hob List.\r
@param Handle Pointer for returning the handle.\r
\r
@return EFI_SUCCESS The function completed successfully.\r
IN VOID *Table,\r
IN BOOLEAN Checksum,\r
IN EFI_ACPI_TABLE_VERSION Version,\r
+ IN BOOLEAN IsFromHob,\r
OUT UINTN *Handle\r
)\r
{\r
// SMM communication ACPI table.\r
//\r
ASSERT ((EFI_PAGE_SIZE % 64) == 0);\r
- Status = gBS->AllocatePages (\r
- AllocateMaxAddress,\r
- EfiACPIMemoryNVS,\r
- EFI_SIZE_TO_PAGES (CurrentTableList->TableSize),\r
- &AllocPhysAddress\r
- );\r
+ if (IsFromHob){\r
+ AllocPhysAddress = (UINTN)Table;\r
+ Status = EFI_SUCCESS;\r
+ } else {\r
+ Status = gBS->AllocatePages (\r
+ AllocateMaxAddress,\r
+ EfiACPIMemoryNVS,\r
+ EFI_SIZE_TO_PAGES (CurrentTableList->TableSize),\r
+ &AllocPhysAddress\r
+ );\r
+ }\r
} else if (mAcpiTableAllocType == AllocateAnyPages) {\r
//\r
// If there is no allocation limit, there is also no need to use page\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ This function will find gUniversalPayloadAcpiTableGuid Guid Hob, and install Acpi table from it.\r
+\r
+ @param AcpiTableInstance Protocol instance private data.\r
+\r
+ @return EFI_SUCCESS The function completed successfully.\r
+ @return EFI_NOT_FOUND The function doesn't find the gEfiAcpiTableGuid Guid Hob.\r
+ @return EFI_ABORTED The function could not complete successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+InstallAcpiTableFromHob (\r
+ EFI_ACPI_TABLE_INSTANCE *AcpiTableInstance\r
+ )\r
+{\r
+ EFI_HOB_GUID_TYPE *GuidHob;\r
+ EFI_ACPI_TABLE_VERSION Version;\r
+ EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;\r
+ EFI_ACPI_DESCRIPTION_HEADER *Rsdt;\r
+ EFI_ACPI_DESCRIPTION_HEADER *ChildTable;\r
+ UINT64 ChildTableAddress;\r
+ UINTN Count;\r
+ UINTN Index;\r
+ UINTN TableKey;\r
+ EFI_STATUS Status;\r
+ UINTN EntrySize;\r
+ UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTableAdress;\r
+ VOID *TableToInstall;\r
+ EFI_ACPI_SDT_HEADER *Table;\r
+ UNIVERSAL_PAYLOAD_GENERIC_HEADER *GenericHeader;\r
+\r
+ TableKey = 0;\r
+ Version = PcdGet32 (PcdAcpiExposedTableVersions);\r
+ Status = EFI_SUCCESS;\r
+ //\r
+ // HOB only contains the ACPI table in 2.0+ format.\r
+ //\r
+ GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid);\r
+ if (GuidHob == NULL) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *) GET_GUID_HOB_DATA (GuidHob);\r
+ if ((sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) > GET_GUID_HOB_DATA_SIZE (GuidHob)) || (GenericHeader->Length > GET_GUID_HOB_DATA_SIZE (GuidHob))) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ if (GenericHeader->Revision == UNIVERSAL_PAYLOAD_ACPI_TABLE_REVISION) {\r
+ //\r
+ // UNIVERSAL_PAYLOAD_ACPI_TABLE structure is used when Revision equals to UNIVERSAL_PAYLOAD_ACPI_TABLE_REVISION\r
+ //\r
+ AcpiTableAdress = (UNIVERSAL_PAYLOAD_ACPI_TABLE *) GET_GUID_HOB_DATA (GuidHob);\r
+ if (AcpiTableAdress->Header.Length < UNIVERSAL_PAYLOAD_SIZEOF_THROUGH_FIELD (UNIVERSAL_PAYLOAD_ACPI_TABLE, Rsdp)) {\r
+ //\r
+ // Retrun if can't find the ACPI Info Hob with enough length\r
+ //\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) (UINTN) (AcpiTableAdress->Rsdp);\r
+\r
+ //\r
+ // An ACPI-compatible OS must use the XSDT if present.\r
+ // It shouldn't happen that XsdtAddress points beyond 4G range in 32-bit environment.\r
+ //\r
+ ASSERT ((UINTN) Rsdp->XsdtAddress == Rsdp->XsdtAddress);\r
+\r
+ EntrySize = sizeof (UINT64);\r
+ Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;\r
+ if (Rsdt == NULL) {\r
+ //\r
+ // XsdtAddress is zero, then we use Rsdt which has 32 bit entry\r
+ //\r
+ Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;\r
+ EntrySize = sizeof (UINT32);\r
+ }\r
+\r
+ if (Rsdt->Length <= sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ Count = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / EntrySize;\r
+\r
+ for (Index = 0; Index < Count; Index++){\r
+ ChildTableAddress = 0;\r
+ CopyMem (&ChildTableAddress, (UINT8 *) (Rsdt + 1) + EntrySize * Index, EntrySize);\r
+ //\r
+ // If the address is of UINT64 while this module runs at 32 bits,\r
+ // make sure the upper bits are all-zeros.\r
+ //\r
+ ASSERT (ChildTableAddress == (UINTN) ChildTableAddress);\r
+ if (ChildTableAddress != (UINTN) ChildTableAddress) {\r
+ Status = EFI_ABORTED;\r
+ break;\r
+ }\r
+\r
+ ChildTable = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) ChildTableAddress;\r
+ Status = AddTableToList (AcpiTableInstance, ChildTable, TRUE, Version, TRUE, &TableKey);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "InstallAcpiTableFromHob: Fail to add ACPI table at 0x%p\n", ChildTable));\r
+ ASSERT_EFI_ERROR (Status);\r
+ break;\r
+ }\r
+ if (ChildTable->Signature == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE){\r
+ //\r
+ // Add the FACS and DSDT tables if it is not NULL.\r
+ //\r
+ if (((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) ChildTable)->FirmwareCtrl != 0) {\r
+ TableToInstall = (VOID *) (UINTN) ((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) ChildTable)->FirmwareCtrl;\r
+ Status = AddTableToList (AcpiTableInstance, TableToInstall, TRUE, Version, TRUE, &TableKey);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "InstallAcpiTableFromHob: Fail to add ACPI table FACS\n"));\r
+ ASSERT_EFI_ERROR (Status);\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) ChildTable)->Dsdt != 0) {\r
+ TableToInstall = (VOID *) (UINTN) ((EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *) ChildTable)->Dsdt;\r
+ Status = AddTableToList (AcpiTableInstance, TableToInstall, TRUE, Version, TRUE, &TableKey);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "InstallAcpiTableFromHob: Fail to add ACPI table DSDT\n"));\r
+ ASSERT_EFI_ERROR (Status);\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Error happens when trying to add ACPI table to the list.\r
+ // Remove all of them from list because at this time, no other tables except from HOB are in the list\r
+ //\r
+ while (SdtGetAcpiTable (AcpiTableInstance, 0, &Table, &Version, &TableKey) == EFI_SUCCESS) {\r
+ RemoveTableFromList (AcpiTableInstance, Version, TableKey);\r
+ }\r
+ } else {\r
+ Status = PublishTables (AcpiTableInstance, Version);\r
+ }\r
+\r
+ ASSERT_EFI_ERROR (Status);\r
+ return Status;\r
+}\r
\r
/**\r
Constructor for the ACPI table protocol. Initializes instance\r
\r
ChecksumCommonTables (AcpiTableInstance);\r
\r
+ InstallAcpiTableFromHob (AcpiTableInstance);\r
+\r
//\r
// Completed successfully\r
//\r