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