]> git.proxmox.com Git - mirror_edk2.git/blame - 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
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
1436aea4 70#define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')\r
aab6a9c9
AB
71\r
72typedef struct {\r
1436aea4
MK
73 UINT32 Signature;\r
74 UINTN ImageRecordCount;\r
75 UINTN CodeSegmentCountMax;\r
76 LIST_ENTRY ImageRecordList;\r
aab6a9c9
AB
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
1436aea4 86STATIC EFI_LOCK mMemoryAttributesTableLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
aab6a9c9 87\r
1436aea4
MK
88BOOLEAN mMemoryAttributesTableEnable = TRUE;\r
89BOOLEAN mMemoryAttributesTableEndOfDxe = FALSE;\r
90EFI_MEMORY_ATTRIBUTES_TABLE *mMemoryAttributesTable = NULL;\r
74a88770 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
1436aea4
MK
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
98c4b005 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
87000d77 123 DEBUG ((DEBUG_VERBOSE, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10));\r
1436aea4 124 return;\r
98c4b005
JY
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
1436aea4 133 Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID *)(UINTN)MAX_ADDRESS);\r
74a88770
SZ
134 ASSERT_EFI_ERROR (Status);\r
135 }\r
136\r
98c4b005 137 MemoryMapSize = 0;\r
1436aea4
MK
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
98c4b005
JY
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
1436aea4 164 MemoryMapStart = MemoryMap;\r
98c4b005
JY
165 RuntimeEntryCount = 0;\r
166 for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {\r
167 switch (MemoryMap->Type) {\r
1436aea4
MK
168 case EfiRuntimeServicesCode:\r
169 case EfiRuntimeServicesData:\r
170 RuntimeEntryCount++;\r
171 break;\r
98c4b005 172 }\r
1436aea4
MK
173\r
174 MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);\r
98c4b005
JY
175 }\r
176\r
177 //\r
178 // Allocate MemoryAttributesTable\r
179 //\r
1436aea4 180 MemoryAttributesTable = AllocatePool (sizeof (EFI_MEMORY_ATTRIBUTES_TABLE) + DescriptorSize * RuntimeEntryCount);\r
98c4b005
JY
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
87000d77
MK
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
98c4b005 190 MemoryAttributesEntry = (EFI_MEMORY_DESCRIPTOR *)(MemoryAttributesTable + 1);\r
1436aea4 191 MemoryMap = MemoryMapStart;\r
98c4b005
JY
192 for (Index = 0; Index < MemoryMapSize/DescriptorSize; Index++) {\r
193 switch (MemoryMap->Type) {\r
1436aea4
MK
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
98c4b005 206 }\r
1436aea4
MK
207\r
208 MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, DescriptorSize);\r
98c4b005 209 }\r
1436aea4 210\r
2bfac751
SZ
211 MemoryMap = MemoryMapStart;\r
212 FreePool (MemoryMap);\r
98c4b005 213\r
74a88770
SZ
214 //\r
215 // Update configuratoin table for MemoryAttributesTable.\r
216 //\r
98c4b005
JY
217 Status = gBS->InstallConfigurationTable (&gEfiMemoryAttributesTableGuid, MemoryAttributesTable);\r
218 ASSERT_EFI_ERROR (Status);\r
74a88770
SZ
219\r
220 if (mMemoryAttributesTable != NULL) {\r
221 FreePool (mMemoryAttributesTable);\r
222 }\r
1436aea4 223\r
d1102dba 224 mMemoryAttributesTable = MemoryAttributesTable;\r
74a88770
SZ
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
1436aea4 234 IN EFI_MEMORY_TYPE MemoryType\r
74a88770
SZ
235 )\r
236{\r
237 //\r
238 // Install MemoryAttributesTable after ReadyToBoot on runtime memory allocation.\r
239 //\r
240 if (mMemoryAttributesTableReadyToBoot &&\r
1436aea4
MK
241 ((MemoryType == EfiRuntimeServicesCode) || (MemoryType == EfiRuntimeServicesData)))\r
242 {\r
74a88770
SZ
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
1436aea4
MK
256 IN EFI_EVENT Event,\r
257 IN VOID *Context\r
74a88770
SZ
258 )\r
259{\r
260 InstallMemoryAttributesTable ();\r
d1102dba 261 mMemoryAttributesTableReadyToBoot = TRUE;\r
98c4b005
JY
262}\r
263\r
b2305dd2
JY
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
1436aea4
MK
274 IN EFI_EVENT Event,\r
275 IN VOID *Context\r
b2305dd2
JY
276 )\r
277{\r
aab6a9c9 278 mMemoryAttributesTableEndOfDxe = TRUE;\r
b2305dd2
JY
279 InstallMemoryAttributesTable ();\r
280}\r
281\r
98c4b005
JY
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
b2305dd2 293 EFI_EVENT EndOfDxeEvent;\r
98c4b005
JY
294\r
295 //\r
74a88770 296 // Construct the table at ReadyToBoot.\r
98c4b005 297 //\r
74a88770
SZ
298 Status = CoreCreateEventInternal (\r
299 EVT_NOTIFY_SIGNAL,\r
b2305dd2 300 TPL_CALLBACK,\r
74a88770
SZ
301 InstallMemoryAttributesTableOnReadyToBoot,\r
302 NULL,\r
303 &gEfiEventReadyToBootGuid,\r
304 &ReadyToBootEvent\r
305 );\r
98c4b005 306 ASSERT_EFI_ERROR (Status);\r
b2305dd2
JY
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
1436aea4 323 return;\r
98c4b005 324}\r
aab6a9c9
AB
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
1436aea4 343 IN UINT64 Pages\r
aab6a9c9
AB
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
1436aea4 363 IN UINT64 Size\r
aab6a9c9
AB
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
1436aea4
MK
409 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;\r
410 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;\r
411 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;\r
412 EFI_MEMORY_DESCRIPTOR TempMemoryMap;\r
aab6a9c9 413\r
1436aea4 414 MemoryMapEntry = MemoryMap;\r
aab6a9c9 415 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
1436aea4 416 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);\r
aab6a9c9
AB
417 while (MemoryMapEntry < MemoryMapEnd) {\r
418 while (NextMemoryMapEntry < MemoryMapEnd) {\r
419 if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {\r
1436aea4
MK
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
aab6a9c9
AB
423 }\r
424\r
425 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);\r
426 }\r
427\r
1436aea4
MK
428 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
429 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
aab6a9c9
AB
430 }\r
431\r
1436aea4 432 return;\r
aab6a9c9
AB
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
1436aea4
MK
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
aab6a9c9 458\r
1436aea4 459 MemoryMapEntry = MemoryMap;\r
aab6a9c9 460 NewMemoryMapEntry = MemoryMap;\r
1436aea4 461 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + *MemoryMapSize);\r
aab6a9c9 462 while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {\r
1436aea4 463 CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));\r
aab6a9c9
AB
464 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
465\r
466 do {\r
467 MergeGuardPages (NewMemoryMapEntry, NextMemoryMapEntry->PhysicalStart);\r
1436aea4 468 MemoryBlockLength = (UINT64)(EfiPagesToSize (NewMemoryMapEntry->NumberOfPages));\r
aab6a9c9
AB
469 if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&\r
470 (NewMemoryMapEntry->Type == NextMemoryMapEntry->Type) &&\r
471 (NewMemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) &&\r
1436aea4
MK
472 ((NewMemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart))\r
473 {\r
aab6a9c9 474 NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;\r
1436aea4 475 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);\r
aab6a9c9
AB
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
1436aea4 483 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
aab6a9c9
AB
484 NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);\r
485 }\r
486\r
487 *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;\r
488\r
1436aea4 489 return;\r
aab6a9c9
AB
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
1436aea4
MK
509 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;\r
510 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;\r
aab6a9c9
AB
511\r
512 MemoryMapEntry = MemoryMap;\r
1436aea4 513 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);\r
aab6a9c9
AB
514 while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {\r
515 switch (MemoryMapEntry->Type) {\r
1436aea4
MK
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
aab6a9c9
AB
527 }\r
528\r
529 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);\r
530 }\r
531\r
1436aea4 532 return;\r
aab6a9c9
AB
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
1436aea4
MK
550 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
551 LIST_ENTRY *ImageRecordLink;\r
552 LIST_ENTRY *ImageRecordList;\r
aab6a9c9
AB
553\r
554 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;\r
555\r
556 for (ImageRecordLink = ImageRecordList->ForwardLink;\r
557 ImageRecordLink != ImageRecordList;\r
1436aea4
MK
558 ImageRecordLink = ImageRecordLink->ForwardLink)\r
559 {\r
aab6a9c9
AB
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
1436aea4
MK
568 (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize))\r
569 {\r
aab6a9c9
AB
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
1436aea4
MK
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
aab6a9c9
AB
597 )\r
598{\r
1436aea4
MK
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
aab6a9c9
AB
610 NewRecordCount = 0;\r
611\r
612 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;\r
613\r
1436aea4 614 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;\r
aab6a9c9
AB
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
1436aea4 632 NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart);\r
aab6a9c9
AB
633 NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;\r
634 if (NewRecord->NumberOfPages != 0) {\r
635 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
1436aea4 636 NewRecordCount++;\r
aab6a9c9
AB
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
1436aea4 645 NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize);\r
aab6a9c9
AB
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
1436aea4 649 NewRecordCount++;\r
aab6a9c9
AB
650 }\r
651\r
1436aea4
MK
652 TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize));\r
653 TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - TempRecord.PhysicalStart);\r
aab6a9c9
AB
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
1436aea4 671 NewRecordCount++;\r
aab6a9c9
AB
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
1436aea4 689 IN EFI_MEMORY_DESCRIPTOR *OldRecord\r
aab6a9c9
AB
690 )\r
691{\r
1436aea4
MK
692 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
693 UINTN SplitRecordCount;\r
694 UINT64 PhysicalStart;\r
695 UINT64 PhysicalEnd;\r
aab6a9c9
AB
696\r
697 SplitRecordCount = 0;\r
1436aea4
MK
698 PhysicalStart = OldRecord->PhysicalStart;\r
699 PhysicalEnd = OldRecord->PhysicalStart + EfiPagesToSize (OldRecord->NumberOfPages);\r
aab6a9c9
AB
700\r
701 do {\r
702 ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);\r
703 if (ImageRecord == NULL) {\r
704 break;\r
705 }\r
1436aea4 706\r
aab6a9c9 707 SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1);\r
1436aea4 708 PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;\r
aab6a9c9
AB
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
1436aea4
MK
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
aab6a9c9
AB
740 )\r
741{\r
1436aea4
MK
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
aab6a9c9
AB
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
1436aea4 761 CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR));\r
aab6a9c9 762 PhysicalStart = TempRecord.PhysicalStart;\r
1436aea4 763 PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages);\r
aab6a9c9
AB
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
1436aea4 776 NewRecord = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
aab6a9c9
AB
777 IsLastRecordData = FALSE;\r
778 if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) {\r
779 IsLastRecordData = TRUE;\r
780 }\r
1436aea4 781\r
aab6a9c9
AB
782 if (IsLastRecordData) {\r
783 //\r
784 // Last record is DATA, just merge it.\r
785 //\r
1436aea4 786 NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - NewRecord->PhysicalStart);\r
aab6a9c9
AB
787 } else {\r
788 //\r
789 // Last record is CODE, create a new DATA entry.\r
790 //\r
1436aea4 791 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);\r
aab6a9c9
AB
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
1436aea4 797 TotalNewRecordCount++;\r
aab6a9c9
AB
798 }\r
799 }\r
1436aea4 800\r
aab6a9c9
AB
801 break;\r
802 }\r
1436aea4 803\r
aab6a9c9
AB
804 ImageRecord = NewImageRecord;\r
805\r
806 //\r
807 // Set new record\r
808 //\r
1436aea4 809 NewRecordCount = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize);\r
aab6a9c9 810 TotalNewRecordCount += NewRecordCount;\r
1436aea4 811 NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize);\r
aab6a9c9
AB
812\r
813 //\r
814 // Update PhysicalStart, in order to exclude the image buffer already splitted.\r
815 //\r
1436aea4 816 PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;\r
aab6a9c9
AB
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
1436aea4
MK
883 INTN IndexOld;\r
884 INTN IndexNew;\r
885 UINTN MaxSplitRecordCount;\r
886 UINTN RealSplitRecordCount;\r
887 UINTN TotalSplitRecordCount;\r
888 UINTN AdditionalRecordCount;\r
aab6a9c9
AB
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
1436aea4 901 for ( ; IndexOld >= 0; IndexOld--) {\r
aab6a9c9
AB
902 MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize));\r
903 //\r
904 // Split this MemoryMap record\r
905 //\r
1436aea4 906 IndexNew -= MaxSplitRecordCount;\r
aab6a9c9
AB
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
1436aea4 921 IndexNew = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;\r
aab6a9c9 922 TotalSplitRecordCount += RealSplitRecordCount;\r
1436aea4 923 IndexNew--;\r
aab6a9c9 924 }\r
1436aea4 925\r
aab6a9c9
AB
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
1436aea4 952 return;\r
aab6a9c9
AB
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
1436aea4 1017 Status = CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);\r
aab6a9c9
AB
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
1436aea4
MK
1056 mMemoryAttributesTableEnable)\r
1057 {\r
aab6a9c9
AB
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
1436aea4
MK
1072 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *FirstImageRecordCodeSection,\r
1073 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *SecondImageRecordCodeSection\r
aab6a9c9
AB
1074 )\r
1075{\r
1436aea4 1076 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection;\r
aab6a9c9
AB
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
1436aea4 1095 IN IMAGE_PROPERTIES_RECORD *ImageRecord\r
aab6a9c9
AB
1096 )\r
1097{\r
1436aea4
MK
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
aab6a9c9
AB
1104\r
1105 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;\r
1106\r
1436aea4 1107 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;\r
aab6a9c9 1108 NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;\r
1436aea4 1109 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;\r
aab6a9c9
AB
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
1436aea4 1127\r
aab6a9c9
AB
1128 NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;\r
1129 }\r
1130\r
1436aea4 1131 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;\r
aab6a9c9
AB
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
1436aea4 1146 IN IMAGE_PROPERTIES_RECORD *ImageRecord\r
aab6a9c9
AB
1147 )\r
1148{\r
1436aea4
MK
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
aab6a9c9
AB
1154\r
1155 DEBUG ((DEBUG_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));\r
1156\r
1157 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;\r
1158\r
1436aea4 1159 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;\r
aab6a9c9 1160 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;\r
1436aea4 1161 LastImageRecordCodeSection = NULL;\r
aab6a9c9
AB
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
1436aea4 1172\r
aab6a9c9
AB
1173 if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) {\r
1174 return FALSE;\r
1175 }\r
1436aea4 1176\r
aab6a9c9
AB
1177 if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) {\r
1178 return FALSE;\r
1179 }\r
1436aea4 1180\r
aab6a9c9
AB
1181 if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) {\r
1182 return FALSE;\r
1183 }\r
1436aea4 1184\r
aab6a9c9
AB
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
1436aea4
MK
1207 IN IMAGE_PROPERTIES_RECORD *FirstImageRecord,\r
1208 IN IMAGE_PROPERTIES_RECORD *SecondImageRecord\r
aab6a9c9
AB
1209 )\r
1210{\r
1436aea4 1211 IMAGE_PROPERTIES_RECORD TempImageRecord;\r
aab6a9c9 1212\r
1436aea4
MK
1213 TempImageRecord.ImageBase = FirstImageRecord->ImageBase;\r
1214 TempImageRecord.ImageSize = FirstImageRecord->ImageSize;\r
aab6a9c9
AB
1215 TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;\r
1216\r
1436aea4
MK
1217 FirstImageRecord->ImageBase = SecondImageRecord->ImageBase;\r
1218 FirstImageRecord->ImageSize = SecondImageRecord->ImageSize;\r
aab6a9c9
AB
1219 FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount;\r
1220\r
1436aea4
MK
1221 SecondImageRecord->ImageBase = TempImageRecord.ImageBase;\r
1222 SecondImageRecord->ImageSize = TempImageRecord.ImageSize;\r
aab6a9c9
AB
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
1436aea4
MK
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
aab6a9c9
AB
1243\r
1244 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;\r
1245\r
1436aea4 1246 ImageRecordLink = ImageRecordList->ForwardLink;\r
aab6a9c9 1247 NextImageRecordLink = ImageRecordLink->ForwardLink;\r
1436aea4 1248 ImageRecordEndLink = ImageRecordList;\r
aab6a9c9
AB
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
1436aea4 1266\r
aab6a9c9
AB
1267 NextImageRecordLink = NextImageRecordLink->ForwardLink;\r
1268 }\r
1269\r
1436aea4 1270 ImageRecordLink = ImageRecordLink->ForwardLink;\r
aab6a9c9
AB
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
1436aea4
MK
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
aab6a9c9
AB
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
1436aea4 1302 return;\r
aab6a9c9
AB
1303 }\r
1304\r
1436aea4 1305 ImageRecord = AllocatePool (sizeof (*ImageRecord));\r
aab6a9c9 1306 if (ImageRecord == NULL) {\r
1436aea4 1307 return;\r
aab6a9c9 1308 }\r
1436aea4 1309\r
aab6a9c9
AB
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
1436aea4 1322 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);\r
aab6a9c9
AB
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
1436aea4 1330 DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageAddress;\r
aab6a9c9
AB
1331 PeCoffHeaderOffset = 0;\r
1332 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
1333 PeCoffHeaderOffset = DosHdr->e_lfanew;\r
1334 }\r
1335\r
1436aea4 1336 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageAddress + PeCoffHeaderOffset);\r
aab6a9c9
AB
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
1436aea4 1347 SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;\r
aab6a9c9 1348 } else {\r
1436aea4 1349 SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;\r
aab6a9c9
AB
1350 }\r
1351\r
1352 SetMemoryAttributesTableSectionAlignment (SectionAlignment);\r
1353 if ((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {\r
1436aea4
MK
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
aab6a9c9
AB
1361 if (PdbPointer != NULL) {\r
1362 DEBUG ((DEBUG_WARN, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));\r
1363 }\r
1436aea4 1364\r
aab6a9c9
AB
1365 goto Finish;\r
1366 }\r
1367\r
1436aea4
MK
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
aab6a9c9
AB
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
1436aea4 1406 ImageRecordCodeSection = AllocatePool (sizeof (*ImageRecordCodeSection));\r
aab6a9c9 1407 if (ImageRecordCodeSection == NULL) {\r
1436aea4 1408 return;\r
aab6a9c9 1409 }\r
1436aea4 1410\r
aab6a9c9
AB
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
1436aea4 1426 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageAddress);\r
aab6a9c9
AB
1427 if (PdbPointer != NULL) {\r
1428 DEBUG ((DEBUG_ERROR, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));\r
1429 }\r
1436aea4 1430\r
aab6a9c9
AB
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
1436aea4 1456 return;\r
aab6a9c9
AB
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
1436aea4
MK
1474 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
1475 LIST_ENTRY *ImageRecordLink;\r
1476 LIST_ENTRY *ImageRecordList;\r
aab6a9c9
AB
1477\r
1478 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;\r
1479\r
1480 for (ImageRecordLink = ImageRecordList->ForwardLink;\r
1481 ImageRecordLink != ImageRecordList;\r
1436aea4
MK
1482 ImageRecordLink = ImageRecordLink->ForwardLink)\r
1483 {\r
aab6a9c9
AB
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
1436aea4
MK
1492 (ImageSize == ImageRecord->ImageSize))\r
1493 {\r
aab6a9c9
AB
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
1436aea4
MK
1511 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
1512 LIST_ENTRY *CodeSegmentListHead;\r
1513 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;\r
aab6a9c9
AB
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
1436aea4 1520 return;\r
aab6a9c9
AB
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
1436aea4 1526 return;\r
aab6a9c9
AB
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