]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Dxe/Misc/PropertiesTable.c
MdeModulePkg/DxeCore: Not update RtCode in MemAttrTable after EndOfDxe
[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
81338070 1079 UINT16 Magic;\r
03d486b2
JY
1080\r
1081 DEBUG ((EFI_D_VERBOSE, "InsertImageRecord - 0x%x\n", RuntimeImage));\r
1082 DEBUG ((EFI_D_VERBOSE, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize));\r
1083\r
4a723ed2
JY
1084 if (mPropertiesTableEndOfDxe) {\r
1085 DEBUG ((DEBUG_INFO, "Do not insert runtime image record after EndOfDxe\n"));\r
1086 return ;\r
1087 }\r
1088\r
03d486b2
JY
1089 ImageRecord = AllocatePool (sizeof(*ImageRecord));\r
1090 if (ImageRecord == NULL) {\r
1091 return ;\r
1092 }\r
1093 ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;\r
1094\r
1095 DEBUG ((EFI_D_VERBOSE, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));\r
1096\r
1097 //\r
1098 // Step 1: record whole region\r
1099 //\r
1100 ImageRecord->ImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase;\r
1101 ImageRecord->ImageSize = RuntimeImage->ImageSize;\r
1102\r
1103 ImageAddress = RuntimeImage->ImageBase;\r
1104\r
1105 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);\r
1106 if (PdbPointer != NULL) {\r
1107 DEBUG ((EFI_D_VERBOSE, " Image - %a\n", PdbPointer));\r
1108 }\r
1109\r
1110 //\r
1111 // Check PE/COFF image\r
1112 //\r
1113 DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress;\r
1114 PeCoffHeaderOffset = 0;\r
1115 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
1116 PeCoffHeaderOffset = DosHdr->e_lfanew;\r
1117 }\r
1118\r
1119 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset);\r
1120 if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1121 DEBUG ((EFI_D_VERBOSE, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature));\r
81338070 1122 // It might be image in SMM.\r
03d486b2
JY
1123 goto Finish;\r
1124 }\r
1125\r
1126 //\r
81338070 1127 // Get SectionAlignment\r
03d486b2
JY
1128 //\r
1129 if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1130 //\r
1131 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
1132 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
1133 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
1134 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
1135 //\r
81338070 1136 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
03d486b2
JY
1137 } else {\r
1138 //\r
1139 // Get the magic value from the PE/COFF Optional Header\r
1140 //\r
81338070
JY
1141 Magic = Hdr.Pe32->OptionalHeader.Magic;\r
1142 }\r
1143 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
1144 SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;\r
1145 } else {\r
03d486b2
JY
1146 SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;\r
1147 }\r
1148\r
1149 SetPropertiesTableSectionAlignment (SectionAlignment);\r
d4731a98 1150 if ((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {\r
2495c9bf 1151 DEBUG ((EFI_D_WARN, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",\r
d4731a98 1152 SectionAlignment, RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10));\r
03d486b2
JY
1153 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);\r
1154 if (PdbPointer != NULL) {\r
2495c9bf 1155 DEBUG ((EFI_D_WARN, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));\r
03d486b2
JY
1156 }\r
1157 goto Finish;\r
1158 }\r
1159\r
1160 Section = (EFI_IMAGE_SECTION_HEADER *) (\r
1161 (UINT8 *) (UINTN) ImageAddress +\r
1162 PeCoffHeaderOffset +\r
1163 sizeof(UINT32) +\r
1164 sizeof(EFI_IMAGE_FILE_HEADER) +\r
1165 Hdr.Pe32->FileHeader.SizeOfOptionalHeader\r
1166 );\r
1167 ImageRecord->CodeSegmentCount = 0;\r
1168 InitializeListHead (&ImageRecord->CodeSegmentList);\r
1169 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {\r
1170 Name = Section[Index].Name;\r
1171 DEBUG ((\r
1172 EFI_D_VERBOSE,\r
1173 " Section - '%c%c%c%c%c%c%c%c'\n",\r
1174 Name[0],\r
1175 Name[1],\r
1176 Name[2],\r
1177 Name[3],\r
1178 Name[4],\r
1179 Name[5],\r
1180 Name[6],\r
1181 Name[7]\r
1182 ));\r
1183\r
1184 if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) {\r
1185 DEBUG ((EFI_D_VERBOSE, " VirtualSize - 0x%08x\n", Section[Index].Misc.VirtualSize));\r
1186 DEBUG ((EFI_D_VERBOSE, " VirtualAddress - 0x%08x\n", Section[Index].VirtualAddress));\r
1187 DEBUG ((EFI_D_VERBOSE, " SizeOfRawData - 0x%08x\n", Section[Index].SizeOfRawData));\r
1188 DEBUG ((EFI_D_VERBOSE, " PointerToRawData - 0x%08x\n", Section[Index].PointerToRawData));\r
1189 DEBUG ((EFI_D_VERBOSE, " PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations));\r
1190 DEBUG ((EFI_D_VERBOSE, " PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers));\r
1191 DEBUG ((EFI_D_VERBOSE, " NumberOfRelocations - 0x%08x\n", Section[Index].NumberOfRelocations));\r
1192 DEBUG ((EFI_D_VERBOSE, " NumberOfLinenumbers - 0x%08x\n", Section[Index].NumberOfLinenumbers));\r
1193 DEBUG ((EFI_D_VERBOSE, " Characteristics - 0x%08x\n", Section[Index].Characteristics));\r
1194\r
1195 //\r
1196 // Step 2: record code section\r
1197 //\r
1198 ImageRecordCodeSection = AllocatePool (sizeof(*ImageRecordCodeSection));\r
1199 if (ImageRecordCodeSection == NULL) {\r
1200 return ;\r
1201 }\r
1202 ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;\r
1203\r
1204 ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress;\r
1205 ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData;\r
1206\r
1207 DEBUG ((EFI_D_VERBOSE, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize));\r
1208\r
1209 InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);\r
1210 ImageRecord->CodeSegmentCount++;\r
1211 }\r
1212 }\r
1213\r
1214 if (ImageRecord->CodeSegmentCount == 0) {\r
1215 SetPropertiesTableSectionAlignment (1);\r
1216 DEBUG ((EFI_D_ERROR, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));\r
1217 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);\r
1218 if (PdbPointer != NULL) {\r
1219 DEBUG ((EFI_D_ERROR, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));\r
1220 }\r
1221 goto Finish;\r
1222 }\r
1223\r
1224 //\r
1225 // Final\r
1226 //\r
1227 SortImageRecordCodeSection (ImageRecord);\r
1228 //\r
1229 // Check overlap all section in ImageBase/Size\r
1230 //\r
1231 if (!IsImageRecordCodeSectionValid (ImageRecord)) {\r
1232 DEBUG ((EFI_D_ERROR, "IsImageRecordCodeSectionValid - FAIL\n"));\r
1233 goto Finish;\r
1234 }\r
1235\r
1236 InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link);\r
1237 mImagePropertiesPrivateData.ImageRecordCount++;\r
1238\r
03d486b2
JY
1239 if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) {\r
1240 mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;\r
1241 }\r
1242\r
3d817fd1
JW
1243 SortImageRecord ();\r
1244\r
03d486b2
JY
1245Finish:\r
1246 return ;\r
1247}\r
1248\r
1249/**\r
ab91c9a8 1250 Find image record according to image base and size.\r
03d486b2
JY
1251\r
1252 @param ImageBase Base of PE image\r
1253 @param ImageSize Size of PE image\r
1254\r
1255 @return image record\r
1256**/\r
2caab142 1257STATIC\r
03d486b2
JY
1258IMAGE_PROPERTIES_RECORD *\r
1259FindImageRecord (\r
1260 IN EFI_PHYSICAL_ADDRESS ImageBase,\r
1261 IN UINT64 ImageSize\r
1262 )\r
1263{\r
1264 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
1265 LIST_ENTRY *ImageRecordLink;\r
1266 LIST_ENTRY *ImageRecordList;\r
1267\r
1268 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;\r
1269\r
1270 for (ImageRecordLink = ImageRecordList->ForwardLink;\r
1271 ImageRecordLink != ImageRecordList;\r
1272 ImageRecordLink = ImageRecordLink->ForwardLink) {\r
1273 ImageRecord = CR (\r
1274 ImageRecordLink,\r
1275 IMAGE_PROPERTIES_RECORD,\r
1276 Link,\r
1277 IMAGE_PROPERTIES_RECORD_SIGNATURE\r
1278 );\r
1279\r
1280 if ((ImageBase == ImageRecord->ImageBase) &&\r
1281 (ImageSize == ImageRecord->ImageSize)) {\r
1282 return ImageRecord;\r
1283 }\r
1284 }\r
1285\r
1286 return NULL;\r
1287}\r
1288\r
1289/**\r
1290 Remove Image record.\r
1291\r
1292 @param RuntimeImage Runtime image information\r
1293**/\r
1294VOID\r
1295RemoveImageRecord (\r
1296 IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage\r
1297 )\r
1298{\r
1299 IMAGE_PROPERTIES_RECORD *ImageRecord;\r
1300 LIST_ENTRY *CodeSegmentListHead;\r
1301 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;\r
1302\r
1303 DEBUG ((EFI_D_VERBOSE, "RemoveImageRecord - 0x%x\n", RuntimeImage));\r
1304 DEBUG ((EFI_D_VERBOSE, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize));\r
1305\r
4a723ed2
JY
1306 if (mPropertiesTableEndOfDxe) {\r
1307 DEBUG ((DEBUG_INFO, "Do not remove runtime image record after EndOfDxe\n"));\r
1308 return ;\r
1309 }\r
1310\r
03d486b2
JY
1311 ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize);\r
1312 if (ImageRecord == NULL) {\r
1313 DEBUG ((EFI_D_ERROR, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));\r
1314 return ;\r
1315 }\r
1316\r
1317 CodeSegmentListHead = &ImageRecord->CodeSegmentList;\r
1318 while (!IsListEmpty (CodeSegmentListHead)) {\r
1319 ImageRecordCodeSection = CR (\r
1320 CodeSegmentListHead->ForwardLink,\r
1321 IMAGE_PROPERTIES_RECORD_CODE_SECTION,\r
1322 Link,\r
1323 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE\r
1324 );\r
1325 RemoveEntryList (&ImageRecordCodeSection->Link);\r
1326 FreePool (ImageRecordCodeSection);\r
1327 }\r
1328\r
1329 RemoveEntryList (&ImageRecord->Link);\r
1330 FreePool (ImageRecord);\r
1331 mImagePropertiesPrivateData.ImageRecordCount--;\r
1332}\r
1333\r
1334\r
1335/**\r
1336 Install PropertiesTable.\r
1337\r
1338 @param[in] Event The Event this notify function registered to.\r
1339 @param[in] Context Pointer to the context data registered to the Event.\r
1340**/\r
1341VOID\r
1342EFIAPI\r
1343InstallPropertiesTable (\r
1344 EFI_EVENT Event,\r
1345 VOID *Context\r
1346 )\r
1347{\r
4a723ed2 1348 mPropertiesTableEndOfDxe = TRUE;\r
bc31c0c6 1349 if (PcdGetBool (PcdPropertiesTableEnable)) {\r
03d486b2
JY
1350 EFI_STATUS Status;\r
1351\r
1352 Status = gBS->InstallConfigurationTable (&gEfiPropertiesTableGuid, &mPropertiesTable);\r
1353 ASSERT_EFI_ERROR (Status);\r
1354\r
1355 DEBUG ((EFI_D_INFO, "MemoryProtectionAttribute - 0x%016lx\n", mPropertiesTable.MemoryProtectionAttribute));\r
1356 if ((mPropertiesTable.MemoryProtectionAttribute & EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {\r
2495c9bf 1357 DEBUG ((EFI_D_ERROR, "MemoryProtectionAttribute NON_EXECUTABLE_PE_DATA is not set, "));\r
d4731a98 1358 DEBUG ((EFI_D_ERROR, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY >> 10));\r
03d486b2
JY
1359 return ;\r
1360 }\r
1361\r
0ab90add 1362 gBS->GetMemoryMap = CoreGetMemoryMapWithSeparatedImageSection;\r
03d486b2
JY
1363 gBS->Hdr.CRC32 = 0;\r
1364 gBS->CalculateCrc32 ((UINT8 *)gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);\r
1365\r
1366 DEBUG ((EFI_D_VERBOSE, "Total Image Count - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));\r
1367 DEBUG ((EFI_D_VERBOSE, "Dump ImageRecord:\n"));\r
1368 DumpImageRecord ();\r
82f0f411
JY
1369\r
1370 mPropertiesTableEnable = TRUE;\r
03d486b2
JY
1371 }\r
1372}\r
1373\r
1374/**\r
1375 Initialize PropertiesTable support.\r
1376**/\r
1377VOID\r
1378EFIAPI\r
1379CoreInitializePropertiesTable (\r
1380 VOID\r
1381 )\r
1382{\r
1383 EFI_STATUS Status;\r
1384 EFI_EVENT EndOfDxeEvent;\r
1385\r
1386 Status = gBS->CreateEventEx (\r
1387 EVT_NOTIFY_SIGNAL,\r
1388 TPL_NOTIFY,\r
1389 InstallPropertiesTable,\r
1390 NULL,\r
1391 &gEfiEndOfDxeEventGroupGuid,\r
1392 &EndOfDxeEvent\r
1393 );\r
1394 ASSERT_EFI_ERROR (Status);\r
1395 return ;\r
1396}\r