mirror of https://github.com/acidanthera/audk.git
MdeModulePkg: Move Some DXE MAT Logic to ImagePropertiesRecordLib
Move some DXE MAT logic to ImagePropertiesRecordLib to consolidate code and enable unit testability. Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Dandan Bi <dandan.bi@intel.com> Signed-off-by: Taylor Beebe <taylor.d.beebe@gmail.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
This commit is contained in:
parent
561362368b
commit
7284c44951
|
@ -228,26 +228,6 @@ typedef struct {
|
||||||
#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
|
#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \
|
||||||
CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE)
|
CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE)
|
||||||
|
|
||||||
#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I','P','R','C')
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
UINT32 Signature;
|
|
||||||
LIST_ENTRY Link;
|
|
||||||
EFI_PHYSICAL_ADDRESS CodeSegmentBase;
|
|
||||||
UINT64 CodeSegmentSize;
|
|
||||||
} IMAGE_PROPERTIES_RECORD_CODE_SECTION;
|
|
||||||
|
|
||||||
#define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D')
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
UINT32 Signature;
|
|
||||||
LIST_ENTRY Link;
|
|
||||||
EFI_PHYSICAL_ADDRESS ImageBase;
|
|
||||||
UINT64 ImageSize;
|
|
||||||
UINTN CodeSegmentCount;
|
|
||||||
LIST_ENTRY CodeSegmentList;
|
|
||||||
} IMAGE_PROPERTIES_RECORD;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// DXE Core Global Variables
|
// DXE Core Global Variables
|
||||||
//
|
//
|
||||||
|
|
|
@ -94,6 +94,7 @@
|
||||||
DebugAgentLib
|
DebugAgentLib
|
||||||
CpuExceptionHandlerLib
|
CpuExceptionHandlerLib
|
||||||
PcdLib
|
PcdLib
|
||||||
|
ImagePropertiesRecordLib
|
||||||
|
|
||||||
[Guids]
|
[Guids]
|
||||||
gEfiEventMemoryMapChangeGuid ## PRODUCES ## Event
|
gEfiEventMemoryMapChangeGuid ## PRODUCES ## Event
|
||||||
|
|
|
@ -14,6 +14,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
#include <Library/DxeServicesTableLib.h>
|
#include <Library/DxeServicesTableLib.h>
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
#include <Library/UefiLib.h>
|
#include <Library/UefiLib.h>
|
||||||
|
#include <Library/ImagePropertiesRecordLib.h>
|
||||||
|
|
||||||
#include <Guid/EventGroup.h>
|
#include <Guid/EventGroup.h>
|
||||||
|
|
||||||
|
@ -333,45 +334,6 @@ CoreInitializeMemoryAttributesTable (
|
||||||
// Below functions are for MemoryMap
|
// 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.
|
Acquire memory lock on mMemoryAttributesTableLock.
|
||||||
**/
|
**/
|
||||||
|
@ -396,48 +358,6 @@ CoreReleasemMemoryAttributesTableLock (
|
||||||
CoreReleaseLock (&mMemoryAttributesTableLock);
|
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.
|
Merge continous memory map entries whose have same attributes.
|
||||||
|
|
||||||
|
@ -471,7 +391,7 @@ MergeMemoryMap (
|
||||||
|
|
||||||
do {
|
do {
|
||||||
MergeGuardPages (NewMemoryMapEntry, NextMemoryMapEntry->PhysicalStart);
|
MergeGuardPages (NewMemoryMapEntry, NextMemoryMapEntry->PhysicalStart);
|
||||||
MemoryBlockLength = (UINT64)(EfiPagesToSize (NewMemoryMapEntry->NumberOfPages));
|
MemoryBlockLength = LShiftU64 (NewMemoryMapEntry->NumberOfPages, EFI_PAGE_SHIFT);
|
||||||
if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
|
if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
|
||||||
(NewMemoryMapEntry->Type == NextMemoryMapEntry->Type) &&
|
(NewMemoryMapEntry->Type == NextMemoryMapEntry->Type) &&
|
||||||
(NewMemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) &&
|
(NewMemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) &&
|
||||||
|
@ -538,434 +458,6 @@ EnforceMemoryMapAttribute (
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
|
|
||||||
|
|
||||||
@param Buffer Start Address
|
|
||||||
@param Length Address length
|
|
||||||
@param ImageRecordList Image record list
|
|
||||||
|
|
||||||
@return first image record covered by [buffer, length]
|
|
||||||
**/
|
|
||||||
STATIC
|
|
||||||
IMAGE_PROPERTIES_RECORD *
|
|
||||||
GetImageRecordByAddress (
|
|
||||||
IN EFI_PHYSICAL_ADDRESS Buffer,
|
|
||||||
IN UINT64 Length,
|
|
||||||
IN LIST_ENTRY *ImageRecordList
|
|
||||||
)
|
|
||||||
{
|
|
||||||
IMAGE_PROPERTIES_RECORD *ImageRecord;
|
|
||||||
LIST_ENTRY *ImageRecordLink;
|
|
||||||
|
|
||||||
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,
|
|
||||||
IN LIST_ENTRY *ImageRecordList
|
|
||||||
)
|
|
||||||
{
|
|
||||||
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, ImageRecordList);
|
|
||||||
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.
|
|
||||||
@param ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries used when searching
|
|
||||||
for an image record contained by the memory range described in
|
|
||||||
the existing EFI memory map descriptor OldRecord
|
|
||||||
|
|
||||||
@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,
|
|
||||||
IN LIST_ENTRY *ImageRecordList
|
|
||||||
)
|
|
||||||
{
|
|
||||||
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, ImageRecordList);
|
|
||||||
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.
|
|
||||||
@param ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries used when searching
|
|
||||||
for an image record contained by the memory range described in
|
|
||||||
EFI memory map descriptors.
|
|
||||||
@param NumberOfAdditionalDescriptors The number of unused descriptors at the end of the input MemoryMap.
|
|
||||||
**/
|
|
||||||
STATIC
|
|
||||||
VOID
|
|
||||||
SplitTable (
|
|
||||||
IN OUT UINTN *MemoryMapSize,
|
|
||||||
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
|
|
||||||
IN UINTN DescriptorSize,
|
|
||||||
IN LIST_ENTRY *ImageRecordList,
|
|
||||||
IN UINTN NumberOfAdditionalDescriptors
|
|
||||||
)
|
|
||||||
{
|
|
||||||
INTN IndexOld;
|
|
||||||
INTN IndexNew;
|
|
||||||
UINTN MaxSplitRecordCount;
|
|
||||||
UINTN RealSplitRecordCount;
|
|
||||||
UINTN TotalSplitRecordCount;
|
|
||||||
|
|
||||||
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 + NumberOfAdditionalDescriptors;
|
|
||||||
for ( ; IndexOld >= 0; IndexOld--) {
|
|
||||||
MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), ImageRecordList);
|
|
||||||
//
|
|
||||||
// Split this MemoryMap record
|
|
||||||
//
|
|
||||||
IndexNew -= MaxSplitRecordCount;
|
|
||||||
RealSplitRecordCount = SplitRecord (
|
|
||||||
(EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),
|
|
||||||
(EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
|
|
||||||
MaxSplitRecordCount,
|
|
||||||
DescriptorSize,
|
|
||||||
ImageRecordList
|
|
||||||
);
|
|
||||||
//
|
|
||||||
// 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 + (NumberOfAdditionalDescriptors - 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.
|
This function for GetMemoryMap() with properties table capability.
|
||||||
|
|
||||||
|
@ -1044,6 +536,16 @@ CoreGetMemoryMapWithSeparatedImageSection (
|
||||||
// Split PE code/data
|
// Split PE code/data
|
||||||
//
|
//
|
||||||
SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize, &mImagePropertiesPrivateData.ImageRecordList, AdditionalRecordCount);
|
SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize, &mImagePropertiesPrivateData.ImageRecordList, AdditionalRecordCount);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set RuntimeData to XP
|
||||||
|
//
|
||||||
|
EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, *DescriptorSize);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Merge same type to save entry size
|
||||||
|
//
|
||||||
|
MergeMemoryMap (MemoryMap, MemoryMapSize, *DescriptorSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1074,217 +576,6 @@ SetMemoryAttributesTableSectionAlignment (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
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.
|
|
||||||
|
|
||||||
@param ImageRecordList Image record list to be sorted
|
|
||||||
**/
|
|
||||||
STATIC
|
|
||||||
VOID
|
|
||||||
SortImageRecord (
|
|
||||||
IN LIST_ENTRY *ImageRecordList
|
|
||||||
)
|
|
||||||
{
|
|
||||||
IMAGE_PROPERTIES_RECORD *ImageRecord;
|
|
||||||
IMAGE_PROPERTIES_RECORD *NextImageRecord;
|
|
||||||
LIST_ENTRY *ImageRecordLink;
|
|
||||||
LIST_ENTRY *NextImageRecordLink;
|
|
||||||
LIST_ENTRY *ImageRecordEndLink;
|
|
||||||
|
|
||||||
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.
|
Insert image record.
|
||||||
|
|
||||||
|
@ -1469,47 +760,6 @@ Finish:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Find image record according to image base and size.
|
|
||||||
|
|
||||||
@param ImageBase Base of PE image
|
|
||||||
@param ImageSize Size of PE image
|
|
||||||
@param ImageRecordList Image record list to be searched
|
|
||||||
|
|
||||||
@return image record
|
|
||||||
**/
|
|
||||||
STATIC
|
|
||||||
IMAGE_PROPERTIES_RECORD *
|
|
||||||
FindImageRecord (
|
|
||||||
IN EFI_PHYSICAL_ADDRESS ImageBase,
|
|
||||||
IN UINT64 ImageSize,
|
|
||||||
IN LIST_ENTRY *ImageRecordList
|
|
||||||
)
|
|
||||||
{
|
|
||||||
IMAGE_PROPERTIES_RECORD *ImageRecord;
|
|
||||||
LIST_ENTRY *ImageRecordLink;
|
|
||||||
|
|
||||||
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.
|
Remove Image record.
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
#include <Library/DxeServicesTableLib.h>
|
#include <Library/DxeServicesTableLib.h>
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
#include <Library/UefiLib.h>
|
#include <Library/UefiLib.h>
|
||||||
|
#include <Library/ImagePropertiesRecordLib.h>
|
||||||
|
|
||||||
#include <Guid/EventGroup.h>
|
#include <Guid/EventGroup.h>
|
||||||
#include <Guid/MemoryAttributesTable.h>
|
#include <Guid/MemoryAttributesTable.h>
|
||||||
|
@ -66,29 +67,6 @@ extern LIST_ENTRY mGcdMemorySpaceMap;
|
||||||
|
|
||||||
STATIC LIST_ENTRY mProtectedImageRecordList;
|
STATIC LIST_ENTRY mProtectedImageRecordList;
|
||||||
|
|
||||||
/**
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the image type.
|
Get the image type.
|
||||||
|
|
||||||
|
|
|
@ -11,4 +11,163 @@
|
||||||
#ifndef IMAGE_PROPERTIES_RECORD_SUPPORT_LIB_H_
|
#ifndef IMAGE_PROPERTIES_RECORD_SUPPORT_LIB_H_
|
||||||
#define IMAGE_PROPERTIES_RECORD_SUPPORT_LIB_H_
|
#define IMAGE_PROPERTIES_RECORD_SUPPORT_LIB_H_
|
||||||
|
|
||||||
|
#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I','P','R','C')
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Signature;
|
||||||
|
LIST_ENTRY Link;
|
||||||
|
EFI_PHYSICAL_ADDRESS CodeSegmentBase;
|
||||||
|
UINT64 CodeSegmentSize;
|
||||||
|
} IMAGE_PROPERTIES_RECORD_CODE_SECTION;
|
||||||
|
|
||||||
|
#define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D')
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Signature;
|
||||||
|
LIST_ENTRY Link;
|
||||||
|
EFI_PHYSICAL_ADDRESS ImageBase;
|
||||||
|
UINT64 ImageSize;
|
||||||
|
UINTN CodeSegmentCount;
|
||||||
|
LIST_ENTRY CodeSegmentList;
|
||||||
|
} IMAGE_PROPERTIES_RECORD;
|
||||||
|
|
||||||
|
/**
|
||||||
|
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.
|
||||||
|
@param ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries used when searching
|
||||||
|
for an image record contained by the memory range described in
|
||||||
|
EFI memory map descriptors.
|
||||||
|
@param NumberOfAdditionalDescriptors The number of unused descriptors at the end of the input MemoryMap.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SplitTable (
|
||||||
|
IN OUT UINTN *MemoryMapSize,
|
||||||
|
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
|
||||||
|
IN UINTN DescriptorSize,
|
||||||
|
IN LIST_ENTRY *ImageRecordList,
|
||||||
|
IN UINTN NumberOfAdditionalDescriptors
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sort code section in image record, based upon CodeSegmentBase from low to high.
|
||||||
|
|
||||||
|
@param ImageRecord image record to be sorted
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SortImageRecordCodeSection (
|
||||||
|
IN IMAGE_PROPERTIES_RECORD *ImageRecord
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
EFIAPI
|
||||||
|
IsImageRecordCodeSectionValid (
|
||||||
|
IN IMAGE_PROPERTIES_RECORD *ImageRecord
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sort image record based upon the ImageBase from low to high.
|
||||||
|
|
||||||
|
@param ImageRecordList Image record list to be sorted
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SortImageRecord (
|
||||||
|
IN LIST_ENTRY *ImageRecordList
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Swap two image records.
|
||||||
|
|
||||||
|
@param[in] FirstImageRecord The first image record.
|
||||||
|
@param[in] SecondImageRecord The second image record.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SwapImageRecord (
|
||||||
|
IN IMAGE_PROPERTIES_RECORD *FirstImageRecord,
|
||||||
|
IN IMAGE_PROPERTIES_RECORD *SecondImageRecord
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Swap two code sections in a single IMAGE_PROPERTIES_RECORD.
|
||||||
|
|
||||||
|
@param[in] FirstImageRecordCodeSection The first code section
|
||||||
|
@param[in] SecondImageRecordCodeSection The second code section
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SwapImageRecordCodeSection (
|
||||||
|
IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *FirstImageRecordCodeSection,
|
||||||
|
IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *SecondImageRecordCodeSection
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Find image record according to image base and size.
|
||||||
|
|
||||||
|
@param ImageBase Base of PE image
|
||||||
|
@param ImageSize Size of PE image
|
||||||
|
@param ImageRecordList Image record list to be searched
|
||||||
|
|
||||||
|
@return image record
|
||||||
|
**/
|
||||||
|
IMAGE_PROPERTIES_RECORD *
|
||||||
|
EFIAPI
|
||||||
|
FindImageRecord (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS ImageBase,
|
||||||
|
IN UINT64 ImageSize,
|
||||||
|
IN LIST_ENTRY *ImageRecordList
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,3 +7,773 @@
|
||||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/ImagePropertiesRecordLib.h>
|
||||||
|
|
||||||
|
#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
|
||||||
|
((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
|
||||||
|
|
||||||
|
#define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
|
||||||
|
((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
|
||||||
|
|
||||||
|
@param Buffer Start Address
|
||||||
|
@param Length Address length
|
||||||
|
@param ImageRecordList Image record list
|
||||||
|
|
||||||
|
@return first image record covered by [buffer, length]
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
IMAGE_PROPERTIES_RECORD *
|
||||||
|
GetImageRecordByAddress (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS Buffer,
|
||||||
|
IN UINT64 Length,
|
||||||
|
IN LIST_ENTRY *ImageRecordList
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IMAGE_PROPERTIES_RECORD *ImageRecord;
|
||||||
|
LIST_ENTRY *ImageRecordLink;
|
||||||
|
|
||||||
|
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.
|
||||||
|
@param ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries used when searching
|
||||||
|
for an image record contained by the memory range described in
|
||||||
|
the existing EFI memory map descriptor OldRecord
|
||||||
|
|
||||||
|
@retval 0 no entry need to be splitted.
|
||||||
|
@return the max number of new splitted entries
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
UINTN
|
||||||
|
GetMaxSplitRecordCount (
|
||||||
|
IN EFI_MEMORY_DESCRIPTOR *OldRecord,
|
||||||
|
IN LIST_ENTRY *ImageRecordList
|
||||||
|
)
|
||||||
|
{
|
||||||
|
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, ImageRecordList);
|
||||||
|
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.
|
||||||
|
@param ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries used when searching
|
||||||
|
for an image record contained by the memory range described in
|
||||||
|
the existing EFI memory map descriptor OldRecord
|
||||||
|
|
||||||
|
@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,
|
||||||
|
IN LIST_ENTRY *ImageRecordList
|
||||||
|
)
|
||||||
|
{
|
||||||
|
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, ImageRecordList);
|
||||||
|
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.
|
||||||
|
@param ImageRecordList A list of IMAGE_PROPERTIES_RECORD entries used when searching
|
||||||
|
for an image record contained by the memory range described in
|
||||||
|
EFI memory map descriptors.
|
||||||
|
@param NumberOfAdditionalDescriptors The number of unused descriptors at the end of the input MemoryMap.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SplitTable (
|
||||||
|
IN OUT UINTN *MemoryMapSize,
|
||||||
|
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
|
||||||
|
IN UINTN DescriptorSize,
|
||||||
|
IN LIST_ENTRY *ImageRecordList,
|
||||||
|
IN UINTN NumberOfAdditionalDescriptors
|
||||||
|
)
|
||||||
|
{
|
||||||
|
INTN IndexOld;
|
||||||
|
INTN IndexNew;
|
||||||
|
UINTN MaxSplitRecordCount;
|
||||||
|
UINTN RealSplitRecordCount;
|
||||||
|
UINTN TotalSplitRecordCount;
|
||||||
|
|
||||||
|
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 + NumberOfAdditionalDescriptors;
|
||||||
|
for ( ; IndexOld >= 0; IndexOld--) {
|
||||||
|
MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), ImageRecordList);
|
||||||
|
//
|
||||||
|
// Split this MemoryMap record
|
||||||
|
//
|
||||||
|
IndexNew -= MaxSplitRecordCount;
|
||||||
|
RealSplitRecordCount = SplitRecord (
|
||||||
|
(EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),
|
||||||
|
(EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
|
||||||
|
MaxSplitRecordCount,
|
||||||
|
DescriptorSize,
|
||||||
|
ImageRecordList
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// 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 + (NumberOfAdditionalDescriptors - TotalSplitRecordCount) * DescriptorSize,
|
||||||
|
(*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize
|
||||||
|
);
|
||||||
|
|
||||||
|
*MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Sort from low to high (Just in case)
|
||||||
|
//
|
||||||
|
SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Swap two code sections in image record.
|
||||||
|
|
||||||
|
@param FirstImageRecordCodeSection first code section in image record
|
||||||
|
@param SecondImageRecordCodeSection second code section in image record
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
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
|
||||||
|
EFIAPI
|
||||||
|
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
|
||||||
|
EFIAPI
|
||||||
|
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.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
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.
|
||||||
|
|
||||||
|
@param ImageRecordList Image record list to be sorted
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
SortImageRecord (
|
||||||
|
IN LIST_ENTRY *ImageRecordList
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IMAGE_PROPERTIES_RECORD *ImageRecord;
|
||||||
|
IMAGE_PROPERTIES_RECORD *NextImageRecord;
|
||||||
|
LIST_ENTRY *ImageRecordLink;
|
||||||
|
LIST_ENTRY *NextImageRecordLink;
|
||||||
|
LIST_ENTRY *ImageRecordEndLink;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Find image record according to image base and size.
|
||||||
|
|
||||||
|
@param ImageBase Base of PE image
|
||||||
|
@param ImageSize Size of PE image
|
||||||
|
@param ImageRecordList Image record list to be searched
|
||||||
|
|
||||||
|
@return image record
|
||||||
|
**/
|
||||||
|
IMAGE_PROPERTIES_RECORD *
|
||||||
|
EFIAPI
|
||||||
|
FindImageRecord (
|
||||||
|
IN EFI_PHYSICAL_ADDRESS ImageBase,
|
||||||
|
IN UINT64 ImageSize,
|
||||||
|
IN LIST_ENTRY *ImageRecordList
|
||||||
|
)
|
||||||
|
{
|
||||||
|
IMAGE_PROPERTIES_RECORD *ImageRecord;
|
||||||
|
LIST_ENTRY *ImageRecordLink;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
[Sources.common]
|
[Sources.common]
|
||||||
ImagePropertiesRecordLib.c
|
ImagePropertiesRecordLib.c
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
BaseLib
|
||||||
|
BaseMemoryLib
|
||||||
|
DebugLib
|
||||||
|
|
||||||
[Packages]
|
[Packages]
|
||||||
MdePkg/MdePkg.dec
|
MdePkg/MdePkg.dec
|
||||||
|
|
Loading…
Reference in New Issue