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
;
44 Status
= gBS
->LocateProtocol (&gFdtClientProtocolGuid
, NULL
,
46 ASSERT_EFI_ERROR (Status
);
48 Status
= gBS
->LocateProtocol (&gEfiCpuArchProtocolGuid
, NULL
,
50 ASSERT_EFI_ERROR (Status
);
53 // Check for memory node and add the memory spaces except the lowest one
55 for (FindNodeStatus
= FdtClient
->FindMemoryNodeReg (FdtClient
, &Node
,
56 (CONST VOID
**) &Reg
, &AddressCells
,
57 &SizeCells
, &RegSize
);
58 !EFI_ERROR (FindNodeStatus
);
59 FindNodeStatus
= FdtClient
->FindNextMemoryNodeReg (FdtClient
, Node
,
60 &Node
, (CONST VOID
**) &Reg
, &AddressCells
,
61 &SizeCells
, &RegSize
)) {
62 ASSERT (AddressCells
<= 2);
63 ASSERT (SizeCells
<= 2);
66 CurBase
= SwapBytes32 (*Reg
++);
67 if (AddressCells
> 1) {
68 CurBase
= (CurBase
<< 32) | SwapBytes32 (*Reg
++);
70 CurSize
= SwapBytes32 (*Reg
++);
72 CurSize
= (CurSize
<< 32) | SwapBytes32 (*Reg
++);
74 RegSize
-= (AddressCells
+ SizeCells
) * sizeof (UINT32
);
76 if (PcdGet64 (PcdSystemMemoryBase
) != CurBase
) {
77 Status
= gDS
->AddMemorySpace (EfiGcdMemoryTypeSystemMemory
, CurBase
,
78 CurSize
, EFI_MEMORY_WB
);
80 if (EFI_ERROR (Status
)) {
82 "%a: Failed to add System RAM @ 0x%lx - 0x%lx (%r)\n",
83 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1, Status
));
87 Status
= gDS
->SetMemorySpaceAttributes (CurBase
, CurSize
,
89 if (EFI_ERROR (Status
)) {
91 "%a: gDS->SetMemorySpaceAttributes() failed on region 0x%lx - 0x%lx (%r)\n",
92 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1, Status
));
96 // Due to the ambiguous nature of the RO/XP GCD memory space attributes,
97 // it is impossible to add a memory space with the XP attribute in a way
98 // that does not result in the XP attribute being set on *all* UEFI
99 // memory map entries that are carved from it, including code regions
100 // that require executable permissions.
102 // So instead, we never set the RO/XP attributes in the GCD memory space
103 // capabilities or attribute fields, and apply any protections directly
104 // on the page table mappings by going through the cpu arch protocol.
106 Attributes
= EFI_MEMORY_WB
;
107 if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy
) &
108 (1U << (UINT32
)EfiConventionalMemory
)) != 0) {
109 Attributes
|= EFI_MEMORY_XP
;
112 Status
= Cpu
->SetMemoryAttributes (Cpu
, CurBase
, CurSize
, Attributes
);
114 if (EFI_ERROR (Status
)) {
116 "%a: Failed to set System RAM @ 0x%lx - 0x%lx attribute (%r)\n",
117 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1, Status
));
119 DEBUG ((EFI_D_INFO
, "%a: Add System RAM @ 0x%lx - 0x%lx\n",
120 __FUNCTION__
, CurBase
, CurBase
+ CurSize
- 1));