From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.93; helo=mga11.intel.com; envelope-from=star.zeng@intel.com; receiver=edk2-devel@lists.01.org Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 2B78221B02822 for ; Thu, 13 Sep 2018 03:27:11 -0700 (PDT) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 13 Sep 2018 03:27:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.53,368,1531810800"; d="scan'208";a="72644135" Received: from shwdeopenpsi068.ccr.corp.intel.com ([10.239.158.46]) by orsmga007.jf.intel.com with ESMTP; 13 Sep 2018 03:27:09 -0700 From: Star Zeng To: edk2-devel@lists.01.org Cc: Star Zeng , Younas khan , Michael D Kinney , Liming Gao , Jiewen Yao Date: Thu, 13 Sep 2018 18:26:55 +0800 Message-Id: <1536834420-16620-2-git-send-email-star.zeng@intel.com> X-Mailer: git-send-email 2.7.0.windows.1 In-Reply-To: <1536834420-16620-1-git-send-email-star.zeng@intel.com> References: <1536834420-16620-1-git-send-email-star.zeng@intel.com> Subject: [PATCH V2 1/6] MdePkg UefiLib: Add new EfiLocateXXXAcpiTable() APIs X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Sep 2018 10:27:11 -0000 https://bugzilla.tianocore.org/show_bug.cgi?id=967 Request to add a library function for GetAcpiTable() in order to get ACPI table using signature as input. After evaluation, we found there are many duplicated code to find ACPI table by signature in different modules. This patch adds new EfiLocateXXXAcpiTable() APIs in UefiLib for the request and also the following patch to remove the duplicated code. Cc: Younas khan Cc: Michael D Kinney Cc: Liming Gao Cc: Jiewen Yao Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Star Zeng --- MdePkg/Include/Library/UefiLib.h | 68 ++++++ MdePkg/Library/UefiLib/Acpi.c | 488 +++++++++++++++++++++++++++++++++++++ MdePkg/Library/UefiLib/UefiLib.inf | 3 + 3 files changed, 559 insertions(+) create mode 100644 MdePkg/Library/UefiLib/Acpi.c diff --git a/MdePkg/Include/Library/UefiLib.h b/MdePkg/Include/Library/UefiLib.h index f80067f11103..cf82ff4a920a 100644 --- a/MdePkg/Include/Library/UefiLib.h +++ b/MdePkg/Include/Library/UefiLib.h @@ -26,6 +26,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #ifndef __UEFI_LIB_H__ #define __UEFI_LIB_H__ +#include + #include #include #include @@ -1595,4 +1597,70 @@ EfiOpenFileByDevicePath ( IN UINT64 OpenMode, IN UINT64 Attributes ); + +/** + This function locates next ACPI table in XSDT/RSDT based on Signature and + previous returned Table. + + If PreviousTable is NULL: + This function will locate the first ACPI table in XSDT/RSDT based on + Signature in gEfiAcpi20TableGuid system configuration table first, and then + gEfiAcpi10TableGuid system configuration table. + This function will locate in XSDT first, and then RSDT. + For DSDT, this function will locate XDsdt in FADT first, and then Dsdt in + FADT. + For FACS, this function will locate XFirmwareCtrl in FADT first, and then + FirmwareCtrl in FADT. + + If PreviousTable is not NULL: + 1. If it could be located in XSDT in gEfiAcpi20TableGuid system configuration + table, then this function will just locate next table in XSDT in + gEfiAcpi20TableGuid system configuration table. + 2. If it could be located in RSDT in gEfiAcpi20TableGuid system configuration + table, then this function will just locate next table in RSDT in + gEfiAcpi20TableGuid system configuration table. + 3. If it could be located in RSDT in gEfiAcpi10TableGuid system configuration + table, then this function will just locate next table in RSDT in + gEfiAcpi10TableGuid system configuration table. + + If PreviousTable is not NULL and PreviousTable->Signature is not same with + Signature, then ASSERT. + + @param Signature ACPI table signature. + @param PreviousTable Pointer to previous returned table to locate next + table, or NULL to locate first table. + + @return Next ACPI table or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +EFIAPI +EfiLocateNextAcpiTable ( + IN UINT32 Signature, + IN EFI_ACPI_COMMON_HEADER *PreviousTable OPTIONAL + ); + +/** + This function locates first ACPI table in XSDT/RSDT based on Signature. + + This function will locate the first ACPI table in XSDT/RSDT based on + Signature in gEfiAcpi20TableGuid system configuration table first, and then + gEfiAcpi10TableGuid system configuration table. + This function will locate in XSDT first, and then RSDT. + For DSDT, this function will locate XDsdt in FADT first, and then Dsdt in + FADT. + For FACS, this function will locate XFirmwareCtrl in FADT first, and then + FirmwareCtrl in FADT. + + @param Signature ACPI table signature. + + @return First ACPI table or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +EFIAPI +EfiLocateFirstAcpiTable ( + IN UINT32 Signature + ); + #endif diff --git a/MdePkg/Library/UefiLib/Acpi.c b/MdePkg/Library/UefiLib/Acpi.c new file mode 100644 index 000000000000..0793bbdc787f --- /dev/null +++ b/MdePkg/Library/UefiLib/Acpi.c @@ -0,0 +1,488 @@ +/** @file + This module provides help function for finding ACPI table. + + Copyright (c) 2018, Intel Corporation. All rights reserved.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UefiLibInternal.h" +#include +#include + +/** + This function scans ACPI table in RSDT. + + @param Rsdt ACPI RSDT. + @param Signature ACPI table signature. + @param PreviousTable Pointer to previous returned table to locate + next table, or NULL to locate first table. + @param PreviousTableLocated Pointer to the indicator about whether the + previous returned table could be located, or + NULL if PreviousTable is NULL. + + If PreviousTable is NULL and PreviousTableLocated is not NULL, then ASSERT(). + If PreviousTable is not NULL and PreviousTableLocated is NULL, then ASSERT(). + + @return ACPI table or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +ScanTableInRSDT ( + IN EFI_ACPI_DESCRIPTION_HEADER *Rsdt, + IN UINT32 Signature, + IN EFI_ACPI_COMMON_HEADER *PreviousTable, OPTIONAL + OUT BOOLEAN *PreviousTableLocated OPTIONAL + ) +{ + UINTN Index; + UINT32 EntryCount; + UINT32 *EntryPtr; + EFI_ACPI_COMMON_HEADER *Table; + + if (PreviousTableLocated != NULL) { + ASSERT (PreviousTable != NULL); + *PreviousTableLocated = FALSE; + } else { + ASSERT (PreviousTable == NULL); + } + + if (Rsdt == NULL) { + return NULL; + } + + EntryCount = (Rsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT32); + + EntryPtr = (UINT32 *)(Rsdt + 1); + for (Index = 0; Index < EntryCount; Index ++, EntryPtr ++) { + Table = (EFI_ACPI_COMMON_HEADER *)((UINTN)(*EntryPtr)); + if (Table->Signature == Signature) { + if (PreviousTable != NULL) { + if (Table == PreviousTable) { + *PreviousTableLocated = TRUE; + } else if (*PreviousTableLocated) { + // + // Return next table. + // + return Table; + } + } else { + // + // Return first table. + // + return Table; + } + } + } + + return NULL; +} + +/** + This function scans ACPI table in XSDT. + + @param Xsdt ACPI XSDT. + @param Signature ACPI table signature. + @param PreviousTable Pointer to previous returned table to locate + next table, or NULL to locate first table. + @param PreviousTableLocated Pointer to the indicator about whether the + previous returned table could be located, or + NULL if PreviousTable is NULL. + + If PreviousTable is NULL and PreviousTableLocated is not NULL, then ASSERT(). + If PreviousTable is not NULL and PreviousTableLocated is NULL, then ASSERT(). + + @return ACPI table or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +ScanTableInXSDT ( + IN EFI_ACPI_DESCRIPTION_HEADER *Xsdt, + IN UINT32 Signature, + IN EFI_ACPI_COMMON_HEADER *PreviousTable, OPTIONAL + OUT BOOLEAN *PreviousTableLocated OPTIONAL + ) +{ + UINTN Index; + UINT32 EntryCount; + UINT64 EntryPtr; + UINTN BasePtr; + EFI_ACPI_COMMON_HEADER *Table; + + if (PreviousTableLocated != NULL) { + ASSERT (PreviousTable != NULL); + *PreviousTableLocated = FALSE; + } else { + ASSERT (PreviousTable == NULL); + } + + if (Xsdt == NULL) { + return NULL; + } + + EntryCount = (Xsdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / sizeof(UINT64); + + BasePtr = (UINTN)(Xsdt + 1); + for (Index = 0; Index < EntryCount; Index ++) { + CopyMem (&EntryPtr, (VOID *)(BasePtr + Index * sizeof(UINT64)), sizeof(UINT64)); + Table = (EFI_ACPI_COMMON_HEADER *)((UINTN)(EntryPtr)); + if (Table->Signature == Signature) { + if (PreviousTable != NULL) { + if (Table == PreviousTable) { + *PreviousTableLocated = TRUE; + } else if (*PreviousTableLocated) { + // + // Return next table. + // + return Table; + } + } else { + // + // Return first table. + // + return Table; + } + + } + } + + return NULL; +} + +/** + To locate FACS in FADT. + + @param Fadt FADT table pointer. + + @return FACS table pointer or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +LocateAcpiFacsFromFadt ( + IN EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt + ) +{ + EFI_ACPI_COMMON_HEADER *Facs; + UINT64 Data64; + + if (Fadt == NULL) { + return NULL; + } + + if (Fadt->Header.Revision < EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) { + Facs = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->FirmwareCtrl; + } else { + CopyMem (&Data64, &Fadt->XFirmwareCtrl, sizeof(UINT64)); + if (Data64 != 0) { + Facs = (EFI_ACPI_COMMON_HEADER *)(UINTN)Data64; + } else { + Facs = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->FirmwareCtrl; + } + } + return Facs; +} + +/** + To locate DSDT in FADT. + + @param Fadt FADT table pointer. + + @return DSDT table pointer or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +LocateAcpiDsdtFromFadt ( + IN EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt + ) +{ + EFI_ACPI_COMMON_HEADER *Dsdt; + UINT64 Data64; + + if (Fadt == NULL) { + return NULL; + } + + if (Fadt->Header.Revision < EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) { + Dsdt = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->Dsdt; + } else { + CopyMem (&Data64, &Fadt->XDsdt, sizeof(UINT64)); + if (Data64 != 0) { + Dsdt = (EFI_ACPI_COMMON_HEADER *)(UINTN)Data64; + } else { + Dsdt = (EFI_ACPI_COMMON_HEADER *)(UINTN)Fadt->Dsdt; + } + } + return Dsdt; +} + +/** + To locate ACPI table in ACPI ConfigurationTable. + + @param AcpiTableGuid The GUID used to get ACPI ConfigurationTable. + @param Signature ACPI table signature. + @param PreviousTable Pointer to previous returned table to locate + next table, or NULL to locate first table. + @param PreviousTableLocated Pointer to the indicator to return whether the + previous returned table could be located or not, + or NULL if PreviousTable is NULL. + + If PreviousTable is NULL and PreviousTableLocated is not NULL, then ASSERT(). + If PreviousTable is not NULL and PreviousTableLocated is NULL, then ASSERT(). + If AcpiGuid is NULL, then ASSERT(). + + @return ACPI table or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +LocateAcpiTableInAcpiConfigurationTable ( + IN EFI_GUID *AcpiGuid, + IN UINT32 Signature, + IN EFI_ACPI_COMMON_HEADER *PreviousTable, OPTIONAL + OUT BOOLEAN *PreviousTableLocated OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_ACPI_COMMON_HEADER *Table; + EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp; + EFI_ACPI_DESCRIPTION_HEADER *Rsdt; + EFI_ACPI_DESCRIPTION_HEADER *Xsdt; + EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt; + + if (PreviousTableLocated != NULL) { + ASSERT (PreviousTable != NULL); + *PreviousTableLocated = FALSE; + } else { + ASSERT (PreviousTable == NULL); + } + + Rsdp = NULL; + // + // Get ACPI ConfigurationTable (RSD_PTR) + // + Status = EfiGetSystemConfigurationTable(AcpiGuid, (VOID **)&Rsdp); + if (EFI_ERROR (Status) || (Rsdp == NULL)) { + return NULL; + } + + Table = NULL; + + // + // Search XSDT + // + if (Rsdp->Revision >= EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) { + Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->XsdtAddress; + if (Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) { + ASSERT (PreviousTable == NULL); + // + // It is to locate DSDT, + // need to locate FADT first. + // + Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInXSDT ( + Xsdt, + EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, + NULL, + NULL + ); + Table = LocateAcpiDsdtFromFadt (Fadt); + } else if (Signature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) { + ASSERT (PreviousTable == NULL); + // + // It is to locate FACS, + // need to locate FADT first. + // + Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInXSDT ( + Xsdt, + EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, + NULL, + NULL + ); + Table = LocateAcpiFacsFromFadt (Fadt); + } else { + Table = ScanTableInXSDT ( + Xsdt, + Signature, + PreviousTable, + PreviousTableLocated + ); + } + } + + if (Table != NULL) { + return Table; + } else if ((PreviousTableLocated != NULL) && + *PreviousTableLocated) { + // + // PreviousTable could be located in XSDT, + // but next table could not be located in XSDT. + // + return NULL; + } + + // + // Search RSDT + // + Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->RsdtAddress; + if (Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) { + ASSERT (PreviousTable == NULL); + // + // It is to locate DSDT, + // need to locate FADT first. + // + Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInRSDT ( + Rsdt, + EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, + NULL, + NULL + ); + Table = LocateAcpiDsdtFromFadt (Fadt); + } else if (Signature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE) { + ASSERT (PreviousTable == NULL); + // + // It is to locate FACS, + // need to locate FADT first. + // + Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) ScanTableInRSDT ( + Rsdt, + EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, + NULL, + NULL + ); + Table = LocateAcpiFacsFromFadt (Fadt); + } else { + Table = ScanTableInRSDT ( + Rsdt, + Signature, + PreviousTable, + PreviousTableLocated + ); + } + + return Table; +} + +/** + This function locates next ACPI table in XSDT/RSDT based on Signature and + previous returned Table. + + If PreviousTable is NULL: + This function will locate the first ACPI table in XSDT/RSDT based on + Signature in gEfiAcpi20TableGuid system configuration table first, and then + gEfiAcpi10TableGuid system configuration table. + This function will locate in XSDT first, and then RSDT. + For DSDT, this function will locate XDsdt in FADT first, and then Dsdt in + FADT. + For FACS, this function will locate XFirmwareCtrl in FADT first, and then + FirmwareCtrl in FADT. + + If PreviousTable is not NULL: + 1. If it could be located in XSDT in gEfiAcpi20TableGuid system configuration + table, then this function will just locate next table in XSDT in + gEfiAcpi20TableGuid system configuration table. + 2. If it could be located in RSDT in gEfiAcpi20TableGuid system configuration + table, then this function will just locate next table in RSDT in + gEfiAcpi20TableGuid system configuration table. + 3. If it could be located in RSDT in gEfiAcpi10TableGuid system configuration + table, then this function will just locate next table in RSDT in + gEfiAcpi10TableGuid system configuration table. + + If PreviousTable is not NULL and PreviousTable->Signature is not same with + Signature, then ASSERT. + + @param Signature ACPI table signature. + @param PreviousTable Pointer to previous returned table to locate next + table, or NULL to locate first table. + + @return Next ACPI table or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +EFIAPI +EfiLocateNextAcpiTable ( + IN UINT32 Signature, + IN EFI_ACPI_COMMON_HEADER *PreviousTable OPTIONAL + ) +{ + EFI_ACPI_COMMON_HEADER *Table; + BOOLEAN TempPreviousTableLocated; + BOOLEAN *PreviousTableLocated; + + if (PreviousTable != NULL) { + if (PreviousTable->Signature != Signature) { + // + // PreviousTable->Signature is not same with Signature. + // + ASSERT (FALSE); + return NULL; + } else if ((Signature == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) || + (Signature == EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) || + (Signature == EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE)) { + // + // There is only one FADT/DSDT/FACS table, + // so don't try to locate next one. + // + return NULL; + } + + PreviousTableLocated = &TempPreviousTableLocated; + *PreviousTableLocated = FALSE; + } else { + PreviousTableLocated = NULL; + } + + Table = LocateAcpiTableInAcpiConfigurationTable ( + &gEfiAcpi20TableGuid, + Signature, + PreviousTable, + PreviousTableLocated + ); + if (Table != NULL) { + return Table; + } else if ((PreviousTableLocated != NULL) && + *PreviousTableLocated) { + // + // PreviousTable could be located in gEfiAcpi20TableGuid system + // configuration table, but next table could not be located in + // gEfiAcpi20TableGuid system configuration table. + // + return NULL; + } + + return LocateAcpiTableInAcpiConfigurationTable ( + &gEfiAcpi10TableGuid, + Signature, + PreviousTable, + PreviousTableLocated + ); +} + +/** + This function locates first ACPI table in XSDT/RSDT based on Signature. + + This function will locate the first ACPI table in XSDT/RSDT based on + Signature in gEfiAcpi20TableGuid system configuration table first, and then + gEfiAcpi10TableGuid system configuration table. + This function will locate in XSDT first, and then RSDT. + For DSDT, this function will locate XDsdt in FADT first, and then Dsdt in + FADT. + For FACS, this function will locate XFirmwareCtrl in FADT first, and then + FirmwareCtrl in FADT. + + @param Signature ACPI table signature. + + @return First ACPI table or NULL if not found. + +**/ +EFI_ACPI_COMMON_HEADER * +EFIAPI +EfiLocateFirstAcpiTable ( + IN UINT32 Signature + ) +{ + return EfiLocateNextAcpiTable (Signature, NULL); +} diff --git a/MdePkg/Library/UefiLib/UefiLib.inf b/MdePkg/Library/UefiLib/UefiLib.inf index a6c739ef3d6d..aea20fe67153 100644 --- a/MdePkg/Library/UefiLib/UefiLib.inf +++ b/MdePkg/Library/UefiLib/UefiLib.inf @@ -41,6 +41,7 @@ [Sources] Console.c UefiLib.c UefiLibInternal.h + Acpi.c [Packages] @@ -62,6 +63,8 @@ [Guids] gEfiEventReadyToBootGuid ## SOMETIMES_CONSUMES ## Event gEfiEventLegacyBootGuid ## SOMETIMES_CONSUMES ## Event gEfiGlobalVariableGuid ## SOMETIMES_CONSUMES ## Variable + gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ## SystemTable + gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ## SystemTable [Protocols] gEfiDriverBindingProtocolGuid ## SOMETIMES_PRODUCES -- 2.7.0.windows.1