REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			1392 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1392 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  PI SMM MemoryAttributes support
 | 
						|
 | 
						|
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <PiDxe.h>
 | 
						|
#include <Library/BaseLib.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Library/UefiBootServicesTableLib.h>
 | 
						|
#include <Library/SmmServicesTableLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/PcdLib.h>
 | 
						|
 | 
						|
#include <Library/PeCoffLib.h>
 | 
						|
#include <Library/PeCoffGetEntryPointLib.h>
 | 
						|
 | 
						|
#include <Guid/PiSmmMemoryAttributesTable.h>
 | 
						|
 | 
						|
#include "PiSmmCore.h"
 | 
						|
 | 
						|
#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
 | 
						|
  ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
 | 
						|
 | 
						|
#define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE  SIGNATURE_32 ('I','P','R','C')
 | 
						|
 | 
						|
typedef struct {
 | 
						|
  UINT32                  Signature;
 | 
						|
  LIST_ENTRY              Link;
 | 
						|
  EFI_PHYSICAL_ADDRESS    CodeSegmentBase;
 | 
						|
  UINT64                  CodeSegmentSize;
 | 
						|
} IMAGE_PROPERTIES_RECORD_CODE_SECTION;
 | 
						|
 | 
						|
#define IMAGE_PROPERTIES_RECORD_SIGNATURE  SIGNATURE_32 ('I','P','R','D')
 | 
						|
 | 
						|
typedef struct {
 | 
						|
  UINT32                  Signature;
 | 
						|
  LIST_ENTRY              Link;
 | 
						|
  EFI_PHYSICAL_ADDRESS    ImageBase;
 | 
						|
  UINT64                  ImageSize;
 | 
						|
  UINTN                   CodeSegmentCount;
 | 
						|
  LIST_ENTRY              CodeSegmentList;
 | 
						|
} IMAGE_PROPERTIES_RECORD;
 | 
						|
 | 
						|
#define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('I','P','P','D')
 | 
						|
 | 
						|
typedef struct {
 | 
						|
  UINT32        Signature;
 | 
						|
  UINTN         ImageRecordCount;
 | 
						|
  UINTN         CodeSegmentCountMax;
 | 
						|
  LIST_ENTRY    ImageRecordList;
 | 
						|
} IMAGE_PROPERTIES_PRIVATE_DATA;
 | 
						|
 | 
						|
IMAGE_PROPERTIES_PRIVATE_DATA  mImagePropertiesPrivateData = {
 | 
						|
  IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE,
 | 
						|
  0,
 | 
						|
  0,
 | 
						|
  INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData.ImageRecordList)
 | 
						|
};
 | 
						|
 | 
						|
#define EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA  BIT0
 | 
						|
 | 
						|
UINT64  mMemoryProtectionAttribute = EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA;
 | 
						|
 | 
						|
//
 | 
						|
// Below functions are for MemoryMap
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Converts a number of EFI_PAGEs to a size in bytes.
 | 
						|
 | 
						|
  NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
 | 
						|
 | 
						|
  @param[in]  Pages     The number of EFI_PAGES.
 | 
						|
 | 
						|
  @return  The number of bytes associated with the number of EFI_PAGEs specified
 | 
						|
           by Pages.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
UINT64
 | 
						|
EfiPagesToSize (
 | 
						|
  IN UINT64  Pages
 | 
						|
  )
 | 
						|
{
 | 
						|
  return LShiftU64 (Pages, EFI_PAGE_SHIFT);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Converts a size, in bytes, to a number of EFI_PAGESs.
 | 
						|
 | 
						|
  NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
 | 
						|
 | 
						|
  @param[in]  Size      A size in bytes.
 | 
						|
 | 
						|
  @return  The number of EFI_PAGESs associated with the number of bytes specified
 | 
						|
           by Size.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
UINT64
 | 
						|
EfiSizeToPages (
 | 
						|
  IN UINT64  Size
 | 
						|
  )
 | 
						|
{
 | 
						|
  return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Sort memory map entries based upon PhysicalStart, from low to high.
 | 
						|
 | 
						|
  @param[in,out]  MemoryMap         A pointer to the buffer in which firmware places
 | 
						|
                                    the current memory map.
 | 
						|
  @param[in]      MemoryMapSize     Size, in bytes, of the MemoryMap buffer.
 | 
						|
  @param[in]      DescriptorSize    Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
SortMemoryMap (
 | 
						|
  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
 | 
						|
  IN UINTN                      MemoryMapSize,
 | 
						|
  IN UINTN                      DescriptorSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_MEMORY_DESCRIPTOR  *MemoryMapEntry;
 | 
						|
  EFI_MEMORY_DESCRIPTOR  *NextMemoryMapEntry;
 | 
						|
  EFI_MEMORY_DESCRIPTOR  *MemoryMapEnd;
 | 
						|
  EFI_MEMORY_DESCRIPTOR  TempMemoryMap;
 | 
						|
 | 
						|
  MemoryMapEntry     = MemoryMap;
 | 
						|
  NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
 | 
						|
  MemoryMapEnd       = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
 | 
						|
  while (MemoryMapEntry < MemoryMapEnd) {
 | 
						|
    while (NextMemoryMapEntry < MemoryMapEnd) {
 | 
						|
      if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {
 | 
						|
        CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
 | 
						|
        CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
 | 
						|
        CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof (EFI_MEMORY_DESCRIPTOR));
 | 
						|
      }
 | 
						|
 | 
						|
      NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
 | 
						|
    }
 | 
						|
 | 
						|
    MemoryMapEntry     = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
 | 
						|
    NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
 | 
						|
  }
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Merge continuous memory map entries whose have same attributes.
 | 
						|
 | 
						|
  @param[in, out]  MemoryMap              A pointer to the buffer in which firmware places
 | 
						|
                                          the current memory map.
 | 
						|
  @param[in, out]  MemoryMapSize          A pointer to the size, in bytes, of the
 | 
						|
                                          MemoryMap buffer. On input, this is the size of
 | 
						|
                                          the current memory map.  On output,
 | 
						|
                                          it is the size of new memory map after merge.
 | 
						|
  @param[in]       DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
MergeMemoryMap (
 | 
						|
  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
 | 
						|
  IN OUT UINTN                  *MemoryMapSize,
 | 
						|
  IN UINTN                      DescriptorSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_MEMORY_DESCRIPTOR  *MemoryMapEntry;
 | 
						|
  EFI_MEMORY_DESCRIPTOR  *MemoryMapEnd;
 | 
						|
  UINT64                 MemoryBlockLength;
 | 
						|
  EFI_MEMORY_DESCRIPTOR  *NewMemoryMapEntry;
 | 
						|
  EFI_MEMORY_DESCRIPTOR  *NextMemoryMapEntry;
 | 
						|
 | 
						|
  MemoryMapEntry    = MemoryMap;
 | 
						|
  NewMemoryMapEntry = MemoryMap;
 | 
						|
  MemoryMapEnd      = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + *MemoryMapSize);
 | 
						|
  while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
 | 
						|
    CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
 | 
						|
    NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
 | 
						|
 | 
						|
    do {
 | 
						|
      MemoryBlockLength = (UINT64)(EfiPagesToSize (MemoryMapEntry->NumberOfPages));
 | 
						|
      if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
 | 
						|
          (MemoryMapEntry->Type == NextMemoryMapEntry->Type) &&
 | 
						|
          (MemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) &&
 | 
						|
          ((MemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart))
 | 
						|
      {
 | 
						|
        MemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
 | 
						|
        if (NewMemoryMapEntry != MemoryMapEntry) {
 | 
						|
          NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
 | 
						|
        }
 | 
						|
 | 
						|
        NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
 | 
						|
        continue;
 | 
						|
      } else {
 | 
						|
        MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    } while (TRUE);
 | 
						|
 | 
						|
    MemoryMapEntry    = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
 | 
						|
    NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);
 | 
						|
  }
 | 
						|
 | 
						|
  *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Enforce memory map attributes.
 | 
						|
  This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
 | 
						|
 | 
						|
  @param[in, out]  MemoryMap              A pointer to the buffer in which firmware places
 | 
						|
                                          the current memory map.
 | 
						|
  @param[in]       MemoryMapSize          Size, in bytes, of the MemoryMap buffer.
 | 
						|
  @param[in]       DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
EnforceMemoryMapAttribute (
 | 
						|
  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
 | 
						|
  IN UINTN                      MemoryMapSize,
 | 
						|
  IN UINTN                      DescriptorSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_MEMORY_DESCRIPTOR  *MemoryMapEntry;
 | 
						|
  EFI_MEMORY_DESCRIPTOR  *MemoryMapEnd;
 | 
						|
 | 
						|
  MemoryMapEntry = MemoryMap;
 | 
						|
  MemoryMapEnd   = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
 | 
						|
  while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
 | 
						|
    if (MemoryMapEntry->Attribute != 0) {
 | 
						|
      // It is PE image, the attribute is already set.
 | 
						|
    } else {
 | 
						|
      switch (MemoryMapEntry->Type) {
 | 
						|
        case EfiRuntimeServicesCode:
 | 
						|
          MemoryMapEntry->Attribute = EFI_MEMORY_RO;
 | 
						|
          break;
 | 
						|
        case EfiRuntimeServicesData:
 | 
						|
        default:
 | 
						|
          MemoryMapEntry->Attribute |= EFI_MEMORY_XP;
 | 
						|
          break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
 | 
						|
  }
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
 | 
						|
 | 
						|
  @param[in] Buffer  Start Address
 | 
						|
  @param[in] Length  Address length
 | 
						|
 | 
						|
  @return first image record covered by [buffer, length]
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
IMAGE_PROPERTIES_RECORD *
 | 
						|
GetImageRecordByAddress (
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  Buffer,
 | 
						|
  IN UINT64                Length
 | 
						|
  )
 | 
						|
{
 | 
						|
  IMAGE_PROPERTIES_RECORD  *ImageRecord;
 | 
						|
  LIST_ENTRY               *ImageRecordLink;
 | 
						|
  LIST_ENTRY               *ImageRecordList;
 | 
						|
 | 
						|
  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
 | 
						|
 | 
						|
  for (ImageRecordLink = ImageRecordList->ForwardLink;
 | 
						|
       ImageRecordLink != ImageRecordList;
 | 
						|
       ImageRecordLink = ImageRecordLink->ForwardLink)
 | 
						|
  {
 | 
						|
    ImageRecord = CR (
 | 
						|
                    ImageRecordLink,
 | 
						|
                    IMAGE_PROPERTIES_RECORD,
 | 
						|
                    Link,
 | 
						|
                    IMAGE_PROPERTIES_RECORD_SIGNATURE
 | 
						|
                    );
 | 
						|
 | 
						|
    if ((Buffer <= ImageRecord->ImageBase) &&
 | 
						|
        (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize))
 | 
						|
    {
 | 
						|
      return ImageRecord;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Set the memory map to new entries, according to one old entry,
 | 
						|
  based upon PE code section and data section in image record
 | 
						|
 | 
						|
  @param[in]       ImageRecord            An image record whose [ImageBase, ImageSize] covered
 | 
						|
                                          by old memory map entry.
 | 
						|
  @param[in, out]  NewRecord              A pointer to several new memory map entries.
 | 
						|
                                          The caller guarantee the buffer size be 1 +
 | 
						|
                                          (SplitRecordCount * DescriptorSize) calculated
 | 
						|
                                          below.
 | 
						|
  @param[in]       OldRecord              A pointer to one old memory map entry.
 | 
						|
  @param[in]       DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
UINTN
 | 
						|
SetNewRecord (
 | 
						|
  IN IMAGE_PROPERTIES_RECORD    *ImageRecord,
 | 
						|
  IN OUT EFI_MEMORY_DESCRIPTOR  *NewRecord,
 | 
						|
  IN EFI_MEMORY_DESCRIPTOR      *OldRecord,
 | 
						|
  IN UINTN                      DescriptorSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_MEMORY_DESCRIPTOR                 TempRecord;
 | 
						|
  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
 | 
						|
  LIST_ENTRY                            *ImageRecordCodeSectionLink;
 | 
						|
  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
 | 
						|
  LIST_ENTRY                            *ImageRecordCodeSectionList;
 | 
						|
  UINTN                                 NewRecordCount;
 | 
						|
  UINT64                                PhysicalEnd;
 | 
						|
  UINT64                                ImageEnd;
 | 
						|
 | 
						|
  CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR));
 | 
						|
  PhysicalEnd    = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages);
 | 
						|
  NewRecordCount = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Always create a new entry for non-PE image record
 | 
						|
  //
 | 
						|
  if (ImageRecord->ImageBase > TempRecord.PhysicalStart) {
 | 
						|
    NewRecord->Type          = TempRecord.Type;
 | 
						|
    NewRecord->PhysicalStart = TempRecord.PhysicalStart;
 | 
						|
    NewRecord->VirtualStart  = 0;
 | 
						|
    NewRecord->NumberOfPages = EfiSizeToPages (ImageRecord->ImageBase - TempRecord.PhysicalStart);
 | 
						|
    NewRecord->Attribute     = TempRecord.Attribute;
 | 
						|
    NewRecord                = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
 | 
						|
    NewRecordCount++;
 | 
						|
    TempRecord.PhysicalStart = ImageRecord->ImageBase;
 | 
						|
    TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - TempRecord.PhysicalStart);
 | 
						|
  }
 | 
						|
 | 
						|
  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
 | 
						|
 | 
						|
  ImageRecordCodeSectionLink    = ImageRecordCodeSectionList->ForwardLink;
 | 
						|
  ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
 | 
						|
  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
 | 
						|
    ImageRecordCodeSection = CR (
 | 
						|
                               ImageRecordCodeSectionLink,
 | 
						|
                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
 | 
						|
                               Link,
 | 
						|
                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
 | 
						|
                               );
 | 
						|
    ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
 | 
						|
 | 
						|
    if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) {
 | 
						|
      //
 | 
						|
      // DATA
 | 
						|
      //
 | 
						|
      NewRecord->Type          = EfiRuntimeServicesData;
 | 
						|
      NewRecord->PhysicalStart = TempRecord.PhysicalStart;
 | 
						|
      NewRecord->VirtualStart  = 0;
 | 
						|
      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart);
 | 
						|
      NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
 | 
						|
      if (NewRecord->NumberOfPages != 0) {
 | 
						|
        NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
 | 
						|
        NewRecordCount++;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // CODE
 | 
						|
      //
 | 
						|
      NewRecord->Type          = EfiRuntimeServicesCode;
 | 
						|
      NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase;
 | 
						|
      NewRecord->VirtualStart  = 0;
 | 
						|
      NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize);
 | 
						|
      NewRecord->Attribute     = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO;
 | 
						|
      if (NewRecord->NumberOfPages != 0) {
 | 
						|
        NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
 | 
						|
        NewRecordCount++;
 | 
						|
      }
 | 
						|
 | 
						|
      TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize));
 | 
						|
      TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - TempRecord.PhysicalStart);
 | 
						|
      if (TempRecord.NumberOfPages == 0) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Final DATA
 | 
						|
  //
 | 
						|
  if (TempRecord.PhysicalStart < ImageEnd) {
 | 
						|
    NewRecord->Type          = EfiRuntimeServicesData;
 | 
						|
    NewRecord->PhysicalStart = TempRecord.PhysicalStart;
 | 
						|
    NewRecord->VirtualStart  = 0;
 | 
						|
    NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart);
 | 
						|
    NewRecord->Attribute     = TempRecord.Attribute | EFI_MEMORY_XP;
 | 
						|
    NewRecordCount++;
 | 
						|
  }
 | 
						|
 | 
						|
  return NewRecordCount;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return the max number of new splitted entries, according to one old entry,
 | 
						|
  based upon PE code section and data section.
 | 
						|
 | 
						|
  @param[in]  OldRecord              A pointer to one old memory map entry.
 | 
						|
 | 
						|
  @retval  0 no entry need to be splitted.
 | 
						|
  @return  the max number of new splitted entries
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
UINTN
 | 
						|
GetMaxSplitRecordCount (
 | 
						|
  IN EFI_MEMORY_DESCRIPTOR  *OldRecord
 | 
						|
  )
 | 
						|
{
 | 
						|
  IMAGE_PROPERTIES_RECORD  *ImageRecord;
 | 
						|
  UINTN                    SplitRecordCount;
 | 
						|
  UINT64                   PhysicalStart;
 | 
						|
  UINT64                   PhysicalEnd;
 | 
						|
 | 
						|
  SplitRecordCount = 0;
 | 
						|
  PhysicalStart    = OldRecord->PhysicalStart;
 | 
						|
  PhysicalEnd      = OldRecord->PhysicalStart + EfiPagesToSize (OldRecord->NumberOfPages);
 | 
						|
 | 
						|
  do {
 | 
						|
    ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
 | 
						|
    if (ImageRecord == NULL) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 2);
 | 
						|
    PhysicalStart     = ImageRecord->ImageBase + ImageRecord->ImageSize;
 | 
						|
  } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
 | 
						|
 | 
						|
  return SplitRecordCount;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Split the memory map to new entries, according to one old entry,
 | 
						|
  based upon PE code section and data section.
 | 
						|
 | 
						|
  @param[in]       OldRecord              A pointer to one old memory map entry.
 | 
						|
  @param[in, out]  NewRecord              A pointer to several new memory map entries.
 | 
						|
                                          The caller guarantee the buffer size be 1 +
 | 
						|
                                          (SplitRecordCount * DescriptorSize) calculated
 | 
						|
                                          below.
 | 
						|
  @param[in]       MaxSplitRecordCount    The max number of splitted entries
 | 
						|
  @param[in]       DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
 | 
						|
 | 
						|
  @retval  0 no entry is splitted.
 | 
						|
  @return  the real number of splitted record.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
UINTN
 | 
						|
SplitRecord (
 | 
						|
  IN EFI_MEMORY_DESCRIPTOR      *OldRecord,
 | 
						|
  IN OUT EFI_MEMORY_DESCRIPTOR  *NewRecord,
 | 
						|
  IN UINTN                      MaxSplitRecordCount,
 | 
						|
  IN UINTN                      DescriptorSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_MEMORY_DESCRIPTOR    TempRecord;
 | 
						|
  IMAGE_PROPERTIES_RECORD  *ImageRecord;
 | 
						|
  IMAGE_PROPERTIES_RECORD  *NewImageRecord;
 | 
						|
  UINT64                   PhysicalStart;
 | 
						|
  UINT64                   PhysicalEnd;
 | 
						|
  UINTN                    NewRecordCount;
 | 
						|
  UINTN                    TotalNewRecordCount;
 | 
						|
 | 
						|
  if (MaxSplitRecordCount == 0) {
 | 
						|
    CopyMem (NewRecord, OldRecord, DescriptorSize);
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  TotalNewRecordCount = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Override previous record
 | 
						|
  //
 | 
						|
  CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR));
 | 
						|
  PhysicalStart = TempRecord.PhysicalStart;
 | 
						|
  PhysicalEnd   = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages);
 | 
						|
 | 
						|
  ImageRecord = NULL;
 | 
						|
  do {
 | 
						|
    NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
 | 
						|
    if (NewImageRecord == NULL) {
 | 
						|
      //
 | 
						|
      // No more image covered by this range, stop
 | 
						|
      //
 | 
						|
      if (PhysicalEnd > PhysicalStart) {
 | 
						|
        //
 | 
						|
        // Always create a new entry for non-PE image record
 | 
						|
        //
 | 
						|
        NewRecord->Type          = TempRecord.Type;
 | 
						|
        NewRecord->PhysicalStart = TempRecord.PhysicalStart;
 | 
						|
        NewRecord->VirtualStart  = 0;
 | 
						|
        NewRecord->NumberOfPages = TempRecord.NumberOfPages;
 | 
						|
        NewRecord->Attribute     = TempRecord.Attribute;
 | 
						|
        TotalNewRecordCount++;
 | 
						|
      }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    ImageRecord = NewImageRecord;
 | 
						|
 | 
						|
    //
 | 
						|
    // Set new record
 | 
						|
    //
 | 
						|
    NewRecordCount       = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize);
 | 
						|
    TotalNewRecordCount += NewRecordCount;
 | 
						|
    NewRecord            = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize);
 | 
						|
 | 
						|
    //
 | 
						|
    // Update PhysicalStart, in order to exclude the image buffer already splitted.
 | 
						|
    //
 | 
						|
    PhysicalStart            = ImageRecord->ImageBase + ImageRecord->ImageSize;
 | 
						|
    TempRecord.PhysicalStart = PhysicalStart;
 | 
						|
    TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
 | 
						|
  } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
 | 
						|
 | 
						|
  return TotalNewRecordCount - 1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Split the original memory map, and add more entries to describe PE code section and data section.
 | 
						|
  This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
 | 
						|
  This function will merge entries with same attributes finally.
 | 
						|
 | 
						|
  NOTE: It assumes PE code/data section are page aligned.
 | 
						|
  NOTE: It assumes enough entry is prepared for new memory map.
 | 
						|
 | 
						|
  Split table:
 | 
						|
   +---------------+
 | 
						|
   | Record X      |
 | 
						|
   +---------------+
 | 
						|
   | Record RtCode |
 | 
						|
   +---------------+
 | 
						|
   | Record Y      |
 | 
						|
   +---------------+
 | 
						|
   ==>
 | 
						|
   +---------------+
 | 
						|
   | Record X      |
 | 
						|
   +---------------+
 | 
						|
   | Record RtCode |
 | 
						|
   +---------------+ ----
 | 
						|
   | Record RtData |     |
 | 
						|
   +---------------+     |
 | 
						|
   | Record RtCode |     |-> PE/COFF1
 | 
						|
   +---------------+     |
 | 
						|
   | Record RtData |     |
 | 
						|
   +---------------+ ----
 | 
						|
   | Record RtCode |
 | 
						|
   +---------------+ ----
 | 
						|
   | Record RtData |     |
 | 
						|
   +---------------+     |
 | 
						|
   | Record RtCode |     |-> PE/COFF2
 | 
						|
   +---------------+     |
 | 
						|
   | Record RtData |     |
 | 
						|
   +---------------+ ----
 | 
						|
   | Record RtCode |
 | 
						|
   +---------------+
 | 
						|
   | Record Y      |
 | 
						|
   +---------------+
 | 
						|
 | 
						|
  @param[in, out]  MemoryMapSize          A pointer to the size, in bytes, of the
 | 
						|
                                          MemoryMap buffer. On input, this is the size of
 | 
						|
                                          old MemoryMap before split. The actual buffer
 | 
						|
                                          size of MemoryMap is MemoryMapSize +
 | 
						|
                                          (AdditionalRecordCount * DescriptorSize) calculated
 | 
						|
                                          below. On output, it is the size of new MemoryMap
 | 
						|
                                          after split.
 | 
						|
  @param[in, out]  MemoryMap              A pointer to the buffer in which firmware places
 | 
						|
                                          the current memory map.
 | 
						|
  @param[in]       DescriptorSize         Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
SplitTable (
 | 
						|
  IN OUT UINTN                  *MemoryMapSize,
 | 
						|
  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
 | 
						|
  IN UINTN                      DescriptorSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  INTN   IndexOld;
 | 
						|
  INTN   IndexNew;
 | 
						|
  UINTN  MaxSplitRecordCount;
 | 
						|
  UINTN  RealSplitRecordCount;
 | 
						|
  UINTN  TotalSplitRecordCount;
 | 
						|
  UINTN  AdditionalRecordCount;
 | 
						|
 | 
						|
  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 2) * mImagePropertiesPrivateData.ImageRecordCount;
 | 
						|
 | 
						|
  TotalSplitRecordCount = 0;
 | 
						|
  //
 | 
						|
  // Let old record point to end of valid MemoryMap buffer.
 | 
						|
  //
 | 
						|
  IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1;
 | 
						|
  //
 | 
						|
  // Let new record point to end of full MemoryMap buffer.
 | 
						|
  //
 | 
						|
  IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + AdditionalRecordCount;
 | 
						|
  for ( ; IndexOld >= 0; IndexOld--) {
 | 
						|
    MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize));
 | 
						|
    //
 | 
						|
    // Split this MemoryMap record
 | 
						|
    //
 | 
						|
    IndexNew            -= MaxSplitRecordCount;
 | 
						|
    RealSplitRecordCount = SplitRecord (
 | 
						|
                             (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),
 | 
						|
                             (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
 | 
						|
                             MaxSplitRecordCount,
 | 
						|
                             DescriptorSize
 | 
						|
                             );
 | 
						|
    //
 | 
						|
    // Adjust IndexNew according to real split.
 | 
						|
    //
 | 
						|
    if (MaxSplitRecordCount != RealSplitRecordCount) {
 | 
						|
      CopyMem (
 | 
						|
        ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),
 | 
						|
        ((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
 | 
						|
        (RealSplitRecordCount + 1) * DescriptorSize
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    IndexNew               = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;
 | 
						|
    TotalSplitRecordCount += RealSplitRecordCount;
 | 
						|
    IndexNew--;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Move all records to the beginning.
 | 
						|
  //
 | 
						|
  CopyMem (
 | 
						|
    MemoryMap,
 | 
						|
    (UINT8 *)MemoryMap + (AdditionalRecordCount - TotalSplitRecordCount) * DescriptorSize,
 | 
						|
    (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize
 | 
						|
    );
 | 
						|
 | 
						|
  *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount;
 | 
						|
 | 
						|
  //
 | 
						|
  // Sort from low to high (Just in case)
 | 
						|
  //
 | 
						|
  SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);
 | 
						|
 | 
						|
  //
 | 
						|
  // Set RuntimeData to XP
 | 
						|
  //
 | 
						|
  EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, DescriptorSize);
 | 
						|
 | 
						|
  //
 | 
						|
  // Merge same type to save entry size
 | 
						|
  //
 | 
						|
  MergeMemoryMap (MemoryMap, MemoryMapSize, DescriptorSize);
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function for GetMemoryMap() with memory attributes table.
 | 
						|
 | 
						|
  It calls original GetMemoryMap() to get the original memory map information. Then
 | 
						|
  plus the additional memory map entries for PE Code/Data separation.
 | 
						|
 | 
						|
  @param[in, out]  MemoryMapSize          A pointer to the size, in bytes, of the
 | 
						|
                                          MemoryMap buffer. On input, this is the size of
 | 
						|
                                          the buffer allocated by the caller.  On output,
 | 
						|
                                          it is the size of the buffer returned by the
 | 
						|
                                          firmware  if the buffer was large enough, or the
 | 
						|
                                          size of the buffer needed  to contain the map if
 | 
						|
                                          the buffer was too small.
 | 
						|
  @param[in, out]  MemoryMap              A pointer to the buffer in which firmware places
 | 
						|
                                          the current memory map.
 | 
						|
  @param[out]      MapKey                 A pointer to the location in which firmware
 | 
						|
                                          returns the key for the current memory map.
 | 
						|
  @param[out]      DescriptorSize         A pointer to the location in which firmware
 | 
						|
                                          returns the size, in bytes, of an individual
 | 
						|
                                          EFI_MEMORY_DESCRIPTOR.
 | 
						|
  @param[out]      DescriptorVersion      A pointer to the location in which firmware
 | 
						|
                                          returns the version number associated with the
 | 
						|
                                          EFI_MEMORY_DESCRIPTOR.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            The memory map was returned in the MemoryMap
 | 
						|
                                 buffer.
 | 
						|
  @retval EFI_BUFFER_TOO_SMALL   The MemoryMap buffer was too small. The current
 | 
						|
                                 buffer size needed to hold the memory map is
 | 
						|
                                 returned in MemoryMapSize.
 | 
						|
  @retval EFI_INVALID_PARAMETER  One of the parameters has an invalid value.
 | 
						|
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SmmCoreGetMemoryMapMemoryAttributesTable (
 | 
						|
  IN OUT UINTN                  *MemoryMapSize,
 | 
						|
  IN OUT EFI_MEMORY_DESCRIPTOR  *MemoryMap,
 | 
						|
  OUT UINTN                     *MapKey,
 | 
						|
  OUT UINTN                     *DescriptorSize,
 | 
						|
  OUT UINT32                    *DescriptorVersion
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  UINTN       OldMemoryMapSize;
 | 
						|
  UINTN       AdditionalRecordCount;
 | 
						|
 | 
						|
  //
 | 
						|
  // If PE code/data is not aligned, just return.
 | 
						|
  //
 | 
						|
  if ((mMemoryProtectionAttribute & EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {
 | 
						|
    return SmmCoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
 | 
						|
  }
 | 
						|
 | 
						|
  if (MemoryMapSize == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 2) * mImagePropertiesPrivateData.ImageRecordCount;
 | 
						|
 | 
						|
  OldMemoryMapSize = *MemoryMapSize;
 | 
						|
  Status           = SmmCoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
 | 
						|
  if (Status == EFI_BUFFER_TOO_SMALL) {
 | 
						|
    *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount;
 | 
						|
  } else if (Status == EFI_SUCCESS) {
 | 
						|
    if (OldMemoryMapSize - *MemoryMapSize < (*DescriptorSize) * AdditionalRecordCount) {
 | 
						|
      *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount;
 | 
						|
      //
 | 
						|
      // Need update status to buffer too small
 | 
						|
      //
 | 
						|
      Status = EFI_BUFFER_TOO_SMALL;
 | 
						|
    } else {
 | 
						|
      //
 | 
						|
      // Split PE code/data
 | 
						|
      //
 | 
						|
      ASSERT (MemoryMap != NULL);
 | 
						|
      SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// Below functions are for ImageRecord
 | 
						|
//
 | 
						|
 | 
						|
/**
 | 
						|
  Set MemoryProtectionAttribute according to PE/COFF image section alignment.
 | 
						|
 | 
						|
  @param[in]  SectionAlignment    PE/COFF section alignment
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
SetMemoryAttributesTableSectionAlignment (
 | 
						|
  IN UINT32  SectionAlignment
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) &&
 | 
						|
      ((mMemoryProtectionAttribute & EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) != 0))
 | 
						|
  {
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "SMM SetMemoryAttributesTableSectionAlignment - Clear\n"));
 | 
						|
    mMemoryProtectionAttribute &= ~((UINT64)EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Swap two code sections in image record.
 | 
						|
 | 
						|
  @param[in]  FirstImageRecordCodeSection    first code section in image record
 | 
						|
  @param[in]  SecondImageRecordCodeSection   second code section in image record
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
SwapImageRecordCodeSection (
 | 
						|
  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *FirstImageRecordCodeSection,
 | 
						|
  IN IMAGE_PROPERTIES_RECORD_CODE_SECTION  *SecondImageRecordCodeSection
 | 
						|
  )
 | 
						|
{
 | 
						|
  IMAGE_PROPERTIES_RECORD_CODE_SECTION  TempImageRecordCodeSection;
 | 
						|
 | 
						|
  TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase;
 | 
						|
  TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize;
 | 
						|
 | 
						|
  FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase;
 | 
						|
  FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize;
 | 
						|
 | 
						|
  SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase;
 | 
						|
  SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Sort code section in image record, based upon CodeSegmentBase from low to high.
 | 
						|
 | 
						|
  @param[in]  ImageRecord    image record to be sorted
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
SortImageRecordCodeSection (
 | 
						|
  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
 | 
						|
  )
 | 
						|
{
 | 
						|
  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
 | 
						|
  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *NextImageRecordCodeSection;
 | 
						|
  LIST_ENTRY                            *ImageRecordCodeSectionLink;
 | 
						|
  LIST_ENTRY                            *NextImageRecordCodeSectionLink;
 | 
						|
  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
 | 
						|
  LIST_ENTRY                            *ImageRecordCodeSectionList;
 | 
						|
 | 
						|
  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
 | 
						|
 | 
						|
  ImageRecordCodeSectionLink     = ImageRecordCodeSectionList->ForwardLink;
 | 
						|
  NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
 | 
						|
  ImageRecordCodeSectionEndLink  = ImageRecordCodeSectionList;
 | 
						|
  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
 | 
						|
    ImageRecordCodeSection = CR (
 | 
						|
                               ImageRecordCodeSectionLink,
 | 
						|
                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
 | 
						|
                               Link,
 | 
						|
                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
 | 
						|
                               );
 | 
						|
    while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
 | 
						|
      NextImageRecordCodeSection = CR (
 | 
						|
                                     NextImageRecordCodeSectionLink,
 | 
						|
                                     IMAGE_PROPERTIES_RECORD_CODE_SECTION,
 | 
						|
                                     Link,
 | 
						|
                                     IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
 | 
						|
                                     );
 | 
						|
      if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) {
 | 
						|
        SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);
 | 
						|
      }
 | 
						|
 | 
						|
      NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;
 | 
						|
    }
 | 
						|
 | 
						|
    ImageRecordCodeSectionLink     = ImageRecordCodeSectionLink->ForwardLink;
 | 
						|
    NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check if code section in image record is valid.
 | 
						|
 | 
						|
  @param[in]  ImageRecord    image record to be checked
 | 
						|
 | 
						|
  @retval TRUE  image record is valid
 | 
						|
  @retval FALSE image record is invalid
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
BOOLEAN
 | 
						|
IsImageRecordCodeSectionValid (
 | 
						|
  IN IMAGE_PROPERTIES_RECORD  *ImageRecord
 | 
						|
  )
 | 
						|
{
 | 
						|
  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
 | 
						|
  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *LastImageRecordCodeSection;
 | 
						|
  LIST_ENTRY                            *ImageRecordCodeSectionLink;
 | 
						|
  LIST_ENTRY                            *ImageRecordCodeSectionEndLink;
 | 
						|
  LIST_ENTRY                            *ImageRecordCodeSectionList;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "SMM ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));
 | 
						|
 | 
						|
  ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
 | 
						|
 | 
						|
  ImageRecordCodeSectionLink    = ImageRecordCodeSectionList->ForwardLink;
 | 
						|
  ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
 | 
						|
  LastImageRecordCodeSection    = NULL;
 | 
						|
  while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
 | 
						|
    ImageRecordCodeSection = CR (
 | 
						|
                               ImageRecordCodeSectionLink,
 | 
						|
                               IMAGE_PROPERTIES_RECORD_CODE_SECTION,
 | 
						|
                               Link,
 | 
						|
                               IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
 | 
						|
                               );
 | 
						|
    if (ImageRecordCodeSection->CodeSegmentSize == 0) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (LastImageRecordCodeSection != NULL) {
 | 
						|
      if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) {
 | 
						|
        return FALSE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    LastImageRecordCodeSection = ImageRecordCodeSection;
 | 
						|
    ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Swap two image records.
 | 
						|
 | 
						|
  @param[in]  FirstImageRecord   first image record.
 | 
						|
  @param[in]  SecondImageRecord  second image record.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
SwapImageRecord (
 | 
						|
  IN IMAGE_PROPERTIES_RECORD  *FirstImageRecord,
 | 
						|
  IN IMAGE_PROPERTIES_RECORD  *SecondImageRecord
 | 
						|
  )
 | 
						|
{
 | 
						|
  IMAGE_PROPERTIES_RECORD  TempImageRecord;
 | 
						|
 | 
						|
  TempImageRecord.ImageBase        = FirstImageRecord->ImageBase;
 | 
						|
  TempImageRecord.ImageSize        = FirstImageRecord->ImageSize;
 | 
						|
  TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;
 | 
						|
 | 
						|
  FirstImageRecord->ImageBase        = SecondImageRecord->ImageBase;
 | 
						|
  FirstImageRecord->ImageSize        = SecondImageRecord->ImageSize;
 | 
						|
  FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount;
 | 
						|
 | 
						|
  SecondImageRecord->ImageBase        = TempImageRecord.ImageBase;
 | 
						|
  SecondImageRecord->ImageSize        = TempImageRecord.ImageSize;
 | 
						|
  SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount;
 | 
						|
 | 
						|
  SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Sort image record based upon the ImageBase from low to high.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
SortImageRecord (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  IMAGE_PROPERTIES_RECORD  *ImageRecord;
 | 
						|
  IMAGE_PROPERTIES_RECORD  *NextImageRecord;
 | 
						|
  LIST_ENTRY               *ImageRecordLink;
 | 
						|
  LIST_ENTRY               *NextImageRecordLink;
 | 
						|
  LIST_ENTRY               *ImageRecordEndLink;
 | 
						|
  LIST_ENTRY               *ImageRecordList;
 | 
						|
 | 
						|
  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
 | 
						|
 | 
						|
  ImageRecordLink     = ImageRecordList->ForwardLink;
 | 
						|
  NextImageRecordLink = ImageRecordLink->ForwardLink;
 | 
						|
  ImageRecordEndLink  = ImageRecordList;
 | 
						|
  while (ImageRecordLink != ImageRecordEndLink) {
 | 
						|
    ImageRecord = CR (
 | 
						|
                    ImageRecordLink,
 | 
						|
                    IMAGE_PROPERTIES_RECORD,
 | 
						|
                    Link,
 | 
						|
                    IMAGE_PROPERTIES_RECORD_SIGNATURE
 | 
						|
                    );
 | 
						|
    while (NextImageRecordLink != ImageRecordEndLink) {
 | 
						|
      NextImageRecord = CR (
 | 
						|
                          NextImageRecordLink,
 | 
						|
                          IMAGE_PROPERTIES_RECORD,
 | 
						|
                          Link,
 | 
						|
                          IMAGE_PROPERTIES_RECORD_SIGNATURE
 | 
						|
                          );
 | 
						|
      if (ImageRecord->ImageBase > NextImageRecord->ImageBase) {
 | 
						|
        SwapImageRecord (ImageRecord, NextImageRecord);
 | 
						|
      }
 | 
						|
 | 
						|
      NextImageRecordLink = NextImageRecordLink->ForwardLink;
 | 
						|
    }
 | 
						|
 | 
						|
    ImageRecordLink     = ImageRecordLink->ForwardLink;
 | 
						|
    NextImageRecordLink = ImageRecordLink->ForwardLink;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Dump image record.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
VOID
 | 
						|
DumpImageRecord (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  IMAGE_PROPERTIES_RECORD  *ImageRecord;
 | 
						|
  LIST_ENTRY               *ImageRecordLink;
 | 
						|
  LIST_ENTRY               *ImageRecordList;
 | 
						|
  UINTN                    Index;
 | 
						|
 | 
						|
  ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
 | 
						|
 | 
						|
  for (ImageRecordLink = ImageRecordList->ForwardLink, Index = 0;
 | 
						|
       ImageRecordLink != ImageRecordList;
 | 
						|
       ImageRecordLink = ImageRecordLink->ForwardLink, Index++)
 | 
						|
  {
 | 
						|
    ImageRecord = CR (
 | 
						|
                    ImageRecordLink,
 | 
						|
                    IMAGE_PROPERTIES_RECORD,
 | 
						|
                    Link,
 | 
						|
                    IMAGE_PROPERTIES_RECORD_SIGNATURE
 | 
						|
                    );
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "SMM  Image[%d]: 0x%016lx - 0x%016lx\n", Index, ImageRecord->ImageBase, ImageRecord->ImageSize));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Insert image record.
 | 
						|
 | 
						|
  @param[in]  DriverEntry    Driver information
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SmmInsertImageRecord (
 | 
						|
  IN EFI_SMM_DRIVER_ENTRY  *DriverEntry
 | 
						|
  )
 | 
						|
{
 | 
						|
  VOID                                  *ImageAddress;
 | 
						|
  EFI_IMAGE_DOS_HEADER                  *DosHdr;
 | 
						|
  UINT32                                PeCoffHeaderOffset;
 | 
						|
  UINT32                                SectionAlignment;
 | 
						|
  EFI_IMAGE_SECTION_HEADER              *Section;
 | 
						|
  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
 | 
						|
  UINT8                                 *Name;
 | 
						|
  UINTN                                 Index;
 | 
						|
  IMAGE_PROPERTIES_RECORD               *ImageRecord;
 | 
						|
  CHAR8                                 *PdbPointer;
 | 
						|
  IMAGE_PROPERTIES_RECORD_CODE_SECTION  *ImageRecordCodeSection;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "SMM InsertImageRecord - 0x%x\n", DriverEntry));
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "SMM InsertImageRecord - 0x%016lx - 0x%08x\n", DriverEntry->ImageBuffer, DriverEntry->NumberOfPage));
 | 
						|
 | 
						|
  ImageRecord = AllocatePool (sizeof (*ImageRecord));
 | 
						|
  if (ImageRecord == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;
 | 
						|
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "SMM ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
 | 
						|
 | 
						|
  //
 | 
						|
  // Step 1: record whole region
 | 
						|
  //
 | 
						|
  ImageRecord->ImageBase = DriverEntry->ImageBuffer;
 | 
						|
  ImageRecord->ImageSize = EfiPagesToSize (DriverEntry->NumberOfPage);
 | 
						|
 | 
						|
  ImageAddress = (VOID *)(UINTN)DriverEntry->ImageBuffer;
 | 
						|
 | 
						|
  PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);
 | 
						|
  if (PdbPointer != NULL) {
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "SMM   Image - %a\n", PdbPointer));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check PE/COFF image
 | 
						|
  //
 | 
						|
  DosHdr             = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress;
 | 
						|
  PeCoffHeaderOffset = 0;
 | 
						|
  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
 | 
						|
    PeCoffHeaderOffset = DosHdr->e_lfanew;
 | 
						|
  }
 | 
						|
 | 
						|
  Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);
 | 
						|
  if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "SMM Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature));
 | 
						|
    goto Finish;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get SectionAlignment
 | 
						|
  //
 | 
						|
  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
 | 
						|
    SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
 | 
						|
  } else {
 | 
						|
    SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
 | 
						|
  }
 | 
						|
 | 
						|
  SetMemoryAttributesTableSectionAlignment (SectionAlignment);
 | 
						|
  if ((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_WARN,
 | 
						|
      "SMM !!!!!!!!  InsertImageRecord - Section Alignment(0x%x) is not %dK  !!!!!!!!\n",
 | 
						|
      SectionAlignment,
 | 
						|
      RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10
 | 
						|
      ));
 | 
						|
    PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);
 | 
						|
    if (PdbPointer != NULL) {
 | 
						|
      DEBUG ((DEBUG_WARN, "SMM !!!!!!!!  Image - %a  !!!!!!!!\n", PdbPointer));
 | 
						|
    }
 | 
						|
 | 
						|
    goto Finish;
 | 
						|
  }
 | 
						|
 | 
						|
  Section = (EFI_IMAGE_SECTION_HEADER *)(
 | 
						|
                                         (UINT8 *)(UINTN)ImageAddress +
 | 
						|
                                         PeCoffHeaderOffset +
 | 
						|
                                         sizeof (UINT32) +
 | 
						|
                                         sizeof (EFI_IMAGE_FILE_HEADER) +
 | 
						|
                                         Hdr.Pe32->FileHeader.SizeOfOptionalHeader
 | 
						|
                                         );
 | 
						|
  ImageRecord->CodeSegmentCount = 0;
 | 
						|
  InitializeListHead (&ImageRecord->CodeSegmentList);
 | 
						|
  for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
 | 
						|
    Name = Section[Index].Name;
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_VERBOSE,
 | 
						|
      "SMM   Section - '%c%c%c%c%c%c%c%c'\n",
 | 
						|
      Name[0],
 | 
						|
      Name[1],
 | 
						|
      Name[2],
 | 
						|
      Name[3],
 | 
						|
      Name[4],
 | 
						|
      Name[5],
 | 
						|
      Name[6],
 | 
						|
      Name[7]
 | 
						|
      ));
 | 
						|
 | 
						|
    if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) {
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "SMM   VirtualSize          - 0x%08x\n", Section[Index].Misc.VirtualSize));
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "SMM   VirtualAddress       - 0x%08x\n", Section[Index].VirtualAddress));
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "SMM   SizeOfRawData        - 0x%08x\n", Section[Index].SizeOfRawData));
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "SMM   PointerToRawData     - 0x%08x\n", Section[Index].PointerToRawData));
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "SMM   PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations));
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "SMM   PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers));
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "SMM   NumberOfRelocations  - 0x%08x\n", Section[Index].NumberOfRelocations));
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "SMM   NumberOfLinenumbers  - 0x%08x\n", Section[Index].NumberOfLinenumbers));
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "SMM   Characteristics      - 0x%08x\n", Section[Index].Characteristics));
 | 
						|
 | 
						|
      //
 | 
						|
      // Step 2: record code section
 | 
						|
      //
 | 
						|
      ImageRecordCodeSection = AllocatePool (sizeof (*ImageRecordCodeSection));
 | 
						|
      if (ImageRecordCodeSection == NULL) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
 | 
						|
 | 
						|
      ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress;
 | 
						|
      ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData;
 | 
						|
 | 
						|
      DEBUG ((DEBUG_VERBOSE, "SMM ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize));
 | 
						|
 | 
						|
      InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);
 | 
						|
      ImageRecord->CodeSegmentCount++;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (ImageRecord->CodeSegmentCount == 0) {
 | 
						|
    SetMemoryAttributesTableSectionAlignment (1);
 | 
						|
    DEBUG ((DEBUG_ERROR, "SMM !!!!!!!!  InsertImageRecord - CodeSegmentCount is 0  !!!!!!!!\n"));
 | 
						|
    PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);
 | 
						|
    if (PdbPointer != NULL) {
 | 
						|
      DEBUG ((DEBUG_ERROR, "SMM !!!!!!!!  Image - %a  !!!!!!!!\n", PdbPointer));
 | 
						|
    }
 | 
						|
 | 
						|
    goto Finish;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Final
 | 
						|
  //
 | 
						|
  SortImageRecordCodeSection (ImageRecord);
 | 
						|
  //
 | 
						|
  // Check overlap all section in ImageBase/Size
 | 
						|
  //
 | 
						|
  if (!IsImageRecordCodeSectionValid (ImageRecord)) {
 | 
						|
    DEBUG ((DEBUG_ERROR, "SMM IsImageRecordCodeSectionValid - FAIL\n"));
 | 
						|
    goto Finish;
 | 
						|
  }
 | 
						|
 | 
						|
  InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link);
 | 
						|
  mImagePropertiesPrivateData.ImageRecordCount++;
 | 
						|
 | 
						|
  if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) {
 | 
						|
    mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;
 | 
						|
  }
 | 
						|
 | 
						|
  SortImageRecord ();
 | 
						|
 | 
						|
Finish:
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Publish MemoryAttributesTable to SMM configuration table.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
PublishMemoryAttributesTable (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                                 MemoryMapSize;
 | 
						|
  EFI_MEMORY_DESCRIPTOR                 *MemoryMap;
 | 
						|
  UINTN                                 MapKey;
 | 
						|
  UINTN                                 DescriptorSize;
 | 
						|
  UINT32                                DescriptorVersion;
 | 
						|
  UINTN                                 Index;
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  UINTN                                 RuntimeEntryCount;
 | 
						|
  EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE  *MemoryAttributesTable;
 | 
						|
  EFI_MEMORY_DESCRIPTOR                 *MemoryAttributesEntry;
 | 
						|
  UINTN                                 MemoryAttributesTableSize;
 | 
						|
 | 
						|
  MemoryMapSize = 0;
 | 
						|
  MemoryMap     = NULL;
 | 
						|
  Status        = SmmCoreGetMemoryMapMemoryAttributesTable (
 | 
						|
                    &MemoryMapSize,
 | 
						|
                    MemoryMap,
 | 
						|
                    &MapKey,
 | 
						|
                    &DescriptorSize,
 | 
						|
                    &DescriptorVersion
 | 
						|
                    );
 | 
						|
  ASSERT (Status == EFI_BUFFER_TOO_SMALL);
 | 
						|
 | 
						|
  do {
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "MemoryMapSize - 0x%x\n", MemoryMapSize));
 | 
						|
    MemoryMap = AllocatePool (MemoryMapSize);
 | 
						|
    ASSERT (MemoryMap != NULL);
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "MemoryMap - 0x%x\n", MemoryMap));
 | 
						|
 | 
						|
    Status = SmmCoreGetMemoryMapMemoryAttributesTable (
 | 
						|
               &MemoryMapSize,
 | 
						|
               MemoryMap,
 | 
						|
               &MapKey,
 | 
						|
               &DescriptorSize,
 | 
						|
               &DescriptorVersion
 | 
						|
               );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      FreePool (MemoryMap);
 | 
						|
    }
 | 
						|
  } while (Status == EFI_BUFFER_TOO_SMALL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Allocate MemoryAttributesTable
 | 
						|
  //
 | 
						|
  RuntimeEntryCount         = MemoryMapSize/DescriptorSize;
 | 
						|
  MemoryAttributesTableSize = sizeof (EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE) + DescriptorSize * RuntimeEntryCount;
 | 
						|
  MemoryAttributesTable     = AllocatePool (sizeof (EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE) + DescriptorSize * RuntimeEntryCount);
 | 
						|
  ASSERT (MemoryAttributesTable != NULL);
 | 
						|
  MemoryAttributesTable->Version         = EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE_VERSION;
 | 
						|
  MemoryAttributesTable->NumberOfEntries = (UINT32)RuntimeEntryCount;
 | 
						|
  MemoryAttributesTable->DescriptorSize  = (UINT32)DescriptorSize;
 | 
						|
  MemoryAttributesTable->Reserved        = 0;
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "MemoryAttributesTable:\n"));
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "  Version              - 0x%08x\n", MemoryAttributesTable->Version));
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "  NumberOfEntries      - 0x%08x\n", MemoryAttributesTable->NumberOfEntries));
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "  DescriptorSize       - 0x%08x\n", MemoryAttributesTable->DescriptorSize));
 | 
						|
  MemoryAttributesEntry = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1);
 | 
						|
  for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {
 | 
						|
    CopyMem (MemoryAttributesEntry, MemoryMap, DescriptorSize);
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "Entry (0x%x)\n", MemoryAttributesEntry));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "  Type              - 0x%x\n", MemoryAttributesEntry->Type));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "  PhysicalStart     - 0x%016lx\n", MemoryAttributesEntry->PhysicalStart));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "  VirtualStart      - 0x%016lx\n", MemoryAttributesEntry->VirtualStart));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "  NumberOfPages     - 0x%016lx\n", MemoryAttributesEntry->NumberOfPages));
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "  Attribute         - 0x%016lx\n", MemoryAttributesEntry->Attribute));
 | 
						|
    MemoryAttributesEntry = NEXT_MEMORY_DESCRIPTOR (MemoryAttributesEntry, DescriptorSize);
 | 
						|
 | 
						|
    MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gSmst->SmmInstallConfigurationTable (gSmst, &gEdkiiPiSmmMemoryAttributesTableGuid, MemoryAttributesTable, MemoryAttributesTableSize);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function installs all SMM image record information.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
SmmInstallImageRecord (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                 Status;
 | 
						|
  UINTN                      NoHandles;
 | 
						|
  EFI_HANDLE                 *HandleBuffer;
 | 
						|
  EFI_LOADED_IMAGE_PROTOCOL  *LoadedImage;
 | 
						|
  UINTN                      Index;
 | 
						|
  EFI_SMM_DRIVER_ENTRY       DriverEntry;
 | 
						|
 | 
						|
  Status = SmmLocateHandleBuffer (
 | 
						|
             ByProtocol,
 | 
						|
             &gEfiLoadedImageProtocolGuid,
 | 
						|
             NULL,
 | 
						|
             &NoHandles,
 | 
						|
             &HandleBuffer
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < NoHandles; Index++) {
 | 
						|
    Status = gSmst->SmmHandleProtocol (
 | 
						|
                      HandleBuffer[Index],
 | 
						|
                      &gEfiLoadedImageProtocolGuid,
 | 
						|
                      (VOID **)&LoadedImage
 | 
						|
                      );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "LoadedImage - 0x%x 0x%x ", LoadedImage->ImageBase, LoadedImage->ImageSize));
 | 
						|
    {
 | 
						|
      VOID  *PdbPointer;
 | 
						|
      PdbPointer = PeCoffLoaderGetPdbPointer (LoadedImage->ImageBase);
 | 
						|
      if (PdbPointer != NULL) {
 | 
						|
        DEBUG ((DEBUG_VERBOSE, "(%a) ", PdbPointer));
 | 
						|
      }
 | 
						|
    }
 | 
						|
    DEBUG ((DEBUG_VERBOSE, "\n"));
 | 
						|
    ZeroMem (&DriverEntry, sizeof (DriverEntry));
 | 
						|
    DriverEntry.ImageBuffer  = (UINTN)LoadedImage->ImageBase;
 | 
						|
    DriverEntry.NumberOfPage = EFI_SIZE_TO_PAGES ((UINTN)LoadedImage->ImageSize);
 | 
						|
    SmmInsertImageRecord (&DriverEntry);
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (HandleBuffer);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Install MemoryAttributesTable.
 | 
						|
 | 
						|
  @param[in] Protocol   Points to the protocol's unique identifier.
 | 
						|
  @param[in] Interface  Points to the interface instance.
 | 
						|
  @param[in] Handle     The handle on which the interface was installed.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS   Notification runs successfully.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SmmInstallMemoryAttributesTable (
 | 
						|
  IN CONST EFI_GUID  *Protocol,
 | 
						|
  IN VOID            *Interface,
 | 
						|
  IN EFI_HANDLE      Handle
 | 
						|
  )
 | 
						|
{
 | 
						|
  SmmInstallImageRecord ();
 | 
						|
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "SMM MemoryProtectionAttribute - 0x%016lx\n", mMemoryProtectionAttribute));
 | 
						|
  if ((mMemoryProtectionAttribute & EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "SMM Total Image Count - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
 | 
						|
  DEBUG ((DEBUG_VERBOSE, "SMM Dump ImageRecord:\n"));
 | 
						|
  DumpImageRecord ();
 | 
						|
 | 
						|
  PublishMemoryAttributesTable ();
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Initialize MemoryAttributesTable support.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
SmmCoreInitializeMemoryAttributesTable (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  VOID        *Registration;
 | 
						|
 | 
						|
  Status = gSmst->SmmRegisterProtocolNotify (
 | 
						|
                    &gEfiSmmEndOfDxeProtocolGuid,
 | 
						|
                    SmmInstallMemoryAttributesTable,
 | 
						|
                    &Registration
 | 
						|
                    );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  return;
 | 
						|
}
 |