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