diff --git a/MdeModulePkg/Core/Dxe/DxeMain.h b/MdeModulePkg/Core/Dxe/DxeMain.h index 6a64852730..9bd3c0d084 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.h +++ b/MdeModulePkg/Core/Dxe/DxeMain.h @@ -2815,15 +2815,6 @@ CoreUpdateMemoryAttributes ( IN UINT64 NewAttributes ); -/** - Initialize PropertiesTable support. -**/ -VOID -EFIAPI -CoreInitializePropertiesTable ( - VOID - ); - /** Initialize MemoryAttrubutesTable support. **/ diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeMain.inf index 75e0a968f0..1d4b11dc73 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -34,7 +34,6 @@ Misc/Stall.c Misc/SetWatchdogTimer.c Misc/InstallConfigurationTable.c - Misc/PropertiesTable.c Misc/MemoryAttributesTable.c Misc/MemoryProtection.c Library/Library.c diff --git a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c index 514d1aa75a..5ee4cd10b4 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c +++ b/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c @@ -423,7 +423,6 @@ DxeMain ( MemoryProfileInstallProtocol (); - CoreInitializePropertiesTable (); CoreInitializeMemoryAttributesTable (); CoreInitializeMemoryProtection (); diff --git a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c index 4a2b4a82a6..45356130bc 100644 --- a/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c +++ b/MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c @@ -20,6 +20,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include "DxeMain.h" +#include "HeapGuard.h" /** This function for GetMemoryMap() with properties table capability. @@ -63,7 +64,29 @@ CoreGetMemoryMapWithSeparatedImageSection ( OUT UINT32 *DescriptorVersion ); +#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \ + ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size))) + +#define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D') + +typedef struct { + UINT32 Signature; + UINTN ImageRecordCount; + UINTN CodeSegmentCountMax; + LIST_ENTRY ImageRecordList; +} IMAGE_PROPERTIES_PRIVATE_DATA; + +STATIC IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData = { + IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE, + 0, + 0, + INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData.ImageRecordList) +}; + +STATIC EFI_LOCK mMemoryAttributesTableLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY); + BOOLEAN mMemoryAttributesTableEnable = TRUE; +BOOLEAN mMemoryAttributesTableEndOfDxe = FALSE; EFI_MEMORY_ATTRIBUTES_TABLE *mMemoryAttributesTable = NULL; BOOLEAN mMemoryAttributesTableReadyToBoot = FALSE; @@ -247,6 +270,7 @@ InstallMemoryAttributesTableOnEndOfDxe ( IN VOID *Context ) { + mMemoryAttributesTableEndOfDxe = TRUE; InstallMemoryAttributesTable (); } @@ -293,3 +317,1198 @@ CoreInitializeMemoryAttributesTable ( ASSERT_EFI_ERROR (Status); return ; } + +// +// Below functions are for MemoryMap +// + +/** + Converts a number of EFI_PAGEs to a size in bytes. + + NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only. + + @param Pages The number of EFI_PAGES. + + @return The number of bytes associated with the number of EFI_PAGEs specified + by Pages. +**/ +STATIC +UINT64 +EfiPagesToSize ( + IN UINT64 Pages + ) +{ + return LShiftU64 (Pages, EFI_PAGE_SHIFT); +} + +/** + Converts a size, in bytes, to a number of EFI_PAGESs. + + NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only. + + @param Size A size in bytes. + + @return The number of EFI_PAGESs associated with the number of bytes specified + by Size. + +**/ +STATIC +UINT64 +EfiSizeToPages ( + IN UINT64 Size + ) +{ + return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0); +} + +/** + Acquire memory lock on mMemoryAttributesTableLock. +**/ +STATIC +VOID +CoreAcquiremMemoryAttributesTableLock ( + VOID + ) +{ + CoreAcquireLock (&mMemoryAttributesTableLock); +} + +/** + Release memory lock on mMemoryAttributesTableLock. +**/ +STATIC +VOID +CoreReleasemMemoryAttributesTableLock ( + VOID + ) +{ + CoreReleaseLock (&mMemoryAttributesTableLock); +} + +/** + Sort memory map entries based upon PhysicalStart, from low to high. + + @param MemoryMap A pointer to the buffer in which firmware places + the current memory map. + @param MemoryMapSize Size, in bytes, of the MemoryMap buffer. + @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. +**/ +STATIC +VOID +SortMemoryMap ( + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize + ) +{ + EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; + EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry; + EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; + EFI_MEMORY_DESCRIPTOR TempMemoryMap; + + MemoryMapEntry = MemoryMap; + NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); + MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize); + while (MemoryMapEntry < MemoryMapEnd) { + while (NextMemoryMapEntry < MemoryMapEnd) { + if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) { + CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR)); + CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR)); + CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof(EFI_MEMORY_DESCRIPTOR)); + } + + NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize); + } + + MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); + NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); + } + + return ; +} + +/** + Merge continous memory map entries whose have same attributes. + + @param MemoryMap A pointer to the buffer in which firmware places + the current memory map. + @param MemoryMapSize A pointer to the size, in bytes, of the + MemoryMap buffer. On input, this is the size of + the current memory map. On output, + it is the size of new memory map after merge. + @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. +**/ +VOID +MergeMemoryMap ( + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + IN OUT UINTN *MemoryMapSize, + IN UINTN DescriptorSize + ) +{ + EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; + EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; + UINT64 MemoryBlockLength; + EFI_MEMORY_DESCRIPTOR *NewMemoryMapEntry; + EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry; + + MemoryMapEntry = MemoryMap; + NewMemoryMapEntry = MemoryMap; + MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + *MemoryMapSize); + while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) { + CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR)); + NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); + + do { + MergeGuardPages (NewMemoryMapEntry, NextMemoryMapEntry->PhysicalStart); + MemoryBlockLength = (UINT64) (EfiPagesToSize (NewMemoryMapEntry->NumberOfPages)); + if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) && + (NewMemoryMapEntry->Type == NextMemoryMapEntry->Type) && + (NewMemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) && + ((NewMemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart)) { + NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages; + NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize); + continue; + } else { + MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize); + break; + } + } while (TRUE); + + MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); + NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize); + } + + *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap; + + return ; +} + +/** + Enforce memory map attributes. + This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP. + + @param MemoryMap A pointer to the buffer in which firmware places + the current memory map. + @param MemoryMapSize Size, in bytes, of the MemoryMap buffer. + @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. +**/ +STATIC +VOID +EnforceMemoryMapAttribute ( + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize + ) +{ + EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; + EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; + + MemoryMapEntry = MemoryMap; + MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize); + while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) { + switch (MemoryMapEntry->Type) { + case EfiRuntimeServicesCode: + // do nothing + break; + case EfiRuntimeServicesData: + case EfiMemoryMappedIO: + case EfiMemoryMappedIOPortSpace: + MemoryMapEntry->Attribute |= EFI_MEMORY_XP; + break; + case EfiReservedMemoryType: + case EfiACPIMemoryNVS: + break; + } + + MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); + } + + return ; +} + +/** + Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length]. + + @param Buffer Start Address + @param Length Address length + + @return first image record covered by [buffer, length] +**/ +STATIC +IMAGE_PROPERTIES_RECORD * +GetImageRecordByAddress ( + IN EFI_PHYSICAL_ADDRESS Buffer, + IN UINT64 Length + ) +{ + IMAGE_PROPERTIES_RECORD *ImageRecord; + LIST_ENTRY *ImageRecordLink; + LIST_ENTRY *ImageRecordList; + + ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList; + + for (ImageRecordLink = ImageRecordList->ForwardLink; + ImageRecordLink != ImageRecordList; + ImageRecordLink = ImageRecordLink->ForwardLink) { + ImageRecord = CR ( + ImageRecordLink, + IMAGE_PROPERTIES_RECORD, + Link, + IMAGE_PROPERTIES_RECORD_SIGNATURE + ); + + if ((Buffer <= ImageRecord->ImageBase) && + (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize)) { + return ImageRecord; + } + } + + return NULL; +} + +/** + Set the memory map to new entries, according to one old entry, + based upon PE code section and data section in image record + + @param ImageRecord An image record whose [ImageBase, ImageSize] covered + by old memory map entry. + @param NewRecord A pointer to several new memory map entries. + The caller gurantee the buffer size be 1 + + (SplitRecordCount * DescriptorSize) calculated + below. + @param OldRecord A pointer to one old memory map entry. + @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. +**/ +STATIC +UINTN +SetNewRecord ( + IN IMAGE_PROPERTIES_RECORD *ImageRecord, + IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord, + IN EFI_MEMORY_DESCRIPTOR *OldRecord, + IN UINTN DescriptorSize + ) +{ + EFI_MEMORY_DESCRIPTOR TempRecord; + IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; + LIST_ENTRY *ImageRecordCodeSectionLink; + LIST_ENTRY *ImageRecordCodeSectionEndLink; + LIST_ENTRY *ImageRecordCodeSectionList; + UINTN NewRecordCount; + UINT64 PhysicalEnd; + UINT64 ImageEnd; + + CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR)); + PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages); + NewRecordCount = 0; + + ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList; + + ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink; + ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList; + while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { + ImageRecordCodeSection = CR ( + ImageRecordCodeSectionLink, + IMAGE_PROPERTIES_RECORD_CODE_SECTION, + Link, + IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE + ); + ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; + + if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) { + // + // DATA + // + NewRecord->Type = TempRecord.Type; + NewRecord->PhysicalStart = TempRecord.PhysicalStart; + NewRecord->VirtualStart = 0; + NewRecord->NumberOfPages = EfiSizeToPages(ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart); + NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP; + if (NewRecord->NumberOfPages != 0) { + NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); + NewRecordCount ++; + } + + // + // CODE + // + NewRecord->Type = TempRecord.Type; + NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase; + NewRecord->VirtualStart = 0; + NewRecord->NumberOfPages = EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize); + NewRecord->Attribute = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO; + if (NewRecord->NumberOfPages != 0) { + NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); + NewRecordCount ++; + } + + TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize)); + TempRecord.NumberOfPages = EfiSizeToPages(PhysicalEnd - TempRecord.PhysicalStart); + if (TempRecord.NumberOfPages == 0) { + break; + } + } + } + + ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize; + + // + // Final DATA + // + if (TempRecord.PhysicalStart < ImageEnd) { + NewRecord->Type = TempRecord.Type; + NewRecord->PhysicalStart = TempRecord.PhysicalStart; + NewRecord->VirtualStart = 0; + NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart); + NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP; + NewRecordCount ++; + } + + return NewRecordCount; +} + +/** + Return the max number of new splitted entries, according to one old entry, + based upon PE code section and data section. + + @param OldRecord A pointer to one old memory map entry. + + @retval 0 no entry need to be splitted. + @return the max number of new splitted entries +**/ +STATIC +UINTN +GetMaxSplitRecordCount ( + IN EFI_MEMORY_DESCRIPTOR *OldRecord + ) +{ + IMAGE_PROPERTIES_RECORD *ImageRecord; + UINTN SplitRecordCount; + UINT64 PhysicalStart; + UINT64 PhysicalEnd; + + SplitRecordCount = 0; + PhysicalStart = OldRecord->PhysicalStart; + PhysicalEnd = OldRecord->PhysicalStart + EfiPagesToSize(OldRecord->NumberOfPages); + + do { + ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart); + if (ImageRecord == NULL) { + break; + } + SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1); + PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize; + } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd)); + + if (SplitRecordCount != 0) { + SplitRecordCount--; + } + + return SplitRecordCount; +} + +/** + Split the memory map to new entries, according to one old entry, + based upon PE code section and data section. + + @param OldRecord A pointer to one old memory map entry. + @param NewRecord A pointer to several new memory map entries. + The caller gurantee the buffer size be 1 + + (SplitRecordCount * DescriptorSize) calculated + below. + @param MaxSplitRecordCount The max number of splitted entries + @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. + + @retval 0 no entry is splitted. + @return the real number of splitted record. +**/ +STATIC +UINTN +SplitRecord ( + IN EFI_MEMORY_DESCRIPTOR *OldRecord, + IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord, + IN UINTN MaxSplitRecordCount, + IN UINTN DescriptorSize + ) +{ + EFI_MEMORY_DESCRIPTOR TempRecord; + IMAGE_PROPERTIES_RECORD *ImageRecord; + IMAGE_PROPERTIES_RECORD *NewImageRecord; + UINT64 PhysicalStart; + UINT64 PhysicalEnd; + UINTN NewRecordCount; + UINTN TotalNewRecordCount; + BOOLEAN IsLastRecordData; + + if (MaxSplitRecordCount == 0) { + CopyMem (NewRecord, OldRecord, DescriptorSize); + return 0; + } + + TotalNewRecordCount = 0; + + // + // Override previous record + // + CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR)); + PhysicalStart = TempRecord.PhysicalStart; + PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages); + + ImageRecord = NULL; + do { + NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart); + if (NewImageRecord == NULL) { + // + // No more image covered by this range, stop + // + if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) { + // + // If this is still address in this record, need record. + // + NewRecord = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); + IsLastRecordData = FALSE; + if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) { + IsLastRecordData = TRUE; + } + if (IsLastRecordData) { + // + // Last record is DATA, just merge it. + // + NewRecord->NumberOfPages = EfiSizeToPages(PhysicalEnd - NewRecord->PhysicalStart); + } else { + // + // Last record is CODE, create a new DATA entry. + // + NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); + NewRecord->Type = TempRecord.Type; + NewRecord->PhysicalStart = TempRecord.PhysicalStart; + NewRecord->VirtualStart = 0; + NewRecord->NumberOfPages = TempRecord.NumberOfPages; + NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP; + TotalNewRecordCount ++; + } + } + break; + } + ImageRecord = NewImageRecord; + + // + // Set new record + // + NewRecordCount = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize); + TotalNewRecordCount += NewRecordCount; + NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize); + + // + // Update PhysicalStart, in order to exclude the image buffer already splitted. + // + PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize; + TempRecord.PhysicalStart = PhysicalStart; + TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart); + } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd)); + + // + // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the + // code reaches here. + // + ASSERT (TotalNewRecordCount != 0); + return TotalNewRecordCount - 1; +} + +/** + Split the original memory map, and add more entries to describe PE code section and data section. + This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP. + This function will merge entries with same attributes finally. + + NOTE: It assumes PE code/data section are page aligned. + NOTE: It assumes enough entry is prepared for new memory map. + + Split table: + +---------------+ + | Record X | + +---------------+ + | Record RtCode | + +---------------+ + | Record Y | + +---------------+ + ==> + +---------------+ + | Record X | + +---------------+ ---- + | Record RtData | | + +---------------+ | + | Record RtCode | |-> PE/COFF1 + +---------------+ | + | Record RtData | | + +---------------+ ---- + | Record RtData | | + +---------------+ | + | Record RtCode | |-> PE/COFF2 + +---------------+ | + | Record RtData | | + +---------------+ ---- + | Record Y | + +---------------+ + + @param MemoryMapSize A pointer to the size, in bytes, of the + MemoryMap buffer. On input, this is the size of + old MemoryMap before split. The actual buffer + size of MemoryMap is MemoryMapSize + + (AdditionalRecordCount * DescriptorSize) calculated + below. On output, it is the size of new MemoryMap + after split. + @param MemoryMap A pointer to the buffer in which firmware places + the current memory map. + @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. +**/ +STATIC +VOID +SplitTable ( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + IN UINTN DescriptorSize + ) +{ + INTN IndexOld; + INTN IndexNew; + UINTN MaxSplitRecordCount; + UINTN RealSplitRecordCount; + UINTN TotalSplitRecordCount; + UINTN AdditionalRecordCount; + + AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount; + + TotalSplitRecordCount = 0; + // + // Let old record point to end of valid MemoryMap buffer. + // + IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1; + // + // Let new record point to end of full MemoryMap buffer. + // + IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + AdditionalRecordCount; + for (; IndexOld >= 0; IndexOld--) { + MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize)); + // + // Split this MemoryMap record + // + IndexNew -= MaxSplitRecordCount; + RealSplitRecordCount = SplitRecord ( + (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), + (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize), + MaxSplitRecordCount, + DescriptorSize + ); + // + // Adjust IndexNew according to real split. + // + CopyMem ( + ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize), + ((UINT8 *)MemoryMap + IndexNew * DescriptorSize), + RealSplitRecordCount * DescriptorSize + ); + IndexNew = IndexNew + MaxSplitRecordCount - RealSplitRecordCount; + TotalSplitRecordCount += RealSplitRecordCount; + IndexNew --; + } + // + // Move all records to the beginning. + // + CopyMem ( + MemoryMap, + (UINT8 *)MemoryMap + (AdditionalRecordCount - TotalSplitRecordCount) * DescriptorSize, + (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize + ); + + *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount; + + // + // Sort from low to high (Just in case) + // + SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize); + + // + // Set RuntimeData to XP + // + EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, DescriptorSize); + + // + // Merge same type to save entry size + // + MergeMemoryMap (MemoryMap, MemoryMapSize, DescriptorSize); + + return ; +} + +/** + 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 +CoreGetMemoryMapWithSeparatedImageSection ( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ) +{ + EFI_STATUS Status; + UINTN OldMemoryMapSize; + UINTN AdditionalRecordCount; + + // + // If PE code/data is not aligned, just return. + // + if (!mMemoryAttributesTableEnable) { + return CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion); + } + + if (MemoryMapSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquiremMemoryAttributesTableLock (); + + AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount; + + OldMemoryMapSize = *MemoryMapSize; + Status = CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion); + if (Status == EFI_BUFFER_TOO_SMALL) { + *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount; + } else if (Status == EFI_SUCCESS) { + ASSERT (MemoryMap != NULL); + if (OldMemoryMapSize - *MemoryMapSize < (*DescriptorSize) * AdditionalRecordCount) { + *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount; + // + // Need update status to buffer too small + // + Status = EFI_BUFFER_TOO_SMALL; + } else { + // + // Split PE code/data + // + SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize); + } + } + + CoreReleasemMemoryAttributesTableLock (); + return Status; +} + +// +// Below functions are for ImageRecord +// + +/** + Set MemoryAttributesTable according to PE/COFF image section alignment. + + @param SectionAlignment PE/COFF section alignment +**/ +STATIC +VOID +SetMemoryAttributesTableSectionAlignment ( + IN UINT32 SectionAlignment + ) +{ + if (((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) && + mMemoryAttributesTableEnable) { + DEBUG ((DEBUG_VERBOSE, "SetMemoryAttributesTableSectionAlignment - Clear\n")); + mMemoryAttributesTableEnable = FALSE; + } +} + +/** + Swap two code sections in image record. + + @param FirstImageRecordCodeSection first code section in image record + @param SecondImageRecordCodeSection second code section in image record +**/ +STATIC +VOID +SwapImageRecordCodeSection ( + IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *FirstImageRecordCodeSection, + IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *SecondImageRecordCodeSection + ) +{ + IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection; + + TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase; + TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize; + + FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase; + FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize; + + SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase; + SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize; +} + +/** + Sort code section in image record, based upon CodeSegmentBase from low to high. + + @param ImageRecord image record to be sorted +**/ +VOID +SortImageRecordCodeSection ( + IN IMAGE_PROPERTIES_RECORD *ImageRecord + ) +{ + IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; + IMAGE_PROPERTIES_RECORD_CODE_SECTION *NextImageRecordCodeSection; + LIST_ENTRY *ImageRecordCodeSectionLink; + LIST_ENTRY *NextImageRecordCodeSectionLink; + LIST_ENTRY *ImageRecordCodeSectionEndLink; + LIST_ENTRY *ImageRecordCodeSectionList; + + ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList; + + ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink; + NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; + ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList; + while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { + ImageRecordCodeSection = CR ( + ImageRecordCodeSectionLink, + IMAGE_PROPERTIES_RECORD_CODE_SECTION, + Link, + IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE + ); + while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { + NextImageRecordCodeSection = CR ( + NextImageRecordCodeSectionLink, + IMAGE_PROPERTIES_RECORD_CODE_SECTION, + Link, + IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE + ); + if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) { + SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection); + } + NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink; + } + + ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; + NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; + } +} + +/** + Check if code section in image record is valid. + + @param ImageRecord image record to be checked + + @retval TRUE image record is valid + @retval FALSE image record is invalid +**/ +BOOLEAN +IsImageRecordCodeSectionValid ( + IN IMAGE_PROPERTIES_RECORD *ImageRecord + ) +{ + IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; + IMAGE_PROPERTIES_RECORD_CODE_SECTION *LastImageRecordCodeSection; + LIST_ENTRY *ImageRecordCodeSectionLink; + LIST_ENTRY *ImageRecordCodeSectionEndLink; + LIST_ENTRY *ImageRecordCodeSectionList; + + DEBUG ((DEBUG_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount)); + + ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList; + + ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink; + ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList; + LastImageRecordCodeSection = NULL; + while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { + ImageRecordCodeSection = CR ( + ImageRecordCodeSectionLink, + IMAGE_PROPERTIES_RECORD_CODE_SECTION, + Link, + IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE + ); + if (ImageRecordCodeSection->CodeSegmentSize == 0) { + return FALSE; + } + if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) { + return FALSE; + } + if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) { + return FALSE; + } + if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) { + return FALSE; + } + if (LastImageRecordCodeSection != NULL) { + if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) { + return FALSE; + } + } + + LastImageRecordCodeSection = ImageRecordCodeSection; + ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; + } + + return TRUE; +} + +/** + Swap two image records. + + @param FirstImageRecord first image record. + @param SecondImageRecord second image record. +**/ +STATIC +VOID +SwapImageRecord ( + IN IMAGE_PROPERTIES_RECORD *FirstImageRecord, + IN IMAGE_PROPERTIES_RECORD *SecondImageRecord + ) +{ + IMAGE_PROPERTIES_RECORD TempImageRecord; + + TempImageRecord.ImageBase = FirstImageRecord->ImageBase; + TempImageRecord.ImageSize = FirstImageRecord->ImageSize; + TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount; + + FirstImageRecord->ImageBase = SecondImageRecord->ImageBase; + FirstImageRecord->ImageSize = SecondImageRecord->ImageSize; + FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount; + + SecondImageRecord->ImageBase = TempImageRecord.ImageBase; + SecondImageRecord->ImageSize = TempImageRecord.ImageSize; + SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount; + + SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList); +} + +/** + Sort image record based upon the ImageBase from low to high. +**/ +STATIC +VOID +SortImageRecord ( + VOID + ) +{ + IMAGE_PROPERTIES_RECORD *ImageRecord; + IMAGE_PROPERTIES_RECORD *NextImageRecord; + LIST_ENTRY *ImageRecordLink; + LIST_ENTRY *NextImageRecordLink; + LIST_ENTRY *ImageRecordEndLink; + LIST_ENTRY *ImageRecordList; + + ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList; + + ImageRecordLink = ImageRecordList->ForwardLink; + NextImageRecordLink = ImageRecordLink->ForwardLink; + ImageRecordEndLink = ImageRecordList; + while (ImageRecordLink != ImageRecordEndLink) { + ImageRecord = CR ( + ImageRecordLink, + IMAGE_PROPERTIES_RECORD, + Link, + IMAGE_PROPERTIES_RECORD_SIGNATURE + ); + while (NextImageRecordLink != ImageRecordEndLink) { + NextImageRecord = CR ( + NextImageRecordLink, + IMAGE_PROPERTIES_RECORD, + Link, + IMAGE_PROPERTIES_RECORD_SIGNATURE + ); + if (ImageRecord->ImageBase > NextImageRecord->ImageBase) { + SwapImageRecord (ImageRecord, NextImageRecord); + } + NextImageRecordLink = NextImageRecordLink->ForwardLink; + } + + ImageRecordLink = ImageRecordLink->ForwardLink; + NextImageRecordLink = ImageRecordLink->ForwardLink; + } +} + +/** + Insert image record. + + @param RuntimeImage Runtime image information +**/ +VOID +InsertImageRecord ( + IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage + ) +{ + VOID *ImageAddress; + EFI_IMAGE_DOS_HEADER *DosHdr; + UINT32 PeCoffHeaderOffset; + UINT32 SectionAlignment; + EFI_IMAGE_SECTION_HEADER *Section; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + UINT8 *Name; + UINTN Index; + IMAGE_PROPERTIES_RECORD *ImageRecord; + CHAR8 *PdbPointer; + IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; + + DEBUG ((DEBUG_VERBOSE, "InsertImageRecord - 0x%x\n", RuntimeImage)); + DEBUG ((DEBUG_VERBOSE, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize)); + + if (mMemoryAttributesTableEndOfDxe) { + DEBUG ((DEBUG_INFO, "Do not insert runtime image record after EndOfDxe\n")); + return ; + } + + ImageRecord = AllocatePool (sizeof(*ImageRecord)); + if (ImageRecord == NULL) { + return ; + } + ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE; + + DEBUG ((DEBUG_VERBOSE, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount)); + + // + // Step 1: record whole region + // + ImageRecord->ImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase; + ImageRecord->ImageSize = RuntimeImage->ImageSize; + + ImageAddress = RuntimeImage->ImageBase; + + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress); + if (PdbPointer != NULL) { + DEBUG ((DEBUG_VERBOSE, " Image - %a\n", PdbPointer)); + } + + // + // Check PE/COFF image + // + DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress; + PeCoffHeaderOffset = 0; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + PeCoffHeaderOffset = DosHdr->e_lfanew; + } + + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset); + if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) { + DEBUG ((DEBUG_VERBOSE, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature)); + // It might be image in SMM. + goto Finish; + } + + // + // Get SectionAlignment + // + if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment; + } else { + SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment; + } + + SetMemoryAttributesTableSectionAlignment (SectionAlignment); + if ((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) { + DEBUG ((DEBUG_WARN, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n", + SectionAlignment, RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10)); + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress); + if (PdbPointer != NULL) { + DEBUG ((DEBUG_WARN, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer)); + } + goto Finish; + } + + Section = (EFI_IMAGE_SECTION_HEADER *) ( + (UINT8 *) (UINTN) ImageAddress + + PeCoffHeaderOffset + + sizeof(UINT32) + + sizeof(EFI_IMAGE_FILE_HEADER) + + Hdr.Pe32->FileHeader.SizeOfOptionalHeader + ); + ImageRecord->CodeSegmentCount = 0; + InitializeListHead (&ImageRecord->CodeSegmentList); + for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) { + Name = Section[Index].Name; + DEBUG (( + DEBUG_VERBOSE, + " Section - '%c%c%c%c%c%c%c%c'\n", + Name[0], + Name[1], + Name[2], + Name[3], + Name[4], + Name[5], + Name[6], + Name[7] + )); + + if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) { + DEBUG ((DEBUG_VERBOSE, " VirtualSize - 0x%08x\n", Section[Index].Misc.VirtualSize)); + DEBUG ((DEBUG_VERBOSE, " VirtualAddress - 0x%08x\n", Section[Index].VirtualAddress)); + DEBUG ((DEBUG_VERBOSE, " SizeOfRawData - 0x%08x\n", Section[Index].SizeOfRawData)); + DEBUG ((DEBUG_VERBOSE, " PointerToRawData - 0x%08x\n", Section[Index].PointerToRawData)); + DEBUG ((DEBUG_VERBOSE, " PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations)); + DEBUG ((DEBUG_VERBOSE, " PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers)); + DEBUG ((DEBUG_VERBOSE, " NumberOfRelocations - 0x%08x\n", Section[Index].NumberOfRelocations)); + DEBUG ((DEBUG_VERBOSE, " NumberOfLinenumbers - 0x%08x\n", Section[Index].NumberOfLinenumbers)); + DEBUG ((DEBUG_VERBOSE, " Characteristics - 0x%08x\n", Section[Index].Characteristics)); + + // + // Step 2: record code section + // + ImageRecordCodeSection = AllocatePool (sizeof(*ImageRecordCodeSection)); + if (ImageRecordCodeSection == NULL) { + return ; + } + ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE; + + ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress; + ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData; + + DEBUG ((DEBUG_VERBOSE, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize)); + + InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link); + ImageRecord->CodeSegmentCount++; + } + } + + if (ImageRecord->CodeSegmentCount == 0) { + SetMemoryAttributesTableSectionAlignment (1); + DEBUG ((DEBUG_ERROR, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n")); + PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress); + if (PdbPointer != NULL) { + DEBUG ((DEBUG_ERROR, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer)); + } + goto Finish; + } + + // + // Final + // + SortImageRecordCodeSection (ImageRecord); + // + // Check overlap all section in ImageBase/Size + // + if (!IsImageRecordCodeSectionValid (ImageRecord)) { + DEBUG ((DEBUG_ERROR, "IsImageRecordCodeSectionValid - FAIL\n")); + goto Finish; + } + + InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link); + mImagePropertiesPrivateData.ImageRecordCount++; + + if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) { + mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount; + } + + SortImageRecord (); + +Finish: + return ; +} + +/** + Find image record according to image base and size. + + @param ImageBase Base of PE image + @param ImageSize Size of PE image + + @return image record +**/ +STATIC +IMAGE_PROPERTIES_RECORD * +FindImageRecord ( + IN EFI_PHYSICAL_ADDRESS ImageBase, + IN UINT64 ImageSize + ) +{ + IMAGE_PROPERTIES_RECORD *ImageRecord; + LIST_ENTRY *ImageRecordLink; + LIST_ENTRY *ImageRecordList; + + ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList; + + for (ImageRecordLink = ImageRecordList->ForwardLink; + ImageRecordLink != ImageRecordList; + ImageRecordLink = ImageRecordLink->ForwardLink) { + ImageRecord = CR ( + ImageRecordLink, + IMAGE_PROPERTIES_RECORD, + Link, + IMAGE_PROPERTIES_RECORD_SIGNATURE + ); + + if ((ImageBase == ImageRecord->ImageBase) && + (ImageSize == ImageRecord->ImageSize)) { + return ImageRecord; + } + } + + return NULL; +} + +/** + Remove Image record. + + @param RuntimeImage Runtime image information +**/ +VOID +RemoveImageRecord ( + IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage + ) +{ + IMAGE_PROPERTIES_RECORD *ImageRecord; + LIST_ENTRY *CodeSegmentListHead; + IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; + + DEBUG ((DEBUG_VERBOSE, "RemoveImageRecord - 0x%x\n", RuntimeImage)); + DEBUG ((DEBUG_VERBOSE, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize)); + + if (mMemoryAttributesTableEndOfDxe) { + DEBUG ((DEBUG_INFO, "Do not remove runtime image record after EndOfDxe\n")); + return ; + } + + ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize); + if (ImageRecord == NULL) { + DEBUG ((DEBUG_ERROR, "!!!!!!!! ImageRecord not found !!!!!!!!\n")); + return ; + } + + CodeSegmentListHead = &ImageRecord->CodeSegmentList; + while (!IsListEmpty (CodeSegmentListHead)) { + ImageRecordCodeSection = CR ( + CodeSegmentListHead->ForwardLink, + IMAGE_PROPERTIES_RECORD_CODE_SECTION, + Link, + IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE + ); + RemoveEntryList (&ImageRecordCodeSection->Link); + FreePool (ImageRecordCodeSection); + } + + RemoveEntryList (&ImageRecord->Link); + FreePool (ImageRecord); + mImagePropertiesPrivateData.ImageRecordCount--; +} diff --git a/MdeModulePkg/Core/Dxe/Misc/PropertiesTable.c b/MdeModulePkg/Core/Dxe/Misc/PropertiesTable.c deleted file mode 100644 index 6ee8a8af90..0000000000 --- a/MdeModulePkg/Core/Dxe/Misc/PropertiesTable.c +++ /dev/null @@ -1,1288 +0,0 @@ -/** @file - UEFI PropertiesTable support - -Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
-SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "DxeMain.h" -#include "HeapGuard.h" - -#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \ - ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size))) - -#define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D') - -typedef struct { - UINT32 Signature; - UINTN ImageRecordCount; - UINTN CodeSegmentCountMax; - LIST_ENTRY ImageRecordList; -} IMAGE_PROPERTIES_PRIVATE_DATA; - -IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData = { - IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE, - 0, - 0, - INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData.ImageRecordList) -}; - -EFI_LOCK mPropertiesTableLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY); - -BOOLEAN mPropertiesTableEndOfDxe = FALSE; - -extern BOOLEAN mMemoryAttributesTableEnable; - -// -// Below functions are for MemoryMap -// - -/** - Converts a number of EFI_PAGEs to a size in bytes. - - NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only. - - @param Pages The number of EFI_PAGES. - - @return The number of bytes associated with the number of EFI_PAGEs specified - by Pages. -**/ -STATIC -UINT64 -EfiPagesToSize ( - IN UINT64 Pages - ) -{ - return LShiftU64 (Pages, EFI_PAGE_SHIFT); -} - -/** - Converts a size, in bytes, to a number of EFI_PAGESs. - - NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only. - - @param Size A size in bytes. - - @return The number of EFI_PAGESs associated with the number of bytes specified - by Size. - -**/ -STATIC -UINT64 -EfiSizeToPages ( - IN UINT64 Size - ) -{ - return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0); -} - -/** - Acquire memory lock on mPropertiesTableLock. -**/ -STATIC -VOID -CoreAcquirePropertiesTableLock ( - VOID - ) -{ - CoreAcquireLock (&mPropertiesTableLock); -} - -/** - Release memory lock on mPropertiesTableLock. -**/ -STATIC -VOID -CoreReleasePropertiesTableLock ( - VOID - ) -{ - CoreReleaseLock (&mPropertiesTableLock); -} - -/** - Sort memory map entries based upon PhysicalStart, from low to high. - - @param MemoryMap A pointer to the buffer in which firmware places - the current memory map. - @param MemoryMapSize Size, in bytes, of the MemoryMap buffer. - @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. -**/ -STATIC -VOID -SortMemoryMap ( - IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, - IN UINTN MemoryMapSize, - IN UINTN DescriptorSize - ) -{ - EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; - EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry; - EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; - EFI_MEMORY_DESCRIPTOR TempMemoryMap; - - MemoryMapEntry = MemoryMap; - NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); - MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize); - while (MemoryMapEntry < MemoryMapEnd) { - while (NextMemoryMapEntry < MemoryMapEnd) { - if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) { - CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR)); - CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR)); - CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof(EFI_MEMORY_DESCRIPTOR)); - } - - NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize); - } - - MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); - NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); - } - - return ; -} - -/** - Merge continous memory map entries whose have same attributes. - - @param MemoryMap A pointer to the buffer in which firmware places - the current memory map. - @param MemoryMapSize A pointer to the size, in bytes, of the - MemoryMap buffer. On input, this is the size of - the current memory map. On output, - it is the size of new memory map after merge. - @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. -**/ -VOID -MergeMemoryMap ( - IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, - IN OUT UINTN *MemoryMapSize, - IN UINTN DescriptorSize - ) -{ - EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; - EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; - UINT64 MemoryBlockLength; - EFI_MEMORY_DESCRIPTOR *NewMemoryMapEntry; - EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry; - - MemoryMapEntry = MemoryMap; - NewMemoryMapEntry = MemoryMap; - MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + *MemoryMapSize); - while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) { - CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR)); - NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); - - do { - MergeGuardPages (NewMemoryMapEntry, NextMemoryMapEntry->PhysicalStart); - MemoryBlockLength = (UINT64) (EfiPagesToSize (NewMemoryMapEntry->NumberOfPages)); - if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) && - (NewMemoryMapEntry->Type == NextMemoryMapEntry->Type) && - (NewMemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) && - ((NewMemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart)) { - NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages; - NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize); - continue; - } else { - MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize); - break; - } - } while (TRUE); - - MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); - NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize); - } - - *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap; - - return ; -} - -/** - Enforce memory map attributes. - This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP. - - @param MemoryMap A pointer to the buffer in which firmware places - the current memory map. - @param MemoryMapSize Size, in bytes, of the MemoryMap buffer. - @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. -**/ -STATIC -VOID -EnforceMemoryMapAttribute ( - IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, - IN UINTN MemoryMapSize, - IN UINTN DescriptorSize - ) -{ - EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; - EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; - - MemoryMapEntry = MemoryMap; - MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize); - while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) { - switch (MemoryMapEntry->Type) { - case EfiRuntimeServicesCode: - // do nothing - break; - case EfiRuntimeServicesData: - case EfiMemoryMappedIO: - case EfiMemoryMappedIOPortSpace: - MemoryMapEntry->Attribute |= EFI_MEMORY_XP; - break; - case EfiReservedMemoryType: - case EfiACPIMemoryNVS: - break; - } - - MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); - } - - return ; -} - -/** - Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length]. - - @param Buffer Start Address - @param Length Address length - - @return first image record covered by [buffer, length] -**/ -STATIC -IMAGE_PROPERTIES_RECORD * -GetImageRecordByAddress ( - IN EFI_PHYSICAL_ADDRESS Buffer, - IN UINT64 Length - ) -{ - IMAGE_PROPERTIES_RECORD *ImageRecord; - LIST_ENTRY *ImageRecordLink; - LIST_ENTRY *ImageRecordList; - - ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList; - - for (ImageRecordLink = ImageRecordList->ForwardLink; - ImageRecordLink != ImageRecordList; - ImageRecordLink = ImageRecordLink->ForwardLink) { - ImageRecord = CR ( - ImageRecordLink, - IMAGE_PROPERTIES_RECORD, - Link, - IMAGE_PROPERTIES_RECORD_SIGNATURE - ); - - if ((Buffer <= ImageRecord->ImageBase) && - (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize)) { - return ImageRecord; - } - } - - return NULL; -} - -/** - Set the memory map to new entries, according to one old entry, - based upon PE code section and data section in image record - - @param ImageRecord An image record whose [ImageBase, ImageSize] covered - by old memory map entry. - @param NewRecord A pointer to several new memory map entries. - The caller gurantee the buffer size be 1 + - (SplitRecordCount * DescriptorSize) calculated - below. - @param OldRecord A pointer to one old memory map entry. - @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. -**/ -STATIC -UINTN -SetNewRecord ( - IN IMAGE_PROPERTIES_RECORD *ImageRecord, - IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord, - IN EFI_MEMORY_DESCRIPTOR *OldRecord, - IN UINTN DescriptorSize - ) -{ - EFI_MEMORY_DESCRIPTOR TempRecord; - IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; - LIST_ENTRY *ImageRecordCodeSectionLink; - LIST_ENTRY *ImageRecordCodeSectionEndLink; - LIST_ENTRY *ImageRecordCodeSectionList; - UINTN NewRecordCount; - UINT64 PhysicalEnd; - UINT64 ImageEnd; - - CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR)); - PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages); - NewRecordCount = 0; - - ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList; - - ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink; - ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList; - while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { - ImageRecordCodeSection = CR ( - ImageRecordCodeSectionLink, - IMAGE_PROPERTIES_RECORD_CODE_SECTION, - Link, - IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE - ); - ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; - - if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) { - // - // DATA - // - NewRecord->Type = TempRecord.Type; - NewRecord->PhysicalStart = TempRecord.PhysicalStart; - NewRecord->VirtualStart = 0; - NewRecord->NumberOfPages = EfiSizeToPages(ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart); - NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP; - if (NewRecord->NumberOfPages != 0) { - NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); - NewRecordCount ++; - } - - // - // CODE - // - NewRecord->Type = TempRecord.Type; - NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase; - NewRecord->VirtualStart = 0; - NewRecord->NumberOfPages = EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize); - NewRecord->Attribute = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO; - if (NewRecord->NumberOfPages != 0) { - NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); - NewRecordCount ++; - } - - TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize)); - TempRecord.NumberOfPages = EfiSizeToPages(PhysicalEnd - TempRecord.PhysicalStart); - if (TempRecord.NumberOfPages == 0) { - break; - } - } - } - - ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize; - - // - // Final DATA - // - if (TempRecord.PhysicalStart < ImageEnd) { - NewRecord->Type = TempRecord.Type; - NewRecord->PhysicalStart = TempRecord.PhysicalStart; - NewRecord->VirtualStart = 0; - NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart); - NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP; - NewRecordCount ++; - } - - return NewRecordCount; -} - -/** - Return the max number of new splitted entries, according to one old entry, - based upon PE code section and data section. - - @param OldRecord A pointer to one old memory map entry. - - @retval 0 no entry need to be splitted. - @return the max number of new splitted entries -**/ -STATIC -UINTN -GetMaxSplitRecordCount ( - IN EFI_MEMORY_DESCRIPTOR *OldRecord - ) -{ - IMAGE_PROPERTIES_RECORD *ImageRecord; - UINTN SplitRecordCount; - UINT64 PhysicalStart; - UINT64 PhysicalEnd; - - SplitRecordCount = 0; - PhysicalStart = OldRecord->PhysicalStart; - PhysicalEnd = OldRecord->PhysicalStart + EfiPagesToSize(OldRecord->NumberOfPages); - - do { - ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart); - if (ImageRecord == NULL) { - break; - } - SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1); - PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize; - } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd)); - - if (SplitRecordCount != 0) { - SplitRecordCount--; - } - - return SplitRecordCount; -} - -/** - Split the memory map to new entries, according to one old entry, - based upon PE code section and data section. - - @param OldRecord A pointer to one old memory map entry. - @param NewRecord A pointer to several new memory map entries. - The caller gurantee the buffer size be 1 + - (SplitRecordCount * DescriptorSize) calculated - below. - @param MaxSplitRecordCount The max number of splitted entries - @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. - - @retval 0 no entry is splitted. - @return the real number of splitted record. -**/ -STATIC -UINTN -SplitRecord ( - IN EFI_MEMORY_DESCRIPTOR *OldRecord, - IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord, - IN UINTN MaxSplitRecordCount, - IN UINTN DescriptorSize - ) -{ - EFI_MEMORY_DESCRIPTOR TempRecord; - IMAGE_PROPERTIES_RECORD *ImageRecord; - IMAGE_PROPERTIES_RECORD *NewImageRecord; - UINT64 PhysicalStart; - UINT64 PhysicalEnd; - UINTN NewRecordCount; - UINTN TotalNewRecordCount; - BOOLEAN IsLastRecordData; - - if (MaxSplitRecordCount == 0) { - CopyMem (NewRecord, OldRecord, DescriptorSize); - return 0; - } - - TotalNewRecordCount = 0; - - // - // Override previous record - // - CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR)); - PhysicalStart = TempRecord.PhysicalStart; - PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages); - - ImageRecord = NULL; - do { - NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart); - if (NewImageRecord == NULL) { - // - // No more image covered by this range, stop - // - if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) { - // - // If this is still address in this record, need record. - // - NewRecord = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); - IsLastRecordData = FALSE; - if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) { - IsLastRecordData = TRUE; - } - if (IsLastRecordData) { - // - // Last record is DATA, just merge it. - // - NewRecord->NumberOfPages = EfiSizeToPages(PhysicalEnd - NewRecord->PhysicalStart); - } else { - // - // Last record is CODE, create a new DATA entry. - // - NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize); - NewRecord->Type = TempRecord.Type; - NewRecord->PhysicalStart = TempRecord.PhysicalStart; - NewRecord->VirtualStart = 0; - NewRecord->NumberOfPages = TempRecord.NumberOfPages; - NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP; - TotalNewRecordCount ++; - } - } - break; - } - ImageRecord = NewImageRecord; - - // - // Set new record - // - NewRecordCount = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize); - TotalNewRecordCount += NewRecordCount; - NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize); - - // - // Update PhysicalStart, in order to exclude the image buffer already splitted. - // - PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize; - TempRecord.PhysicalStart = PhysicalStart; - TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart); - } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd)); - - // - // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the - // code reaches here. - // - ASSERT (TotalNewRecordCount != 0); - return TotalNewRecordCount - 1; -} - -/** - Split the original memory map, and add more entries to describe PE code section and data section. - This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP. - This function will merge entries with same attributes finally. - - NOTE: It assumes PE code/data section are page aligned. - NOTE: It assumes enough entry is prepared for new memory map. - - Split table: - +---------------+ - | Record X | - +---------------+ - | Record RtCode | - +---------------+ - | Record Y | - +---------------+ - ==> - +---------------+ - | Record X | - +---------------+ ---- - | Record RtData | | - +---------------+ | - | Record RtCode | |-> PE/COFF1 - +---------------+ | - | Record RtData | | - +---------------+ ---- - | Record RtData | | - +---------------+ | - | Record RtCode | |-> PE/COFF2 - +---------------+ | - | Record RtData | | - +---------------+ ---- - | Record Y | - +---------------+ - - @param MemoryMapSize A pointer to the size, in bytes, of the - MemoryMap buffer. On input, this is the size of - old MemoryMap before split. The actual buffer - size of MemoryMap is MemoryMapSize + - (AdditionalRecordCount * DescriptorSize) calculated - below. On output, it is the size of new MemoryMap - after split. - @param MemoryMap A pointer to the buffer in which firmware places - the current memory map. - @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR. -**/ -STATIC -VOID -SplitTable ( - IN OUT UINTN *MemoryMapSize, - IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, - IN UINTN DescriptorSize - ) -{ - INTN IndexOld; - INTN IndexNew; - UINTN MaxSplitRecordCount; - UINTN RealSplitRecordCount; - UINTN TotalSplitRecordCount; - UINTN AdditionalRecordCount; - - AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount; - - TotalSplitRecordCount = 0; - // - // Let old record point to end of valid MemoryMap buffer. - // - IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1; - // - // Let new record point to end of full MemoryMap buffer. - // - IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + AdditionalRecordCount; - for (; IndexOld >= 0; IndexOld--) { - MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize)); - // - // Split this MemoryMap record - // - IndexNew -= MaxSplitRecordCount; - RealSplitRecordCount = SplitRecord ( - (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), - (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize), - MaxSplitRecordCount, - DescriptorSize - ); - // - // Adjust IndexNew according to real split. - // - CopyMem ( - ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize), - ((UINT8 *)MemoryMap + IndexNew * DescriptorSize), - RealSplitRecordCount * DescriptorSize - ); - IndexNew = IndexNew + MaxSplitRecordCount - RealSplitRecordCount; - TotalSplitRecordCount += RealSplitRecordCount; - IndexNew --; - } - // - // Move all records to the beginning. - // - CopyMem ( - MemoryMap, - (UINT8 *)MemoryMap + (AdditionalRecordCount - TotalSplitRecordCount) * DescriptorSize, - (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize - ); - - *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount; - - // - // Sort from low to high (Just in case) - // - SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize); - - // - // Set RuntimeData to XP - // - EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, DescriptorSize); - - // - // Merge same type to save entry size - // - MergeMemoryMap (MemoryMap, MemoryMapSize, DescriptorSize); - - return ; -} - -/** - 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 -CoreGetMemoryMapWithSeparatedImageSection ( - IN OUT UINTN *MemoryMapSize, - IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, - OUT UINTN *MapKey, - OUT UINTN *DescriptorSize, - OUT UINT32 *DescriptorVersion - ) -{ - EFI_STATUS Status; - UINTN OldMemoryMapSize; - UINTN AdditionalRecordCount; - - // - // If PE code/data is not aligned, just return. - // - if (!mMemoryAttributesTableEnable) { - return CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion); - } - - if (MemoryMapSize == NULL) { - return EFI_INVALID_PARAMETER; - } - - CoreAcquirePropertiesTableLock (); - - AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount; - - OldMemoryMapSize = *MemoryMapSize; - Status = CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion); - if (Status == EFI_BUFFER_TOO_SMALL) { - *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount; - } else if (Status == EFI_SUCCESS) { - ASSERT (MemoryMap != NULL); - if (OldMemoryMapSize - *MemoryMapSize < (*DescriptorSize) * AdditionalRecordCount) { - *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount; - // - // Need update status to buffer too small - // - Status = EFI_BUFFER_TOO_SMALL; - } else { - // - // Split PE code/data - // - SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize); - } - } - - CoreReleasePropertiesTableLock (); - return Status; -} - -// -// Below functions are for ImageRecord -// - -/** - Set PropertiesTable according to PE/COFF image section alignment. - - @param SectionAlignment PE/COFF section alignment -**/ -STATIC -VOID -SetPropertiesTableSectionAlignment ( - IN UINT32 SectionAlignment - ) -{ - if (((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) && - mMemoryAttributesTableEnable) { - DEBUG ((EFI_D_VERBOSE, "SetPropertiesTableSectionAlignment - Clear\n")); - mMemoryAttributesTableEnable = FALSE; - } -} - -/** - Swap two code sections in image record. - - @param FirstImageRecordCodeSection first code section in image record - @param SecondImageRecordCodeSection second code section in image record -**/ -STATIC -VOID -SwapImageRecordCodeSection ( - IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *FirstImageRecordCodeSection, - IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *SecondImageRecordCodeSection - ) -{ - IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection; - - TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase; - TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize; - - FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase; - FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize; - - SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase; - SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize; -} - -/** - Sort code section in image record, based upon CodeSegmentBase from low to high. - - @param ImageRecord image record to be sorted -**/ -VOID -SortImageRecordCodeSection ( - IN IMAGE_PROPERTIES_RECORD *ImageRecord - ) -{ - IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; - IMAGE_PROPERTIES_RECORD_CODE_SECTION *NextImageRecordCodeSection; - LIST_ENTRY *ImageRecordCodeSectionLink; - LIST_ENTRY *NextImageRecordCodeSectionLink; - LIST_ENTRY *ImageRecordCodeSectionEndLink; - LIST_ENTRY *ImageRecordCodeSectionList; - - ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList; - - ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink; - NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; - ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList; - while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { - ImageRecordCodeSection = CR ( - ImageRecordCodeSectionLink, - IMAGE_PROPERTIES_RECORD_CODE_SECTION, - Link, - IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE - ); - while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { - NextImageRecordCodeSection = CR ( - NextImageRecordCodeSectionLink, - IMAGE_PROPERTIES_RECORD_CODE_SECTION, - Link, - IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE - ); - if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) { - SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection); - } - NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink; - } - - ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; - NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; - } -} - -/** - Check if code section in image record is valid. - - @param ImageRecord image record to be checked - - @retval TRUE image record is valid - @retval FALSE image record is invalid -**/ -BOOLEAN -IsImageRecordCodeSectionValid ( - IN IMAGE_PROPERTIES_RECORD *ImageRecord - ) -{ - IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; - IMAGE_PROPERTIES_RECORD_CODE_SECTION *LastImageRecordCodeSection; - LIST_ENTRY *ImageRecordCodeSectionLink; - LIST_ENTRY *ImageRecordCodeSectionEndLink; - LIST_ENTRY *ImageRecordCodeSectionList; - - DEBUG ((EFI_D_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount)); - - ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList; - - ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink; - ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList; - LastImageRecordCodeSection = NULL; - while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) { - ImageRecordCodeSection = CR ( - ImageRecordCodeSectionLink, - IMAGE_PROPERTIES_RECORD_CODE_SECTION, - Link, - IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE - ); - if (ImageRecordCodeSection->CodeSegmentSize == 0) { - return FALSE; - } - if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) { - return FALSE; - } - if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) { - return FALSE; - } - if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) { - return FALSE; - } - if (LastImageRecordCodeSection != NULL) { - if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) { - return FALSE; - } - } - - LastImageRecordCodeSection = ImageRecordCodeSection; - ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink; - } - - return TRUE; -} - -/** - Swap two image records. - - @param FirstImageRecord first image record. - @param SecondImageRecord second image record. -**/ -STATIC -VOID -SwapImageRecord ( - IN IMAGE_PROPERTIES_RECORD *FirstImageRecord, - IN IMAGE_PROPERTIES_RECORD *SecondImageRecord - ) -{ - IMAGE_PROPERTIES_RECORD TempImageRecord; - - TempImageRecord.ImageBase = FirstImageRecord->ImageBase; - TempImageRecord.ImageSize = FirstImageRecord->ImageSize; - TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount; - - FirstImageRecord->ImageBase = SecondImageRecord->ImageBase; - FirstImageRecord->ImageSize = SecondImageRecord->ImageSize; - FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount; - - SecondImageRecord->ImageBase = TempImageRecord.ImageBase; - SecondImageRecord->ImageSize = TempImageRecord.ImageSize; - SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount; - - SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList); -} - -/** - Sort image record based upon the ImageBase from low to high. -**/ -STATIC -VOID -SortImageRecord ( - VOID - ) -{ - IMAGE_PROPERTIES_RECORD *ImageRecord; - IMAGE_PROPERTIES_RECORD *NextImageRecord; - LIST_ENTRY *ImageRecordLink; - LIST_ENTRY *NextImageRecordLink; - LIST_ENTRY *ImageRecordEndLink; - LIST_ENTRY *ImageRecordList; - - ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList; - - ImageRecordLink = ImageRecordList->ForwardLink; - NextImageRecordLink = ImageRecordLink->ForwardLink; - ImageRecordEndLink = ImageRecordList; - while (ImageRecordLink != ImageRecordEndLink) { - ImageRecord = CR ( - ImageRecordLink, - IMAGE_PROPERTIES_RECORD, - Link, - IMAGE_PROPERTIES_RECORD_SIGNATURE - ); - while (NextImageRecordLink != ImageRecordEndLink) { - NextImageRecord = CR ( - NextImageRecordLink, - IMAGE_PROPERTIES_RECORD, - Link, - IMAGE_PROPERTIES_RECORD_SIGNATURE - ); - if (ImageRecord->ImageBase > NextImageRecord->ImageBase) { - SwapImageRecord (ImageRecord, NextImageRecord); - } - NextImageRecordLink = NextImageRecordLink->ForwardLink; - } - - ImageRecordLink = ImageRecordLink->ForwardLink; - NextImageRecordLink = ImageRecordLink->ForwardLink; - } -} - -/** - Insert image record. - - @param RuntimeImage Runtime image information -**/ -VOID -InsertImageRecord ( - IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage - ) -{ - VOID *ImageAddress; - EFI_IMAGE_DOS_HEADER *DosHdr; - UINT32 PeCoffHeaderOffset; - UINT32 SectionAlignment; - EFI_IMAGE_SECTION_HEADER *Section; - EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; - UINT8 *Name; - UINTN Index; - IMAGE_PROPERTIES_RECORD *ImageRecord; - CHAR8 *PdbPointer; - IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; - - DEBUG ((EFI_D_VERBOSE, "InsertImageRecord - 0x%x\n", RuntimeImage)); - DEBUG ((EFI_D_VERBOSE, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize)); - - if (mPropertiesTableEndOfDxe) { - DEBUG ((DEBUG_INFO, "Do not insert runtime image record after EndOfDxe\n")); - return ; - } - - ImageRecord = AllocatePool (sizeof(*ImageRecord)); - if (ImageRecord == NULL) { - return ; - } - ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE; - - DEBUG ((EFI_D_VERBOSE, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount)); - - // - // Step 1: record whole region - // - ImageRecord->ImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase; - ImageRecord->ImageSize = RuntimeImage->ImageSize; - - ImageAddress = RuntimeImage->ImageBase; - - PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress); - if (PdbPointer != NULL) { - DEBUG ((EFI_D_VERBOSE, " Image - %a\n", PdbPointer)); - } - - // - // Check PE/COFF image - // - DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress; - PeCoffHeaderOffset = 0; - if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { - PeCoffHeaderOffset = DosHdr->e_lfanew; - } - - Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset); - if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) { - DEBUG ((EFI_D_VERBOSE, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature)); - // It might be image in SMM. - goto Finish; - } - - // - // Get SectionAlignment - // - if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment; - } else { - SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment; - } - - SetPropertiesTableSectionAlignment (SectionAlignment); - if ((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) { - DEBUG ((EFI_D_WARN, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n", - SectionAlignment, RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10)); - PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress); - if (PdbPointer != NULL) { - DEBUG ((EFI_D_WARN, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer)); - } - goto Finish; - } - - Section = (EFI_IMAGE_SECTION_HEADER *) ( - (UINT8 *) (UINTN) ImageAddress + - PeCoffHeaderOffset + - sizeof(UINT32) + - sizeof(EFI_IMAGE_FILE_HEADER) + - Hdr.Pe32->FileHeader.SizeOfOptionalHeader - ); - ImageRecord->CodeSegmentCount = 0; - InitializeListHead (&ImageRecord->CodeSegmentList); - for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) { - Name = Section[Index].Name; - DEBUG (( - EFI_D_VERBOSE, - " Section - '%c%c%c%c%c%c%c%c'\n", - Name[0], - Name[1], - Name[2], - Name[3], - Name[4], - Name[5], - Name[6], - Name[7] - )); - - if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) { - DEBUG ((EFI_D_VERBOSE, " VirtualSize - 0x%08x\n", Section[Index].Misc.VirtualSize)); - DEBUG ((EFI_D_VERBOSE, " VirtualAddress - 0x%08x\n", Section[Index].VirtualAddress)); - DEBUG ((EFI_D_VERBOSE, " SizeOfRawData - 0x%08x\n", Section[Index].SizeOfRawData)); - DEBUG ((EFI_D_VERBOSE, " PointerToRawData - 0x%08x\n", Section[Index].PointerToRawData)); - DEBUG ((EFI_D_VERBOSE, " PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations)); - DEBUG ((EFI_D_VERBOSE, " PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers)); - DEBUG ((EFI_D_VERBOSE, " NumberOfRelocations - 0x%08x\n", Section[Index].NumberOfRelocations)); - DEBUG ((EFI_D_VERBOSE, " NumberOfLinenumbers - 0x%08x\n", Section[Index].NumberOfLinenumbers)); - DEBUG ((EFI_D_VERBOSE, " Characteristics - 0x%08x\n", Section[Index].Characteristics)); - - // - // Step 2: record code section - // - ImageRecordCodeSection = AllocatePool (sizeof(*ImageRecordCodeSection)); - if (ImageRecordCodeSection == NULL) { - return ; - } - ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE; - - ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress; - ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData; - - DEBUG ((EFI_D_VERBOSE, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize)); - - InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link); - ImageRecord->CodeSegmentCount++; - } - } - - if (ImageRecord->CodeSegmentCount == 0) { - SetPropertiesTableSectionAlignment (1); - DEBUG ((EFI_D_ERROR, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n")); - PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress); - if (PdbPointer != NULL) { - DEBUG ((EFI_D_ERROR, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer)); - } - goto Finish; - } - - // - // Final - // - SortImageRecordCodeSection (ImageRecord); - // - // Check overlap all section in ImageBase/Size - // - if (!IsImageRecordCodeSectionValid (ImageRecord)) { - DEBUG ((EFI_D_ERROR, "IsImageRecordCodeSectionValid - FAIL\n")); - goto Finish; - } - - InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link); - mImagePropertiesPrivateData.ImageRecordCount++; - - if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) { - mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount; - } - - SortImageRecord (); - -Finish: - return ; -} - -/** - Find image record according to image base and size. - - @param ImageBase Base of PE image - @param ImageSize Size of PE image - - @return image record -**/ -STATIC -IMAGE_PROPERTIES_RECORD * -FindImageRecord ( - IN EFI_PHYSICAL_ADDRESS ImageBase, - IN UINT64 ImageSize - ) -{ - IMAGE_PROPERTIES_RECORD *ImageRecord; - LIST_ENTRY *ImageRecordLink; - LIST_ENTRY *ImageRecordList; - - ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList; - - for (ImageRecordLink = ImageRecordList->ForwardLink; - ImageRecordLink != ImageRecordList; - ImageRecordLink = ImageRecordLink->ForwardLink) { - ImageRecord = CR ( - ImageRecordLink, - IMAGE_PROPERTIES_RECORD, - Link, - IMAGE_PROPERTIES_RECORD_SIGNATURE - ); - - if ((ImageBase == ImageRecord->ImageBase) && - (ImageSize == ImageRecord->ImageSize)) { - return ImageRecord; - } - } - - return NULL; -} - -/** - Remove Image record. - - @param RuntimeImage Runtime image information -**/ -VOID -RemoveImageRecord ( - IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage - ) -{ - IMAGE_PROPERTIES_RECORD *ImageRecord; - LIST_ENTRY *CodeSegmentListHead; - IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection; - - DEBUG ((EFI_D_VERBOSE, "RemoveImageRecord - 0x%x\n", RuntimeImage)); - DEBUG ((EFI_D_VERBOSE, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize)); - - if (mPropertiesTableEndOfDxe) { - DEBUG ((DEBUG_INFO, "Do not remove runtime image record after EndOfDxe\n")); - return ; - } - - ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize); - if (ImageRecord == NULL) { - DEBUG ((EFI_D_ERROR, "!!!!!!!! ImageRecord not found !!!!!!!!\n")); - return ; - } - - CodeSegmentListHead = &ImageRecord->CodeSegmentList; - while (!IsListEmpty (CodeSegmentListHead)) { - ImageRecordCodeSection = CR ( - CodeSegmentListHead->ForwardLink, - IMAGE_PROPERTIES_RECORD_CODE_SECTION, - Link, - IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE - ); - RemoveEntryList (&ImageRecordCodeSection->Link); - FreePool (ImageRecordCodeSection); - } - - RemoveEntryList (&ImageRecord->Link); - FreePool (ImageRecord); - mImagePropertiesPrivateData.ImageRecordCount--; -} - - -/** - Install PropertiesTable. - - @param[in] Event The Event this notify function registered to. - @param[in] Context Pointer to the context data registered to the Event. -**/ -VOID -EFIAPI -InstallPropertiesTable ( - EFI_EVENT Event, - VOID *Context - ) -{ - mPropertiesTableEndOfDxe = TRUE; -} - -/** - Initialize PropertiesTable support. -**/ -VOID -EFIAPI -CoreInitializePropertiesTable ( - VOID - ) -{ - EFI_STATUS Status; - EFI_EVENT EndOfDxeEvent; - - Status = gBS->CreateEventEx ( - EVT_NOTIFY_SIGNAL, - TPL_NOTIFY, - InstallPropertiesTable, - NULL, - &gEfiEndOfDxeEventGroupGuid, - &EndOfDxeEvent - ); - ASSERT_EFI_ERROR (Status); - return ; -}