2 UEFI MemoryAttributesTable support
4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseLib.h>
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/MemoryAllocationLib.h>
13 #include <Library/UefiBootServicesTableLib.h>
14 #include <Library/DxeServicesTableLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/UefiLib.h>
18 #include <Guid/EventGroup.h>
20 #include <Guid/MemoryAttributesTable.h>
23 #include "HeapGuard.h"
26 This function for GetMemoryMap() with properties table capability.
28 It calls original GetMemoryMap() to get the original memory map information. Then
29 plus the additional memory map entries for PE Code/Data seperation.
31 @param MemoryMapSize A pointer to the size, in bytes, of the
32 MemoryMap buffer. On input, this is the size of
33 the buffer allocated by the caller. On output,
34 it is the size of the buffer returned by the
35 firmware if the buffer was large enough, or the
36 size of the buffer needed to contain the map if
37 the buffer was too small.
38 @param MemoryMap A pointer to the buffer in which firmware places
39 the current memory map.
40 @param MapKey A pointer to the location in which firmware
41 returns the key for the current memory map.
42 @param DescriptorSize A pointer to the location in which firmware
43 returns the size, in bytes, of an individual
44 EFI_MEMORY_DESCRIPTOR.
45 @param DescriptorVersion A pointer to the location in which firmware
46 returns the version number associated with the
47 EFI_MEMORY_DESCRIPTOR.
49 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
51 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
52 buffer size needed to hold the memory map is
53 returned in MemoryMapSize.
54 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
59 CoreGetMemoryMapWithSeparatedImageSection (
60 IN OUT UINTN
*MemoryMapSize
,
61 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
63 OUT UINTN
*DescriptorSize
,
64 OUT UINT32
*DescriptorVersion
67 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
68 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
70 #define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')
74 UINTN ImageRecordCount
;
75 UINTN CodeSegmentCountMax
;
76 LIST_ENTRY ImageRecordList
;
77 } IMAGE_PROPERTIES_PRIVATE_DATA
;
79 STATIC IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData
= {
80 IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE
,
83 INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData
.ImageRecordList
)
86 STATIC EFI_LOCK mMemoryAttributesTableLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
88 BOOLEAN mMemoryAttributesTableEnable
= TRUE
;
89 BOOLEAN mMemoryAttributesTableEndOfDxe
= FALSE
;
90 EFI_MEMORY_ATTRIBUTES_TABLE
*mMemoryAttributesTable
= NULL
;
91 BOOLEAN mMemoryAttributesTableReadyToBoot
= FALSE
;
94 Install MemoryAttributesTable.
98 InstallMemoryAttributesTable (
103 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
104 EFI_MEMORY_DESCRIPTOR
*MemoryMapStart
;
106 UINTN DescriptorSize
;
107 UINT32 DescriptorVersion
;
110 UINT32 RuntimeEntryCount
;
111 EFI_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
;
112 EFI_MEMORY_DESCRIPTOR
*MemoryAttributesEntry
;
114 if (gMemoryMapTerminated
) {
116 // Directly return after MemoryMap terminated.
121 if (!mMemoryAttributesTableEnable
) {
122 DEBUG ((DEBUG_VERBOSE
, "Cannot install Memory Attributes Table "));
123 DEBUG ((DEBUG_VERBOSE
, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
127 if (mMemoryAttributesTable
== NULL
) {
129 // InstallConfigurationTable here to occupy one entry for MemoryAttributesTable
130 // before GetMemoryMap below, as InstallConfigurationTable may allocate runtime
131 // memory for the new entry.
133 Status
= gBS
->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid
, (VOID
*)(UINTN
)MAX_ADDRESS
);
134 ASSERT_EFI_ERROR (Status
);
139 Status
= CoreGetMemoryMapWithSeparatedImageSection (
146 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
149 MemoryMap
= AllocatePool (MemoryMapSize
);
150 ASSERT (MemoryMap
!= NULL
);
152 Status
= CoreGetMemoryMapWithSeparatedImageSection (
159 if (EFI_ERROR (Status
)) {
160 FreePool (MemoryMap
);
162 } while (Status
== EFI_BUFFER_TOO_SMALL
);
164 MemoryMapStart
= MemoryMap
;
165 RuntimeEntryCount
= 0;
166 for (Index
= 0; Index
< MemoryMapSize
/DescriptorSize
; Index
++) {
167 switch (MemoryMap
->Type
) {
168 case EfiRuntimeServicesCode
:
169 case EfiRuntimeServicesData
:
174 MemoryMap
= NEXT_MEMORY_DESCRIPTOR (MemoryMap
, DescriptorSize
);
178 // Allocate MemoryAttributesTable
180 MemoryAttributesTable
= AllocatePool (sizeof (EFI_MEMORY_ATTRIBUTES_TABLE
) + DescriptorSize
* RuntimeEntryCount
);
181 ASSERT (MemoryAttributesTable
!= NULL
);
182 MemoryAttributesTable
->Version
= EFI_MEMORY_ATTRIBUTES_TABLE_VERSION
;
183 MemoryAttributesTable
->NumberOfEntries
= RuntimeEntryCount
;
184 MemoryAttributesTable
->DescriptorSize
= (UINT32
)DescriptorSize
;
185 MemoryAttributesTable
->Reserved
= 0;
186 DEBUG ((DEBUG_VERBOSE
, "MemoryAttributesTable:\n"));
187 DEBUG ((DEBUG_VERBOSE
, " Version - 0x%08x\n", MemoryAttributesTable
->Version
));
188 DEBUG ((DEBUG_VERBOSE
, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable
->NumberOfEntries
));
189 DEBUG ((DEBUG_VERBOSE
, " DescriptorSize - 0x%08x\n", MemoryAttributesTable
->DescriptorSize
));
190 MemoryAttributesEntry
= (EFI_MEMORY_DESCRIPTOR
*)(MemoryAttributesTable
+ 1);
191 MemoryMap
= MemoryMapStart
;
192 for (Index
= 0; Index
< MemoryMapSize
/DescriptorSize
; Index
++) {
193 switch (MemoryMap
->Type
) {
194 case EfiRuntimeServicesCode
:
195 case EfiRuntimeServicesData
:
196 CopyMem (MemoryAttributesEntry
, MemoryMap
, DescriptorSize
);
197 MemoryAttributesEntry
->Attribute
&= (EFI_MEMORY_RO
|EFI_MEMORY_XP
|EFI_MEMORY_RUNTIME
);
198 DEBUG ((DEBUG_VERBOSE
, "Entry (0x%x)\n", MemoryAttributesEntry
));
199 DEBUG ((DEBUG_VERBOSE
, " Type - 0x%x\n", MemoryAttributesEntry
->Type
));
200 DEBUG ((DEBUG_VERBOSE
, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry
->PhysicalStart
));
201 DEBUG ((DEBUG_VERBOSE
, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry
->VirtualStart
));
202 DEBUG ((DEBUG_VERBOSE
, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry
->NumberOfPages
));
203 DEBUG ((DEBUG_VERBOSE
, " Attribute - 0x%016lx\n", MemoryAttributesEntry
->Attribute
));
204 MemoryAttributesEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryAttributesEntry
, DescriptorSize
);
208 MemoryMap
= NEXT_MEMORY_DESCRIPTOR (MemoryMap
, DescriptorSize
);
211 MemoryMap
= MemoryMapStart
;
212 FreePool (MemoryMap
);
215 // Update configuratoin table for MemoryAttributesTable.
217 Status
= gBS
->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid
, MemoryAttributesTable
);
218 ASSERT_EFI_ERROR (Status
);
220 if (mMemoryAttributesTable
!= NULL
) {
221 FreePool (mMemoryAttributesTable
);
224 mMemoryAttributesTable
= MemoryAttributesTable
;
228 Install MemoryAttributesTable on memory allocation.
230 @param[in] MemoryType EFI memory type.
233 InstallMemoryAttributesTableOnMemoryAllocation (
234 IN EFI_MEMORY_TYPE MemoryType
238 // Install MemoryAttributesTable after ReadyToBoot on runtime memory allocation.
240 if (mMemoryAttributesTableReadyToBoot
&&
241 ((MemoryType
== EfiRuntimeServicesCode
) || (MemoryType
== EfiRuntimeServicesData
)))
243 InstallMemoryAttributesTable ();
248 Install MemoryAttributesTable on ReadyToBoot.
250 @param[in] Event The Event this notify function registered to.
251 @param[in] Context Pointer to the context data registered to the Event.
255 InstallMemoryAttributesTableOnReadyToBoot (
260 InstallMemoryAttributesTable ();
261 mMemoryAttributesTableReadyToBoot
= TRUE
;
265 Install initial MemoryAttributesTable on EndOfDxe.
266 Then SMM can consume this information.
268 @param[in] Event The Event this notify function registered to.
269 @param[in] Context Pointer to the context data registered to the Event.
273 InstallMemoryAttributesTableOnEndOfDxe (
278 mMemoryAttributesTableEndOfDxe
= TRUE
;
279 InstallMemoryAttributesTable ();
283 Initialize MemoryAttrubutesTable support.
287 CoreInitializeMemoryAttributesTable (
292 EFI_EVENT ReadyToBootEvent
;
293 EFI_EVENT EndOfDxeEvent
;
296 // Construct the table at ReadyToBoot.
298 Status
= CoreCreateEventInternal (
301 InstallMemoryAttributesTableOnReadyToBoot
,
303 &gEfiEventReadyToBootGuid
,
306 ASSERT_EFI_ERROR (Status
);
309 // Construct the initial table at EndOfDxe,
310 // then SMM can consume this information.
311 // Use TPL_NOTIFY here, as such SMM code (TPL_CALLBACK)
314 Status
= CoreCreateEventInternal (
317 InstallMemoryAttributesTableOnEndOfDxe
,
319 &gEfiEndOfDxeEventGroupGuid
,
322 ASSERT_EFI_ERROR (Status
);
327 // Below functions are for MemoryMap
331 Converts a number of EFI_PAGEs to a size in bytes.
333 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
335 @param Pages The number of EFI_PAGES.
337 @return The number of bytes associated with the number of EFI_PAGEs specified
346 return LShiftU64 (Pages
, EFI_PAGE_SHIFT
);
350 Converts a size, in bytes, to a number of EFI_PAGESs.
352 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
354 @param Size A size in bytes.
356 @return The number of EFI_PAGESs associated with the number of bytes specified
366 return RShiftU64 (Size
, EFI_PAGE_SHIFT
) + ((((UINTN
)Size
) & EFI_PAGE_MASK
) ? 1 : 0);
370 Acquire memory lock on mMemoryAttributesTableLock.
374 CoreAcquiremMemoryAttributesTableLock (
378 CoreAcquireLock (&mMemoryAttributesTableLock
);
382 Release memory lock on mMemoryAttributesTableLock.
386 CoreReleasemMemoryAttributesTableLock (
390 CoreReleaseLock (&mMemoryAttributesTableLock
);
394 Sort memory map entries based upon PhysicalStart, from low to high.
396 @param MemoryMap A pointer to the buffer in which firmware places
397 the current memory map.
398 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
399 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
404 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
405 IN UINTN MemoryMapSize
,
406 IN UINTN DescriptorSize
409 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
410 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
411 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
412 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
414 MemoryMapEntry
= MemoryMap
;
415 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
416 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ MemoryMapSize
);
417 while (MemoryMapEntry
< MemoryMapEnd
) {
418 while (NextMemoryMapEntry
< MemoryMapEnd
) {
419 if (MemoryMapEntry
->PhysicalStart
> NextMemoryMapEntry
->PhysicalStart
) {
420 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof (EFI_MEMORY_DESCRIPTOR
));
421 CopyMem (MemoryMapEntry
, NextMemoryMapEntry
, sizeof (EFI_MEMORY_DESCRIPTOR
));
422 CopyMem (NextMemoryMapEntry
, &TempMemoryMap
, sizeof (EFI_MEMORY_DESCRIPTOR
));
425 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
428 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
429 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
436 Merge continous memory map entries whose have same attributes.
438 @param MemoryMap A pointer to the buffer in which firmware places
439 the current memory map.
440 @param MemoryMapSize A pointer to the size, in bytes, of the
441 MemoryMap buffer. On input, this is the size of
442 the current memory map. On output,
443 it is the size of new memory map after merge.
444 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
448 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
449 IN OUT UINTN
*MemoryMapSize
,
450 IN UINTN DescriptorSize
453 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
454 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
455 UINT64 MemoryBlockLength
;
456 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
457 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
459 MemoryMapEntry
= MemoryMap
;
460 NewMemoryMapEntry
= MemoryMap
;
461 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ *MemoryMapSize
);
462 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
463 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof (EFI_MEMORY_DESCRIPTOR
));
464 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
467 MergeGuardPages (NewMemoryMapEntry
, NextMemoryMapEntry
->PhysicalStart
);
468 MemoryBlockLength
= (UINT64
)(EfiPagesToSize (NewMemoryMapEntry
->NumberOfPages
));
469 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
470 (NewMemoryMapEntry
->Type
== NextMemoryMapEntry
->Type
) &&
471 (NewMemoryMapEntry
->Attribute
== NextMemoryMapEntry
->Attribute
) &&
472 ((NewMemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
) == NextMemoryMapEntry
->PhysicalStart
))
474 NewMemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
475 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
478 MemoryMapEntry
= PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
483 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
484 NewMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry
, DescriptorSize
);
487 *MemoryMapSize
= (UINTN
)NewMemoryMapEntry
- (UINTN
)MemoryMap
;
493 Enforce memory map attributes.
494 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
496 @param MemoryMap A pointer to the buffer in which firmware places
497 the current memory map.
498 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
499 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
503 EnforceMemoryMapAttribute (
504 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
505 IN UINTN MemoryMapSize
,
506 IN UINTN DescriptorSize
509 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
510 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
512 MemoryMapEntry
= MemoryMap
;
513 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ MemoryMapSize
);
514 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
515 switch (MemoryMapEntry
->Type
) {
516 case EfiRuntimeServicesCode
:
519 case EfiRuntimeServicesData
:
520 case EfiMemoryMappedIO
:
521 case EfiMemoryMappedIOPortSpace
:
522 MemoryMapEntry
->Attribute
|= EFI_MEMORY_XP
;
524 case EfiReservedMemoryType
:
525 case EfiACPIMemoryNVS
:
529 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
536 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
538 @param Buffer Start Address
539 @param Length Address length
541 @return first image record covered by [buffer, length]
544 IMAGE_PROPERTIES_RECORD
*
545 GetImageRecordByAddress (
546 IN EFI_PHYSICAL_ADDRESS Buffer
,
550 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
551 LIST_ENTRY
*ImageRecordLink
;
552 LIST_ENTRY
*ImageRecordList
;
554 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
556 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
557 ImageRecordLink
!= ImageRecordList
;
558 ImageRecordLink
= ImageRecordLink
->ForwardLink
)
562 IMAGE_PROPERTIES_RECORD
,
564 IMAGE_PROPERTIES_RECORD_SIGNATURE
567 if ((Buffer
<= ImageRecord
->ImageBase
) &&
568 (Buffer
+ Length
>= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
))
578 Set the memory map to new entries, according to one old entry,
579 based upon PE code section and data section in image record
581 @param ImageRecord An image record whose [ImageBase, ImageSize] covered
582 by old memory map entry.
583 @param NewRecord A pointer to several new memory map entries.
584 The caller gurantee the buffer size be 1 +
585 (SplitRecordCount * DescriptorSize) calculated
587 @param OldRecord A pointer to one old memory map entry.
588 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
593 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
,
594 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
595 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
596 IN UINTN DescriptorSize
599 EFI_MEMORY_DESCRIPTOR TempRecord
;
600 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
601 LIST_ENTRY
*ImageRecordCodeSectionLink
;
602 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
603 LIST_ENTRY
*ImageRecordCodeSectionList
;
604 UINTN NewRecordCount
;
608 CopyMem (&TempRecord
, OldRecord
, sizeof (EFI_MEMORY_DESCRIPTOR
));
609 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize (TempRecord
.NumberOfPages
);
612 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
614 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
615 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
616 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
617 ImageRecordCodeSection
= CR (
618 ImageRecordCodeSectionLink
,
619 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
621 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
623 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
625 if (TempRecord
.PhysicalStart
<= ImageRecordCodeSection
->CodeSegmentBase
) {
629 NewRecord
->Type
= TempRecord
.Type
;
630 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
631 NewRecord
->VirtualStart
= 0;
632 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageRecordCodeSection
->CodeSegmentBase
- NewRecord
->PhysicalStart
);
633 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
634 if (NewRecord
->NumberOfPages
!= 0) {
635 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
642 NewRecord
->Type
= TempRecord
.Type
;
643 NewRecord
->PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
;
644 NewRecord
->VirtualStart
= 0;
645 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageRecordCodeSection
->CodeSegmentSize
);
646 NewRecord
->Attribute
= (TempRecord
.Attribute
& (~EFI_MEMORY_XP
)) | EFI_MEMORY_RO
;
647 if (NewRecord
->NumberOfPages
!= 0) {
648 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
652 TempRecord
.PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
+ EfiPagesToSize (EfiSizeToPages (ImageRecordCodeSection
->CodeSegmentSize
));
653 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- TempRecord
.PhysicalStart
);
654 if (TempRecord
.NumberOfPages
== 0) {
660 ImageEnd
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
665 if (TempRecord
.PhysicalStart
< ImageEnd
) {
666 NewRecord
->Type
= TempRecord
.Type
;
667 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
668 NewRecord
->VirtualStart
= 0;
669 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageEnd
- TempRecord
.PhysicalStart
);
670 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
674 return NewRecordCount
;
678 Return the max number of new splitted entries, according to one old entry,
679 based upon PE code section and data section.
681 @param OldRecord A pointer to one old memory map entry.
683 @retval 0 no entry need to be splitted.
684 @return the max number of new splitted entries
688 GetMaxSplitRecordCount (
689 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
692 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
693 UINTN SplitRecordCount
;
694 UINT64 PhysicalStart
;
697 SplitRecordCount
= 0;
698 PhysicalStart
= OldRecord
->PhysicalStart
;
699 PhysicalEnd
= OldRecord
->PhysicalStart
+ EfiPagesToSize (OldRecord
->NumberOfPages
);
702 ImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
703 if (ImageRecord
== NULL
) {
707 SplitRecordCount
+= (2 * ImageRecord
->CodeSegmentCount
+ 1);
708 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
709 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
711 if (SplitRecordCount
!= 0) {
715 return SplitRecordCount
;
719 Split the memory map to new entries, according to one old entry,
720 based upon PE code section and data section.
722 @param OldRecord A pointer to one old memory map entry.
723 @param NewRecord A pointer to several new memory map entries.
724 The caller gurantee the buffer size be 1 +
725 (SplitRecordCount * DescriptorSize) calculated
727 @param MaxSplitRecordCount The max number of splitted entries
728 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
730 @retval 0 no entry is splitted.
731 @return the real number of splitted record.
736 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
737 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
738 IN UINTN MaxSplitRecordCount
,
739 IN UINTN DescriptorSize
742 EFI_MEMORY_DESCRIPTOR TempRecord
;
743 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
744 IMAGE_PROPERTIES_RECORD
*NewImageRecord
;
745 UINT64 PhysicalStart
;
747 UINTN NewRecordCount
;
748 UINTN TotalNewRecordCount
;
749 BOOLEAN IsLastRecordData
;
751 if (MaxSplitRecordCount
== 0) {
752 CopyMem (NewRecord
, OldRecord
, DescriptorSize
);
756 TotalNewRecordCount
= 0;
759 // Override previous record
761 CopyMem (&TempRecord
, OldRecord
, sizeof (EFI_MEMORY_DESCRIPTOR
));
762 PhysicalStart
= TempRecord
.PhysicalStart
;
763 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize (TempRecord
.NumberOfPages
);
767 NewImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
768 if (NewImageRecord
== NULL
) {
770 // No more image covered by this range, stop
772 if ((PhysicalEnd
> PhysicalStart
) && (ImageRecord
!= NULL
)) {
774 // If this is still address in this record, need record.
776 NewRecord
= PREVIOUS_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
777 IsLastRecordData
= FALSE
;
778 if ((NewRecord
->Attribute
& EFI_MEMORY_XP
) != 0) {
779 IsLastRecordData
= TRUE
;
782 if (IsLastRecordData
) {
784 // Last record is DATA, just merge it.
786 NewRecord
->NumberOfPages
= EfiSizeToPages (PhysicalEnd
- NewRecord
->PhysicalStart
);
789 // Last record is CODE, create a new DATA entry.
791 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
792 NewRecord
->Type
= TempRecord
.Type
;
793 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
794 NewRecord
->VirtualStart
= 0;
795 NewRecord
->NumberOfPages
= TempRecord
.NumberOfPages
;
796 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
797 TotalNewRecordCount
++;
804 ImageRecord
= NewImageRecord
;
809 NewRecordCount
= SetNewRecord (ImageRecord
, NewRecord
, &TempRecord
, DescriptorSize
);
810 TotalNewRecordCount
+= NewRecordCount
;
811 NewRecord
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)NewRecord
+ NewRecordCount
* DescriptorSize
);
814 // Update PhysicalStart, in order to exclude the image buffer already splitted.
816 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
817 TempRecord
.PhysicalStart
= PhysicalStart
;
818 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- PhysicalStart
);
819 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
822 // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the
823 // code reaches here.
825 ASSERT (TotalNewRecordCount
!= 0);
826 return TotalNewRecordCount
- 1;
830 Split the original memory map, and add more entries to describe PE code section and data section.
831 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
832 This function will merge entries with same attributes finally.
834 NOTE: It assumes PE code/data section are page aligned.
835 NOTE: It assumes enough entry is prepared for new memory map.
848 +---------------+ ----
851 | Record RtCode | |-> PE/COFF1
854 +---------------+ ----
857 | Record RtCode | |-> PE/COFF2
860 +---------------+ ----
864 @param MemoryMapSize A pointer to the size, in bytes, of the
865 MemoryMap buffer. On input, this is the size of
866 old MemoryMap before split. The actual buffer
867 size of MemoryMap is MemoryMapSize +
868 (AdditionalRecordCount * DescriptorSize) calculated
869 below. On output, it is the size of new MemoryMap
871 @param MemoryMap A pointer to the buffer in which firmware places
872 the current memory map.
873 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
878 IN OUT UINTN
*MemoryMapSize
,
879 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
880 IN UINTN DescriptorSize
885 UINTN MaxSplitRecordCount
;
886 UINTN RealSplitRecordCount
;
887 UINTN TotalSplitRecordCount
;
888 UINTN AdditionalRecordCount
;
890 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
892 TotalSplitRecordCount
= 0;
894 // Let old record point to end of valid MemoryMap buffer.
896 IndexOld
= ((*MemoryMapSize
) / DescriptorSize
) - 1;
898 // Let new record point to end of full MemoryMap buffer.
900 IndexNew
= ((*MemoryMapSize
) / DescriptorSize
) - 1 + AdditionalRecordCount
;
901 for ( ; IndexOld
>= 0; IndexOld
--) {
902 MaxSplitRecordCount
= GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
));
904 // Split this MemoryMap record
906 IndexNew
-= MaxSplitRecordCount
;
907 RealSplitRecordCount
= SplitRecord (
908 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
),
909 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
914 // Adjust IndexNew according to real split.
917 ((UINT8
*)MemoryMap
+ (IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
) * DescriptorSize
),
918 ((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
919 RealSplitRecordCount
* DescriptorSize
921 IndexNew
= IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
;
922 TotalSplitRecordCount
+= RealSplitRecordCount
;
927 // Move all records to the beginning.
931 (UINT8
*)MemoryMap
+ (AdditionalRecordCount
- TotalSplitRecordCount
) * DescriptorSize
,
932 (*MemoryMapSize
) + TotalSplitRecordCount
* DescriptorSize
935 *MemoryMapSize
= (*MemoryMapSize
) + DescriptorSize
* TotalSplitRecordCount
;
938 // Sort from low to high (Just in case)
940 SortMemoryMap (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
943 // Set RuntimeData to XP
945 EnforceMemoryMapAttribute (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
948 // Merge same type to save entry size
950 MergeMemoryMap (MemoryMap
, MemoryMapSize
, DescriptorSize
);
956 This function for GetMemoryMap() with properties table capability.
958 It calls original GetMemoryMap() to get the original memory map information. Then
959 plus the additional memory map entries for PE Code/Data seperation.
961 @param MemoryMapSize A pointer to the size, in bytes, of the
962 MemoryMap buffer. On input, this is the size of
963 the buffer allocated by the caller. On output,
964 it is the size of the buffer returned by the
965 firmware if the buffer was large enough, or the
966 size of the buffer needed to contain the map if
967 the buffer was too small.
968 @param MemoryMap A pointer to the buffer in which firmware places
969 the current memory map.
970 @param MapKey A pointer to the location in which firmware
971 returns the key for the current memory map.
972 @param DescriptorSize A pointer to the location in which firmware
973 returns the size, in bytes, of an individual
974 EFI_MEMORY_DESCRIPTOR.
975 @param DescriptorVersion A pointer to the location in which firmware
976 returns the version number associated with the
977 EFI_MEMORY_DESCRIPTOR.
979 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
981 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
982 buffer size needed to hold the memory map is
983 returned in MemoryMapSize.
984 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
989 CoreGetMemoryMapWithSeparatedImageSection (
990 IN OUT UINTN
*MemoryMapSize
,
991 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
993 OUT UINTN
*DescriptorSize
,
994 OUT UINT32
*DescriptorVersion
998 UINTN OldMemoryMapSize
;
999 UINTN AdditionalRecordCount
;
1002 // If PE code/data is not aligned, just return.
1004 if (!mMemoryAttributesTableEnable
) {
1005 return CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
1008 if (MemoryMapSize
== NULL
) {
1009 return EFI_INVALID_PARAMETER
;
1012 CoreAcquiremMemoryAttributesTableLock ();
1014 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
1016 OldMemoryMapSize
= *MemoryMapSize
;
1017 Status
= CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
1018 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1019 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
1020 } else if (Status
== EFI_SUCCESS
) {
1021 ASSERT (MemoryMap
!= NULL
);
1022 if (OldMemoryMapSize
- *MemoryMapSize
< (*DescriptorSize
) * AdditionalRecordCount
) {
1023 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
1025 // Need update status to buffer too small
1027 Status
= EFI_BUFFER_TOO_SMALL
;
1030 // Split PE code/data
1032 SplitTable (MemoryMapSize
, MemoryMap
, *DescriptorSize
);
1036 CoreReleasemMemoryAttributesTableLock ();
1041 // Below functions are for ImageRecord
1045 Set MemoryAttributesTable according to PE/COFF image section alignment.
1047 @param SectionAlignment PE/COFF section alignment
1051 SetMemoryAttributesTableSectionAlignment (
1052 IN UINT32 SectionAlignment
1055 if (((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) &&
1056 mMemoryAttributesTableEnable
)
1058 DEBUG ((DEBUG_VERBOSE
, "SetMemoryAttributesTableSectionAlignment - Clear\n"));
1059 mMemoryAttributesTableEnable
= FALSE
;
1064 Swap two code sections in image record.
1066 @param FirstImageRecordCodeSection first code section in image record
1067 @param SecondImageRecordCodeSection second code section in image record
1071 SwapImageRecordCodeSection (
1072 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*FirstImageRecordCodeSection
,
1073 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*SecondImageRecordCodeSection
1076 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection
;
1078 TempImageRecordCodeSection
.CodeSegmentBase
= FirstImageRecordCodeSection
->CodeSegmentBase
;
1079 TempImageRecordCodeSection
.CodeSegmentSize
= FirstImageRecordCodeSection
->CodeSegmentSize
;
1081 FirstImageRecordCodeSection
->CodeSegmentBase
= SecondImageRecordCodeSection
->CodeSegmentBase
;
1082 FirstImageRecordCodeSection
->CodeSegmentSize
= SecondImageRecordCodeSection
->CodeSegmentSize
;
1084 SecondImageRecordCodeSection
->CodeSegmentBase
= TempImageRecordCodeSection
.CodeSegmentBase
;
1085 SecondImageRecordCodeSection
->CodeSegmentSize
= TempImageRecordCodeSection
.CodeSegmentSize
;
1089 Sort code section in image record, based upon CodeSegmentBase from low to high.
1091 @param ImageRecord image record to be sorted
1094 SortImageRecordCodeSection (
1095 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
1098 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1099 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*NextImageRecordCodeSection
;
1100 LIST_ENTRY
*ImageRecordCodeSectionLink
;
1101 LIST_ENTRY
*NextImageRecordCodeSectionLink
;
1102 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
1103 LIST_ENTRY
*ImageRecordCodeSectionList
;
1105 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
1107 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
1108 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
1109 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
1110 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
1111 ImageRecordCodeSection
= CR (
1112 ImageRecordCodeSectionLink
,
1113 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1115 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1117 while (NextImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
1118 NextImageRecordCodeSection
= CR (
1119 NextImageRecordCodeSectionLink
,
1120 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1122 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1124 if (ImageRecordCodeSection
->CodeSegmentBase
> NextImageRecordCodeSection
->CodeSegmentBase
) {
1125 SwapImageRecordCodeSection (ImageRecordCodeSection
, NextImageRecordCodeSection
);
1128 NextImageRecordCodeSectionLink
= NextImageRecordCodeSectionLink
->ForwardLink
;
1131 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
1132 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
1137 Check if code section in image record is valid.
1139 @param ImageRecord image record to be checked
1141 @retval TRUE image record is valid
1142 @retval FALSE image record is invalid
1145 IsImageRecordCodeSectionValid (
1146 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
1149 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1150 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*LastImageRecordCodeSection
;
1151 LIST_ENTRY
*ImageRecordCodeSectionLink
;
1152 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
1153 LIST_ENTRY
*ImageRecordCodeSectionList
;
1155 DEBUG ((DEBUG_VERBOSE
, "ImageCode SegmentCount - 0x%x\n", ImageRecord
->CodeSegmentCount
));
1157 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
1159 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
1160 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
1161 LastImageRecordCodeSection
= NULL
;
1162 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
1163 ImageRecordCodeSection
= CR (
1164 ImageRecordCodeSectionLink
,
1165 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1167 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1169 if (ImageRecordCodeSection
->CodeSegmentSize
== 0) {
1173 if (ImageRecordCodeSection
->CodeSegmentBase
< ImageRecord
->ImageBase
) {
1177 if (ImageRecordCodeSection
->CodeSegmentBase
>= MAX_ADDRESS
- ImageRecordCodeSection
->CodeSegmentSize
) {
1181 if ((ImageRecordCodeSection
->CodeSegmentBase
+ ImageRecordCodeSection
->CodeSegmentSize
) > (ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
1185 if (LastImageRecordCodeSection
!= NULL
) {
1186 if ((LastImageRecordCodeSection
->CodeSegmentBase
+ LastImageRecordCodeSection
->CodeSegmentSize
) > ImageRecordCodeSection
->CodeSegmentBase
) {
1191 LastImageRecordCodeSection
= ImageRecordCodeSection
;
1192 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
1199 Swap two image records.
1201 @param FirstImageRecord first image record.
1202 @param SecondImageRecord second image record.
1207 IN IMAGE_PROPERTIES_RECORD
*FirstImageRecord
,
1208 IN IMAGE_PROPERTIES_RECORD
*SecondImageRecord
1211 IMAGE_PROPERTIES_RECORD TempImageRecord
;
1213 TempImageRecord
.ImageBase
= FirstImageRecord
->ImageBase
;
1214 TempImageRecord
.ImageSize
= FirstImageRecord
->ImageSize
;
1215 TempImageRecord
.CodeSegmentCount
= FirstImageRecord
->CodeSegmentCount
;
1217 FirstImageRecord
->ImageBase
= SecondImageRecord
->ImageBase
;
1218 FirstImageRecord
->ImageSize
= SecondImageRecord
->ImageSize
;
1219 FirstImageRecord
->CodeSegmentCount
= SecondImageRecord
->CodeSegmentCount
;
1221 SecondImageRecord
->ImageBase
= TempImageRecord
.ImageBase
;
1222 SecondImageRecord
->ImageSize
= TempImageRecord
.ImageSize
;
1223 SecondImageRecord
->CodeSegmentCount
= TempImageRecord
.CodeSegmentCount
;
1225 SwapListEntries (&FirstImageRecord
->CodeSegmentList
, &SecondImageRecord
->CodeSegmentList
);
1229 Sort image record based upon the ImageBase from low to high.
1237 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1238 IMAGE_PROPERTIES_RECORD
*NextImageRecord
;
1239 LIST_ENTRY
*ImageRecordLink
;
1240 LIST_ENTRY
*NextImageRecordLink
;
1241 LIST_ENTRY
*ImageRecordEndLink
;
1242 LIST_ENTRY
*ImageRecordList
;
1244 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1246 ImageRecordLink
= ImageRecordList
->ForwardLink
;
1247 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1248 ImageRecordEndLink
= ImageRecordList
;
1249 while (ImageRecordLink
!= ImageRecordEndLink
) {
1252 IMAGE_PROPERTIES_RECORD
,
1254 IMAGE_PROPERTIES_RECORD_SIGNATURE
1256 while (NextImageRecordLink
!= ImageRecordEndLink
) {
1257 NextImageRecord
= CR (
1258 NextImageRecordLink
,
1259 IMAGE_PROPERTIES_RECORD
,
1261 IMAGE_PROPERTIES_RECORD_SIGNATURE
1263 if (ImageRecord
->ImageBase
> NextImageRecord
->ImageBase
) {
1264 SwapImageRecord (ImageRecord
, NextImageRecord
);
1267 NextImageRecordLink
= NextImageRecordLink
->ForwardLink
;
1270 ImageRecordLink
= ImageRecordLink
->ForwardLink
;
1271 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1276 Insert image record.
1278 @param RuntimeImage Runtime image information
1282 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1286 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1287 UINT32 PeCoffHeaderOffset
;
1288 UINT32 SectionAlignment
;
1289 EFI_IMAGE_SECTION_HEADER
*Section
;
1290 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1293 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1295 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1297 DEBUG ((DEBUG_VERBOSE
, "InsertImageRecord - 0x%x\n", RuntimeImage
));
1298 DEBUG ((DEBUG_VERBOSE
, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1300 if (mMemoryAttributesTableEndOfDxe
) {
1301 DEBUG ((DEBUG_INFO
, "Do not insert runtime image record after EndOfDxe\n"));
1305 ImageRecord
= AllocatePool (sizeof (*ImageRecord
));
1306 if (ImageRecord
== NULL
) {
1310 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1312 DEBUG ((DEBUG_VERBOSE
, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1315 // Step 1: record whole region
1317 ImageRecord
->ImageBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
;
1318 ImageRecord
->ImageSize
= RuntimeImage
->ImageSize
;
1320 ImageAddress
= RuntimeImage
->ImageBase
;
1322 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*)(UINTN
)ImageAddress
);
1323 if (PdbPointer
!= NULL
) {
1324 DEBUG ((DEBUG_VERBOSE
, " Image - %a\n", PdbPointer
));
1328 // Check PE/COFF image
1330 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(UINTN
)ImageAddress
;
1331 PeCoffHeaderOffset
= 0;
1332 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1333 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1336 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*)(UINTN
)ImageAddress
+ PeCoffHeaderOffset
);
1337 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1338 DEBUG ((DEBUG_VERBOSE
, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1339 // It might be image in SMM.
1344 // Get SectionAlignment
1346 if (Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1347 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1349 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1352 SetMemoryAttributesTableSectionAlignment (SectionAlignment
);
1353 if ((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) {
1356 "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1358 RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10
1360 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*)(UINTN
)ImageAddress
);
1361 if (PdbPointer
!= NULL
) {
1362 DEBUG ((DEBUG_WARN
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1368 Section
= (EFI_IMAGE_SECTION_HEADER
*)(
1369 (UINT8
*)(UINTN
)ImageAddress
+
1370 PeCoffHeaderOffset
+
1372 sizeof (EFI_IMAGE_FILE_HEADER
) +
1373 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1375 ImageRecord
->CodeSegmentCount
= 0;
1376 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1377 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1378 Name
= Section
[Index
].Name
;
1381 " Section - '%c%c%c%c%c%c%c%c'\n",
1392 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1393 DEBUG ((DEBUG_VERBOSE
, " VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1394 DEBUG ((DEBUG_VERBOSE
, " VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1395 DEBUG ((DEBUG_VERBOSE
, " SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1396 DEBUG ((DEBUG_VERBOSE
, " PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1397 DEBUG ((DEBUG_VERBOSE
, " PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1398 DEBUG ((DEBUG_VERBOSE
, " PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1399 DEBUG ((DEBUG_VERBOSE
, " NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1400 DEBUG ((DEBUG_VERBOSE
, " NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1401 DEBUG ((DEBUG_VERBOSE
, " Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1404 // Step 2: record code section
1406 ImageRecordCodeSection
= AllocatePool (sizeof (*ImageRecordCodeSection
));
1407 if (ImageRecordCodeSection
== NULL
) {
1411 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1413 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1414 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1416 DEBUG ((DEBUG_VERBOSE
, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1418 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1419 ImageRecord
->CodeSegmentCount
++;
1423 if (ImageRecord
->CodeSegmentCount
== 0) {
1424 SetMemoryAttributesTableSectionAlignment (1);
1425 DEBUG ((DEBUG_ERROR
, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1426 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*)(UINTN
)ImageAddress
);
1427 if (PdbPointer
!= NULL
) {
1428 DEBUG ((DEBUG_ERROR
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1437 SortImageRecordCodeSection (ImageRecord
);
1439 // Check overlap all section in ImageBase/Size
1441 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1442 DEBUG ((DEBUG_ERROR
, "IsImageRecordCodeSectionValid - FAIL\n"));
1446 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1447 mImagePropertiesPrivateData
.ImageRecordCount
++;
1449 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1450 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1460 Find image record according to image base and size.
1462 @param ImageBase Base of PE image
1463 @param ImageSize Size of PE image
1465 @return image record
1468 IMAGE_PROPERTIES_RECORD
*
1470 IN EFI_PHYSICAL_ADDRESS ImageBase
,
1474 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1475 LIST_ENTRY
*ImageRecordLink
;
1476 LIST_ENTRY
*ImageRecordList
;
1478 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1480 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
1481 ImageRecordLink
!= ImageRecordList
;
1482 ImageRecordLink
= ImageRecordLink
->ForwardLink
)
1486 IMAGE_PROPERTIES_RECORD
,
1488 IMAGE_PROPERTIES_RECORD_SIGNATURE
1491 if ((ImageBase
== ImageRecord
->ImageBase
) &&
1492 (ImageSize
== ImageRecord
->ImageSize
))
1502 Remove Image record.
1504 @param RuntimeImage Runtime image information
1508 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1511 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1512 LIST_ENTRY
*CodeSegmentListHead
;
1513 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1515 DEBUG ((DEBUG_VERBOSE
, "RemoveImageRecord - 0x%x\n", RuntimeImage
));
1516 DEBUG ((DEBUG_VERBOSE
, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1518 if (mMemoryAttributesTableEndOfDxe
) {
1519 DEBUG ((DEBUG_INFO
, "Do not remove runtime image record after EndOfDxe\n"));
1523 ImageRecord
= FindImageRecord ((EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
);
1524 if (ImageRecord
== NULL
) {
1525 DEBUG ((DEBUG_ERROR
, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
1529 CodeSegmentListHead
= &ImageRecord
->CodeSegmentList
;
1530 while (!IsListEmpty (CodeSegmentListHead
)) {
1531 ImageRecordCodeSection
= CR (
1532 CodeSegmentListHead
->ForwardLink
,
1533 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1535 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1537 RemoveEntryList (&ImageRecordCodeSection
->Link
);
1538 FreePool (ImageRecordCodeSection
);
1541 RemoveEntryList (&ImageRecord
->Link
);
1542 FreePool (ImageRecord
);
1543 mImagePropertiesPrivateData
.ImageRecordCount
--;