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