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