/** @file | |
* High memory node enumeration DXE driver for ARM and RISC-V | |
* Virtual Machines | |
* | |
* Copyright (c) 2015-2016, Linaro Ltd. All rights reserved. | |
* | |
* SPDX-License-Identifier: BSD-2-Clause-Patent | |
* | |
**/ | |
#include <Library/BaseLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/DxeServicesTableLib.h> | |
#include <Library/PcdLib.h> | |
#include <Library/UefiBootServicesTableLib.h> | |
#include <Protocol/Cpu.h> | |
#include <Protocol/FdtClient.h> | |
EFI_STATUS | |
EFIAPI | |
InitializeHighMemDxe ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
{ | |
FDT_CLIENT_PROTOCOL *FdtClient; | |
EFI_CPU_ARCH_PROTOCOL *Cpu; | |
EFI_STATUS Status, FindNodeStatus; | |
INT32 Node; | |
CONST UINT32 *Reg; | |
UINT32 RegSize; | |
UINTN AddressCells, SizeCells; | |
UINT64 CurBase; | |
UINT64 CurSize; | |
UINT64 Attributes; | |
EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; | |
Status = gBS->LocateProtocol ( | |
&gFdtClientProtocolGuid, | |
NULL, | |
(VOID **)&FdtClient | |
); | |
ASSERT_EFI_ERROR (Status); | |
Status = gBS->LocateProtocol ( | |
&gEfiCpuArchProtocolGuid, | |
NULL, | |
(VOID **)&Cpu | |
); | |
ASSERT_EFI_ERROR (Status); | |
// | |
// Check for memory node and add the memory spaces except the lowest one | |
// | |
for (FindNodeStatus = FdtClient->FindMemoryNodeReg ( | |
FdtClient, | |
&Node, | |
(CONST VOID **)&Reg, | |
&AddressCells, | |
&SizeCells, | |
&RegSize | |
); | |
!EFI_ERROR (FindNodeStatus); | |
FindNodeStatus = FdtClient->FindNextMemoryNodeReg ( | |
FdtClient, | |
Node, | |
&Node, | |
(CONST VOID **)&Reg, | |
&AddressCells, | |
&SizeCells, | |
&RegSize | |
)) | |
{ | |
ASSERT (AddressCells <= 2); | |
ASSERT (SizeCells <= 2); | |
while (RegSize > 0) { | |
CurBase = SwapBytes32 (*Reg++); | |
if (AddressCells > 1) { | |
CurBase = (CurBase << 32) | SwapBytes32 (*Reg++); | |
} | |
CurSize = SwapBytes32 (*Reg++); | |
if (SizeCells > 1) { | |
CurSize = (CurSize << 32) | SwapBytes32 (*Reg++); | |
} | |
RegSize -= (AddressCells + SizeCells) * sizeof (UINT32); | |
Status = gDS->GetMemorySpaceDescriptor (CurBase, &GcdDescriptor); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_WARN, | |
"%a: Region 0x%lx - 0x%lx not found in the GCD memory space map\n", | |
__func__, | |
CurBase, | |
CurBase + CurSize - 1 | |
)); | |
continue; | |
} | |
if (GcdDescriptor.GcdMemoryType == EfiGcdMemoryTypeNonExistent) { | |
Status = gDS->AddMemorySpace ( | |
EfiGcdMemoryTypeSystemMemory, | |
CurBase, | |
CurSize, | |
EFI_MEMORY_WB | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"%a: Failed to add System RAM @ 0x%lx - 0x%lx (%r)\n", | |
__func__, | |
CurBase, | |
CurBase + CurSize - 1, | |
Status | |
)); | |
continue; | |
} | |
Status = gDS->SetMemorySpaceAttributes ( | |
CurBase, | |
CurSize, | |
EFI_MEMORY_WB | |
); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_WARN, | |
"%a: gDS->SetMemorySpaceAttributes() failed on region 0x%lx - 0x%lx (%r)\n", | |
__func__, | |
CurBase, | |
CurBase + CurSize - 1, | |
Status | |
)); | |
} | |
// | |
// Due to the ambiguous nature of the RO/XP GCD memory space attributes, | |
// it is impossible to add a memory space with the XP attribute in a way | |
// that does not result in the XP attribute being set on *all* UEFI | |
// memory map entries that are carved from it, including code regions | |
// that require executable permissions. | |
// | |
// So instead, we never set the RO/XP attributes in the GCD memory space | |
// capabilities or attribute fields, and apply any protections directly | |
// on the page table mappings by going through the cpu arch protocol. | |
// | |
Attributes = EFI_MEMORY_WB; | |
if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) & | |
(1U << (UINT32)EfiConventionalMemory)) != 0) | |
{ | |
Attributes |= EFI_MEMORY_XP; | |
} | |
Status = Cpu->SetMemoryAttributes (Cpu, CurBase, CurSize, Attributes); | |
if (EFI_ERROR (Status)) { | |
DEBUG (( | |
DEBUG_ERROR, | |
"%a: Failed to set System RAM @ 0x%lx - 0x%lx attribute (%r)\n", | |
__func__, | |
CurBase, | |
CurBase + CurSize - 1, | |
Status | |
)); | |
} else { | |
DEBUG (( | |
DEBUG_INFO, | |
"%a: Add System RAM @ 0x%lx - 0x%lx\n", | |
__func__, | |
CurBase, | |
CurBase + CurSize - 1 | |
)); | |
} | |
} | |
} | |
} | |
return EFI_SUCCESS; | |
} |