2 PI SMM MemoryAttributes support
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/BaseLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/MemoryAllocationLib.h>
19 #include <Library/UefiBootServicesTableLib.h>
20 #include <Library/SmmServicesTableLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/PcdLib.h>
24 #include <Library/PeCoffLib.h>
25 #include <Library/PeCoffGetEntryPointLib.h>
27 #include <Guid/PiSmmMemoryAttributesTable.h>
29 #include "PiSmmCore.h"
31 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
32 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
34 #define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I','P','R','C')
39 EFI_PHYSICAL_ADDRESS CodeSegmentBase
;
40 UINT64 CodeSegmentSize
;
41 } IMAGE_PROPERTIES_RECORD_CODE_SECTION
;
43 #define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D')
48 EFI_PHYSICAL_ADDRESS ImageBase
;
50 UINTN CodeSegmentCount
;
51 LIST_ENTRY CodeSegmentList
;
52 } IMAGE_PROPERTIES_RECORD
;
54 #define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')
58 UINTN ImageRecordCount
;
59 UINTN CodeSegmentCountMax
;
60 LIST_ENTRY ImageRecordList
;
61 } IMAGE_PROPERTIES_PRIVATE_DATA
;
63 IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData
= {
64 IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE
,
67 INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData
.ImageRecordList
)
70 #define EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA BIT0
72 UINT64 mMemoryProtectionAttribute
= EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
;
75 // Below functions are for MemoryMap
79 Converts a number of EFI_PAGEs to a size in bytes.
81 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
83 @param[in] Pages The number of EFI_PAGES.
85 @return The number of bytes associated with the number of EFI_PAGEs specified
94 return LShiftU64 (Pages
, EFI_PAGE_SHIFT
);
98 Converts a size, in bytes, to a number of EFI_PAGESs.
100 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
102 @param[in] Size A size in bytes.
104 @return The number of EFI_PAGESs associated with the number of bytes specified
114 return RShiftU64 (Size
, EFI_PAGE_SHIFT
) + ((((UINTN
)Size
) & EFI_PAGE_MASK
) ? 1 : 0);
118 Check the consistency of Smm memory attributes table.
120 @param[in] MemoryAttributesTable PI SMM memory attributes table
123 SmmMemoryAttributesTableConsistencyCheck (
124 IN EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
127 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
128 UINTN MemoryMapEntryCount
;
129 UINTN DescriptorSize
;
134 MemoryMapEntryCount
= MemoryAttributesTable
->NumberOfEntries
;
135 DescriptorSize
= MemoryAttributesTable
->DescriptorSize
;
136 MemoryMap
= (EFI_MEMORY_DESCRIPTOR
*)(MemoryAttributesTable
+ 1);
137 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
139 ASSERT (Address
== MemoryMap
->PhysicalStart
);
141 Address
= MemoryMap
->PhysicalStart
+ EfiPagesToSize(MemoryMap
->NumberOfPages
);
142 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
147 Sort memory map entries based upon PhysicalStart, from low to high.
149 @param[in] MemoryMap A pointer to the buffer in which firmware places
150 the current memory map.
151 @param[in] MemoryMapSize Size, in bytes, of the MemoryMap buffer.
152 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
157 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
158 IN UINTN MemoryMapSize
,
159 IN UINTN DescriptorSize
162 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
163 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
164 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
165 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
167 MemoryMapEntry
= MemoryMap
;
168 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
169 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
170 while (MemoryMapEntry
< MemoryMapEnd
) {
171 while (NextMemoryMapEntry
< MemoryMapEnd
) {
172 if (MemoryMapEntry
->PhysicalStart
> NextMemoryMapEntry
->PhysicalStart
) {
173 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
174 CopyMem (MemoryMapEntry
, NextMemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
175 CopyMem (NextMemoryMapEntry
, &TempMemoryMap
, sizeof(EFI_MEMORY_DESCRIPTOR
));
178 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
181 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
182 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
189 Merge continous memory map entries whose have same attributes.
191 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
192 the current memory map.
193 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
194 MemoryMap buffer. On input, this is the size of
195 the current memory map. On output,
196 it is the size of new memory map after merge.
197 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
202 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
203 IN OUT UINTN
*MemoryMapSize
,
204 IN UINTN DescriptorSize
207 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
208 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
209 UINT64 MemoryBlockLength
;
210 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
211 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
213 MemoryMapEntry
= MemoryMap
;
214 NewMemoryMapEntry
= MemoryMap
;
215 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ *MemoryMapSize
);
216 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
217 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
218 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
221 MemoryBlockLength
= (UINT64
) (EfiPagesToSize (MemoryMapEntry
->NumberOfPages
));
222 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
223 (MemoryMapEntry
->Type
== NextMemoryMapEntry
->Type
) &&
224 (MemoryMapEntry
->Attribute
== NextMemoryMapEntry
->Attribute
) &&
225 ((MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
) == NextMemoryMapEntry
->PhysicalStart
)) {
226 MemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
227 if (NewMemoryMapEntry
!= MemoryMapEntry
) {
228 NewMemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
231 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
234 MemoryMapEntry
= PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
239 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
240 NewMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry
, DescriptorSize
);
243 *MemoryMapSize
= (UINTN
)NewMemoryMapEntry
- (UINTN
)MemoryMap
;
249 Enforce memory map attributes.
250 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
252 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
253 the current memory map.
254 @param[in] MemoryMapSize Size, in bytes, of the MemoryMap buffer.
255 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
259 EnforceMemoryMapAttribute (
260 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
261 IN UINTN MemoryMapSize
,
262 IN UINTN DescriptorSize
265 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
266 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
268 MemoryMapEntry
= MemoryMap
;
269 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
270 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
271 if (MemoryMapEntry
->Attribute
!= 0) {
272 // It is PE image, the attribute is already set.
274 switch (MemoryMapEntry
->Type
) {
275 case EfiRuntimeServicesCode
:
276 MemoryMapEntry
->Attribute
= EFI_MEMORY_RO
;
278 case EfiRuntimeServicesData
:
280 MemoryMapEntry
->Attribute
|= EFI_MEMORY_XP
;
284 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
291 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
293 @param[in] Buffer Start Address
294 @param[in] Length Address length
296 @return first image record covered by [buffer, length]
299 IMAGE_PROPERTIES_RECORD
*
300 GetImageRecordByAddress (
301 IN EFI_PHYSICAL_ADDRESS Buffer
,
305 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
306 LIST_ENTRY
*ImageRecordLink
;
307 LIST_ENTRY
*ImageRecordList
;
309 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
311 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
312 ImageRecordLink
!= ImageRecordList
;
313 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
316 IMAGE_PROPERTIES_RECORD
,
318 IMAGE_PROPERTIES_RECORD_SIGNATURE
321 if ((Buffer
<= ImageRecord
->ImageBase
) &&
322 (Buffer
+ Length
>= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
331 Set the memory map to new entries, according to one old entry,
332 based upon PE code section and data section in image record
334 @param[in] ImageRecord An image record whose [ImageBase, ImageSize] covered
335 by old memory map entry.
336 @param[in, out] NewRecord A pointer to several new memory map entries.
337 The caller gurantee the buffer size be 1 +
338 (SplitRecordCount * DescriptorSize) calculated
340 @param[in] OldRecord A pointer to one old memory map entry.
341 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
346 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
,
347 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
348 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
349 IN UINTN DescriptorSize
352 EFI_MEMORY_DESCRIPTOR TempRecord
;
353 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
354 LIST_ENTRY
*ImageRecordCodeSectionLink
;
355 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
356 LIST_ENTRY
*ImageRecordCodeSectionList
;
357 UINTN NewRecordCount
;
361 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
362 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
366 // Always create a new entry for non-PE image record
368 if (ImageRecord
->ImageBase
> TempRecord
.PhysicalStart
) {
369 NewRecord
->Type
= TempRecord
.Type
;
370 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
371 NewRecord
->VirtualStart
= 0;
372 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecord
->ImageBase
- TempRecord
.PhysicalStart
);
373 NewRecord
->Attribute
= TempRecord
.Attribute
;
374 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
376 TempRecord
.PhysicalStart
= ImageRecord
->ImageBase
;
377 TempRecord
.NumberOfPages
= EfiSizeToPages(PhysicalEnd
- TempRecord
.PhysicalStart
);
380 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
382 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
383 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
384 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
385 ImageRecordCodeSection
= CR (
386 ImageRecordCodeSectionLink
,
387 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
389 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
391 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
393 if (TempRecord
.PhysicalStart
<= ImageRecordCodeSection
->CodeSegmentBase
) {
397 NewRecord
->Type
= EfiRuntimeServicesData
;
398 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
399 NewRecord
->VirtualStart
= 0;
400 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentBase
- NewRecord
->PhysicalStart
);
401 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
402 if (NewRecord
->NumberOfPages
!= 0) {
403 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
410 NewRecord
->Type
= EfiRuntimeServicesCode
;
411 NewRecord
->PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
;
412 NewRecord
->VirtualStart
= 0;
413 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
);
414 NewRecord
->Attribute
= (TempRecord
.Attribute
& (~EFI_MEMORY_XP
)) | EFI_MEMORY_RO
;
415 if (NewRecord
->NumberOfPages
!= 0) {
416 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
420 TempRecord
.PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
+ EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
));
421 TempRecord
.NumberOfPages
= EfiSizeToPages(PhysicalEnd
- TempRecord
.PhysicalStart
);
422 if (TempRecord
.NumberOfPages
== 0) {
428 ImageEnd
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
433 if (TempRecord
.PhysicalStart
< ImageEnd
) {
434 NewRecord
->Type
= EfiRuntimeServicesData
;
435 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
436 NewRecord
->VirtualStart
= 0;
437 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageEnd
- TempRecord
.PhysicalStart
);
438 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
442 return NewRecordCount
;
446 Return the max number of new splitted entries, according to one old entry,
447 based upon PE code section and data section.
449 @param[in] OldRecord A pointer to one old memory map entry.
451 @retval 0 no entry need to be splitted.
452 @return the max number of new splitted entries
456 GetMaxSplitRecordCount (
457 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
460 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
461 UINTN SplitRecordCount
;
462 UINT64 PhysicalStart
;
465 SplitRecordCount
= 0;
466 PhysicalStart
= OldRecord
->PhysicalStart
;
467 PhysicalEnd
= OldRecord
->PhysicalStart
+ EfiPagesToSize(OldRecord
->NumberOfPages
);
470 ImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
471 if (ImageRecord
== NULL
) {
474 SplitRecordCount
+= (2 * ImageRecord
->CodeSegmentCount
+ 2);
475 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
476 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
478 return SplitRecordCount
;
482 Split the memory map to new entries, according to one old entry,
483 based upon PE code section and data section.
485 @param[in] OldRecord A pointer to one old memory map entry.
486 @param[in, out] NewRecord A pointer to several new memory map entries.
487 The caller gurantee the buffer size be 1 +
488 (SplitRecordCount * DescriptorSize) calculated
490 @param[in] MaxSplitRecordCount The max number of splitted entries
491 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
493 @retval 0 no entry is splitted.
494 @return the real number of splitted record.
499 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
500 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
501 IN UINTN MaxSplitRecordCount
,
502 IN UINTN DescriptorSize
505 EFI_MEMORY_DESCRIPTOR TempRecord
;
506 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
507 IMAGE_PROPERTIES_RECORD
*NewImageRecord
;
508 UINT64 PhysicalStart
;
510 UINTN NewRecordCount
;
511 UINTN TotalNewRecordCount
;
513 if (MaxSplitRecordCount
== 0) {
514 CopyMem (NewRecord
, OldRecord
, DescriptorSize
);
518 TotalNewRecordCount
= 0;
521 // Override previous record
523 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
524 PhysicalStart
= TempRecord
.PhysicalStart
;
525 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
529 NewImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
530 if (NewImageRecord
== NULL
) {
532 // No more image covered by this range, stop
534 if (PhysicalEnd
> PhysicalStart
) {
536 // Always create a new entry for non-PE image record
538 NewRecord
->Type
= TempRecord
.Type
;
539 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
540 NewRecord
->VirtualStart
= 0;
541 NewRecord
->NumberOfPages
= TempRecord
.NumberOfPages
;
542 NewRecord
->Attribute
= TempRecord
.Attribute
;
543 TotalNewRecordCount
++;
547 ImageRecord
= NewImageRecord
;
552 NewRecordCount
= SetNewRecord (ImageRecord
, NewRecord
, &TempRecord
, DescriptorSize
);
553 TotalNewRecordCount
+= NewRecordCount
;
554 NewRecord
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)NewRecord
+ NewRecordCount
* DescriptorSize
);
557 // Update PhysicalStart, in order to exclude the image buffer already splitted.
559 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
560 TempRecord
.PhysicalStart
= PhysicalStart
;
561 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- PhysicalStart
);
562 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
564 return TotalNewRecordCount
- 1;
568 Split the original memory map, and add more entries to describe PE code section and data section.
569 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
570 This function will merge entries with same attributes finally.
572 NOTE: It assumes PE code/data section are page aligned.
573 NOTE: It assumes enough entry is prepared for new memory map.
588 +---------------+ ----
591 | Record RtCode | |-> PE/COFF1
594 +---------------+ ----
596 +---------------+ ----
599 | Record RtCode | |-> PE/COFF2
602 +---------------+ ----
608 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
609 MemoryMap buffer. On input, this is the size of
610 old MemoryMap before split. The actual buffer
611 size of MemoryMap is MemoryMapSize +
612 (AdditionalRecordCount * DescriptorSize) calculated
613 below. On output, it is the size of new MemoryMap
615 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
616 the current memory map.
617 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
622 IN OUT UINTN
*MemoryMapSize
,
623 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
624 IN UINTN DescriptorSize
629 UINTN MaxSplitRecordCount
;
630 UINTN RealSplitRecordCount
;
631 UINTN TotalSplitRecordCount
;
632 UINTN AdditionalRecordCount
;
634 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 2) * mImagePropertiesPrivateData
.ImageRecordCount
;
636 TotalSplitRecordCount
= 0;
638 // Let old record point to end of valid MemoryMap buffer.
640 IndexOld
= ((*MemoryMapSize
) / DescriptorSize
) - 1;
642 // Let new record point to end of full MemoryMap buffer.
644 IndexNew
= ((*MemoryMapSize
) / DescriptorSize
) - 1 + AdditionalRecordCount
;
645 for (; IndexOld
>= 0; IndexOld
--) {
646 MaxSplitRecordCount
= GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
));
648 // Split this MemoryMap record
650 IndexNew
-= MaxSplitRecordCount
;
651 RealSplitRecordCount
= SplitRecord (
652 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
),
653 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
658 // Adjust IndexNew according to real split.
660 if (MaxSplitRecordCount
!= RealSplitRecordCount
) {
662 ((UINT8
*)MemoryMap
+ (IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
) * DescriptorSize
),
663 ((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
664 (RealSplitRecordCount
+ 1) * DescriptorSize
667 IndexNew
= IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
;
668 TotalSplitRecordCount
+= RealSplitRecordCount
;
672 // Move all records to the beginning.
676 (UINT8
*)MemoryMap
+ (AdditionalRecordCount
- TotalSplitRecordCount
) * DescriptorSize
,
677 (*MemoryMapSize
) + TotalSplitRecordCount
* DescriptorSize
680 *MemoryMapSize
= (*MemoryMapSize
) + DescriptorSize
* TotalSplitRecordCount
;
683 // Sort from low to high (Just in case)
685 SortMemoryMap (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
688 // Set RuntimeData to XP
690 EnforceMemoryMapAttribute (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
693 // Merge same type to save entry size
695 MergeMemoryMap (MemoryMap
, MemoryMapSize
, DescriptorSize
);
701 This function for GetMemoryMap() with memory attributes table.
703 It calls original GetMemoryMap() to get the original memory map information. Then
704 plus the additional memory map entries for PE Code/Data seperation.
706 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
707 MemoryMap buffer. On input, this is the size of
708 the buffer allocated by the caller. On output,
709 it is the size of the buffer returned by the
710 firmware if the buffer was large enough, or the
711 size of the buffer needed to contain the map if
712 the buffer was too small.
713 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
714 the current memory map.
715 @param[out] MapKey A pointer to the location in which firmware
716 returns the key for the current memory map.
717 @param[out] DescriptorSize A pointer to the location in which firmware
718 returns the size, in bytes, of an individual
719 EFI_MEMORY_DESCRIPTOR.
720 @param[out] DescriptorVersion A pointer to the location in which firmware
721 returns the version number associated with the
722 EFI_MEMORY_DESCRIPTOR.
724 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
726 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
727 buffer size needed to hold the memory map is
728 returned in MemoryMapSize.
729 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
735 SmmCoreGetMemoryMapMemoryAttributesTable (
736 IN OUT UINTN
*MemoryMapSize
,
737 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
739 OUT UINTN
*DescriptorSize
,
740 OUT UINT32
*DescriptorVersion
744 UINTN OldMemoryMapSize
;
745 UINTN AdditionalRecordCount
;
748 // If PE code/data is not aligned, just return.
750 if ((mMemoryProtectionAttribute
& EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
751 return SmmCoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
754 if (MemoryMapSize
== NULL
) {
755 return EFI_INVALID_PARAMETER
;
758 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 2) * mImagePropertiesPrivateData
.ImageRecordCount
;
760 OldMemoryMapSize
= *MemoryMapSize
;
761 Status
= SmmCoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
762 if (Status
== EFI_BUFFER_TOO_SMALL
) {
763 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
764 } else if (Status
== EFI_SUCCESS
) {
765 if (OldMemoryMapSize
- *MemoryMapSize
< (*DescriptorSize
) * AdditionalRecordCount
) {
766 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
768 // Need update status to buffer too small
770 Status
= EFI_BUFFER_TOO_SMALL
;
773 // Split PE code/data
775 ASSERT(MemoryMap
!= NULL
);
776 SplitTable (MemoryMapSize
, MemoryMap
, *DescriptorSize
);
784 // Below functions are for ImageRecord
788 Set MemoryProtectionAttribute accroding to PE/COFF image section alignment.
790 @param[in] SectionAlignment PE/COFF section alignment
794 SetMemoryAttributesTableSectionAlignment (
795 IN UINT32 SectionAlignment
798 if (((SectionAlignment
& (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT
- 1)) != 0) &&
799 ((mMemoryProtectionAttribute
& EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) != 0)) {
800 DEBUG ((DEBUG_VERBOSE
, "SMM SetMemoryAttributesTableSectionAlignment - Clear\n"));
801 mMemoryProtectionAttribute
&= ~((UINT64
)EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
);
806 Swap two code sections in image record.
808 @param[in] FirstImageRecordCodeSection first code section in image record
809 @param[in] SecondImageRecordCodeSection second code section in image record
813 SwapImageRecordCodeSection (
814 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*FirstImageRecordCodeSection
,
815 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*SecondImageRecordCodeSection
818 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection
;
820 TempImageRecordCodeSection
.CodeSegmentBase
= FirstImageRecordCodeSection
->CodeSegmentBase
;
821 TempImageRecordCodeSection
.CodeSegmentSize
= FirstImageRecordCodeSection
->CodeSegmentSize
;
823 FirstImageRecordCodeSection
->CodeSegmentBase
= SecondImageRecordCodeSection
->CodeSegmentBase
;
824 FirstImageRecordCodeSection
->CodeSegmentSize
= SecondImageRecordCodeSection
->CodeSegmentSize
;
826 SecondImageRecordCodeSection
->CodeSegmentBase
= TempImageRecordCodeSection
.CodeSegmentBase
;
827 SecondImageRecordCodeSection
->CodeSegmentSize
= TempImageRecordCodeSection
.CodeSegmentSize
;
831 Sort code section in image record, based upon CodeSegmentBase from low to high.
833 @param[in] ImageRecord image record to be sorted
837 SortImageRecordCodeSection (
838 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
841 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
842 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*NextImageRecordCodeSection
;
843 LIST_ENTRY
*ImageRecordCodeSectionLink
;
844 LIST_ENTRY
*NextImageRecordCodeSectionLink
;
845 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
846 LIST_ENTRY
*ImageRecordCodeSectionList
;
848 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
850 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
851 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
852 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
853 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
854 ImageRecordCodeSection
= CR (
855 ImageRecordCodeSectionLink
,
856 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
858 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
860 while (NextImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
861 NextImageRecordCodeSection
= CR (
862 NextImageRecordCodeSectionLink
,
863 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
865 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
867 if (ImageRecordCodeSection
->CodeSegmentBase
> NextImageRecordCodeSection
->CodeSegmentBase
) {
868 SwapImageRecordCodeSection (ImageRecordCodeSection
, NextImageRecordCodeSection
);
870 NextImageRecordCodeSectionLink
= NextImageRecordCodeSectionLink
->ForwardLink
;
873 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
874 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
879 Check if code section in image record is valid.
881 @param[in] ImageRecord image record to be checked
883 @retval TRUE image record is valid
884 @retval FALSE image record is invalid
888 IsImageRecordCodeSectionValid (
889 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
892 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
893 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*LastImageRecordCodeSection
;
894 LIST_ENTRY
*ImageRecordCodeSectionLink
;
895 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
896 LIST_ENTRY
*ImageRecordCodeSectionList
;
898 DEBUG ((DEBUG_VERBOSE
, "SMM ImageCode SegmentCount - 0x%x\n", ImageRecord
->CodeSegmentCount
));
900 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
902 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
903 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
904 LastImageRecordCodeSection
= NULL
;
905 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
906 ImageRecordCodeSection
= CR (
907 ImageRecordCodeSectionLink
,
908 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
910 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
912 if (ImageRecordCodeSection
->CodeSegmentSize
== 0) {
915 if (ImageRecordCodeSection
->CodeSegmentBase
< ImageRecord
->ImageBase
) {
918 if (ImageRecordCodeSection
->CodeSegmentBase
>= MAX_ADDRESS
- ImageRecordCodeSection
->CodeSegmentSize
) {
921 if ((ImageRecordCodeSection
->CodeSegmentBase
+ ImageRecordCodeSection
->CodeSegmentSize
) > (ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
924 if (LastImageRecordCodeSection
!= NULL
) {
925 if ((LastImageRecordCodeSection
->CodeSegmentBase
+ LastImageRecordCodeSection
->CodeSegmentSize
) > ImageRecordCodeSection
->CodeSegmentBase
) {
930 LastImageRecordCodeSection
= ImageRecordCodeSection
;
931 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
938 Swap two image records.
940 @param[in] FirstImageRecord first image record.
941 @param[in] SecondImageRecord second image record.
946 IN IMAGE_PROPERTIES_RECORD
*FirstImageRecord
,
947 IN IMAGE_PROPERTIES_RECORD
*SecondImageRecord
950 IMAGE_PROPERTIES_RECORD TempImageRecord
;
952 TempImageRecord
.ImageBase
= FirstImageRecord
->ImageBase
;
953 TempImageRecord
.ImageSize
= FirstImageRecord
->ImageSize
;
954 TempImageRecord
.CodeSegmentCount
= FirstImageRecord
->CodeSegmentCount
;
956 FirstImageRecord
->ImageBase
= SecondImageRecord
->ImageBase
;
957 FirstImageRecord
->ImageSize
= SecondImageRecord
->ImageSize
;
958 FirstImageRecord
->CodeSegmentCount
= SecondImageRecord
->CodeSegmentCount
;
960 SecondImageRecord
->ImageBase
= TempImageRecord
.ImageBase
;
961 SecondImageRecord
->ImageSize
= TempImageRecord
.ImageSize
;
962 SecondImageRecord
->CodeSegmentCount
= TempImageRecord
.CodeSegmentCount
;
964 SwapListEntries (&FirstImageRecord
->CodeSegmentList
, &SecondImageRecord
->CodeSegmentList
);
968 Sort image record based upon the ImageBase from low to high.
976 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
977 IMAGE_PROPERTIES_RECORD
*NextImageRecord
;
978 LIST_ENTRY
*ImageRecordLink
;
979 LIST_ENTRY
*NextImageRecordLink
;
980 LIST_ENTRY
*ImageRecordEndLink
;
981 LIST_ENTRY
*ImageRecordList
;
983 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
985 ImageRecordLink
= ImageRecordList
->ForwardLink
;
986 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
987 ImageRecordEndLink
= ImageRecordList
;
988 while (ImageRecordLink
!= ImageRecordEndLink
) {
991 IMAGE_PROPERTIES_RECORD
,
993 IMAGE_PROPERTIES_RECORD_SIGNATURE
995 while (NextImageRecordLink
!= ImageRecordEndLink
) {
996 NextImageRecord
= CR (
998 IMAGE_PROPERTIES_RECORD
,
1000 IMAGE_PROPERTIES_RECORD_SIGNATURE
1002 if (ImageRecord
->ImageBase
> NextImageRecord
->ImageBase
) {
1003 SwapImageRecord (ImageRecord
, NextImageRecord
);
1005 NextImageRecordLink
= NextImageRecordLink
->ForwardLink
;
1008 ImageRecordLink
= ImageRecordLink
->ForwardLink
;
1009 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1022 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1023 LIST_ENTRY
*ImageRecordLink
;
1024 LIST_ENTRY
*ImageRecordList
;
1027 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1029 for (ImageRecordLink
= ImageRecordList
->ForwardLink
, Index
= 0;
1030 ImageRecordLink
!= ImageRecordList
;
1031 ImageRecordLink
= ImageRecordLink
->ForwardLink
, Index
++) {
1034 IMAGE_PROPERTIES_RECORD
,
1036 IMAGE_PROPERTIES_RECORD_SIGNATURE
1038 DEBUG ((DEBUG_VERBOSE
, "SMM Image[%d]: 0x%016lx - 0x%016lx\n", Index
, ImageRecord
->ImageBase
, ImageRecord
->ImageSize
));
1043 Insert image record.
1045 @param[in] DriverEntry Driver information
1048 SmmInsertImageRecord (
1049 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
1053 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1054 UINT32 PeCoffHeaderOffset
;
1055 UINT32 SectionAlignment
;
1056 EFI_IMAGE_SECTION_HEADER
*Section
;
1057 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1060 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1062 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1065 DEBUG ((DEBUG_VERBOSE
, "SMM InsertImageRecord - 0x%x\n", DriverEntry
));
1066 DEBUG ((DEBUG_VERBOSE
, "SMM InsertImageRecord - 0x%016lx - 0x%08x\n", DriverEntry
->ImageBuffer
, DriverEntry
->NumberOfPage
));
1068 ImageRecord
= AllocatePool (sizeof(*ImageRecord
));
1069 if (ImageRecord
== NULL
) {
1072 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1074 DEBUG ((DEBUG_VERBOSE
, "SMM ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1077 // Step 1: record whole region
1079 ImageRecord
->ImageBase
= DriverEntry
->ImageBuffer
;
1080 ImageRecord
->ImageSize
= EfiPagesToSize(DriverEntry
->NumberOfPage
);
1082 ImageAddress
= (VOID
*)(UINTN
)DriverEntry
->ImageBuffer
;
1084 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1085 if (PdbPointer
!= NULL
) {
1086 DEBUG ((DEBUG_VERBOSE
, "SMM Image - %a\n", PdbPointer
));
1090 // Check PE/COFF image
1092 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) (UINTN
) ImageAddress
;
1093 PeCoffHeaderOffset
= 0;
1094 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1095 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1098 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*) (UINTN
) ImageAddress
+ PeCoffHeaderOffset
);
1099 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1100 DEBUG ((DEBUG_VERBOSE
, "SMM Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1105 // Get SectionAlignment
1107 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1109 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1110 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1111 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1112 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1114 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1117 // Get the magic value from the PE/COFF Optional Header
1119 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
1121 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1122 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1124 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1127 SetMemoryAttributesTableSectionAlignment (SectionAlignment
);
1128 if ((SectionAlignment
& (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT
- 1)) != 0) {
1129 DEBUG ((DEBUG_WARN
, "SMM !!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1130 SectionAlignment
, EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT
>> 10));
1131 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1132 if (PdbPointer
!= NULL
) {
1133 DEBUG ((DEBUG_WARN
, "SMM !!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1138 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1139 (UINT8
*) (UINTN
) ImageAddress
+
1140 PeCoffHeaderOffset
+
1142 sizeof(EFI_IMAGE_FILE_HEADER
) +
1143 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1145 ImageRecord
->CodeSegmentCount
= 0;
1146 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1147 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1148 Name
= Section
[Index
].Name
;
1151 "SMM Section - '%c%c%c%c%c%c%c%c'\n",
1162 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1163 DEBUG ((DEBUG_VERBOSE
, "SMM VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1164 DEBUG ((DEBUG_VERBOSE
, "SMM VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1165 DEBUG ((DEBUG_VERBOSE
, "SMM SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1166 DEBUG ((DEBUG_VERBOSE
, "SMM PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1167 DEBUG ((DEBUG_VERBOSE
, "SMM PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1168 DEBUG ((DEBUG_VERBOSE
, "SMM PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1169 DEBUG ((DEBUG_VERBOSE
, "SMM NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1170 DEBUG ((DEBUG_VERBOSE
, "SMM NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1171 DEBUG ((DEBUG_VERBOSE
, "SMM Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1174 // Step 2: record code section
1176 ImageRecordCodeSection
= AllocatePool (sizeof(*ImageRecordCodeSection
));
1177 if (ImageRecordCodeSection
== NULL
) {
1180 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1182 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1183 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1185 DEBUG ((DEBUG_VERBOSE
, "SMM ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1187 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1188 ImageRecord
->CodeSegmentCount
++;
1192 if (ImageRecord
->CodeSegmentCount
== 0) {
1193 SetMemoryAttributesTableSectionAlignment (1);
1194 DEBUG ((DEBUG_ERROR
, "SMM !!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1195 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1196 if (PdbPointer
!= NULL
) {
1197 DEBUG ((DEBUG_ERROR
, "SMM !!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1205 SortImageRecordCodeSection (ImageRecord
);
1207 // Check overlap all section in ImageBase/Size
1209 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1210 DEBUG ((DEBUG_ERROR
, "SMM IsImageRecordCodeSectionValid - FAIL\n"));
1214 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1215 mImagePropertiesPrivateData
.ImageRecordCount
++;
1219 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1220 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1228 Find image record accroding to image base and size.
1230 @param[in] ImageBase Base of PE image
1231 @param[in] ImageSize Size of PE image
1233 @return image record
1236 IMAGE_PROPERTIES_RECORD
*
1238 IN EFI_PHYSICAL_ADDRESS ImageBase
,
1242 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1243 LIST_ENTRY
*ImageRecordLink
;
1244 LIST_ENTRY
*ImageRecordList
;
1246 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1248 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
1249 ImageRecordLink
!= ImageRecordList
;
1250 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
1253 IMAGE_PROPERTIES_RECORD
,
1255 IMAGE_PROPERTIES_RECORD_SIGNATURE
1258 if ((ImageBase
== ImageRecord
->ImageBase
) &&
1259 (ImageSize
== ImageRecord
->ImageSize
)) {
1268 Remove Image record.
1270 @param[in] DriverEntry Driver information
1273 SmmRemoveImageRecord (
1274 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
1277 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1278 LIST_ENTRY
*CodeSegmentListHead
;
1279 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1281 DEBUG ((DEBUG_VERBOSE
, "SMM RemoveImageRecord - 0x%x\n", DriverEntry
));
1282 DEBUG ((DEBUG_VERBOSE
, "SMM RemoveImageRecord - 0x%016lx - 0x%016lx\n", DriverEntry
->ImageBuffer
, DriverEntry
->NumberOfPage
));
1284 ImageRecord
= FindImageRecord (DriverEntry
->ImageBuffer
, EfiPagesToSize(DriverEntry
->NumberOfPage
));
1285 if (ImageRecord
== NULL
) {
1286 DEBUG ((DEBUG_ERROR
, "SMM !!!!!!!! ImageRecord not found !!!!!!!!\n"));
1290 CodeSegmentListHead
= &ImageRecord
->CodeSegmentList
;
1291 while (!IsListEmpty (CodeSegmentListHead
)) {
1292 ImageRecordCodeSection
= CR (
1293 CodeSegmentListHead
->ForwardLink
,
1294 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1296 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1298 RemoveEntryList (&ImageRecordCodeSection
->Link
);
1299 FreePool (ImageRecordCodeSection
);
1302 RemoveEntryList (&ImageRecord
->Link
);
1303 FreePool (ImageRecord
);
1304 mImagePropertiesPrivateData
.ImageRecordCount
--;
1308 Publish MemoryAttributesTable to SMM configuration table.
1311 PublishMemoryAttributesTable (
1315 UINTN MemoryMapSize
;
1316 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
1318 UINTN DescriptorSize
;
1319 UINT32 DescriptorVersion
;
1322 UINTN RuntimeEntryCount
;
1323 EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
;
1324 EFI_MEMORY_DESCRIPTOR
*MemoryAttributesEntry
;
1325 UINTN MemoryAttributesTableSize
;
1329 Status
= SmmCoreGetMemoryMapMemoryAttributesTable (
1336 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
1339 DEBUG ((DEBUG_INFO
, "MemoryMapSize - 0x%x\n", MemoryMapSize
));
1340 MemoryMap
= AllocatePool (MemoryMapSize
);
1341 ASSERT (MemoryMap
!= NULL
);
1342 DEBUG ((DEBUG_INFO
, "MemoryMap - 0x%x\n", MemoryMap
));
1344 Status
= SmmCoreGetMemoryMapMemoryAttributesTable (
1351 if (EFI_ERROR (Status
)) {
1352 FreePool (MemoryMap
);
1354 } while (Status
== EFI_BUFFER_TOO_SMALL
);
1357 // Allocate MemoryAttributesTable
1359 RuntimeEntryCount
= MemoryMapSize
/DescriptorSize
;
1360 MemoryAttributesTableSize
= sizeof(EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
) + DescriptorSize
* RuntimeEntryCount
;
1361 MemoryAttributesTable
= AllocatePool (sizeof(EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
) + DescriptorSize
* RuntimeEntryCount
);
1362 ASSERT (MemoryAttributesTable
!= NULL
);
1363 MemoryAttributesTable
->Version
= EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE_VERSION
;
1364 MemoryAttributesTable
->NumberOfEntries
= (UINT32
)RuntimeEntryCount
;
1365 MemoryAttributesTable
->DescriptorSize
= (UINT32
)DescriptorSize
;
1366 MemoryAttributesTable
->Reserved
= 0;
1367 DEBUG ((DEBUG_INFO
, "MemoryAttributesTable:\n"));
1368 DEBUG ((DEBUG_INFO
, " Version - 0x%08x\n", MemoryAttributesTable
->Version
));
1369 DEBUG ((DEBUG_INFO
, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable
->NumberOfEntries
));
1370 DEBUG ((DEBUG_INFO
, " DescriptorSize - 0x%08x\n", MemoryAttributesTable
->DescriptorSize
));
1371 MemoryAttributesEntry
= (EFI_MEMORY_DESCRIPTOR
*)(MemoryAttributesTable
+ 1);
1372 for (Index
= 0; Index
< MemoryMapSize
/DescriptorSize
; Index
++) {
1373 CopyMem (MemoryAttributesEntry
, MemoryMap
, DescriptorSize
);
1374 DEBUG ((DEBUG_INFO
, "Entry (0x%x)\n", MemoryAttributesEntry
));
1375 DEBUG ((DEBUG_INFO
, " Type - 0x%x\n", MemoryAttributesEntry
->Type
));
1376 DEBUG ((DEBUG_INFO
, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry
->PhysicalStart
));
1377 DEBUG ((DEBUG_INFO
, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry
->VirtualStart
));
1378 DEBUG ((DEBUG_INFO
, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry
->NumberOfPages
));
1379 DEBUG ((DEBUG_INFO
, " Attribute - 0x%016lx\n", MemoryAttributesEntry
->Attribute
));
1380 MemoryAttributesEntry
= NEXT_MEMORY_DESCRIPTOR(MemoryAttributesEntry
, DescriptorSize
);
1382 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
1385 Status
= gSmst
->SmmInstallConfigurationTable (gSmst
, &gEdkiiPiSmmMemoryAttributesTableGuid
, MemoryAttributesTable
, MemoryAttributesTableSize
);
1386 ASSERT_EFI_ERROR (Status
);
1390 This function returns if image is inside SMRAM.
1392 @param[in] LoadedImage LoadedImage protocol instance for an image.
1394 @retval TRUE the image is inside SMRAM.
1395 @retval FALSE the image is outside SMRAM.
1398 IsImageInsideSmram (
1399 IN EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
1404 for (Index
= 0; Index
< mFullSmramRangeCount
; Index
++) {
1405 if ((mFullSmramRanges
[Index
].PhysicalStart
<= (UINTN
)LoadedImage
->ImageBase
)&&
1406 (mFullSmramRanges
[Index
].PhysicalStart
+ mFullSmramRanges
[Index
].PhysicalSize
>= (UINTN
)LoadedImage
->ImageBase
+ LoadedImage
->ImageSize
)) {
1415 This function installs all SMM image record information.
1418 SmmInstallImageRecord (
1424 EFI_HANDLE
*HandleBuffer
;
1425 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
1427 EFI_SMM_DRIVER_ENTRY DriverEntry
;
1429 Status
= SmmLocateHandleBuffer (
1431 &gEfiLoadedImageProtocolGuid
,
1436 if (EFI_ERROR (Status
)) {
1440 for (Index
= 0; Index
< NoHandles
; Index
++) {
1441 Status
= gSmst
->SmmHandleProtocol (
1442 HandleBuffer
[Index
],
1443 &gEfiLoadedImageProtocolGuid
,
1444 (VOID
**)&LoadedImage
1446 if (EFI_ERROR (Status
)) {
1449 DEBUG ((DEBUG_VERBOSE
, "LoadedImage - 0x%x 0x%x ", LoadedImage
->ImageBase
, LoadedImage
->ImageSize
));
1452 PdbPointer
= PeCoffLoaderGetPdbPointer (LoadedImage
->ImageBase
);
1453 if (PdbPointer
!= NULL
) {
1454 DEBUG ((DEBUG_VERBOSE
, "(%a) ", PdbPointer
));
1457 DEBUG ((DEBUG_VERBOSE
, "\n"));
1458 ZeroMem (&DriverEntry
, sizeof(DriverEntry
));
1459 DriverEntry
.ImageBuffer
= (UINTN
)LoadedImage
->ImageBase
;
1460 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES((UINTN
)LoadedImage
->ImageSize
);
1461 SmmInsertImageRecord (&DriverEntry
);
1464 FreePool (HandleBuffer
);
1468 Install MemoryAttributesTable.
1470 @param[in] Protocol Points to the protocol's unique identifier.
1471 @param[in] Interface Points to the interface instance.
1472 @param[in] Handle The handle on which the interface was installed.
1474 @retval EFI_SUCCESS Notification runs successfully.
1478 SmmInstallMemoryAttributesTable (
1479 IN CONST EFI_GUID
*Protocol
,
1481 IN EFI_HANDLE Handle
1484 SmmInstallImageRecord ();
1486 DEBUG ((DEBUG_INFO
, "SMM MemoryProtectionAttribute - 0x%016lx\n", mMemoryProtectionAttribute
));
1487 if ((mMemoryProtectionAttribute
& EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
1491 DEBUG ((DEBUG_VERBOSE
, "SMM Total Image Count - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1492 DEBUG ((DEBUG_VERBOSE
, "SMM Dump ImageRecord:\n"));
1495 PublishMemoryAttributesTable ();
1501 Initialize MemoryAttributesTable support.
1505 SmmCoreInitializeMemoryAttributesTable (
1512 Status
= gSmst
->SmmRegisterProtocolNotify (
1513 &gEfiSmmEndOfDxeProtocolGuid
,
1514 SmmInstallMemoryAttributesTable
,
1517 ASSERT_EFI_ERROR (Status
);