4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 // The package level header files this module uses
17 // The Library classes this module consumes
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/BaseLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/HobLib.h>
23 #include <Library/IoLib.h>
24 #include <Library/MemoryAllocationLib.h>
25 #include <Library/PcdLib.h>
26 #include <Library/PciLib.h>
27 #include <Library/PeimEntryPoint.h>
28 #include <Library/PeiServicesLib.h>
29 #include <Library/QemuFwCfgLib.h>
30 #include <Library/QemuFwCfgS3Lib.h>
31 #include <Library/QemuFwCfgSimpleParserLib.h>
32 #include <Library/ResourcePublicationLib.h>
33 #include <Ppi/MasterBootMode.h>
34 #include <IndustryStandard/I440FxPiix4.h>
35 #include <IndustryStandard/Microvm.h>
36 #include <IndustryStandard/Pci22.h>
37 #include <IndustryStandard/Q35MchIch9.h>
38 #include <IndustryStandard/QemuCpuHotplug.h>
39 #include <Library/MemEncryptSevLib.h>
40 #include <OvmfPlatforms.h>
44 EFI_HOB_PLATFORM_INFO mPlatformInfoHob
= { 0 };
46 EFI_PEI_PPI_DESCRIPTOR mPpiBootMode
[] = {
48 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
49 &gEfiPeiMasterBootModePpiGuid
,
55 MemMapInitialization (
56 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
61 RETURN_STATUS PcdStatus
;
71 // Video memory + Legacy BIOS region
73 PlatformAddIoMemoryRangeHob (0x0A0000, BASE_1MB
);
75 if (PlatformInfoHob
->HostBridgeDevId
== 0xffff /* microvm */) {
76 PlatformAddIoMemoryBaseSizeHob (MICROVM_GED_MMIO_BASE
, SIZE_4KB
);
77 PlatformAddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB
); /* ioapic #1 */
78 PlatformAddIoMemoryBaseSizeHob (0xFEC10000, SIZE_4KB
); /* ioapic #2 */
82 TopOfLowRam
= GetSystemMemorySizeBelow4gb (PlatformInfoHob
);
84 if (PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
86 // The MMCONFIG area is expected to fall between the top of low RAM and
87 // the base of the 32-bit PCI host aperture.
89 PciExBarBase
= FixedPcdGet64 (PcdPciExpressBaseAddress
);
90 ASSERT (TopOfLowRam
<= PciExBarBase
);
91 ASSERT (PciExBarBase
<= MAX_UINT32
- SIZE_256MB
);
92 PciBase
= (UINT32
)(PciExBarBase
+ SIZE_256MB
);
94 ASSERT (TopOfLowRam
<= PlatformInfoHob
->Uc32Base
);
95 PciBase
= PlatformInfoHob
->Uc32Base
;
99 // address purpose size
100 // ------------ -------- -------------------------
101 // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g)
102 // 0xFC000000 gap 44 MB
103 // 0xFEC00000 IO-APIC 4 KB
104 // 0xFEC01000 gap 1020 KB
105 // 0xFED00000 HPET 1 KB
106 // 0xFED00400 gap 111 KB
107 // 0xFED1C000 gap (PIIX4) / RCRB (ICH9) 16 KB
108 // 0xFED20000 gap 896 KB
109 // 0xFEE00000 LAPIC 1 MB
111 PciSize
= 0xFC000000 - PciBase
;
112 PlatformAddIoMemoryBaseSizeHob (PciBase
, PciSize
);
113 PcdStatus
= PcdSet64S (PcdPciMmio32Base
, PciBase
);
114 ASSERT_RETURN_ERROR (PcdStatus
);
115 PcdStatus
= PcdSet64S (PcdPciMmio32Size
, PciSize
);
116 ASSERT_RETURN_ERROR (PcdStatus
);
118 PlatformInfoHob
->PcdPciMmio32Base
= PciBase
;
119 PlatformInfoHob
->PcdPciMmio32Size
= PciSize
;
121 PlatformAddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB
);
122 PlatformAddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB
);
123 if (PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
124 PlatformAddIoMemoryBaseSizeHob (ICH9_ROOT_COMPLEX_BASE
, SIZE_16KB
);
126 // Note: there should be an
128 // PlatformAddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB);
130 // call below, just like the one above for RCBA. However, Linux insists
131 // that the MMCONFIG area be marked in the E820 or UEFI memory map as
132 // "reserved memory" -- Linux does not content itself with a simple gap
133 // in the memory map wherever the MCFG ACPI table points to.
135 // This appears to be a safety measure. The PCI Firmware Specification
136 // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can
137 // *optionally* be returned in [...] EFIGetMemoryMap as reserved memory
138 // [...]". (Emphasis added here.)
140 // Normally we add memory resource descriptor HOBs in
141 // QemuInitializeRam(), and pre-allocate from those with memory
142 // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area
143 // is most definitely not RAM; so, as an exception, cover it with
144 // uncacheable reserved memory right here.
146 PlatformAddReservedMemoryBaseSizeHob (PciExBarBase
, SIZE_256MB
, FALSE
);
147 BuildMemoryAllocationHob (
150 EfiReservedMemoryType
154 PlatformAddIoMemoryBaseSizeHob (PcdGet32 (PcdCpuLocalApicBaseAddress
), SIZE_1MB
);
157 // On Q35, the IO Port space is available for PCI resource allocations from
160 if (PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
163 ASSERT ((ICH9_PMBASE_VALUE
& 0xF000) < PciIoBase
);
167 // Add PCI IO Port space available for PCI resource allocations.
169 BuildResourceDescriptorHob (
171 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
172 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
,
176 PcdStatus
= PcdSet64S (PcdPciIoBase
, PciIoBase
);
177 ASSERT_RETURN_ERROR (PcdStatus
);
178 PcdStatus
= PcdSet64S (PcdPciIoSize
, PciIoSize
);
179 ASSERT_RETURN_ERROR (PcdStatus
);
181 PlatformInfoHob
->PcdPciIoBase
= PciIoBase
;
182 PlatformInfoHob
->PcdPciIoSize
= PciIoSize
;
185 #define UPDATE_BOOLEAN_PCD_FROM_FW_CFG(TokenName) \
188 RETURN_STATUS PcdStatus; \
190 if (!RETURN_ERROR (QemuFwCfgParseBool ( \
191 "opt/ovmf/" #TokenName, &Setting))) { \
192 PcdStatus = PcdSetBoolS (TokenName, Setting); \
193 ASSERT_RETURN_ERROR (PcdStatus); \
198 NoexecDxeInitialization (
202 UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdSetNxForStack
);
206 PciExBarInitialization (
216 // We only support the 256MB size for the MMCONFIG area:
217 // 256 buses * 32 devices * 8 functions * 4096 bytes config space.
219 // The masks used below enforce the Q35 requirements that the MMCONFIG area
220 // be (a) correctly aligned -- here at 256 MB --, (b) located under 64 GB.
222 // Note that (b) also ensures that the minimum address width we have
223 // determined in AddressWidthInitialization(), i.e., 36 bits, will suffice
224 // for DXE's page tables to cover the MMCONFIG area.
226 PciExBarBase
.Uint64
= FixedPcdGet64 (PcdPciExpressBaseAddress
);
227 ASSERT ((PciExBarBase
.Uint32
[1] & MCH_PCIEXBAR_HIGHMASK
) == 0);
228 ASSERT ((PciExBarBase
.Uint32
[0] & MCH_PCIEXBAR_LOWMASK
) == 0);
231 // Clear the PCIEXBAREN bit first, before programming the high register.
233 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW
), 0);
236 // Program the high register. Then program the low register, setting the
237 // MMCONFIG area size and enabling decoding at once.
239 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_HIGH
), PciExBarBase
.Uint32
[1]);
241 DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW
),
242 PciExBarBase
.Uint32
[0] | MCH_PCIEXBAR_BUS_FF
| MCH_PCIEXBAR_EN
246 static const UINT8 EmptyFdt
[] = {
247 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x48,
248 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x48,
249 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11,
250 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
255 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09,
259 MicrovmInitialization (
263 FIRMWARE_CONFIG_ITEM FdtItem
;
270 Status
= QemuFwCfgFindFile ("etc/fdt", &FdtItem
, &FdtSize
);
271 if (EFI_ERROR (Status
)) {
272 DEBUG ((DEBUG_INFO
, "%a: no etc/fdt found in fw_cfg, using dummy\n", __FUNCTION__
));
274 FdtSize
= sizeof (EmptyFdt
);
277 FdtPages
= EFI_SIZE_TO_PAGES (FdtSize
);
278 NewBase
= AllocatePages (FdtPages
);
279 if (NewBase
== NULL
) {
280 DEBUG ((DEBUG_INFO
, "%a: AllocatePages failed\n", __FUNCTION__
));
285 QemuFwCfgSelectItem (FdtItem
);
286 QemuFwCfgReadBytes (FdtSize
, NewBase
);
288 CopyMem (NewBase
, EmptyFdt
, FdtSize
);
291 FdtHobData
= BuildGuidHob (&gFdtHobGuid
, sizeof (*FdtHobData
));
292 if (FdtHobData
== NULL
) {
293 DEBUG ((DEBUG_INFO
, "%a: BuildGuidHob failed\n", __FUNCTION__
));
299 "%a: fdt at 0x%x (size %d)\n",
304 *FdtHobData
= (UINTN
)NewBase
;
309 IN EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
318 RETURN_STATUS PcdStatus
;
326 // Build the CPU HOB with guest RAM size dependent address width and 16-bits
327 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
328 // S3 resume as well, so we build it unconditionally.)
330 BuildCpuHob (PlatformInfoHob
->PhysMemAddressWidth
, 16);
333 // Determine platform type and save Host Bridge DID to PCD
335 switch (PlatformInfoHob
->HostBridgeDevId
) {
336 case INTEL_82441_DEVICE_ID
:
337 PmCmd
= POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET
);
338 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
339 PmbaAndVal
= ~(UINT32
)PIIX4_PMBA_MASK
;
340 PmbaOrVal
= PIIX4_PMBA_VALUE
;
341 AcpiCtlReg
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC
);
342 AcpiEnBit
= PIIX4_PMREGMISC_PMIOSE
;
344 case INTEL_Q35_MCH_DEVICE_ID
:
345 PmCmd
= POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET
);
346 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
347 PmbaAndVal
= ~(UINT32
)ICH9_PMBASE_MASK
;
348 PmbaOrVal
= ICH9_PMBASE_VALUE
;
349 AcpiCtlReg
= POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL
);
350 AcpiEnBit
= ICH9_ACPI_CNTL_ACPI_EN
;
352 case 0xffff: /* microvm */
353 DEBUG ((DEBUG_INFO
, "%a: microvm\n", __FUNCTION__
));
354 MicrovmInitialization ();
355 PcdStatus
= PcdSet16S (
356 PcdOvmfHostBridgePciDevId
,
357 MICROVM_PSEUDO_DEVICE_ID
359 ASSERT_RETURN_ERROR (PcdStatus
);
361 case CLOUDHV_DEVICE_ID
:
362 DEBUG ((DEBUG_INFO
, "%a: Cloud Hypervisor host bridge\n", __FUNCTION__
));
363 PcdStatus
= PcdSet16S (
364 PcdOvmfHostBridgePciDevId
,
367 ASSERT_RETURN_ERROR (PcdStatus
);
372 "%a: Unknown Host Bridge Device ID: 0x%04x\n",
374 PlatformInfoHob
->HostBridgeDevId
380 PcdStatus
= PcdSet16S (PcdOvmfHostBridgePciDevId
, PlatformInfoHob
->HostBridgeDevId
);
381 ASSERT_RETURN_ERROR (PcdStatus
);
384 // If the appropriate IOspace enable bit is set, assume the ACPI PMBA has
385 // been configured and skip the setup here. This matches the logic in
386 // AcpiTimerLibConstructor ().
388 if ((PciRead8 (AcpiCtlReg
) & AcpiEnBit
) == 0) {
390 // The PEI phase should be exited with fully accessibe ACPI PM IO space:
393 PciAndThenOr32 (Pmba
, PmbaAndVal
, PmbaOrVal
);
396 // 2. set PCICMD/IOSE
398 PciOr8 (PmCmd
, EFI_PCI_COMMAND_IO_SPACE
);
401 // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN)
403 PciOr8 (AcpiCtlReg
, AcpiEnBit
);
406 if (PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
408 // Set Root Complex Register Block BAR
411 POWER_MGMT_REGISTER_Q35 (ICH9_RCBA
),
412 ICH9_ROOT_COMPLEX_BASE
| ICH9_RCBA_EN
416 // Set PCI Express Register Range Base Address
418 PciExBarInitialization ();
423 BootModeInitialization (
424 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
429 if (PlatformCmosRead8 (0xF) == 0xFE) {
430 PlatformInfoHob
->BootMode
= BOOT_ON_S3_RESUME
;
433 PlatformCmosWrite8 (0xF, 0x00);
435 Status
= PeiServicesSetBootMode (PlatformInfoHob
->BootMode
);
436 ASSERT_EFI_ERROR (Status
);
438 Status
= PeiServicesInstallPpi (mPpiBootMode
);
439 ASSERT_EFI_ERROR (Status
);
443 ReserveEmuVariableNvStore (
446 EFI_PHYSICAL_ADDRESS VariableStore
;
447 RETURN_STATUS PcdStatus
;
450 // Allocate storage for NV variables early on so it will be
451 // at a consistent address. Since VM memory is preserved
452 // across reboots, this allows the NV variable storage to survive
456 (EFI_PHYSICAL_ADDRESS
)(UINTN
)
457 AllocateRuntimePages (
458 EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize
))
462 "Reserved variable store memory: 0x%lX; size: %dkb\n",
464 (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize
)) / 1024
466 PcdStatus
= PcdSet64S (PcdEmuVariableNvStoreReserved
, VariableStore
);
467 ASSERT_RETURN_ERROR (PcdStatus
);
475 #if defined (MDE_CPU_X64)
476 if (mPlatformInfoHob
.SmmSmramRequire
&& mPlatformInfoHob
.S3Supported
) {
479 "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n",
484 "%a: Please disable S3 on the QEMU command line (see the README),\n",
489 "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n",
500 Q35BoardVerification (
504 if (mPlatformInfoHob
.HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
510 "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
511 "only DID=0x%04x (Q35) is supported\n",
513 mPlatformInfoHob
.HostBridgeDevId
,
514 INTEL_Q35_MCH_DEVICE_ID
521 Fetch the boot CPU count and the possible CPU count from QEMU, and expose
522 them to UefiCpuPkg modules. Set the mMaxCpuCount variable.
525 MaxCpuCountInitialization (
526 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
531 RETURN_STATUS PcdStatus
;
534 // Try to fetch the boot CPU count.
536 QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount
);
537 BootCpuCount
= QemuFwCfgRead16 ();
538 if (BootCpuCount
== 0) {
540 // QEMU doesn't report the boot CPU count. (BootCpuCount == 0) will let
541 // MpInitLib count APs up to (PcdCpuMaxLogicalProcessorNumber - 1), or
542 // until PcdCpuApInitTimeOutInMicroSeconds elapses (whichever is reached
545 DEBUG ((DEBUG_WARN
, "%a: boot CPU count unavailable\n", __FUNCTION__
));
546 MaxCpuCount
= PlatformInfoHob
->DefaultMaxCpuNumber
;
549 // We will expose BootCpuCount to MpInitLib. MpInitLib will count APs up to
550 // (BootCpuCount - 1) precisely, regardless of timeout.
552 // Now try to fetch the possible CPU count.
557 CpuHpBase
= ((PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) ?
558 ICH9_CPU_HOTPLUG_BASE
: PIIX4_CPU_HOTPLUG_BASE
);
561 // If only legacy mode is available in the CPU hotplug register block, or
562 // the register block is completely missing, then the writes below are
565 // 1. Switch the hotplug register block to modern mode.
567 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, 0);
569 // 2. Select a valid CPU for deterministic reading of
570 // QEMU_CPUHP_R_CMD_DATA2.
572 // CPU#0 is always valid; it is the always present and non-removable
575 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, 0);
577 // 3. Send a command after which QEMU_CPUHP_R_CMD_DATA2 is specified to
578 // read as zero, and which does not invalidate the selector. (The
579 // selector may change, but it must not become invalid.)
581 // Send QEMU_CPUHP_CMD_GET_PENDING, as it will prove useful later.
583 IoWrite8 (CpuHpBase
+ QEMU_CPUHP_W_CMD
, QEMU_CPUHP_CMD_GET_PENDING
);
585 // 4. Read QEMU_CPUHP_R_CMD_DATA2.
587 // If the register block is entirely missing, then this is an unassigned
588 // IO read, returning all-bits-one.
590 // If only legacy mode is available, then bit#0 stands for CPU#0 in the
591 // "CPU present bitmap". CPU#0 is always present.
593 // Otherwise, QEMU_CPUHP_R_CMD_DATA2 is either still reserved (returning
594 // all-bits-zero), or it is specified to read as zero after the above
595 // steps. Both cases confirm modern mode.
597 CmdData2
= IoRead32 (CpuHpBase
+ QEMU_CPUHP_R_CMD_DATA2
);
598 DEBUG ((DEBUG_VERBOSE
, "%a: CmdData2=0x%x\n", __FUNCTION__
, CmdData2
));
601 // QEMU doesn't support the modern CPU hotplug interface. Assume that the
602 // possible CPU count equals the boot CPU count (precluding hotplug).
606 "%a: modern CPU hotplug interface unavailable\n",
609 MaxCpuCount
= BootCpuCount
;
612 // Grab the possible CPU count from the modern CPU hotplug interface.
614 UINT32 Present
, Possible
, Selected
;
620 // We've sent QEMU_CPUHP_CMD_GET_PENDING last; this ensures
621 // QEMU_CPUHP_RW_CMD_DATA can now be read usefully. However,
622 // QEMU_CPUHP_CMD_GET_PENDING may have selected a CPU with actual pending
623 // hotplug events; therefore, select CPU#0 forcibly.
625 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, Possible
);
631 // Read the status of the currently selected CPU. This will help with a
632 // sanity check against "BootCpuCount".
634 CpuStatus
= IoRead8 (CpuHpBase
+ QEMU_CPUHP_R_CPU_STAT
);
635 if ((CpuStatus
& QEMU_CPUHP_STAT_ENABLED
) != 0) {
640 // Attempt to select the next CPU.
643 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, Possible
);
645 // If the selection is successful, then the following read will return
646 // the selector (which we know is positive at this point). Otherwise,
647 // the read will return 0.
649 Selected
= IoRead32 (CpuHpBase
+ QEMU_CPUHP_RW_CMD_DATA
);
650 ASSERT (Selected
== Possible
|| Selected
== 0);
651 } while (Selected
> 0);
654 // Sanity check: fw_cfg and the modern CPU hotplug interface should
655 // return the same boot CPU count.
657 if (BootCpuCount
!= Present
) {
660 "%a: QEMU v2.7 reset bug: BootCpuCount=%d "
667 // The handling of QemuFwCfgItemSmpCpuCount, across CPU hotplug plus
668 // platform reset (including S3), was corrected in QEMU commit
669 // e3cadac073a9 ("pc: fix FW_CFG_NB_CPUS to account for -device added
670 // CPUs", 2016-11-16), part of release v2.8.0.
672 BootCpuCount
= (UINT16
)Present
;
675 MaxCpuCount
= Possible
;
681 "%a: BootCpuCount=%d MaxCpuCount=%u\n",
686 ASSERT (BootCpuCount
<= MaxCpuCount
);
688 PcdStatus
= PcdSet32S (PcdCpuBootLogicalProcessorNumber
, BootCpuCount
);
689 ASSERT_RETURN_ERROR (PcdStatus
);
690 PcdStatus
= PcdSet32S (PcdCpuMaxLogicalProcessorNumber
, MaxCpuCount
);
691 ASSERT_RETURN_ERROR (PcdStatus
);
693 PlatformInfoHob
->PcdCpuMaxLogicalProcessorNumber
= MaxCpuCount
;
694 PlatformInfoHob
->PcdCpuBootLogicalProcessorNumber
= BootCpuCount
;
698 Perform Platform PEI initialization.
700 @param FileHandle Handle of the file being invoked.
701 @param PeiServices Describes the list of possible PEI Services.
703 @return EFI_SUCCESS The PEIM initialized successfully.
709 IN EFI_PEI_FILE_HANDLE FileHandle
,
710 IN CONST EFI_PEI_SERVICES
**PeiServices
715 DEBUG ((DEBUG_INFO
, "Platform PEIM Loaded\n"));
717 mPlatformInfoHob
.SmmSmramRequire
= FeaturePcdGet (PcdSmmSmramRequire
);
718 mPlatformInfoHob
.SevEsIsEnabled
= MemEncryptSevEsIsEnabled ();
720 PlatformDebugDumpCmos ();
722 if (QemuFwCfgS3Enabled ()) {
723 DEBUG ((DEBUG_INFO
, "S3 support was detected on QEMU\n"));
724 mPlatformInfoHob
.S3Supported
= TRUE
;
725 Status
= PcdSetBoolS (PcdAcpiS3Enable
, TRUE
);
726 ASSERT_EFI_ERROR (Status
);
730 BootModeInitialization (&mPlatformInfoHob
);
731 AddressWidthInitialization (&mPlatformInfoHob
);
734 // Query Host Bridge DID
736 mPlatformInfoHob
.HostBridgeDevId
= PciRead16 (OVMF_HOSTBRIDGE_DID
);
738 MaxCpuCountInitialization (&mPlatformInfoHob
);
740 if (mPlatformInfoHob
.SmmSmramRequire
) {
741 Q35BoardVerification ();
742 Q35TsegMbytesInitialization ();
743 Q35SmramAtDefaultSmbaseInitialization ();
748 QemuUc32BaseInitialization (&mPlatformInfoHob
);
750 InitializeRamRegions (&mPlatformInfoHob
);
752 if (mPlatformInfoHob
.BootMode
!= BOOT_ON_S3_RESUME
) {
753 if (!mPlatformInfoHob
.SmmSmramRequire
) {
754 ReserveEmuVariableNvStore ();
757 PeiFvInitialization ();
758 MemTypeInfoInitialization ();
759 MemMapInitialization (&mPlatformInfoHob
);
760 NoexecDxeInitialization ();
763 InstallClearCacheCallback ();
765 MiscInitialization (&mPlatformInfoHob
);
766 InstallFeatureControlCallback ();