]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Misc / MemoryAttributesTable.c
CommitLineData
98c4b005
JY
1/** @file\r
2 UEFI MemoryAttributesTable support\r
3\r
d1102dba 4Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
98c4b005
JY
6\r
7**/\r
8\r
9#include <PiDxe.h>\r
10#include <Library/BaseLib.h>\r
11#include <Library/BaseMemoryLib.h>\r
12#include <Library/MemoryAllocationLib.h>\r
13#include <Library/UefiBootServicesTableLib.h>\r
14#include <Library/DxeServicesTableLib.h>\r
15#include <Library/DebugLib.h>\r
16#include <Library/UefiLib.h>\r
17\r
18#include <Guid/EventGroup.h>\r
19\r
20#include <Guid/MemoryAttributesTable.h>\r
21#include <Guid/PropertiesTable.h>\r
22\r
23#include "DxeMain.h"\r
24\r
25/**\r
26 This function for GetMemoryMap() with properties table capability.\r
27\r
28 It calls original GetMemoryMap() to get the original memory map information. Then\r
29 plus the additional memory map entries for PE Code/Data seperation.\r
30\r
31 @param MemoryMapSize A pointer to the size, in bytes, of the\r
32 MemoryMap buffer. On input, this is the size of\r
33 the buffer allocated by the caller. On output,\r
34 it is the size of the buffer returned by the\r
35 firmware if the buffer was large enough, or the\r
36 size of the buffer needed to contain the map if\r
37 the buffer was too small.\r
38 @param MemoryMap A pointer to the buffer in which firmware places\r
39 the current memory map.\r
40 @param MapKey A pointer to the location in which firmware\r
41 returns the key for the current memory map.\r
42 @param DescriptorSize A pointer to the location in which firmware\r
43 returns the size, in bytes, of an individual\r
44 EFI_MEMORY_DESCRIPTOR.\r
45 @param DescriptorVersion A pointer to the location in which firmware\r
46 returns the version number associated with the\r
47 EFI_MEMORY_DESCRIPTOR.\r
48\r
49 @retval EFI_SUCCESS The memory map was returned in the MemoryMap\r
50 buffer.\r
51 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current\r
52 buffer size needed to hold the memory map is\r
53 returned in MemoryMapSize.\r
54 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
55\r
56**/\r
57EFI_STATUS\r
58EFIAPI\r
0ab90add 59CoreGetMemoryMapWithSeparatedImageSection (\r
98c4b005
JY
60 IN OUT UINTN *MemoryMapSize,\r
61 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
62 OUT UINTN *MapKey,\r
63 OUT UINTN *DescriptorSize,\r
64 OUT UINT32 *DescriptorVersion\r
65 );\r
66\r
67extern EFI_PROPERTIES_TABLE mPropertiesTable;\r
74a88770
SZ
68EFI_MEMORY_ATTRIBUTES_TABLE *mMemoryAttributesTable = NULL;\r
69BOOLEAN mMemoryAttributesTableReadyToBoot = FALSE;\r
98c4b005 70\r
98c4b005
JY
71/**\r
72 Install MemoryAttributesTable.\r
73\r
98c4b005
JY
74**/\r
75VOID\r
98c4b005 76InstallMemoryAttributesTable (\r
74a88770 77 VOID\r
98c4b005
JY
78 )\r
79{\r
80 UINTN MemoryMapSize;\r
81 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
82 EFI_MEMORY_DESCRIPTOR *MemoryMapStart;\r
83 UINTN MapKey;\r
84 UINTN DescriptorSize;\r
85 UINT32 DescriptorVersion;\r
86 UINTN Index;\r
87 EFI_STATUS Status;\r
88 UINT32 RuntimeEntryCount;\r
89 EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;\r
90 EFI_MEMORY_DESCRIPTOR *MemoryAttributesEntry;\r
91\r
74a88770
SZ
92 if (gMemoryMapTerminated) {\r
93 //\r
94 // Directly return after MemoryMap terminated.\r
95 //\r
96 return;\r
97 }\r
98\r
98c4b005
JY
99 if ((mPropertiesTable.MemoryProtectionAttribute & EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {\r
100 DEBUG ((EFI_D_VERBOSE, "MemoryProtectionAttribute NON_EXECUTABLE_PE_DATA is not set, "));\r
d4731a98 101 DEBUG ((EFI_D_VERBOSE, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10));\r
98c4b005
JY
102 return ;\r
103 }\r
104\r
74a88770
SZ
105 if (mMemoryAttributesTable == NULL) {\r
106 //\r
107 // InstallConfigurationTable here to occupy one entry for MemoryAttributesTable\r
108 // before GetMemoryMap below, as InstallConfigurationTable may allocate runtime\r
109 // memory for the new entry.\r
110 //\r
111 Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID *) (UINTN) MAX_ADDRESS);\r
112 ASSERT_EFI_ERROR (Status);\r
113 }\r
114\r
98c4b005
JY
115 MemoryMapSize = 0;\r
116 MemoryMap = NULL;\r
0ab90add 117 Status = CoreGetMemoryMapWithSeparatedImageSection (\r
98c4b005
JY
118 &MemoryMapSize,\r
119 MemoryMap,\r
120 &MapKey,\r
121 &DescriptorSize,\r
122 &DescriptorVersion\r
123 );\r
124 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
125\r
126 do {\r
127 MemoryMap = AllocatePool (MemoryMapSize);\r
128 ASSERT (MemoryMap != NULL);\r
129\r
0ab90add 130 Status = CoreGetMemoryMapWithSeparatedImageSection (\r
98c4b005
JY
131 &MemoryMapSize,\r
132 MemoryMap,\r
133 &MapKey,\r
134 &DescriptorSize,\r
135 &DescriptorVersion\r
136 );\r
137 if (EFI_ERROR (Status)) {\r
138 FreePool (MemoryMap);\r
139 }\r
140 } while (Status == EFI_BUFFER_TOO_SMALL);\r
141\r
142 MemoryMapStart = MemoryMap;\r
143 RuntimeEntryCount = 0;\r
144 for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {\r
145 switch (MemoryMap->Type) {\r
146 case EfiRuntimeServicesCode:\r
147 case EfiRuntimeServicesData:\r
148 RuntimeEntryCount ++;\r
149 break;\r
150 }\r
151 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);\r
152 }\r
153\r
154 //\r
155 // Allocate MemoryAttributesTable\r
156 //\r
157 MemoryAttributesTable = AllocatePool (sizeof(EFI_MEMORY_ATTRIBUTES_TABLE) + DescriptorSize * RuntimeEntryCount);\r
158 ASSERT (MemoryAttributesTable != NULL);\r
159 MemoryAttributesTable->Version = EFI_MEMORY_ATTRIBUTES_TABLE_VERSION;\r
160 MemoryAttributesTable->NumberOfEntries = RuntimeEntryCount;\r
161 MemoryAttributesTable->DescriptorSize = (UINT32)DescriptorSize;\r
162 MemoryAttributesTable->Reserved = 0;\r
163 DEBUG ((EFI_D_VERBOSE, "MemoryAttributesTable:\n"));\r
164 DEBUG ((EFI_D_VERBOSE, " Version - 0x%08x\n", MemoryAttributesTable->Version));\r
165 DEBUG ((EFI_D_VERBOSE, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable->NumberOfEntries));\r
166 DEBUG ((EFI_D_VERBOSE, " DescriptorSize - 0x%08x\n", MemoryAttributesTable->DescriptorSize));\r
167 MemoryAttributesEntry = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1);\r
168 MemoryMap = MemoryMapStart;\r
169 for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {\r
170 switch (MemoryMap->Type) {\r
171 case EfiRuntimeServicesCode:\r
172 case EfiRuntimeServicesData:\r
173 CopyMem (MemoryAttributesEntry, MemoryMap, DescriptorSize);\r
174 MemoryAttributesEntry->Attribute &= (EFI_MEMORY_RO|EFI_MEMORY_XP|EFI_MEMORY_RUNTIME);\r
175 DEBUG ((EFI_D_VERBOSE, "Entry (0x%x)\n", MemoryAttributesEntry));\r
176 DEBUG ((EFI_D_VERBOSE, " Type - 0x%x\n", MemoryAttributesEntry->Type));\r
177 DEBUG ((EFI_D_VERBOSE, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry->PhysicalStart));\r
178 DEBUG ((EFI_D_VERBOSE, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry->VirtualStart));\r
179 DEBUG ((EFI_D_VERBOSE, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry->NumberOfPages));\r
180 DEBUG ((EFI_D_VERBOSE, " Attribute - 0x%016lx\n", MemoryAttributesEntry->Attribute));\r
181 MemoryAttributesEntry = NEXT_MEMORY_DESCRIPTOR(MemoryAttributesEntry, DescriptorSize);\r
182 break;\r
183 }\r
184 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);\r
185 }\r
2bfac751
SZ
186 MemoryMap = MemoryMapStart;\r
187 FreePool (MemoryMap);\r
98c4b005 188\r
74a88770
SZ
189 //\r
190 // Update configuratoin table for MemoryAttributesTable.\r
191 //\r
98c4b005
JY
192 Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, MemoryAttributesTable);\r
193 ASSERT_EFI_ERROR (Status);\r
74a88770
SZ
194\r
195 if (mMemoryAttributesTable != NULL) {\r
196 FreePool (mMemoryAttributesTable);\r
197 }\r
d1102dba 198 mMemoryAttributesTable = MemoryAttributesTable;\r
74a88770
SZ
199}\r
200\r
201/**\r
202 Install MemoryAttributesTable on memory allocation.\r
203\r
204 @param[in] MemoryType EFI memory type.\r
205**/\r
206VOID\r
207InstallMemoryAttributesTableOnMemoryAllocation (\r
208 IN EFI_MEMORY_TYPE MemoryType\r
209 )\r
210{\r
211 //\r
212 // Install MemoryAttributesTable after ReadyToBoot on runtime memory allocation.\r
213 //\r
214 if (mMemoryAttributesTableReadyToBoot &&\r
215 ((MemoryType == EfiRuntimeServicesCode) || (MemoryType == EfiRuntimeServicesData))) {\r
216 InstallMemoryAttributesTable ();\r
217 }\r
218}\r
219\r
220/**\r
221 Install MemoryAttributesTable on ReadyToBoot.\r
222\r
223 @param[in] Event The Event this notify function registered to.\r
224 @param[in] Context Pointer to the context data registered to the Event.\r
225**/\r
226VOID\r
227EFIAPI\r
228InstallMemoryAttributesTableOnReadyToBoot (\r
229 IN EFI_EVENT Event,\r
230 IN VOID *Context\r
231 )\r
232{\r
233 InstallMemoryAttributesTable ();\r
d1102dba 234 mMemoryAttributesTableReadyToBoot = TRUE;\r
98c4b005
JY
235}\r
236\r
b2305dd2
JY
237/**\r
238 Install initial MemoryAttributesTable on EndOfDxe.\r
239 Then SMM can consume this information.\r
240\r
241 @param[in] Event The Event this notify function registered to.\r
242 @param[in] Context Pointer to the context data registered to the Event.\r
243**/\r
244VOID\r
245EFIAPI\r
246InstallMemoryAttributesTableOnEndOfDxe (\r
247 IN EFI_EVENT Event,\r
248 IN VOID *Context\r
249 )\r
250{\r
251 InstallMemoryAttributesTable ();\r
252}\r
253\r
98c4b005
JY
254/**\r
255 Initialize MemoryAttrubutesTable support.\r
256**/\r
257VOID\r
258EFIAPI\r
259CoreInitializeMemoryAttributesTable (\r
260 VOID\r
261 )\r
262{\r
263 EFI_STATUS Status;\r
264 EFI_EVENT ReadyToBootEvent;\r
b2305dd2 265 EFI_EVENT EndOfDxeEvent;\r
98c4b005
JY
266\r
267 //\r
74a88770 268 // Construct the table at ReadyToBoot.\r
98c4b005 269 //\r
74a88770
SZ
270 Status = CoreCreateEventInternal (\r
271 EVT_NOTIFY_SIGNAL,\r
b2305dd2 272 TPL_CALLBACK,\r
74a88770
SZ
273 InstallMemoryAttributesTableOnReadyToBoot,\r
274 NULL,\r
275 &gEfiEventReadyToBootGuid,\r
276 &ReadyToBootEvent\r
277 );\r
98c4b005 278 ASSERT_EFI_ERROR (Status);\r
b2305dd2
JY
279\r
280 //\r
281 // Construct the initial table at EndOfDxe,\r
282 // then SMM can consume this information.\r
283 // Use TPL_NOTIFY here, as such SMM code (TPL_CALLBACK)\r
284 // can run after it.\r
285 //\r
286 Status = CoreCreateEventInternal (\r
287 EVT_NOTIFY_SIGNAL,\r
288 TPL_NOTIFY,\r
289 InstallMemoryAttributesTableOnEndOfDxe,\r
290 NULL,\r
291 &gEfiEndOfDxeEventGroupGuid,\r
292 &EndOfDxeEvent\r
293 );\r
294 ASSERT_EFI_ERROR (Status);\r
98c4b005
JY
295 return ;\r
296}\r