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