ArmVirtPkg/HighMemDxe: use CPU arch protocol to apply memprotect policy
[mirror_edk2.git] / ArmVirtPkg / HighMemDxe / HighMemDxe.c
1 /** @file
2 * High memory node enumeration DXE driver for ARM Virtual Machines
3 *
4 * Copyright (c) 2015-2016, Linaro Ltd. All rights reserved.
5 *
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
10 *
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
13 * IMPLIED.
14 *
15 **/
16
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>
22
23 #include <Protocol/Cpu.h>
24 #include <Protocol/FdtClient.h>
25
26 EFI_STATUS
27 EFIAPI
28 InitializeHighMemDxe (
29 IN EFI_HANDLE ImageHandle,
30 IN EFI_SYSTEM_TABLE *SystemTable
31 )
32 {
33 FDT_CLIENT_PROTOCOL *FdtClient;
34 EFI_CPU_ARCH_PROTOCOL *Cpu;
35 EFI_STATUS Status, FindNodeStatus;
36 INT32 Node;
37 CONST UINT32 *Reg;
38 UINT32 RegSize;
39 UINTN AddressCells, SizeCells;
40 UINT64 CurBase;
41 UINT64 CurSize;
42 UINT64 Attributes;
43
44 Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
45 (VOID **)&FdtClient);
46 ASSERT_EFI_ERROR (Status);
47
48 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL,
49 (VOID **)&Cpu);
50 ASSERT_EFI_ERROR (Status);
51
52 //
53 // Check for memory node and add the memory spaces except the lowest one
54 //
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);
64
65 while (RegSize > 0) {
66 CurBase = SwapBytes32 (*Reg++);
67 if (AddressCells > 1) {
68 CurBase = (CurBase << 32) | SwapBytes32 (*Reg++);
69 }
70 CurSize = SwapBytes32 (*Reg++);
71 if (SizeCells > 1) {
72 CurSize = (CurSize << 32) | SwapBytes32 (*Reg++);
73 }
74 RegSize -= (AddressCells + SizeCells) * sizeof (UINT32);
75
76 if (PcdGet64 (PcdSystemMemoryBase) != CurBase) {
77 Status = gDS->AddMemorySpace (EfiGcdMemoryTypeSystemMemory, CurBase,
78 CurSize, EFI_MEMORY_WB);
79
80 if (EFI_ERROR (Status)) {
81 DEBUG ((EFI_D_ERROR,
82 "%a: Failed to add System RAM @ 0x%lx - 0x%lx (%r)\n",
83 __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));
84 continue;
85 }
86
87 Status = gDS->SetMemorySpaceAttributes (CurBase, CurSize,
88 EFI_MEMORY_WB);
89 if (EFI_ERROR (Status)) {
90 DEBUG ((DEBUG_WARN,
91 "%a: gDS->SetMemorySpaceAttributes() failed on region 0x%lx - 0x%lx (%r)\n",
92 __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));
93 }
94
95 //
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.
101 //
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.
105 //
106 Attributes = EFI_MEMORY_WB;
107 if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) &
108 (1U << (UINT32)EfiConventionalMemory)) != 0) {
109 Attributes |= EFI_MEMORY_XP;
110 }
111
112 Status = Cpu->SetMemoryAttributes (Cpu, CurBase, CurSize, Attributes);
113
114 if (EFI_ERROR (Status)) {
115 DEBUG ((EFI_D_ERROR,
116 "%a: Failed to set System RAM @ 0x%lx - 0x%lx attribute (%r)\n",
117 __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));
118 } else {
119 DEBUG ((EFI_D_INFO, "%a: Add System RAM @ 0x%lx - 0x%lx\n",
120 __FUNCTION__, CurBase, CurBase + CurSize - 1));
121 }
122 }
123 }
124 }
125
126 return EFI_SUCCESS;
127 }