mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-28 17:08:18 +01:00
7c0aa811ec
Signed-off-by: Sergey Isakov <isakov-sl@bk.ru>
297 lines
10 KiB
C
297 lines
10 KiB
C
/** @file
|
|
UEFI MemoryAttributesTable support
|
|
|
|
Copyright (c) 2016 - 2018, 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/DxeServicesTableLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/UefiLib.h>
|
|
|
|
#include <Guid/EventGroup.h>
|
|
|
|
#include <Guid/MemoryAttributesTable.h>
|
|
#include <Guid/PropertiesTable.h>
|
|
|
|
#include "DxeMain.h"
|
|
|
|
/**
|
|
This function for GetMemoryMap() with properties table capability.
|
|
|
|
It calls original GetMemoryMap() to get the original memory map information. Then
|
|
plus the additional memory map entries for PE Code/Data seperation.
|
|
|
|
@param 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 MemoryMap A pointer to the buffer in which firmware places
|
|
the current memory map.
|
|
@param MapKey A pointer to the location in which firmware
|
|
returns the key for the current memory map.
|
|
@param DescriptorSize A pointer to the location in which firmware
|
|
returns the size, in bytes, of an individual
|
|
EFI_MEMORY_DESCRIPTOR.
|
|
@param 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.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CoreGetMemoryMapWithSeparatedImageSection (
|
|
IN OUT UINTN *MemoryMapSize,
|
|
IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
|
|
OUT UINTN *MapKey,
|
|
OUT UINTN *DescriptorSize,
|
|
OUT UINT32 *DescriptorVersion
|
|
);
|
|
|
|
extern EFI_PROPERTIES_TABLE mPropertiesTable;
|
|
EFI_MEMORY_ATTRIBUTES_TABLE *mMemoryAttributesTable = NULL;
|
|
BOOLEAN mMemoryAttributesTableReadyToBoot = FALSE;
|
|
|
|
/**
|
|
Install MemoryAttributesTable.
|
|
|
|
**/
|
|
VOID
|
|
InstallMemoryAttributesTable (
|
|
VOID
|
|
)
|
|
{
|
|
UINTN MemoryMapSize;
|
|
EFI_MEMORY_DESCRIPTOR *MemoryMap;
|
|
EFI_MEMORY_DESCRIPTOR *MemoryMapStart;
|
|
UINTN MapKey;
|
|
UINTN DescriptorSize;
|
|
UINT32 DescriptorVersion;
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
UINT32 RuntimeEntryCount;
|
|
EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;
|
|
EFI_MEMORY_DESCRIPTOR *MemoryAttributesEntry;
|
|
|
|
if (gMemoryMapTerminated) {
|
|
//
|
|
// Directly return after MemoryMap terminated.
|
|
//
|
|
return;
|
|
}
|
|
|
|
if ((mPropertiesTable.MemoryProtectionAttribute & EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {
|
|
DEBUG ((EFI_D_VERBOSE, "MemoryProtectionAttribute NON_EXECUTABLE_PE_DATA is not set, "));
|
|
DEBUG ((EFI_D_VERBOSE, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10));
|
|
return ;
|
|
}
|
|
|
|
if (mMemoryAttributesTable == NULL) {
|
|
//
|
|
// InstallConfigurationTable here to occupy one entry for MemoryAttributesTable
|
|
// before GetMemoryMap below, as InstallConfigurationTable may allocate runtime
|
|
// memory for the new entry.
|
|
//
|
|
Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID *) (UINTN) MAX_ADDRESS);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
MemoryMapSize = 0;
|
|
MemoryMap = NULL;
|
|
Status = CoreGetMemoryMapWithSeparatedImageSection (
|
|
&MemoryMapSize,
|
|
MemoryMap,
|
|
&MapKey,
|
|
&DescriptorSize,
|
|
&DescriptorVersion
|
|
);
|
|
ASSERT (Status == EFI_BUFFER_TOO_SMALL);
|
|
|
|
do {
|
|
MemoryMap = AllocatePool (MemoryMapSize);
|
|
ASSERT (MemoryMap != NULL);
|
|
|
|
Status = CoreGetMemoryMapWithSeparatedImageSection (
|
|
&MemoryMapSize,
|
|
MemoryMap,
|
|
&MapKey,
|
|
&DescriptorSize,
|
|
&DescriptorVersion
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
FreePool (MemoryMap);
|
|
}
|
|
} while (Status == EFI_BUFFER_TOO_SMALL);
|
|
|
|
MemoryMapStart = MemoryMap;
|
|
RuntimeEntryCount = 0;
|
|
for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {
|
|
switch (MemoryMap->Type) {
|
|
case EfiRuntimeServicesCode:
|
|
case EfiRuntimeServicesData:
|
|
RuntimeEntryCount ++;
|
|
break;
|
|
}
|
|
MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);
|
|
}
|
|
|
|
//
|
|
// Allocate MemoryAttributesTable
|
|
//
|
|
MemoryAttributesTable = AllocatePool (sizeof(EFI_MEMORY_ATTRIBUTES_TABLE) + DescriptorSize * RuntimeEntryCount);
|
|
ASSERT (MemoryAttributesTable != NULL);
|
|
MemoryAttributesTable->Version = EFI_MEMORY_ATTRIBUTES_TABLE_VERSION;
|
|
MemoryAttributesTable->NumberOfEntries = RuntimeEntryCount;
|
|
MemoryAttributesTable->DescriptorSize = (UINT32)DescriptorSize;
|
|
MemoryAttributesTable->Reserved = 0;
|
|
DEBUG ((EFI_D_VERBOSE, "MemoryAttributesTable:\n"));
|
|
DEBUG ((EFI_D_VERBOSE, " Version - 0x%08x\n", MemoryAttributesTable->Version));
|
|
DEBUG ((EFI_D_VERBOSE, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable->NumberOfEntries));
|
|
DEBUG ((EFI_D_VERBOSE, " DescriptorSize - 0x%08x\n", MemoryAttributesTable->DescriptorSize));
|
|
MemoryAttributesEntry = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1);
|
|
MemoryMap = MemoryMapStart;
|
|
for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {
|
|
switch (MemoryMap->Type) {
|
|
case EfiRuntimeServicesCode:
|
|
case EfiRuntimeServicesData:
|
|
CopyMem (MemoryAttributesEntry, MemoryMap, DescriptorSize);
|
|
MemoryAttributesEntry->Attribute &= (EFI_MEMORY_RO|EFI_MEMORY_XP|EFI_MEMORY_RUNTIME);
|
|
DEBUG ((EFI_D_VERBOSE, "Entry (0x%x)\n", MemoryAttributesEntry));
|
|
DEBUG ((EFI_D_VERBOSE, " Type - 0x%x\n", MemoryAttributesEntry->Type));
|
|
DEBUG ((EFI_D_VERBOSE, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry->PhysicalStart));
|
|
DEBUG ((EFI_D_VERBOSE, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry->VirtualStart));
|
|
DEBUG ((EFI_D_VERBOSE, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry->NumberOfPages));
|
|
DEBUG ((EFI_D_VERBOSE, " Attribute - 0x%016lx\n", MemoryAttributesEntry->Attribute));
|
|
MemoryAttributesEntry = NEXT_MEMORY_DESCRIPTOR(MemoryAttributesEntry, DescriptorSize);
|
|
break;
|
|
}
|
|
MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);
|
|
}
|
|
MemoryMap = MemoryMapStart;
|
|
FreePool (MemoryMap);
|
|
|
|
//
|
|
// Update configuratoin table for MemoryAttributesTable.
|
|
//
|
|
Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, MemoryAttributesTable);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
if (mMemoryAttributesTable != NULL) {
|
|
FreePool (mMemoryAttributesTable);
|
|
}
|
|
mMemoryAttributesTable = MemoryAttributesTable;
|
|
}
|
|
|
|
/**
|
|
Install MemoryAttributesTable on memory allocation.
|
|
|
|
@param[in] MemoryType EFI memory type.
|
|
**/
|
|
VOID
|
|
InstallMemoryAttributesTableOnMemoryAllocation (
|
|
IN EFI_MEMORY_TYPE MemoryType
|
|
)
|
|
{
|
|
//
|
|
// Install MemoryAttributesTable after ReadyToBoot on runtime memory allocation.
|
|
//
|
|
if (mMemoryAttributesTableReadyToBoot &&
|
|
((MemoryType == EfiRuntimeServicesCode) || (MemoryType == EfiRuntimeServicesData))) {
|
|
InstallMemoryAttributesTable ();
|
|
}
|
|
}
|
|
|
|
/**
|
|
Install MemoryAttributesTable on ReadyToBoot.
|
|
|
|
@param[in] Event The Event this notify function registered to.
|
|
@param[in] Context Pointer to the context data registered to the Event.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
InstallMemoryAttributesTableOnReadyToBoot (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
InstallMemoryAttributesTable ();
|
|
mMemoryAttributesTableReadyToBoot = TRUE;
|
|
}
|
|
|
|
/**
|
|
Install initial MemoryAttributesTable on EndOfDxe.
|
|
Then SMM can consume this information.
|
|
|
|
@param[in] Event The Event this notify function registered to.
|
|
@param[in] Context Pointer to the context data registered to the Event.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
InstallMemoryAttributesTableOnEndOfDxe (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
InstallMemoryAttributesTable ();
|
|
}
|
|
|
|
/**
|
|
Initialize MemoryAttrubutesTable support.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
CoreInitializeMemoryAttributesTable (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_EVENT ReadyToBootEvent;
|
|
EFI_EVENT EndOfDxeEvent;
|
|
|
|
//
|
|
// Construct the table at ReadyToBoot.
|
|
//
|
|
Status = CoreCreateEventInternal (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_CALLBACK,
|
|
InstallMemoryAttributesTableOnReadyToBoot,
|
|
NULL,
|
|
&gEfiEventReadyToBootGuid,
|
|
&ReadyToBootEvent
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Construct the initial table at EndOfDxe,
|
|
// then SMM can consume this information.
|
|
// Use TPL_NOTIFY here, as such SMM code (TPL_CALLBACK)
|
|
// can run after it.
|
|
//
|
|
Status = CoreCreateEventInternal (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_NOTIFY,
|
|
InstallMemoryAttributesTableOnEndOfDxe,
|
|
NULL,
|
|
&gEfiEndOfDxeEventGroupGuid,
|
|
&EndOfDxeEvent
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
return ;
|
|
}
|