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