]> git.proxmox.com Git - mirror_edk2.git/blob - ArmVirtPkg/HighMemDxe/HighMemDxe.c
ArmVirtPkg: Replace BSD License with BSD+Patent License
[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 * SPDX-License-Identifier: BSD-2-Clause-Patent
7 *
8 **/
9
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>
15
16 #include <Protocol/Cpu.h>
17 #include <Protocol/FdtClient.h>
18
19 EFI_STATUS
20 EFIAPI
21 InitializeHighMemDxe (
22 IN EFI_HANDLE ImageHandle,
23 IN EFI_SYSTEM_TABLE *SystemTable
24 )
25 {
26 FDT_CLIENT_PROTOCOL *FdtClient;
27 EFI_CPU_ARCH_PROTOCOL *Cpu;
28 EFI_STATUS Status, FindNodeStatus;
29 INT32 Node;
30 CONST UINT32 *Reg;
31 UINT32 RegSize;
32 UINTN AddressCells, SizeCells;
33 UINT64 CurBase;
34 UINT64 CurSize;
35 UINT64 Attributes;
36 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
37
38 Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,
39 (VOID **)&FdtClient);
40 ASSERT_EFI_ERROR (Status);
41
42 Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL,
43 (VOID **)&Cpu);
44 ASSERT_EFI_ERROR (Status);
45
46 //
47 // Check for memory node and add the memory spaces except the lowest one
48 //
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);
58
59 while (RegSize > 0) {
60 CurBase = SwapBytes32 (*Reg++);
61 if (AddressCells > 1) {
62 CurBase = (CurBase << 32) | SwapBytes32 (*Reg++);
63 }
64 CurSize = SwapBytes32 (*Reg++);
65 if (SizeCells > 1) {
66 CurSize = (CurSize << 32) | SwapBytes32 (*Reg++);
67 }
68 RegSize -= (AddressCells + SizeCells) * sizeof (UINT32);
69
70 Status = gDS->GetMemorySpaceDescriptor (CurBase, &GcdDescriptor);
71 if (EFI_ERROR (Status)) {
72 DEBUG ((DEBUG_WARN,
73 "%a: Region 0x%lx - 0x%lx not found in the GCD memory space map\n",
74 __FUNCTION__, CurBase, CurBase + CurSize - 1));
75 continue;
76 }
77 if (GcdDescriptor.GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
78 Status = gDS->AddMemorySpace (EfiGcdMemoryTypeSystemMemory, CurBase,
79 CurSize, EFI_MEMORY_WB);
80
81 if (EFI_ERROR (Status)) {
82 DEBUG ((EFI_D_ERROR,
83 "%a: Failed to add System RAM @ 0x%lx - 0x%lx (%r)\n",
84 __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));
85 continue;
86 }
87
88 Status = gDS->SetMemorySpaceAttributes (CurBase, CurSize,
89 EFI_MEMORY_WB);
90 if (EFI_ERROR (Status)) {
91 DEBUG ((DEBUG_WARN,
92 "%a: gDS->SetMemorySpaceAttributes() failed on region 0x%lx - 0x%lx (%r)\n",
93 __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));
94 }
95
96 //
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.
102 //
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.
106 //
107 Attributes = EFI_MEMORY_WB;
108 if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) &
109 (1U << (UINT32)EfiConventionalMemory)) != 0) {
110 Attributes |= EFI_MEMORY_XP;
111 }
112
113 Status = Cpu->SetMemoryAttributes (Cpu, CurBase, CurSize, Attributes);
114
115 if (EFI_ERROR (Status)) {
116 DEBUG ((EFI_D_ERROR,
117 "%a: Failed to set System RAM @ 0x%lx - 0x%lx attribute (%r)\n",
118 __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));
119 } else {
120 DEBUG ((EFI_D_INFO, "%a: Add System RAM @ 0x%lx - 0x%lx\n",
121 __FUNCTION__, CurBase, CurBase + CurSize - 1));
122 }
123 }
124 }
125 }
126
127 return EFI_SUCCESS;
128 }