2 * High memory node enumeration DXE driver for ARM and RISC-V
5 * Copyright (c) 2015-2016, Linaro Ltd. All rights reserved.
7 * SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Library/BaseLib.h>
12 #include <Library/DebugLib.h>
13 #include <Library/DxeServicesTableLib.h>
14 #include <Library/PcdLib.h>
15 #include <Library/UefiBootServicesTableLib.h>
17 #include <Protocol/Cpu.h>
18 #include <Protocol/FdtClient.h>
22 InitializeHighMemDxe (
23 IN EFI_HANDLE ImageHandle
,
24 IN EFI_SYSTEM_TABLE
*SystemTable
27 FDT_CLIENT_PROTOCOL
*FdtClient
;
28 EFI_CPU_ARCH_PROTOCOL
*Cpu
;
29 EFI_STATUS Status
, FindNodeStatus
;
33 UINTN AddressCells
, SizeCells
;
37 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
39 Status
= gBS
->LocateProtocol (&gFdtClientProtocolGuid
, NULL
,
41 ASSERT_EFI_ERROR (Status
);
43 Status
= gBS
->LocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
,
45 ASSERT_EFI_ERROR (Status
);
48 // Check for memory node and add the memory spaces except the lowest one
50 for (FindNodeStatus
= FdtClient
->FindMemoryNodeReg (FdtClient
, &Node
,
51 (CONST VOID
**) &Reg
, &AddressCells
,
52 &SizeCells
, &RegSize
);
53 !EFI_ERROR (FindNodeStatus
);
54 FindNodeStatus
= FdtClient
->FindNextMemoryNodeReg (FdtClient
, Node
,
55 &Node
, (CONST VOID
**) &Reg
, &AddressCells
,
56 &SizeCells
, &RegSize
)) {
57 ASSERT (AddressCells
<= 2);
58 ASSERT (SizeCells
<= 2);
61 CurBase
= SwapBytes32 (*Reg
++);
62 if (AddressCells
> 1) {
63 CurBase
= (CurBase
<< 32) | SwapBytes32 (*Reg
++);
65 CurSize
= SwapBytes32 (*Reg
++);
67 CurSize
= (CurSize
<< 32) | SwapBytes32 (*Reg
++);
69 RegSize
-= (AddressCells
+ SizeCells
) * sizeof (UINT32
);
71 Status
= gDS
->GetMemorySpaceDescriptor (CurBase
, &GcdDescriptor
);
72 if (EFI_ERROR (Status
)) {
74 "%a: Region 0x%lx - 0x%lx not found in the GCD memory space map\n",
75 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1));
78 if (GcdDescriptor
.GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
79 Status
= gDS
->AddMemorySpace (EfiGcdMemoryTypeSystemMemory
, CurBase
,
80 CurSize
, EFI_MEMORY_WB
);
82 if (EFI_ERROR (Status
)) {
84 "%a: Failed to add System RAM @ 0x%lx - 0x%lx (%r)\n",
85 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1, Status
));
89 Status
= gDS
->SetMemorySpaceAttributes (CurBase
, CurSize
,
91 if (EFI_ERROR (Status
)) {
93 "%a: gDS->SetMemorySpaceAttributes() failed on region 0x%lx - 0x%lx (%r)\n",
94 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1, Status
));
98 // Due to the ambiguous nature of the RO/XP GCD memory space attributes,
99 // it is impossible to add a memory space with the XP attribute in a way
100 // that does not result in the XP attribute being set on *all* UEFI
101 // memory map entries that are carved from it, including code regions
102 // that require executable permissions.
104 // So instead, we never set the RO/XP attributes in the GCD memory space
105 // capabilities or attribute fields, and apply any protections directly
106 // on the page table mappings by going through the cpu arch protocol.
108 Attributes
= EFI_MEMORY_WB
;
109 if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy
) &
110 (1U << (UINT32
)EfiConventionalMemory
)) != 0) {
111 Attributes
|= EFI_MEMORY_XP
;
114 Status
= Cpu
->SetMemoryAttributes (Cpu
, CurBase
, CurSize
, Attributes
);
116 if (EFI_ERROR (Status
)) {
118 "%a: Failed to set System RAM @ 0x%lx - 0x%lx attribute (%r)\n",
119 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1, Status
));
121 DEBUG ((DEBUG_INFO
, "%a: Add System RAM @ 0x%lx - 0x%lx\n",
122 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1));