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