]>
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 | 5 | *\r |
9792fb0e | 6 | * SPDX-License-Identifier: BSD-2-Clause-Patent\r |
68312710 SZ |
7 | *\r |
8 | **/\r | |
9 | \r | |
10 | #include <Library/BaseLib.h>\r | |
68312710 | 11 | #include <Library/DebugLib.h>\r |
68312710 | 12 | #include <Library/DxeServicesTableLib.h>\r |
490acf89 AB |
13 | #include <Library/PcdLib.h>\r |
14 | #include <Library/UefiBootServicesTableLib.h>\r | |
15 | \r | |
60bd1e12 | 16 | #include <Protocol/Cpu.h>\r |
490acf89 | 17 | #include <Protocol/FdtClient.h>\r |
68312710 SZ |
18 | \r |
19 | EFI_STATUS\r | |
20 | EFIAPI\r | |
21 | InitializeHighMemDxe (\r | |
22 | IN EFI_HANDLE ImageHandle,\r | |
23 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
24 | )\r | |
25 | {\r | |
5d5a1902 AB |
26 | FDT_CLIENT_PROTOCOL *FdtClient;\r |
27 | EFI_CPU_ARCH_PROTOCOL *Cpu;\r | |
28 | EFI_STATUS Status, FindNodeStatus;\r | |
29 | INT32 Node;\r | |
30 | CONST UINT32 *Reg;\r | |
31 | UINT32 RegSize;\r | |
32 | UINTN AddressCells, SizeCells;\r | |
33 | UINT64 CurBase;\r | |
34 | UINT64 CurSize;\r | |
35 | UINT64 Attributes;\r | |
36 | EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r | |
68312710 | 37 | \r |
490acf89 AB |
38 | Status = gBS->LocateProtocol (&gFdtClientProtocolGuid, NULL,\r |
39 | (VOID **)&FdtClient);\r | |
40 | ASSERT_EFI_ERROR (Status);\r | |
68312710 | 41 | \r |
60bd1e12 AB |
42 | Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL,\r |
43 | (VOID **)&Cpu);\r | |
44 | ASSERT_EFI_ERROR (Status);\r | |
45 | \r | |
68312710 | 46 | //\r |
490acf89 | 47 | // Check for memory node and add the memory spaces except the lowest one\r |
68312710 | 48 | //\r |
490acf89 AB |
49 | for (FindNodeStatus = FdtClient->FindMemoryNodeReg (FdtClient, &Node,\r |
50 | (CONST VOID **) &Reg, &AddressCells,\r | |
51 | &SizeCells, &RegSize);\r | |
52 | !EFI_ERROR (FindNodeStatus);\r | |
53 | FindNodeStatus = FdtClient->FindNextMemoryNodeReg (FdtClient, Node,\r | |
54 | &Node, (CONST VOID **) &Reg, &AddressCells,\r | |
55 | &SizeCells, &RegSize)) {\r | |
56 | ASSERT (AddressCells <= 2);\r | |
57 | ASSERT (SizeCells <= 2);\r | |
68312710 | 58 | \r |
490acf89 AB |
59 | while (RegSize > 0) {\r |
60 | CurBase = SwapBytes32 (*Reg++);\r | |
61 | if (AddressCells > 1) {\r | |
62 | CurBase = (CurBase << 32) | SwapBytes32 (*Reg++);\r | |
63 | }\r | |
64 | CurSize = SwapBytes32 (*Reg++);\r | |
65 | if (SizeCells > 1) {\r | |
66 | CurSize = (CurSize << 32) | SwapBytes32 (*Reg++);\r | |
67 | }\r | |
68 | RegSize -= (AddressCells + SizeCells) * sizeof (UINT32);\r | |
68312710 | 69 | \r |
5d5a1902 AB |
70 | Status = gDS->GetMemorySpaceDescriptor (CurBase, &GcdDescriptor);\r |
71 | if (EFI_ERROR (Status)) {\r | |
72 | DEBUG ((DEBUG_WARN,\r | |
73 | "%a: Region 0x%lx - 0x%lx not found in the GCD memory space map\n",\r | |
74 | __FUNCTION__, CurBase, CurBase + CurSize - 1));\r | |
75 | continue;\r | |
76 | }\r | |
77 | if (GcdDescriptor.GcdMemoryType == EfiGcdMemoryTypeNonExistent) {\r | |
490acf89 AB |
78 | Status = gDS->AddMemorySpace (EfiGcdMemoryTypeSystemMemory, CurBase,\r |
79 | CurSize, EFI_MEMORY_WB);\r | |
68312710 | 80 | \r |
490acf89 AB |
81 | if (EFI_ERROR (Status)) {\r |
82 | DEBUG ((EFI_D_ERROR,\r | |
83 | "%a: Failed to add System RAM @ 0x%lx - 0x%lx (%r)\n",\r | |
84 | __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));\r | |
85 | continue;\r | |
86 | }\r | |
68312710 | 87 | \r |
60bd1e12 AB |
88 | Status = gDS->SetMemorySpaceAttributes (CurBase, CurSize,\r |
89 | EFI_MEMORY_WB);\r | |
90 | if (EFI_ERROR (Status)) {\r | |
91 | DEBUG ((DEBUG_WARN,\r | |
92 | "%a: gDS->SetMemorySpaceAttributes() failed on region 0x%lx - 0x%lx (%r)\n",\r | |
93 | __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));\r | |
94 | }\r | |
95 | \r | |
96 | //\r | |
97 | // Due to the ambiguous nature of the RO/XP GCD memory space attributes,\r | |
98 | // it is impossible to add a memory space with the XP attribute in a way\r | |
99 | // that does not result in the XP attribute being set on *all* UEFI\r | |
100 | // memory map entries that are carved from it, including code regions\r | |
101 | // that require executable permissions.\r | |
413edd47 | 102 | //\r |
60bd1e12 AB |
103 | // So instead, we never set the RO/XP attributes in the GCD memory space\r |
104 | // capabilities or attribute fields, and apply any protections directly\r | |
105 | // on the page table mappings by going through the cpu arch protocol.\r | |
413edd47 AB |
106 | //\r |
107 | Attributes = EFI_MEMORY_WB;\r | |
108 | if ((PcdGet64 (PcdDxeNxMemoryProtectionPolicy) &\r | |
109 | (1U << (UINT32)EfiConventionalMemory)) != 0) {\r | |
110 | Attributes |= EFI_MEMORY_XP;\r | |
111 | }\r | |
112 | \r | |
60bd1e12 | 113 | Status = Cpu->SetMemoryAttributes (Cpu, CurBase, CurSize, Attributes);\r |
68312710 | 114 | \r |
490acf89 AB |
115 | if (EFI_ERROR (Status)) {\r |
116 | DEBUG ((EFI_D_ERROR,\r | |
117 | "%a: Failed to set System RAM @ 0x%lx - 0x%lx attribute (%r)\n",\r | |
118 | __FUNCTION__, CurBase, CurBase + CurSize - 1, Status));\r | |
119 | } else {\r | |
120 | DEBUG ((EFI_D_INFO, "%a: Add System RAM @ 0x%lx - 0x%lx\n",\r | |
121 | __FUNCTION__, CurBase, CurBase + CurSize - 1));\r | |
68312710 SZ |
122 | }\r |
123 | }\r | |
124 | }\r | |
125 | }\r | |
126 | \r | |
127 | return EFI_SUCCESS;\r | |
128 | }\r |