From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by mx.groups.io with SMTP id smtpd.web11.6452.1586158158468443054 for ; Mon, 06 Apr 2020 00:29:18 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 192.55.52.93, mailfrom: miki.shindo@intel.com) IronPort-SDR: NjQnKYqqeM5XT05nBxS7i9mmD867gFpWQg62//Cvz1eFnfv2lZZ4Fm+81+YQFyNQMEj9y4SPyH lMiJofUijW4A== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Apr 2020 00:29:18 -0700 IronPort-SDR: IwaiET3/txFmq4RPOX5HiZomwSWcRirsvJvwP1PA6+YYOJnWGQEFIEZn2wMo565svoT6VgBNcg lWgLXBUndMGA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,350,1580803200"; d="scan'208";a="241708189" Received: from mshindo-desk2.amr.corp.intel.com ([10.9.69.166]) by fmsmga007.fm.intel.com with ESMTP; 06 Apr 2020 00:29:17 -0700 From: "Miki Shindo" To: devel@edk2.groups.io Cc: Sai Chaganty , Chasel Chiu , Nate DeSimone , Prince Agyeman , Ray Ni Subject: [edk2-platforms:PATCH v3] IntelSiliconPkg/DxeAslUpdateLib: Add DxeAslUpdateLib support Date: Mon, 6 Apr 2020 00:29:10 -0700 Message-Id: <20200406072910.24136-1-miki.shindo@intel.com> X-Mailer: git-send-email 2.16.2.windows.1 REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2536 This commit adds DxeAslUpdateLib library support in IntelSiliconPkg, which allows AML to be updated in DXE. Signed-off-by: Miki Shindo Cc: Sai Chaganty Cc: Chasel Chiu Cc: Nate DeSimone Cc: Prince Agyeman Cc: Ray Ni Acked-by: Chasel Chiu Acked-by: Nate DeSimone Reviewed-by: Ray Ni --- Silicon/Intel/IntelSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c | 512 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Silicon/Intel/IntelSiliconPkg/Include/Library/AslUpdateLib.h | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 4 ++++ Silicon/Intel/IntelSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf | 42 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 664 insertions(+) diff --git a/Silicon/Intel/IntelSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c b/Silicon/Intel/IntelSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c new file mode 100644 index 0000000000..4e031b0edd --- /dev/null +++ b/Silicon/Intel/IntelSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.c @@ -0,0 +1,512 @@ +/** @file + Boot service DXE ASL update library implementation. + Note that the current version of the library updates AML. + + These functions in this file can be called during DXE and cannot be called during runtime + or in SMM which should use a RT or SMM library. + + This library uses the ACPI Support protocol. + + Copyright (c) 2020, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// +// Function implemenations +// +static EFI_ACPI_SDT_PROTOCOL *mAcpiSdt = NULL; +static EFI_ACPI_TABLE_PROTOCOL *mAcpiTable = NULL; + +/** + Initialize the ASL update library state. + This must be called prior to invoking other library functions. + + @retval EFI_SUCCESS - The function completed successfully. +**/ +EFI_STATUS +InitializeAslUpdateLib ( + VOID + ) +{ + EFI_STATUS Status; + + /// + /// Locate ACPI tables + /// + Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (VOID **) &mAcpiSdt); + ASSERT_EFI_ERROR (Status); + Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &mAcpiTable); + ASSERT_EFI_ERROR (Status); + return Status; +} + +/** + This function calculates and updates an UINT8 checksum. + + @param Buffer Pointer to buffer to checksum + @param Size Number of bytes to checksum + @param ChecksumOffset Offset to place the checksum result in + + @return EFI_SUCCESS The function completed successfully. + +**/ +EFI_STATUS +AcpiPlatformChecksum ( + IN VOID *Buffer, + IN UINTN Size, + IN UINTN ChecksumOffset + ) +{ + UINT8 Sum; + UINT8 *Ptr; + + Sum = 0; + // + // Initialize pointer + // + Ptr = Buffer; + + // + // set checksum to 0 first + // + Ptr[ChecksumOffset] = 0; + + // + // add all content of buffer + // + while ((Size--) != 0) { + Sum = (UINT8) (Sum + (*Ptr++)); + } + // + // set checksum + // + Ptr = Buffer; + Ptr[ChecksumOffset] = (UINT8) (0xff - Sum + 1); + + return EFI_SUCCESS; +} + +/** + This procedure will update immediate value assigned to a Name + + @param[in] AslSignature - The signature of Operation Region that we want to update. + @param[in] Buffer - source of data to be written over original aml + @param[in] Length - length of data to be overwritten + + @retval EFI_SUCCESS - The function completed successfully. + @retval EFI_NOT_FOUND - Failed to locate AcpiTable. +**/ +EFIAPI +EFI_STATUS +UpdateNameAslCode ( + IN UINT32 AslSignature, + IN VOID *Buffer, + IN UINTN Length + ) +{ + EFI_STATUS Status; + EFI_ACPI_DESCRIPTION_HEADER *Table; + UINT8 *CurrPtr; + UINT8 *EndPtr; + UINT32 *Signature; + UINT8 *DsdtPointer; + UINTN Handle; + UINT8 DataSize; + + if (mAcpiTable == NULL) { + InitializeAslUpdateLib (); + if (mAcpiTable == NULL) { + return EFI_NOT_READY; + } + } + + /// + /// Locate table with matching ID + /// + Handle = 0; + Status = LocateAcpiTableBySignature ( + EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, + (EFI_ACPI_DESCRIPTION_HEADER **) &Table, + &Handle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + /// + /// Point to the beginning of the DSDT table + /// + CurrPtr = (UINT8 *) Table; + if (CurrPtr == NULL) { + return EFI_NOT_FOUND; + } + + // + // EndPtr = beginning of table + length of table + // + EndPtr = CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length; + + /// + /// Loop through the ASL looking for values that we must fix up. + /// + for (DsdtPointer = CurrPtr; DsdtPointer < EndPtr; DsdtPointer++) { + /// + /// Get a pointer to compare for signature + /// + Signature = (UINT32 *) DsdtPointer; + /// + /// Check if this is the Device Object signature we are looking for + /// + if ((*Signature) == AslSignature) { + /// + /// Look for Name Encoding + /// + if (*(DsdtPointer-1) == AML_NAME_OP) { + /// + /// Check if size of new and old data is the same + /// + DataSize = *(DsdtPointer+4); + if ((Length == 1 && DataSize == 0xA) || + (Length == 2 && DataSize == 0xB) || + (Length == 4 && DataSize == 0xC)) { + CopyMem (DsdtPointer+5, Buffer, Length); + } else if (Length == 1 && ((*(UINT8*) Buffer) == 0 || (*(UINT8*) Buffer) == 1) && (DataSize == 0 || DataSize == 1)) { + CopyMem (DsdtPointer+4, Buffer, Length); + } else { + FreePool (Table); + return EFI_BAD_BUFFER_SIZE; + } + Status = mAcpiTable->UninstallAcpiTable ( + mAcpiTable, + Handle + ); + Handle = 0; + Status = mAcpiTable->InstallAcpiTable ( + mAcpiTable, + Table, + Table->Length, + &Handle + ); + FreePool (Table); + return Status; + } + } + } + return EFI_NOT_FOUND; +} + +/** + This procedure will update immediate value assigned to a Name in SSDT table + + @param[in] TableId - Pointer to an ASCII string containing the OEM Table ID from the ACPI table header + @param[in] TableIdSize - Length of the TableId to match. Table ID are 8 bytes long, this function + @param[in] Buffer - source of data to be written over original aml + @param[in] Length - length of data to be overwritten + + @retval EFI_SUCCESS - The function completed successfully. + @retval EFI_NOT_FOUND - Failed to locate AcpiTable. +**/ +EFIAPI +EFI_STATUS +UpdateSsdtNameAslCode ( + IN UINT8 *TableId, + IN UINT8 TableIdSize, + IN UINT32 AslSignature, + IN VOID *Buffer, + IN UINTN Length + ) +{ + EFI_STATUS Status; + EFI_ACPI_DESCRIPTION_HEADER *Table; + UINT8 *CurrPtr; + UINT32 *Signature; + UINT8 *SsdtPointer; + UINTN Handle; + UINT8 DataSize; + + if (mAcpiTable == NULL) { + InitializeAslUpdateLib (); + if (mAcpiTable == NULL) { + return EFI_NOT_READY; + } + } + + /// + /// Locate table with matching ID + /// + Handle = 0; + Status = LocateAcpiTableByOemTableId ( + TableId, + TableIdSize, + (EFI_ACPI_DESCRIPTION_HEADER **) &Table, + &Handle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + /// + /// Point to the beginning of the DSDT table + /// + CurrPtr = (UINT8 *) Table; + if (CurrPtr == NULL) { + return EFI_NOT_FOUND; + } + + /// + /// Loop through the ASL looking for values that we must fix up. + /// + for (SsdtPointer = CurrPtr; SsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); SsdtPointer++) { + /// + /// Get a pointer to compare for signature + /// + Signature = (UINT32 *) SsdtPointer; + /// + /// Check if this is the Device Object signature we are looking for + /// + if ((*Signature) == AslSignature) { + /// + /// Look for Name Encoding + /// + if (*(SsdtPointer-1) == AML_NAME_OP) { + /// + /// Check if size of new and old data is the same + /// + DataSize = *(SsdtPointer+4); + if ((Length == 1 && DataSize == 0xA) || + (Length == 2 && DataSize == 0xB) || + (Length == 4 && DataSize == 0xC)) { + CopyMem (SsdtPointer+5, Buffer, Length); + } else if (Length == 1 && ((*(UINT8*) Buffer) == 0 || (*(UINT8*) Buffer) == 1) && (DataSize == 0 || DataSize == 1)) { + CopyMem (SsdtPointer+4, Buffer, Length); + } else { + return EFI_BAD_BUFFER_SIZE; + } + AcpiPlatformChecksum ( + Table, + Table->Length, + OFFSET_OF (EFI_ACPI_DESCRIPTION_HEADER, + Checksum) + ); + return Status; + } + } + } + return EFI_NOT_FOUND; +} + +/** + This procedure will update the name of ASL Method + + @param[in] AslSignature - The signature of Operation Region that we want to update. + @param[in] Buffer - source of data to be written over original aml + @param[in] Length - length of data to be overwritten + + @retval EFI_SUCCESS - The function completed successfully. + @retval EFI_NOT_FOUND - Failed to locate AcpiTable. +**/ +EFIAPI +EFI_STATUS +UpdateMethodAslCode ( + IN UINT32 AslSignature, + IN VOID *Buffer, + IN UINTN Length + ) +{ + EFI_STATUS Status; + EFI_ACPI_DESCRIPTION_HEADER *Table; + UINT8 *CurrPtr; + UINT32 *Signature; + UINT8 *DsdtPointer; + UINTN Handle; + + if (mAcpiTable == NULL) { + InitializeAslUpdateLib (); + if (mAcpiTable == NULL) { + return EFI_NOT_READY; + } + } + + /// + /// Locate table with matching ID + /// + Handle = 0; + Status = LocateAcpiTableBySignature ( + EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE, + (EFI_ACPI_DESCRIPTION_HEADER **) &Table, + &Handle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + /// + /// Point to the beginning of the DSDT table + /// + CurrPtr = (UINT8 *) Table; + if (CurrPtr == NULL) { + return EFI_NOT_FOUND; + } + + /// + /// Loop through the ASL looking for values that we must fix up. + /// + for (DsdtPointer = CurrPtr; DsdtPointer <= (CurrPtr + ((EFI_ACPI_COMMON_HEADER *) CurrPtr)->Length); DsdtPointer++) { + /// + /// Get a pointer to compare for signature + /// + Signature = (UINT32 *) DsdtPointer; + /// + /// Check if this is the Device Object signature we are looking for + /// + if ((*Signature) == AslSignature) { + /// + /// Look for Name Encoding + /// + if ((*(DsdtPointer-3) == AML_METHOD_OP) + || (*(DsdtPointer-2) == AML_METHOD_OP) + ) + { + CopyMem (DsdtPointer, Buffer, Length); + Status = mAcpiTable->UninstallAcpiTable ( + mAcpiTable, + Handle + ); + Handle = 0; + Status = mAcpiTable->InstallAcpiTable ( + mAcpiTable, + Table, + Table->Length, + &Handle + ); + FreePool (Table); + return Status; + } + } + } + return EFI_NOT_FOUND; +} + +/** + This function uses the ACPI SDT protocol to locate an ACPI table. + It is really only useful for finding tables that only have a single instance, + e.g. FADT, FACS, MADT, etc. It is not good for locating SSDT, etc. + + @param[in] Signature - Pointer to an ASCII string containing the OEM Table ID from the ACPI table header + @param[in, out] Table - Updated with a pointer to the table + @param[in, out] Handle - AcpiSupport protocol table handle for the table found + @param[in, out] Version - The version of the table desired + + @retval EFI_SUCCESS - The function completed successfully. +**/ +EFIAPI +EFI_STATUS +LocateAcpiTableBySignature ( + IN UINT32 Signature, + IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table, + IN OUT UINTN *Handle + ) +{ + EFI_STATUS Status; + INTN Index; + EFI_ACPI_TABLE_VERSION Version; + EFI_ACPI_DESCRIPTION_HEADER *OrgTable; + + if (mAcpiSdt == NULL) { + InitializeAslUpdateLib (); + if (mAcpiSdt == NULL) { + return EFI_NOT_READY; + } + } + + /// + /// Locate table with matching ID + /// + Version = 0; + Index = 0; + do { + Status = mAcpiSdt->GetAcpiTable (Index, (EFI_ACPI_SDT_HEADER **)&OrgTable, &Version, Handle); + if (Status == EFI_NOT_FOUND) { + break; + } + ASSERT_EFI_ERROR (Status); + Index++; + } while (OrgTable->Signature != Signature); + + if (Status != EFI_NOT_FOUND) { + *Table = AllocateCopyPool (OrgTable->Length, OrgTable); + ASSERT (*Table); + } + + /// + /// If we found the table, there will be no error. + /// + return Status; +} + +/** + This function uses the ACPI SDT protocol to locate an ACPI SSDT table. + + @param[in] TableId - Pointer to an ASCII string containing the OEM Table ID from the ACPI table header + @param[in] TableIdSize - Length of the TableId to match. Table ID are 8 bytes long, this function + will consider it a match if the first TableIdSize bytes match + @param[in, out] Table - Updated with a pointer to the table + @param[in, out] Handle - AcpiSupport protocol table handle for the table found + @param[in, out] Version - See AcpiSupport protocol, GetAcpiTable function for use + + @retval EFI_SUCCESS - The function completed successfully. +**/ +EFI_STATUS +LocateAcpiTableByOemTableId ( + IN UINT8 *TableId, + IN UINT8 TableIdSize, + IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table, + IN OUT UINTN *Handle + ) +{ + EFI_STATUS Status; + INTN Index; + EFI_ACPI_TABLE_VERSION Version; + EFI_ACPI_DESCRIPTION_HEADER *OrgTable; + + if (mAcpiSdt == NULL) { + InitializeAslUpdateLib (); + if (mAcpiSdt == NULL) { + return EFI_NOT_READY; + } + } + /// + /// Locate table with matching ID + /// + Version = 0; + Index = 0; + do { + Status = mAcpiSdt->GetAcpiTable (Index, (EFI_ACPI_SDT_HEADER **)&OrgTable, &Version, Handle); + if (Status == EFI_NOT_FOUND) { + break; + } + ASSERT_EFI_ERROR (Status); + Index++; + } while (CompareMem (&(OrgTable->OemTableId), TableId, TableIdSize)); + + if (Status != EFI_NOT_FOUND) { + *Table = OrgTable; + ASSERT (*Table); + } + + /// + /// If we found the table, there will be no error. + /// + return Status; +} diff --git a/Silicon/Intel/IntelSiliconPkg/Include/Library/AslUpdateLib.h b/Silicon/Intel/IntelSiliconPkg/Include/Library/AslUpdateLib.h new file mode 100644 index 0000000000..c9699e59b6 --- /dev/null +++ b/Silicon/Intel/IntelSiliconPkg/Include/Library/AslUpdateLib.h @@ -0,0 +1,106 @@ +/** @file + ASL dynamic update library definitions. + + This library provides dynamic update to various ASL structures. + There may be different libraries for different environments (PEI, BS, RT, SMM). + Make sure you meet the requirements for the library (protocol dependencies, use + restrictions, etc). + + Note that the current version of the library updates AML. + + Copyright (c) 2020 Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#ifndef _ASL_UPDATE_LIB_H_ +#define _ASL_UPDATE_LIB_H_ + +// +// Include files +// +#include +#include +#include +#include + + +/** + This procedure will update immediate value assigned to a Name + + @param[in] AslSignature The signature of Operation Region that we want to update. + @param[in] Buffer source of data to be written over original aml + @param[in] Length length of data to be overwritten + + @retval EFI_SUCCESS The function completed successfully. +**/ +EFIAPI +EFI_STATUS +UpdateNameAslCode( + IN UINT32 AslSignature, + IN VOID *Buffer, + IN UINTN Length + ); + +/** + This procedure will update the name of ASL Method + + @param[in] AslSignature - The signature of Operation Region that we want to update. + @param[in] Buffer - source of data to be written over original aml + @param[in] Length - length of data to be overwritten + + @retval EFI_SUCCESS - The function completed successfully. + @retval EFI_NOT_FOUND - Failed to locate AcpiTable. +**/ +EFIAPI +EFI_STATUS +UpdateSsdtNameAslCode ( + IN UINT8 *TableId, + IN UINT8 TableIdSize, + IN UINT32 AslSignature, + IN VOID *Buffer, + IN UINTN Length + ); + +/** + This procedure will update the name of ASL Method + + @param[in] AslSignature - The signature of Operation Region that we want to update. + @param[in] Buffer - source of data to be written over original aml + @param[in] Length - length of data to be overwritten + + @retval EFI_SUCCESS - The function completed successfully. + @retval EFI_NOT_FOUND - Failed to locate AcpiTable. +**/ +EFIAPI +EFI_STATUS +UpdateMethodAslCode ( + IN UINT32 AslSignature, + IN VOID *Buffer, + IN UINTN Length + ); + +/** + This function uses the ACPI support protocol to locate an ACPI table using the . + It is really only useful for finding tables that only have a single instance, + e.g. FADT, FACS, MADT, etc. It is not good for locating SSDT, etc. + Matches are determined by finding the table with ACPI table that has + a matching signature and version. + + @param[in] Signature Pointer to an ASCII string containing the Signature to match + @param[in, out] Table Updated with a pointer to the table + @param[in, out] Handle AcpiSupport protocol table handle for the table found + @param[in, out] Version On input, the version of the table desired, + on output, the versions the table belongs to + @see AcpiSupport protocol for details + + @retval EFI_SUCCESS The function completed successfully. +**/ +EFIAPI +EFI_STATUS +LocateAcpiTableBySignature ( + IN UINT32 Signature, + IN OUT EFI_ACPI_DESCRIPTION_HEADER **Table, + IN OUT UINTN *Handle + ); + +#endif diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec index 3c49fb289c..d5debbf0da 100644 --- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec +++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec @@ -30,6 +30,10 @@ # PeiGetVtdPmrAlignmentLib|Include/Library/PeiGetVtdPmrAlignmentLib.h + ## @libraryclass Provides services to update AML in DXE + # + AslUpdateLib|Include/Library/AslUpdateLib.h + [Guids] ## GUID for Package token space # {A9F8D54E-1107-4F0A-ADD0-4587E7A4A735} diff --git a/Silicon/Intel/IntelSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf b/Silicon/Intel/IntelSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf new file mode 100644 index 0000000000..cefbe30628 --- /dev/null +++ b/Silicon/Intel/IntelSiliconPkg/Library/DxeAslUpdateLib/DxeAslUpdateLib.inf @@ -0,0 +1,42 @@ +## @file +# Provides services to update ASL tables. +# Note that the current version of the library updates AML. +# +# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + + + +[Defines] +INF_VERSION = 0x00010017 +BASE_NAME = DxeAslUpdateLib +FILE_GUID = 8621697D-4E3A-4bf2-ADB0-3E2FF06559CA +VERSION_STRING = 1.0 +MODULE_TYPE = DXE_DRIVER +LIBRARY_CLASS = AslUpdateLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PcdLib +BaseMemoryLib +UefiLib +MemoryAllocationLib + + +[Packages] +MdePkg/MdePkg.dec +IntelSiliconPkg/IntelSiliconPkg.dec + +[Sources] +DxeAslUpdateLib.c + + +[Protocols] +gEfiAcpiTableProtocolGuid ## CONSUMES +gEfiAcpiSdtProtocolGuid ## CONSUMES -- 2.16.2.windows.1