diff --git a/0028-MdeModulePkg-FPDT-Lock-boot-performance-table-addres.patch b/0028-MdeModulePkg-FPDT-Lock-boot-performance-table-addres.patch new file mode 100644 index 0000000000000000000000000000000000000000..0917f11c5f0a8efcd2b57b8a8f56528f98db9d79 --- /dev/null +++ b/0028-MdeModulePkg-FPDT-Lock-boot-performance-table-addres.patch @@ -0,0 +1,982 @@ +From 306307df0e228c73f6ad38ef231db75c4a3478d1 Mon Sep 17 00:00:00 2001 +From: Dandan Bi +Date: Mon, 28 Jun 2021 19:50:22 +0800 +Subject: [PATCH] MdeModulePkg/FPDT: Lock boot performance table address + variable at EndOfDxe + +REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2957 + +1. Allocate performance data table at EndOfDxe and then lock the varible + which store the table address at EndOfDxe. + +2. Enlarge PCD gEfiMdeModulePkgTokenSpaceGuid.PcdExtFpdtBootRecordPadSize + from 0x20000 to 0x30000 in order to hold the Delta performance data + between EndOfDxe and ReadyToBoot. + +3. SMM performance data is collected by DXE modules through SMM communication + at ReadyToBoot before. + Now to do SMM communication twice, one for allocating the performance + size at EndOfDxe, another is at ReadyToBoot to get SMM performance data. + +4. Make SmmCorePerformanceLib rather than FirmwarePerformanceSmm to communicate + with DxeCorePerformanceLib for SMM performance data and size. + +Cc: Liming Gao +Cc: Hao A Wu +Cc: Jian J Wang +Signed-off-by: Dandan Bi +Reviewed-by: Hao A Wu +Signed-off-by: Jinhua Cao +--- + .../DxeCorePerformanceLib.c | 132 +++++++++++---- + .../DxeCorePerformanceLib.inf | 3 +- + .../SmmCorePerformanceLib.c | 142 ++++++++++++---- + .../SmmCorePerformanceLib.inf | 5 +- + MdeModulePkg/MdeModulePkg.dec | 4 +- + .../FirmwarePerformanceDxe.c | 90 +++++++++-- + .../FirmwarePerformanceDxe.inf | 6 +- + .../FirmwarePerformanceSmm.c | 151 +----------------- + .../FirmwarePerformanceSmm.inf | 4 +- + 9 files changed, 302 insertions(+), 235 deletions(-) + +diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c +index f500e20b32..bcefac6b6c 100644 +--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c ++++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c +@@ -10,7 +10,7 @@ + This library is mainly used by DxeCore to start performance logging to ensure that + Performance Protocol is installed at the very beginning of DXE phase. + +-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
++Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +@@ -64,7 +64,7 @@ UINT32 mLoadImageCount = 0; + UINT32 mPerformanceLength = 0; + UINT32 mMaxPerformanceLength = 0; + UINT32 mBootRecordSize = 0; +-UINT32 mBootRecordMaxSize = 0; ++UINTN mBootRecordMaxSize = 0; + UINT32 mCachedLength = 0; + + BOOLEAN mFpdtBufferIsReported = FALSE; +@@ -205,25 +205,26 @@ IsKnownID ( + } + + /** +- Allocate buffer for Boot Performance table. ++ This internal function dumps all the SMM performance data and size. + +- @return Status code. ++ @param SmmPerfData Smm Performance data. The buffer contain the SMM perf data is allocated by this function and caller needs to free it. ++ @param SmmPerfDataSize Smm Performance data size. ++ @param SkipGetPerfData Skip to get performance data, just get the size. + + **/ +-EFI_STATUS +-AllocateBootPerformanceTable ( ++VOID ++InternalGetSmmPerfData ( ++ OUT VOID **SmmPerfData, ++ OUT UINTN *SmmPerfDataSize, ++ IN BOOLEAN SkipGetPerfData + ) + { + EFI_STATUS Status; +- UINTN Size; + UINT8 *SmmBootRecordCommBuffer; + EFI_SMM_COMMUNICATE_HEADER *SmmCommBufferHeader; + SMM_BOOT_RECORD_COMMUNICATE *SmmCommData; + UINTN CommSize; +- UINTN BootPerformanceDataSize; +- UINT8 *BootPerformanceData; + EFI_SMM_COMMUNICATION_PROTOCOL *Communication; +- FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable; + EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *SmmCommRegionTable; + EFI_MEMORY_DESCRIPTOR *SmmCommMemRegion; + UINTN Index; +@@ -237,7 +238,6 @@ AllocateBootPerformanceTable ( + SmmBootRecordCommBuffer = NULL; + SmmCommData = NULL; + SmmBootRecordData = NULL; +- SmmBootRecordDataSize = 0; + ReservedMemSize = 0; + Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &Communication); + if (!EFI_ERROR (Status)) { +@@ -284,6 +284,10 @@ AllocateBootPerformanceTable ( + Status = Communication->Communicate (Communication, SmmBootRecordCommBuffer, &CommSize); + + if (!EFI_ERROR (Status) && !EFI_ERROR (SmmCommData->ReturnStatus) && SmmCommData->BootRecordSize != 0) { ++ if (SkipGetPerfData) { ++ *SmmPerfDataSize = SmmCommData->BootRecordSize; ++ return; ++ } + // + // Get all boot records + // +@@ -305,19 +309,45 @@ AllocateBootPerformanceTable ( + } + SmmCommData->BootRecordOffset = SmmCommData->BootRecordOffset + SmmCommData->BootRecordSize; + } ++ *SmmPerfData = SmmBootRecordData; ++ *SmmPerfDataSize = SmmBootRecordDataSize; + } + } + } + } ++} ++ ++/** ++ Allocate buffer for Boot Performance table. ++ ++ @return Status code. ++ ++**/ ++EFI_STATUS ++AllocateBootPerformanceTable ( ++ VOID ++ ) ++{ ++ EFI_STATUS Status; ++ UINTN Size; ++ UINTN BootPerformanceDataSize; ++ UINT8 *BootPerformanceData; ++ FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable; ++ UINTN SmmBootRecordDataSize; ++ ++ SmmBootRecordDataSize = 0; ++ ++ // ++ // Get SMM performance data size at the point of EndOfDxe in order to allocate the boot performance table. ++ // Will Get all the data at ReadyToBoot. ++ // ++ InternalGetSmmPerfData (NULL, &SmmBootRecordDataSize, TRUE); + + // + // Prepare memory for Boot Performance table. + // Boot Performance table includes BasicBoot record, and one or more appended Boot Records. + // +- BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mPerformanceLength + PcdGet32 (PcdExtFpdtBootRecordPadSize); +- if (SmmCommData != NULL && SmmBootRecordData != NULL) { +- BootPerformanceDataSize += SmmBootRecordDataSize; +- } ++ BootPerformanceDataSize = sizeof (BOOT_PERFORMANCE_TABLE) + mPerformanceLength + SmmBootRecordDataSize + PcdGet32 (PcdExtFpdtBootRecordPadSize); + + // + // Try to allocate the same runtime buffer as last time boot. +@@ -358,9 +388,6 @@ AllocateBootPerformanceTable ( + DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: ACPI Boot Performance Table address = 0x%x\n", mAcpiBootPerformanceTable)); + + if (mAcpiBootPerformanceTable == NULL) { +- if (SmmCommData != NULL && SmmBootRecordData != NULL) { +- FreePool (SmmBootRecordData); +- } + return EFI_OUT_OF_RESOURCES; + } + +@@ -385,19 +412,10 @@ AllocateBootPerformanceTable ( + mPerformanceLength = 0; + mMaxPerformanceLength = 0; + } +- if (SmmCommData != NULL && SmmBootRecordData != NULL) { +- // +- // Fill Boot records from SMM drivers. +- // +- CopyMem (BootPerformanceData, SmmBootRecordData, SmmBootRecordDataSize); +- FreePool (SmmBootRecordData); +- mAcpiBootPerformanceTable->Header.Length = (UINT32) (mAcpiBootPerformanceTable->Header.Length + SmmBootRecordDataSize); +- BootPerformanceData = BootPerformanceData + SmmBootRecordDataSize; +- } + + mBootRecordBuffer = (UINT8 *) mAcpiBootPerformanceTable; + mBootRecordSize = mAcpiBootPerformanceTable->Header.Length; +- mBootRecordMaxSize = mBootRecordSize + PcdGet32 (PcdExtFpdtBootRecordPadSize); ++ mBootRecordMaxSize = BootPerformanceDataSize; + + return EFI_SUCCESS; + } +@@ -1336,6 +1354,47 @@ ReportFpdtRecordBuffer ( + } + } + ++/** ++ Update Boot Performance table. ++ ++ @param Event The event of notify protocol. ++ @param Context Notify event context. ++ ++**/ ++VOID ++EFIAPI ++UpdateBootPerformanceTable ( ++ IN EFI_EVENT Event, ++ IN VOID *Context ++ ) ++{ ++ VOID *SmmBootRecordData; ++ UINTN SmmBootRecordDataSize; ++ UINTN AppendSize; ++ UINT8 *FirmwarePerformanceTablePtr; ++ ++ // ++ // Get SMM performance data. ++ // ++ SmmBootRecordData = NULL; ++ InternalGetSmmPerfData (&SmmBootRecordData, &SmmBootRecordDataSize, FALSE); ++ ++ FirmwarePerformanceTablePtr = (UINT8 *) mAcpiBootPerformanceTable + mAcpiBootPerformanceTable->Header.Length; ++ ++ if (mAcpiBootPerformanceTable->Header.Length + SmmBootRecordDataSize > mBootRecordMaxSize) { ++ DEBUG ((DEBUG_INFO, "DxeCorePerformanceLib: No enough space to save all SMM boot performance data\n")); ++ AppendSize = mBootRecordMaxSize - mAcpiBootPerformanceTable->Header.Length; ++ } else { ++ AppendSize = SmmBootRecordDataSize; ++ } ++ if (SmmBootRecordData != NULL) { ++ CopyMem (FirmwarePerformanceTablePtr, SmmBootRecordData, AppendSize); ++ mAcpiBootPerformanceTable->Header.Length += (UINT32) AppendSize; ++ mBootRecordSize += (UINT32) AppendSize; ++ FreePool (SmmBootRecordData); ++ } ++} ++ + /** + The constructor function initializes Performance infrastructure for DXE phase. + +@@ -1358,6 +1417,7 @@ DxeCorePerformanceLibConstructor ( + { + EFI_STATUS Status; + EFI_HANDLE Handle; ++ EFI_EVENT EndOfDxeEvent; + EFI_EVENT ReadyToBootEvent; + PERFORMANCE_PROPERTY *PerformanceProperty; + +@@ -1386,13 +1446,25 @@ DxeCorePerformanceLibConstructor ( + ASSERT_EFI_ERROR (Status); + + // +- // Register ReadyToBoot event to report StatusCode data ++ // Register EndOfDxe event to allocate the boot performance table and report the table address through status code. + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, +- TPL_CALLBACK, ++ TPL_NOTIFY, + ReportFpdtRecordBuffer, + NULL, ++ &gEfiEndOfDxeEventGroupGuid, ++ &EndOfDxeEvent ++ ); ++ ++ // ++ // Register ReadyToBoot event to update the boot performance table for SMM performance data. ++ // ++ Status = gBS->CreateEventEx ( ++ EVT_NOTIFY_SIGNAL, ++ TPL_CALLBACK, ++ UpdateBootPerformanceTable, ++ NULL, + &gEfiEventReadyToBootGuid, + &ReadyToBootEvent + ); +diff --git a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf +index 1c1dcc60a6..599d4dea66 100644 +--- a/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf ++++ b/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.inf +@@ -9,7 +9,7 @@ + # This library is mainly used by DxeCore to start performance logging to ensure that + # Performance and PerformanceEx Protocol are installed at the very beginning of DXE phase. + # +-# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
++# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.
+ # (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ # SPDX-License-Identifier: BSD-2-Clause-Patent + # +@@ -67,6 +67,7 @@ + gZeroGuid ## SOMETIMES_CONSUMES ## GUID + gEfiFirmwarePerformanceGuid ## SOMETIMES_PRODUCES ## UNDEFINED # StatusCode Data + gEdkiiFpdtExtendedFirmwarePerformanceGuid ## SOMETIMES_CONSUMES ## HOB # StatusCode Data ++ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event + gEfiEventReadyToBootGuid ## CONSUMES ## Event + gEdkiiPiSmmCommunicationRegionTableGuid ## SOMETIMES_CONSUMES ## SystemTable + gEdkiiPerformanceMeasurementProtocolGuid ## PRODUCES ## UNDEFINED # Install protocol +diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c +index b4f22c14ae..d80f37e520 100644 +--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c ++++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.c +@@ -16,7 +16,7 @@ + + SmmPerformanceHandlerEx(), SmmPerformanceHandler() will receive untrusted input and do basic validation. + +-Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
++Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -48,6 +48,7 @@ CHAR8 *mPlatformLanguage = NULL; + SPIN_LOCK mSmmFpdtLock; + PERFORMANCE_PROPERTY mPerformanceProperty; + UINT32 mCachedLength = 0; ++UINT32 mBootRecordSize = 0; + + // + // Interfaces for SMM PerformanceMeasurement Protocol. +@@ -776,41 +777,116 @@ InsertFpdtRecord ( + } + + /** +- SmmReadyToBoot protocol notification event handler. ++ Communication service SMI Handler entry. + +- @param Protocol Points to the protocol's unique identifier +- @param Interface Points to the interface instance +- @param Handle The handle on which the interface was installed ++ This SMI handler provides services for report MM boot records. + +- @retval EFI_SUCCESS SmmReadyToBootCallback runs successfully ++ Caution: This function may receive untrusted input. ++ Communicate buffer and buffer size are external input, so this function will do basic validation. ++ ++ @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). ++ @param[in] RegisterContext Points to an optional handler context which was specified when the ++ handler was registered. ++ @param[in, out] CommBuffer A pointer to a collection of data in memory that will ++ be conveyed from a non-MM environment into an MM environment. ++ @param[in, out] CommBufferSize The size of the CommBuffer. ++ ++ @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers ++ should still be called. ++ @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should ++ still be called. ++ @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still ++ be called. ++ @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced. + + **/ + EFI_STATUS + EFIAPI +-SmmReportFpdtRecordData ( +- IN CONST EFI_GUID *Protocol, +- IN VOID *Interface, +- IN EFI_HANDLE Handle ++FpdtSmiHandler ( ++ IN EFI_HANDLE DispatchHandle, ++ IN CONST VOID *RegisterContext, ++ IN OUT VOID *CommBuffer, ++ IN OUT UINTN *CommBufferSize + ) + { +- UINT64 SmmBPDTddr; +- +- if (!mFpdtDataIsReported && mSmmBootPerformanceTable != NULL) { +- SmmBPDTddr = (UINT64)(UINTN)mSmmBootPerformanceTable; +- REPORT_STATUS_CODE_EX ( +- EFI_PROGRESS_CODE, +- EFI_SOFTWARE_SMM_DRIVER, +- 0, +- NULL, +- &gEdkiiFpdtExtendedFirmwarePerformanceGuid, +- &SmmBPDTddr, +- sizeof (UINT64) ++ EFI_STATUS Status; ++ SMM_BOOT_RECORD_COMMUNICATE *SmmCommData; ++ UINTN BootRecordOffset; ++ UINTN BootRecordSize; ++ VOID *BootRecordData; ++ UINTN TempCommBufferSize; ++ UINT8 *BootRecordBuffer; ++ ++ // ++ // If input is invalid, stop processing this SMI ++ // ++ if (CommBuffer == NULL || CommBufferSize == NULL) { ++ return EFI_SUCCESS; ++ } ++ ++ TempCommBufferSize = *CommBufferSize; ++ ++ if(TempCommBufferSize < sizeof (SMM_BOOT_RECORD_COMMUNICATE)) { ++ return EFI_SUCCESS; ++ } ++ ++ if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) { ++ DEBUG ((DEBUG_ERROR, "FpdtSmiHandler: MM communication data buffer in MMRAM or overflow!\n")); ++ return EFI_SUCCESS; ++ } ++ ++ SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)CommBuffer; ++ ++ Status = EFI_SUCCESS; ++ ++ switch (SmmCommData->Function) { ++ case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE : ++ if (mSmmBootPerformanceTable != NULL) { ++ mBootRecordSize = mSmmBootPerformanceTable->Header.Length - sizeof (SMM_BOOT_PERFORMANCE_TABLE); ++ } ++ SmmCommData->BootRecordSize = mBootRecordSize; ++ break; ++ ++ case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA : ++ Status = EFI_UNSUPPORTED; ++ break; ++ ++ case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA_BY_OFFSET : ++ BootRecordOffset = SmmCommData->BootRecordOffset; ++ BootRecordData = SmmCommData->BootRecordData; ++ BootRecordSize = SmmCommData->BootRecordSize; ++ if (BootRecordData == NULL || BootRecordOffset >= mBootRecordSize) { ++ Status = EFI_INVALID_PARAMETER; ++ break; ++ } ++ ++ // ++ // Sanity check ++ // ++ if (BootRecordSize > mBootRecordSize - BootRecordOffset) { ++ BootRecordSize = mBootRecordSize - BootRecordOffset; ++ } ++ SmmCommData->BootRecordSize = BootRecordSize; ++ if (!SmmIsBufferOutsideSmmValid ((UINTN)BootRecordData, BootRecordSize)) { ++ DEBUG ((DEBUG_ERROR, "FpdtSmiHandler: MM Data buffer in MMRAM or overflow!\n")); ++ Status = EFI_ACCESS_DENIED; ++ break; ++ } ++ BootRecordBuffer = ((UINT8 *) (mSmmBootPerformanceTable)) + sizeof (SMM_BOOT_PERFORMANCE_TABLE); ++ CopyMem ( ++ (UINT8*)BootRecordData, ++ BootRecordBuffer + BootRecordOffset, ++ BootRecordSize + ); +- // +- // Set FPDT report state to TRUE. +- // +- mFpdtDataIsReported = TRUE; ++ mFpdtDataIsReported = TRUE; ++ break; ++ ++ default: ++ Status = EFI_UNSUPPORTED; + } ++ ++ SmmCommData->ReturnStatus = Status; ++ + return EFI_SUCCESS; + } + +@@ -830,8 +906,8 @@ InitializeSmmCorePerformanceLib ( + ) + { + EFI_HANDLE Handle; ++ EFI_HANDLE SmiHandle; + EFI_STATUS Status; +- VOID *SmmReadyToBootRegistration; + PERFORMANCE_PROPERTY *PerformanceProperty; + + // +@@ -851,11 +927,13 @@ InitializeSmmCorePerformanceLib ( + ); + ASSERT_EFI_ERROR (Status); + +- Status = gSmst->SmmRegisterProtocolNotify ( +- &gEdkiiSmmReadyToBootProtocolGuid, +- SmmReportFpdtRecordData, +- &SmmReadyToBootRegistration +- ); ++ // ++ // Register SMI handler. ++ // ++ SmiHandle = NULL; ++ Status = gSmst->SmiHandlerRegister (FpdtSmiHandler, &gEfiFirmwarePerformanceGuid, &SmiHandle); ++ ASSERT_EFI_ERROR (Status); ++ + Status = EfiGetSystemConfigurationTable (&gPerformanceProtocolGuid, (VOID **) &PerformanceProperty); + if (EFI_ERROR (Status)) { + // +diff --git a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf +index 6b013b8557..9eecc4b58c 100644 +--- a/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf ++++ b/MdeModulePkg/Library/SmmCorePerformanceLib/SmmCorePerformanceLib.inf +@@ -8,7 +8,7 @@ + # This library is mainly used by SMM Core to start performance logging to ensure that + # SMM Performance and PerformanceEx Protocol are installed at the very beginning of SMM phase. + # +-# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
++# Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.
+ # SPDX-License-Identifier: BSD-2-Clause-Patent + # + ## +@@ -58,14 +58,13 @@ + + [Protocols] + gEfiSmmBase2ProtocolGuid ## CONSUMES +- gEdkiiSmmReadyToBootProtocolGuid ## NOTIFY + + [Guids] + ## PRODUCES ## SystemTable + gPerformanceProtocolGuid +- gEdkiiFpdtExtendedFirmwarePerformanceGuid ## SOMETIMES_PRODUCES ## UNDEFINED # StatusCode Data + gZeroGuid ## SOMETIMES_CONSUMES ## GUID + gEdkiiSmmPerformanceMeasurementProtocolGuid ## PRODUCES ## UNDEFINED # Install protocol ++ gEfiFirmwarePerformanceGuid ## SOMETIMES_PRODUCES ## UNDEFINED # SmiHandlerRegister + + [Pcd] + gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask ## CONSUMES +diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec +index 5d9e2b8d3d..b139f1668c 100644 +--- a/MdeModulePkg/MdeModulePkg.dec ++++ b/MdeModulePkg/MdeModulePkg.dec +@@ -1822,9 +1822,9 @@ + gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosEntryPointProvideMethod|0x3|UINT32|0x00010069 + + ## This PCD specifies the additional pad size in FPDT Basic Boot Performance Table for +- # the extension FPDT boot records received after ReadyToBoot and before ExitBootService. ++ # the extension FPDT boot records received after EndOfDxe and before ExitBootService. + # @Prompt Pad size for extension FPDT boot records. +- gEfiMdeModulePkgTokenSpaceGuid.PcdExtFpdtBootRecordPadSize|0x20000|UINT32|0x0001005F ++ gEfiMdeModulePkgTokenSpaceGuid.PcdExtFpdtBootRecordPadSize|0x30000|UINT32|0x0001005F + + ## Indicates if ConIn device are connected on demand.

+ # TRUE - ConIn device are not connected during BDS and ReadKeyStroke/ReadKeyStrokeEx produced +diff --git a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.c b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.c +index 61a7704b37..68755554ad 100644 +--- a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.c ++++ b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.c +@@ -5,7 +5,7 @@ + for Firmware Basic Boot Performance Record and other boot performance records, + and install FPDT to ACPI table. + +- Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.
++ Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -32,6 +33,8 @@ + #include + #include + #include ++#include ++#include + + #define SMM_BOOT_RECORD_COMM_SIZE (OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + sizeof(SMM_BOOT_RECORD_COMMUNICATE)) + +@@ -278,11 +281,12 @@ InstallFirmwarePerformanceDataTable ( + VOID + ) + { +- EFI_STATUS Status; +- EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; +- UINTN BootPerformanceDataSize; +- FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable; +- UINTN Size; ++ EFI_STATUS Status; ++ EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol; ++ UINTN BootPerformanceDataSize; ++ FIRMWARE_PERFORMANCE_VARIABLE PerformanceVariable; ++ UINTN Size; ++ EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicyProtocol; + + // + // Get AcpiTable Protocol. +@@ -292,6 +296,14 @@ InstallFirmwarePerformanceDataTable ( + return Status; + } + ++ // ++ // Get VariablePolicy Protocol. ++ // ++ Status = gBS->LocateProtocol(&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicyProtocol); ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } ++ + if (mReceivedAcpiBootPerformanceTable != NULL) { + mAcpiBootPerformanceTable = mReceivedAcpiBootPerformanceTable; + mAcpiBootPerformanceTable->BasicBoot.ResetEnd = mBootPerformanceTableTemplate.BasicBoot.ResetEnd; +@@ -369,6 +381,24 @@ InstallFirmwarePerformanceDataTable ( + &PerformanceVariable + ); + ++ // ++ // Lock the variable which stores the Performance Table pointers. ++ // ++ Status = RegisterBasicVariablePolicy ( ++ VariablePolicyProtocol, ++ &gEfiFirmwarePerformanceGuid, ++ EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME, ++ VARIABLE_POLICY_NO_MIN_SIZE, ++ VARIABLE_POLICY_NO_MAX_SIZE, ++ VARIABLE_POLICY_NO_MUST_ATTR, ++ VARIABLE_POLICY_NO_CANT_ATTR, ++ VARIABLE_POLICY_TYPE_LOCK_NOW ++ ); ++ if (EFI_ERROR(Status)) { ++ DEBUG((DEBUG_ERROR, "[FirmwarePerformanceDxe] Error when lock variable %s, Status = %r\n", EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME, Status)); ++ ASSERT_EFI_ERROR(Status); ++ } ++ + // + // Publish Firmware Performance Data Table. + // +@@ -501,18 +531,12 @@ FpdtStatusCodeListenerDxe ( + DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart)); + DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesEntry = 0\n")); + DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesExit = 0\n")); +- } else if (Value == (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT)) { +- if (mAcpiBootPerformanceTable == NULL) { +- // +- // ACPI Firmware Performance Data Table not installed yet, install it now. +- // +- InstallFirmwarePerformanceDataTable (); +- } + } else if (Data != NULL && CompareGuid (&Data->Type, &gEdkiiFpdtExtendedFirmwarePerformanceGuid)) { + // + // Get the Boot performance table and then install it to ACPI table. + // + CopyMem (&mReceivedAcpiBootPerformanceTable, Data + 1, Data->Size); ++ InstallFirmwarePerformanceDataTable (); + } else if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) { + DEBUG ((DEBUG_ERROR, "FpdtStatusCodeListenerDxe: Performance data reported through gEfiFirmwarePerformanceGuid will not be collected by FirmwarePerformanceDataTableDxe\n")); + Status = EFI_UNSUPPORTED; +@@ -526,6 +550,32 @@ FpdtStatusCodeListenerDxe ( + return Status; + } + ++/** ++ Notify function for event EndOfDxe. ++ ++ This is used to install ACPI Firmware Performance Data Table for basic boot records. ++ ++ @param[in] Event The Event that is being processed. ++ @param[in] Context The Event Context. ++ ++**/ ++VOID ++EFIAPI ++FpdtEndOfDxeEventNotify ( ++ IN EFI_EVENT Event, ++ IN VOID *Context ++ ) ++{ ++ // ++ // When performance is enabled, the FPDT will be installed when DxeCorePerformanceLib report the data to FimwarePerformanceDxe. ++ // This is used to install the FPDT for the basic boot recods when performance infrastructure is not enabled. ++ // ++ if ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0) { ++ return; ++ } ++ ASSERT (mReceivedAcpiBootPerformanceTable == NULL); ++ InstallFirmwarePerformanceDataTable (); ++} + + /** + Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record +@@ -596,6 +646,7 @@ FirmwarePerformanceDxeEntryPoint ( + FIRMWARE_SEC_PERFORMANCE *Performance; + VOID *Registration; + UINT64 OemTableId; ++ EFI_EVENT EndOfDxeEvent; + + CopyMem ( + mFirmwarePerformanceTableTemplate.Header.OemId, +@@ -620,6 +671,19 @@ FirmwarePerformanceDxeEntryPoint ( + Status = mRscHandlerProtocol->Register (FpdtStatusCodeListenerDxe, TPL_HIGH_LEVEL); + ASSERT_EFI_ERROR (Status); + ++ // ++ // Register the notify function to install FPDT at EndOfDxe. ++ // ++ Status = gBS->CreateEventEx ( ++ EVT_NOTIFY_SIGNAL, ++ TPL_NOTIFY, ++ FpdtEndOfDxeEventNotify, ++ NULL, ++ &gEfiEndOfDxeEventGroupGuid, ++ &EndOfDxeEvent ++ ); ++ ASSERT_EFI_ERROR (Status); ++ + // + // Register the notify function to update FPDT on ExitBootServices Event. + // +diff --git a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf +index 1debb0193e..0411a22e66 100644 +--- a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf ++++ b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableDxe/FirmwarePerformanceDxe.inf +@@ -5,7 +5,7 @@ + # for Firmware Basic Boot Performance Record and other boot performance records, + # and install FPDT to ACPI table. + # +-# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
++# Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.
+ # SPDX-License-Identifier: BSD-2-Clause-Patent + # + ## +@@ -46,12 +46,14 @@ + HobLib + LockBoxLib + UefiLib ++ VariablePolicyHelperLib + + [Protocols] + gEfiAcpiTableProtocolGuid ## CONSUMES + gEfiRscHandlerProtocolGuid ## CONSUMES + gEfiVariableArchProtocolGuid ## CONSUMES + gEfiLockBoxProtocolGuid ## CONSUMES ++ gEdkiiVariablePolicyProtocolGuid ## CONSUMES + + [Guids] + gEfiEventExitBootServicesGuid ## CONSUMES ## Event +@@ -63,6 +65,7 @@ + gEfiFirmwarePerformanceGuid + gEdkiiFpdtExtendedFirmwarePerformanceGuid ## SOMETIMES_CONSUMES ## UNDEFINED # StatusCode Data + gFirmwarePerformanceS3PointerGuid ## PRODUCES ## UNDEFINED # SaveLockBox ++ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event + + [Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeOsLoaderLoad ## CONSUMES +@@ -72,6 +75,7 @@ + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## CONSUMES ++ gEfiMdePkgTokenSpaceGuid.PcdPerformanceLibraryPropertyMask ## CONSUMES + + [FeaturePcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwarePerformanceDataTableS3Support ## CONSUMES +diff --git a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c +index d6c6e7693e..dbd9fe1842 100644 +--- a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c ++++ b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c +@@ -11,7 +11,7 @@ + + FpdtSmiHandler() will receive untrusted input and do basic validation. + +- Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
++ Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + **/ +@@ -29,21 +29,12 @@ + #include + #include + #include +-#include + #include +-#include + #include + +-SMM_BOOT_PERFORMANCE_TABLE *mSmmBootPerformanceTable = NULL; +- + EFI_SMM_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL; + UINT64 mSuspendStartTime = 0; + BOOLEAN mS3SuspendLockBoxSaved = FALSE; +-UINT32 mBootRecordSize = 0; +-UINT8 *mBootRecordBuffer = NULL; +- +-SPIN_LOCK mSmmFpdtLock; +-BOOLEAN mSmramIsOutOfResource = FALSE; + + /** + Report status code listener for SMM. This is used to record the performance +@@ -85,21 +76,6 @@ FpdtStatusCodeListenerSmm ( + return EFI_UNSUPPORTED; + } + +- // +- // Collect one or more Boot records in boot time +- // +- if (Data != NULL && CompareGuid (&Data->Type, &gEdkiiFpdtExtendedFirmwarePerformanceGuid)) { +- AcquireSpinLock (&mSmmFpdtLock); +- // +- // Get the boot performance data. +- // +- CopyMem (&mSmmBootPerformanceTable, Data + 1, Data->Size); +- mBootRecordBuffer = ((UINT8 *) (mSmmBootPerformanceTable)) + sizeof (SMM_BOOT_PERFORMANCE_TABLE); +- +- ReleaseSpinLock (&mSmmFpdtLock); +- return EFI_SUCCESS; +- } +- + if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) { + DEBUG ((DEBUG_ERROR, "FpdtStatusCodeListenerSmm: Performance data reported through gEfiFirmwarePerformanceGuid will not be collected by FirmwarePerformanceDataTableSmm\n")); + return EFI_UNSUPPORTED; +@@ -154,118 +130,6 @@ FpdtStatusCodeListenerSmm ( + return EFI_SUCCESS; + } + +-/** +- Communication service SMI Handler entry. +- +- This SMI handler provides services for report SMM boot records. +- +- Caution: This function may receive untrusted input. +- Communicate buffer and buffer size are external input, so this function will do basic validation. +- +- @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister(). +- @param[in] RegisterContext Points to an optional handler context which was specified when the +- handler was registered. +- @param[in, out] CommBuffer A pointer to a collection of data in memory that will +- be conveyed from a non-SMM environment into an SMM environment. +- @param[in, out] CommBufferSize The size of the CommBuffer. +- +- @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers +- should still be called. +- @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should +- still be called. +- @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still +- be called. +- @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced. +- +-**/ +-EFI_STATUS +-EFIAPI +-FpdtSmiHandler ( +- IN EFI_HANDLE DispatchHandle, +- IN CONST VOID *RegisterContext, +- IN OUT VOID *CommBuffer, +- IN OUT UINTN *CommBufferSize +- ) +-{ +- EFI_STATUS Status; +- SMM_BOOT_RECORD_COMMUNICATE *SmmCommData; +- UINTN BootRecordOffset; +- UINTN BootRecordSize; +- VOID *BootRecordData; +- UINTN TempCommBufferSize; +- +- // +- // If input is invalid, stop processing this SMI +- // +- if (CommBuffer == NULL || CommBufferSize == NULL) { +- return EFI_SUCCESS; +- } +- +- TempCommBufferSize = *CommBufferSize; +- +- if(TempCommBufferSize < sizeof (SMM_BOOT_RECORD_COMMUNICATE)) { +- return EFI_SUCCESS; +- } +- +- if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) { +- DEBUG ((EFI_D_ERROR, "FpdtSmiHandler: SMM communication data buffer in SMRAM or overflow!\n")); +- return EFI_SUCCESS; +- } +- +- SmmCommData = (SMM_BOOT_RECORD_COMMUNICATE*)CommBuffer; +- +- Status = EFI_SUCCESS; +- +- switch (SmmCommData->Function) { +- case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE : +- if (mSmmBootPerformanceTable != NULL) { +- mBootRecordSize = mSmmBootPerformanceTable->Header.Length - sizeof (SMM_BOOT_PERFORMANCE_TABLE); +- } +- SmmCommData->BootRecordSize = mBootRecordSize; +- break; +- +- case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA : +- Status = EFI_UNSUPPORTED; +- break; +- +- case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_DATA_BY_OFFSET : +- BootRecordOffset = SmmCommData->BootRecordOffset; +- BootRecordData = SmmCommData->BootRecordData; +- BootRecordSize = SmmCommData->BootRecordSize; +- if (BootRecordData == NULL || BootRecordOffset >= mBootRecordSize) { +- Status = EFI_INVALID_PARAMETER; +- break; +- } +- +- // +- // Sanity check +- // +- if (BootRecordSize > mBootRecordSize - BootRecordOffset) { +- BootRecordSize = mBootRecordSize - BootRecordOffset; +- } +- SmmCommData->BootRecordSize = BootRecordSize; +- if (!SmmIsBufferOutsideSmmValid ((UINTN)BootRecordData, BootRecordSize)) { +- DEBUG ((EFI_D_ERROR, "FpdtSmiHandler: SMM Data buffer in SMRAM or overflow!\n")); +- Status = EFI_ACCESS_DENIED; +- break; +- } +- +- CopyMem ( +- (UINT8*)BootRecordData, +- mBootRecordBuffer + BootRecordOffset, +- BootRecordSize +- ); +- break; +- +- default: +- Status = EFI_UNSUPPORTED; +- } +- +- SmmCommData->ReturnStatus = Status; +- +- return EFI_SUCCESS; +-} +- + /** + The module Entry Point of the Firmware Performance Data Table SMM driver. + +@@ -284,12 +148,6 @@ FirmwarePerformanceSmmEntryPoint ( + ) + { + EFI_STATUS Status; +- EFI_HANDLE Handle; +- +- // +- // Initialize spin lock +- // +- InitializeSpinLock (&mSmmFpdtLock); + + // + // Get SMM Report Status Code Handler Protocol. +@@ -307,12 +165,5 @@ FirmwarePerformanceSmmEntryPoint ( + Status = mRscHandlerProtocol->Register (FpdtStatusCodeListenerSmm); + ASSERT_EFI_ERROR (Status); + +- // +- // Register SMI handler. +- // +- Handle = NULL; +- Status = gSmst->SmiHandlerRegister (FpdtSmiHandler, &gEfiFirmwarePerformanceGuid, &Handle); +- ASSERT_EFI_ERROR (Status); +- + return Status; + } +diff --git a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf +index 618cbd56ca..6be57553f0 100644 +--- a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf ++++ b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf +@@ -4,7 +4,7 @@ + # This module registers report status code listener to collect performance data + # for SMM boot performance records and S3 Suspend Performance Record. + # +-# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
++# Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.
+ # SPDX-License-Identifier: BSD-2-Clause-Patent + # + ## +@@ -51,10 +51,8 @@ + + [Guids] + ## SOMETIMES_PRODUCES ## UNDEFINED # SaveLockBox +- ## PRODUCES ## UNDEFINED # SmiHandlerRegister + ## SOMETIMES_CONSUMES ## UNDEFINED # StatusCode Data + gEfiFirmwarePerformanceGuid +- gEdkiiFpdtExtendedFirmwarePerformanceGuid ## SOMETIMES_PRODUCES ## UNDEFINED # StatusCode Data + + [Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeS3SuspendStart ## CONSUMES +-- +2.27.0 + diff --git a/edk2.spec b/edk2.spec index f126508016dee84833749f4630a800c77ca91c22..815c96126c05da47292dbc66a753772f8dc48bba 100644 --- a/edk2.spec +++ b/edk2.spec @@ -5,7 +5,7 @@ Name: edk2 Version: %{stable_date} -Release: 9 +Release: 10 Summary: EFI Development Kit II License: BSD-2-Clause-Patent URL: https://github.com/tianocore/edk2 @@ -39,6 +39,7 @@ Patch0024: 0024-NetworkPkg-IScsiDxe-reformat-IScsiHexToBin-leading-c.patch Patch0025: 0025-NetworkPkg-IScsiDxe-fix-IScsiHexToBin-hex-parsing.patch Patch0026: 0026-NetworkPkg-IScsiDxe-fix-IScsiHexToBin-buffer-overflo.patch Patch0027: 0027-NetworkPkg-IScsiDxe-check-IScsiHexToBin-return-value.patch +Patch0028: 0028-MdeModulePkg-FPDT-Lock-boot-performance-table-addres.patch BuildRequires: acpica-tools gcc gcc-c++ libuuid-devel python3 bc nasm python3-unversioned-command @@ -236,6 +237,9 @@ chmod +x %{buildroot}%{_bindir}/Rsa2048Sha256GenerateKeys %endif %changelog +* Wed Dec 1 2021 Jinhua Cao -202002-10 +- fix CVE-2021-28216 + * Wed Sep 22 2021 imxcc - 202002-9 - fix cve-2021-38575