• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   PI SMM MemoryAttributes support
3 
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
9 
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.
12 
13 **/
14 
15 #include <PiDxe.h>
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>
23 
24 #include <Library/PeCoffLib.h>
25 #include <Library/PeCoffGetEntryPointLib.h>
26 
27 #include <Guid/PiSmmMemoryAttributesTable.h>
28 
29 #include "PiSmmCore.h"
30 
31 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
32   ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
33 
34 #define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I','P','R','C')
35 
36 typedef struct {
37   UINT32                 Signature;
38   LIST_ENTRY             Link;
39   EFI_PHYSICAL_ADDRESS   CodeSegmentBase;
40   UINT64                 CodeSegmentSize;
41 } IMAGE_PROPERTIES_RECORD_CODE_SECTION;
42 
43 #define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D')
44 
45 typedef struct {
46   UINT32                 Signature;
47   LIST_ENTRY             Link;
48   EFI_PHYSICAL_ADDRESS   ImageBase;
49   UINT64                 ImageSize;
50   UINTN                  CodeSegmentCount;
51   LIST_ENTRY             CodeSegmentList;
52 } IMAGE_PROPERTIES_RECORD;
53 
54 #define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')
55 
56 typedef struct {
57   UINT32                 Signature;
58   UINTN                  ImageRecordCount;
59   UINTN                  CodeSegmentCountMax;
60   LIST_ENTRY             ImageRecordList;
61 } IMAGE_PROPERTIES_PRIVATE_DATA;
62 
63 IMAGE_PROPERTIES_PRIVATE_DATA  mImagePropertiesPrivateData = {
64   IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE,
65   0,
66   0,
67   INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData.ImageRecordList)
68 };
69 
70 #define EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA  BIT0
71 
72 UINT64 mMemoryProtectionAttribute = EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA;
73 
74 //
75 // Below functions are for MemoryMap
76 //
77 
78 /**
79   Converts a number of EFI_PAGEs to a size in bytes.
80 
81   NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
82 
83   @param[in]  Pages     The number of EFI_PAGES.
84 
85   @return  The number of bytes associated with the number of EFI_PAGEs specified
86            by Pages.
87 **/
88 STATIC
89 UINT64
EfiPagesToSize(IN UINT64 Pages)90 EfiPagesToSize (
91   IN UINT64 Pages
92   )
93 {
94   return LShiftU64 (Pages, EFI_PAGE_SHIFT);
95 }
96 
97 /**
98   Converts a size, in bytes, to a number of EFI_PAGESs.
99 
100   NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
101 
102   @param[in]  Size      A size in bytes.
103 
104   @return  The number of EFI_PAGESs associated with the number of bytes specified
105            by Size.
106 
107 **/
108 STATIC
109 UINT64
EfiSizeToPages(IN UINT64 Size)110 EfiSizeToPages (
111   IN UINT64 Size
112   )
113 {
114   return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0);
115 }
116 
117 /**
118   Check the consistency of Smm memory attributes table.
119 
120   @param[in] MemoryAttributesTable  PI SMM memory attributes table
121 **/
122 VOID
SmmMemoryAttributesTableConsistencyCheck(IN EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE * MemoryAttributesTable)123 SmmMemoryAttributesTableConsistencyCheck (
124   IN EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable
125   )
126 {
127   EFI_MEMORY_DESCRIPTOR                     *MemoryMap;
128   UINTN                                     MemoryMapEntryCount;
129   UINTN                                     DescriptorSize;
130   UINTN                                     Index;
131   UINT64                                    Address;
132 
133   Address = 0;
134   MemoryMapEntryCount = MemoryAttributesTable->NumberOfEntries;
135   DescriptorSize = MemoryAttributesTable->DescriptorSize;
136   MemoryMap = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1);
137   for (Index = 0; Index < MemoryMapEntryCount; Index++) {
138     if (Address != 0) {
139       ASSERT (Address == MemoryMap->PhysicalStart);
140     }
141     Address = MemoryMap->PhysicalStart + EfiPagesToSize(MemoryMap->NumberOfPages);
142     MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);
143   }
144 }
145 
146 /**
147   Sort memory map entries based upon PhysicalStart, from low to high.
148 
149   @param[in,out]  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.
153 **/
154 STATIC
155 VOID
SortMemoryMap(IN OUT EFI_MEMORY_DESCRIPTOR * MemoryMap,IN UINTN MemoryMapSize,IN UINTN DescriptorSize)156 SortMemoryMap (
157   IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
158   IN UINTN                      MemoryMapSize,
159   IN UINTN                      DescriptorSize
160   )
161 {
162   EFI_MEMORY_DESCRIPTOR       *MemoryMapEntry;
163   EFI_MEMORY_DESCRIPTOR       *NextMemoryMapEntry;
164   EFI_MEMORY_DESCRIPTOR       *MemoryMapEnd;
165   EFI_MEMORY_DESCRIPTOR       TempMemoryMap;
166 
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));
176       }
177 
178       NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
179     }
180 
181     MemoryMapEntry      = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
182     NextMemoryMapEntry  = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
183   }
184 
185   return ;
186 }
187 
188 /**
189   Merge continous memory map entries whose have same attributes.
190 
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.
198 **/
199 STATIC
200 VOID
MergeMemoryMap(IN OUT EFI_MEMORY_DESCRIPTOR * MemoryMap,IN OUT UINTN * MemoryMapSize,IN UINTN DescriptorSize)201 MergeMemoryMap (
202   IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
203   IN OUT UINTN                  *MemoryMapSize,
204   IN UINTN                      DescriptorSize
205   )
206 {
207   EFI_MEMORY_DESCRIPTOR       *MemoryMapEntry;
208   EFI_MEMORY_DESCRIPTOR       *MemoryMapEnd;
209   UINT64                      MemoryBlockLength;
210   EFI_MEMORY_DESCRIPTOR       *NewMemoryMapEntry;
211   EFI_MEMORY_DESCRIPTOR       *NextMemoryMapEntry;
212 
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);
219 
220     do {
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;
229         }
230 
231         NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
232         continue;
233       } else {
234         MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
235         break;
236       }
237     } while (TRUE);
238 
239     MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
240     NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);
241   }
242 
243   *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;
244 
245   return ;
246 }
247 
248 /**
249   Enforce memory map attributes.
250   This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
251 
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.
256 **/
257 STATIC
258 VOID
EnforceMemoryMapAttribute(IN OUT EFI_MEMORY_DESCRIPTOR * MemoryMap,IN UINTN MemoryMapSize,IN UINTN DescriptorSize)259 EnforceMemoryMapAttribute (
260   IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
261   IN UINTN                      MemoryMapSize,
262   IN UINTN                      DescriptorSize
263   )
264 {
265   EFI_MEMORY_DESCRIPTOR       *MemoryMapEntry;
266   EFI_MEMORY_DESCRIPTOR       *MemoryMapEnd;
267 
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.
273     } else {
274       switch (MemoryMapEntry->Type) {
275       case EfiRuntimeServicesCode:
276         MemoryMapEntry->Attribute = EFI_MEMORY_RO;
277         break;
278       case EfiRuntimeServicesData:
279       default:
280         MemoryMapEntry->Attribute |= EFI_MEMORY_XP;
281         break;
282       }
283     }
284     MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
285   }
286 
287   return ;
288 }
289 
290 /**
291   Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
292 
293   @param[in] Buffer  Start Address
294   @param[in] Length  Address length
295 
296   @return first image record covered by [buffer, length]
297 **/
298 STATIC
299 IMAGE_PROPERTIES_RECORD *
GetImageRecordByAddress(IN EFI_PHYSICAL_ADDRESS Buffer,IN UINT64 Length)300 GetImageRecordByAddress (
301   IN EFI_PHYSICAL_ADDRESS  Buffer,
302   IN UINT64                Length
303   )
304 {
305   IMAGE_PROPERTIES_RECORD    *ImageRecord;
306   LIST_ENTRY                 *ImageRecordLink;
307   LIST_ENTRY                 *ImageRecordList;
308 
309   ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
310 
311   for (ImageRecordLink = ImageRecordList->ForwardLink;
312        ImageRecordLink != ImageRecordList;
313        ImageRecordLink = ImageRecordLink->ForwardLink) {
314     ImageRecord = CR (
315                     ImageRecordLink,
316                     IMAGE_PROPERTIES_RECORD,
317                     Link,
318                     IMAGE_PROPERTIES_RECORD_SIGNATURE
319                     );
320 
321     if ((Buffer <= ImageRecord->ImageBase) &&
322         (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize)) {
323       return ImageRecord;
324     }
325   }
326 
327   return NULL;
328 }
329 
330 /**
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
333 
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
339                                           below.
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.
342 **/
343 STATIC
344 UINTN
SetNewRecord(IN IMAGE_PROPERTIES_RECORD * ImageRecord,IN OUT EFI_MEMORY_DESCRIPTOR * NewRecord,IN EFI_MEMORY_DESCRIPTOR * OldRecord,IN UINTN DescriptorSize)345 SetNewRecord (
346   IN IMAGE_PROPERTIES_RECORD       *ImageRecord,
347   IN OUT EFI_MEMORY_DESCRIPTOR     *NewRecord,
348   IN EFI_MEMORY_DESCRIPTOR         *OldRecord,
349   IN UINTN                         DescriptorSize
350   )
351 {
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;
358   UINT64                                    PhysicalEnd;
359   UINT64                                    ImageEnd;
360 
361   CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR));
362   PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);
363   NewRecordCount = 0;
364 
365   //
366   // Always create a new entry for non-PE image record
367   //
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);
375     NewRecordCount ++;
376     TempRecord.PhysicalStart = ImageRecord->ImageBase;
377     TempRecord.NumberOfPages = EfiSizeToPages(PhysicalEnd - TempRecord.PhysicalStart);
378   }
379 
380   ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
381 
382   ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
383   ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
384   while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
385     ImageRecordCodeSection = CR (
386                                ImageRecordCodeSectionLink,
387                                IMAGE_PROPERTIES_RECORD_CODE_SECTION,
388                                Link,
389                                IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
390                                );
391     ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
392 
393     if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) {
394       //
395       // DATA
396       //
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);
404         NewRecordCount ++;
405       }
406 
407       //
408       // CODE
409       //
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);
417         NewRecordCount ++;
418       }
419 
420       TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize));
421       TempRecord.NumberOfPages = EfiSizeToPages(PhysicalEnd - TempRecord.PhysicalStart);
422       if (TempRecord.NumberOfPages == 0) {
423         break;
424       }
425     }
426   }
427 
428   ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;
429 
430   //
431   // Final DATA
432   //
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;
439     NewRecordCount ++;
440   }
441 
442   return NewRecordCount;
443 }
444 
445 /**
446   Return the max number of new splitted entries, according to one old entry,
447   based upon PE code section and data section.
448 
449   @param[in]  OldRecord              A pointer to one old memory map entry.
450 
451   @retval  0 no entry need to be splitted.
452   @return  the max number of new splitted entries
453 **/
454 STATIC
455 UINTN
GetMaxSplitRecordCount(IN EFI_MEMORY_DESCRIPTOR * OldRecord)456 GetMaxSplitRecordCount (
457   IN EFI_MEMORY_DESCRIPTOR *OldRecord
458   )
459 {
460   IMAGE_PROPERTIES_RECORD *ImageRecord;
461   UINTN                   SplitRecordCount;
462   UINT64                  PhysicalStart;
463   UINT64                  PhysicalEnd;
464 
465   SplitRecordCount = 0;
466   PhysicalStart = OldRecord->PhysicalStart;
467   PhysicalEnd = OldRecord->PhysicalStart + EfiPagesToSize(OldRecord->NumberOfPages);
468 
469   do {
470     ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
471     if (ImageRecord == NULL) {
472       break;
473     }
474     SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 2);
475     PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;
476   } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
477 
478   return SplitRecordCount;
479 }
480 
481 /**
482   Split the memory map to new entries, according to one old entry,
483   based upon PE code section and data section.
484 
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
489                                           below.
490   @param[in]       MaxSplitRecordCount    The max number of splitted entries
491   @param[in]       DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
492 
493   @retval  0 no entry is splitted.
494   @return  the real number of splitted record.
495 **/
496 STATIC
497 UINTN
SplitRecord(IN EFI_MEMORY_DESCRIPTOR * OldRecord,IN OUT EFI_MEMORY_DESCRIPTOR * NewRecord,IN UINTN MaxSplitRecordCount,IN UINTN DescriptorSize)498 SplitRecord (
499   IN EFI_MEMORY_DESCRIPTOR     *OldRecord,
500   IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord,
501   IN UINTN                     MaxSplitRecordCount,
502   IN UINTN                     DescriptorSize
503   )
504 {
505   EFI_MEMORY_DESCRIPTOR   TempRecord;
506   IMAGE_PROPERTIES_RECORD *ImageRecord;
507   IMAGE_PROPERTIES_RECORD *NewImageRecord;
508   UINT64                  PhysicalStart;
509   UINT64                  PhysicalEnd;
510   UINTN                   NewRecordCount;
511   UINTN                   TotalNewRecordCount;
512 
513   if (MaxSplitRecordCount == 0) {
514     CopyMem (NewRecord, OldRecord, DescriptorSize);
515     return 0;
516   }
517 
518   TotalNewRecordCount = 0;
519 
520   //
521   // Override previous record
522   //
523   CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR));
524   PhysicalStart = TempRecord.PhysicalStart;
525   PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);
526 
527   ImageRecord = NULL;
528   do {
529     NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
530     if (NewImageRecord == NULL) {
531       //
532       // No more image covered by this range, stop
533       //
534       if (PhysicalEnd > PhysicalStart) {
535         //
536         // Always create a new entry for non-PE image record
537         //
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 ++;
544       }
545       break;
546     }
547     ImageRecord = NewImageRecord;
548 
549     //
550     // Set new record
551     //
552     NewRecordCount = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize);
553     TotalNewRecordCount += NewRecordCount;
554     NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize);
555 
556     //
557     // Update PhysicalStart, in order to exclude the image buffer already splitted.
558     //
559     PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;
560     TempRecord.PhysicalStart = PhysicalStart;
561     TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
562   } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
563 
564   return TotalNewRecordCount - 1;
565 }
566 
567 /**
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.
571 
572   NOTE: It assumes PE code/data section are page aligned.
573   NOTE: It assumes enough entry is prepared for new memory map.
574 
575   Split table:
576    +---------------+
577    | Record X      |
578    +---------------+
579    | Record RtCode |
580    +---------------+
581    | Record Y      |
582    +---------------+
583    ==>
584    +---------------+
585    | Record X      |
586    +---------------+
587    | Record RtCode |
588    +---------------+ ----
589    | Record RtData |     |
590    +---------------+     |
591    | Record RtCode |     |-> PE/COFF1
592    +---------------+     |
593    | Record RtData |     |
594    +---------------+ ----
595    | Record RtCode |
596    +---------------+ ----
597    | Record RtData |     |
598    +---------------+     |
599    | Record RtCode |     |-> PE/COFF2
600    +---------------+     |
601    | Record RtData |     |
602    +---------------+ ----
603    | Record RtCode |
604    +---------------+
605    | Record Y      |
606    +---------------+
607 
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
614                                           after split.
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.
618 **/
619 STATIC
620 VOID
SplitTable(IN OUT UINTN * MemoryMapSize,IN OUT EFI_MEMORY_DESCRIPTOR * MemoryMap,IN UINTN DescriptorSize)621 SplitTable (
622   IN OUT UINTN                  *MemoryMapSize,
623   IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
624   IN UINTN                      DescriptorSize
625   )
626 {
627   INTN        IndexOld;
628   INTN        IndexNew;
629   UINTN       MaxSplitRecordCount;
630   UINTN       RealSplitRecordCount;
631   UINTN       TotalSplitRecordCount;
632   UINTN       AdditionalRecordCount;
633 
634   AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 2) * mImagePropertiesPrivateData.ImageRecordCount;
635 
636   TotalSplitRecordCount = 0;
637   //
638   // Let old record point to end of valid MemoryMap buffer.
639   //
640   IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1;
641   //
642   // Let new record point to end of full MemoryMap buffer.
643   //
644   IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + AdditionalRecordCount;
645   for (; IndexOld >= 0; IndexOld--) {
646     MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize));
647     //
648     // Split this MemoryMap record
649     //
650     IndexNew -= MaxSplitRecordCount;
651     RealSplitRecordCount = SplitRecord (
652                              (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),
653                              (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
654                              MaxSplitRecordCount,
655                              DescriptorSize
656                              );
657     //
658     // Adjust IndexNew according to real split.
659     //
660     if (MaxSplitRecordCount != RealSplitRecordCount) {
661       CopyMem (
662         ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),
663         ((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
664         (RealSplitRecordCount + 1) * DescriptorSize
665         );
666     }
667     IndexNew = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;
668     TotalSplitRecordCount += RealSplitRecordCount;
669     IndexNew --;
670   }
671   //
672   // Move all records to the beginning.
673   //
674   CopyMem (
675     MemoryMap,
676     (UINT8 *)MemoryMap + (AdditionalRecordCount - TotalSplitRecordCount) * DescriptorSize,
677     (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize
678     );
679 
680   *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount;
681 
682   //
683   // Sort from low to high (Just in case)
684   //
685   SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);
686 
687   //
688   // Set RuntimeData to XP
689   //
690   EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, DescriptorSize);
691 
692   //
693   // Merge same type to save entry size
694   //
695   MergeMemoryMap (MemoryMap, MemoryMapSize, DescriptorSize);
696 
697   return ;
698 }
699 
700 /**
701   This function for GetMemoryMap() with memory attributes table.
702 
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.
705 
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.
723 
724   @retval EFI_SUCCESS            The memory map was returned in the MemoryMap
725                                  buffer.
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.
730 
731 **/
732 STATIC
733 EFI_STATUS
734 EFIAPI
SmmCoreGetMemoryMapMemoryAttributesTable(IN OUT UINTN * MemoryMapSize,IN OUT EFI_MEMORY_DESCRIPTOR * MemoryMap,OUT UINTN * MapKey,OUT UINTN * DescriptorSize,OUT UINT32 * DescriptorVersion)735 SmmCoreGetMemoryMapMemoryAttributesTable (
736   IN OUT UINTN                  *MemoryMapSize,
737   IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
738   OUT UINTN                     *MapKey,
739   OUT UINTN                     *DescriptorSize,
740   OUT UINT32                    *DescriptorVersion
741   )
742 {
743   EFI_STATUS  Status;
744   UINTN       OldMemoryMapSize;
745   UINTN       AdditionalRecordCount;
746 
747   //
748   // If PE code/data is not aligned, just return.
749   //
750   if ((mMemoryProtectionAttribute & EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {
751     return SmmCoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
752   }
753 
754   if (MemoryMapSize == NULL) {
755     return EFI_INVALID_PARAMETER;
756   }
757 
758   AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 2) * mImagePropertiesPrivateData.ImageRecordCount;
759 
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;
767       //
768       // Need update status to buffer too small
769       //
770       Status = EFI_BUFFER_TOO_SMALL;
771     } else {
772       //
773       // Split PE code/data
774       //
775       ASSERT(MemoryMap != NULL);
776       SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize);
777     }
778   }
779 
780   return Status;
781 }
782 
783 //
784 // Below functions are for ImageRecord
785 //
786 
787 /**
788   Set MemoryProtectionAttribute accroding to PE/COFF image section alignment.
789 
790   @param[in]  SectionAlignment    PE/COFF section alignment
791 **/
792 STATIC
793 VOID
SetMemoryAttributesTableSectionAlignment(IN UINT32 SectionAlignment)794 SetMemoryAttributesTableSectionAlignment (
795   IN UINT32  SectionAlignment
796   )
797 {
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);
802   }
803 }
804 
805 /**
806   Swap two code sections in image record.
807 
808   @param[in]  FirstImageRecordCodeSection    first code section in image record
809   @param[in]  SecondImageRecordCodeSection   second code section in image record
810 **/
811 STATIC
812 VOID
SwapImageRecordCodeSection(IN IMAGE_PROPERTIES_RECORD_CODE_SECTION * FirstImageRecordCodeSection,IN IMAGE_PROPERTIES_RECORD_CODE_SECTION * SecondImageRecordCodeSection)813 SwapImageRecordCodeSection (
814   IN IMAGE_PROPERTIES_RECORD_CODE_SECTION      *FirstImageRecordCodeSection,
815   IN IMAGE_PROPERTIES_RECORD_CODE_SECTION      *SecondImageRecordCodeSection
816   )
817 {
818   IMAGE_PROPERTIES_RECORD_CODE_SECTION      TempImageRecordCodeSection;
819 
820   TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase;
821   TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize;
822 
823   FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase;
824   FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize;
825 
826   SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase;
827   SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize;
828 }
829 
830 /**
831   Sort code section in image record, based upon CodeSegmentBase from low to high.
832 
833   @param[in]  ImageRecord    image record to be sorted
834 **/
835 STATIC
836 VOID
SortImageRecordCodeSection(IN IMAGE_PROPERTIES_RECORD * ImageRecord)837 SortImageRecordCodeSection (
838   IN IMAGE_PROPERTIES_RECORD              *ImageRecord
839   )
840 {
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;
847 
848   ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
849 
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,
857                                Link,
858                                IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
859                                );
860     while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
861       NextImageRecordCodeSection = CR (
862                                      NextImageRecordCodeSectionLink,
863                                      IMAGE_PROPERTIES_RECORD_CODE_SECTION,
864                                      Link,
865                                      IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
866                                      );
867       if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) {
868         SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);
869       }
870       NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;
871     }
872 
873     ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
874     NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
875   }
876 }
877 
878 /**
879   Check if code section in image record is valid.
880 
881   @param[in]  ImageRecord    image record to be checked
882 
883   @retval TRUE  image record is valid
884   @retval FALSE image record is invalid
885 **/
886 STATIC
887 BOOLEAN
IsImageRecordCodeSectionValid(IN IMAGE_PROPERTIES_RECORD * ImageRecord)888 IsImageRecordCodeSectionValid (
889   IN IMAGE_PROPERTIES_RECORD              *ImageRecord
890   )
891 {
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;
897 
898   DEBUG ((DEBUG_VERBOSE, "SMM ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));
899 
900   ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
901 
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,
909                                Link,
910                                IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
911                                );
912     if (ImageRecordCodeSection->CodeSegmentSize == 0) {
913       return FALSE;
914     }
915     if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) {
916       return FALSE;
917     }
918     if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) {
919       return FALSE;
920     }
921     if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
922       return FALSE;
923     }
924     if (LastImageRecordCodeSection != NULL) {
925       if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) {
926         return FALSE;
927       }
928     }
929 
930     LastImageRecordCodeSection = ImageRecordCodeSection;
931     ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
932   }
933 
934   return TRUE;
935 }
936 
937 /**
938   Swap two image records.
939 
940   @param[in]  FirstImageRecord   first image record.
941   @param[in]  SecondImageRecord  second image record.
942 **/
943 STATIC
944 VOID
SwapImageRecord(IN IMAGE_PROPERTIES_RECORD * FirstImageRecord,IN IMAGE_PROPERTIES_RECORD * SecondImageRecord)945 SwapImageRecord (
946   IN IMAGE_PROPERTIES_RECORD      *FirstImageRecord,
947   IN IMAGE_PROPERTIES_RECORD      *SecondImageRecord
948   )
949 {
950   IMAGE_PROPERTIES_RECORD      TempImageRecord;
951 
952   TempImageRecord.ImageBase = FirstImageRecord->ImageBase;
953   TempImageRecord.ImageSize = FirstImageRecord->ImageSize;
954   TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;
955 
956   FirstImageRecord->ImageBase = SecondImageRecord->ImageBase;
957   FirstImageRecord->ImageSize = SecondImageRecord->ImageSize;
958   FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount;
959 
960   SecondImageRecord->ImageBase = TempImageRecord.ImageBase;
961   SecondImageRecord->ImageSize = TempImageRecord.ImageSize;
962   SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount;
963 
964   SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList);
965 }
966 
967 /**
968   Sort image record based upon the ImageBase from low to high.
969 **/
970 STATIC
971 VOID
SortImageRecord(VOID)972 SortImageRecord (
973   VOID
974   )
975 {
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;
982 
983   ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
984 
985   ImageRecordLink = ImageRecordList->ForwardLink;
986   NextImageRecordLink = ImageRecordLink->ForwardLink;
987   ImageRecordEndLink = ImageRecordList;
988   while (ImageRecordLink != ImageRecordEndLink) {
989     ImageRecord = CR (
990                     ImageRecordLink,
991                     IMAGE_PROPERTIES_RECORD,
992                     Link,
993                     IMAGE_PROPERTIES_RECORD_SIGNATURE
994                     );
995     while (NextImageRecordLink != ImageRecordEndLink) {
996       NextImageRecord = CR (
997                           NextImageRecordLink,
998                           IMAGE_PROPERTIES_RECORD,
999                           Link,
1000                           IMAGE_PROPERTIES_RECORD_SIGNATURE
1001                           );
1002       if (ImageRecord->ImageBase > NextImageRecord->ImageBase) {
1003         SwapImageRecord (ImageRecord, NextImageRecord);
1004       }
1005       NextImageRecordLink = NextImageRecordLink->ForwardLink;
1006     }
1007 
1008     ImageRecordLink = ImageRecordLink->ForwardLink;
1009     NextImageRecordLink = ImageRecordLink->ForwardLink;
1010   }
1011 }
1012 
1013 /**
1014   Dump image record.
1015 **/
1016 STATIC
1017 VOID
DumpImageRecord(VOID)1018 DumpImageRecord (
1019   VOID
1020   )
1021 {
1022   IMAGE_PROPERTIES_RECORD      *ImageRecord;
1023   LIST_ENTRY                   *ImageRecordLink;
1024   LIST_ENTRY                   *ImageRecordList;
1025   UINTN                        Index;
1026 
1027   ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
1028 
1029   for (ImageRecordLink = ImageRecordList->ForwardLink, Index= 0;
1030        ImageRecordLink != ImageRecordList;
1031        ImageRecordLink = ImageRecordLink->ForwardLink, Index++) {
1032     ImageRecord = CR (
1033                     ImageRecordLink,
1034                     IMAGE_PROPERTIES_RECORD,
1035                     Link,
1036                     IMAGE_PROPERTIES_RECORD_SIGNATURE
1037                     );
1038     DEBUG ((DEBUG_VERBOSE, "SMM  Image[%d]: 0x%016lx - 0x%016lx\n", Index, ImageRecord->ImageBase, ImageRecord->ImageSize));
1039   }
1040 }
1041 
1042 /**
1043   Insert image record.
1044 
1045   @param[in]  DriverEntry    Driver information
1046 **/
1047 VOID
SmmInsertImageRecord(IN EFI_SMM_DRIVER_ENTRY * DriverEntry)1048 SmmInsertImageRecord (
1049   IN EFI_SMM_DRIVER_ENTRY  *DriverEntry
1050   )
1051 {
1052   VOID                                 *ImageAddress;
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;
1058   UINT8                                *Name;
1059   UINTN                                Index;
1060   IMAGE_PROPERTIES_RECORD              *ImageRecord;
1061   CHAR8                                *PdbPointer;
1062   IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
1063   UINT16                               Magic;
1064 
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));
1067 
1068   ImageRecord = AllocatePool (sizeof(*ImageRecord));
1069   if (ImageRecord == NULL) {
1070     return ;
1071   }
1072   ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;
1073 
1074   DEBUG ((DEBUG_VERBOSE, "SMM ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
1075 
1076   //
1077   // Step 1: record whole region
1078   //
1079   ImageRecord->ImageBase = DriverEntry->ImageBuffer;
1080   ImageRecord->ImageSize = EfiPagesToSize(DriverEntry->NumberOfPage);
1081 
1082   ImageAddress = (VOID *)(UINTN)DriverEntry->ImageBuffer;
1083 
1084   PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);
1085   if (PdbPointer != NULL) {
1086     DEBUG ((DEBUG_VERBOSE, "SMM   Image - %a\n", PdbPointer));
1087   }
1088 
1089   //
1090   // Check PE/COFF image
1091   //
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;
1096   }
1097 
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));
1101     goto Finish;
1102   }
1103 
1104   //
1105   // Get SectionAlignment
1106   //
1107   if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1108     //
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
1113     //
1114     Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
1115   } else {
1116     //
1117     // Get the magic value from the PE/COFF Optional Header
1118     //
1119     Magic = Hdr.Pe32->OptionalHeader.Magic;
1120   }
1121   if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1122     SectionAlignment  = Hdr.Pe32->OptionalHeader.SectionAlignment;
1123   } else {
1124     SectionAlignment  = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
1125   }
1126 
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));
1134     }
1135     goto Finish;
1136   }
1137 
1138   Section = (EFI_IMAGE_SECTION_HEADER *) (
1139                (UINT8 *) (UINTN) ImageAddress +
1140                PeCoffHeaderOffset +
1141                sizeof(UINT32) +
1142                sizeof(EFI_IMAGE_FILE_HEADER) +
1143                Hdr.Pe32->FileHeader.SizeOfOptionalHeader
1144                );
1145   ImageRecord->CodeSegmentCount = 0;
1146   InitializeListHead (&ImageRecord->CodeSegmentList);
1147   for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
1148     Name = Section[Index].Name;
1149     DEBUG ((
1150       DEBUG_VERBOSE,
1151       "SMM   Section - '%c%c%c%c%c%c%c%c'\n",
1152       Name[0],
1153       Name[1],
1154       Name[2],
1155       Name[3],
1156       Name[4],
1157       Name[5],
1158       Name[6],
1159       Name[7]
1160       ));
1161 
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));
1172 
1173       //
1174       // Step 2: record code section
1175       //
1176       ImageRecordCodeSection = AllocatePool (sizeof(*ImageRecordCodeSection));
1177       if (ImageRecordCodeSection == NULL) {
1178         return ;
1179       }
1180       ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
1181 
1182       ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress;
1183       ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData;
1184 
1185       DEBUG ((DEBUG_VERBOSE, "SMM ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize));
1186 
1187       InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);
1188       ImageRecord->CodeSegmentCount++;
1189     }
1190   }
1191 
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));
1198     }
1199     goto Finish;
1200   }
1201 
1202   //
1203   // Final
1204   //
1205   SortImageRecordCodeSection (ImageRecord);
1206   //
1207   // Check overlap all section in ImageBase/Size
1208   //
1209   if (!IsImageRecordCodeSectionValid (ImageRecord)) {
1210     DEBUG ((DEBUG_ERROR, "SMM IsImageRecordCodeSectionValid - FAIL\n"));
1211     goto Finish;
1212   }
1213 
1214   InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link);
1215   mImagePropertiesPrivateData.ImageRecordCount++;
1216 
1217   SortImageRecord ();
1218 
1219   if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) {
1220     mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;
1221   }
1222 
1223 Finish:
1224   return ;
1225 }
1226 
1227 /**
1228   Find image record accroding to image base and size.
1229 
1230   @param[in]  ImageBase    Base of PE image
1231   @param[in]  ImageSize    Size of PE image
1232 
1233   @return image record
1234 **/
1235 STATIC
1236 IMAGE_PROPERTIES_RECORD *
FindImageRecord(IN EFI_PHYSICAL_ADDRESS ImageBase,IN UINT64 ImageSize)1237 FindImageRecord (
1238   IN EFI_PHYSICAL_ADDRESS  ImageBase,
1239   IN UINT64                ImageSize
1240   )
1241 {
1242   IMAGE_PROPERTIES_RECORD    *ImageRecord;
1243   LIST_ENTRY                 *ImageRecordLink;
1244   LIST_ENTRY                 *ImageRecordList;
1245 
1246   ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
1247 
1248   for (ImageRecordLink = ImageRecordList->ForwardLink;
1249        ImageRecordLink != ImageRecordList;
1250        ImageRecordLink = ImageRecordLink->ForwardLink) {
1251     ImageRecord = CR (
1252                     ImageRecordLink,
1253                     IMAGE_PROPERTIES_RECORD,
1254                     Link,
1255                     IMAGE_PROPERTIES_RECORD_SIGNATURE
1256                     );
1257 
1258     if ((ImageBase == ImageRecord->ImageBase) &&
1259         (ImageSize == ImageRecord->ImageSize)) {
1260       return ImageRecord;
1261     }
1262   }
1263 
1264   return NULL;
1265 }
1266 
1267 /**
1268   Remove Image record.
1269 
1270   @param[in]  DriverEntry    Driver information
1271 **/
1272 VOID
SmmRemoveImageRecord(IN EFI_SMM_DRIVER_ENTRY * DriverEntry)1273 SmmRemoveImageRecord (
1274   IN EFI_SMM_DRIVER_ENTRY  *DriverEntry
1275   )
1276 {
1277   IMAGE_PROPERTIES_RECORD              *ImageRecord;
1278   LIST_ENTRY                           *CodeSegmentListHead;
1279   IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
1280 
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));
1283 
1284   ImageRecord = FindImageRecord (DriverEntry->ImageBuffer, EfiPagesToSize(DriverEntry->NumberOfPage));
1285   if (ImageRecord == NULL) {
1286     DEBUG ((DEBUG_ERROR, "SMM !!!!!!!! ImageRecord not found !!!!!!!!\n"));
1287     return ;
1288   }
1289 
1290   CodeSegmentListHead = &ImageRecord->CodeSegmentList;
1291   while (!IsListEmpty (CodeSegmentListHead)) {
1292     ImageRecordCodeSection = CR (
1293                                CodeSegmentListHead->ForwardLink,
1294                                IMAGE_PROPERTIES_RECORD_CODE_SECTION,
1295                                Link,
1296                                IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1297                                );
1298     RemoveEntryList (&ImageRecordCodeSection->Link);
1299     FreePool (ImageRecordCodeSection);
1300   }
1301 
1302   RemoveEntryList (&ImageRecord->Link);
1303   FreePool (ImageRecord);
1304   mImagePropertiesPrivateData.ImageRecordCount--;
1305 }
1306 
1307 /**
1308   Publish MemoryAttributesTable to SMM configuration table.
1309 **/
1310 VOID
PublishMemoryAttributesTable(VOID)1311 PublishMemoryAttributesTable (
1312   VOID
1313   )
1314 {
1315   UINTN                                MemoryMapSize;
1316   EFI_MEMORY_DESCRIPTOR                *MemoryMap;
1317   UINTN                                MapKey;
1318   UINTN                                DescriptorSize;
1319   UINT32                               DescriptorVersion;
1320   UINTN                                Index;
1321   EFI_STATUS                           Status;
1322   UINTN                                RuntimeEntryCount;
1323   EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;
1324   EFI_MEMORY_DESCRIPTOR                *MemoryAttributesEntry;
1325   UINTN                                MemoryAttributesTableSize;
1326 
1327   MemoryMapSize = 0;
1328   MemoryMap = NULL;
1329   Status = SmmCoreGetMemoryMapMemoryAttributesTable (
1330              &MemoryMapSize,
1331              MemoryMap,
1332              &MapKey,
1333              &DescriptorSize,
1334              &DescriptorVersion
1335              );
1336   ASSERT (Status == EFI_BUFFER_TOO_SMALL);
1337 
1338   do {
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));
1343 
1344     Status = SmmCoreGetMemoryMapMemoryAttributesTable (
1345                &MemoryMapSize,
1346                MemoryMap,
1347                &MapKey,
1348                &DescriptorSize,
1349                &DescriptorVersion
1350                );
1351     if (EFI_ERROR (Status)) {
1352       FreePool (MemoryMap);
1353     }
1354   } while (Status == EFI_BUFFER_TOO_SMALL);
1355 
1356   //
1357   // Allocate MemoryAttributesTable
1358   //
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);
1381 
1382     MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);
1383   }
1384 
1385   Status = gSmst->SmmInstallConfigurationTable (gSmst, &gEdkiiPiSmmMemoryAttributesTableGuid, MemoryAttributesTable, MemoryAttributesTableSize);
1386   ASSERT_EFI_ERROR (Status);
1387 }
1388 
1389 /**
1390   This function returns if image is inside SMRAM.
1391 
1392   @param[in] LoadedImage LoadedImage protocol instance for an image.
1393 
1394   @retval TRUE  the image is inside SMRAM.
1395   @retval FALSE the image is outside SMRAM.
1396 **/
1397 BOOLEAN
IsImageInsideSmram(IN EFI_LOADED_IMAGE_PROTOCOL * LoadedImage)1398 IsImageInsideSmram (
1399   IN EFI_LOADED_IMAGE_PROTOCOL   *LoadedImage
1400   )
1401 {
1402   UINTN  Index;
1403 
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)) {
1407       return TRUE;
1408     }
1409   }
1410 
1411   return FALSE;
1412 }
1413 
1414 /**
1415   This function installs all SMM image record information.
1416 **/
1417 VOID
SmmInstallImageRecord(VOID)1418 SmmInstallImageRecord (
1419   VOID
1420   )
1421 {
1422   EFI_STATUS                  Status;
1423   UINTN                       NoHandles;
1424   EFI_HANDLE                  *HandleBuffer;
1425   EFI_LOADED_IMAGE_PROTOCOL   *LoadedImage;
1426   UINTN                       Index;
1427   EFI_SMM_DRIVER_ENTRY        DriverEntry;
1428 
1429   Status = SmmLocateHandleBuffer (
1430              ByProtocol,
1431              &gEfiLoadedImageProtocolGuid,
1432              NULL,
1433              &NoHandles,
1434              &HandleBuffer
1435              );
1436   if (EFI_ERROR (Status)) {
1437     return ;
1438   }
1439 
1440   for (Index = 0; Index < NoHandles; Index++) {
1441     Status = gSmst->SmmHandleProtocol (
1442                       HandleBuffer[Index],
1443                       &gEfiLoadedImageProtocolGuid,
1444                       (VOID **)&LoadedImage
1445                       );
1446     if (EFI_ERROR (Status)) {
1447       continue;
1448     }
1449     DEBUG ((DEBUG_VERBOSE, "LoadedImage - 0x%x 0x%x ", LoadedImage->ImageBase, LoadedImage->ImageSize));
1450     {
1451       VOID *PdbPointer;
1452       PdbPointer = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);
1453       if (PdbPointer != NULL) {
1454         DEBUG ((DEBUG_VERBOSE, "(%a) ", PdbPointer));
1455       }
1456     }
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);
1462   }
1463 
1464   FreePool (HandleBuffer);
1465 }
1466 
1467 /**
1468   Install MemoryAttributesTable.
1469 
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.
1473 
1474   @retval EFI_SUCCESS   Notification runs successfully.
1475 **/
1476 EFI_STATUS
1477 EFIAPI
SmmInstallMemoryAttributesTable(IN CONST EFI_GUID * Protocol,IN VOID * Interface,IN EFI_HANDLE Handle)1478 SmmInstallMemoryAttributesTable (
1479   IN CONST EFI_GUID  *Protocol,
1480   IN VOID            *Interface,
1481   IN EFI_HANDLE      Handle
1482   )
1483 {
1484   SmmInstallImageRecord ();
1485 
1486   DEBUG ((DEBUG_INFO, "SMM MemoryProtectionAttribute - 0x%016lx\n", mMemoryProtectionAttribute));
1487   if ((mMemoryProtectionAttribute & EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {
1488     return EFI_SUCCESS;
1489   }
1490 
1491   DEBUG ((DEBUG_VERBOSE, "SMM Total Image Count - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
1492   DEBUG ((DEBUG_VERBOSE, "SMM Dump ImageRecord:\n"));
1493   DumpImageRecord ();
1494 
1495   PublishMemoryAttributesTable ();
1496 
1497   return EFI_SUCCESS;
1498 }
1499 
1500 /**
1501   Initialize MemoryAttributesTable support.
1502 **/
1503 VOID
1504 EFIAPI
SmmCoreInitializeMemoryAttributesTable(VOID)1505 SmmCoreInitializeMemoryAttributesTable (
1506   VOID
1507   )
1508 {
1509   EFI_STATUS                        Status;
1510   VOID                              *Registration;
1511 
1512   Status = gSmst->SmmRegisterProtocolNotify (
1513                     &gEfiSmmEndOfDxeProtocolGuid,
1514                     SmmInstallMemoryAttributesTable,
1515                     &Registration
1516                     );
1517   ASSERT_EFI_ERROR (Status);
1518 
1519   return ;
1520 }
1521