mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-31 01:24:12 +02:00
UefiCpuPkg/PiSmmCpuDxeSmm: Centralize Non-Mmram Mem Management Code
Centralize the SMM Non-Mmram Memory Management related code into the NonMmramMapDxeSmm.c. The file SmmCpuMemoryManagement.c will be target to use for both SMM and MM in subsequent patches. No function impact. Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: Star Zeng <star.zeng@intel.com> Cc: Dun Tan <dun.tan@intel.com> Cc: Hongbin1 Zhang <hongbin1.zhang@intel.com> Cc: Wei6 Xu <wei6.xu@intel.com> Cc: Yuanhao Xie <yuanhao.xie@intel.com>
This commit is contained in:
parent
cc5df45eb6
commit
8ccf7f65e5
488
UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapDxeSmm.c
Normal file
488
UefiCpuPkg/PiSmmCpuDxeSmm/NonMmramMapDxeSmm.c
Normal file
@ -0,0 +1,488 @@
|
|||||||
|
/** @file
|
||||||
|
|
||||||
|
Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "PiSmmCpuCommon.h"
|
||||||
|
#include <Library/DxeServicesTableLib.h>
|
||||||
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||||
|
|
||||||
|
//
|
||||||
|
// attributes for reserved memory before it is promoted to system memory
|
||||||
|
//
|
||||||
|
#define EFI_MEMORY_PRESENT 0x0100000000000000ULL
|
||||||
|
#define EFI_MEMORY_INITIALIZED 0x0200000000000000ULL
|
||||||
|
#define EFI_MEMORY_TESTED 0x0400000000000000ULL
|
||||||
|
|
||||||
|
#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
|
||||||
|
((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
|
||||||
|
|
||||||
|
EFI_MEMORY_DESCRIPTOR *mUefiMemoryMap;
|
||||||
|
UINTN mUefiMemoryMapSize;
|
||||||
|
UINTN mUefiDescriptorSize;
|
||||||
|
|
||||||
|
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *mGcdMemSpace = NULL;
|
||||||
|
UINTN mGcdMemNumberOfDesc = 0;
|
||||||
|
|
||||||
|
EFI_MEMORY_ATTRIBUTES_TABLE *mUefiMemoryAttributesTable = NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sort memory map entries based upon PhysicalStart, from low to high.
|
||||||
|
|
||||||
|
@param MemoryMap A pointer to the buffer in which firmware places
|
||||||
|
the current memory map.
|
||||||
|
@param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
|
||||||
|
@param 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 if a UEFI memory page should be marked as not present in SMM page table.
|
||||||
|
If the memory map entries type is
|
||||||
|
EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
|
||||||
|
EfiUnusableMemory, EfiACPIReclaimMemory, return TRUE.
|
||||||
|
Or return FALSE.
|
||||||
|
|
||||||
|
@param[in] MemoryMap A pointer to the memory descriptor.
|
||||||
|
|
||||||
|
@return TRUE The memory described will be marked as not present in SMM page table.
|
||||||
|
@return FALSE The memory described will not be marked as not present in SMM page table.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsUefiPageNotPresent (
|
||||||
|
IN EFI_MEMORY_DESCRIPTOR *MemoryMap
|
||||||
|
)
|
||||||
|
{
|
||||||
|
switch (MemoryMap->Type) {
|
||||||
|
case EfiLoaderCode:
|
||||||
|
case EfiLoaderData:
|
||||||
|
case EfiBootServicesCode:
|
||||||
|
case EfiBootServicesData:
|
||||||
|
case EfiConventionalMemory:
|
||||||
|
case EfiUnusableMemory:
|
||||||
|
case EfiACPIReclaimMemory:
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Merge continuous memory map entries whose type is
|
||||||
|
EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
|
||||||
|
EfiUnusableMemory, EfiACPIReclaimMemory, because the memory described by
|
||||||
|
these entries will be set as NOT present in SMM page table.
|
||||||
|
|
||||||
|
@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
|
||||||
|
MergeMemoryMapForNotPresentEntry (
|
||||||
|
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)(EFI_PAGES_TO_SIZE ((UINTN)MemoryMapEntry->NumberOfPages));
|
||||||
|
if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
|
||||||
|
IsUefiPageNotPresent (MemoryMapEntry) && IsUefiPageNotPresent (NextMemoryMapEntry) &&
|
||||||
|
((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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function caches the GCD memory map information.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
GetGcdMemoryMap (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN NumberOfDescriptors;
|
||||||
|
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemSpaceMap;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemSpaceMap);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mGcdMemNumberOfDesc = 0;
|
||||||
|
for (Index = 0; Index < NumberOfDescriptors; Index++) {
|
||||||
|
if ((MemSpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved) &&
|
||||||
|
((MemSpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
|
||||||
|
(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
mGcdMemNumberOfDesc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mGcdMemSpace = AllocateZeroPool (mGcdMemNumberOfDesc * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));
|
||||||
|
ASSERT (mGcdMemSpace != NULL);
|
||||||
|
if (mGcdMemSpace == NULL) {
|
||||||
|
mGcdMemNumberOfDesc = 0;
|
||||||
|
gBS->FreePool (MemSpaceMap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mGcdMemNumberOfDesc = 0;
|
||||||
|
for (Index = 0; Index < NumberOfDescriptors; Index++) {
|
||||||
|
if ((MemSpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved) &&
|
||||||
|
((MemSpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
|
||||||
|
(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
CopyMem (
|
||||||
|
&mGcdMemSpace[mGcdMemNumberOfDesc],
|
||||||
|
&MemSpaceMap[Index],
|
||||||
|
sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR)
|
||||||
|
);
|
||||||
|
mGcdMemNumberOfDesc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gBS->FreePool (MemSpaceMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get UEFI MemoryAttributesTable.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
GetUefiMemoryAttributesTable (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;
|
||||||
|
UINTN MemoryAttributesTableSize;
|
||||||
|
|
||||||
|
Status = EfiGetSystemConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable);
|
||||||
|
if (!EFI_ERROR (Status) && (MemoryAttributesTable != NULL)) {
|
||||||
|
MemoryAttributesTableSize = sizeof (EFI_MEMORY_ATTRIBUTES_TABLE) + MemoryAttributesTable->DescriptorSize * MemoryAttributesTable->NumberOfEntries;
|
||||||
|
mUefiMemoryAttributesTable = AllocateCopyPool (MemoryAttributesTableSize, MemoryAttributesTable);
|
||||||
|
ASSERT (mUefiMemoryAttributesTable != NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function caches the UEFI memory map information.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
GetUefiMemoryMap (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN MapKey;
|
||||||
|
UINT32 DescriptorVersion;
|
||||||
|
EFI_MEMORY_DESCRIPTOR *MemoryMap;
|
||||||
|
UINTN UefiMemoryMapSize;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "GetUefiMemoryMap\n"));
|
||||||
|
|
||||||
|
UefiMemoryMapSize = 0;
|
||||||
|
MemoryMap = NULL;
|
||||||
|
Status = gBS->GetMemoryMap (
|
||||||
|
&UefiMemoryMapSize,
|
||||||
|
MemoryMap,
|
||||||
|
&MapKey,
|
||||||
|
&mUefiDescriptorSize,
|
||||||
|
&DescriptorVersion
|
||||||
|
);
|
||||||
|
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
do {
|
||||||
|
Status = gBS->AllocatePool (EfiBootServicesData, UefiMemoryMapSize, (VOID **)&MemoryMap);
|
||||||
|
ASSERT (MemoryMap != NULL);
|
||||||
|
if (MemoryMap == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gBS->GetMemoryMap (
|
||||||
|
&UefiMemoryMapSize,
|
||||||
|
MemoryMap,
|
||||||
|
&MapKey,
|
||||||
|
&mUefiDescriptorSize,
|
||||||
|
&DescriptorVersion
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
gBS->FreePool (MemoryMap);
|
||||||
|
MemoryMap = NULL;
|
||||||
|
}
|
||||||
|
} while (Status == EFI_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
|
if (MemoryMap == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SortMemoryMap (MemoryMap, UefiMemoryMapSize, mUefiDescriptorSize);
|
||||||
|
MergeMemoryMapForNotPresentEntry (MemoryMap, &UefiMemoryMapSize, mUefiDescriptorSize);
|
||||||
|
|
||||||
|
mUefiMemoryMapSize = UefiMemoryMapSize;
|
||||||
|
mUefiMemoryMap = AllocateCopyPool (UefiMemoryMapSize, MemoryMap);
|
||||||
|
ASSERT (mUefiMemoryMap != NULL);
|
||||||
|
|
||||||
|
gBS->FreePool (MemoryMap);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get additional information from GCD memory map.
|
||||||
|
//
|
||||||
|
GetGcdMemoryMap ();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get UEFI memory attributes table.
|
||||||
|
//
|
||||||
|
GetUefiMemoryAttributesTable ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function sets UEFI memory attribute according to UEFI memory map.
|
||||||
|
|
||||||
|
The normal memory region is marked as not present, such as
|
||||||
|
EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
|
||||||
|
EfiUnusableMemory, EfiACPIReclaimMemory.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
SetUefiMemMapAttributes (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_MEMORY_DESCRIPTOR *MemoryMap;
|
||||||
|
UINTN MemoryMapEntryCount;
|
||||||
|
UINTN Index;
|
||||||
|
EFI_MEMORY_DESCRIPTOR *Entry;
|
||||||
|
BOOLEAN WriteProtect;
|
||||||
|
BOOLEAN CetEnabled;
|
||||||
|
|
||||||
|
PERF_FUNCTION_BEGIN ();
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n"));
|
||||||
|
|
||||||
|
WRITE_UNPROTECT_RO_PAGES (WriteProtect, CetEnabled);
|
||||||
|
|
||||||
|
if (mUefiMemoryMap != NULL) {
|
||||||
|
MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;
|
||||||
|
MemoryMap = mUefiMemoryMap;
|
||||||
|
for (Index = 0; Index < MemoryMapEntryCount; Index++) {
|
||||||
|
if (IsUefiPageNotPresent (MemoryMap)) {
|
||||||
|
Status = SmmSetMemoryAttributes (
|
||||||
|
MemoryMap->PhysicalStart,
|
||||||
|
EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages),
|
||||||
|
EFI_MEMORY_RP
|
||||||
|
);
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"UefiMemory protection: 0x%lx - 0x%lx %r\n",
|
||||||
|
MemoryMap->PhysicalStart,
|
||||||
|
MemoryMap->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages),
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, mUefiDescriptorSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Do not free mUefiMemoryMap, it will be checked in IsSmmCommBufferForbiddenAddress().
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set untested memory as not present.
|
||||||
|
//
|
||||||
|
if (mGcdMemSpace != NULL) {
|
||||||
|
for (Index = 0; Index < mGcdMemNumberOfDesc; Index++) {
|
||||||
|
Status = SmmSetMemoryAttributes (
|
||||||
|
mGcdMemSpace[Index].BaseAddress,
|
||||||
|
mGcdMemSpace[Index].Length,
|
||||||
|
EFI_MEMORY_RP
|
||||||
|
);
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"GcdMemory protection: 0x%lx - 0x%lx %r\n",
|
||||||
|
mGcdMemSpace[Index].BaseAddress,
|
||||||
|
mGcdMemSpace[Index].BaseAddress + mGcdMemSpace[Index].Length,
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Do not free mGcdMemSpace, it will be checked in IsSmmCommBufferForbiddenAddress().
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set UEFI runtime memory with EFI_MEMORY_RO as not present.
|
||||||
|
//
|
||||||
|
if (mUefiMemoryAttributesTable != NULL) {
|
||||||
|
Entry = (EFI_MEMORY_DESCRIPTOR *)(mUefiMemoryAttributesTable + 1);
|
||||||
|
for (Index = 0; Index < mUefiMemoryAttributesTable->NumberOfEntries; Index++) {
|
||||||
|
if ((Entry->Type == EfiRuntimeServicesCode) || (Entry->Type == EfiRuntimeServicesData)) {
|
||||||
|
if ((Entry->Attribute & EFI_MEMORY_RO) != 0) {
|
||||||
|
Status = SmmSetMemoryAttributes (
|
||||||
|
Entry->PhysicalStart,
|
||||||
|
EFI_PAGES_TO_SIZE ((UINTN)Entry->NumberOfPages),
|
||||||
|
EFI_MEMORY_RP
|
||||||
|
);
|
||||||
|
DEBUG ((
|
||||||
|
DEBUG_INFO,
|
||||||
|
"UefiMemoryAttribute protection: 0x%lx - 0x%lx %r\n",
|
||||||
|
Entry->PhysicalStart,
|
||||||
|
Entry->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE ((UINTN)Entry->NumberOfPages),
|
||||||
|
Status
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry = NEXT_MEMORY_DESCRIPTOR (Entry, mUefiMemoryAttributesTable->DescriptorSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WRITE_PROTECT_RO_PAGES (WriteProtect, CetEnabled);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Do not free mUefiMemoryAttributesTable, it will be checked in IsSmmCommBufferForbiddenAddress().
|
||||||
|
//
|
||||||
|
|
||||||
|
PERF_FUNCTION_END ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return if the Address is forbidden as SMM communication buffer.
|
||||||
|
|
||||||
|
@param[in] Address the address to be checked
|
||||||
|
|
||||||
|
@return TRUE The address is forbidden as SMM communication buffer.
|
||||||
|
@return FALSE The address is allowed as SMM communication buffer.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsSmmCommBufferForbiddenAddress (
|
||||||
|
IN UINT64 Address
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_MEMORY_DESCRIPTOR *MemoryMap;
|
||||||
|
UINTN MemoryMapEntryCount;
|
||||||
|
UINTN Index;
|
||||||
|
EFI_MEMORY_DESCRIPTOR *Entry;
|
||||||
|
|
||||||
|
if (mUefiMemoryMap != NULL) {
|
||||||
|
MemoryMap = mUefiMemoryMap;
|
||||||
|
MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;
|
||||||
|
for (Index = 0; Index < MemoryMapEntryCount; Index++) {
|
||||||
|
if (IsUefiPageNotPresent (MemoryMap)) {
|
||||||
|
if ((Address >= MemoryMap->PhysicalStart) &&
|
||||||
|
(Address < MemoryMap->PhysicalStart + EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages)))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, mUefiDescriptorSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mGcdMemSpace != NULL) {
|
||||||
|
for (Index = 0; Index < mGcdMemNumberOfDesc; Index++) {
|
||||||
|
if ((Address >= mGcdMemSpace[Index].BaseAddress) &&
|
||||||
|
(Address < mGcdMemSpace[Index].BaseAddress + mGcdMemSpace[Index].Length))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mUefiMemoryAttributesTable != NULL) {
|
||||||
|
Entry = (EFI_MEMORY_DESCRIPTOR *)(mUefiMemoryAttributesTable + 1);
|
||||||
|
for (Index = 0; Index < mUefiMemoryAttributesTable->NumberOfEntries; Index++) {
|
||||||
|
if ((Entry->Type == EfiRuntimeServicesCode) || (Entry->Type == EfiRuntimeServicesData)) {
|
||||||
|
if ((Entry->Attribute & EFI_MEMORY_RO) != 0) {
|
||||||
|
if ((Address >= Entry->PhysicalStart) &&
|
||||||
|
(Address < Entry->PhysicalStart + LShiftU64 (Entry->NumberOfPages, EFI_PAGE_SHIFT)))
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry = NEXT_MEMORY_DESCRIPTOR (Entry, mUefiMemoryAttributesTable->DescriptorSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
@ -46,6 +46,7 @@
|
|||||||
SmmMp.c
|
SmmMp.c
|
||||||
SmmMpPerf.h
|
SmmMpPerf.h
|
||||||
SmmMpPerf.c
|
SmmMpPerf.c
|
||||||
|
NonMmramMapDxeSmm.c
|
||||||
|
|
||||||
[Sources.Ia32]
|
[Sources.Ia32]
|
||||||
Ia32/PageTbl.c
|
Ia32/PageTbl.c
|
||||||
|
@ -7,25 +7,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
|||||||
|
|
||||||
#include "PiSmmCpuCommon.h"
|
#include "PiSmmCpuCommon.h"
|
||||||
|
|
||||||
//
|
|
||||||
// attributes for reserved memory before it is promoted to system memory
|
|
||||||
//
|
|
||||||
#define EFI_MEMORY_PRESENT 0x0100000000000000ULL
|
|
||||||
#define EFI_MEMORY_INITIALIZED 0x0200000000000000ULL
|
|
||||||
#define EFI_MEMORY_TESTED 0x0400000000000000ULL
|
|
||||||
|
|
||||||
#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
|
|
||||||
((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
|
|
||||||
|
|
||||||
EFI_MEMORY_DESCRIPTOR *mUefiMemoryMap;
|
|
||||||
UINTN mUefiMemoryMapSize;
|
|
||||||
UINTN mUefiDescriptorSize;
|
|
||||||
|
|
||||||
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *mGcdMemSpace = NULL;
|
|
||||||
UINTN mGcdMemNumberOfDesc = 0;
|
|
||||||
|
|
||||||
EFI_MEMORY_ATTRIBUTES_TABLE *mUefiMemoryAttributesTable = NULL;
|
|
||||||
|
|
||||||
BOOLEAN mIsShadowStack = FALSE;
|
BOOLEAN mIsShadowStack = FALSE;
|
||||||
BOOLEAN m5LevelPagingNeeded = FALSE;
|
BOOLEAN m5LevelPagingNeeded = FALSE;
|
||||||
PAGING_MODE mPagingMode = PagingModeMax;
|
PAGING_MODE mPagingMode = PagingModeMax;
|
||||||
@ -1118,464 +1099,6 @@ SetMemMapAttributes (
|
|||||||
PERF_FUNCTION_END ();
|
PERF_FUNCTION_END ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Sort memory map entries based upon PhysicalStart, from low to high.
|
|
||||||
|
|
||||||
@param MemoryMap A pointer to the buffer in which firmware places
|
|
||||||
the current memory map.
|
|
||||||
@param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
|
|
||||||
@param 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 if a UEFI memory page should be marked as not present in SMM page table.
|
|
||||||
If the memory map entries type is
|
|
||||||
EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
|
|
||||||
EfiUnusableMemory, EfiACPIReclaimMemory, return TRUE.
|
|
||||||
Or return FALSE.
|
|
||||||
|
|
||||||
@param[in] MemoryMap A pointer to the memory descriptor.
|
|
||||||
|
|
||||||
@return TRUE The memory described will be marked as not present in SMM page table.
|
|
||||||
@return FALSE The memory described will not be marked as not present in SMM page table.
|
|
||||||
**/
|
|
||||||
BOOLEAN
|
|
||||||
IsUefiPageNotPresent (
|
|
||||||
IN EFI_MEMORY_DESCRIPTOR *MemoryMap
|
|
||||||
)
|
|
||||||
{
|
|
||||||
switch (MemoryMap->Type) {
|
|
||||||
case EfiLoaderCode:
|
|
||||||
case EfiLoaderData:
|
|
||||||
case EfiBootServicesCode:
|
|
||||||
case EfiBootServicesData:
|
|
||||||
case EfiConventionalMemory:
|
|
||||||
case EfiUnusableMemory:
|
|
||||||
case EfiACPIReclaimMemory:
|
|
||||||
return TRUE;
|
|
||||||
default:
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Merge continuous memory map entries whose type is
|
|
||||||
EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
|
|
||||||
EfiUnusableMemory, EfiACPIReclaimMemory, because the memory described by
|
|
||||||
these entries will be set as NOT present in SMM page table.
|
|
||||||
|
|
||||||
@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
|
|
||||||
MergeMemoryMapForNotPresentEntry (
|
|
||||||
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)(EFI_PAGES_TO_SIZE ((UINTN)MemoryMapEntry->NumberOfPages));
|
|
||||||
if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
|
|
||||||
IsUefiPageNotPresent (MemoryMapEntry) && IsUefiPageNotPresent (NextMemoryMapEntry) &&
|
|
||||||
((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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function caches the GCD memory map information.
|
|
||||||
**/
|
|
||||||
VOID
|
|
||||||
GetGcdMemoryMap (
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
UINTN NumberOfDescriptors;
|
|
||||||
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemSpaceMap;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
UINTN Index;
|
|
||||||
|
|
||||||
Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemSpaceMap);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mGcdMemNumberOfDesc = 0;
|
|
||||||
for (Index = 0; Index < NumberOfDescriptors; Index++) {
|
|
||||||
if ((MemSpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved) &&
|
|
||||||
((MemSpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
|
|
||||||
(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
mGcdMemNumberOfDesc++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mGcdMemSpace = AllocateZeroPool (mGcdMemNumberOfDesc * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));
|
|
||||||
ASSERT (mGcdMemSpace != NULL);
|
|
||||||
if (mGcdMemSpace == NULL) {
|
|
||||||
mGcdMemNumberOfDesc = 0;
|
|
||||||
gBS->FreePool (MemSpaceMap);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mGcdMemNumberOfDesc = 0;
|
|
||||||
for (Index = 0; Index < NumberOfDescriptors; Index++) {
|
|
||||||
if ((MemSpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved) &&
|
|
||||||
((MemSpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==
|
|
||||||
(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED))
|
|
||||||
)
|
|
||||||
{
|
|
||||||
CopyMem (
|
|
||||||
&mGcdMemSpace[mGcdMemNumberOfDesc],
|
|
||||||
&MemSpaceMap[Index],
|
|
||||||
sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR)
|
|
||||||
);
|
|
||||||
mGcdMemNumberOfDesc++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gBS->FreePool (MemSpaceMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get UEFI MemoryAttributesTable.
|
|
||||||
**/
|
|
||||||
VOID
|
|
||||||
GetUefiMemoryAttributesTable (
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;
|
|
||||||
UINTN MemoryAttributesTableSize;
|
|
||||||
|
|
||||||
Status = EfiGetSystemConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable);
|
|
||||||
if (!EFI_ERROR (Status) && (MemoryAttributesTable != NULL)) {
|
|
||||||
MemoryAttributesTableSize = sizeof (EFI_MEMORY_ATTRIBUTES_TABLE) + MemoryAttributesTable->DescriptorSize * MemoryAttributesTable->NumberOfEntries;
|
|
||||||
mUefiMemoryAttributesTable = AllocateCopyPool (MemoryAttributesTableSize, MemoryAttributesTable);
|
|
||||||
ASSERT (mUefiMemoryAttributesTable != NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function caches the UEFI memory map information.
|
|
||||||
**/
|
|
||||||
VOID
|
|
||||||
GetUefiMemoryMap (
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
UINTN MapKey;
|
|
||||||
UINT32 DescriptorVersion;
|
|
||||||
EFI_MEMORY_DESCRIPTOR *MemoryMap;
|
|
||||||
UINTN UefiMemoryMapSize;
|
|
||||||
|
|
||||||
DEBUG ((DEBUG_INFO, "GetUefiMemoryMap\n"));
|
|
||||||
|
|
||||||
UefiMemoryMapSize = 0;
|
|
||||||
MemoryMap = NULL;
|
|
||||||
Status = gBS->GetMemoryMap (
|
|
||||||
&UefiMemoryMapSize,
|
|
||||||
MemoryMap,
|
|
||||||
&MapKey,
|
|
||||||
&mUefiDescriptorSize,
|
|
||||||
&DescriptorVersion
|
|
||||||
);
|
|
||||||
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
|
|
||||||
|
|
||||||
do {
|
|
||||||
Status = gBS->AllocatePool (EfiBootServicesData, UefiMemoryMapSize, (VOID **)&MemoryMap);
|
|
||||||
ASSERT (MemoryMap != NULL);
|
|
||||||
if (MemoryMap == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = gBS->GetMemoryMap (
|
|
||||||
&UefiMemoryMapSize,
|
|
||||||
MemoryMap,
|
|
||||||
&MapKey,
|
|
||||||
&mUefiDescriptorSize,
|
|
||||||
&DescriptorVersion
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
gBS->FreePool (MemoryMap);
|
|
||||||
MemoryMap = NULL;
|
|
||||||
}
|
|
||||||
} while (Status == EFI_BUFFER_TOO_SMALL);
|
|
||||||
|
|
||||||
if (MemoryMap == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SortMemoryMap (MemoryMap, UefiMemoryMapSize, mUefiDescriptorSize);
|
|
||||||
MergeMemoryMapForNotPresentEntry (MemoryMap, &UefiMemoryMapSize, mUefiDescriptorSize);
|
|
||||||
|
|
||||||
mUefiMemoryMapSize = UefiMemoryMapSize;
|
|
||||||
mUefiMemoryMap = AllocateCopyPool (UefiMemoryMapSize, MemoryMap);
|
|
||||||
ASSERT (mUefiMemoryMap != NULL);
|
|
||||||
|
|
||||||
gBS->FreePool (MemoryMap);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get additional information from GCD memory map.
|
|
||||||
//
|
|
||||||
GetGcdMemoryMap ();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Get UEFI memory attributes table.
|
|
||||||
//
|
|
||||||
GetUefiMemoryAttributesTable ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
This function sets UEFI memory attribute according to UEFI memory map.
|
|
||||||
|
|
||||||
The normal memory region is marked as not present, such as
|
|
||||||
EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
|
|
||||||
EfiUnusableMemory, EfiACPIReclaimMemory.
|
|
||||||
**/
|
|
||||||
VOID
|
|
||||||
SetUefiMemMapAttributes (
|
|
||||||
VOID
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
EFI_MEMORY_DESCRIPTOR *MemoryMap;
|
|
||||||
UINTN MemoryMapEntryCount;
|
|
||||||
UINTN Index;
|
|
||||||
EFI_MEMORY_DESCRIPTOR *Entry;
|
|
||||||
BOOLEAN WriteProtect;
|
|
||||||
BOOLEAN CetEnabled;
|
|
||||||
|
|
||||||
PERF_FUNCTION_BEGIN ();
|
|
||||||
|
|
||||||
DEBUG ((DEBUG_INFO, "SetUefiMemMapAttributes\n"));
|
|
||||||
|
|
||||||
WRITE_UNPROTECT_RO_PAGES (WriteProtect, CetEnabled);
|
|
||||||
|
|
||||||
if (mUefiMemoryMap != NULL) {
|
|
||||||
MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;
|
|
||||||
MemoryMap = mUefiMemoryMap;
|
|
||||||
for (Index = 0; Index < MemoryMapEntryCount; Index++) {
|
|
||||||
if (IsUefiPageNotPresent (MemoryMap)) {
|
|
||||||
Status = SmmSetMemoryAttributes (
|
|
||||||
MemoryMap->PhysicalStart,
|
|
||||||
EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages),
|
|
||||||
EFI_MEMORY_RP
|
|
||||||
);
|
|
||||||
DEBUG ((
|
|
||||||
DEBUG_INFO,
|
|
||||||
"UefiMemory protection: 0x%lx - 0x%lx %r\n",
|
|
||||||
MemoryMap->PhysicalStart,
|
|
||||||
MemoryMap->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages),
|
|
||||||
Status
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, mUefiDescriptorSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do not free mUefiMemoryMap, it will be checked in IsSmmCommBufferForbiddenAddress().
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set untested memory as not present.
|
|
||||||
//
|
|
||||||
if (mGcdMemSpace != NULL) {
|
|
||||||
for (Index = 0; Index < mGcdMemNumberOfDesc; Index++) {
|
|
||||||
Status = SmmSetMemoryAttributes (
|
|
||||||
mGcdMemSpace[Index].BaseAddress,
|
|
||||||
mGcdMemSpace[Index].Length,
|
|
||||||
EFI_MEMORY_RP
|
|
||||||
);
|
|
||||||
DEBUG ((
|
|
||||||
DEBUG_INFO,
|
|
||||||
"GcdMemory protection: 0x%lx - 0x%lx %r\n",
|
|
||||||
mGcdMemSpace[Index].BaseAddress,
|
|
||||||
mGcdMemSpace[Index].BaseAddress + mGcdMemSpace[Index].Length,
|
|
||||||
Status
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do not free mGcdMemSpace, it will be checked in IsSmmCommBufferForbiddenAddress().
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Set UEFI runtime memory with EFI_MEMORY_RO as not present.
|
|
||||||
//
|
|
||||||
if (mUefiMemoryAttributesTable != NULL) {
|
|
||||||
Entry = (EFI_MEMORY_DESCRIPTOR *)(mUefiMemoryAttributesTable + 1);
|
|
||||||
for (Index = 0; Index < mUefiMemoryAttributesTable->NumberOfEntries; Index++) {
|
|
||||||
if ((Entry->Type == EfiRuntimeServicesCode) || (Entry->Type == EfiRuntimeServicesData)) {
|
|
||||||
if ((Entry->Attribute & EFI_MEMORY_RO) != 0) {
|
|
||||||
Status = SmmSetMemoryAttributes (
|
|
||||||
Entry->PhysicalStart,
|
|
||||||
EFI_PAGES_TO_SIZE ((UINTN)Entry->NumberOfPages),
|
|
||||||
EFI_MEMORY_RP
|
|
||||||
);
|
|
||||||
DEBUG ((
|
|
||||||
DEBUG_INFO,
|
|
||||||
"UefiMemoryAttribute protection: 0x%lx - 0x%lx %r\n",
|
|
||||||
Entry->PhysicalStart,
|
|
||||||
Entry->PhysicalStart + (UINT64)EFI_PAGES_TO_SIZE ((UINTN)Entry->NumberOfPages),
|
|
||||||
Status
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Entry = NEXT_MEMORY_DESCRIPTOR (Entry, mUefiMemoryAttributesTable->DescriptorSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WRITE_PROTECT_RO_PAGES (WriteProtect, CetEnabled);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Do not free mUefiMemoryAttributesTable, it will be checked in IsSmmCommBufferForbiddenAddress().
|
|
||||||
//
|
|
||||||
|
|
||||||
PERF_FUNCTION_END ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Return if the Address is forbidden as SMM communication buffer.
|
|
||||||
|
|
||||||
@param[in] Address the address to be checked
|
|
||||||
|
|
||||||
@return TRUE The address is forbidden as SMM communication buffer.
|
|
||||||
@return FALSE The address is allowed as SMM communication buffer.
|
|
||||||
**/
|
|
||||||
BOOLEAN
|
|
||||||
IsSmmCommBufferForbiddenAddress (
|
|
||||||
IN UINT64 Address
|
|
||||||
)
|
|
||||||
{
|
|
||||||
EFI_MEMORY_DESCRIPTOR *MemoryMap;
|
|
||||||
UINTN MemoryMapEntryCount;
|
|
||||||
UINTN Index;
|
|
||||||
EFI_MEMORY_DESCRIPTOR *Entry;
|
|
||||||
|
|
||||||
if (mUefiMemoryMap != NULL) {
|
|
||||||
MemoryMap = mUefiMemoryMap;
|
|
||||||
MemoryMapEntryCount = mUefiMemoryMapSize/mUefiDescriptorSize;
|
|
||||||
for (Index = 0; Index < MemoryMapEntryCount; Index++) {
|
|
||||||
if (IsUefiPageNotPresent (MemoryMap)) {
|
|
||||||
if ((Address >= MemoryMap->PhysicalStart) &&
|
|
||||||
(Address < MemoryMap->PhysicalStart + EFI_PAGES_TO_SIZE ((UINTN)MemoryMap->NumberOfPages)))
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, mUefiDescriptorSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mGcdMemSpace != NULL) {
|
|
||||||
for (Index = 0; Index < mGcdMemNumberOfDesc; Index++) {
|
|
||||||
if ((Address >= mGcdMemSpace[Index].BaseAddress) &&
|
|
||||||
(Address < mGcdMemSpace[Index].BaseAddress + mGcdMemSpace[Index].Length))
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mUefiMemoryAttributesTable != NULL) {
|
|
||||||
Entry = (EFI_MEMORY_DESCRIPTOR *)(mUefiMemoryAttributesTable + 1);
|
|
||||||
for (Index = 0; Index < mUefiMemoryAttributesTable->NumberOfEntries; Index++) {
|
|
||||||
if ((Entry->Type == EfiRuntimeServicesCode) || (Entry->Type == EfiRuntimeServicesData)) {
|
|
||||||
if ((Entry->Attribute & EFI_MEMORY_RO) != 0) {
|
|
||||||
if ((Address >= Entry->PhysicalStart) &&
|
|
||||||
(Address < Entry->PhysicalStart + LShiftU64 (Entry->NumberOfPages, EFI_PAGE_SHIFT)))
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entry = NEXT_MEMORY_DESCRIPTOR (Entry, mUefiMemoryAttributesTable->DescriptorSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This function set given attributes of the memory region specified by
|
This function set given attributes of the memory region specified by
|
||||||
BaseAddress and Length.
|
BaseAddress and Length.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user