1 /** @file 2 Main SEC phase code. Transitions to PEI. 3 4 Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR> 5 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include <PiPei.h> 17 18 #include <Library/PeimEntryPoint.h> 19 #include <Library/BaseLib.h> 20 #include <Library/DebugLib.h> 21 #include <Library/BaseMemoryLib.h> 22 #include <Library/PeiServicesLib.h> 23 #include <Library/PcdLib.h> 24 #include <Library/UefiCpuLib.h> 25 #include <Library/DebugAgentLib.h> 26 #include <Library/IoLib.h> 27 #include <Library/PeCoffLib.h> 28 #include <Library/PeCoffGetEntryPointLib.h> 29 #include <Library/PeCoffExtraActionLib.h> 30 #include <Library/ExtractGuidedSectionLib.h> 31 #include <Library/LocalApicLib.h> 32 33 #include <Ppi/TemporaryRamSupport.h> 34 35 #define SEC_IDT_ENTRY_COUNT 34 36 37 typedef struct _SEC_IDT_TABLE { 38 EFI_PEI_SERVICES *PeiService; 39 IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT]; 40 } SEC_IDT_TABLE; 41 42 VOID 43 EFIAPI 44 SecStartupPhase2 ( 45 IN VOID *Context 46 ); 47 48 EFI_STATUS 49 EFIAPI 50 TemporaryRamMigration ( 51 IN CONST EFI_PEI_SERVICES **PeiServices, 52 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, 53 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, 54 IN UINTN CopySize 55 ); 56 57 // 58 // 59 // 60 EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = { 61 TemporaryRamMigration 62 }; 63 64 EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = { 65 { 66 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), 67 &gEfiTemporaryRamSupportPpiGuid, 68 &mTemporaryRamSupportPpi 69 }, 70 }; 71 72 // 73 // Template of an IDT entry pointing to 10:FFFFFFE4h. 74 // 75 IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = { 76 { // Bits 77 0xffe4, // OffsetLow 78 0x10, // Selector 79 0x0, // Reserved_0 80 IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType 81 0xffff // OffsetHigh 82 } 83 }; 84 85 /** 86 Locates the main boot firmware volume. 87 88 @param[in,out] BootFv On input, the base of the BootFv 89 On output, the decompressed main firmware volume 90 91 @retval EFI_SUCCESS The main firmware volume was located and decompressed 92 @retval EFI_NOT_FOUND The main firmware volume was not found 93 94 **/ 95 EFI_STATUS 96 FindMainFv ( 97 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv 98 ) 99 { 100 EFI_FIRMWARE_VOLUME_HEADER *Fv; 101 UINTN Distance; 102 103 ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0); 104 105 Fv = *BootFv; 106 Distance = (UINTN) (*BootFv)->FvLength; 107 do { 108 Fv = (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE); 109 Distance += EFI_PAGE_SIZE; 110 if (Distance > SIZE_32MB) { 111 return EFI_NOT_FOUND; 112 } 113 114 if (Fv->Signature != EFI_FVH_SIGNATURE) { 115 continue; 116 } 117 118 if ((UINTN) Fv->FvLength > Distance) { 119 continue; 120 } 121 122 *BootFv = Fv; 123 return EFI_SUCCESS; 124 125 } while (TRUE); 126 } 127 128 /** 129 Locates a section within a series of sections 130 with the specified section type. 131 132 The Instance parameter indicates which instance of the section 133 type to return. (0 is first instance, 1 is second...) 134 135 @param[in] Sections The sections to search 136 @param[in] SizeOfSections Total size of all sections 137 @param[in] SectionType The section type to locate 138 @param[in] Instance The section instance number 139 @param[out] FoundSection The FFS section if found 140 141 @retval EFI_SUCCESS The file and section was found 142 @retval EFI_NOT_FOUND The file and section was not found 143 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted 144 145 **/ 146 EFI_STATUS 147 FindFfsSectionInstance ( 148 IN VOID *Sections, 149 IN UINTN SizeOfSections, 150 IN EFI_SECTION_TYPE SectionType, 151 IN UINTN Instance, 152 OUT EFI_COMMON_SECTION_HEADER **FoundSection 153 ) 154 { 155 EFI_PHYSICAL_ADDRESS CurrentAddress; 156 UINT32 Size; 157 EFI_PHYSICAL_ADDRESS EndOfSections; 158 EFI_COMMON_SECTION_HEADER *Section; 159 EFI_PHYSICAL_ADDRESS EndOfSection; 160 161 // 162 // Loop through the FFS file sections within the PEI Core FFS file 163 // 164 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections; 165 EndOfSections = EndOfSection + SizeOfSections; 166 for (;;) { 167 if (EndOfSection == EndOfSections) { 168 break; 169 } 170 CurrentAddress = (EndOfSection + 3) & ~(3ULL); 171 if (CurrentAddress >= EndOfSections) { 172 return EFI_VOLUME_CORRUPTED; 173 } 174 175 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; 176 177 Size = SECTION_SIZE (Section); 178 if (Size < sizeof (*Section)) { 179 return EFI_VOLUME_CORRUPTED; 180 } 181 182 EndOfSection = CurrentAddress + Size; 183 if (EndOfSection > EndOfSections) { 184 return EFI_VOLUME_CORRUPTED; 185 } 186 187 // 188 // Look for the requested section type 189 // 190 if (Section->Type == SectionType) { 191 if (Instance == 0) { 192 *FoundSection = Section; 193 return EFI_SUCCESS; 194 } else { 195 Instance--; 196 } 197 } 198 } 199 200 return EFI_NOT_FOUND; 201 } 202 203 /** 204 Locates a section within a series of sections 205 with the specified section type. 206 207 @param[in] Sections The sections to search 208 @param[in] SizeOfSections Total size of all sections 209 @param[in] SectionType The section type to locate 210 @param[out] FoundSection The FFS section if found 211 212 @retval EFI_SUCCESS The file and section was found 213 @retval EFI_NOT_FOUND The file and section was not found 214 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted 215 216 **/ 217 EFI_STATUS 218 FindFfsSectionInSections ( 219 IN VOID *Sections, 220 IN UINTN SizeOfSections, 221 IN EFI_SECTION_TYPE SectionType, 222 OUT EFI_COMMON_SECTION_HEADER **FoundSection 223 ) 224 { 225 return FindFfsSectionInstance ( 226 Sections, 227 SizeOfSections, 228 SectionType, 229 0, 230 FoundSection 231 ); 232 } 233 234 /** 235 Locates a FFS file with the specified file type and a section 236 within that file with the specified section type. 237 238 @param[in] Fv The firmware volume to search 239 @param[in] FileType The file type to locate 240 @param[in] SectionType The section type to locate 241 @param[out] FoundSection The FFS section if found 242 243 @retval EFI_SUCCESS The file and section was found 244 @retval EFI_NOT_FOUND The file and section was not found 245 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted 246 247 **/ 248 EFI_STATUS 249 FindFfsFileAndSection ( 250 IN EFI_FIRMWARE_VOLUME_HEADER *Fv, 251 IN EFI_FV_FILETYPE FileType, 252 IN EFI_SECTION_TYPE SectionType, 253 OUT EFI_COMMON_SECTION_HEADER **FoundSection 254 ) 255 { 256 EFI_STATUS Status; 257 EFI_PHYSICAL_ADDRESS CurrentAddress; 258 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; 259 EFI_FFS_FILE_HEADER *File; 260 UINT32 Size; 261 EFI_PHYSICAL_ADDRESS EndOfFile; 262 263 if (Fv->Signature != EFI_FVH_SIGNATURE) { 264 DEBUG ((EFI_D_ERROR, "FV at %p does not have FV header signature\n", Fv)); 265 return EFI_VOLUME_CORRUPTED; 266 } 267 268 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv; 269 EndOfFirmwareVolume = CurrentAddress + Fv->FvLength; 270 271 // 272 // Loop through the FFS files in the Boot Firmware Volume 273 // 274 for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) { 275 276 CurrentAddress = (EndOfFile + 7) & ~(7ULL); 277 if (CurrentAddress > EndOfFirmwareVolume) { 278 return EFI_VOLUME_CORRUPTED; 279 } 280 281 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress; 282 Size = *(UINT32*) File->Size & 0xffffff; 283 if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) { 284 return EFI_VOLUME_CORRUPTED; 285 } 286 287 EndOfFile = CurrentAddress + Size; 288 if (EndOfFile > EndOfFirmwareVolume) { 289 return EFI_VOLUME_CORRUPTED; 290 } 291 292 // 293 // Look for the request file type 294 // 295 if (File->Type != FileType) { 296 continue; 297 } 298 299 Status = FindFfsSectionInSections ( 300 (VOID*) (File + 1), 301 (UINTN) EndOfFile - (UINTN) (File + 1), 302 SectionType, 303 FoundSection 304 ); 305 if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) { 306 return Status; 307 } 308 } 309 } 310 311 /** 312 Locates the compressed main firmware volume and decompresses it. 313 314 @param[in,out] Fv On input, the firmware volume to search 315 On output, the decompressed BOOT/PEI FV 316 317 @retval EFI_SUCCESS The file and section was found 318 @retval EFI_NOT_FOUND The file and section was not found 319 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted 320 321 **/ 322 EFI_STATUS 323 DecompressMemFvs ( 324 IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv 325 ) 326 { 327 EFI_STATUS Status; 328 EFI_GUID_DEFINED_SECTION *Section; 329 UINT32 OutputBufferSize; 330 UINT32 ScratchBufferSize; 331 UINT16 SectionAttribute; 332 UINT32 AuthenticationStatus; 333 VOID *OutputBuffer; 334 VOID *ScratchBuffer; 335 EFI_FIRMWARE_VOLUME_IMAGE_SECTION *FvSection; 336 EFI_FIRMWARE_VOLUME_HEADER *PeiMemFv; 337 EFI_FIRMWARE_VOLUME_HEADER *DxeMemFv; 338 339 FvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL; 340 341 Status = FindFfsFileAndSection ( 342 *Fv, 343 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, 344 EFI_SECTION_GUID_DEFINED, 345 (EFI_COMMON_SECTION_HEADER**) &Section 346 ); 347 if (EFI_ERROR (Status)) { 348 DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n")); 349 return Status; 350 } 351 352 Status = ExtractGuidedSectionGetInfo ( 353 Section, 354 &OutputBufferSize, 355 &ScratchBufferSize, 356 &SectionAttribute 357 ); 358 if (EFI_ERROR (Status)) { 359 DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n")); 360 return Status; 361 } 362 363 OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase) + SIZE_1MB); 364 ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB); 365 366 DEBUG ((EFI_D_VERBOSE, "%a: OutputBuffer@%p+0x%x ScratchBuffer@%p+0x%x " 367 "PcdOvmfDecompressionScratchEnd=0x%x\n", __FUNCTION__, OutputBuffer, 368 OutputBufferSize, ScratchBuffer, ScratchBufferSize, 369 PcdGet32 (PcdOvmfDecompressionScratchEnd))); 370 ASSERT ((UINTN)ScratchBuffer + ScratchBufferSize == 371 PcdGet32 (PcdOvmfDecompressionScratchEnd)); 372 373 Status = ExtractGuidedSectionDecode ( 374 Section, 375 &OutputBuffer, 376 ScratchBuffer, 377 &AuthenticationStatus 378 ); 379 if (EFI_ERROR (Status)) { 380 DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n")); 381 return Status; 382 } 383 384 Status = FindFfsSectionInstance ( 385 OutputBuffer, 386 OutputBufferSize, 387 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, 388 0, 389 (EFI_COMMON_SECTION_HEADER**) &FvSection 390 ); 391 if (EFI_ERROR (Status)) { 392 DEBUG ((EFI_D_ERROR, "Unable to find PEI FV section\n")); 393 return Status; 394 } 395 396 ASSERT (SECTION_SIZE (FvSection) == 397 (PcdGet32 (PcdOvmfPeiMemFvSize) + sizeof (*FvSection))); 398 ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE); 399 400 PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase); 401 CopyMem (PeiMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdOvmfPeiMemFvSize)); 402 403 if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) { 404 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv)); 405 CpuDeadLoop (); 406 return EFI_VOLUME_CORRUPTED; 407 } 408 409 Status = FindFfsSectionInstance ( 410 OutputBuffer, 411 OutputBufferSize, 412 EFI_SECTION_FIRMWARE_VOLUME_IMAGE, 413 1, 414 (EFI_COMMON_SECTION_HEADER**) &FvSection 415 ); 416 if (EFI_ERROR (Status)) { 417 DEBUG ((EFI_D_ERROR, "Unable to find DXE FV section\n")); 418 return Status; 419 } 420 421 ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE); 422 ASSERT (SECTION_SIZE (FvSection) == 423 (PcdGet32 (PcdOvmfDxeMemFvSize) + sizeof (*FvSection))); 424 425 DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase); 426 CopyMem (DxeMemFv, (VOID*) (FvSection + 1), PcdGet32 (PcdOvmfDxeMemFvSize)); 427 428 if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) { 429 DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv)); 430 CpuDeadLoop (); 431 return EFI_VOLUME_CORRUPTED; 432 } 433 434 *Fv = PeiMemFv; 435 return EFI_SUCCESS; 436 } 437 438 /** 439 Locates the PEI Core entry point address 440 441 @param[in] Fv The firmware volume to search 442 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image 443 444 @retval EFI_SUCCESS The file and section was found 445 @retval EFI_NOT_FOUND The file and section was not found 446 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted 447 448 **/ 449 EFI_STATUS 450 FindPeiCoreImageBaseInFv ( 451 IN EFI_FIRMWARE_VOLUME_HEADER *Fv, 452 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase 453 ) 454 { 455 EFI_STATUS Status; 456 EFI_COMMON_SECTION_HEADER *Section; 457 458 Status = FindFfsFileAndSection ( 459 Fv, 460 EFI_FV_FILETYPE_PEI_CORE, 461 EFI_SECTION_PE32, 462 &Section 463 ); 464 if (EFI_ERROR (Status)) { 465 Status = FindFfsFileAndSection ( 466 Fv, 467 EFI_FV_FILETYPE_PEI_CORE, 468 EFI_SECTION_TE, 469 &Section 470 ); 471 if (EFI_ERROR (Status)) { 472 DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n")); 473 return Status; 474 } 475 } 476 477 *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1); 478 return EFI_SUCCESS; 479 } 480 481 482 /** 483 Reads 8-bits of CMOS data. 484 485 Reads the 8-bits of CMOS data at the location specified by Index. 486 The 8-bit read value is returned. 487 488 @param Index The CMOS location to read. 489 490 @return The value read. 491 492 **/ 493 STATIC 494 UINT8 495 CmosRead8 ( 496 IN UINTN Index 497 ) 498 { 499 IoWrite8 (0x70, (UINT8) Index); 500 return IoRead8 (0x71); 501 } 502 503 504 STATIC 505 BOOLEAN 506 IsS3Resume ( 507 VOID 508 ) 509 { 510 return (CmosRead8 (0xF) == 0xFE); 511 } 512 513 514 STATIC 515 EFI_STATUS 516 GetS3ResumePeiFv ( 517 IN OUT EFI_FIRMWARE_VOLUME_HEADER **PeiFv 518 ) 519 { 520 *PeiFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdOvmfPeiMemFvBase); 521 return EFI_SUCCESS; 522 } 523 524 525 /** 526 Locates the PEI Core entry point address 527 528 @param[in,out] Fv The firmware volume to search 529 @param[out] PeiCoreEntryPoint The entry point of the PEI Core image 530 531 @retval EFI_SUCCESS The file and section was found 532 @retval EFI_NOT_FOUND The file and section was not found 533 @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted 534 535 **/ 536 VOID 537 FindPeiCoreImageBase ( 538 IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv, 539 OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase 540 ) 541 { 542 BOOLEAN S3Resume; 543 544 *PeiCoreImageBase = 0; 545 546 S3Resume = IsS3Resume (); 547 if (S3Resume && !FeaturePcdGet (PcdSmmSmramRequire)) { 548 // 549 // A malicious runtime OS may have injected something into our previously 550 // decoded PEI FV, but we don't care about that unless SMM/SMRAM is required. 551 // 552 DEBUG ((EFI_D_VERBOSE, "SEC: S3 resume\n")); 553 GetS3ResumePeiFv (BootFv); 554 } else { 555 // 556 // We're either not resuming, or resuming "securely" -- we'll decompress 557 // both PEI FV and DXE FV from pristine flash. 558 // 559 DEBUG ((EFI_D_VERBOSE, "SEC: %a\n", 560 S3Resume ? "S3 resume (with PEI decompression)" : "Normal boot")); 561 FindMainFv (BootFv); 562 563 DecompressMemFvs (BootFv); 564 } 565 566 FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase); 567 } 568 569 /** 570 Find core image base. 571 572 **/ 573 EFI_STATUS 574 FindImageBase ( 575 IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, 576 OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase 577 ) 578 { 579 EFI_PHYSICAL_ADDRESS CurrentAddress; 580 EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; 581 EFI_FFS_FILE_HEADER *File; 582 UINT32 Size; 583 EFI_PHYSICAL_ADDRESS EndOfFile; 584 EFI_COMMON_SECTION_HEADER *Section; 585 EFI_PHYSICAL_ADDRESS EndOfSection; 586 587 *SecCoreImageBase = 0; 588 589 CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr; 590 EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength; 591 592 // 593 // Loop through the FFS files in the Boot Firmware Volume 594 // 595 for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) { 596 597 CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL; 598 if (CurrentAddress > EndOfFirmwareVolume) { 599 return EFI_NOT_FOUND; 600 } 601 602 File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress; 603 Size = *(UINT32*) File->Size & 0xffffff; 604 if (Size < sizeof (*File)) { 605 return EFI_NOT_FOUND; 606 } 607 608 EndOfFile = CurrentAddress + Size; 609 if (EndOfFile > EndOfFirmwareVolume) { 610 return EFI_NOT_FOUND; 611 } 612 613 // 614 // Look for SEC Core 615 // 616 if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) { 617 continue; 618 } 619 620 // 621 // Loop through the FFS file sections within the FFS file 622 // 623 EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1); 624 for (;;) { 625 CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL; 626 Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; 627 628 Size = *(UINT32*) Section->Size & 0xffffff; 629 if (Size < sizeof (*Section)) { 630 return EFI_NOT_FOUND; 631 } 632 633 EndOfSection = CurrentAddress + Size; 634 if (EndOfSection > EndOfFile) { 635 return EFI_NOT_FOUND; 636 } 637 638 // 639 // Look for executable sections 640 // 641 if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) { 642 if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) { 643 *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1); 644 } 645 break; 646 } 647 } 648 649 // 650 // SEC Core image found 651 // 652 if (*SecCoreImageBase != 0) { 653 return EFI_SUCCESS; 654 } 655 } 656 } 657 658 /* 659 Find and return Pei Core entry point. 660 661 It also find SEC and PEI Core file debug inforamtion. It will report them if 662 remote debug is enabled. 663 664 **/ 665 VOID 666 FindAndReportEntryPoints ( 667 IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr, 668 OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint 669 ) 670 { 671 EFI_STATUS Status; 672 EFI_PHYSICAL_ADDRESS SecCoreImageBase; 673 EFI_PHYSICAL_ADDRESS PeiCoreImageBase; 674 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; 675 676 // 677 // Find SEC Core and PEI Core image base 678 // 679 Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase); 680 ASSERT_EFI_ERROR (Status); 681 682 FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase); 683 684 ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); 685 // 686 // Report SEC Core debug information when remote debug is enabled 687 // 688 ImageContext.ImageAddress = SecCoreImageBase; 689 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress); 690 PeCoffLoaderRelocateImageExtraAction (&ImageContext); 691 692 // 693 // Report PEI Core debug information when remote debug is enabled 694 // 695 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase; 696 ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress); 697 PeCoffLoaderRelocateImageExtraAction (&ImageContext); 698 699 // 700 // Find PEI Core entry point 701 // 702 Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint); 703 if (EFI_ERROR (Status)) { 704 *PeiCoreEntryPoint = 0; 705 } 706 707 return; 708 } 709 710 VOID 711 EFIAPI 712 SecCoreStartupWithStack ( 713 IN EFI_FIRMWARE_VOLUME_HEADER *BootFv, 714 IN VOID *TopOfCurrentStack 715 ) 716 { 717 EFI_SEC_PEI_HAND_OFF SecCoreData; 718 SEC_IDT_TABLE IdtTableInStack; 719 IA32_DESCRIPTOR IdtDescriptor; 720 UINT32 Index; 721 volatile UINT8 *Table; 722 723 // 724 // To ensure SMM can't be compromised on S3 resume, we must force re-init of 725 // the BaseExtractGuidedSectionLib. Since this is before library contructors 726 // are called, we must use a loop rather than SetMem. 727 // 728 Table = (UINT8*)(UINTN)FixedPcdGet64 (PcdGuidedExtractHandlerTableAddress); 729 for (Index = 0; 730 Index < FixedPcdGet32 (PcdGuidedExtractHandlerTableSize); 731 ++Index) { 732 Table[Index] = 0; 733 } 734 735 ProcessLibraryConstructorList (NULL, NULL); 736 737 DEBUG ((EFI_D_INFO, 738 "SecCoreStartupWithStack(0x%x, 0x%x)\n", 739 (UINT32)(UINTN)BootFv, 740 (UINT32)(UINTN)TopOfCurrentStack 741 )); 742 743 // 744 // Initialize floating point operating environment 745 // to be compliant with UEFI spec. 746 // 747 InitializeFloatingPointUnits (); 748 749 // 750 // Initialize IDT 751 // 752 IdtTableInStack.PeiService = NULL; 753 for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) { 754 CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate)); 755 } 756 757 IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable; 758 IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); 759 760 AsmWriteIdtr (&IdtDescriptor); 761 762 #if defined (MDE_CPU_X64) 763 // 764 // ASSERT that the Page Tables were set by the reset vector code to 765 // the address we expect. 766 // 767 ASSERT (AsmReadCr3 () == (UINTN) PcdGet32 (PcdOvmfSecPageTablesBase)); 768 #endif 769 770 // 771 // |-------------| <-- TopOfCurrentStack 772 // | Stack | 32k 773 // |-------------| 774 // | Heap | 32k 775 // |-------------| <-- SecCoreData.TemporaryRamBase 776 // 777 778 ASSERT ((UINTN) (PcdGet32 (PcdOvmfSecPeiTempRamBase) + 779 PcdGet32 (PcdOvmfSecPeiTempRamSize)) == 780 (UINTN) TopOfCurrentStack); 781 782 // 783 // Initialize SEC hand-off state 784 // 785 SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF); 786 787 SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdOvmfSecPeiTempRamSize); 788 SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize); 789 790 SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; 791 SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1; 792 793 SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize; 794 SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1; 795 796 SecCoreData.BootFirmwareVolumeBase = BootFv; 797 SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength; 798 799 // 800 // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled 801 // 802 IoWrite8 (0x21, 0xff); 803 IoWrite8 (0xA1, 0xff); 804 805 // 806 // Initialize Local APIC Timer hardware and disable Local APIC Timer 807 // interrupts before initializing the Debug Agent and the debug timer is 808 // enabled. 809 // 810 InitializeApicTimer (0, MAX_UINT32, TRUE, 5); 811 DisableApicTimerInterrupt (); 812 813 // 814 // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready. 815 // 816 InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2); 817 } 818 819 /** 820 Caller provided function to be invoked at the end of InitializeDebugAgent(). 821 822 Entry point to the C language phase of SEC. After the SEC assembly 823 code has initialized some temporary memory and set up the stack, 824 the control is transferred to this function. 825 826 @param[in] Context The first input parameter of InitializeDebugAgent(). 827 828 **/ 829 VOID 830 EFIAPI 831 SecStartupPhase2( 832 IN VOID *Context 833 ) 834 { 835 EFI_SEC_PEI_HAND_OFF *SecCoreData; 836 EFI_FIRMWARE_VOLUME_HEADER *BootFv; 837 EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint; 838 839 SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context; 840 841 // 842 // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug 843 // is enabled. 844 // 845 BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase; 846 FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint); 847 SecCoreData->BootFirmwareVolumeBase = BootFv; 848 SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength; 849 850 // 851 // Transfer the control to the PEI core 852 // 853 (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable); 854 855 // 856 // If we get here then the PEI Core returned, which is not recoverable. 857 // 858 ASSERT (FALSE); 859 CpuDeadLoop (); 860 } 861 862 EFI_STATUS 863 EFIAPI 864 TemporaryRamMigration ( 865 IN CONST EFI_PEI_SERVICES **PeiServices, 866 IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, 867 IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, 868 IN UINTN CopySize 869 ) 870 { 871 IA32_DESCRIPTOR IdtDescriptor; 872 VOID *OldHeap; 873 VOID *NewHeap; 874 VOID *OldStack; 875 VOID *NewStack; 876 DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext; 877 BOOLEAN OldStatus; 878 BASE_LIBRARY_JUMP_BUFFER JumpBuffer; 879 880 DEBUG ((EFI_D_INFO, 881 "TemporaryRamMigration(0x%Lx, 0x%Lx, 0x%Lx)\n", 882 TemporaryMemoryBase, 883 PermanentMemoryBase, 884 (UINT64)CopySize 885 )); 886 887 OldHeap = (VOID*)(UINTN)TemporaryMemoryBase; 888 NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1)); 889 890 OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1)); 891 NewStack = (VOID*)(UINTN)PermanentMemoryBase; 892 893 DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap; 894 DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack; 895 896 OldStatus = SaveAndSetDebugTimerInterrupt (FALSE); 897 InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL); 898 899 // 900 // Migrate Heap 901 // 902 CopyMem (NewHeap, OldHeap, CopySize >> 1); 903 904 // 905 // Migrate Stack 906 // 907 CopyMem (NewStack, OldStack, CopySize >> 1); 908 909 // 910 // Rebase IDT table in permanent memory 911 // 912 AsmReadIdtr (&IdtDescriptor); 913 IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack; 914 915 AsmWriteIdtr (&IdtDescriptor); 916 917 // 918 // Use SetJump()/LongJump() to switch to a new stack. 919 // 920 if (SetJump (&JumpBuffer) == 0) { 921 #if defined (MDE_CPU_IA32) 922 JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset; 923 #endif 924 #if defined (MDE_CPU_X64) 925 JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset; 926 #endif 927 LongJump (&JumpBuffer, (UINTN)-1); 928 } 929 930 SaveAndSetDebugTimerInterrupt (OldStatus); 931 932 return EFI_SUCCESS; 933 } 934 935