2 * High memory node enumeration DXE driver for ARM Virtual Machines
4 * Copyright (c) 2015-2016, Linaro Ltd. All rights reserved.
6 * This program and the accompanying materials are licensed and made available
7 * under the terms and conditions of the BSD License which accompanies this
8 * distribution. The full text of the license may be found at
9 * http://opensource.org/licenses/bsd-license.php
11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
17 #include <Library/BaseLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/DxeServicesTableLib.h>
20 #include <Library/PcdLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
23 #include <Protocol/Cpu.h>
24 #include <Protocol/FdtClient.h>
28 InitializeHighMemDxe (
29 IN EFI_HANDLE ImageHandle
,
30 IN EFI_SYSTEM_TABLE
*SystemTable
33 FDT_CLIENT_PROTOCOL
*FdtClient
;
34 EFI_CPU_ARCH_PROTOCOL
*Cpu
;
35 EFI_STATUS Status
, FindNodeStatus
;
39 UINTN AddressCells
, SizeCells
;
43 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
45 Status
= gBS
->LocateProtocol (&gFdtClientProtocolGuid
, NULL
,
47 ASSERT_EFI_ERROR (Status
);
49 Status
= gBS
->LocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
,
51 ASSERT_EFI_ERROR (Status
);
54 // Check for memory node and add the memory spaces except the lowest one
56 for (FindNodeStatus
= FdtClient
->FindMemoryNodeReg (FdtClient
, &Node
,
57 (CONST VOID
**) &Reg
, &AddressCells
,
58 &SizeCells
, &RegSize
);
59 !EFI_ERROR (FindNodeStatus
);
60 FindNodeStatus
= FdtClient
->FindNextMemoryNodeReg (FdtClient
, Node
,
61 &Node
, (CONST VOID
**) &Reg
, &AddressCells
,
62 &SizeCells
, &RegSize
)) {
63 ASSERT (AddressCells
<= 2);
64 ASSERT (SizeCells
<= 2);
67 CurBase
= SwapBytes32 (*Reg
++);
68 if (AddressCells
> 1) {
69 CurBase
= (CurBase
<< 32) | SwapBytes32 (*Reg
++);
71 CurSize
= SwapBytes32 (*Reg
++);
73 CurSize
= (CurSize
<< 32) | SwapBytes32 (*Reg
++);
75 RegSize
-= (AddressCells
+ SizeCells
) * sizeof (UINT32
);
77 Status
= gDS
->GetMemorySpaceDescriptor (CurBase
, &GcdDescriptor
);
78 if (EFI_ERROR (Status
)) {
80 "%a: Region 0x%lx - 0x%lx not found in the GCD memory space map\n",
81 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1));
84 if (GcdDescriptor
.GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
85 Status
= gDS
->AddMemorySpace (EfiGcdMemoryTypeSystemMemory
, CurBase
,
86 CurSize
, EFI_MEMORY_WB
);
88 if (EFI_ERROR (Status
)) {
90 "%a: Failed to add System RAM @ 0x%lx - 0x%lx (%r)\n",
91 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1, Status
));
95 Status
= gDS
->SetMemorySpaceAttributes (CurBase
, CurSize
,
97 if (EFI_ERROR (Status
)) {
99 "%a: gDS->SetMemorySpaceAttributes() failed on region 0x%lx - 0x%lx (%r)\n",
100 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1, Status
));
104 // Due to the ambiguous nature of the RO/XP GCD memory space attributes,
105 // it is impossible to add a memory space with the XP attribute in a way
106 // that does not result in the XP attribute being set on *all* UEFI
107 // memory map entries that are carved from it, including code regions
108 // that require executable permissions.
110 // So instead, we never set the RO/XP attributes in the GCD memory space
111 // capabilities or attribute fields, and apply any protections directly
112 // on the page table mappings by going through the cpu arch protocol.
114 Attributes
= EFI_MEMORY_WB
;
115 if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy
) &
116 (1U << (UINT32
)EfiConventionalMemory
)) != 0) {
117 Attributes
|= EFI_MEMORY_XP
;
120 Status
= Cpu
->SetMemoryAttributes (Cpu
, CurBase
, CurSize
, Attributes
);
122 if (EFI_ERROR (Status
)) {
124 "%a: Failed to set System RAM @ 0x%lx - 0x%lx attribute (%r)\n",
125 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1, Status
));
127 DEBUG ((EFI_D_INFO
, "%a: Add System RAM @ 0x%lx - 0x%lx\n",
128 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1));