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