]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Misc/MemoryAttributesTable.c
MdeModulePkg/DxeCore: merge properties table routines into MAT handling
[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
98c4b005
JY
21\r
22#include "DxeMain.h"\r
aab6a9c9 23#include "HeapGuard.h"\r
98c4b005
JY
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
aab6a9c9
AB
67#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \\r
68 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))\r
69\r
70#define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')\r
71\r
72typedef struct {\r
73 UINT32 Signature;\r
74 UINTN ImageRecordCount;\r
75 UINTN CodeSegmentCountMax;\r
76 LIST_ENTRY ImageRecordList;\r
77} IMAGE_PROPERTIES_PRIVATE_DATA;\r
78\r
79STATIC IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData = {\r
80 IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE,\r
81 0,\r
82 0,\r
83 INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData.ImageRecordList)\r
84};\r
85\r
86STATIC EFI_LOCK mMemoryAttributesTableLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
87\r
d2c46681 88BOOLEAN mMemoryAttributesTableEnable = TRUE;\r
aab6a9c9 89BOOLEAN mMemoryAttributesTableEndOfDxe = FALSE;\r
74a88770
SZ
90EFI_MEMORY_ATTRIBUTES_TABLE *mMemoryAttributesTable = NULL;\r
91BOOLEAN mMemoryAttributesTableReadyToBoot = FALSE;\r
98c4b005 92\r
98c4b005
JY
93/**\r
94 Install MemoryAttributesTable.\r
95\r
98c4b005
JY
96**/\r
97VOID\r
98c4b005 98InstallMemoryAttributesTable (\r
74a88770 99 VOID\r
98c4b005
JY
100 )\r
101{\r
102 UINTN MemoryMapSize;\r
103 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
104 EFI_MEMORY_DESCRIPTOR *MemoryMapStart;\r
105 UINTN MapKey;\r
106 UINTN DescriptorSize;\r
107 UINT32 DescriptorVersion;\r
108 UINTN Index;\r
109 EFI_STATUS Status;\r
110 UINT32 RuntimeEntryCount;\r
111 EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;\r
112 EFI_MEMORY_DESCRIPTOR *MemoryAttributesEntry;\r
113\r
74a88770
SZ
114 if (gMemoryMapTerminated) {\r
115 //\r
116 // Directly return after MemoryMap terminated.\r
117 //\r
118 return;\r
119 }\r
120\r
d2c46681
AB
121 if (!mMemoryAttributesTableEnable) {\r
122 DEBUG ((DEBUG_VERBOSE, "Cannot install Memory Attributes Table "));\r
d4731a98 123 DEBUG ((EFI_D_VERBOSE, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10));\r
98c4b005
JY
124 return ;\r
125 }\r
126\r
74a88770
SZ
127 if (mMemoryAttributesTable == NULL) {\r
128 //\r
129 // InstallConfigurationTable here to occupy one entry for MemoryAttributesTable\r
130 // before GetMemoryMap below, as InstallConfigurationTable may allocate runtime\r
131 // memory for the new entry.\r
132 //\r
133 Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID *) (UINTN) MAX_ADDRESS);\r
134 ASSERT_EFI_ERROR (Status);\r
135 }\r
136\r
98c4b005
JY
137 MemoryMapSize = 0;\r
138 MemoryMap = NULL;\r
0ab90add 139 Status = CoreGetMemoryMapWithSeparatedImageSection (\r
98c4b005
JY
140 &MemoryMapSize,\r
141 MemoryMap,\r
142 &MapKey,\r
143 &DescriptorSize,\r
144 &DescriptorVersion\r
145 );\r
146 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
147\r
148 do {\r
149 MemoryMap = AllocatePool (MemoryMapSize);\r
150 ASSERT (MemoryMap != NULL);\r
151\r
0ab90add 152 Status = CoreGetMemoryMapWithSeparatedImageSection (\r
98c4b005
JY
153 &MemoryMapSize,\r
154 MemoryMap,\r
155 &MapKey,\r
156 &DescriptorSize,\r
157 &DescriptorVersion\r
158 );\r
159 if (EFI_ERROR (Status)) {\r
160 FreePool (MemoryMap);\r
161 }\r
162 } while (Status == EFI_BUFFER_TOO_SMALL);\r
163\r
164 MemoryMapStart = MemoryMap;\r
165 RuntimeEntryCount = 0;\r
166 for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {\r
167 switch (MemoryMap->Type) {\r
168 case EfiRuntimeServicesCode:\r
169 case EfiRuntimeServicesData:\r
170 RuntimeEntryCount ++;\r
171 break;\r
172 }\r
173 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);\r
174 }\r
175\r
176 //\r
177 // Allocate MemoryAttributesTable\r
178 //\r
179 MemoryAttributesTable = AllocatePool (sizeof(EFI_MEMORY_ATTRIBUTES_TABLE) + DescriptorSize * RuntimeEntryCount);\r
180 ASSERT (MemoryAttributesTable != NULL);\r
181 MemoryAttributesTable->Version = EFI_MEMORY_ATTRIBUTES_TABLE_VERSION;\r
182 MemoryAttributesTable->NumberOfEntries = RuntimeEntryCount;\r
183 MemoryAttributesTable->DescriptorSize = (UINT32)DescriptorSize;\r
184 MemoryAttributesTable->Reserved = 0;\r
185 DEBUG ((EFI_D_VERBOSE, "MemoryAttributesTable:\n"));\r
186 DEBUG ((EFI_D_VERBOSE, " Version - 0x%08x\n", MemoryAttributesTable->Version));\r
187 DEBUG ((EFI_D_VERBOSE, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable->NumberOfEntries));\r
188 DEBUG ((EFI_D_VERBOSE, " DescriptorSize - 0x%08x\n", MemoryAttributesTable->DescriptorSize));\r
189 MemoryAttributesEntry = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1);\r
190 MemoryMap = MemoryMapStart;\r
191 for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {\r
192 switch (MemoryMap->Type) {\r
193 case EfiRuntimeServicesCode:\r
194 case EfiRuntimeServicesData:\r
195 CopyMem (MemoryAttributesEntry, MemoryMap, DescriptorSize);\r
196 MemoryAttributesEntry->Attribute &= (EFI_MEMORY_RO|EFI_MEMORY_XP|EFI_MEMORY_RUNTIME);\r
197 DEBUG ((EFI_D_VERBOSE, "Entry (0x%x)\n", MemoryAttributesEntry));\r
198 DEBUG ((EFI_D_VERBOSE, " Type - 0x%x\n", MemoryAttributesEntry->Type));\r
199 DEBUG ((EFI_D_VERBOSE, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry->PhysicalStart));\r
200 DEBUG ((EFI_D_VERBOSE, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry->VirtualStart));\r
201 DEBUG ((EFI_D_VERBOSE, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry->NumberOfPages));\r
202 DEBUG ((EFI_D_VERBOSE, " Attribute - 0x%016lx\n", MemoryAttributesEntry->Attribute));\r
203 MemoryAttributesEntry = NEXT_MEMORY_DESCRIPTOR(MemoryAttributesEntry, DescriptorSize);\r
204 break;\r
205 }\r
206 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);\r
207 }\r
2bfac751
SZ
208 MemoryMap = MemoryMapStart;\r
209 FreePool (MemoryMap);\r
98c4b005 210\r
74a88770
SZ
211 //\r
212 // Update configuratoin table for MemoryAttributesTable.\r
213 //\r
98c4b005
JY
214 Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, MemoryAttributesTable);\r
215 ASSERT_EFI_ERROR (Status);\r
74a88770
SZ
216\r
217 if (mMemoryAttributesTable != NULL) {\r
218 FreePool (mMemoryAttributesTable);\r
219 }\r
d1102dba 220 mMemoryAttributesTable = MemoryAttributesTable;\r
74a88770
SZ
221}\r
222\r
223/**\r
224 Install MemoryAttributesTable on memory allocation.\r
225\r
226 @param[in] MemoryType EFI memory type.\r
227**/\r
228VOID\r
229InstallMemoryAttributesTableOnMemoryAllocation (\r
230 IN EFI_MEMORY_TYPE MemoryType\r
231 )\r
232{\r
233 //\r
234 // Install MemoryAttributesTable after ReadyToBoot on runtime memory allocation.\r
235 //\r
236 if (mMemoryAttributesTableReadyToBoot &&\r
237 ((MemoryType == EfiRuntimeServicesCode) || (MemoryType == EfiRuntimeServicesData))) {\r
238 InstallMemoryAttributesTable ();\r
239 }\r
240}\r
241\r
242/**\r
243 Install MemoryAttributesTable on ReadyToBoot.\r
244\r
245 @param[in] Event The Event this notify function registered to.\r
246 @param[in] Context Pointer to the context data registered to the Event.\r
247**/\r
248VOID\r
249EFIAPI\r
250InstallMemoryAttributesTableOnReadyToBoot (\r
251 IN EFI_EVENT Event,\r
252 IN VOID *Context\r
253 )\r
254{\r
255 InstallMemoryAttributesTable ();\r
d1102dba 256 mMemoryAttributesTableReadyToBoot = TRUE;\r
98c4b005
JY
257}\r
258\r
b2305dd2
JY
259/**\r
260 Install initial MemoryAttributesTable on EndOfDxe.\r
261 Then SMM can consume this information.\r
262\r
263 @param[in] Event The Event this notify function registered to.\r
264 @param[in] Context Pointer to the context data registered to the Event.\r
265**/\r
266VOID\r
267EFIAPI\r
268InstallMemoryAttributesTableOnEndOfDxe (\r
269 IN EFI_EVENT Event,\r
270 IN VOID *Context\r
271 )\r
272{\r
aab6a9c9 273 mMemoryAttributesTableEndOfDxe = TRUE;\r
b2305dd2
JY
274 InstallMemoryAttributesTable ();\r
275}\r
276\r
98c4b005
JY
277/**\r
278 Initialize MemoryAttrubutesTable support.\r
279**/\r
280VOID\r
281EFIAPI\r
282CoreInitializeMemoryAttributesTable (\r
283 VOID\r
284 )\r
285{\r
286 EFI_STATUS Status;\r
287 EFI_EVENT ReadyToBootEvent;\r
b2305dd2 288 EFI_EVENT EndOfDxeEvent;\r
98c4b005
JY
289\r
290 //\r
74a88770 291 // Construct the table at ReadyToBoot.\r
98c4b005 292 //\r
74a88770
SZ
293 Status = CoreCreateEventInternal (\r
294 EVT_NOTIFY_SIGNAL,\r
b2305dd2 295 TPL_CALLBACK,\r
74a88770
SZ
296 InstallMemoryAttributesTableOnReadyToBoot,\r
297 NULL,\r
298 &gEfiEventReadyToBootGuid,\r
299 &ReadyToBootEvent\r
300 );\r
98c4b005 301 ASSERT_EFI_ERROR (Status);\r
b2305dd2
JY
302\r
303 //\r
304 // Construct the initial table at EndOfDxe,\r
305 // then SMM can consume this information.\r
306 // Use TPL_NOTIFY here, as such SMM code (TPL_CALLBACK)\r
307 // can run after it.\r
308 //\r
309 Status = CoreCreateEventInternal (\r
310 EVT_NOTIFY_SIGNAL,\r
311 TPL_NOTIFY,\r
312 InstallMemoryAttributesTableOnEndOfDxe,\r
313 NULL,\r
314 &gEfiEndOfDxeEventGroupGuid,\r
315 &EndOfDxeEvent\r
316 );\r
317 ASSERT_EFI_ERROR (Status);\r
98c4b005
JY
318 return ;\r
319}\r
aab6a9c9
AB
320\r
321//\r
322// Below functions are for MemoryMap\r
323//\r
324\r
325/**\r
326 Converts a number of EFI_PAGEs to a size in bytes.\r
327\r
328 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.\r
329\r
330 @param Pages The number of EFI_PAGES.\r
331\r
332 @return The number of bytes associated with the number of EFI_PAGEs specified\r
333 by Pages.\r
334**/\r
335STATIC\r
336UINT64\r
337EfiPagesToSize (\r
338 IN UINT64 Pages\r
339 )\r
340{\r
341 return LShiftU64 (Pages, EFI_PAGE_SHIFT);\r
342}\r
343\r
344/**\r
345 Converts a size, in bytes, to a number of EFI_PAGESs.\r
346\r
347 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.\r
348\r
349 @param Size A size in bytes.\r
350\r
351 @return The number of EFI_PAGESs associated with the number of bytes specified\r
352 by Size.\r
353\r
354**/\r
355STATIC\r
356UINT64\r
357EfiSizeToPages (\r
358 IN UINT64 Size\r
359 )\r
360{\r
361 return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0);\r
362}\r
363\r
364/**\r
365 Acquire memory lock on mMemoryAttributesTableLock.\r
366**/\r
367STATIC\r
368VOID\r
369CoreAcquiremMemoryAttributesTableLock (\r
370 VOID\r
371 )\r
372{\r
373 CoreAcquireLock (&mMemoryAttributesTableLock);\r
374}\r
375\r
376/**\r
377 Release memory lock on mMemoryAttributesTableLock.\r
378**/\r
379STATIC\r
380VOID\r
381CoreReleasemMemoryAttributesTableLock (\r
382 VOID\r
383 )\r
384{\r
385 CoreReleaseLock (&mMemoryAttributesTableLock);\r
386}\r
387\r
388/**\r
389 Sort memory map entries based upon PhysicalStart, from low to high.\r
390\r
391 @param MemoryMap A pointer to the buffer in which firmware places\r
392 the current memory map.\r
393 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.\r
394 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
395**/\r
396STATIC\r
397VOID\r
398SortMemoryMap (\r
399 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
400 IN UINTN MemoryMapSize,\r
401 IN UINTN DescriptorSize\r
402 )\r
403{\r
404 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;\r
405 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;\r
406 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;\r
407 EFI_MEMORY_DESCRIPTOR TempMemoryMap;\r
408\r
409 MemoryMapEntry = MemoryMap;\r
410 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
411 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);\r
412 while (MemoryMapEntry < MemoryMapEnd) {\r
413 while (NextMemoryMapEntry < MemoryMapEnd) {\r
414 if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {\r
415 CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));\r
416 CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));\r
417 CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof(EFI_MEMORY_DESCRIPTOR));\r
418 }\r
419\r
420 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);\r
421 }\r
422\r
423 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
424 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
425 }\r
426\r
427 return ;\r
428}\r
429\r
430/**\r
431 Merge continous memory map entries whose have same attributes.\r
432\r
433 @param MemoryMap A pointer to the buffer in which firmware places\r
434 the current memory map.\r
435 @param MemoryMapSize A pointer to the size, in bytes, of the\r
436 MemoryMap buffer. On input, this is the size of\r
437 the current memory map. On output,\r
438 it is the size of new memory map after merge.\r
439 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
440**/\r
441VOID\r
442MergeMemoryMap (\r
443 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
444 IN OUT UINTN *MemoryMapSize,\r
445 IN UINTN DescriptorSize\r
446 )\r
447{\r
448 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;\r
449 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;\r
450 UINT64 MemoryBlockLength;\r
451 EFI_MEMORY_DESCRIPTOR *NewMemoryMapEntry;\r
452 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;\r
453\r
454 MemoryMapEntry = MemoryMap;\r
455 NewMemoryMapEntry = MemoryMap;\r
456 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + *MemoryMapSize);\r
457 while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {\r
458 CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));\r
459 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
460\r
461 do {\r
462 MergeGuardPages (NewMemoryMapEntry, NextMemoryMapEntry->PhysicalStart);\r
463 MemoryBlockLength = (UINT64) (EfiPagesToSize (NewMemoryMapEntry->NumberOfPages));\r
464 if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&\r
465 (NewMemoryMapEntry->Type == NextMemoryMapEntry->Type) &&\r
466 (NewMemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) &&\r
467 ((NewMemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart)) {\r
468 NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;\r
469 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);\r
470 continue;\r
471 } else {\r
472 MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);\r
473 break;\r
474 }\r
475 } while (TRUE);\r
476\r
477 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
478 NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);\r
479 }\r
480\r
481 *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;\r
482\r
483 return ;\r
484}\r
485\r
486/**\r
487 Enforce memory map attributes.\r
488 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.\r
489\r
490 @param MemoryMap A pointer to the buffer in which firmware places\r
491 the current memory map.\r
492 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.\r
493 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
494**/\r
495STATIC\r
496VOID\r
497EnforceMemoryMapAttribute (\r
498 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
499 IN UINTN MemoryMapSize,\r
500 IN UINTN DescriptorSize\r
501 )\r
502{\r
503 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;\r
504 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;\r
505\r
506 MemoryMapEntry = MemoryMap;\r
507 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);\r
508 while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {\r
509 switch (MemoryMapEntry->Type) {\r
510 case EfiRuntimeServicesCode:\r
511 // do nothing\r
512 break;\r
513 case EfiRuntimeServicesData:\r
514 case EfiMemoryMappedIO:\r
515 case EfiMemoryMappedIOPortSpace:\r
516 MemoryMapEntry->Attribute |= EFI_MEMORY_XP;\r
517 break;\r
518 case EfiReservedMemoryType:\r
519 case EfiACPIMemoryNVS:\r
520 break;\r
521 }\r
522\r
523 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
524 }\r
525\r
526 return ;\r
527}\r
528\r
529/**\r
530 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].\r
531\r
532 @param Buffer Start Address\r
533 @param Length Address length\r
534\r
535 @return first image record covered by [buffer, length]\r
536**/\r
537STATIC\r
538IMAGE_PROPERTIES_RECORD *\r
539GetImageRecordByAddress (\r
540 IN EFI_PHYSICAL_ADDRESS Buffer,\r
541 IN UINT64 Length\r
542 )\r
543{\r
544 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
545 LIST_ENTRY *ImageRecordLink;\r
546 LIST_ENTRY *ImageRecordList;\r
547\r
548 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;\r
549\r
550 for (ImageRecordLink = ImageRecordList->ForwardLink;\r
551 ImageRecordLink != ImageRecordList;\r
552 ImageRecordLink = ImageRecordLink->ForwardLink) {\r
553 ImageRecord = CR (\r
554 ImageRecordLink,\r
555 IMAGE_PROPERTIES_RECORD,\r
556 Link,\r
557 IMAGE_PROPERTIES_RECORD_SIGNATURE\r
558 );\r
559\r
560 if ((Buffer <= ImageRecord->ImageBase) &&\r
561 (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize)) {\r
562 return ImageRecord;\r
563 }\r
564 }\r
565\r
566 return NULL;\r
567}\r
568\r
569/**\r
570 Set the memory map to new entries, according to one old entry,\r
571 based upon PE code section and data section in image record\r
572\r
573 @param ImageRecord An image record whose [ImageBase, ImageSize] covered\r
574 by old memory map entry.\r
575 @param NewRecord A pointer to several new memory map entries.\r
576 The caller gurantee the buffer size be 1 +\r
577 (SplitRecordCount * DescriptorSize) calculated\r
578 below.\r
579 @param OldRecord A pointer to one old memory map entry.\r
580 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
581**/\r
582STATIC\r
583UINTN\r
584SetNewRecord (\r
585 IN IMAGE_PROPERTIES_RECORD *ImageRecord,\r
586 IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord,\r
587 IN EFI_MEMORY_DESCRIPTOR *OldRecord,\r
588 IN UINTN DescriptorSize\r
589 )\r
590{\r
591 EFI_MEMORY_DESCRIPTOR TempRecord;\r
592 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;\r
593 LIST_ENTRY *ImageRecordCodeSectionLink;\r
594 LIST_ENTRY *ImageRecordCodeSectionEndLink;\r
595 LIST_ENTRY *ImageRecordCodeSectionList;\r
596 UINTN NewRecordCount;\r
597 UINT64 PhysicalEnd;\r
598 UINT64 ImageEnd;\r
599\r
600 CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR));\r
601 PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);\r
602 NewRecordCount = 0;\r
603\r
604 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;\r
605\r
606 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;\r
607 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;\r
608 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {\r
609 ImageRecordCodeSection = CR (\r
610 ImageRecordCodeSectionLink,\r
611 IMAGE_PROPERTIES_RECORD_CODE_SECTION,\r
612 Link,\r
613 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE\r
614 );\r
615 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;\r
616\r
617 if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) {\r
618 //\r
619 // DATA\r
620 //\r
621 NewRecord->Type = TempRecord.Type;\r
622 NewRecord->PhysicalStart = TempRecord.PhysicalStart;\r
623 NewRecord->VirtualStart = 0;\r
624 NewRecord->NumberOfPages = EfiSizeToPages(ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart);\r
625 NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;\r
626 if (NewRecord->NumberOfPages != 0) {\r
627 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
628 NewRecordCount ++;\r
629 }\r
630\r
631 //\r
632 // CODE\r
633 //\r
634 NewRecord->Type = TempRecord.Type;\r
635 NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase;\r
636 NewRecord->VirtualStart = 0;\r
637 NewRecord->NumberOfPages = EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize);\r
638 NewRecord->Attribute = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO;\r
639 if (NewRecord->NumberOfPages != 0) {\r
640 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
641 NewRecordCount ++;\r
642 }\r
643\r
644 TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize));\r
645 TempRecord.NumberOfPages = EfiSizeToPages(PhysicalEnd - TempRecord.PhysicalStart);\r
646 if (TempRecord.NumberOfPages == 0) {\r
647 break;\r
648 }\r
649 }\r
650 }\r
651\r
652 ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;\r
653\r
654 //\r
655 // Final DATA\r
656 //\r
657 if (TempRecord.PhysicalStart < ImageEnd) {\r
658 NewRecord->Type = TempRecord.Type;\r
659 NewRecord->PhysicalStart = TempRecord.PhysicalStart;\r
660 NewRecord->VirtualStart = 0;\r
661 NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart);\r
662 NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;\r
663 NewRecordCount ++;\r
664 }\r
665\r
666 return NewRecordCount;\r
667}\r
668\r
669/**\r
670 Return the max number of new splitted entries, according to one old entry,\r
671 based upon PE code section and data section.\r
672\r
673 @param OldRecord A pointer to one old memory map entry.\r
674\r
675 @retval 0 no entry need to be splitted.\r
676 @return the max number of new splitted entries\r
677**/\r
678STATIC\r
679UINTN\r
680GetMaxSplitRecordCount (\r
681 IN EFI_MEMORY_DESCRIPTOR *OldRecord\r
682 )\r
683{\r
684 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
685 UINTN SplitRecordCount;\r
686 UINT64 PhysicalStart;\r
687 UINT64 PhysicalEnd;\r
688\r
689 SplitRecordCount = 0;\r
690 PhysicalStart = OldRecord->PhysicalStart;\r
691 PhysicalEnd = OldRecord->PhysicalStart + EfiPagesToSize(OldRecord->NumberOfPages);\r
692\r
693 do {\r
694 ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);\r
695 if (ImageRecord == NULL) {\r
696 break;\r
697 }\r
698 SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1);\r
699 PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;\r
700 } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));\r
701\r
702 if (SplitRecordCount != 0) {\r
703 SplitRecordCount--;\r
704 }\r
705\r
706 return SplitRecordCount;\r
707}\r
708\r
709/**\r
710 Split the memory map to new entries, according to one old entry,\r
711 based upon PE code section and data section.\r
712\r
713 @param OldRecord A pointer to one old memory map entry.\r
714 @param NewRecord A pointer to several new memory map entries.\r
715 The caller gurantee the buffer size be 1 +\r
716 (SplitRecordCount * DescriptorSize) calculated\r
717 below.\r
718 @param MaxSplitRecordCount The max number of splitted entries\r
719 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
720\r
721 @retval 0 no entry is splitted.\r
722 @return the real number of splitted record.\r
723**/\r
724STATIC\r
725UINTN\r
726SplitRecord (\r
727 IN EFI_MEMORY_DESCRIPTOR *OldRecord,\r
728 IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord,\r
729 IN UINTN MaxSplitRecordCount,\r
730 IN UINTN DescriptorSize\r
731 )\r
732{\r
733 EFI_MEMORY_DESCRIPTOR TempRecord;\r
734 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
735 IMAGE_PROPERTIES_RECORD *NewImageRecord;\r
736 UINT64 PhysicalStart;\r
737 UINT64 PhysicalEnd;\r
738 UINTN NewRecordCount;\r
739 UINTN TotalNewRecordCount;\r
740 BOOLEAN IsLastRecordData;\r
741\r
742 if (MaxSplitRecordCount == 0) {\r
743 CopyMem (NewRecord, OldRecord, DescriptorSize);\r
744 return 0;\r
745 }\r
746\r
747 TotalNewRecordCount = 0;\r
748\r
749 //\r
750 // Override previous record\r
751 //\r
752 CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR));\r
753 PhysicalStart = TempRecord.PhysicalStart;\r
754 PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);\r
755\r
756 ImageRecord = NULL;\r
757 do {\r
758 NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);\r
759 if (NewImageRecord == NULL) {\r
760 //\r
761 // No more image covered by this range, stop\r
762 //\r
763 if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {\r
764 //\r
765 // If this is still address in this record, need record.\r
766 //\r
767 NewRecord = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
768 IsLastRecordData = FALSE;\r
769 if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) {\r
770 IsLastRecordData = TRUE;\r
771 }\r
772 if (IsLastRecordData) {\r
773 //\r
774 // Last record is DATA, just merge it.\r
775 //\r
776 NewRecord->NumberOfPages = EfiSizeToPages(PhysicalEnd - NewRecord->PhysicalStart);\r
777 } else {\r
778 //\r
779 // Last record is CODE, create a new DATA entry.\r
780 //\r
781 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
782 NewRecord->Type = TempRecord.Type;\r
783 NewRecord->PhysicalStart = TempRecord.PhysicalStart;\r
784 NewRecord->VirtualStart = 0;\r
785 NewRecord->NumberOfPages = TempRecord.NumberOfPages;\r
786 NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;\r
787 TotalNewRecordCount ++;\r
788 }\r
789 }\r
790 break;\r
791 }\r
792 ImageRecord = NewImageRecord;\r
793\r
794 //\r
795 // Set new record\r
796 //\r
797 NewRecordCount = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize);\r
798 TotalNewRecordCount += NewRecordCount;\r
799 NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize);\r
800\r
801 //\r
802 // Update PhysicalStart, in order to exclude the image buffer already splitted.\r
803 //\r
804 PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;\r
805 TempRecord.PhysicalStart = PhysicalStart;\r
806 TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);\r
807 } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));\r
808\r
809 //\r
810 // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the\r
811 // code reaches here.\r
812 //\r
813 ASSERT (TotalNewRecordCount != 0);\r
814 return TotalNewRecordCount - 1;\r
815}\r
816\r
817/**\r
818 Split the original memory map, and add more entries to describe PE code section and data section.\r
819 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.\r
820 This function will merge entries with same attributes finally.\r
821\r
822 NOTE: It assumes PE code/data section are page aligned.\r
823 NOTE: It assumes enough entry is prepared for new memory map.\r
824\r
825 Split table:\r
826 +---------------+\r
827 | Record X |\r
828 +---------------+\r
829 | Record RtCode |\r
830 +---------------+\r
831 | Record Y |\r
832 +---------------+\r
833 ==>\r
834 +---------------+\r
835 | Record X |\r
836 +---------------+ ----\r
837 | Record RtData | |\r
838 +---------------+ |\r
839 | Record RtCode | |-> PE/COFF1\r
840 +---------------+ |\r
841 | Record RtData | |\r
842 +---------------+ ----\r
843 | Record RtData | |\r
844 +---------------+ |\r
845 | Record RtCode | |-> PE/COFF2\r
846 +---------------+ |\r
847 | Record RtData | |\r
848 +---------------+ ----\r
849 | Record Y |\r
850 +---------------+\r
851\r
852 @param MemoryMapSize A pointer to the size, in bytes, of the\r
853 MemoryMap buffer. On input, this is the size of\r
854 old MemoryMap before split. The actual buffer\r
855 size of MemoryMap is MemoryMapSize +\r
856 (AdditionalRecordCount * DescriptorSize) calculated\r
857 below. On output, it is the size of new MemoryMap\r
858 after split.\r
859 @param MemoryMap A pointer to the buffer in which firmware places\r
860 the current memory map.\r
861 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.\r
862**/\r
863STATIC\r
864VOID\r
865SplitTable (\r
866 IN OUT UINTN *MemoryMapSize,\r
867 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
868 IN UINTN DescriptorSize\r
869 )\r
870{\r
871 INTN IndexOld;\r
872 INTN IndexNew;\r
873 UINTN MaxSplitRecordCount;\r
874 UINTN RealSplitRecordCount;\r
875 UINTN TotalSplitRecordCount;\r
876 UINTN AdditionalRecordCount;\r
877\r
878 AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;\r
879\r
880 TotalSplitRecordCount = 0;\r
881 //\r
882 // Let old record point to end of valid MemoryMap buffer.\r
883 //\r
884 IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1;\r
885 //\r
886 // Let new record point to end of full MemoryMap buffer.\r
887 //\r
888 IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + AdditionalRecordCount;\r
889 for (; IndexOld >= 0; IndexOld--) {\r
890 MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize));\r
891 //\r
892 // Split this MemoryMap record\r
893 //\r
894 IndexNew -= MaxSplitRecordCount;\r
895 RealSplitRecordCount = SplitRecord (\r
896 (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),\r
897 (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),\r
898 MaxSplitRecordCount,\r
899 DescriptorSize\r
900 );\r
901 //\r
902 // Adjust IndexNew according to real split.\r
903 //\r
904 CopyMem (\r
905 ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),\r
906 ((UINT8 *)MemoryMap + IndexNew * DescriptorSize),\r
907 RealSplitRecordCount * DescriptorSize\r
908 );\r
909 IndexNew = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;\r
910 TotalSplitRecordCount += RealSplitRecordCount;\r
911 IndexNew --;\r
912 }\r
913 //\r
914 // Move all records to the beginning.\r
915 //\r
916 CopyMem (\r
917 MemoryMap,\r
918 (UINT8 *)MemoryMap + (AdditionalRecordCount - TotalSplitRecordCount) * DescriptorSize,\r
919 (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize\r
920 );\r
921\r
922 *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount;\r
923\r
924 //\r
925 // Sort from low to high (Just in case)\r
926 //\r
927 SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);\r
928\r
929 //\r
930 // Set RuntimeData to XP\r
931 //\r
932 EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, DescriptorSize);\r
933\r
934 //\r
935 // Merge same type to save entry size\r
936 //\r
937 MergeMemoryMap (MemoryMap, MemoryMapSize, DescriptorSize);\r
938\r
939 return ;\r
940}\r
941\r
942/**\r
943 This function for GetMemoryMap() with properties table capability.\r
944\r
945 It calls original GetMemoryMap() to get the original memory map information. Then\r
946 plus the additional memory map entries for PE Code/Data seperation.\r
947\r
948 @param MemoryMapSize A pointer to the size, in bytes, of the\r
949 MemoryMap buffer. On input, this is the size of\r
950 the buffer allocated by the caller. On output,\r
951 it is the size of the buffer returned by the\r
952 firmware if the buffer was large enough, or the\r
953 size of the buffer needed to contain the map if\r
954 the buffer was too small.\r
955 @param MemoryMap A pointer to the buffer in which firmware places\r
956 the current memory map.\r
957 @param MapKey A pointer to the location in which firmware\r
958 returns the key for the current memory map.\r
959 @param DescriptorSize A pointer to the location in which firmware\r
960 returns the size, in bytes, of an individual\r
961 EFI_MEMORY_DESCRIPTOR.\r
962 @param DescriptorVersion A pointer to the location in which firmware\r
963 returns the version number associated with the\r
964 EFI_MEMORY_DESCRIPTOR.\r
965\r
966 @retval EFI_SUCCESS The memory map was returned in the MemoryMap\r
967 buffer.\r
968 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current\r
969 buffer size needed to hold the memory map is\r
970 returned in MemoryMapSize.\r
971 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.\r
972\r
973**/\r
974EFI_STATUS\r
975EFIAPI\r
976CoreGetMemoryMapWithSeparatedImageSection (\r
977 IN OUT UINTN *MemoryMapSize,\r
978 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,\r
979 OUT UINTN *MapKey,\r
980 OUT UINTN *DescriptorSize,\r
981 OUT UINT32 *DescriptorVersion\r
982 )\r
983{\r
984 EFI_STATUS Status;\r
985 UINTN OldMemoryMapSize;\r
986 UINTN AdditionalRecordCount;\r
987\r
988 //\r
989 // If PE code/data is not aligned, just return.\r
990 //\r
991 if (!mMemoryAttributesTableEnable) {\r
992 return CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);\r
993 }\r
994\r
995 if (MemoryMapSize == NULL) {\r
996 return EFI_INVALID_PARAMETER;\r
997 }\r
998\r
999 CoreAcquiremMemoryAttributesTableLock ();\r
1000\r
1001 AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;\r
1002\r
1003 OldMemoryMapSize = *MemoryMapSize;\r
1004 Status = CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);\r
1005 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1006 *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount;\r
1007 } else if (Status == EFI_SUCCESS) {\r
1008 ASSERT (MemoryMap != NULL);\r
1009 if (OldMemoryMapSize - *MemoryMapSize < (*DescriptorSize) * AdditionalRecordCount) {\r
1010 *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount;\r
1011 //\r
1012 // Need update status to buffer too small\r
1013 //\r
1014 Status = EFI_BUFFER_TOO_SMALL;\r
1015 } else {\r
1016 //\r
1017 // Split PE code/data\r
1018 //\r
1019 SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize);\r
1020 }\r
1021 }\r
1022\r
1023 CoreReleasemMemoryAttributesTableLock ();\r
1024 return Status;\r
1025}\r
1026\r
1027//\r
1028// Below functions are for ImageRecord\r
1029//\r
1030\r
1031/**\r
1032 Set MemoryAttributesTable according to PE/COFF image section alignment.\r
1033\r
1034 @param SectionAlignment PE/COFF section alignment\r
1035**/\r
1036STATIC\r
1037VOID\r
1038SetMemoryAttributesTableSectionAlignment (\r
1039 IN UINT32 SectionAlignment\r
1040 )\r
1041{\r
1042 if (((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) &&\r
1043 mMemoryAttributesTableEnable) {\r
1044 DEBUG ((DEBUG_VERBOSE, "SetMemoryAttributesTableSectionAlignment - Clear\n"));\r
1045 mMemoryAttributesTableEnable = FALSE;\r
1046 }\r
1047}\r
1048\r
1049/**\r
1050 Swap two code sections in image record.\r
1051\r
1052 @param FirstImageRecordCodeSection first code section in image record\r
1053 @param SecondImageRecordCodeSection second code section in image record\r
1054**/\r
1055STATIC\r
1056VOID\r
1057SwapImageRecordCodeSection (\r
1058 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *FirstImageRecordCodeSection,\r
1059 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *SecondImageRecordCodeSection\r
1060 )\r
1061{\r
1062 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection;\r
1063\r
1064 TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase;\r
1065 TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize;\r
1066\r
1067 FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase;\r
1068 FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize;\r
1069\r
1070 SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase;\r
1071 SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize;\r
1072}\r
1073\r
1074/**\r
1075 Sort code section in image record, based upon CodeSegmentBase from low to high.\r
1076\r
1077 @param ImageRecord image record to be sorted\r
1078**/\r
1079VOID\r
1080SortImageRecordCodeSection (\r
1081 IN IMAGE_PROPERTIES_RECORD *ImageRecord\r
1082 )\r
1083{\r
1084 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;\r
1085 IMAGE_PROPERTIES_RECORD_CODE_SECTION *NextImageRecordCodeSection;\r
1086 LIST_ENTRY *ImageRecordCodeSectionLink;\r
1087 LIST_ENTRY *NextImageRecordCodeSectionLink;\r
1088 LIST_ENTRY *ImageRecordCodeSectionEndLink;\r
1089 LIST_ENTRY *ImageRecordCodeSectionList;\r
1090\r
1091 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;\r
1092\r
1093 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;\r
1094 NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;\r
1095 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;\r
1096 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {\r
1097 ImageRecordCodeSection = CR (\r
1098 ImageRecordCodeSectionLink,\r
1099 IMAGE_PROPERTIES_RECORD_CODE_SECTION,\r
1100 Link,\r
1101 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE\r
1102 );\r
1103 while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {\r
1104 NextImageRecordCodeSection = CR (\r
1105 NextImageRecordCodeSectionLink,\r
1106 IMAGE_PROPERTIES_RECORD_CODE_SECTION,\r
1107 Link,\r
1108 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE\r
1109 );\r
1110 if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) {\r
1111 SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);\r
1112 }\r
1113 NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;\r
1114 }\r
1115\r
1116 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;\r
1117 NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;\r
1118 }\r
1119}\r
1120\r
1121/**\r
1122 Check if code section in image record is valid.\r
1123\r
1124 @param ImageRecord image record to be checked\r
1125\r
1126 @retval TRUE image record is valid\r
1127 @retval FALSE image record is invalid\r
1128**/\r
1129BOOLEAN\r
1130IsImageRecordCodeSectionValid (\r
1131 IN IMAGE_PROPERTIES_RECORD *ImageRecord\r
1132 )\r
1133{\r
1134 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;\r
1135 IMAGE_PROPERTIES_RECORD_CODE_SECTION *LastImageRecordCodeSection;\r
1136 LIST_ENTRY *ImageRecordCodeSectionLink;\r
1137 LIST_ENTRY *ImageRecordCodeSectionEndLink;\r
1138 LIST_ENTRY *ImageRecordCodeSectionList;\r
1139\r
1140 DEBUG ((DEBUG_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));\r
1141\r
1142 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;\r
1143\r
1144 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;\r
1145 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;\r
1146 LastImageRecordCodeSection = NULL;\r
1147 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {\r
1148 ImageRecordCodeSection = CR (\r
1149 ImageRecordCodeSectionLink,\r
1150 IMAGE_PROPERTIES_RECORD_CODE_SECTION,\r
1151 Link,\r
1152 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE\r
1153 );\r
1154 if (ImageRecordCodeSection->CodeSegmentSize == 0) {\r
1155 return FALSE;\r
1156 }\r
1157 if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) {\r
1158 return FALSE;\r
1159 }\r
1160 if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) {\r
1161 return FALSE;\r
1162 }\r
1163 if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) {\r
1164 return FALSE;\r
1165 }\r
1166 if (LastImageRecordCodeSection != NULL) {\r
1167 if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) {\r
1168 return FALSE;\r
1169 }\r
1170 }\r
1171\r
1172 LastImageRecordCodeSection = ImageRecordCodeSection;\r
1173 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;\r
1174 }\r
1175\r
1176 return TRUE;\r
1177}\r
1178\r
1179/**\r
1180 Swap two image records.\r
1181\r
1182 @param FirstImageRecord first image record.\r
1183 @param SecondImageRecord second image record.\r
1184**/\r
1185STATIC\r
1186VOID\r
1187SwapImageRecord (\r
1188 IN IMAGE_PROPERTIES_RECORD *FirstImageRecord,\r
1189 IN IMAGE_PROPERTIES_RECORD *SecondImageRecord\r
1190 )\r
1191{\r
1192 IMAGE_PROPERTIES_RECORD TempImageRecord;\r
1193\r
1194 TempImageRecord.ImageBase = FirstImageRecord->ImageBase;\r
1195 TempImageRecord.ImageSize = FirstImageRecord->ImageSize;\r
1196 TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;\r
1197\r
1198 FirstImageRecord->ImageBase = SecondImageRecord->ImageBase;\r
1199 FirstImageRecord->ImageSize = SecondImageRecord->ImageSize;\r
1200 FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount;\r
1201\r
1202 SecondImageRecord->ImageBase = TempImageRecord.ImageBase;\r
1203 SecondImageRecord->ImageSize = TempImageRecord.ImageSize;\r
1204 SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount;\r
1205\r
1206 SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList);\r
1207}\r
1208\r
1209/**\r
1210 Sort image record based upon the ImageBase from low to high.\r
1211**/\r
1212STATIC\r
1213VOID\r
1214SortImageRecord (\r
1215 VOID\r
1216 )\r
1217{\r
1218 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
1219 IMAGE_PROPERTIES_RECORD *NextImageRecord;\r
1220 LIST_ENTRY *ImageRecordLink;\r
1221 LIST_ENTRY *NextImageRecordLink;\r
1222 LIST_ENTRY *ImageRecordEndLink;\r
1223 LIST_ENTRY *ImageRecordList;\r
1224\r
1225 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;\r
1226\r
1227 ImageRecordLink = ImageRecordList->ForwardLink;\r
1228 NextImageRecordLink = ImageRecordLink->ForwardLink;\r
1229 ImageRecordEndLink = ImageRecordList;\r
1230 while (ImageRecordLink != ImageRecordEndLink) {\r
1231 ImageRecord = CR (\r
1232 ImageRecordLink,\r
1233 IMAGE_PROPERTIES_RECORD,\r
1234 Link,\r
1235 IMAGE_PROPERTIES_RECORD_SIGNATURE\r
1236 );\r
1237 while (NextImageRecordLink != ImageRecordEndLink) {\r
1238 NextImageRecord = CR (\r
1239 NextImageRecordLink,\r
1240 IMAGE_PROPERTIES_RECORD,\r
1241 Link,\r
1242 IMAGE_PROPERTIES_RECORD_SIGNATURE\r
1243 );\r
1244 if (ImageRecord->ImageBase > NextImageRecord->ImageBase) {\r
1245 SwapImageRecord (ImageRecord, NextImageRecord);\r
1246 }\r
1247 NextImageRecordLink = NextImageRecordLink->ForwardLink;\r
1248 }\r
1249\r
1250 ImageRecordLink = ImageRecordLink->ForwardLink;\r
1251 NextImageRecordLink = ImageRecordLink->ForwardLink;\r
1252 }\r
1253}\r
1254\r
1255/**\r
1256 Insert image record.\r
1257\r
1258 @param RuntimeImage Runtime image information\r
1259**/\r
1260VOID\r
1261InsertImageRecord (\r
1262 IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage\r
1263 )\r
1264{\r
1265 VOID *ImageAddress;\r
1266 EFI_IMAGE_DOS_HEADER *DosHdr;\r
1267 UINT32 PeCoffHeaderOffset;\r
1268 UINT32 SectionAlignment;\r
1269 EFI_IMAGE_SECTION_HEADER *Section;\r
1270 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
1271 UINT8 *Name;\r
1272 UINTN Index;\r
1273 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
1274 CHAR8 *PdbPointer;\r
1275 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;\r
1276\r
1277 DEBUG ((DEBUG_VERBOSE, "InsertImageRecord - 0x%x\n", RuntimeImage));\r
1278 DEBUG ((DEBUG_VERBOSE, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize));\r
1279\r
1280 if (mMemoryAttributesTableEndOfDxe) {\r
1281 DEBUG ((DEBUG_INFO, "Do not insert runtime image record after EndOfDxe\n"));\r
1282 return ;\r
1283 }\r
1284\r
1285 ImageRecord = AllocatePool (sizeof(*ImageRecord));\r
1286 if (ImageRecord == NULL) {\r
1287 return ;\r
1288 }\r
1289 ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;\r
1290\r
1291 DEBUG ((DEBUG_VERBOSE, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));\r
1292\r
1293 //\r
1294 // Step 1: record whole region\r
1295 //\r
1296 ImageRecord->ImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase;\r
1297 ImageRecord->ImageSize = RuntimeImage->ImageSize;\r
1298\r
1299 ImageAddress = RuntimeImage->ImageBase;\r
1300\r
1301 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);\r
1302 if (PdbPointer != NULL) {\r
1303 DEBUG ((DEBUG_VERBOSE, " Image - %a\n", PdbPointer));\r
1304 }\r
1305\r
1306 //\r
1307 // Check PE/COFF image\r
1308 //\r
1309 DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress;\r
1310 PeCoffHeaderOffset = 0;\r
1311 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
1312 PeCoffHeaderOffset = DosHdr->e_lfanew;\r
1313 }\r
1314\r
1315 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset);\r
1316 if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1317 DEBUG ((DEBUG_VERBOSE, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature));\r
1318 // It might be image in SMM.\r
1319 goto Finish;\r
1320 }\r
1321\r
1322 //\r
1323 // Get SectionAlignment\r
1324 //\r
1325 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1326 SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;\r
1327 } else {\r
1328 SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;\r
1329 }\r
1330\r
1331 SetMemoryAttributesTableSectionAlignment (SectionAlignment);\r
1332 if ((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {\r
1333 DEBUG ((DEBUG_WARN, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",\r
1334 SectionAlignment, RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10));\r
1335 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);\r
1336 if (PdbPointer != NULL) {\r
1337 DEBUG ((DEBUG_WARN, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));\r
1338 }\r
1339 goto Finish;\r
1340 }\r
1341\r
1342 Section = (EFI_IMAGE_SECTION_HEADER *) (\r
1343 (UINT8 *) (UINTN) ImageAddress +\r
1344 PeCoffHeaderOffset +\r
1345 sizeof(UINT32) +\r
1346 sizeof(EFI_IMAGE_FILE_HEADER) +\r
1347 Hdr.Pe32->FileHeader.SizeOfOptionalHeader\r
1348 );\r
1349 ImageRecord->CodeSegmentCount = 0;\r
1350 InitializeListHead (&ImageRecord->CodeSegmentList);\r
1351 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {\r
1352 Name = Section[Index].Name;\r
1353 DEBUG ((\r
1354 DEBUG_VERBOSE,\r
1355 " Section - '%c%c%c%c%c%c%c%c'\n",\r
1356 Name[0],\r
1357 Name[1],\r
1358 Name[2],\r
1359 Name[3],\r
1360 Name[4],\r
1361 Name[5],\r
1362 Name[6],\r
1363 Name[7]\r
1364 ));\r
1365\r
1366 if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) {\r
1367 DEBUG ((DEBUG_VERBOSE, " VirtualSize - 0x%08x\n", Section[Index].Misc.VirtualSize));\r
1368 DEBUG ((DEBUG_VERBOSE, " VirtualAddress - 0x%08x\n", Section[Index].VirtualAddress));\r
1369 DEBUG ((DEBUG_VERBOSE, " SizeOfRawData - 0x%08x\n", Section[Index].SizeOfRawData));\r
1370 DEBUG ((DEBUG_VERBOSE, " PointerToRawData - 0x%08x\n", Section[Index].PointerToRawData));\r
1371 DEBUG ((DEBUG_VERBOSE, " PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations));\r
1372 DEBUG ((DEBUG_VERBOSE, " PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers));\r
1373 DEBUG ((DEBUG_VERBOSE, " NumberOfRelocations - 0x%08x\n", Section[Index].NumberOfRelocations));\r
1374 DEBUG ((DEBUG_VERBOSE, " NumberOfLinenumbers - 0x%08x\n", Section[Index].NumberOfLinenumbers));\r
1375 DEBUG ((DEBUG_VERBOSE, " Characteristics - 0x%08x\n", Section[Index].Characteristics));\r
1376\r
1377 //\r
1378 // Step 2: record code section\r
1379 //\r
1380 ImageRecordCodeSection = AllocatePool (sizeof(*ImageRecordCodeSection));\r
1381 if (ImageRecordCodeSection == NULL) {\r
1382 return ;\r
1383 }\r
1384 ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;\r
1385\r
1386 ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress;\r
1387 ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData;\r
1388\r
1389 DEBUG ((DEBUG_VERBOSE, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize));\r
1390\r
1391 InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);\r
1392 ImageRecord->CodeSegmentCount++;\r
1393 }\r
1394 }\r
1395\r
1396 if (ImageRecord->CodeSegmentCount == 0) {\r
1397 SetMemoryAttributesTableSectionAlignment (1);\r
1398 DEBUG ((DEBUG_ERROR, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));\r
1399 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);\r
1400 if (PdbPointer != NULL) {\r
1401 DEBUG ((DEBUG_ERROR, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));\r
1402 }\r
1403 goto Finish;\r
1404 }\r
1405\r
1406 //\r
1407 // Final\r
1408 //\r
1409 SortImageRecordCodeSection (ImageRecord);\r
1410 //\r
1411 // Check overlap all section in ImageBase/Size\r
1412 //\r
1413 if (!IsImageRecordCodeSectionValid (ImageRecord)) {\r
1414 DEBUG ((DEBUG_ERROR, "IsImageRecordCodeSectionValid - FAIL\n"));\r
1415 goto Finish;\r
1416 }\r
1417\r
1418 InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link);\r
1419 mImagePropertiesPrivateData.ImageRecordCount++;\r
1420\r
1421 if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) {\r
1422 mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;\r
1423 }\r
1424\r
1425 SortImageRecord ();\r
1426\r
1427Finish:\r
1428 return ;\r
1429}\r
1430\r
1431/**\r
1432 Find image record according to image base and size.\r
1433\r
1434 @param ImageBase Base of PE image\r
1435 @param ImageSize Size of PE image\r
1436\r
1437 @return image record\r
1438**/\r
1439STATIC\r
1440IMAGE_PROPERTIES_RECORD *\r
1441FindImageRecord (\r
1442 IN EFI_PHYSICAL_ADDRESS ImageBase,\r
1443 IN UINT64 ImageSize\r
1444 )\r
1445{\r
1446 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
1447 LIST_ENTRY *ImageRecordLink;\r
1448 LIST_ENTRY *ImageRecordList;\r
1449\r
1450 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;\r
1451\r
1452 for (ImageRecordLink = ImageRecordList->ForwardLink;\r
1453 ImageRecordLink != ImageRecordList;\r
1454 ImageRecordLink = ImageRecordLink->ForwardLink) {\r
1455 ImageRecord = CR (\r
1456 ImageRecordLink,\r
1457 IMAGE_PROPERTIES_RECORD,\r
1458 Link,\r
1459 IMAGE_PROPERTIES_RECORD_SIGNATURE\r
1460 );\r
1461\r
1462 if ((ImageBase == ImageRecord->ImageBase) &&\r
1463 (ImageSize == ImageRecord->ImageSize)) {\r
1464 return ImageRecord;\r
1465 }\r
1466 }\r
1467\r
1468 return NULL;\r
1469}\r
1470\r
1471/**\r
1472 Remove Image record.\r
1473\r
1474 @param RuntimeImage Runtime image information\r
1475**/\r
1476VOID\r
1477RemoveImageRecord (\r
1478 IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage\r
1479 )\r
1480{\r
1481 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
1482 LIST_ENTRY *CodeSegmentListHead;\r
1483 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;\r
1484\r
1485 DEBUG ((DEBUG_VERBOSE, "RemoveImageRecord - 0x%x\n", RuntimeImage));\r
1486 DEBUG ((DEBUG_VERBOSE, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize));\r
1487\r
1488 if (mMemoryAttributesTableEndOfDxe) {\r
1489 DEBUG ((DEBUG_INFO, "Do not remove runtime image record after EndOfDxe\n"));\r
1490 return ;\r
1491 }\r
1492\r
1493 ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize);\r
1494 if (ImageRecord == NULL) {\r
1495 DEBUG ((DEBUG_ERROR, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));\r
1496 return ;\r
1497 }\r
1498\r
1499 CodeSegmentListHead = &ImageRecord->CodeSegmentList;\r
1500 while (!IsListEmpty (CodeSegmentListHead)) {\r
1501 ImageRecordCodeSection = CR (\r
1502 CodeSegmentListHead->ForwardLink,\r
1503 IMAGE_PROPERTIES_RECORD_CODE_SECTION,\r
1504 Link,\r
1505 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE\r
1506 );\r
1507 RemoveEntryList (&ImageRecordCodeSection->Link);\r
1508 FreePool (ImageRecordCodeSection);\r
1509 }\r
1510\r
1511 RemoveEntryList (&ImageRecord->Link);\r
1512 FreePool (ImageRecord);\r
1513 mImagePropertiesPrivateData.ImageRecordCount--;\r
1514}\r