/** @file | |
This module sets default policy for attributes of EfiACPIMemoryNVS and EfiReservedMemoryType. | |
This module sets EFI_MEMORY_XP for attributes of EfiACPIMemoryNVS and EfiReservedMemoryType | |
in UEFI memory map, if and only of PropertiesTable is published and has BIT0 set. | |
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> | |
This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
**/ | |
#include <Uefi.h> | |
#include <Library/DebugLib.h> | |
#include <Library/UefiBootServicesTableLib.h> | |
#include <Library/DxeServicesTableLib.h> | |
#include <Library/UefiLib.h> | |
#include <Library/MemoryAllocationLib.h> | |
#include <Guid/EventGroup.h> | |
#include <Guid/PropertiesTable.h> | |
/** | |
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 Pages The number of EFI_PAGES. | |
@return The number of bytes associated with the number of EFI_PAGEs specified | |
by Pages. | |
**/ | |
UINT64 | |
EfiPagesToSize ( | |
IN UINT64 Pages | |
) | |
{ | |
return LShiftU64 (Pages, EFI_PAGE_SHIFT); | |
} | |
/** | |
Set memory attributes according to default policy. | |
@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. | |
**/ | |
VOID | |
SetMemorySpaceAttributesDefault ( | |
IN EFI_MEMORY_DESCRIPTOR *MemoryMap, | |
IN UINTN MemoryMapSize, | |
IN UINTN DescriptorSize | |
) | |
{ | |
EFI_MEMORY_DESCRIPTOR *MemoryMapEntry; | |
EFI_MEMORY_DESCRIPTOR *MemoryMapEnd; | |
EFI_STATUS Status; | |
DEBUG ((EFI_D_INFO, "SetMemorySpaceAttributesDefault\n")); | |
MemoryMapEntry = MemoryMap; | |
MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize); | |
while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) { | |
if (MemoryMapEntry->PhysicalStart < BASE_1MB) { | |
// | |
// Do not touch memory space below 1MB | |
// | |
MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); | |
continue; | |
} | |
switch (MemoryMapEntry->Type) { | |
case EfiRuntimeServicesCode: | |
case EfiRuntimeServicesData: | |
// | |
// should be handled later; | |
// | |
break; | |
case EfiReservedMemoryType: | |
case EfiACPIMemoryNVS: | |
// | |
// Handle EfiReservedMemoryType and EfiACPIMemoryNVS, because there might be firmware executable there. | |
// | |
DEBUG ((EFI_D_INFO, "SetMemorySpaceAttributes - %016lx - %016lx (%016lx) ...\n", | |
MemoryMapEntry->PhysicalStart, | |
MemoryMapEntry->PhysicalStart + EfiPagesToSize (MemoryMapEntry->NumberOfPages), | |
MemoryMapEntry->Attribute | |
)); | |
Status = gDS->SetMemorySpaceCapabilities ( | |
MemoryMapEntry->PhysicalStart, | |
EfiPagesToSize (MemoryMapEntry->NumberOfPages), | |
MemoryMapEntry->Attribute | EFI_MEMORY_XP | |
); | |
DEBUG ((EFI_D_INFO, "SetMemorySpaceCapabilities - %r\n", Status)); | |
break; | |
} | |
MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize); | |
} | |
return ; | |
} | |
/** | |
Update memory attributes according to default policy. | |
@param[in] Event The Event this notify function registered to. | |
@param[in] Context Pointer to the context data registered to the Event. | |
**/ | |
VOID | |
EFIAPI | |
UpdateMemoryAttributesDefault ( | |
EFI_EVENT Event, | |
VOID *Context | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_MEMORY_DESCRIPTOR *MemoryMap; | |
UINTN MemoryMapSize; | |
UINTN MapKey; | |
UINTN DescriptorSize; | |
UINT32 DescriptorVersion; | |
EFI_PROPERTIES_TABLE *PropertiesTable; | |
DEBUG ((EFI_D_INFO, "UpdateMemoryAttributesDefault\n")); | |
Status = EfiGetSystemConfigurationTable (&gEfiPropertiesTableGuid, (VOID **) &PropertiesTable); | |
if (EFI_ERROR (Status)) { | |
goto Done; | |
} | |
ASSERT (PropertiesTable != NULL); | |
DEBUG ((EFI_D_INFO, "MemoryProtectionAttribute - 0x%016lx\n", PropertiesTable->MemoryProtectionAttribute)); | |
if ((PropertiesTable->MemoryProtectionAttribute & EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) { | |
goto Done; | |
} | |
// | |
// Get the EFI memory map. | |
// | |
MemoryMapSize = 0; | |
MemoryMap = NULL; | |
Status = gBS->GetMemoryMap ( | |
&MemoryMapSize, | |
MemoryMap, | |
&MapKey, | |
&DescriptorSize, | |
&DescriptorVersion | |
); | |
ASSERT (Status == EFI_BUFFER_TOO_SMALL); | |
do { | |
MemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (MemoryMapSize); | |
ASSERT (MemoryMap != NULL); | |
Status = gBS->GetMemoryMap ( | |
&MemoryMapSize, | |
MemoryMap, | |
&MapKey, | |
&DescriptorSize, | |
&DescriptorVersion | |
); | |
if (EFI_ERROR (Status)) { | |
FreePool (MemoryMap); | |
} | |
} while (Status == EFI_BUFFER_TOO_SMALL); | |
ASSERT_EFI_ERROR (Status); | |
SetMemorySpaceAttributesDefault (MemoryMap, MemoryMapSize, DescriptorSize); | |
Done: | |
gBS->CloseEvent (Event); | |
return ; | |
} | |
/** | |
The entrypoint of properties table attribute driver. | |
@param ImageHandle The firmware allocated handle for the EFI image. | |
@param SystemTable A pointer to the EFI System Table. | |
@retval EFI_SUCCESS It always returns EFI_SUCCESS. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
InitializePropertiesTableAttributesDxe ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_EVENT ReadyToBootEvent; | |
Status = gBS->CreateEventEx ( | |
EVT_NOTIFY_SIGNAL, | |
TPL_CALLBACK, | |
UpdateMemoryAttributesDefault, | |
NULL, | |
&gEfiEventReadyToBootGuid, | |
&ReadyToBootEvent | |
); | |
ASSERT_EFI_ERROR (Status); | |
return EFI_SUCCESS; | |
} |