Home | History | Annotate | Download | only in PiSmmCore
      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
     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
    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
    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
    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
    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
    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 *
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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 *
   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
   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
   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
   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
   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
   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
   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