]>
Commit | Line | Data |
---|---|---|
68312710 SZ |
1 | /** @file\r |
2 | * High memory node enumeration DXE driver for ARM Virtual Machines\r | |
3 | *\r | |
490acf89 | 4 | * Copyright (c) 2015-2016, Linaro Ltd. All rights reserved.\r |
68312710 SZ |
5 | *\r |
6 | * This program and the accompanying materials are licensed and made available\r | |
7 | * under the terms and conditions of the BSD License which accompanies this\r | |
8 | * distribution. The full text of the license may be found at\r | |
9 | * http://opensource.org/licenses/bsd-license.php\r | |
10 | *\r | |
11 | * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
12 | * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR\r | |
13 | * IMPLIED.\r | |
14 | *\r | |
15 | **/\r | |
16 | \r | |
17 | #include <Library/BaseLib.h>\r | |
68312710 | 18 | #include <Library/DebugLib.h>\r |
68312710 | 19 | #include <Library/DxeServicesTableLib.h>\r |
490acf89 AB |
20 | #include <Library/PcdLib.h>\r |
21 | #include <Library/UefiBootServicesTableLib.h>\r | |
22 | \r | |
60bd1e12 | 23 | #include <Protocol/Cpu.h>\r |
490acf89 | 24 | #include <Protocol/FdtClient.h>\r |
68312710 SZ |
25 | \r |
26 | EFI_STATUS\r | |
27 | EFIAPI\r | |
28 | InitializeHighMemDxe (\r | |
29 | IN EFI_HANDLE ImageHandle,\r | |
30 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
31 | )\r | |
32 | {\r | |
5d5a1902 AB |
33 | FDT_CLIENT_PROTOCOL *FdtClient;\r |
34 | EFI_CPU_ARCH_PROTOCOL *Cpu;\r | |
35 | EFI_STATUS Status, FindNodeStatus;\r | |
36 | INT32 Node;\r | |
37 | CONST UINT32 *Reg;\r | |
38 | UINT32 RegSize;\r | |
39 | UINTN AddressCells, SizeCells;\r | |
40 | UINT64 CurBase;\r | |
41 | UINT64 CurSize;\r | |
42 | UINT64 Attributes;\r | |
43 | EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r | |
68312710 | 44 | \r |
490acf89 AB |
45 | Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r |
46 | (VOID **)&FdtClient);\r | |
47 | ASSERT_EFI_ERROR (Status);\r | |
68312710 | 48 | \r |
60bd1e12 AB |
49 | Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL,\r |
50 | (VOID **)&Cpu);\r | |
51 | ASSERT_EFI_ERROR (Status);\r | |
52 | \r | |
68312710 | 53 | //\r |
490acf89 | 54 | // Check for memory node and add the memory spaces except the lowest one\r |
68312710 | 55 | //\r |
490acf89 AB |
56 | for (FindNodeStatus = FdtClient->FindMemoryNodeReg (FdtClient, &Node,\r |
57 | (CONST VOID **) &Reg, &AddressCells,\r | |
58 | &SizeCells, &RegSize);\r | |
59 | !EFI_ERROR (FindNodeStatus);\r | |
60 | FindNodeStatus = FdtClient->FindNextMemoryNodeReg (FdtClient, Node,\r | |
61 | &Node, (CONST VOID **) &Reg, &AddressCells,\r | |
62 | &SizeCells, &RegSize)) {\r | |
63 | ASSERT (AddressCells <= 2);\r | |
64 | ASSERT (SizeCells <= 2);\r | |
68312710 | 65 | \r |
490acf89 AB |
66 | while (RegSize > 0) {\r |
67 | CurBase = SwapBytes32 (*Reg++);\r | |
68 | if (AddressCells > 1) {\r | |
69 | CurBase = (CurBase << 32) | SwapBytes32 (*Reg++);\r | |
70 | }\r | |
71 | CurSize = SwapBytes32 (*Reg++);\r | |
72 | if (SizeCells > 1) {\r | |
73 | CurSize = (CurSize << 32) | SwapBytes32 (*Reg++);\r | |
74 | }\r | |
75 | RegSize -= (AddressCells + SizeCells) * sizeof (UINT32);\r | |
68312710 | 76 | \r |
5d5a1902 AB |
77 | Status = gDS->GetMemorySpaceDescriptor (CurBase, &GcdDescriptor);\r |
78 | if (EFI_ERROR (Status)) {\r | |
79 | DEBUG ((DEBUG_WARN,\r | |
80 | "%a: Region 0x%lx - 0x%lx not found in the GCD memory space map\n",\r | |
81 | __FUNCTION__, CurBase, CurBase + CurSize - 1));\r | |
82 | continue;\r | |
83 | }\r | |
84 | if (GcdDescriptor.GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r | |
490acf89 AB |
85 | Status = gDS->AddMemorySpace (EfiGcdMemoryTypeSystemMemory, CurBase,\r |
86 | CurSize, EFI_MEMORY_WB);\r | |
68312710 | 87 | \r |
490acf89 AB |
88 | if (EFI_ERROR (Status)) {\r |
89 | DEBUG ((EFI_D_ERROR,\r | |
90 | "%a: Failed to add System RAM @ 0x%lx - 0x%lx (%r)\n",\r | |
91 | __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));\r | |
92 | continue;\r | |
93 | }\r | |
68312710 | 94 | \r |
60bd1e12 AB |
95 | Status = gDS->SetMemorySpaceAttributes (CurBase, CurSize,\r |
96 | EFI_MEMORY_WB);\r | |
97 | if (EFI_ERROR (Status)) {\r | |
98 | DEBUG ((DEBUG_WARN,\r | |
99 | "%a: gDS->SetMemorySpaceAttributes() failed on region 0x%lx - 0x%lx (%r)\n",\r | |
100 | __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));\r | |
101 | }\r | |
102 | \r | |
103 | //\r | |
104 | // Due to the ambiguous nature of the RO/XP GCD memory space attributes,\r | |
105 | // it is impossible to add a memory space with the XP attribute in a way\r | |
106 | // that does not result in the XP attribute being set on *all* UEFI\r | |
107 | // memory map entries that are carved from it, including code regions\r | |
108 | // that require executable permissions.\r | |
413edd47 | 109 | //\r |
60bd1e12 AB |
110 | // So instead, we never set the RO/XP attributes in the GCD memory space\r |
111 | // capabilities or attribute fields, and apply any protections directly\r | |
112 | // on the page table mappings by going through the cpu arch protocol.\r | |
413edd47 AB |
113 | //\r |
114 | Attributes = EFI_MEMORY_WB;\r | |
115 | if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) &\r | |
116 | (1U << (UINT32)EfiConventionalMemory)) != 0) {\r | |
117 | Attributes |= EFI_MEMORY_XP;\r | |
118 | }\r | |
119 | \r | |
60bd1e12 | 120 | Status = Cpu->SetMemoryAttributes (Cpu, CurBase, CurSize, Attributes);\r |
68312710 | 121 | \r |
490acf89 AB |
122 | if (EFI_ERROR (Status)) {\r |
123 | DEBUG ((EFI_D_ERROR,\r | |
124 | "%a: Failed to set System RAM @ 0x%lx - 0x%lx attribute (%r)\n",\r | |
125 | __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));\r | |
126 | } else {\r | |
127 | DEBUG ((EFI_D_INFO, "%a: Add System RAM @ 0x%lx - 0x%lx\n",\r | |
128 | __FUNCTION__, CurBase, CurBase + CurSize - 1));\r | |
68312710 SZ |
129 | }\r |
130 | }\r | |
131 | }\r | |
132 | }\r | |
133 | \r | |
134 | return EFI_SUCCESS;\r | |
135 | }\r |