From 98c4b005c87921646da53a1e3ac01c94cf87139a Mon Sep 17 00:00:00 2001 From: jiewen yao Date: Fri, 29 Jan 2016 16:52:14 +0800 Subject: [PATCH] MdeModulePkg: Add MemoryAttributesTable generation. Add MemoryAttributesTable generation in DxeCore. We leverage the information collected by original PropertiesTable, and publish runtime code/data to another standalone table. So that this is a compatible solution to report more PE Code/Data information. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: "Yao, Jiewen" Reviewed-by: "Gao, Liming" --- .../Core/Dxe/Misc/MemoryAttributesTable.c | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c new file mode 100644 index 0000000000..c84146a8e8 --- /dev/null +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c @@ -0,0 +1,214 @@ +/** @file + UEFI MemoryAttributesTable support + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "DxeMain.h" + +/** + This function for GetMemoryMap() with properties table capability. + + It calls original GetMemoryMap() to get the original memory map information. Then + plus the additional memory map entries for PE Code/Data seperation. + + @param MemoryMapSize A pointer to the size, in bytes, of the + MemoryMap buffer. On input, this is the size of + the buffer allocated by the caller. On output, + it is the size of the buffer returned by the + firmware if the buffer was large enough, or the + size of the buffer needed to contain the map if + the buffer was too small. + @param MemoryMap A pointer to the buffer in which firmware places + the current memory map. + @param MapKey A pointer to the location in which firmware + returns the key for the current memory map. + @param DescriptorSize A pointer to the location in which firmware + returns the size, in bytes, of an individual + EFI_MEMORY_DESCRIPTOR. + @param DescriptorVersion A pointer to the location in which firmware + returns the version number associated with the + EFI_MEMORY_DESCRIPTOR. + + @retval EFI_SUCCESS The memory map was returned in the MemoryMap + buffer. + @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current + buffer size needed to hold the memory map is + returned in MemoryMapSize. + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + +**/ +EFI_STATUS +EFIAPI +CoreGetMemoryMapPropertiesTable ( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ); + +extern EFI_PROPERTIES_TABLE mPropertiesTable; + +BOOLEAN mIsConstructingMemoryAttributesTable = 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 + ) +{ + UINTN MemoryMapSize; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + EFI_MEMORY_DESCRIPTOR *MemoryMapStart; + UINTN MapKey; + UINTN DescriptorSize; + UINT32 DescriptorVersion; + UINTN Index; + EFI_STATUS Status; + UINT32 RuntimeEntryCount; + EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable; + EFI_MEMORY_DESCRIPTOR *MemoryAttributesEntry; + + 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 ; + } + + mIsConstructingMemoryAttributesTable = TRUE; + + MemoryMapSize = 0; + MemoryMap = NULL; + Status = CoreGetMemoryMapPropertiesTable ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + do { + MemoryMap = AllocatePool (MemoryMapSize); + ASSERT (MemoryMap != NULL); + + Status = CoreGetMemoryMapPropertiesTable ( + &MemoryMapSize, + MemoryMap, + &MapKey, + &DescriptorSize, + &DescriptorVersion + ); + if (EFI_ERROR (Status)) { + FreePool (MemoryMap); + } + } while (Status == EFI_BUFFER_TOO_SMALL); + + MemoryMapStart = MemoryMap; + RuntimeEntryCount = 0; + for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) { + switch (MemoryMap->Type) { + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + RuntimeEntryCount ++; + break; + } + MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize); + } + + // + // Allocate MemoryAttributesTable + // + MemoryAttributesTable = AllocatePool (sizeof(EFI_MEMORY_ATTRIBUTES_TABLE) + DescriptorSize * RuntimeEntryCount); + ASSERT (MemoryAttributesTable != NULL); + MemoryAttributesTable->Version = EFI_MEMORY_ATTRIBUTES_TABLE_VERSION; + MemoryAttributesTable->NumberOfEntries = RuntimeEntryCount; + MemoryAttributesTable->DescriptorSize = (UINT32)DescriptorSize; + MemoryAttributesTable->Reserved = 0; + DEBUG ((EFI_D_VERBOSE, "MemoryAttributesTable:\n")); + DEBUG ((EFI_D_VERBOSE, " Version - 0x%08x\n", MemoryAttributesTable->Version)); + DEBUG ((EFI_D_VERBOSE, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable->NumberOfEntries)); + DEBUG ((EFI_D_VERBOSE, " DescriptorSize - 0x%08x\n", MemoryAttributesTable->DescriptorSize)); + MemoryAttributesEntry = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1); + MemoryMap = MemoryMapStart; + for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) { + switch (MemoryMap->Type) { + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + CopyMem (MemoryAttributesEntry, MemoryMap, DescriptorSize); + MemoryAttributesEntry->Attribute &= (EFI_MEMORY_RO|EFI_MEMORY_XP|EFI_MEMORY_RUNTIME); + DEBUG ((EFI_D_VERBOSE, "Entry (0x%x)\n", MemoryAttributesEntry)); + DEBUG ((EFI_D_VERBOSE, " Type - 0x%x\n", MemoryAttributesEntry->Type)); + DEBUG ((EFI_D_VERBOSE, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry->PhysicalStart)); + DEBUG ((EFI_D_VERBOSE, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry->VirtualStart)); + DEBUG ((EFI_D_VERBOSE, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry->NumberOfPages)); + DEBUG ((EFI_D_VERBOSE, " Attribute - 0x%016lx\n", MemoryAttributesEntry->Attribute)); + MemoryAttributesEntry = NEXT_MEMORY_DESCRIPTOR(MemoryAttributesEntry, DescriptorSize); + break; + } + MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize); + } + + Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, MemoryAttributesTable); + ASSERT_EFI_ERROR (Status); + + mIsConstructingMemoryAttributesTable = FALSE; +} + +/** + Initialize MemoryAttrubutesTable support. +**/ +VOID +EFIAPI +CoreInitializeMemoryAttributesTable ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT ReadyToBootEvent; + + // + // Construct the table at ReadyToBoot, because this should be + // last point to allocate RuntimeCode/RuntimeData. + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + InstallMemoryAttributesTable, + NULL, + &gEfiEventReadyToBootGuid, + &ReadyToBootEvent + ); + ASSERT_EFI_ERROR (Status); + return ; +} -- 2.39.2