From 74a88770337121b046ec5f055d4ae06abc37fa60 Mon Sep 17 00:00:00 2001 From: Star Zeng Date: Wed, 20 Apr 2016 17:27:40 +0800 Subject: [PATCH] MdeModulePkg DxeCore: Enhance MemoryAttributesTable installation Current MemoryAttributesTable will be installed on ReadyToBoot event at TPL_NOTIFY level, it maybe incorrect when PcdHiiOsRuntimeSupport = TRUE as HiiDatabaseDxe will have runtime memory allocation for HII OS runtime support on and after ReadyToBoot. The issue was exposed at http://article.gmane.org/gmane.comp.bios.edk2.devel/10125. To make sure the correctness of MemoryAttributesTable, this patch is to enhance MemoryAttributesTable installation to install MemoryAttributesTable on ReadyToBoot event at TPL_CALLBACK - 1 level to make sure it is at the last of ReadyToBoot event, and also hook runtime memory allocation after ReadyToBoot. Cc: Jiewen Yao Cc: Liming Gao Cc: Feng Tian Cc: Ard Biesheuvel Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng Reviewed-by: Jiewen Yao --- MdeModulePkg/Core/Dxe/DxeMain.h | 12 +++ MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c | 3 + MdeModulePkg/Core/Dxe/Mem/Page.c | 2 + MdeModulePkg/Core/Dxe/Mem/Pool.c | 2 + .../Core/Dxe/Misc/MemoryAttributesTable.c | 88 +++++++++++++++---- 5 files changed, 92 insertions(+), 15 deletions(-) diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index edb7ff5b9f..82a3a9b4f2 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -276,6 +276,8 @@ extern EFI_RUNTIME_SERVICES *gDxeCoreRT; extern EFI_DXE_SERVICES *gDxeCoreDS; extern EFI_HANDLE gDxeCoreImageHandle; +extern BOOLEAN gMemoryMapTerminated; + extern EFI_DECOMPRESS_PROTOCOL gEfiDecompress; extern EFI_RUNTIME_ARCH_PROTOCOL *gRuntime; @@ -2858,6 +2860,16 @@ CoreInitializeMemoryAttributesTable ( VOID ); +/** + Install MemoryAttributesTable on memory allocation. + + @param[in] MemoryType EFI memory type. +**/ +VOID +InstallMemoryAttributesTableOnMemoryAllocation ( + IN EFI_MEMORY_TYPE MemoryType + ); + /** Insert image record. diff --git a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c index a458d6b64f..70a283bc2b 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c +++ b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c @@ -207,6 +207,7 @@ EFI_SYSTEM_TABLE *gDxeCoreST = NULL; EFI_RUNTIME_SERVICES *gDxeCoreRT = &mEfiRuntimeServicesTableTemplate; EFI_HANDLE gDxeCoreImageHandle = NULL; +BOOLEAN gMemoryMapTerminated = FALSE; // // EFI Decompress Protocol @@ -751,6 +752,8 @@ CoreExitBootServices ( return Status; } + gMemoryMapTerminated = TRUE; + // // Notify other drivers that we are exiting boot services. // diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c index fa71bd87df..dbdc71b59c 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Page.c +++ b/MdeModulePkg/Core/Dxe/Mem/Page.c @@ -1336,6 +1336,7 @@ CoreAllocatePages ( Status = CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory); if (!EFI_ERROR (Status)) { CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePages, MemoryType, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) *Memory); + InstallMemoryAttributesTableOnMemoryAllocation (MemoryType); } return Status; } @@ -1444,6 +1445,7 @@ CoreFreePages ( Status = CoreInternalFreePages (Memory, NumberOfPages, &MemoryType); if (!EFI_ERROR (Status)) { CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePages, (EFI_MEMORY_TYPE) 0, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) Memory); + InstallMemoryAttributesTableOnMemoryAllocation (MemoryType); } return Status; } diff --git a/MdeModulePkg/Core/Dxe/Mem/Pool.c b/MdeModulePkg/Core/Dxe/Mem/Pool.c index 5496a09cfa..5eced88efb 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Pool.c +++ b/MdeModulePkg/Core/Dxe/Mem/Pool.c @@ -277,6 +277,7 @@ CoreAllocatePool ( Status = CoreInternalAllocatePool (PoolType, Size, Buffer); if (!EFI_ERROR (Status)) { CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer); + InstallMemoryAttributesTableOnMemoryAllocation (PoolType); } return Status; } @@ -505,6 +506,7 @@ CoreFreePool ( Status = CoreInternalFreePool (Buffer, &PoolType); if (!EFI_ERROR (Status)) { CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, (EFI_MEMORY_TYPE) 0, 0, Buffer); + InstallMemoryAttributesTableOnMemoryAllocation (PoolType); } return Status; } diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c index 0362212c8b..3706b23247 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c @@ -71,18 +71,16 @@ CoreGetMemoryMapPropertiesTable ( ); extern EFI_PROPERTIES_TABLE mPropertiesTable; +EFI_MEMORY_ATTRIBUTES_TABLE *mMemoryAttributesTable = NULL; +BOOLEAN mMemoryAttributesTableReadyToBoot = FALSE; /** Install MemoryAttributesTable. - @param[in] Event The Event this notify function registered to. - @param[in] Context Pointer to the context data registered to the Event. **/ VOID -EFIAPI InstallMemoryAttributesTable ( - EFI_EVENT Event, - VOID *Context + VOID ) { UINTN MemoryMapSize; @@ -97,12 +95,29 @@ InstallMemoryAttributesTable ( EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable; EFI_MEMORY_DESCRIPTOR *MemoryAttributesEntry; + if (gMemoryMapTerminated) { + // + // Directly return after MemoryMap terminated. + // + return; + } + if ((mPropertiesTable.MemoryProtectionAttribute & EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) { DEBUG ((EFI_D_VERBOSE, "MemoryProtectionAttribute NON_EXECUTABLE_PE_DATA is not set, ")); DEBUG ((EFI_D_VERBOSE, "because Runtime Driver Section Alignment is not %dK.\n", EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT >> 10)); return ; } + if (mMemoryAttributesTable == NULL) { + // + // InstallConfigurationTable here to occupy one entry for MemoryAttributesTable + // before GetMemoryMap below, as InstallConfigurationTable may allocate runtime + // memory for the new entry. + // + Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID *) (UINTN) MAX_ADDRESS); + ASSERT_EFI_ERROR (Status); + } + MemoryMapSize = 0; MemoryMap = NULL; Status = CoreGetMemoryMapPropertiesTable ( @@ -177,8 +192,52 @@ InstallMemoryAttributesTable ( MemoryMap = MemoryMapStart; FreePool (MemoryMap); + // + // Update configuratoin table for MemoryAttributesTable. + // Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, MemoryAttributesTable); ASSERT_EFI_ERROR (Status); + + if (mMemoryAttributesTable != NULL) { + FreePool (mMemoryAttributesTable); + } + mMemoryAttributesTable = MemoryAttributesTable; +} + +/** + Install MemoryAttributesTable on memory allocation. + + @param[in] MemoryType EFI memory type. +**/ +VOID +InstallMemoryAttributesTableOnMemoryAllocation ( + IN EFI_MEMORY_TYPE MemoryType + ) +{ + // + // Install MemoryAttributesTable after ReadyToBoot on runtime memory allocation. + // + if (mMemoryAttributesTableReadyToBoot && + ((MemoryType == EfiRuntimeServicesCode) || (MemoryType == EfiRuntimeServicesData))) { + InstallMemoryAttributesTable (); + } +} + +/** + Install MemoryAttributesTable on ReadyToBoot. + + @param[in] Event The Event this notify function registered to. + @param[in] Context Pointer to the context data registered to the Event. +**/ +VOID +EFIAPI +InstallMemoryAttributesTableOnReadyToBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + InstallMemoryAttributesTable (); + mMemoryAttributesTableReadyToBoot = TRUE; } /** @@ -194,17 +253,16 @@ CoreInitializeMemoryAttributesTable ( EFI_EVENT ReadyToBootEvent; // - // Construct the table at ReadyToBoot, because this should be - // last point to allocate RuntimeCode/RuntimeData. + // Construct the table at ReadyToBoot. // - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - InstallMemoryAttributesTable, - NULL, - &gEfiEventReadyToBootGuid, - &ReadyToBootEvent - ); + Status = CoreCreateEventInternal ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK - 1, + InstallMemoryAttributesTableOnReadyToBoot, + NULL, + &gEfiEventReadyToBootGuid, + &ReadyToBootEvent + ); ASSERT_EFI_ERROR (Status); return ; } -- 2.39.2