1 /**@file 2 Platform PEI driver 3 4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR> 5 Copyright (c) 2011, Andrei Warkentin <andreiw (at) motorola.com> 6 7 This program and the accompanying materials 8 are licensed and made available under the terms and conditions of the BSD License 9 which accompanies this distribution. The full text of the license may be found at 10 http://opensource.org/licenses/bsd-license.php 11 12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 14 15 **/ 16 17 // 18 // The package level header files this module uses 19 // 20 #include <PiPei.h> 21 22 // 23 // The Library classes this module consumes 24 // 25 #include <Library/BaseLib.h> 26 #include <Library/DebugLib.h> 27 #include <Library/HobLib.h> 28 #include <Library/IoLib.h> 29 #include <Library/MemoryAllocationLib.h> 30 #include <Library/PcdLib.h> 31 #include <Library/PciLib.h> 32 #include <Library/PeimEntryPoint.h> 33 #include <Library/PeiServicesLib.h> 34 #include <Library/QemuFwCfgLib.h> 35 #include <Library/ResourcePublicationLib.h> 36 #include <Guid/MemoryTypeInformation.h> 37 #include <Ppi/MasterBootMode.h> 38 #include <IndustryStandard/Pci22.h> 39 #include <OvmfPlatforms.h> 40 41 #include "Platform.h" 42 #include "Cmos.h" 43 44 EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = { 45 { EfiACPIMemoryNVS, 0x004 }, 46 { EfiACPIReclaimMemory, 0x008 }, 47 { EfiReservedMemoryType, 0x004 }, 48 { EfiRuntimeServicesData, 0x024 }, 49 { EfiRuntimeServicesCode, 0x030 }, 50 { EfiBootServicesCode, 0x180 }, 51 { EfiBootServicesData, 0xF00 }, 52 { EfiMaxMemoryType, 0x000 } 53 }; 54 55 56 EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = { 57 { 58 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, 59 &gEfiPeiMasterBootModePpiGuid, 60 NULL 61 } 62 }; 63 64 65 UINT16 mHostBridgeDevId; 66 67 EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION; 68 69 BOOLEAN mS3Supported = FALSE; 70 71 UINT32 mMaxCpuCount; 72 73 VOID 74 AddIoMemoryBaseSizeHob ( 75 EFI_PHYSICAL_ADDRESS MemoryBase, 76 UINT64 MemorySize 77 ) 78 { 79 BuildResourceDescriptorHob ( 80 EFI_RESOURCE_MEMORY_MAPPED_IO, 81 EFI_RESOURCE_ATTRIBUTE_PRESENT | 82 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | 83 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | 84 EFI_RESOURCE_ATTRIBUTE_TESTED, 85 MemoryBase, 86 MemorySize 87 ); 88 } 89 90 VOID 91 AddReservedMemoryBaseSizeHob ( 92 EFI_PHYSICAL_ADDRESS MemoryBase, 93 UINT64 MemorySize, 94 BOOLEAN Cacheable 95 ) 96 { 97 BuildResourceDescriptorHob ( 98 EFI_RESOURCE_MEMORY_RESERVED, 99 EFI_RESOURCE_ATTRIBUTE_PRESENT | 100 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | 101 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | 102 (Cacheable ? 103 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | 104 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | 105 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE : 106 0 107 ) | 108 EFI_RESOURCE_ATTRIBUTE_TESTED, 109 MemoryBase, 110 MemorySize 111 ); 112 } 113 114 VOID 115 AddIoMemoryRangeHob ( 116 EFI_PHYSICAL_ADDRESS MemoryBase, 117 EFI_PHYSICAL_ADDRESS MemoryLimit 118 ) 119 { 120 AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase)); 121 } 122 123 124 VOID 125 AddMemoryBaseSizeHob ( 126 EFI_PHYSICAL_ADDRESS MemoryBase, 127 UINT64 MemorySize 128 ) 129 { 130 BuildResourceDescriptorHob ( 131 EFI_RESOURCE_SYSTEM_MEMORY, 132 EFI_RESOURCE_ATTRIBUTE_PRESENT | 133 EFI_RESOURCE_ATTRIBUTE_INITIALIZED | 134 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | 135 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | 136 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | 137 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | 138 EFI_RESOURCE_ATTRIBUTE_TESTED, 139 MemoryBase, 140 MemorySize 141 ); 142 } 143 144 145 VOID 146 AddMemoryRangeHob ( 147 EFI_PHYSICAL_ADDRESS MemoryBase, 148 EFI_PHYSICAL_ADDRESS MemoryLimit 149 ) 150 { 151 AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase)); 152 } 153 154 155 VOID 156 MemMapInitialization ( 157 VOID 158 ) 159 { 160 UINT64 PciIoBase; 161 UINT64 PciIoSize; 162 RETURN_STATUS PcdStatus; 163 164 PciIoBase = 0xC000; 165 PciIoSize = 0x4000; 166 167 // 168 // Create Memory Type Information HOB 169 // 170 BuildGuidDataHob ( 171 &gEfiMemoryTypeInformationGuid, 172 mDefaultMemoryTypeInformation, 173 sizeof(mDefaultMemoryTypeInformation) 174 ); 175 176 // 177 // Video memory + Legacy BIOS region 178 // 179 AddIoMemoryRangeHob (0x0A0000, BASE_1MB); 180 181 if (!mXen) { 182 UINT32 TopOfLowRam; 183 UINT64 PciExBarBase; 184 UINT32 PciBase; 185 UINT32 PciSize; 186 187 TopOfLowRam = GetSystemMemorySizeBelow4gb (); 188 PciExBarBase = 0; 189 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) { 190 // 191 // The MMCONFIG area is expected to fall between the top of low RAM and 192 // the base of the 32-bit PCI host aperture. 193 // 194 PciExBarBase = FixedPcdGet64 (PcdPciExpressBaseAddress); 195 ASSERT (TopOfLowRam <= PciExBarBase); 196 ASSERT (PciExBarBase <= MAX_UINT32 - SIZE_256MB); 197 PciBase = (UINT32)(PciExBarBase + SIZE_256MB); 198 } else { 199 PciBase = (TopOfLowRam < BASE_2GB) ? BASE_2GB : TopOfLowRam; 200 } 201 202 // 203 // address purpose size 204 // ------------ -------- ------------------------- 205 // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g) 206 // 0xFC000000 gap 44 MB 207 // 0xFEC00000 IO-APIC 4 KB 208 // 0xFEC01000 gap 1020 KB 209 // 0xFED00000 HPET 1 KB 210 // 0xFED00400 gap 111 KB 211 // 0xFED1C000 gap (PIIX4) / RCRB (ICH9) 16 KB 212 // 0xFED20000 gap 896 KB 213 // 0xFEE00000 LAPIC 1 MB 214 // 215 PciSize = 0xFC000000 - PciBase; 216 AddIoMemoryBaseSizeHob (PciBase, PciSize); 217 PcdStatus = PcdSet64S (PcdPciMmio32Base, PciBase); 218 ASSERT_RETURN_ERROR (PcdStatus); 219 PcdStatus = PcdSet64S (PcdPciMmio32Size, PciSize); 220 ASSERT_RETURN_ERROR (PcdStatus); 221 222 AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB); 223 AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB); 224 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) { 225 AddIoMemoryBaseSizeHob (ICH9_ROOT_COMPLEX_BASE, SIZE_16KB); 226 // 227 // Note: there should be an 228 // 229 // AddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB); 230 // 231 // call below, just like the one above for RCBA. However, Linux insists 232 // that the MMCONFIG area be marked in the E820 or UEFI memory map as 233 // "reserved memory" -- Linux does not content itself with a simple gap 234 // in the memory map wherever the MCFG ACPI table points to. 235 // 236 // This appears to be a safety measure. The PCI Firmware Specification 237 // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can 238 // *optionally* be returned in [...] EFIGetMemoryMap as reserved memory 239 // [...]". (Emphasis added here.) 240 // 241 // Normally we add memory resource descriptor HOBs in 242 // QemuInitializeRam(), and pre-allocate from those with memory 243 // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area 244 // is most definitely not RAM; so, as an exception, cover it with 245 // uncacheable reserved memory right here. 246 // 247 AddReservedMemoryBaseSizeHob (PciExBarBase, SIZE_256MB, FALSE); 248 BuildMemoryAllocationHob (PciExBarBase, SIZE_256MB, 249 EfiReservedMemoryType); 250 } 251 AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB); 252 253 // 254 // On Q35, the IO Port space is available for PCI resource allocations from 255 // 0x6000 up. 256 // 257 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) { 258 PciIoBase = 0x6000; 259 PciIoSize = 0xA000; 260 ASSERT ((ICH9_PMBASE_VALUE & 0xF000) < PciIoBase); 261 } 262 } 263 264 // 265 // Add PCI IO Port space available for PCI resource allocations. 266 // 267 BuildResourceDescriptorHob ( 268 EFI_RESOURCE_IO, 269 EFI_RESOURCE_ATTRIBUTE_PRESENT | 270 EFI_RESOURCE_ATTRIBUTE_INITIALIZED, 271 PciIoBase, 272 PciIoSize 273 ); 274 PcdStatus = PcdSet64S (PcdPciIoBase, PciIoBase); 275 ASSERT_RETURN_ERROR (PcdStatus); 276 PcdStatus = PcdSet64S (PcdPciIoSize, PciIoSize); 277 ASSERT_RETURN_ERROR (PcdStatus); 278 } 279 280 EFI_STATUS 281 GetNamedFwCfgBoolean ( 282 IN CHAR8 *FwCfgFileName, 283 OUT BOOLEAN *Setting 284 ) 285 { 286 EFI_STATUS Status; 287 FIRMWARE_CONFIG_ITEM FwCfgItem; 288 UINTN FwCfgSize; 289 UINT8 Value[3]; 290 291 Status = QemuFwCfgFindFile (FwCfgFileName, &FwCfgItem, &FwCfgSize); 292 if (EFI_ERROR (Status)) { 293 return Status; 294 } 295 if (FwCfgSize > sizeof Value) { 296 return EFI_BAD_BUFFER_SIZE; 297 } 298 QemuFwCfgSelectItem (FwCfgItem); 299 QemuFwCfgReadBytes (FwCfgSize, Value); 300 301 if ((FwCfgSize == 1) || 302 (FwCfgSize == 2 && Value[1] == '\n') || 303 (FwCfgSize == 3 && Value[1] == '\r' && Value[2] == '\n')) { 304 switch (Value[0]) { 305 case '0': 306 case 'n': 307 case 'N': 308 *Setting = FALSE; 309 return EFI_SUCCESS; 310 311 case '1': 312 case 'y': 313 case 'Y': 314 *Setting = TRUE; 315 return EFI_SUCCESS; 316 317 default: 318 break; 319 } 320 } 321 return EFI_PROTOCOL_ERROR; 322 } 323 324 #define UPDATE_BOOLEAN_PCD_FROM_FW_CFG(TokenName) \ 325 do { \ 326 BOOLEAN Setting; \ 327 RETURN_STATUS PcdStatus; \ 328 \ 329 if (!EFI_ERROR (GetNamedFwCfgBoolean ( \ 330 "opt/ovmf/" #TokenName, &Setting))) { \ 331 PcdStatus = PcdSetBoolS (TokenName, Setting); \ 332 ASSERT_RETURN_ERROR (PcdStatus); \ 333 } \ 334 } while (0) 335 336 VOID 337 NoexecDxeInitialization ( 338 VOID 339 ) 340 { 341 UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdPropertiesTableEnable); 342 UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdSetNxForStack); 343 } 344 345 VOID 346 PciExBarInitialization ( 347 VOID 348 ) 349 { 350 union { 351 UINT64 Uint64; 352 UINT32 Uint32[2]; 353 } PciExBarBase; 354 355 // 356 // We only support the 256MB size for the MMCONFIG area: 357 // 256 buses * 32 devices * 8 functions * 4096 bytes config space. 358 // 359 // The masks used below enforce the Q35 requirements that the MMCONFIG area 360 // be (a) correctly aligned -- here at 256 MB --, (b) located under 64 GB. 361 // 362 // Note that (b) also ensures that the minimum address width we have 363 // determined in AddressWidthInitialization(), i.e., 36 bits, will suffice 364 // for DXE's page tables to cover the MMCONFIG area. 365 // 366 PciExBarBase.Uint64 = FixedPcdGet64 (PcdPciExpressBaseAddress); 367 ASSERT ((PciExBarBase.Uint32[1] & MCH_PCIEXBAR_HIGHMASK) == 0); 368 ASSERT ((PciExBarBase.Uint32[0] & MCH_PCIEXBAR_LOWMASK) == 0); 369 370 // 371 // Clear the PCIEXBAREN bit first, before programming the high register. 372 // 373 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW), 0); 374 375 // 376 // Program the high register. Then program the low register, setting the 377 // MMCONFIG area size and enabling decoding at once. 378 // 379 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_HIGH), PciExBarBase.Uint32[1]); 380 PciWrite32 ( 381 DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW), 382 PciExBarBase.Uint32[0] | MCH_PCIEXBAR_BUS_FF | MCH_PCIEXBAR_EN 383 ); 384 } 385 386 VOID 387 MiscInitialization ( 388 VOID 389 ) 390 { 391 UINTN PmCmd; 392 UINTN Pmba; 393 UINT32 PmbaAndVal; 394 UINT32 PmbaOrVal; 395 UINTN AcpiCtlReg; 396 UINT8 AcpiEnBit; 397 RETURN_STATUS PcdStatus; 398 399 // 400 // Disable A20 Mask 401 // 402 IoOr8 (0x92, BIT1); 403 404 // 405 // Build the CPU HOB with guest RAM size dependent address width and 16-bits 406 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during 407 // S3 resume as well, so we build it unconditionally.) 408 // 409 BuildCpuHob (mPhysMemAddressWidth, 16); 410 411 // 412 // Determine platform type and save Host Bridge DID to PCD 413 // 414 switch (mHostBridgeDevId) { 415 case INTEL_82441_DEVICE_ID: 416 PmCmd = POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET); 417 Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA); 418 PmbaAndVal = ~(UINT32)PIIX4_PMBA_MASK; 419 PmbaOrVal = PIIX4_PMBA_VALUE; 420 AcpiCtlReg = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC); 421 AcpiEnBit = PIIX4_PMREGMISC_PMIOSE; 422 break; 423 case INTEL_Q35_MCH_DEVICE_ID: 424 PmCmd = POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET); 425 Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE); 426 PmbaAndVal = ~(UINT32)ICH9_PMBASE_MASK; 427 PmbaOrVal = ICH9_PMBASE_VALUE; 428 AcpiCtlReg = POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL); 429 AcpiEnBit = ICH9_ACPI_CNTL_ACPI_EN; 430 break; 431 default: 432 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n", 433 __FUNCTION__, mHostBridgeDevId)); 434 ASSERT (FALSE); 435 return; 436 } 437 PcdStatus = PcdSet16S (PcdOvmfHostBridgePciDevId, mHostBridgeDevId); 438 ASSERT_RETURN_ERROR (PcdStatus); 439 440 // 441 // If the appropriate IOspace enable bit is set, assume the ACPI PMBA 442 // has been configured (e.g., by Xen) and skip the setup here. 443 // This matches the logic in AcpiTimerLibConstructor (). 444 // 445 if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) == 0) { 446 // 447 // The PEI phase should be exited with fully accessibe ACPI PM IO space: 448 // 1. set PMBA 449 // 450 PciAndThenOr32 (Pmba, PmbaAndVal, PmbaOrVal); 451 452 // 453 // 2. set PCICMD/IOSE 454 // 455 PciOr8 (PmCmd, EFI_PCI_COMMAND_IO_SPACE); 456 457 // 458 // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN) 459 // 460 PciOr8 (AcpiCtlReg, AcpiEnBit); 461 } 462 463 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) { 464 // 465 // Set Root Complex Register Block BAR 466 // 467 PciWrite32 ( 468 POWER_MGMT_REGISTER_Q35 (ICH9_RCBA), 469 ICH9_ROOT_COMPLEX_BASE | ICH9_RCBA_EN 470 ); 471 472 // 473 // Set PCI Express Register Range Base Address 474 // 475 PciExBarInitialization (); 476 } 477 } 478 479 480 VOID 481 BootModeInitialization ( 482 VOID 483 ) 484 { 485 EFI_STATUS Status; 486 487 if (CmosRead8 (0xF) == 0xFE) { 488 mBootMode = BOOT_ON_S3_RESUME; 489 } 490 CmosWrite8 (0xF, 0x00); 491 492 Status = PeiServicesSetBootMode (mBootMode); 493 ASSERT_EFI_ERROR (Status); 494 495 Status = PeiServicesInstallPpi (mPpiBootMode); 496 ASSERT_EFI_ERROR (Status); 497 } 498 499 500 VOID 501 ReserveEmuVariableNvStore ( 502 ) 503 { 504 EFI_PHYSICAL_ADDRESS VariableStore; 505 RETURN_STATUS PcdStatus; 506 507 // 508 // Allocate storage for NV variables early on so it will be 509 // at a consistent address. Since VM memory is preserved 510 // across reboots, this allows the NV variable storage to survive 511 // a VM reboot. 512 // 513 VariableStore = 514 (EFI_PHYSICAL_ADDRESS)(UINTN) 515 AllocateAlignedRuntimePages ( 516 EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)), 517 PcdGet32 (PcdFlashNvStorageFtwSpareSize) 518 ); 519 DEBUG ((EFI_D_INFO, 520 "Reserved variable store memory: 0x%lX; size: %dkb\n", 521 VariableStore, 522 (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024 523 )); 524 PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore); 525 ASSERT_RETURN_ERROR (PcdStatus); 526 } 527 528 529 VOID 530 DebugDumpCmos ( 531 VOID 532 ) 533 { 534 UINT32 Loop; 535 536 DEBUG ((EFI_D_INFO, "CMOS:\n")); 537 538 for (Loop = 0; Loop < 0x80; Loop++) { 539 if ((Loop % 0x10) == 0) { 540 DEBUG ((EFI_D_INFO, "%02x:", Loop)); 541 } 542 DEBUG ((EFI_D_INFO, " %02x", CmosRead8 (Loop))); 543 if ((Loop % 0x10) == 0xf) { 544 DEBUG ((EFI_D_INFO, "\n")); 545 } 546 } 547 } 548 549 550 VOID 551 S3Verification ( 552 VOID 553 ) 554 { 555 #if defined (MDE_CPU_X64) 556 if (FeaturePcdGet (PcdSmmSmramRequire) && mS3Supported) { 557 DEBUG ((EFI_D_ERROR, 558 "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n", __FUNCTION__)); 559 DEBUG ((EFI_D_ERROR, 560 "%a: Please disable S3 on the QEMU command line (see the README),\n", 561 __FUNCTION__)); 562 DEBUG ((EFI_D_ERROR, 563 "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n", __FUNCTION__)); 564 ASSERT (FALSE); 565 CpuDeadLoop (); 566 } 567 #endif 568 } 569 570 571 /** 572 Fetch the number of boot CPUs from QEMU and expose it to UefiCpuPkg modules. 573 Set the mMaxCpuCount variable. 574 **/ 575 VOID 576 MaxCpuCountInitialization ( 577 VOID 578 ) 579 { 580 UINT16 ProcessorCount; 581 RETURN_STATUS PcdStatus; 582 583 QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount); 584 ProcessorCount = QemuFwCfgRead16 (); 585 // 586 // If the fw_cfg key or fw_cfg entirely is unavailable, load mMaxCpuCount 587 // from the PCD default. No change to PCDs. 588 // 589 if (ProcessorCount == 0) { 590 mMaxCpuCount = PcdGet32 (PcdCpuMaxLogicalProcessorNumber); 591 return; 592 } 593 // 594 // Otherwise, set mMaxCpuCount to the value reported by QEMU. 595 // 596 mMaxCpuCount = ProcessorCount; 597 // 598 // Additionally, tell UefiCpuPkg modules (a) the exact number of VCPUs, (b) 599 // to wait, in the initial AP bringup, exactly as long as it takes for all of 600 // the APs to report in. For this, we set the longest representable timeout 601 // (approx. 71 minutes). 602 // 603 PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, ProcessorCount); 604 ASSERT_RETURN_ERROR (PcdStatus); 605 PcdStatus = PcdSet32S (PcdCpuApInitTimeOutInMicroSeconds, MAX_UINT32); 606 ASSERT_RETURN_ERROR (PcdStatus); 607 DEBUG ((DEBUG_INFO, "%a: QEMU reports %d processor(s)\n", __FUNCTION__, 608 ProcessorCount)); 609 } 610 611 612 /** 613 Perform Platform PEI initialization. 614 615 @param FileHandle Handle of the file being invoked. 616 @param PeiServices Describes the list of possible PEI Services. 617 618 @return EFI_SUCCESS The PEIM initialized successfully. 619 620 **/ 621 EFI_STATUS 622 EFIAPI 623 InitializePlatform ( 624 IN EFI_PEI_FILE_HANDLE FileHandle, 625 IN CONST EFI_PEI_SERVICES **PeiServices 626 ) 627 { 628 EFI_STATUS Status; 629 630 DEBUG ((EFI_D_ERROR, "Platform PEIM Loaded\n")); 631 632 DebugDumpCmos (); 633 634 XenDetect (); 635 636 if (QemuFwCfgS3Enabled ()) { 637 DEBUG ((EFI_D_INFO, "S3 support was detected on QEMU\n")); 638 mS3Supported = TRUE; 639 Status = PcdSetBoolS (PcdAcpiS3Enable, TRUE); 640 ASSERT_EFI_ERROR (Status); 641 } 642 643 S3Verification (); 644 BootModeInitialization (); 645 AddressWidthInitialization (); 646 MaxCpuCountInitialization (); 647 648 PublishPeiMemory (); 649 650 InitializeRamRegions (); 651 652 if (mXen) { 653 DEBUG ((EFI_D_INFO, "Xen was detected\n")); 654 InitializeXen (); 655 } 656 657 // 658 // Query Host Bridge DID 659 // 660 mHostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID); 661 662 if (mBootMode != BOOT_ON_S3_RESUME) { 663 ReserveEmuVariableNvStore (); 664 PeiFvInitialization (); 665 MemMapInitialization (); 666 NoexecDxeInitialization (); 667 } 668 669 MiscInitialization (); 670 InstallFeatureControlCallback (); 671 672 return EFI_SUCCESS; 673 } 674