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