2 * High memory node enumeration DXE driver for ARM Virtual Machines
4 * Copyright (c) 2015-2016, Linaro Ltd. All rights reserved.
6 * SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseLib.h>
11 #include <Library/DebugLib.h>
12 #include <Library/DxeServicesTableLib.h>
13 #include <Library/PcdLib.h>
14 #include <Library/UefiBootServicesTableLib.h>
16 #include <Protocol/Cpu.h>
17 #include <Protocol/FdtClient.h>
21 InitializeHighMemDxe (
22 IN EFI_HANDLE ImageHandle
,
23 IN EFI_SYSTEM_TABLE
*SystemTable
26 FDT_CLIENT_PROTOCOL
*FdtClient
;
27 EFI_CPU_ARCH_PROTOCOL
*Cpu
;
28 EFI_STATUS Status
, FindNodeStatus
;
32 UINTN AddressCells
, SizeCells
;
36 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
38 Status
= gBS
->LocateProtocol (&gFdtClientProtocolGuid
, NULL
,
40 ASSERT_EFI_ERROR (Status
);
42 Status
= gBS
->LocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
,
44 ASSERT_EFI_ERROR (Status
);
47 // Check for memory node and add the memory spaces except the lowest one
49 for (FindNodeStatus
= FdtClient
->FindMemoryNodeReg (FdtClient
, &Node
,
50 (CONST VOID
**) &Reg
, &AddressCells
,
51 &SizeCells
, &RegSize
);
52 !EFI_ERROR (FindNodeStatus
);
53 FindNodeStatus
= FdtClient
->FindNextMemoryNodeReg (FdtClient
, Node
,
54 &Node
, (CONST VOID
**) &Reg
, &AddressCells
,
55 &SizeCells
, &RegSize
)) {
56 ASSERT (AddressCells
<= 2);
57 ASSERT (SizeCells
<= 2);
60 CurBase
= SwapBytes32 (*Reg
++);
61 if (AddressCells
> 1) {
62 CurBase
= (CurBase
<< 32) | SwapBytes32 (*Reg
++);
64 CurSize
= SwapBytes32 (*Reg
++);
66 CurSize
= (CurSize
<< 32) | SwapBytes32 (*Reg
++);
68 RegSize
-= (AddressCells
+ SizeCells
) * sizeof (UINT32
);
70 Status
= gDS
->GetMemorySpaceDescriptor (CurBase
, &GcdDescriptor
);
71 if (EFI_ERROR (Status
)) {
73 "%a: Region 0x%lx - 0x%lx not found in the GCD memory space map\n",
74 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1));
77 if (GcdDescriptor
.GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
78 Status
= gDS
->AddMemorySpace (EfiGcdMemoryTypeSystemMemory
, CurBase
,
79 CurSize
, EFI_MEMORY_WB
);
81 if (EFI_ERROR (Status
)) {
83 "%a: Failed to add System RAM @ 0x%lx - 0x%lx (%r)\n",
84 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1, Status
));
88 Status
= gDS
->SetMemorySpaceAttributes (CurBase
, CurSize
,
90 if (EFI_ERROR (Status
)) {
92 "%a: gDS->SetMemorySpaceAttributes() failed on region 0x%lx - 0x%lx (%r)\n",
93 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1, Status
));
97 // Due to the ambiguous nature of the RO/XP GCD memory space attributes,
98 // it is impossible to add a memory space with the XP attribute in a way
99 // that does not result in the XP attribute being set on *all* UEFI
100 // memory map entries that are carved from it, including code regions
101 // that require executable permissions.
103 // So instead, we never set the RO/XP attributes in the GCD memory space
104 // capabilities or attribute fields, and apply any protections directly
105 // on the page table mappings by going through the cpu arch protocol.
107 Attributes
= EFI_MEMORY_WB
;
108 if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy
) &
109 (1U << (UINT32
)EfiConventionalMemory
)) != 0) {
110 Attributes
|= EFI_MEMORY_XP
;
113 Status
= Cpu
->SetMemoryAttributes (Cpu
, CurBase
, CurSize
, Attributes
);
115 if (EFI_ERROR (Status
)) {
117 "%a: Failed to set System RAM @ 0x%lx - 0x%lx attribute (%r)\n",
118 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1, Status
));
120 DEBUG ((EFI_D_INFO
, "%a: Add System RAM @ 0x%lx - 0x%lx\n",
121 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1));