From 70a7906583b6bd38141264e6b6cac71c8e052d5e Mon Sep 17 00:00:00 2001 From: chenhuiying Date: Thu, 29 Sep 2022 16:23:55 +0800 Subject: [PATCH] fix Fix CVE-2019-11098 Signed-off-by: chenhuiying --- 0027-UefiCpuPkg-Correct-some-typos.patch | 119 ++ ...grationPei-Add-initial-PEIM-CVE-2019.patch | 857 +++++++++++ ...Core-Enable-T-RAM-evacuation-in-PeiC.patch | 1339 +++++++++++++++++ ...Pei-Use-Migrated-FV-Info-Hob-for-cal.patch | 117 ++ ...-new-PCD-to-control-the-evacuate-tem.patch | 74 + ...e-Create-Migrated-FV-Info-Hob-for-ca.patch | 170 +++ ...Pei-Add-GDT-migration-support-CVE-20.patch | 137 ++ ...Pei-Enable-paging-and-set-NP-flag-to.patch | 106 ++ ...ei-Use-Migrated-FV-Info-Hob-for-calc.patch | 105 ++ ...MigrateGdt-from-DiscoverMemory-to-Te.patch | 191 +++ edk2.spec | 17 +- 11 files changed, 3230 insertions(+), 2 deletions(-) create mode 100644 0027-UefiCpuPkg-Correct-some-typos.patch create mode 100644 0028-UefiCpuPkg-SecMigrationPei-Add-initial-PEIM-CVE-2019.patch create mode 100644 0029-MdeModulePkg-PeiCore-Enable-T-RAM-evacuation-in-PeiC.patch create mode 100644 0030-SecurityPkg-Tcg2Pei-Use-Migrated-FV-Info-Hob-for-cal.patch create mode 100644 0031-MdeModulePkg-Add-new-PCD-to-control-the-evacuate-tem.patch create mode 100644 0032-MdeModulePkg-Core-Create-Migrated-FV-Info-Hob-for-ca.patch create mode 100644 0033-UefiCpuPkg-CpuMpPei-Add-GDT-migration-support-CVE-20.patch create mode 100644 0034-UefiCpuPkg-CpuMpPei-Enable-paging-and-set-NP-flag-to.patch create mode 100644 0035-SecurityPkg-TcgPei-Use-Migrated-FV-Info-Hob-for-calc.patch create mode 100644 0036-UefiCpuPkg-Move-MigrateGdt-from-DiscoverMemory-to-Te.patch diff --git a/0027-UefiCpuPkg-Correct-some-typos.patch b/0027-UefiCpuPkg-Correct-some-typos.patch new file mode 100644 index 0000000..fe01c4a --- /dev/null +++ b/0027-UefiCpuPkg-Correct-some-typos.patch @@ -0,0 +1,119 @@ +From 92c19c68cb8f3f5313ff886c664b9286fb50632d Mon Sep 17 00:00:00 2001 +From: Guomin Jiang +Date: Tue, 7 Jul 2020 15:46:45 +0800 +Subject: [PATCH] UefiCpuPkg: Correct some typos. + +Correct some typos. + +Cc: Eric Dong +Cc: Ray Ni +Cc: Laszlo Ersek +Cc: Rahul Kumar +Signed-off-by: Guomin Jiang +Reviewed-by: Laszlo Ersek +Reviewed-by: Liming Gao +--- + UefiCpuPkg/CpuMpPei/CpuMpPei.h | 2 +- + UefiCpuPkg/CpuMpPei/CpuPaging.c | 4 ++-- + .../Library/CpuExceptionHandlerLib/CpuExceptionCommon.h | 4 ++-- + .../CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c | 4 ++-- + .../Library/CpuExceptionHandlerLib/SecPeiCpuException.c | 2 +- + .../Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c | 4 ++-- + 6 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.h b/UefiCpuPkg/CpuMpPei/CpuMpPei.h +index 309478cbe1..6a481a84dc 100644 +--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.h ++++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.h +@@ -424,7 +424,7 @@ InitializeCpuMpWorker ( + ); + + /** +- Enabl/setup stack guard for each processor if PcdCpuStackGuard is set to TRUE. ++ Enable/setup stack guard for each processor if PcdCpuStackGuard is set to TRUE. + + Doing this in the memory-discovered callback is to make sure the Stack Guard + feature to cover as most PEI code as possible. +diff --git a/UefiCpuPkg/CpuMpPei/CpuPaging.c b/UefiCpuPkg/CpuMpPei/CpuPaging.c +index 8ab7dfcce3..50ad4277af 100644 +--- a/UefiCpuPkg/CpuMpPei/CpuPaging.c ++++ b/UefiCpuPkg/CpuMpPei/CpuPaging.c +@@ -153,7 +153,7 @@ GetPhysicalAddressWidth ( + Get the type of top level page table. + + @retval Page512G PML4 paging. +- @retval Page1G PAE paing. ++ @retval Page1G PAE paging. + + **/ + PAGE_ATTRIBUTE +@@ -583,7 +583,7 @@ SetupStackGuardPage ( + } + + /** +- Enabl/setup stack guard for each processor if PcdCpuStackGuard is set to TRUE. ++ Enable/setup stack guard for each processor if PcdCpuStackGuard is set to TRUE. + + Doing this in the memory-discovered callback is to make sure the Stack Guard + feature to cover as most PEI code as possible. +diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +index 805dd9cbb4..0544d6dba6 100644 +--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h ++++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h +@@ -90,8 +90,8 @@ AsmGetTemplateAddressMap ( + **/ + VOID + ArchUpdateIdtEntry ( +- IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry, +- IN UINTN InterruptHandler ++ OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry, ++ IN UINTN InterruptHandler + ); + + /** +diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +index 1aafb7dac1..903449e0da 100644 +--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c ++++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c +@@ -18,8 +18,8 @@ + **/ + VOID + ArchUpdateIdtEntry ( +- IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry, +- IN UINTN InterruptHandler ++ OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry, ++ IN UINTN InterruptHandler + ) + { + IdtEntry->Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler; +diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c +index 20148db74c..d4ae153c57 100644 +--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c ++++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c +@@ -87,7 +87,7 @@ InitializeCpuExceptionHandlers ( + IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR); + if (IdtEntryCount > CPU_EXCEPTION_NUM) { + // +- // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most ++ // CPU exception library only setup CPU_EXCEPTION_NUM exception handler at most + // + IdtEntryCount = CPU_EXCEPTION_NUM; + } +diff --git a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +index 894c1cfb75..d3da16e4df 100644 +--- a/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c ++++ b/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c +@@ -17,8 +17,8 @@ + **/ + VOID + ArchUpdateIdtEntry ( +- IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry, +- IN UINTN InterruptHandler ++ OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry, ++ IN UINTN InterruptHandler + ) + { + IdtEntry->Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler; +-- +2.27.0 + diff --git a/0028-UefiCpuPkg-SecMigrationPei-Add-initial-PEIM-CVE-2019.patch b/0028-UefiCpuPkg-SecMigrationPei-Add-initial-PEIM-CVE-2019.patch new file mode 100644 index 0000000..7f6c1ac --- /dev/null +++ b/0028-UefiCpuPkg-SecMigrationPei-Add-initial-PEIM-CVE-2019.patch @@ -0,0 +1,857 @@ +From 479613bd06546e30652354d5dd76ee7b377fb92c Mon Sep 17 00:00:00 2001 +From: Michael Kubacki +Date: Sun, 21 Apr 2019 14:21:55 -0700 +Subject: [PATCH] UefiCpuPkg/SecMigrationPei: Add initial PEIM (CVE-2019-11098) + +REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614 + +Adds a PEIM that republishes structures produced in SEC. This +is done because SEC modules may not be shadowed in some platforms +due to space constraints or special alignment requirements. The +SecMigrationPei module locates interfaces that may be published in +SEC and reinstalls the interface with permanent memory addresses. + +This is important if pre-memory address access is forbidden after +memory initialization and data such as a PPI descriptor, PPI GUID, +or PPI inteface reside in pre-memory. + +Cc: Eric Dong +Cc: Ray Ni +Cc: Laszlo Ersek +Cc: Rahul Kumar +Cc: Debkumar De +Cc: Harry Han +Cc: Catharine West +Signed-off-by: Michael Kubacki +Acked-by: Laszlo Ersek +Reviewed-by: Liming Gao +--- + UefiCpuPkg/Include/Ppi/RepublishSecPpi.h | 54 +++ + UefiCpuPkg/SecCore/SecCore.inf | 2 + + UefiCpuPkg/SecCore/SecMain.c | 26 +- + UefiCpuPkg/SecCore/SecMain.h | 1 + + UefiCpuPkg/SecMigrationPei/SecMigrationPei.c | 385 ++++++++++++++++++ + UefiCpuPkg/SecMigrationPei/SecMigrationPei.h | 158 +++++++ + .../SecMigrationPei/SecMigrationPei.inf | 68 ++++ + .../SecMigrationPei/SecMigrationPei.uni | 13 + + UefiCpuPkg/UefiCpuPkg.dec | 3 + + UefiCpuPkg/UefiCpuPkg.dsc | 1 + + 10 files changed, 709 insertions(+), 2 deletions(-) + create mode 100644 UefiCpuPkg/Include/Ppi/RepublishSecPpi.h + create mode 100644 UefiCpuPkg/SecMigrationPei/SecMigrationPei.c + create mode 100644 UefiCpuPkg/SecMigrationPei/SecMigrationPei.h + create mode 100644 UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf + create mode 100644 UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni + +diff --git a/UefiCpuPkg/Include/Ppi/RepublishSecPpi.h b/UefiCpuPkg/Include/Ppi/RepublishSecPpi.h +new file mode 100644 +index 0000000000..ea865acbb5 +--- /dev/null ++++ b/UefiCpuPkg/Include/Ppi/RepublishSecPpi.h +@@ -0,0 +1,54 @@ ++/** @file ++ This file declares Sec Platform Information PPI. ++ ++ This service is the primary handoff state into the PEI Foundation. ++ The Security (SEC) component creates the early, transitory memory ++ environment and also encapsulates knowledge of at least the ++ location of the Boot Firmware Volume (BFV). ++ ++ Copyright (c) 2020, Intel Corporation. All rights reserved.
++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++ @par Revision Reference: ++ This PPI is introduced in PI Version 1.0. ++ ++**/ ++ ++#ifndef __REPUBLISH_SEC_PPI_H__ ++#define __REPUBLISH_SEC_PPI_H__ ++ ++#include ++ ++#define REPUBLISH_SEC_PPI_PPI_GUID \ ++ { \ ++ 0x27a71b1e, 0x73ee, 0x43d6, { 0xac, 0xe3, 0x52, 0x1a, 0x2d, 0xc5, 0xd0, 0x92 } \ ++ } ++ ++typedef struct _REPUBLISH_SEC_PPI_PPI REPUBLISH_SEC_PPI_PPI; ++ ++/** ++ This interface re-installs PPIs installed in SecCore from a post-memory PEIM. ++ ++ This is to allow a platform that may not support relocation of SecCore to update the PPI instance to a post-memory ++ copy from a PEIM that has been shadowed to permanent memory. ++ ++ @retval EFI_SUCCESS The SecCore PPIs were re-installed successfully. ++ @retval Others An error occurred re-installing the SecCore PPIs. ++ ++**/ ++typedef ++EFI_STATUS ++(EFIAPI *REPUBLISH_SEC_PPI_REPUBLISH_SEC_PPIS)( ++ VOID ++ ); ++ ++/// ++/// Republish SEC PPIs ++/// ++struct _REPUBLISH_SEC_PPI_PPI { ++ REPUBLISH_SEC_PPI_REPUBLISH_SEC_PPIS RepublishSecPpis; ++}; ++ ++extern EFI_GUID gRepublishSecPpiPpiGuid; ++ ++#endif +diff --git a/UefiCpuPkg/SecCore/SecCore.inf b/UefiCpuPkg/SecCore/SecCore.inf +index 0562820c95..545781d6b4 100644 +--- a/UefiCpuPkg/SecCore/SecCore.inf ++++ b/UefiCpuPkg/SecCore/SecCore.inf +@@ -68,6 +68,8 @@ + ## SOMETIMES_CONSUMES + gPeiSecPerformancePpiGuid + gEfiPeiCoreFvLocationPpiGuid ++ ## CONSUMES ++ gRepublishSecPpiPpiGuid + + [Guids] + ## SOMETIMES_PRODUCES ## HOB +diff --git a/UefiCpuPkg/SecCore/SecMain.c b/UefiCpuPkg/SecCore/SecMain.c +index 5d5e7f17dc..155be49a60 100644 +--- a/UefiCpuPkg/SecCore/SecMain.c ++++ b/UefiCpuPkg/SecCore/SecMain.c +@@ -370,13 +370,35 @@ SecTemporaryRamDone ( + VOID + ) + { +- BOOLEAN State; ++ EFI_STATUS Status; ++ EFI_STATUS Status2; ++ UINTN Index; ++ BOOLEAN State; ++ EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor; ++ REPUBLISH_SEC_PPI_PPI *RepublishSecPpiPpi; + + // + // Republish Sec Platform Information(2) PPI + // + RepublishSecPlatformInformationPpi (); + ++ // ++ // Re-install SEC PPIs using a PEIM produced service if published ++ // ++ for (Index = 0, Status = EFI_SUCCESS; Status == EFI_SUCCESS; Index++) { ++ Status = PeiServicesLocatePpi ( ++ &gRepublishSecPpiPpiGuid, ++ Index, ++ &PeiPpiDescriptor, ++ (VOID **) &RepublishSecPpiPpi ++ ); ++ if (!EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_INFO, "Calling RepublishSecPpi instance %d.\n", Index)); ++ Status2 = RepublishSecPpiPpi->RepublishSecPpis (); ++ ASSERT_EFI_ERROR (Status2); ++ } ++ } ++ + // + // Migrate DebugAgentContext. + // +@@ -385,7 +407,7 @@ SecTemporaryRamDone ( + // + // Disable interrupts and save current interrupt state + // +- State = SaveAndDisableInterrupts(); ++ State = SaveAndDisableInterrupts (); + + // + // Disable Temporary RAM after Stack and Heap have been migrated at this point. +diff --git a/UefiCpuPkg/SecCore/SecMain.h b/UefiCpuPkg/SecCore/SecMain.h +index e8c05d7136..e20bcf8653 100644 +--- a/UefiCpuPkg/SecCore/SecMain.h ++++ b/UefiCpuPkg/SecCore/SecMain.h +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #include + +diff --git a/UefiCpuPkg/SecMigrationPei/SecMigrationPei.c b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.c +new file mode 100644 +index 0000000000..4813a06f13 +--- /dev/null ++++ b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.c +@@ -0,0 +1,385 @@ ++/** @file ++ Migrates SEC structures after permanent memory is installed. ++ ++ Copyright (c) 2020, Intel Corporation. All rights reserved.
++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "SecMigrationPei.h" ++ ++STATIC REPUBLISH_SEC_PPI_PPI mEdkiiRepublishSecPpiPpi = { ++ RepublishSecPpis ++ }; ++ ++GLOBAL_REMOVE_IF_UNREFERENCED EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPostMemoryPpi = { ++ SecPlatformInformationPostMemory ++ }; ++ ++ ++GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_TEMPORARY_RAM_DONE_PPI mSecTemporaryRamDonePostMemoryPpi = { ++ SecTemporaryRamDonePostMemory ++ }; ++ ++GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPostMemoryPpi = { ++ SecTemporaryRamSupportPostMemory ++ }; ++ ++GLOBAL_REMOVE_IF_UNREFERENCED PEI_SEC_PERFORMANCE_PPI mSecPerformancePpi = { ++ GetPerformancePostMemory ++ }; ++ ++STATIC EFI_PEI_PPI_DESCRIPTOR mEdkiiRepublishSecPpiDescriptor = { ++ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), ++ &gRepublishSecPpiPpiGuid, ++ &mEdkiiRepublishSecPpiPpi ++ }; ++ ++GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR mSecPlatformInformationPostMemoryDescriptor = { ++ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), ++ &gEfiSecPlatformInformationPpiGuid, ++ &mSecPlatformInformationPostMemoryPpi ++ }; ++ ++GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR mSecTemporaryRamDonePostMemoryDescriptor = { ++ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), ++ &gEfiTemporaryRamDonePpiGuid, ++ &mSecTemporaryRamDonePostMemoryPpi ++ }; ++ ++GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR mSecTemporaryRamSupportPostMemoryDescriptor = { ++ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), ++ &gEfiTemporaryRamSupportPpiGuid, ++ &mSecTemporaryRamSupportPostMemoryPpi ++ }; ++ ++GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR mSecPerformancePpiDescriptor = { ++ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), ++ &gPeiSecPerformancePpiGuid, ++ &mSecPerformancePpi ++ }; ++ ++/** ++ Disables the use of Temporary RAM. ++ ++ If present, this service is invoked by the PEI Foundation after ++ the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed. ++ ++ @retval EFI_SUCCESS Dummy function, alway return this value. ++ ++**/ ++EFI_STATUS ++EFIAPI ++SecTemporaryRamDonePostMemory ( ++ VOID ++ ) ++{ ++ // ++ // Temporary RAM Done is already done in post-memory ++ // install a stub function that is located in permanent memory ++ // ++ return EFI_SUCCESS; ++} ++ ++/** ++ This service of the EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into ++ permanent memory. ++ ++ @param PeiServices Pointer to the PEI Services Table. ++ @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the ++ Temporary RAM contents. ++ @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the ++ Temporary RAM contents. ++ @param CopySize Amount of memory to migrate from temporary to permanent memory. ++ ++ @retval EFI_SUCCESS The data was successfully returned. ++ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when ++ TemporaryMemoryBase > PermanentMemoryBase. ++ ++**/ ++EFI_STATUS ++EFIAPI ++SecTemporaryRamSupportPostMemory ( ++ IN CONST EFI_PEI_SERVICES **PeiServices, ++ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, ++ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, ++ IN UINTN CopySize ++ ) ++{ ++ // ++ // Temporary RAM Support is already done in post-memory ++ // install a stub function that is located in permanent memory ++ // ++ return EFI_SUCCESS; ++} ++ ++/** ++ This interface conveys performance information out of the Security (SEC) phase into PEI. ++ ++ This service is published by the SEC phase. The SEC phase handoff has an optional ++ EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the ++ PEI Foundation. As such, if the platform supports collecting performance data in SEC, ++ this information is encapsulated into the data structure abstracted by this service. ++ This information is collected for the boot-strap processor (BSP) on IA-32. ++ ++ @param[in] PeiServices The pointer to the PEI Services Table. ++ @param[in] This The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI. ++ @param[out] Performance The pointer to performance data collected in SEC phase. ++ ++ @retval EFI_SUCCESS The performance data was successfully returned. ++ @retval EFI_INVALID_PARAMETER The This or Performance is NULL. ++ @retval EFI_NOT_FOUND Can't found the HOB created by the SecMigrationPei component. ++ ++**/ ++EFI_STATUS ++EFIAPI ++GetPerformancePostMemory ( ++ IN CONST EFI_PEI_SERVICES **PeiServices, ++ IN PEI_SEC_PERFORMANCE_PPI *This, ++ OUT FIRMWARE_SEC_PERFORMANCE *Performance ++ ) ++{ ++ SEC_PLATFORM_INFORMATION_CONTEXT_HOB *SecPlatformInformationContexHob; ++ ++ if (This == NULL || Performance == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ SecPlatformInformationContexHob = GetFirstGuidHob (&gEfiCallerIdGuid); ++ if (SecPlatformInformationContexHob == NULL) { ++ return EFI_NOT_FOUND; ++ } ++ ++ Performance->ResetEnd = SecPlatformInformationContexHob->FirmwareSecPerformance.ResetEnd; ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ This interface conveys state information out of the Security (SEC) phase into PEI. ++ ++ @param[in] PeiServices Pointer to the PEI Services Table. ++ @param[in,out] StructureSize Pointer to the variable describing size of the input buffer. ++ @param[out] PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD. ++ ++ @retval EFI_SUCCESS The data was successfully returned. ++ @retval EFI_NOT_FOUND Can't found the HOB created by SecMigrationPei component. ++ @retval EFI_BUFFER_TOO_SMALL The size of buffer pointed by StructureSize is too small and will return ++ the minimal required size in the buffer pointed by StructureSize. ++ @retval EFI_INVALID_PARAMETER The StructureSize is NULL or PlatformInformationRecord is NULL. ++ ++**/ ++EFI_STATUS ++EFIAPI ++SecPlatformInformationPostMemory ( ++ IN CONST EFI_PEI_SERVICES **PeiServices, ++ IN OUT UINT64 *StructureSize, ++ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord ++ ) ++{ ++ SEC_PLATFORM_INFORMATION_CONTEXT_HOB *SecPlatformInformationContexHob; ++ ++ if (StructureSize == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ SecPlatformInformationContexHob = GetFirstGuidHob (&gEfiCallerIdGuid); ++ if (SecPlatformInformationContexHob == NULL) { ++ return EFI_NOT_FOUND; ++ } ++ ++ if (*StructureSize < SecPlatformInformationContexHob->Context.StructureSize) { ++ *StructureSize = SecPlatformInformationContexHob->Context.StructureSize; ++ return EFI_BUFFER_TOO_SMALL; ++ } ++ ++ if (PlatformInformationRecord == NULL) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ *StructureSize = SecPlatformInformationContexHob->Context.StructureSize; ++ CopyMem ( ++ (VOID *) PlatformInformationRecord, ++ (VOID *) SecPlatformInformationContexHob->Context.PlatformInformationRecord, ++ (UINTN) SecPlatformInformationContexHob->Context.StructureSize ++ ); ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ This interface re-installs PPIs installed in SecCore from a post-memory PEIM. ++ ++ This is to allow a platform that may not support relocation of SecCore to update the PPI instance to a post-memory ++ copy from a PEIM that has been shadowed to permanent memory. ++ ++ @retval EFI_SUCCESS The SecCore PPIs were re-installed successfully. ++ @retval Others An error occurred re-installing the SecCore PPIs. ++ ++**/ ++EFI_STATUS ++EFIAPI ++RepublishSecPpis ( ++ VOID ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor; ++ VOID *PeiPpi; ++ SEC_PLATFORM_INFORMATION_CONTEXT_HOB *SecPlatformInformationContextHob; ++ EFI_SEC_PLATFORM_INFORMATION_RECORD *SecPlatformInformationPtr; ++ UINT64 SecStructureSize; ++ ++ SecPlatformInformationPtr = NULL; ++ SecStructureSize = 0; ++ ++ Status = PeiServicesLocatePpi ( ++ &gEfiTemporaryRamDonePpiGuid, ++ 0, ++ &PeiPpiDescriptor, ++ (VOID **) &PeiPpi ++ ); ++ if (!EFI_ERROR (Status)) { ++ Status = PeiServicesReInstallPpi ( ++ PeiPpiDescriptor, ++ &mSecTemporaryRamDonePostMemoryDescriptor ++ ); ++ ASSERT_EFI_ERROR (Status); ++ } ++ ++ Status = PeiServicesLocatePpi ( ++ &gEfiTemporaryRamSupportPpiGuid, ++ 0, ++ &PeiPpiDescriptor, ++ (VOID **) &PeiPpi ++ ); ++ if (!EFI_ERROR (Status)) { ++ Status = PeiServicesReInstallPpi ( ++ PeiPpiDescriptor, ++ &mSecTemporaryRamSupportPostMemoryDescriptor ++ ); ++ ASSERT_EFI_ERROR (Status); ++ } ++ ++ Status = PeiServicesCreateHob ( ++ EFI_HOB_TYPE_GUID_EXTENSION, ++ sizeof (SEC_PLATFORM_INFORMATION_CONTEXT_HOB), ++ (VOID **) &SecPlatformInformationContextHob ++ ); ++ ASSERT_EFI_ERROR (Status); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_ERROR, "SecPlatformInformation Context HOB could not be created.\n")); ++ return Status; ++ } ++ ++ SecPlatformInformationContextHob->Header.Name = gEfiCallerIdGuid; ++ SecPlatformInformationContextHob->Revision = 1; ++ ++ Status = PeiServicesLocatePpi ( ++ &gPeiSecPerformancePpiGuid, ++ 0, ++ &PeiPpiDescriptor, ++ (VOID **) &PeiPpi ++ ); ++ if (!EFI_ERROR (Status)) { ++ Status = ((PEI_SEC_PERFORMANCE_PPI *) PeiPpi)->GetPerformance ( ++ GetPeiServicesTablePointer (), ++ (PEI_SEC_PERFORMANCE_PPI *) PeiPpi, ++ &SecPlatformInformationContextHob->FirmwareSecPerformance ++ ); ++ ASSERT_EFI_ERROR (Status); ++ if (!EFI_ERROR (Status)) { ++ Status = PeiServicesReInstallPpi ( ++ PeiPpiDescriptor, ++ &mSecPerformancePpiDescriptor ++ ); ++ ASSERT_EFI_ERROR (Status); ++ } ++ } ++ ++ Status = PeiServicesLocatePpi ( ++ &gEfiSecPlatformInformationPpiGuid, ++ 0, ++ &PeiPpiDescriptor, ++ (VOID **) &PeiPpi ++ ); ++ if (!EFI_ERROR (Status)) { ++ Status = ((EFI_SEC_PLATFORM_INFORMATION_PPI *) PeiPpi)->PlatformInformation ( ++ GetPeiServicesTablePointer (), ++ &SecStructureSize, ++ SecPlatformInformationPtr ++ ); ++ ASSERT (Status == EFI_BUFFER_TOO_SMALL); ++ if (Status != EFI_BUFFER_TOO_SMALL) { ++ return EFI_NOT_FOUND; ++ } ++ ++ ZeroMem ((VOID *) &(SecPlatformInformationContextHob->Context), sizeof (SEC_PLATFORM_INFORMATION_CONTEXT)); ++ SecPlatformInformationContextHob->Context.PlatformInformationRecord = AllocatePool ((UINTN) SecStructureSize); ++ ASSERT (SecPlatformInformationContextHob->Context.PlatformInformationRecord != NULL); ++ if (SecPlatformInformationContextHob->Context.PlatformInformationRecord == NULL) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ SecPlatformInformationContextHob->Context.StructureSize = SecStructureSize; ++ ++ Status = ((EFI_SEC_PLATFORM_INFORMATION_PPI *) PeiPpi)->PlatformInformation ( ++ GetPeiServicesTablePointer (), ++ &(SecPlatformInformationContextHob->Context.StructureSize), ++ SecPlatformInformationContextHob->Context.PlatformInformationRecord ++ ); ++ ASSERT_EFI_ERROR (Status); ++ if (!EFI_ERROR (Status)) { ++ Status = PeiServicesReInstallPpi ( ++ PeiPpiDescriptor, ++ &mSecPlatformInformationPostMemoryDescriptor ++ ); ++ ASSERT_EFI_ERROR (Status); ++ } ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ This function is the entry point which installs an instance of REPUBLISH_SEC_PPI_PPI. ++ ++ It install the RepublishSecPpi depent on PcdMigrateTemporaryRamFirmwareVolumes, install ++ the PPI when the PcdMigrateTemporaryRamFirmwareVolumes enabled. ++ ++ @param[in] FileHandle Pointer to image file handle. ++ @param[in] PeiServices Pointer to PEI Services Table ++ ++ @retval EFI_ABORTED Disable evacuate temporary memory feature by disable ++ PcdMigrateTemporaryRamFirmwareVolumes. ++ @retval EFI_SUCCESS An instance of REPUBLISH_SEC_PPI_PPI was installed successfully. ++ @retval Others An error occurred installing and instance of REPUBLISH_SEC_PPI_PPI. ++ ++**/ ++EFI_STATUS ++EFIAPI ++SecMigrationPeiInitialize ( ++ IN EFI_PEI_FILE_HANDLE FileHandle, ++ IN CONST EFI_PEI_SERVICES **PeiServices ++ ) ++{ ++ EFI_STATUS Status; ++ ++ Status = EFI_ABORTED; ++ ++ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) { ++ Status = PeiServicesInstallPpi (&mEdkiiRepublishSecPpiDescriptor); ++ ASSERT_EFI_ERROR (Status); ++ } ++ ++ return Status; ++} +diff --git a/UefiCpuPkg/SecMigrationPei/SecMigrationPei.h b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.h +new file mode 100644 +index 0000000000..2d28490d9e +--- /dev/null ++++ b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.h +@@ -0,0 +1,158 @@ ++/** @file ++ Migrates SEC structures after permanent memory is installed. ++ ++ Copyright (c) 2020, Intel Corporation. All rights reserved.
++ SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#ifndef __SEC_MIGRATION_H__ ++#define __SEC_MIGRATION_H__ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/** ++ This interface conveys state information out of the Security (SEC) phase into PEI. ++ ++ @param[in] PeiServices Pointer to the PEI Services Table. ++ @param[in,out] StructureSize Pointer to the variable describing size of the input buffer. ++ @param[out] PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD. ++ ++ @retval EFI_SUCCESS The data was successfully returned. ++ @retval EFI_NOT_FOUND Can't found the HOB created by SecMigrationPei component. ++ @retval EFI_BUFFER_TOO_SMALL The size of buffer pointed by StructureSize is too small and will return ++ the minimal required size in the buffer pointed by StructureSize. ++ @retval EFI_INVALID_PARAMETER The StructureSize is NULL or PlatformInformationRecord is NULL. ++ ++**/ ++EFI_STATUS ++EFIAPI ++SecPlatformInformationPostMemory ( ++ IN CONST EFI_PEI_SERVICES **PeiServices, ++ IN OUT UINT64 *StructureSize, ++ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord ++ ); ++ ++/** ++ Re-installs the SEC Platform Information PPIs to implementation in this module to support post-memory. ++ ++ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. ++ @param[in] NotifyDescriptor Address of the notification descriptor data structure. ++ @param[in] Ppi Address of the PPI that was installed. ++ ++ @retval EFI_SUCCESS The SEC Platform Information PPI could not be re-installed. ++ @return Others An error occurred during PPI re-install. ++ ++**/ ++EFI_STATUS ++EFIAPI ++SecPlatformInformationPpiNotifyCallback ( ++ IN EFI_PEI_SERVICES **PeiServices, ++ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, ++ IN VOID *Ppi ++ ); ++ ++/** ++ This interface re-installs PPIs installed in SecCore from a post-memory PEIM. ++ ++ This is to allow a platform that may not support relocation of SecCore to update the PPI instance to a post-memory ++ copy from a PEIM that has been shadowed to permanent memory. ++ ++ @retval EFI_SUCCESS The SecCore PPIs were re-installed successfully. ++ @retval Others An error occurred re-installing the SecCore PPIs. ++ ++**/ ++EFI_STATUS ++EFIAPI ++RepublishSecPpis ( ++ VOID ++ ); ++ ++/** ++ Disables the use of Temporary RAM. ++ ++ If present, this service is invoked by the PEI Foundation after ++ the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed. ++ ++ @retval EFI_SUCCESS Dummy function, alway return this value. ++ ++**/ ++EFI_STATUS ++EFIAPI ++SecTemporaryRamDonePostMemory ( ++ VOID ++ ); ++ ++/** ++ This service of the EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into ++ permanent memory. ++ ++ @param PeiServices Pointer to the PEI Services Table. ++ @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the ++ Temporary RAM contents. ++ @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the ++ Temporary RAM contents. ++ @param CopySize Amount of memory to migrate from temporary to permanent memory. ++ ++ @retval EFI_SUCCESS The data was successfully returned. ++ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when ++ TemporaryMemoryBase > PermanentMemoryBase. ++ ++**/ ++EFI_STATUS ++EFIAPI ++SecTemporaryRamSupportPostMemory ( ++ IN CONST EFI_PEI_SERVICES **PeiServices, ++ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, ++ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, ++ IN UINTN CopySize ++ ); ++ ++/** ++ This interface conveys performance information out of the Security (SEC) phase into PEI. ++ ++ This service is published by the SEC phase. The SEC phase handoff has an optional ++ EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the ++ PEI Foundation. As such, if the platform supports collecting performance data in SEC, ++ this information is encapsulated into the data structure abstracted by this service. ++ This information is collected for the boot-strap processor (BSP) on IA-32. ++ ++ @param[in] PeiServices The pointer to the PEI Services Table. ++ @param[in] This The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI. ++ @param[out] Performance The pointer to performance data collected in SEC phase. ++ ++ @retval EFI_SUCCESS The performance data was successfully returned. ++ @retval EFI_INVALID_PARAMETER The This or Performance is NULL. ++ @retval EFI_NOT_FOUND Can't found the HOB created by the SecMigrationPei component. ++ ++**/ ++EFI_STATUS ++EFIAPI ++GetPerformancePostMemory ( ++ IN CONST EFI_PEI_SERVICES **PeiServices, ++ IN PEI_SEC_PERFORMANCE_PPI *This, ++ OUT FIRMWARE_SEC_PERFORMANCE *Performance ++ ); ++ ++typedef struct { ++ UINT64 StructureSize; ++ EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord; ++} SEC_PLATFORM_INFORMATION_CONTEXT; ++ ++typedef struct { ++ EFI_HOB_GUID_TYPE Header; ++ UINT8 Revision; ++ UINT8 Reserved[3]; ++ FIRMWARE_SEC_PERFORMANCE FirmwareSecPerformance; ++ SEC_PLATFORM_INFORMATION_CONTEXT Context; ++} SEC_PLATFORM_INFORMATION_CONTEXT_HOB; ++ ++#endif +diff --git a/UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf +new file mode 100644 +index 0000000000..384d6a96f6 +--- /dev/null ++++ b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf +@@ -0,0 +1,68 @@ ++## @file ++# Migrates SEC structures after permanent memory is installed. ++# ++# Copyright (c) 2019, Intel Corporation. All rights reserved.
++# SPDX-License-Identifier: BSD-2-Clause-Patent ++# ++## ++ ++[Defines] ++ INF_VERSION = 0x00010005 ++ BASE_NAME = SecMigrationPei ++ MODULE_UNI_FILE = SecMigrationPei.uni ++ FILE_GUID = 58B35361-8922-41BC-B313-EF7ED9ADFDF7 ++ MODULE_TYPE = PEIM ++ VERSION_STRING = 1.0 ++ ENTRY_POINT = SecMigrationPeiInitialize ++ ++# ++# The following information is for reference only and not required by the build tools. ++# ++# VALID_ARCHITECTURES = IA32 X64 EBC ++# ++ ++[Sources] ++ SecMigrationPei.c ++ SecMigrationPei.h ++ ++[Packages] ++ MdePkg/MdePkg.dec ++ MdeModulePkg/MdeModulePkg.dec ++ UefiCpuPkg/UefiCpuPkg.dec ++ ++[LibraryClasses] ++ BaseLib ++ BaseMemoryLib ++ DebugLib ++ HobLib ++ MemoryAllocationLib ++ PeimEntryPoint ++ PeiServicesLib ++ PeiServicesTablePointerLib ++ ++[Ppis] ++ ## PRODUCES ++ gRepublishSecPpiPpiGuid ++ ++ ## SOMETIMES_PRODUCES ++ gEfiTemporaryRamDonePpiGuid ++ ++ ## SOMETIME_PRODUCES ++ gEfiTemporaryRamSupportPpiGuid ++ ++ ## SOMETIMES_PRODUCES ++ gPeiSecPerformancePpiGuid ++ ++ ## SOMETIMES_CONSUMES ++ ## PRODUCES ++ gEfiSecPlatformInformationPpiGuid ++ ++ ## SOMETIMES_CONSUMES ++ ## SOMETIMES_PRODUCES ++ gEfiSecPlatformInformation2PpiGuid ++ ++[Pcd] ++ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES ++ ++[Depex] ++ TRUE +diff --git a/UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni +new file mode 100644 +index 0000000000..62c2064ba2 +--- /dev/null ++++ b/UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni +@@ -0,0 +1,13 @@ ++// /** @file ++// Migrates SEC structures after permanent memory is installed. ++// ++// Copyright (c) 2019, Intel Corporation. All rights reserved.
++// SPDX-License-Identifier: BSD-2-Clause-Patent ++// ++// **/ ++ ++ ++#string STR_MODULE_ABSTRACT #language en-US "Migrates SEC structures after permanent memory is installed" ++ ++#string STR_MODULE_DESCRIPTION #language en-US "Migrates SEC structures after permanent memory is installed." ++ +diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec +index 762badf5d2..8b2e03d49d 100644 +--- a/UefiCpuPkg/UefiCpuPkg.dec ++++ b/UefiCpuPkg/UefiCpuPkg.dec +@@ -84,6 +84,9 @@ + ## Include/Ppi/ShadowMicrocode.h + gEdkiiPeiShadowMicrocodePpiGuid = { 0x430f6965, 0x9a69, 0x41c5, { 0x93, 0xed, 0x8b, 0xf0, 0x64, 0x35, 0xc1, 0xc6 }} + ++ ## Include/Ppi/RepublishSecPpi.h ++ gRepublishSecPpiPpiGuid = { 0x27a71b1e, 0x73ee, 0x43d6, { 0xac, 0xe3, 0x52, 0x1a, 0x2d, 0xc5, 0xd0, 0x92 }} ++ + [PcdsFeatureFlag] + ## Indicates if SMM Profile will be enabled. + # If enabled, instruction executions in and data accesses to memory outside of SMRAM will be logged. +diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc +index afa3041282..964720048d 100644 +--- a/UefiCpuPkg/UefiCpuPkg.dsc ++++ b/UefiCpuPkg/UefiCpuPkg.dsc +@@ -146,6 +146,7 @@ + UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf + UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf + UefiCpuPkg/SecCore/SecCore.inf ++ UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf + UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf + UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf { + +-- +2.27.0 + diff --git a/0029-MdeModulePkg-PeiCore-Enable-T-RAM-evacuation-in-PeiC.patch b/0029-MdeModulePkg-PeiCore-Enable-T-RAM-evacuation-in-PeiC.patch new file mode 100644 index 0000000..e087020 --- /dev/null +++ b/0029-MdeModulePkg-PeiCore-Enable-T-RAM-evacuation-in-PeiC.patch @@ -0,0 +1,1339 @@ +From 9bedaec05b7b8ba9aee248361bb61a85a26726cb Mon Sep 17 00:00:00 2001 +From: Michael Kubacki +Date: Fri, 12 Apr 2019 06:46:02 +0800 +Subject: [PATCH] MdeModulePkg/PeiCore: Enable T-RAM evacuation in PeiCore + (CVE-2019-11098) + +REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614 + +Introduces new changes to PeiCore to move the contents of temporary +RAM visible to the PeiCore to permanent memory. This expands on +pre-existing shadowing support in the PeiCore to perform the following +additional actions: + + 1. Migrate pointers in PPIs installed in PeiCore to the permanent + memory copy of PeiCore. + + 2. Copy all installed firmware volumes to permanent memory. + + 3. Relocate and fix up the PEIMs within the firmware volumes. + + 4. Convert all PPIs into the migrated firmware volume to the corresponding + PPI address in the permanent memory location. + + This applies to PPIs and PEI notifications. + + 5. Convert all status code callbacks in the migrated firmware volume to + the corresponding address in the permanent memory location. + + 6. Update the FV HOB to the corresponding firmware volume in permanent + memory. + + 7. Use PcdMigrateTemporaryRamFirmwareVolumes to control if enable the + feature or not. when disable the PCD, the EvacuateTempRam() will + never be called. + +The function control flow as below: + PeiCore() + DumpPpiList() + EvacuateTempRam() + ConvertPeiCorePpiPointers() + ConvertPpiPointersFv() + MigratePeimsInFv() + MigratePeim() + PeiGetPe32Data() + LoadAndRelocatePeCoffImageInPlace() + MigrateSecModulesInFv() + ConvertPpiPointersFv() + ConvertStatusCodeCallbacks() + ConvertFvHob() + RemoveFvHobsInTemporaryMemory() + DumpPpiList() + +Cc: Jian J Wang +Cc: Hao A Wu +Cc: Dandan Bi +Cc: Liming Gao +Cc: Debkumar De +Cc: Harry Han +Cc: Catharine West +Signed-off-by: Michael Kubacki +Reviewed-by: Liming Gao +Acked-by: Laszlo Ersek +--- + MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 417 +++++++++++++++++- + MdeModulePkg/Core/Pei/Image/Image.c | 130 +++++- + MdeModulePkg/Core/Pei/Memory/MemoryServices.c | 82 ++++ + MdeModulePkg/Core/Pei/PeiMain.h | 169 +++++++ + MdeModulePkg/Core/Pei/PeiMain.inf | 2 + + MdeModulePkg/Core/Pei/PeiMain/PeiMain.c | 22 +- + MdeModulePkg/Core/Pei/Ppi/Ppi.c | 286 ++++++++++++ + 7 files changed, 1099 insertions(+), 9 deletions(-) + +diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c +index 4c2eac1384..5bc0f8674d 100644 +--- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c ++++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c +@@ -952,6 +952,409 @@ PeiCheckAndSwitchStack ( + } + } + ++/** ++ Migrate a PEIM from temporary RAM to permanent memory. ++ ++ @param PeimFileHandle Pointer to the FFS file header of the image. ++ @param MigratedFileHandle Pointer to the FFS file header of the migrated image. ++ ++ @retval EFI_SUCCESS Sucessfully migrated the PEIM to permanent memory. ++ ++**/ ++EFI_STATUS ++EFIAPI ++MigratePeim ( ++ IN EFI_PEI_FILE_HANDLE FileHandle, ++ IN EFI_PEI_FILE_HANDLE MigratedFileHandle ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_FFS_FILE_HEADER *FileHeader; ++ VOID *Pe32Data; ++ VOID *ImageAddress; ++ CHAR8 *AsciiString; ++ UINTN Index; ++ ++ Status = EFI_SUCCESS; ++ ++ FileHeader = (EFI_FFS_FILE_HEADER *) FileHandle; ++ ASSERT (!IS_FFS_FILE2 (FileHeader)); ++ ++ ImageAddress = NULL; ++ PeiGetPe32Data (MigratedFileHandle, &ImageAddress); ++ if (ImageAddress != NULL) { ++ DEBUG_CODE_BEGIN (); ++ AsciiString = PeCoffLoaderGetPdbPointer (ImageAddress); ++ for (Index = 0; AsciiString[Index] != 0; Index++) { ++ if (AsciiString[Index] == '\\' || AsciiString[Index] == '/') { ++ AsciiString = AsciiString + Index + 1; ++ Index = 0; ++ } else if (AsciiString[Index] == '.') { ++ AsciiString[Index] = 0; ++ } ++ } ++ DEBUG ((DEBUG_INFO, "%a", AsciiString)); ++ DEBUG_CODE_END (); ++ ++ Pe32Data = (VOID *) ((UINTN) ImageAddress - (UINTN) MigratedFileHandle + (UINTN) FileHandle); ++ Status = LoadAndRelocatePeCoffImageInPlace (Pe32Data, ImageAddress); ++ ASSERT_EFI_ERROR (Status); ++ } ++ ++ return Status; ++} ++ ++/** ++ Migrate Status Code Callback function pointers inside an FV from temporary memory to permanent memory. ++ ++ @param OrgFvHandle Address of FV handle in temporary memory. ++ @param FvHandle Address of FV handle in permanent memory. ++ @param FvSize Size of the FV. ++ ++**/ ++VOID ++ConvertStatusCodeCallbacks ( ++ IN UINTN OrgFvHandle, ++ IN UINTN FvHandle, ++ IN UINTN FvSize ++ ) ++{ ++ EFI_PEI_HOB_POINTERS Hob; ++ UINTN *NumberOfEntries; ++ UINTN *CallbackEntry; ++ UINTN Index; ++ ++ Hob.Raw = GetFirstGuidHob (&gStatusCodeCallbackGuid); ++ while (Hob.Raw != NULL) { ++ NumberOfEntries = GET_GUID_HOB_DATA (Hob); ++ CallbackEntry = NumberOfEntries + 1; ++ for (Index = 0; Index < *NumberOfEntries; Index++) { ++ if (((VOID *) CallbackEntry[Index]) != NULL) { ++ if ((CallbackEntry[Index] >= OrgFvHandle) && (CallbackEntry[Index] < (OrgFvHandle + FvSize))) { ++ DEBUG (( ++ DEBUG_INFO, ++ "Migrating CallbackEntry[%Lu] from 0x%0*Lx to ", ++ (UINT64)Index, ++ (sizeof CallbackEntry[Index]) * 2, ++ (UINT64)CallbackEntry[Index] ++ )); ++ if (OrgFvHandle > FvHandle) { ++ CallbackEntry[Index] = CallbackEntry[Index] - (OrgFvHandle - FvHandle); ++ } else { ++ CallbackEntry[Index] = CallbackEntry[Index] + (FvHandle - OrgFvHandle); ++ } ++ DEBUG (( ++ DEBUG_INFO, ++ "0x%0*Lx\n", ++ (sizeof CallbackEntry[Index]) * 2, ++ (UINT64)CallbackEntry[Index] ++ )); ++ } ++ } ++ } ++ Hob.Raw = GET_NEXT_HOB (Hob); ++ Hob.Raw = GetNextGuidHob (&gStatusCodeCallbackGuid, Hob.Raw); ++ } ++} ++ ++/** ++ Migrates SEC modules in the given firmware volume. ++ ++ Migrating SECURITY_CORE files requires special treatment since they are not tracked for PEI dispatch. ++ ++ This functioun should be called after the FV has been copied to its post-memory location and the PEI Core FV list has ++ been updated. ++ ++ @param Private Pointer to the PeiCore's private data structure. ++ @param FvIndex The firmware volume index to migrate. ++ @param OrgFvHandle The handle to the firmware volume in temporary memory. ++ ++ @retval EFI_SUCCESS SEC modules were migrated successfully ++ @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid. ++ @retval EFI_NOT_FOUND Can't find valid FFS header. ++ ++**/ ++EFI_STATUS ++EFIAPI ++MigrateSecModulesInFv ( ++ IN PEI_CORE_INSTANCE *Private, ++ IN UINTN FvIndex, ++ IN UINTN OrgFvHandle ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_STATUS FindFileStatus; ++ EFI_PEI_FILE_HANDLE MigratedFileHandle; ++ EFI_PEI_FILE_HANDLE FileHandle; ++ UINT32 SectionAuthenticationStatus; ++ UINT32 FileSize; ++ VOID *OrgPe32SectionData; ++ VOID *Pe32SectionData; ++ EFI_FFS_FILE_HEADER *FfsFileHeader; ++ EFI_COMMON_SECTION_HEADER *Section; ++ BOOLEAN IsFfs3Fv; ++ UINTN SectionInstance; ++ ++ if (Private == NULL || FvIndex >= Private->FvCount) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ do { ++ FindFileStatus = PeiFfsFindNextFile ( ++ GetPeiServicesTablePointer (), ++ EFI_FV_FILETYPE_SECURITY_CORE, ++ Private->Fv[FvIndex].FvHandle, ++ &MigratedFileHandle ++ ); ++ if (!EFI_ERROR (FindFileStatus ) && MigratedFileHandle != NULL) { ++ FileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) MigratedFileHandle - (UINTN) Private->Fv[FvIndex].FvHandle + OrgFvHandle); ++ FfsFileHeader = (EFI_FFS_FILE_HEADER *) MigratedFileHandle; ++ ++ DEBUG ((DEBUG_VERBOSE, " Migrating SEC_CORE MigratedFileHandle at 0x%x.\n", (UINTN) MigratedFileHandle)); ++ DEBUG ((DEBUG_VERBOSE, " FileHandle at 0x%x.\n", (UINTN) FileHandle)); ++ ++ IsFfs3Fv = CompareGuid (&Private->Fv[FvIndex].FvHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid); ++ if (IS_FFS_FILE2 (FfsFileHeader)) { ++ ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF); ++ if (!IsFfs3Fv) { ++ DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name)); ++ return EFI_NOT_FOUND; ++ } ++ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2)); ++ FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2); ++ } else { ++ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER)); ++ FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER); ++ } ++ ++ SectionInstance = 1; ++ SectionAuthenticationStatus = 0; ++ Status = ProcessSection ( ++ GetPeiServicesTablePointer (), ++ EFI_SECTION_PE32, ++ &SectionInstance, ++ Section, ++ FileSize, ++ &Pe32SectionData, ++ &SectionAuthenticationStatus, ++ IsFfs3Fv ++ ); ++ ++ if (!EFI_ERROR (Status)) { ++ OrgPe32SectionData = (VOID *) ((UINTN) Pe32SectionData - (UINTN) MigratedFileHandle + (UINTN) FileHandle); ++ DEBUG ((DEBUG_VERBOSE, " PE32 section in migrated file at 0x%x.\n", (UINTN) Pe32SectionData)); ++ DEBUG ((DEBUG_VERBOSE, " PE32 section in original file at 0x%x.\n", (UINTN) OrgPe32SectionData)); ++ Status = LoadAndRelocatePeCoffImageInPlace (OrgPe32SectionData, Pe32SectionData); ++ ASSERT_EFI_ERROR (Status); ++ } ++ } ++ } while (!EFI_ERROR (FindFileStatus)); ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ Migrates PEIMs in the given firmware volume. ++ ++ @param Private Pointer to the PeiCore's private data structure. ++ @param FvIndex The firmware volume index to migrate. ++ @param OrgFvHandle The handle to the firmware volume in temporary memory. ++ @param FvHandle The handle to the firmware volume in permanent memory. ++ ++ @retval EFI_SUCCESS The PEIMs in the FV were migrated successfully ++ @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid. ++ ++**/ ++EFI_STATUS ++EFIAPI ++MigratePeimsInFv ( ++ IN PEI_CORE_INSTANCE *Private, ++ IN UINTN FvIndex, ++ IN UINTN OrgFvHandle, ++ IN UINTN FvHandle ++ ) ++{ ++ EFI_STATUS Status; ++ volatile UINTN FileIndex; ++ EFI_PEI_FILE_HANDLE MigratedFileHandle; ++ EFI_PEI_FILE_HANDLE FileHandle; ++ ++ if (Private == NULL || FvIndex >= Private->FvCount) { ++ return EFI_INVALID_PARAMETER; ++ } ++ ++ if (Private->Fv[FvIndex].ScanFv) { ++ for (FileIndex = 0; FileIndex < Private->Fv[FvIndex].PeimCount; FileIndex++) { ++ if (Private->Fv[FvIndex].FvFileHandles[FileIndex] != NULL) { ++ FileHandle = Private->Fv[FvIndex].FvFileHandles[FileIndex]; ++ ++ MigratedFileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) FileHandle - OrgFvHandle + FvHandle); ++ ++ DEBUG ((DEBUG_VERBOSE, " Migrating FileHandle %2d ", FileIndex)); ++ Status = MigratePeim (FileHandle, MigratedFileHandle); ++ DEBUG ((DEBUG_VERBOSE, "\n")); ++ ASSERT_EFI_ERROR (Status); ++ ++ if (!EFI_ERROR (Status)) { ++ Private->Fv[FvIndex].FvFileHandles[FileIndex] = MigratedFileHandle; ++ if (FvIndex == Private->CurrentPeimFvCount) { ++ Private->CurrentFvFileHandles[FileIndex] = MigratedFileHandle; ++ } ++ } ++ } ++ } ++ } ++ ++ return EFI_SUCCESS; ++} ++ ++/** ++ Migrate FVs out of temporary RAM before the cache is flushed. ++ ++ @param Private PeiCore's private data structure ++ @param SecCoreData Points to a data structure containing information about the PEI core's operating ++ environment, such as the size and location of temporary RAM, the stack location and ++ the BFV location. ++ ++ @retval EFI_SUCCESS Succesfully migrated installed FVs from temporary RAM to permanent memory. ++ @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages. ++ ++**/ ++EFI_STATUS ++EFIAPI ++EvacuateTempRam ( ++ IN PEI_CORE_INSTANCE *Private, ++ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData ++ ) ++{ ++ EFI_STATUS Status; ++ volatile UINTN FvIndex; ++ volatile UINTN FvChildIndex; ++ UINTN ChildFvOffset; ++ EFI_FIRMWARE_VOLUME_HEADER *FvHeader; ++ EFI_FIRMWARE_VOLUME_HEADER *ChildFvHeader; ++ EFI_FIRMWARE_VOLUME_HEADER *MigratedFvHeader; ++ EFI_FIRMWARE_VOLUME_HEADER *MigratedChildFvHeader; ++ ++ PEI_CORE_FV_HANDLE PeiCoreFvHandle; ++ EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi; ++ ++ ASSERT (Private->PeiMemoryInstalled); ++ ++ DEBUG ((DEBUG_VERBOSE, "Beginning evacuation of content in temporary RAM.\n")); ++ ++ // ++ // Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded PEI_CORE in permanent memory. ++ // ++ Status = PeiLocatePpi ((CONST EFI_PEI_SERVICES **) &Private->Ps, &gEfiPeiCoreFvLocationPpiGuid, 0, NULL, (VOID **) &PeiCoreFvLocationPpi); ++ if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) { ++ PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) PeiCoreFvLocationPpi->PeiCoreFvLocation; ++ } else { ++ PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) SecCoreData->BootFirmwareVolumeBase; ++ } ++ for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) { ++ if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) { ++ PeiCoreFvHandle = Private->Fv[FvIndex]; ++ break; ++ } ++ } ++ Status = EFI_SUCCESS; ++ ++ ConvertPeiCorePpiPointers (Private, PeiCoreFvHandle); ++ ++ for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) { ++ FvHeader = Private->Fv[FvIndex].FvHeader; ++ ASSERT (FvHeader != NULL); ++ ASSERT (FvIndex < Private->FvCount); ++ ++ DEBUG ((DEBUG_VERBOSE, "FV[%02d] at 0x%x.\n", FvIndex, (UINTN) FvHeader)); ++ if ( ++ !( ++ ((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader >= Private->PhysicalMemoryBegin) && ++ (((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader + (FvHeader->FvLength - 1)) < Private->FreePhysicalMemoryTop) ++ ) ++ ) { ++ Status = PeiServicesAllocatePages ( ++ EfiBootServicesCode, ++ EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength), ++ (EFI_PHYSICAL_ADDRESS *) &MigratedFvHeader ++ ); ++ ASSERT_EFI_ERROR (Status); ++ ++ DEBUG (( ++ DEBUG_VERBOSE, ++ " Migrating FV[%d] from 0x%08X to 0x%08X\n", ++ FvIndex, ++ (UINTN) FvHeader, ++ (UINTN) MigratedFvHeader ++ )); ++ ++ CopyMem (MigratedFvHeader, FvHeader, (UINTN) FvHeader->FvLength); ++ ++ // ++ // Migrate any children for this FV now ++ // ++ for (FvChildIndex = FvIndex; FvChildIndex < Private->FvCount; FvChildIndex++) { ++ ChildFvHeader = Private->Fv[FvChildIndex].FvHeader; ++ if ( ++ ((UINTN) ChildFvHeader > (UINTN) FvHeader) && ++ (((UINTN) ChildFvHeader + ChildFvHeader->FvLength) < ((UINTN) FvHeader) + FvHeader->FvLength) ++ ) { ++ DEBUG ((DEBUG_VERBOSE, " Child FV[%02d] is being migrated.\n", FvChildIndex)); ++ ChildFvOffset = (UINTN) ChildFvHeader - (UINTN) FvHeader; ++ DEBUG ((DEBUG_VERBOSE, " Child FV offset = 0x%x.\n", ChildFvOffset)); ++ MigratedChildFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) MigratedFvHeader + ChildFvOffset); ++ Private->Fv[FvChildIndex].FvHeader = MigratedChildFvHeader; ++ Private->Fv[FvChildIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedChildFvHeader; ++ DEBUG ((DEBUG_VERBOSE, " Child migrated FV header at 0x%x.\n", (UINTN) MigratedChildFvHeader)); ++ ++ Status = MigratePeimsInFv (Private, FvChildIndex, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader); ++ ASSERT_EFI_ERROR (Status); ++ ++ ConvertPpiPointersFv ( ++ Private, ++ (UINTN) ChildFvHeader, ++ (UINTN) MigratedChildFvHeader, ++ (UINTN) ChildFvHeader->FvLength - 1 ++ ); ++ ++ ConvertStatusCodeCallbacks ( ++ (UINTN) ChildFvHeader, ++ (UINTN) MigratedChildFvHeader, ++ (UINTN) ChildFvHeader->FvLength - 1 ++ ); ++ ++ ConvertFvHob (Private, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader); ++ } ++ } ++ Private->Fv[FvIndex].FvHeader = MigratedFvHeader; ++ Private->Fv[FvIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedFvHeader; ++ ++ Status = MigratePeimsInFv (Private, FvIndex, (UINTN) FvHeader, (UINTN) MigratedFvHeader); ++ ASSERT_EFI_ERROR (Status); ++ ++ ConvertPpiPointersFv ( ++ Private, ++ (UINTN) FvHeader, ++ (UINTN) MigratedFvHeader, ++ (UINTN) FvHeader->FvLength - 1 ++ ); ++ ++ ConvertStatusCodeCallbacks ( ++ (UINTN) FvHeader, ++ (UINTN) MigratedFvHeader, ++ (UINTN) FvHeader->FvLength - 1 ++ ); ++ ++ ConvertFvHob (Private, (UINTN) FvHeader, (UINTN) MigratedFvHeader); ++ } ++ } ++ ++ RemoveFvHobsInTemporaryMemory (Private); ++ ++ return Status; ++} ++ + /** + Conduct PEIM dispatch. + +@@ -988,7 +1391,11 @@ PeiDispatcher ( + PeimFileHandle = NULL; + EntryPoint = 0; + +- if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) { ++ if ((Private->PeiMemoryInstalled) && ++ (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || ++ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) || ++ PcdGetBool (PcdShadowPeimOnS3Boot)) ++ ) { + // + // Once real memory is available, shadow the RegisterForShadow modules. And meanwhile + // update the modules' status from PEIM_STATE_REGISTER_FOR_SHADOW to PEIM_STATE_DONE. +@@ -1187,13 +1594,17 @@ PeiDispatcher ( + PeiCheckAndSwitchStack (SecCoreData, Private); + + if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW) && \ +- (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) { ++ (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || ++ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) || ++ PcdGetBool (PcdShadowPeimOnS3Boot)) ++ ) { + // + // If memory is available we shadow images by default for performance reasons. + // We call the entry point a 2nd time so the module knows it's shadowed. + // + //PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0); +- if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot)) { ++ if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot) && ++ !PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) { + // + // Load PEIM into Memory for Register for shadow PEIM. + // +diff --git a/MdeModulePkg/Core/Pei/Image/Image.c b/MdeModulePkg/Core/Pei/Image/Image.c +index e3ee369933..1d15774527 100644 +--- a/MdeModulePkg/Core/Pei/Image/Image.c ++++ b/MdeModulePkg/Core/Pei/Image/Image.c +@@ -328,8 +328,11 @@ LoadAndRelocatePeCoffImage ( + // + // When Image has no reloc section, it can't be relocated into memory. + // +- if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && ((!IsPeiModule) || +- (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))) { ++ if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && ++ ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || ++ (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || ++ (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot))) ++ ) { + DEBUG ((EFI_D_INFO|EFI_D_LOAD, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data)); + } + +@@ -343,8 +346,11 @@ LoadAndRelocatePeCoffImage ( + // On normal boot, PcdShadowPeimOnBoot decides whether load PEIM or PeiCore into memory. + // On S3 boot, PcdShadowPeimOnS3Boot decides whether load PEIM or PeiCore into memory. + // +- if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && ((!IsPeiModule) || +- (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))) { ++ if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && ++ ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || ++ (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || ++ (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot))) ++ ) { + // + // Allocate more buffer to avoid buffer overflow. + // +@@ -444,6 +450,122 @@ LoadAndRelocatePeCoffImage ( + return ReturnStatus; + } + ++/** ++ Loads and relocates a PE/COFF image in place. ++ ++ @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated ++ @param ImageAddress The base address of the relocated PE/COFF image ++ ++ @retval EFI_SUCCESS The file was loaded and relocated. ++ @retval Others The file not be loaded and error occurred. ++ ++**/ ++EFI_STATUS ++LoadAndRelocatePeCoffImageInPlace ( ++ IN VOID *Pe32Data, ++ IN VOID *ImageAddress ++ ) ++{ ++ EFI_STATUS Status; ++ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; ++ ++ ZeroMem (&ImageContext, sizeof (ImageContext)); ++ ImageContext.Handle = Pe32Data; ++ ImageContext.ImageRead = PeiImageRead; ++ ++ Status = PeCoffLoaderGetImageInfo (&ImageContext); ++ if (EFI_ERROR (Status)) { ++ ASSERT_EFI_ERROR (Status); ++ return Status; ++ } ++ ++ ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN) ImageAddress; ++ ++ // ++ // Load the image in place ++ // ++ Status = PeCoffLoaderLoadImage (&ImageContext); ++ if (EFI_ERROR (Status)) { ++ ASSERT_EFI_ERROR (Status); ++ return Status; ++ } ++ ++ // ++ // Relocate the image in place ++ // ++ Status = PeCoffLoaderRelocateImage (&ImageContext); ++ if (EFI_ERROR (Status)) { ++ ASSERT_EFI_ERROR (Status); ++ return Status; ++ } ++ ++ // ++ // Flush the instruction cache so the image data is written before we execute it ++ // ++ if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data) { ++ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); ++ } ++ ++ return Status; ++} ++ ++/** ++ Find the PE32 Data for an FFS file. ++ ++ @param FileHandle Pointer to the FFS file header of the image. ++ @param Pe32Data Pointer to a (VOID *) PE32 Data pointer. ++ ++ @retval EFI_SUCCESS Image is successfully loaded. ++ @retval EFI_NOT_FOUND Fail to locate PE32 Data. ++ ++**/ ++EFI_STATUS ++PeiGetPe32Data ( ++ IN EFI_PEI_FILE_HANDLE FileHandle, ++ OUT VOID **Pe32Data ++ ) ++{ ++ EFI_STATUS Status; ++ EFI_SECTION_TYPE SearchType1; ++ EFI_SECTION_TYPE SearchType2; ++ UINT32 AuthenticationState; ++ ++ *Pe32Data = NULL; ++ ++ if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) { ++ SearchType1 = EFI_SECTION_TE; ++ SearchType2 = EFI_SECTION_PE32; ++ } else { ++ SearchType1 = EFI_SECTION_PE32; ++ SearchType2 = EFI_SECTION_TE; ++ } ++ ++ // ++ // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst ++ // is true, TE will be searched first). ++ // ++ Status = PeiServicesFfsFindSectionData3 ( ++ SearchType1, ++ 0, ++ FileHandle, ++ Pe32Data, ++ &AuthenticationState ++ ); ++ // ++ // If we didn't find a first exe section, try to find the second exe section. ++ // ++ if (EFI_ERROR (Status)) { ++ Status = PeiServicesFfsFindSectionData3 ( ++ SearchType2, ++ 0, ++ FileHandle, ++ Pe32Data, ++ &AuthenticationState ++ ); ++ } ++ return Status; ++} ++ + /** + Loads a PEIM into memory for subsequent execution. If there are compressed + images or images that need to be relocated into memory for performance reasons, +diff --git a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c +index 6b3a64a811..9d933f0393 100644 +--- a/MdeModulePkg/Core/Pei/Memory/MemoryServices.c ++++ b/MdeModulePkg/Core/Pei/Memory/MemoryServices.c +@@ -166,6 +166,88 @@ MigrateMemoryPages ( + Private->FreePhysicalMemoryTop = NewMemPagesBase; + } + ++/** ++ Removes any FV HOBs whose base address is not in PEI installed memory. ++ ++ @param[in] Private Pointer to PeiCore's private data structure. ++ ++**/ ++VOID ++RemoveFvHobsInTemporaryMemory ( ++ IN PEI_CORE_INSTANCE *Private ++ ) ++{ ++ EFI_PEI_HOB_POINTERS Hob; ++ EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob; ++ ++ DEBUG ((DEBUG_INFO, "Removing FVs in FV HOB not already migrated to permanent memory.\n")); ++ ++ for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { ++ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV || GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2 || GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) { ++ FirmwareVolumeHob = Hob.FirmwareVolume; ++ DEBUG ((DEBUG_INFO, " Found FV HOB.\n")); ++ DEBUG (( ++ DEBUG_INFO, ++ " BA=%016lx L=%016lx\n", ++ FirmwareVolumeHob->BaseAddress, ++ FirmwareVolumeHob->Length ++ )); ++ if ( ++ !( ++ ((EFI_PHYSICAL_ADDRESS) (UINTN) FirmwareVolumeHob->BaseAddress >= Private->PhysicalMemoryBegin) && ++ (((EFI_PHYSICAL_ADDRESS) (UINTN) FirmwareVolumeHob->BaseAddress + (FirmwareVolumeHob->Length - 1)) < Private->FreePhysicalMemoryTop) ++ ) ++ ) { ++ DEBUG ((DEBUG_INFO, " Removing FV HOB to an FV in T-RAM (was not migrated).\n")); ++ Hob.Header->HobType = EFI_HOB_TYPE_UNUSED; ++ } ++ } ++ } ++} ++ ++/** ++ Migrate the base address in firmware volume allocation HOBs ++ from temporary memory to PEI installed memory. ++ ++ @param[in] PrivateData Pointer to PeiCore's private data structure. ++ @param[in] OrgFvHandle Address of FV Handle in temporary memory. ++ @param[in] FvHandle Address of FV Handle in permanent memory. ++ ++**/ ++VOID ++ConvertFvHob ( ++ IN PEI_CORE_INSTANCE *PrivateData, ++ IN UINTN OrgFvHandle, ++ IN UINTN FvHandle ++ ) ++{ ++ EFI_PEI_HOB_POINTERS Hob; ++ EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob; ++ EFI_HOB_FIRMWARE_VOLUME2 *FirmwareVolume2Hob; ++ EFI_HOB_FIRMWARE_VOLUME3 *FirmwareVolume3Hob; ++ ++ DEBUG ((DEBUG_INFO, "Converting FVs in FV HOB.\n")); ++ ++ for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { ++ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) { ++ FirmwareVolumeHob = Hob.FirmwareVolume; ++ if (FirmwareVolumeHob->BaseAddress == OrgFvHandle) { ++ FirmwareVolumeHob->BaseAddress = FvHandle; ++ } ++ } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2) { ++ FirmwareVolume2Hob = Hob.FirmwareVolume2; ++ if (FirmwareVolume2Hob->BaseAddress == OrgFvHandle) { ++ FirmwareVolume2Hob->BaseAddress = FvHandle; ++ } ++ } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) { ++ FirmwareVolume3Hob = Hob.FirmwareVolume3; ++ if (FirmwareVolume3Hob->BaseAddress == OrgFvHandle) { ++ FirmwareVolume3Hob->BaseAddress = FvHandle; ++ } ++ } ++ } ++} ++ + /** + Migrate MemoryBaseAddress in memory allocation HOBs + from the temporary memory to PEI installed memory. +diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h +index 56b3bd8579..6d95a5d32c 100644 +--- a/MdeModulePkg/Core/Pei/PeiMain.h ++++ b/MdeModulePkg/Core/Pei/PeiMain.h +@@ -394,6 +394,41 @@ PeimDispatchReadiness ( + IN VOID *DependencyExpression + ); + ++/** ++ Migrate a PEIM from temporary RAM to permanent memory. ++ ++ @param PeimFileHandle Pointer to the FFS file header of the image. ++ @param MigratedFileHandle Pointer to the FFS file header of the migrated image. ++ ++ @retval EFI_SUCCESS Sucessfully migrated the PEIM to permanent memory. ++ ++**/ ++EFI_STATUS ++EFIAPI ++MigratePeim ( ++ IN EFI_PEI_FILE_HANDLE FileHandle, ++ IN EFI_PEI_FILE_HANDLE MigratedFileHandle ++ ); ++ ++/** ++ Migrate FVs out of temporary RAM before the cache is flushed. ++ ++ @param Private PeiCore's private data structure ++ @param SecCoreData Points to a data structure containing information about the PEI core's operating ++ environment, such as the size and location of temporary RAM, the stack location and ++ the BFV location. ++ ++ @retval EFI_SUCCESS Succesfully migrated installed FVs from temporary RAM to permanent memory. ++ @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages. ++ ++**/ ++EFI_STATUS ++EFIAPI ++EvacuateTempRam ( ++ IN PEI_CORE_INSTANCE *Private, ++ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData ++ ); ++ + /** + Conduct PEIM dispatch. + +@@ -477,6 +512,50 @@ ConvertPpiPointers ( + IN PEI_CORE_INSTANCE *PrivateData + ); + ++/** ++ ++ Migrate Notify Pointers inside an FV from temporary memory to permanent memory. ++ ++ @param PrivateData Pointer to PeiCore's private data structure. ++ @param OrgFvHandle Address of FV Handle in temporary memory. ++ @param FvHandle Address of FV Handle in permanent memory. ++ @param FvSize Size of the FV. ++ ++**/ ++VOID ++ConvertPpiPointersFv ( ++ IN PEI_CORE_INSTANCE *PrivateData, ++ IN UINTN OrgFvHandle, ++ IN UINTN FvHandle, ++ IN UINTN FvSize ++ ); ++ ++/** ++ ++ Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory. ++ ++ @param PrivateData Pointer to PeiCore's private data structure. ++ @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory. ++ ++**/ ++VOID ++ConvertPeiCorePpiPointers ( ++ IN PEI_CORE_INSTANCE *PrivateData, ++ PEI_CORE_FV_HANDLE CoreFvHandle ++ ); ++ ++/** ++ ++ Dumps the PPI lists to debug output. ++ ++ @param PrivateData Points to PeiCore's private instance data. ++ ++**/ ++VOID ++DumpPpiList ( ++ IN PEI_CORE_INSTANCE *PrivateData ++ ); ++ + /** + + Install PPI services. It is implementation of EFI_PEI_SERVICE.InstallPpi. +@@ -808,6 +887,37 @@ PeiFfsFindNextFile ( + IN OUT EFI_PEI_FILE_HANDLE *FileHandle + ); + ++/** ++ Go through the file to search SectionType section. ++ Search within encapsulation sections (compression and GUIDed) recursively, ++ until the match section is found. ++ ++ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. ++ @param SectionType Filter to find only section of this type. ++ @param SectionInstance Pointer to the filter to find the specific instance of section. ++ @param Section From where to search. ++ @param SectionSize The file size to search. ++ @param OutputBuffer A pointer to the discovered section, if successful. ++ NULL if section not found. ++ @param AuthenticationStatus Updated upon return to point to the authentication status for this section. ++ @param IsFfs3Fv Indicates the FV format. ++ ++ @return EFI_NOT_FOUND The match section is not found. ++ @return EFI_SUCCESS The match section is found. ++ ++**/ ++EFI_STATUS ++ProcessSection ( ++ IN CONST EFI_PEI_SERVICES **PeiServices, ++ IN EFI_SECTION_TYPE SectionType, ++ IN OUT UINTN *SectionInstance, ++ IN EFI_COMMON_SECTION_HEADER *Section, ++ IN UINTN SectionSize, ++ OUT VOID **OutputBuffer, ++ OUT UINT32 *AuthenticationStatus, ++ IN BOOLEAN IsFfs3Fv ++ ); ++ + /** + Searches for the next matching section within the specified file. + +@@ -931,6 +1041,33 @@ MigrateMemoryPages ( + IN BOOLEAN TemporaryRamMigrated + ); + ++/** ++ Removes any FV HOBs whose base address is not in PEI installed memory. ++ ++ @param[in] Private Pointer to PeiCore's private data structure. ++ ++**/ ++VOID ++RemoveFvHobsInTemporaryMemory ( ++ IN PEI_CORE_INSTANCE *Private ++ ); ++ ++/** ++ Migrate the base address in firmware volume allocation HOBs ++ from temporary memory to PEI installed memory. ++ ++ @param[in] PrivateData Pointer to PeiCore's private data structure. ++ @param[in] OrgFvHandle Address of FV Handle in temporary memory. ++ @param[in] FvHandle Address of FV Handle in permanent memory. ++ ++**/ ++VOID ++ConvertFvHob ( ++ IN PEI_CORE_INSTANCE *PrivateData, ++ IN UINTN OrgFvHandle, ++ IN UINTN FvHandle ++ ); ++ + /** + Migrate MemoryBaseAddress in memory allocation HOBs + from the temporary memory to PEI installed memory. +@@ -1249,6 +1386,38 @@ InitializeImageServices ( + IN PEI_CORE_INSTANCE *OldCoreData + ); + ++/** ++ Loads and relocates a PE/COFF image in place. ++ ++ @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated ++ @param ImageAddress The base address of the relocated PE/COFF image ++ ++ @retval EFI_SUCCESS The file was loaded and relocated ++ @retval Others The file not be loaded and error occurred. ++ ++**/ ++EFI_STATUS ++LoadAndRelocatePeCoffImageInPlace ( ++ IN VOID *Pe32Data, ++ IN VOID *ImageAddress ++ ); ++ ++/** ++ Find the PE32 Data for an FFS file. ++ ++ @param FileHandle Pointer to the FFS file header of the image. ++ @param Pe32Data Pointer to a (VOID *) PE32 Data pointer. ++ ++ @retval EFI_SUCCESS Image is successfully loaded. ++ @retval EFI_NOT_FOUND Fail to locate PE32 Data. ++ ++**/ ++EFI_STATUS ++PeiGetPe32Data ( ++ IN EFI_PEI_FILE_HANDLE FileHandle, ++ OUT VOID **Pe32Data ++ ); ++ + /** + The wrapper function of PeiLoadImageLoadImage(). + +diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf +index 6e25cc4023..5b36d516b3 100644 +--- a/MdeModulePkg/Core/Pei/PeiMain.inf ++++ b/MdeModulePkg/Core/Pei/PeiMain.inf +@@ -76,6 +76,7 @@ + ## CONSUMES ## UNDEFINED # Locate PPI + ## CONSUMES ## GUID # Used to compare with FV's file system GUID and get the FV's file system format + gEfiFirmwareFileSystem3Guid ++ gStatusCodeCallbackGuid + + [Ppis] + gEfiPeiStatusCodePpiGuid ## SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI doesn't exist +@@ -109,6 +110,7 @@ + gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnS3Boot ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack ## CONSUMES ++ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES + + # [BootMode] + # S3_RESUME ## SOMETIMES_CONSUMES +diff --git a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c +index cca57c4c06..2ad08878d9 100644 +--- a/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c ++++ b/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c +@@ -319,8 +319,9 @@ PeiCore ( + // PEI Core and PEIMs to get high performance. + // + OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER) (UINTN) PeiCore; +- if ((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot)) +- || (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) { ++ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) || ++ (HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot)) || ++ (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) { + OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData); + } + +@@ -418,6 +419,23 @@ PeiCore ( + ProcessPpiListFromSec ((CONST EFI_PEI_SERVICES **) &PrivateData.Ps, PpiList); + } + } else { ++ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) { ++ // ++ // When PcdMigrateTemporaryRamFirmwareVolumes is TRUE, alway shadow all ++ // PEIMs no matter the condition of PcdShadowPeimOnBoot and PcdShadowPeimOnS3Boot ++ // ++ DEBUG ((DEBUG_VERBOSE, "PPI lists before temporary RAM evacuation:\n")); ++ DumpPpiList (&PrivateData); ++ ++ // ++ // Migrate installed content from Temporary RAM to Permanent RAM ++ // ++ EvacuateTempRam (&PrivateData, SecCoreData); ++ ++ DEBUG ((DEBUG_VERBOSE, "PPI lists after temporary RAM evacuation:\n")); ++ DumpPpiList (&PrivateData); ++ } ++ + // + // Try to locate Temporary RAM Done Ppi. + // +diff --git a/MdeModulePkg/Core/Pei/Ppi/Ppi.c b/MdeModulePkg/Core/Pei/Ppi/Ppi.c +index 1ffe718c47..541047d98a 100644 +--- a/MdeModulePkg/Core/Pei/Ppi/Ppi.c ++++ b/MdeModulePkg/Core/Pei/Ppi/Ppi.c +@@ -198,6 +198,227 @@ ConvertPpiPointers ( + } + } + ++/** ++ ++ Migrate Notify Pointers inside an FV from temporary memory to permanent memory. ++ ++ @param PrivateData Pointer to PeiCore's private data structure. ++ @param OrgFvHandle Address of FV Handle in temporary memory. ++ @param FvHandle Address of FV Handle in permanent memory. ++ @param FvSize Size of the FV. ++ ++**/ ++VOID ++ConvertPpiPointersFv ( ++ IN PEI_CORE_INSTANCE *PrivateData, ++ IN UINTN OrgFvHandle, ++ IN UINTN FvHandle, ++ IN UINTN FvSize ++ ) ++{ ++ UINT8 Index; ++ UINTN Offset; ++ BOOLEAN OffsetPositive; ++ EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi; ++ UINT8 GuidIndex; ++ EFI_GUID *Guid; ++ EFI_GUID *GuidCheckList[2]; ++ ++ GuidCheckList[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid; ++ GuidCheckList[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid; ++ ++ if (FvHandle > OrgFvHandle) { ++ OffsetPositive = TRUE; ++ Offset = FvHandle - OrgFvHandle; ++ } else { ++ OffsetPositive = FALSE; ++ Offset = OrgFvHandle - FvHandle; ++ } ++ ++ DEBUG ((DEBUG_VERBOSE, "Converting PPI pointers in FV.\n")); ++ DEBUG (( ++ DEBUG_VERBOSE, ++ " OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n", ++ (UINTN) OrgFvHandle, ++ (UINTN) FvHandle, ++ FvSize ++ )); ++ DEBUG (( ++ DEBUG_VERBOSE, ++ " OrgFvHandle range: 0x%08x - 0x%08x\n", ++ OrgFvHandle, ++ OrgFvHandle + FvSize ++ )); ++ ++ for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) { ++ ConvertPointer ( ++ (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw, ++ OrgFvHandle, ++ OrgFvHandle + FvSize, ++ Offset, ++ OffsetPositive ++ ); ++ ConvertPointer ( ++ (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid, ++ OrgFvHandle, ++ OrgFvHandle + FvSize, ++ Offset, ++ OffsetPositive ++ ); ++ ConvertPointer ( ++ (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Notify, ++ OrgFvHandle, ++ OrgFvHandle + FvSize, ++ Offset, ++ OffsetPositive ++ ); ++ } ++ ++ for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) { ++ ConvertPointer ( ++ (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw, ++ OrgFvHandle, ++ OrgFvHandle + FvSize, ++ Offset, ++ OffsetPositive ++ ); ++ ConvertPointer ( ++ (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid, ++ OrgFvHandle, ++ OrgFvHandle + FvSize, ++ Offset, ++ OffsetPositive ++ ); ++ ConvertPointer ( ++ (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Notify, ++ OrgFvHandle, ++ OrgFvHandle + FvSize, ++ Offset, ++ OffsetPositive ++ ); ++ } ++ ++ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { ++ ConvertPointer ( ++ (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw, ++ OrgFvHandle, ++ OrgFvHandle + FvSize, ++ Offset, ++ OffsetPositive ++ ); ++ ConvertPointer ( ++ (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid, ++ OrgFvHandle, ++ OrgFvHandle + FvSize, ++ Offset, ++ OffsetPositive ++ ); ++ ConvertPointer ( ++ (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi, ++ OrgFvHandle, ++ OrgFvHandle + FvSize, ++ Offset, ++ OffsetPositive ++ ); ++ ++ Guid = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid; ++ for (GuidIndex = 0; GuidIndex < ARRAY_SIZE (GuidCheckList); ++GuidIndex) { ++ // ++ // Don't use CompareGuid function here for performance reasons. ++ // Instead we compare the GUID as INT32 at a time and branch ++ // on the first failed comparison. ++ // ++ if ((((INT32 *)Guid)[0] == ((INT32 *)GuidCheckList[GuidIndex])[0]) && ++ (((INT32 *)Guid)[1] == ((INT32 *)GuidCheckList[GuidIndex])[1]) && ++ (((INT32 *)Guid)[2] == ((INT32 *)GuidCheckList[GuidIndex])[2]) && ++ (((INT32 *)Guid)[3] == ((INT32 *)GuidCheckList[GuidIndex])[3])) { ++ FvInfoPpi = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi; ++ DEBUG ((DEBUG_VERBOSE, " FvInfo: %p -> ", FvInfoPpi->FvInfo)); ++ if ((UINTN)FvInfoPpi->FvInfo == OrgFvHandle) { ++ ConvertPointer ( ++ (VOID **)&FvInfoPpi->FvInfo, ++ OrgFvHandle, ++ OrgFvHandle + FvSize, ++ Offset, ++ OffsetPositive ++ ); ++ DEBUG ((DEBUG_VERBOSE, "%p", FvInfoPpi->FvInfo)); ++ } ++ DEBUG ((DEBUG_VERBOSE, "\n")); ++ break; ++ } ++ } ++ } ++} ++ ++/** ++ ++ Dumps the PPI lists to debug output. ++ ++ @param PrivateData Points to PeiCore's private instance data. ++ ++**/ ++VOID ++DumpPpiList ( ++ IN PEI_CORE_INSTANCE *PrivateData ++ ) ++{ ++ DEBUG_CODE_BEGIN (); ++ UINTN Index; ++ ++ if (PrivateData == NULL) { ++ return; ++ } ++ ++ for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) { ++ DEBUG (( ++ DEBUG_VERBOSE, ++ "CallbackNotify[%2d] {%g} at 0x%x (%a)\n", ++ Index, ++ PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid, ++ (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw, ++ ( ++ !( ++ ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) && ++ (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop) ++ ) ++ ? "CAR" : "Post-Memory" ++ ) ++ )); ++ } ++ for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) { ++ DEBUG ((DEBUG_VERBOSE, ++ "DispatchNotify[%2d] {%g} at 0x%x (%a)\n", ++ Index, ++ PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid, ++ (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw, ++ ( ++ !( ++ ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw >=PrivateData->PhysicalMemoryBegin) && ++ (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop) ++ ) ++ ? "CAR" : "Post-Memory" ++ ) ++ )); ++ } ++ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) { ++ DEBUG ((DEBUG_VERBOSE, ++ "PPI[%2d] {%g} at 0x%x (%a)\n", ++ Index, ++ PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid, ++ (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw, ++ ( ++ !( ++ ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) && ++ (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw) + sizeof (EFI_PEI_PPI_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop) ++ ) ++ ? "CAR" : "Post-Memory" ++ ) ++ )); ++ } ++ DEBUG_CODE_END (); ++} ++ + /** + + This function installs an interface in the PEI PPI database by GUID. +@@ -830,3 +1051,68 @@ ProcessPpiListFromSec ( + } + } + ++/** ++ ++ Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory. ++ ++ @param PrivateData Pointer to PeiCore's private data structure. ++ @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory. ++ ++**/ ++VOID ++ConvertPeiCorePpiPointers ( ++ IN PEI_CORE_INSTANCE *PrivateData, ++ PEI_CORE_FV_HANDLE CoreFvHandle ++ ) ++{ ++ EFI_FV_FILE_INFO FileInfo; ++ EFI_PHYSICAL_ADDRESS OrgImageBase; ++ EFI_PHYSICAL_ADDRESS MigratedImageBase; ++ UINTN PeiCoreModuleSize; ++ EFI_PEI_FILE_HANDLE PeiCoreFileHandle; ++ VOID *PeiCoreImageBase; ++ VOID *PeiCoreEntryPoint; ++ EFI_STATUS Status; ++ ++ PeiCoreFileHandle = NULL; ++ ++ // ++ // Find the PEI Core in the BFV in temporary memory. ++ // ++ Status = CoreFvHandle.FvPpi->FindFileByType ( ++ CoreFvHandle.FvPpi, ++ EFI_FV_FILETYPE_PEI_CORE, ++ CoreFvHandle.FvHandle, ++ &PeiCoreFileHandle ++ ); ++ ASSERT_EFI_ERROR (Status); ++ ++ if (!EFI_ERROR (Status)) { ++ Status = CoreFvHandle.FvPpi->GetFileInfo (CoreFvHandle.FvPpi, PeiCoreFileHandle, &FileInfo); ++ ASSERT_EFI_ERROR (Status); ++ ++ Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase); ++ ASSERT_EFI_ERROR (Status); ++ ++ // ++ // Find PEI Core EntryPoint in the BFV in temporary memory. ++ // ++ Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, &PeiCoreEntryPoint); ++ ASSERT_EFI_ERROR (Status); ++ ++ OrgImageBase = (UINTN) PeiCoreImageBase; ++ MigratedImageBase = (UINTN) _ModuleEntryPoint - ((UINTN) PeiCoreEntryPoint - (UINTN) PeiCoreImageBase); ++ ++ // ++ // Size of loaded PEI_CORE in permanent memory. ++ // ++ PeiCoreModuleSize = (UINTN)FileInfo.BufferSize - ((UINTN) OrgImageBase - (UINTN) FileInfo.Buffer); ++ ++ // ++ // Migrate PEI_CORE PPI pointers from temporary memory to newly ++ // installed PEI_CORE in permanent memory. ++ // ++ ConvertPpiPointersFv (PrivateData, (UINTN) OrgImageBase, (UINTN) MigratedImageBase, PeiCoreModuleSize); ++ } ++} ++ +-- +2.27.0 + diff --git a/0030-SecurityPkg-Tcg2Pei-Use-Migrated-FV-Info-Hob-for-cal.patch b/0030-SecurityPkg-Tcg2Pei-Use-Migrated-FV-Info-Hob-for-cal.patch new file mode 100644 index 0000000..2df78a1 --- /dev/null +++ b/0030-SecurityPkg-Tcg2Pei-Use-Migrated-FV-Info-Hob-for-cal.patch @@ -0,0 +1,117 @@ +From 012809cdca4b876e675cbd181fee213133858a5e Mon Sep 17 00:00:00 2001 +From: Guomin Jiang +Date: Mon, 29 Jun 2020 14:50:21 +0800 +Subject: [PATCH] SecurityPkg/Tcg2Pei: Use Migrated FV Info Hob for calculating + hash (CVE-2019-11098) + +REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614 + +When we allocate pool to save rebased the PEIMs, the address will change +randomly, therefore the hash will change and result PCR0 change as well. +To avoid this, we save the raw PEIMs and use it to calculate hash. +The Tcg2Pei calculate the hash and it use the Migrated FV Info. + +Cc: Jiewen Yao +Cc: Jian J Wang +Cc: Chao Zhang +Cc: Qi Zhang +Cc: Rahul Kumar +Signed-off-by: Guomin Jiang +Reviewed-by: Jian J Wang +Reviewed-by: Qi Zhang +Reviewed-by: Liming Gao +--- + SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c | 31 ++++++++++++++++++++++++++--- + SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf | 1 + + 2 files changed, 29 insertions(+), 3 deletions(-) + +diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c +index 4852d86..651a60c 100644 +--- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c ++++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c +@@ -21,6 +21,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + #include + #include + #include ++#include + + #include + #include +@@ -536,6 +537,10 @@ MeasureFvImage ( + EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI *PrehashedFvPpi; + HASH_INFO *PreHashInfo; + UINT32 HashAlgoMask; ++ EFI_PHYSICAL_ADDRESS FvOrgBase; ++ EFI_PHYSICAL_ADDRESS FvDataBase; ++ EFI_PEI_HOB_POINTERS Hob; ++ EDKII_MIGRATED_FV_INFO *MigratedFvInfo; + + // + // Check Excluded FV list +@@ -621,6 +626,26 @@ MeasureFvImage ( + Instance++; + } while (!EFI_ERROR(Status)); + ++ // ++ // Search the matched migration FV info ++ // ++ FvOrgBase = FvBase; ++ FvDataBase = FvBase; ++ Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid); ++ while (Hob.Raw != NULL) { ++ MigratedFvInfo = GET_GUID_HOB_DATA (Hob); ++ if ((MigratedFvInfo->FvNewBase == (UINT32) FvBase) && (MigratedFvInfo->FvLength == (UINT32) FvLength)) { ++ // ++ // Found the migrated FV info ++ // ++ FvOrgBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvOrgBase; ++ FvDataBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvDataBase; ++ break; ++ } ++ Hob.Raw = GET_NEXT_HOB (Hob); ++ Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw); ++ } ++ + // + // Init the log event for FV measurement + // +@@ -631,13 +656,13 @@ MeasureFvImage ( + if (FvName != NULL) { + AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof(FvBlob2.BlobDescription), "Fv(%g)", FvName); + } +- FvBlob2.BlobBase = FvBase; ++ FvBlob2.BlobBase = FvOrgBase; + FvBlob2.BlobLength = FvLength; + TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2; + TcgEventHdr.EventSize = sizeof (FvBlob2); + EventData = &FvBlob2; + } else { +- FvBlob.BlobBase = FvBase; ++ FvBlob.BlobBase = FvOrgBase; + FvBlob.BlobLength = FvLength; + TcgEventHdr.PCRIndex = 0; + TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB; +@@ -672,7 +697,7 @@ MeasureFvImage ( + // + Status = HashLogExtendEvent ( + 0, +- (UINT8*) (UINTN) FvBase, // HashData ++ (UINT8*) (UINTN) FvDataBase, // HashData + (UINTN) FvLength, // HashDataLen + &TcgEventHdr, // EventHdr + EventData // EventData +diff --git a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf +index 3d361e8..367df21 100644 +--- a/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf ++++ b/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf +@@ -63,6 +63,7 @@ + gTcgEvent2EntryHobGuid ## PRODUCES ## HOB + gEfiTpmDeviceInstanceNoneGuid ## SOMETIMES_PRODUCES ## GUID # TPM device identifier + gEfiTpmDeviceInstanceTpm12Guid ## SOMETIMES_PRODUCES ## GUID # TPM device identifier ++ gEdkiiMigratedFvInfoGuid ## SOMETIMES_CONSUMES ## HOB + + [Ppis] + gEfiPeiFirmwareVolumeInfoPpiGuid ## SOMETIMES_CONSUMES ## NOTIFY +-- +2.27.0 + diff --git a/0031-MdeModulePkg-Add-new-PCD-to-control-the-evacuate-tem.patch b/0031-MdeModulePkg-Add-new-PCD-to-control-the-evacuate-tem.patch new file mode 100644 index 0000000..e75b070 --- /dev/null +++ b/0031-MdeModulePkg-Add-new-PCD-to-control-the-evacuate-tem.patch @@ -0,0 +1,74 @@ +From 1facb8fdef6389f390b66da6d8304f54cc93104a Mon Sep 17 00:00:00 2001 +From: Guomin Jiang +Date: Wed, 8 Jul 2020 09:33:46 +0800 +Subject: [PATCH] MdeModulePkg: Add new PCD to control the evacuate temporary + memory feature (CVE-2019-11098) + +REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614 + +The security researcher found that we can get control after NEM disable. + +The reason is that the flash content reside in NEM at startup and the +code will get the content from flash directly after disable NEM. + +To avoid this vulnerability, the feature will copy the PEIMs from +temporary memory to permanent memory and only execute the code in +permanent memory. + +The vulnerability is exist in physical platform and haven't report in +virtual platform, so the virtual can disable the feature currently. + +When enable the PcdMigrateTemporaryRamFirmwareVolumes, always shadow +all PEIMs no matter the condition of PcdShadowPeimOnBoot or +PcdShadowPeimOnS3Boot. + +Cc: Jian J Wang +Cc: Hao A Wu +Signed-off-by: Guomin Jiang +Reviewed-by: Liming Gao +Acked-by: Laszlo Ersek +--- + MdeModulePkg/MdeModulePkg.dec | 9 +++++++++ + MdeModulePkg/MdeModulePkg.uni | 6 ++++++ + 2 files changed, 15 insertions(+) + +diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec +index 843e963ad3..45874e9c82 100644 +--- a/MdeModulePkg/MdeModulePkg.dec ++++ b/MdeModulePkg/MdeModulePkg.dec +@@ -1220,6 +1220,15 @@ + # @Prompt Shadow Peim and PeiCore on boot + gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot|TRUE|BOOLEAN|0x30001029 + ++ ## Enable the feature that evacuate temporary memory to permanent memory or not

++ # Set FALSE as default, if the developer need this feature to avoid this vulnerability, please ++ # enable it to shadow all PEIMs no matter the behavior controled by PcdShadowPeimOnBoot or ++ # PcdShadowPeimOnS3Boot
++ # TRUE - Evacuate temporary memory, the actions include copy memory, convert PPI pointers and so on.
++ # FALSE - Do nothing, for example, no copy memory, no convert PPI pointers and so on.
++ # @Prompt Evacuate temporary memory to permanent memory ++ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes|FALSE|BOOLEAN|0x3000102A ++ + ## The mask is used to control memory profile behavior.

+ # BIT0 - Enable UEFI memory profile.
+ # BIT1 - Enable SMRAM profile.
+diff --git a/MdeModulePkg/MdeModulePkg.uni b/MdeModulePkg/MdeModulePkg.uni +index 2007e0596c..5235dee561 100644 +--- a/MdeModulePkg/MdeModulePkg.uni ++++ b/MdeModulePkg/MdeModulePkg.uni +@@ -214,6 +214,12 @@ + "TRUE - Shadow PEIM on S3 boot path after memory is ready.
\n" + "FALSE - Not shadow PEIM on S3 boot path after memory is ready.
" + ++#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdMigrateTemporaryRamFirmwareVolumes_HELP #language en-US "Enable the feature that evacuate temporary memory to permanent memory or not.

\n" ++ "It will allocate page to save the temporary PEIMs resided in NEM(or CAR) to the permanent memory and change all pointers pointed to the NEM(or CAR) to permanent memory.

\n" ++ "After then, there are no pointer pointed to NEM(or CAR) and TOCTOU volnerability can be avoid.

\n" ++ ++#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdMigrateTemporaryRamFirmwareVolumes_PROMPT #language en-US "Enable the feature that evacuate temporary memory to permanent memory or not" ++ + #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAcpiDefaultOemId_PROMPT #language en-US "Default OEM ID for ACPI table creation" + + #string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAcpiDefaultOemId_HELP #language en-US "Default OEM ID for ACPI table creation, its length must be 0x6 bytes to follow ACPI specification." +-- +2.27.0 + diff --git a/0032-MdeModulePkg-Core-Create-Migrated-FV-Info-Hob-for-ca.patch b/0032-MdeModulePkg-Core-Create-Migrated-FV-Info-Hob-for-ca.patch new file mode 100644 index 0000000..dc224c4 --- /dev/null +++ b/0032-MdeModulePkg-Core-Create-Migrated-FV-Info-Hob-for-ca.patch @@ -0,0 +1,170 @@ +From 4b68cef04c70d8fd8a9bf745fc649c84d67531e8 Mon Sep 17 00:00:00 2001 +From: Guomin Jiang +Date: Mon, 29 Jun 2020 13:52:02 +0800 +Subject: [PATCH] MdeModulePkg/Core: Create Migrated FV Info Hob for + calculating hash (CVE-2019-11098) + +REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614 + +When we allocate pool to save the rebased PEIMs, the address will change +randomly, therefore the hash will change and result PCR0 change as well. +To avoid this, we save the raw PEIMs and use it to calculate hash. + +The MigratedFvInfo HOB will never produce when +PcdMigrateTemporaryRamFirmwareVolumes is FALSE, because the PCD control +the total feature. + +Cc: Jian J Wang +Cc: Hao A Wu +Cc: Dandan Bi +Cc: Liming Gao +Cc: Debkumar De +Cc: Harry Han +Cc: Catharine West +Signed-off-by: Guomin Jiang +Acked-by: Laszlo Ersek +Reviewed-by: Jian J Wang +Reviewed-by: Liming Gao +--- + MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c | 28 +++++++++++++++++++ + MdeModulePkg/Core/Pei/PeiMain.h | 1 + + MdeModulePkg/Core/Pei/PeiMain.inf | 1 + + MdeModulePkg/Include/Guid/MigratedFvInfo.h | 22 +++++++++++++++ + MdeModulePkg/MdeModulePkg.dec | 3 ++ + 5 files changed, 55 insertions(+) + create mode 100644 MdeModulePkg/Include/Guid/MigratedFvInfo.h + +diff --git a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c +index 5bc0f8674d..b9a279ec73 100644 +--- a/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c ++++ b/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c +@@ -1234,10 +1234,12 @@ EvacuateTempRam ( + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FIRMWARE_VOLUME_HEADER *ChildFvHeader; + EFI_FIRMWARE_VOLUME_HEADER *MigratedFvHeader; ++ EFI_FIRMWARE_VOLUME_HEADER *RawDataFvHeader; + EFI_FIRMWARE_VOLUME_HEADER *MigratedChildFvHeader; + + PEI_CORE_FV_HANDLE PeiCoreFvHandle; + EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi; ++ EDKII_MIGRATED_FV_INFO MigratedFvInfo; + + ASSERT (Private->PeiMemoryInstalled); + +@@ -1274,6 +1276,9 @@ EvacuateTempRam ( + (((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader + (FvHeader->FvLength - 1)) < Private->FreePhysicalMemoryTop) + ) + ) { ++ // ++ // Allocate page to save the rebased PEIMs, the PEIMs will get dispatched later. ++ // + Status = PeiServicesAllocatePages ( + EfiBootServicesCode, + EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength), +@@ -1281,6 +1286,17 @@ EvacuateTempRam ( + ); + ASSERT_EFI_ERROR (Status); + ++ // ++ // Allocate pool to save the raw PEIMs, which is used to keep consistent context across ++ // multiple boot and PCR0 will keep the same no matter if the address of allocated page is changed. ++ // ++ Status = PeiServicesAllocatePages ( ++ EfiBootServicesCode, ++ EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength), ++ (EFI_PHYSICAL_ADDRESS *) &RawDataFvHeader ++ ); ++ ASSERT_EFI_ERROR (Status); ++ + DEBUG (( + DEBUG_VERBOSE, + " Migrating FV[%d] from 0x%08X to 0x%08X\n", +@@ -1289,7 +1305,19 @@ EvacuateTempRam ( + (UINTN) MigratedFvHeader + )); + ++ // ++ // Copy the context to the rebased pages and raw pages, and create hob to save the ++ // information. The MigratedFvInfo HOB will never be produced when ++ // PcdMigrateTemporaryRamFirmwareVolumes is FALSE, because the PCD control the ++ // feature. ++ // + CopyMem (MigratedFvHeader, FvHeader, (UINTN) FvHeader->FvLength); ++ CopyMem (RawDataFvHeader, MigratedFvHeader, (UINTN) FvHeader->FvLength); ++ MigratedFvInfo.FvOrgBase = (UINT32) (UINTN) FvHeader; ++ MigratedFvInfo.FvNewBase = (UINT32) (UINTN) MigratedFvHeader; ++ MigratedFvInfo.FvDataBase = (UINT32) (UINTN) RawDataFvHeader; ++ MigratedFvInfo.FvLength = (UINT32) (UINTN) FvHeader->FvLength; ++ BuildGuidDataHob (&gEdkiiMigratedFvInfoGuid, &MigratedFvInfo, sizeof (MigratedFvInfo)); + + // + // Migrate any children for this FV now +diff --git a/MdeModulePkg/Core/Pei/PeiMain.h b/MdeModulePkg/Core/Pei/PeiMain.h +index 6d95a5d32c..c27e8fc33b 100644 +--- a/MdeModulePkg/Core/Pei/PeiMain.h ++++ b/MdeModulePkg/Core/Pei/PeiMain.h +@@ -44,6 +44,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + #include + #include + #include ++#include + + /// + /// It is an FFS type extension used for PeiFindFileEx. It indicates current +diff --git a/MdeModulePkg/Core/Pei/PeiMain.inf b/MdeModulePkg/Core/Pei/PeiMain.inf +index 5b36d516b3..0cf357371a 100644 +--- a/MdeModulePkg/Core/Pei/PeiMain.inf ++++ b/MdeModulePkg/Core/Pei/PeiMain.inf +@@ -77,6 +77,7 @@ + ## CONSUMES ## GUID # Used to compare with FV's file system GUID and get the FV's file system format + gEfiFirmwareFileSystem3Guid + gStatusCodeCallbackGuid ++ gEdkiiMigratedFvInfoGuid ## SOMETIMES_PRODUCES ## HOB + + [Ppis] + gEfiPeiStatusCodePpiGuid ## SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI doesn't exist +diff --git a/MdeModulePkg/Include/Guid/MigratedFvInfo.h b/MdeModulePkg/Include/Guid/MigratedFvInfo.h +new file mode 100644 +index 0000000000..061c17ed0e +--- /dev/null ++++ b/MdeModulePkg/Include/Guid/MigratedFvInfo.h +@@ -0,0 +1,22 @@ ++/** @file ++ Migrated FV information ++ ++Copyright (c) 2020, Intel Corporation. All rights reserved.
++SPDX-License-Identifier: BSD-2-Clause-Patent ++ ++**/ ++ ++#ifndef __EDKII_MIGRATED_FV_INFO_GUID_H__ ++#define __EDKII_MIGRATED_FV_INFO_GUID_H__ ++ ++typedef struct { ++ UINT32 FvOrgBase; // original FV address ++ UINT32 FvNewBase; // new FV address ++ UINT32 FvDataBase; // original FV data ++ UINT32 FvLength; // Fv Length ++} EDKII_MIGRATED_FV_INFO; ++ ++extern EFI_GUID gEdkiiMigratedFvInfoGuid; ++ ++#endif // #ifndef __EDKII_MIGRATED_FV_INFO_GUID_H__ ++ +diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec +index 45874e9c82..d7572eedd1 100644 +--- a/MdeModulePkg/MdeModulePkg.dec ++++ b/MdeModulePkg/MdeModulePkg.dec +@@ -389,6 +389,9 @@ + ## GUID indicates the capsule is to store Capsule On Disk file names. + gEdkiiCapsuleOnDiskNameGuid = { 0x98c80a4f, 0xe16b, 0x4d11, { 0x93, 0x9a, 0xab, 0xe5, 0x61, 0x26, 0x3, 0x30 } } + ++ ## Include/Guid/MigratedFvInfo.h ++ gEdkiiMigratedFvInfoGuid = { 0xc1ab12f7, 0x74aa, 0x408d, { 0xa2, 0xf4, 0xc6, 0xce, 0xfd, 0x17, 0x98, 0x71 } } ++ + [Ppis] + ## Include/Ppi/AtaController.h + gPeiAtaControllerPpiGuid = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a, 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }} +-- +2.27.0 + diff --git a/0033-UefiCpuPkg-CpuMpPei-Add-GDT-migration-support-CVE-20.patch b/0033-UefiCpuPkg-CpuMpPei-Add-GDT-migration-support-CVE-20.patch new file mode 100644 index 0000000..c7dcbeb --- /dev/null +++ b/0033-UefiCpuPkg-CpuMpPei-Add-GDT-migration-support-CVE-20.patch @@ -0,0 +1,137 @@ +From 60b12e69fb1c8c7180fdda92f008248b9ec83db1 Mon Sep 17 00:00:00 2001 +From: Michael Kubacki +Date: Sun, 14 Apr 2019 11:48:07 +0800 +Subject: [PATCH] UefiCpuPkg/CpuMpPei: Add GDT migration support + (CVE-2019-11098) + +REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614 + +Moves the GDT to permanent memory in a memory discovered +callback. This is done to ensure the GDT authenticated in +pre-memory is not fetched from outside a verified location +after the permanent memory transition. + +Cc: Eric Dong +Cc: Ray Ni +Cc: Laszlo Ersek +Cc: Rahul Kumar +Signed-off-by: Michael Kubacki +Reviewed-by: Laszlo Ersek +Reviewed-by: Jian J Wang +Reviewed-by: Liming Gao +--- + UefiCpuPkg/CpuMpPei/CpuMpPei.c | 37 ++++++++++++++++++++++++++++++++ + UefiCpuPkg/CpuMpPei/CpuMpPei.h | 12 +++++++++++ + UefiCpuPkg/CpuMpPei/CpuMpPei.inf | 1 + + UefiCpuPkg/CpuMpPei/CpuPaging.c | 12 +++++++++-- + 4 files changed, 60 insertions(+), 2 deletions(-) + +diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.c b/UefiCpuPkg/CpuMpPei/CpuMpPei.c +index 07ccbe7c6a..d07540cf74 100644 +--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.c ++++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.c +@@ -429,6 +429,43 @@ GetGdtr ( + AsmReadGdtr ((IA32_DESCRIPTOR *)Buffer); + } + ++/** ++ Migrates the Global Descriptor Table (GDT) to permanent memory. ++ ++ @retval EFI_SUCCESS The GDT was migrated successfully. ++ @retval EFI_OUT_OF_RESOURCES The GDT could not be migrated due to lack of available memory. ++ ++**/ ++EFI_STATUS ++MigrateGdt ( ++ VOID ++ ) ++{ ++ EFI_STATUS Status; ++ UINTN GdtBufferSize; ++ IA32_DESCRIPTOR Gdtr; ++ VOID *GdtBuffer; ++ ++ AsmReadGdtr ((IA32_DESCRIPTOR *) &Gdtr); ++ GdtBufferSize = sizeof (IA32_SEGMENT_DESCRIPTOR) -1 + Gdtr.Limit + 1; ++ ++ Status = PeiServicesAllocatePool ( ++ GdtBufferSize, ++ &GdtBuffer ++ ); ++ ASSERT (GdtBuffer != NULL); ++ if (EFI_ERROR (Status)) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ GdtBuffer = ALIGN_POINTER (GdtBuffer, sizeof (IA32_SEGMENT_DESCRIPTOR)); ++ CopyMem (GdtBuffer, (VOID *) Gdtr.Base, Gdtr.Limit + 1); ++ Gdtr.Base = (UINTN) GdtBuffer; ++ AsmWriteGdtr (&Gdtr); ++ ++ return EFI_SUCCESS; ++} ++ + /** + Initializes CPU exceptions handlers for the sake of stack switch requirement. + +diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.h b/UefiCpuPkg/CpuMpPei/CpuMpPei.h +index 7d5c527d60..309478cbe1 100644 +--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.h ++++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.h +@@ -397,6 +397,18 @@ SecPlatformInformation2 ( + OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2 + ); + ++/** ++ Migrates the Global Descriptor Table (GDT) to permanent memory. ++ ++ @retval EFI_SUCCESS The GDT was migrated successfully. ++ @retval EFI_OUT_OF_RESOURCES The GDT could not be migrated due to lack of available memory. ++ ++**/ ++EFI_STATUS ++MigrateGdt ( ++ VOID ++ ); ++ + /** + Initializes MP and exceptions handlers. + +diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf +index caead3ce34..f4d11b861f 100644 +--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf ++++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf +@@ -63,6 +63,7 @@ + gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList ## SOMETIMES_CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownGoodStackSize ## SOMETIMES_CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## SOMETIMES_CONSUMES ++ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES + + [Depex] + TRUE +diff --git a/UefiCpuPkg/CpuMpPei/CpuPaging.c b/UefiCpuPkg/CpuMpPei/CpuPaging.c +index a462e7ee1e..3bf0574b34 100644 +--- a/UefiCpuPkg/CpuMpPei/CpuPaging.c ++++ b/UefiCpuPkg/CpuMpPei/CpuPaging.c +@@ -602,8 +602,16 @@ MemoryDiscoveredPpiNotifyCallback ( + IN VOID *Ppi + ) + { +- EFI_STATUS Status; +- BOOLEAN InitStackGuard; ++ EFI_STATUS Status; ++ BOOLEAN InitStackGuard; ++ BOOLEAN InterruptState; ++ ++ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) { ++ InterruptState = SaveAndDisableInterrupts (); ++ Status = MigrateGdt (); ++ ASSERT_EFI_ERROR (Status); ++ SetInterruptState (InterruptState); ++ } + + // + // Paging must be setup first. Otherwise the exception TSS setup during MP +-- +2.27.0 + diff --git a/0034-UefiCpuPkg-CpuMpPei-Enable-paging-and-set-NP-flag-to.patch b/0034-UefiCpuPkg-CpuMpPei-Enable-paging-and-set-NP-flag-to.patch new file mode 100644 index 0000000..5871067 --- /dev/null +++ b/0034-UefiCpuPkg-CpuMpPei-Enable-paging-and-set-NP-flag-to.patch @@ -0,0 +1,106 @@ +From d7c9de51d249ee101b4d90357a4272b36c831047 Mon Sep 17 00:00:00 2001 +From: Guomin Jiang +Date: Thu, 2 Jul 2020 13:03:34 +0800 +Subject: [PATCH] UefiCpuPkg/CpuMpPei: Enable paging and set NP flag to avoid + TOCTOU (CVE-2019-11098) + +REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614 + +To avoid the TOCTOU, enable paging and set Not Present flag so when +access any code in the flash range, it will trigger #PF exception. + +Cc: Eric Dong +Cc: Ray Ni +Cc: Laszlo Ersek +Cc: Rahul Kumar +Signed-off-by: Guomin Jiang +Acked-by: Laszlo Ersek +Reviewed-by: Jian J Wang +Reviewed-by: Liming Gao +--- + UefiCpuPkg/CpuMpPei/CpuMpPei.inf | 3 +++ + UefiCpuPkg/CpuMpPei/CpuPaging.c | 32 +++++++++++++++++++++++++++----- + 2 files changed, 30 insertions(+), 5 deletions(-) + +diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf +index f4d11b861f..7e511325d8 100644 +--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf ++++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf +@@ -46,6 +46,9 @@ + BaseMemoryLib + CpuLib + ++[Guids] ++ gEdkiiMigratedFvInfoGuid ## SOMETIMES_CONSUMES ## HOB ++ + [Ppis] + gEfiPeiMpServicesPpiGuid ## PRODUCES + gEfiSecPlatformInformationPpiGuid ## SOMETIMES_CONSUMES +diff --git a/UefiCpuPkg/CpuMpPei/CpuPaging.c b/UefiCpuPkg/CpuMpPei/CpuPaging.c +index 3bf0574b34..8ab7dfcce3 100644 +--- a/UefiCpuPkg/CpuMpPei/CpuPaging.c ++++ b/UefiCpuPkg/CpuMpPei/CpuPaging.c +@@ -12,6 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + #include + #include + #include ++#include + + #include "CpuMpPei.h" + +@@ -602,9 +603,11 @@ MemoryDiscoveredPpiNotifyCallback ( + IN VOID *Ppi + ) + { +- EFI_STATUS Status; +- BOOLEAN InitStackGuard; +- BOOLEAN InterruptState; ++ EFI_STATUS Status; ++ BOOLEAN InitStackGuard; ++ BOOLEAN InterruptState; ++ EDKII_MIGRATED_FV_INFO *MigratedFvInfo; ++ EFI_PEI_HOB_POINTERS Hob; + + if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) { + InterruptState = SaveAndDisableInterrupts (); +@@ -619,9 +622,14 @@ MemoryDiscoveredPpiNotifyCallback ( + // the task switch (for the sake of stack switch). + // + InitStackGuard = FALSE; +- if (IsIa32PaeSupported () && PcdGetBool (PcdCpuStackGuard)) { ++ Hob.Raw = NULL; ++ if (IsIa32PaeSupported ()) { ++ Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid); ++ InitStackGuard = PcdGetBool (PcdCpuStackGuard); ++ } ++ ++ if (InitStackGuard || Hob.Raw != NULL) { + EnablePaging (); +- InitStackGuard = TRUE; + } + + Status = InitializeCpuMpWorker ((CONST EFI_PEI_SERVICES **)PeiServices); +@@ -631,6 +639,20 @@ MemoryDiscoveredPpiNotifyCallback ( + SetupStackGuardPage (); + } + ++ while (Hob.Raw != NULL) { ++ MigratedFvInfo = GET_GUID_HOB_DATA (Hob); ++ ++ // ++ // Enable #PF exception, so if the code access SPI after disable NEM, it will generate ++ // the exception to avoid potential vulnerability. ++ // ++ ConvertMemoryPageAttributes (MigratedFvInfo->FvOrgBase, MigratedFvInfo->FvLength, 0); ++ ++ Hob.Raw = GET_NEXT_HOB (Hob); ++ Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw); ++ } ++ CpuFlushTlb (); ++ + return Status; + } + +-- +2.27.0 + diff --git a/0035-SecurityPkg-TcgPei-Use-Migrated-FV-Info-Hob-for-calc.patch b/0035-SecurityPkg-TcgPei-Use-Migrated-FV-Info-Hob-for-calc.patch new file mode 100644 index 0000000..161dfc7 --- /dev/null +++ b/0035-SecurityPkg-TcgPei-Use-Migrated-FV-Info-Hob-for-calc.patch @@ -0,0 +1,105 @@ +From ffde22468e2f0e93b51f97b801e6c7a181088c61 Mon Sep 17 00:00:00 2001 From: Guomin Jiang +Date: Wed, 8 Jul 2020 16:01:14 +0800 +Subject: [PATCH] SecurityPkg/TcgPei: Use Migrated FV Info Hob for calculating + hash (CVE-2019-11098) + +REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1614 + +When we allocate pool to save rebased the PEIMs, the address will change +randomly, therefore the hash will change and result PCR0 change as well. +To avoid this, we save the raw PEIMs and use it to calculate hash. +The TcgPei calculate the hash and it use the Migrated FV Info. + +Cc: Jiewen Yao +Cc: Jian J Wang +Cc: Chao Zhang +Cc: Qi Zhang +Cc: Rahul Kumar +Signed-off-by: Guomin Jiang +Reviewed-by: Jian J Wang +Reviewed-by: Qi Zhang +Reviewed-by: Liming Gao +--- + SecurityPkg/Tcg/TcgPei/TcgPei.c | 29 +++++++++++++++++++++++++++-- + SecurityPkg/Tcg/TcgPei/TcgPei.inf | 1 + + 2 files changed, 28 insertions(+), 2 deletions(-) + +diff --git a/SecurityPkg/Tcg/TcgPei/TcgPei.c b/SecurityPkg/Tcg/TcgPei/TcgPei.c +index a9a808c..9701bfe 100644 +--- a/SecurityPkg/Tcg/TcgPei/TcgPei.c ++++ b/SecurityPkg/Tcg/TcgPei/TcgPei.c +@@ -21,6 +21,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent + #include + #include + #include ++#include + + #include + #include +@@ -378,6 +379,10 @@ MeasureFvImage ( + EFI_STATUS Status; + EFI_PLATFORM_FIRMWARE_BLOB FvBlob; + TCG_PCR_EVENT_HDR TcgEventHdr; ++ EFI_PHYSICAL_ADDRESS FvOrgBase; ++ EFI_PHYSICAL_ADDRESS FvDataBase; ++ EFI_PEI_HOB_POINTERS Hob; ++ EDKII_MIGRATED_FV_INFO *MigratedFvInfo; + + // + // Check if it is in Excluded FV list +@@ -401,10 +406,30 @@ MeasureFvImage ( + } + } + ++ // ++ // Search the matched migration FV info ++ // ++ FvOrgBase = FvBase; ++ FvDataBase = FvBase; ++ Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid); ++ while (Hob.Raw != NULL) { ++ MigratedFvInfo = GET_GUID_HOB_DATA (Hob); ++ if ((MigratedFvInfo->FvNewBase == (UINT32) FvBase) && (MigratedFvInfo->FvLength == (UINT32) FvLength)) { ++ // ++ // Found the migrated FV info ++ // ++ FvOrgBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvOrgBase; ++ FvDataBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvDataBase; ++ break; ++ } ++ Hob.Raw = GET_NEXT_HOB (Hob); ++ Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw); ++ } ++ + // + // Measure and record the FV to the TPM + // +- FvBlob.BlobBase = FvBase; ++ FvBlob.BlobBase = FvOrgBase; + FvBlob.BlobLength = FvLength; + + DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob.BlobBase)); +@@ -416,7 +441,7 @@ MeasureFvImage ( + + Status = HashLogExtendEvent ( + (EFI_PEI_SERVICES **) GetPeiServicesTablePointer(), +- (UINT8*) (UINTN) FvBlob.BlobBase, ++ (UINT8*) (UINTN) FvDataBase, + (UINTN) FvBlob.BlobLength, + &TcgEventHdr, + (UINT8*) &FvBlob +diff --git a/SecurityPkg/Tcg/TcgPei/TcgPei.inf b/SecurityPkg/Tcg/TcgPei/TcgPei.inf +index c0bff6e..6d1951f 100644 +--- a/SecurityPkg/Tcg/TcgPei/TcgPei.inf ++++ b/SecurityPkg/Tcg/TcgPei/TcgPei.inf +@@ -58,6 +58,7 @@ + gTpmErrorHobGuid ## SOMETIMES_PRODUCES ## HOB + gMeasuredFvHobGuid ## PRODUCES ## HOB + gEfiTpmDeviceInstanceTpm12Guid ## PRODUCES ## GUID # TPM device identifier ++ gEdkiiMigratedFvInfoGuid ## SOMETIMES_CONSUMES ## HOB + + [Ppis] + gPeiLockPhysicalPresencePpiGuid ## SOMETIMES_CONSUMES ## NOTIFY +-- +2.27.0 + diff --git a/0036-UefiCpuPkg-Move-MigrateGdt-from-DiscoverMemory-to-Te.patch b/0036-UefiCpuPkg-Move-MigrateGdt-from-DiscoverMemory-to-Te.patch new file mode 100644 index 0000000..082e057 --- /dev/null +++ b/0036-UefiCpuPkg-Move-MigrateGdt-from-DiscoverMemory-to-Te.patch @@ -0,0 +1,191 @@ +From f6ec1dd34fb6b9757b5ead465ee2ea20c182b0ac Mon Sep 17 00:00:00 2001 +From: Guomin Jiang +Date: Wed, 13 Jan 2021 18:08:09 +0800 +Subject: [PATCH] UefiCpuPkg: Move MigrateGdt from DiscoverMemory to + TempRamDone. (CVE-2019-11098) + +REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1614 +REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3160 + +The GDT still in flash with commit 60b12e69fb1c8c7180fdda92f008248b9ec83db1 +after TempRamDone + +So move the action to TempRamDone event to avoid reading GDT from flash. + +Signed-off-by: Guomin Jiang +Cc: Eric Dong +Cc: Ray Ni +Cc: Laszlo Ersek +Cc: Rahul Kumar +Cc: Debkumar De +Cc: Harry Han +Cc: Catharine West +Reviewed-by: Ray Ni +--- + UefiCpuPkg/CpuMpPei/CpuMpPei.c | 37 -------------------------- + UefiCpuPkg/CpuMpPei/CpuMpPei.inf | 1 - + UefiCpuPkg/CpuMpPei/CpuPaging.c | 8 ------ + UefiCpuPkg/SecCore/SecCore.inf | 1 + + UefiCpuPkg/SecCore/SecMain.c | 45 ++++++++++++++++++++++++++++++++ + 5 files changed, 46 insertions(+), 46 deletions(-) + +diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.c b/UefiCpuPkg/CpuMpPei/CpuMpPei.c +index 40729a09b9..3c1bad6470 100644 +--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.c ++++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.c +@@ -429,43 +429,6 @@ GetGdtr ( + AsmReadGdtr ((IA32_DESCRIPTOR *)Buffer); + } + +-/** +- Migrates the Global Descriptor Table (GDT) to permanent memory. +- +- @retval EFI_SUCCESS The GDT was migrated successfully. +- @retval EFI_OUT_OF_RESOURCES The GDT could not be migrated due to lack of available memory. +- +-**/ +-EFI_STATUS +-MigrateGdt ( +- VOID +- ) +-{ +- EFI_STATUS Status; +- UINTN GdtBufferSize; +- IA32_DESCRIPTOR Gdtr; +- VOID *GdtBuffer; +- +- AsmReadGdtr ((IA32_DESCRIPTOR *) &Gdtr); +- GdtBufferSize = sizeof (IA32_SEGMENT_DESCRIPTOR) -1 + Gdtr.Limit + 1; +- +- Status = PeiServicesAllocatePool ( +- GdtBufferSize, +- &GdtBuffer +- ); +- ASSERT (GdtBuffer != NULL); +- if (EFI_ERROR (Status)) { +- return EFI_OUT_OF_RESOURCES; +- } +- +- GdtBuffer = ALIGN_POINTER (GdtBuffer, sizeof (IA32_SEGMENT_DESCRIPTOR)); +- CopyMem (GdtBuffer, (VOID *) Gdtr.Base, Gdtr.Limit + 1); +- Gdtr.Base = (UINTN) GdtBuffer; +- AsmWriteGdtr (&Gdtr); +- +- return EFI_SUCCESS; +-} +- + /** + Initializes CPU exceptions handlers for the sake of stack switch requirement. + +diff --git a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf +index ba829d816e..7444bdb968 100644 +--- a/UefiCpuPkg/CpuMpPei/CpuMpPei.inf ++++ b/UefiCpuPkg/CpuMpPei/CpuMpPei.inf +@@ -67,7 +67,6 @@ + gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList ## SOMETIMES_CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownGoodStackSize ## SOMETIMES_CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## SOMETIMES_CONSUMES +- gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES + + [Depex] + TRUE +diff --git a/UefiCpuPkg/CpuMpPei/CpuPaging.c b/UefiCpuPkg/CpuMpPei/CpuPaging.c +index 50ad4277af..3e261d6657 100644 +--- a/UefiCpuPkg/CpuMpPei/CpuPaging.c ++++ b/UefiCpuPkg/CpuMpPei/CpuPaging.c +@@ -605,17 +605,9 @@ MemoryDiscoveredPpiNotifyCallback ( + { + EFI_STATUS Status; + BOOLEAN InitStackGuard; +- BOOLEAN InterruptState; + EDKII_MIGRATED_FV_INFO *MigratedFvInfo; + EFI_PEI_HOB_POINTERS Hob; + +- if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) { +- InterruptState = SaveAndDisableInterrupts (); +- Status = MigrateGdt (); +- ASSERT_EFI_ERROR (Status); +- SetInterruptState (InterruptState); +- } +- + // + // Paging must be setup first. Otherwise the exception TSS setup during MP + // initialization later will not contain paging information and then fail +diff --git a/UefiCpuPkg/SecCore/SecCore.inf b/UefiCpuPkg/SecCore/SecCore.inf +index 545781d6b4..ded83beb52 100644 +--- a/UefiCpuPkg/SecCore/SecCore.inf ++++ b/UefiCpuPkg/SecCore/SecCore.inf +@@ -77,6 +77,7 @@ + + [Pcd] + gUefiCpuPkgTokenSpaceGuid.PcdPeiTemporaryRamStackSize ## CONSUMES ++ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES + + [UserExtensions.TianoCore."ExtraFiles"] + SecCoreExtra.uni +diff --git a/UefiCpuPkg/SecCore/SecMain.c b/UefiCpuPkg/SecCore/SecMain.c +index 155be49a60..2416c4ce56 100644 +--- a/UefiCpuPkg/SecCore/SecMain.c ++++ b/UefiCpuPkg/SecCore/SecMain.c +@@ -35,6 +35,43 @@ EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = { + } + }; + ++/** ++ Migrates the Global Descriptor Table (GDT) to permanent memory. ++ ++ @retval EFI_SUCCESS The GDT was migrated successfully. ++ @retval EFI_OUT_OF_RESOURCES The GDT could not be migrated due to lack of available memory. ++ ++**/ ++EFI_STATUS ++MigrateGdt ( ++ VOID ++ ) ++{ ++ EFI_STATUS Status; ++ UINTN GdtBufferSize; ++ IA32_DESCRIPTOR Gdtr; ++ VOID *GdtBuffer; ++ ++ AsmReadGdtr ((IA32_DESCRIPTOR *) &Gdtr); ++ GdtBufferSize = sizeof (IA32_SEGMENT_DESCRIPTOR) -1 + Gdtr.Limit + 1; ++ ++ Status = PeiServicesAllocatePool ( ++ GdtBufferSize, ++ &GdtBuffer ++ ); ++ ASSERT (GdtBuffer != NULL); ++ if (EFI_ERROR (Status)) { ++ return EFI_OUT_OF_RESOURCES; ++ } ++ ++ GdtBuffer = ALIGN_POINTER (GdtBuffer, sizeof (IA32_SEGMENT_DESCRIPTOR)); ++ CopyMem (GdtBuffer, (VOID *) Gdtr.Base, Gdtr.Limit + 1); ++ Gdtr.Base = (UINTN) GdtBuffer; ++ AsmWriteGdtr (&Gdtr); ++ ++ return EFI_SUCCESS; ++} ++ + // + // These are IDT entries pointing to 10:FFFFFFE4h. + // +@@ -409,6 +446,14 @@ SecTemporaryRamDone ( + // + State = SaveAndDisableInterrupts (); + ++ // ++ // Migrate GDT before NEM near down ++ // ++ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) { ++ Status = MigrateGdt (); ++ ASSERT_EFI_ERROR (Status); ++ } ++ + // + // Disable Temporary RAM after Stack and Heap have been migrated at this point. + // +-- +2.27.0 + diff --git a/edk2.spec b/edk2.spec index 70eb7c4..431a5ad 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 @@ -40,6 +40,16 @@ Patch0025: 0023-SecurityPkg-Tcg-Import-Tcg2PlatformPei-from-edk2-pla.patch Patch0026: 0024-SecurityPkg-Tcg-Make-Tcg2PlatformPei-buildable-and-f.patch Patch0027: 0025-SecurityPkg-Add-references-to-header-and-inf-files-t.patch Patch0028: 0026-CryptoPkg-BaseCryptLib-fix-NULL-dereference-CVE-2019.patch +Patch0029: 0027-UefiCpuPkg-Correct-some-typos.patch +Patch0030: 0028-UefiCpuPkg-SecMigrationPei-Add-initial-PEIM-CVE-2019.patch +Patch0031: 0029-MdeModulePkg-PeiCore-Enable-T-RAM-evacuation-in-PeiC.patch +Patch0032: 0030-SecurityPkg-Tcg2Pei-Use-Migrated-FV-Info-Hob-for-cal.patch +Patch0033: 0031-MdeModulePkg-Add-new-PCD-to-control-the-evacuate-tem.patch +Patch0034: 0032-MdeModulePkg-Core-Create-Migrated-FV-Info-Hob-for-ca.patch +Patch0035: 0033-UefiCpuPkg-CpuMpPei-Add-GDT-migration-support-CVE-20.patch +Patch0036: 0034-UefiCpuPkg-CpuMpPei-Enable-paging-and-set-NP-flag-to.patch +Patch0037: 0035-SecurityPkg-TcgPei-Use-Migrated-FV-Info-Hob-for-calc.patch +Patch0038: 0036-UefiCpuPkg-Move-MigrateGdt-from-DiscoverMemory-to-Te.patch BuildRequires: acpica-tools gcc gcc-c++ libuuid-devel python3 bc nasm python2 @@ -235,8 +245,11 @@ chmod +x %{buildroot}%{_bindir}/Rsa2048Sha256GenerateKeys %endif %changelog +* Thu Sep 29 2022 chenhuiying - 202002-10 +- fix CVE-2019-11098 + * Thu Sep 29 2022 chenhuiying - 202002-9 -* fix CVE-2019-14584 +- fix CVE-2019-14584 * Fri Jan 28 2022 Jinhua Cao - 202002-8 - fix CVE-2021-38576 -- Gitee