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
;
308 MiscInitializationForMicrovm (
309 IN EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
312 RETURN_STATUS PcdStatus
;
314 ASSERT (PlatformInfoHob
->HostBridgeDevId
== 0xffff);
316 DEBUG ((DEBUG_INFO
, "%a: microvm\n", __FUNCTION__
));
323 // Build the CPU HOB with guest RAM size dependent address width and 16-bits
324 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
325 // S3 resume as well, so we build it unconditionally.)
327 BuildCpuHob (PlatformInfoHob
->PhysMemAddressWidth
, 16);
329 MicrovmInitialization ();
330 PcdStatus
= PcdSet16S (
331 PcdOvmfHostBridgePciDevId
,
332 MICROVM_PSEUDO_DEVICE_ID
334 ASSERT_RETURN_ERROR (PcdStatus
);
339 IN EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
348 RETURN_STATUS PcdStatus
;
356 // Build the CPU HOB with guest RAM size dependent address width and 16-bits
357 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
358 // S3 resume as well, so we build it unconditionally.)
360 BuildCpuHob (PlatformInfoHob
->PhysMemAddressWidth
, 16);
363 // Determine platform type and save Host Bridge DID to PCD
365 switch (PlatformInfoHob
->HostBridgeDevId
) {
366 case INTEL_82441_DEVICE_ID
:
367 PmCmd
= POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET
);
368 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
369 PmbaAndVal
= ~(UINT32
)PIIX4_PMBA_MASK
;
370 PmbaOrVal
= PIIX4_PMBA_VALUE
;
371 AcpiCtlReg
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC
);
372 AcpiEnBit
= PIIX4_PMREGMISC_PMIOSE
;
374 case INTEL_Q35_MCH_DEVICE_ID
:
375 PmCmd
= POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET
);
376 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
377 PmbaAndVal
= ~(UINT32
)ICH9_PMBASE_MASK
;
378 PmbaOrVal
= ICH9_PMBASE_VALUE
;
379 AcpiCtlReg
= POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL
);
380 AcpiEnBit
= ICH9_ACPI_CNTL_ACPI_EN
;
382 case CLOUDHV_DEVICE_ID
:
387 "%a: Unknown Host Bridge Device ID: 0x%04x\n",
389 PlatformInfoHob
->HostBridgeDevId
395 PcdStatus
= PcdSet16S (PcdOvmfHostBridgePciDevId
, PlatformInfoHob
->HostBridgeDevId
);
396 ASSERT_RETURN_ERROR (PcdStatus
);
398 if (PlatformInfoHob
->HostBridgeDevId
== CLOUDHV_DEVICE_ID
) {
399 DEBUG ((DEBUG_INFO
, "%a: Cloud Hypervisor is done.\n", __FUNCTION__
));
404 // If the appropriate IOspace enable bit is set, assume the ACPI PMBA has
405 // been configured and skip the setup here. This matches the logic in
406 // AcpiTimerLibConstructor ().
408 if ((PciRead8 (AcpiCtlReg
) & AcpiEnBit
) == 0) {
410 // The PEI phase should be exited with fully accessibe ACPI PM IO space:
413 PciAndThenOr32 (Pmba
, PmbaAndVal
, PmbaOrVal
);
416 // 2. set PCICMD/IOSE
418 PciOr8 (PmCmd
, EFI_PCI_COMMAND_IO_SPACE
);
421 // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN)
423 PciOr8 (AcpiCtlReg
, AcpiEnBit
);
426 if (PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
428 // Set Root Complex Register Block BAR
431 POWER_MGMT_REGISTER_Q35 (ICH9_RCBA
),
432 ICH9_ROOT_COMPLEX_BASE
| ICH9_RCBA_EN
436 // Set PCI Express Register Range Base Address
438 PciExBarInitialization ();
443 BootModeInitialization (
444 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
449 if (PlatformCmosRead8 (0xF) == 0xFE) {
450 PlatformInfoHob
->BootMode
= BOOT_ON_S3_RESUME
;
453 PlatformCmosWrite8 (0xF, 0x00);
455 Status
= PeiServicesSetBootMode (PlatformInfoHob
->BootMode
);
456 ASSERT_EFI_ERROR (Status
);
458 Status
= PeiServicesInstallPpi (mPpiBootMode
);
459 ASSERT_EFI_ERROR (Status
);
463 ReserveEmuVariableNvStore (
466 EFI_PHYSICAL_ADDRESS VariableStore
;
467 RETURN_STATUS PcdStatus
;
470 // Allocate storage for NV variables early on so it will be
471 // at a consistent address. Since VM memory is preserved
472 // across reboots, this allows the NV variable storage to survive
476 (EFI_PHYSICAL_ADDRESS
)(UINTN
)
477 AllocateRuntimePages (
478 EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize
))
482 "Reserved variable store memory: 0x%lX; size: %dkb\n",
484 (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize
)) / 1024
486 PcdStatus
= PcdSet64S (PcdEmuVariableNvStoreReserved
, VariableStore
);
487 ASSERT_RETURN_ERROR (PcdStatus
);
495 #if defined (MDE_CPU_X64)
496 if (mPlatformInfoHob
.SmmSmramRequire
&& mPlatformInfoHob
.S3Supported
) {
499 "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n",
504 "%a: Please disable S3 on the QEMU command line (see the README),\n",
509 "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n",
520 Q35BoardVerification (
524 if (mPlatformInfoHob
.HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
530 "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
531 "only DID=0x%04x (Q35) is supported\n",
533 mPlatformInfoHob
.HostBridgeDevId
,
534 INTEL_Q35_MCH_DEVICE_ID
541 Fetch the boot CPU count and the possible CPU count from QEMU, and expose
542 them to UefiCpuPkg modules. Set the MaxCpuCount field in PlatformInfoHob.
545 PlatformMaxCpuCountInitialization (
546 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
553 // Try to fetch the boot CPU count.
555 QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount
);
556 BootCpuCount
= QemuFwCfgRead16 ();
557 if (BootCpuCount
== 0) {
559 // QEMU doesn't report the boot CPU count. (BootCpuCount == 0) will let
560 // MpInitLib count APs up to (PcdCpuMaxLogicalProcessorNumber - 1), or
561 // until PcdCpuApInitTimeOutInMicroSeconds elapses (whichever is reached
564 DEBUG ((DEBUG_WARN
, "%a: boot CPU count unavailable\n", __FUNCTION__
));
565 MaxCpuCount
= PlatformInfoHob
->DefaultMaxCpuNumber
;
568 // We will expose BootCpuCount to MpInitLib. MpInitLib will count APs up to
569 // (BootCpuCount - 1) precisely, regardless of timeout.
571 // Now try to fetch the possible CPU count.
576 CpuHpBase
= ((PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) ?
577 ICH9_CPU_HOTPLUG_BASE
: PIIX4_CPU_HOTPLUG_BASE
);
580 // If only legacy mode is available in the CPU hotplug register block, or
581 // the register block is completely missing, then the writes below are
584 // 1. Switch the hotplug register block to modern mode.
586 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, 0);
588 // 2. Select a valid CPU for deterministic reading of
589 // QEMU_CPUHP_R_CMD_DATA2.
591 // CPU#0 is always valid; it is the always present and non-removable
594 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, 0);
596 // 3. Send a command after which QEMU_CPUHP_R_CMD_DATA2 is specified to
597 // read as zero, and which does not invalidate the selector. (The
598 // selector may change, but it must not become invalid.)
600 // Send QEMU_CPUHP_CMD_GET_PENDING, as it will prove useful later.
602 IoWrite8 (CpuHpBase
+ QEMU_CPUHP_W_CMD
, QEMU_CPUHP_CMD_GET_PENDING
);
604 // 4. Read QEMU_CPUHP_R_CMD_DATA2.
606 // If the register block is entirely missing, then this is an unassigned
607 // IO read, returning all-bits-one.
609 // If only legacy mode is available, then bit#0 stands for CPU#0 in the
610 // "CPU present bitmap". CPU#0 is always present.
612 // Otherwise, QEMU_CPUHP_R_CMD_DATA2 is either still reserved (returning
613 // all-bits-zero), or it is specified to read as zero after the above
614 // steps. Both cases confirm modern mode.
616 CmdData2
= IoRead32 (CpuHpBase
+ QEMU_CPUHP_R_CMD_DATA2
);
617 DEBUG ((DEBUG_VERBOSE
, "%a: CmdData2=0x%x\n", __FUNCTION__
, CmdData2
));
620 // QEMU doesn't support the modern CPU hotplug interface. Assume that the
621 // possible CPU count equals the boot CPU count (precluding hotplug).
625 "%a: modern CPU hotplug interface unavailable\n",
628 MaxCpuCount
= BootCpuCount
;
631 // Grab the possible CPU count from the modern CPU hotplug interface.
633 UINT32 Present
, Possible
, Selected
;
639 // We've sent QEMU_CPUHP_CMD_GET_PENDING last; this ensures
640 // QEMU_CPUHP_RW_CMD_DATA can now be read usefully. However,
641 // QEMU_CPUHP_CMD_GET_PENDING may have selected a CPU with actual pending
642 // hotplug events; therefore, select CPU#0 forcibly.
644 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, Possible
);
650 // Read the status of the currently selected CPU. This will help with a
651 // sanity check against "BootCpuCount".
653 CpuStatus
= IoRead8 (CpuHpBase
+ QEMU_CPUHP_R_CPU_STAT
);
654 if ((CpuStatus
& QEMU_CPUHP_STAT_ENABLED
) != 0) {
659 // Attempt to select the next CPU.
662 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, Possible
);
664 // If the selection is successful, then the following read will return
665 // the selector (which we know is positive at this point). Otherwise,
666 // the read will return 0.
668 Selected
= IoRead32 (CpuHpBase
+ QEMU_CPUHP_RW_CMD_DATA
);
669 ASSERT (Selected
== Possible
|| Selected
== 0);
670 } while (Selected
> 0);
673 // Sanity check: fw_cfg and the modern CPU hotplug interface should
674 // return the same boot CPU count.
676 if (BootCpuCount
!= Present
) {
679 "%a: QEMU v2.7 reset bug: BootCpuCount=%d "
686 // The handling of QemuFwCfgItemSmpCpuCount, across CPU hotplug plus
687 // platform reset (including S3), was corrected in QEMU commit
688 // e3cadac073a9 ("pc: fix FW_CFG_NB_CPUS to account for -device added
689 // CPUs", 2016-11-16), part of release v2.8.0.
691 BootCpuCount
= (UINT16
)Present
;
694 MaxCpuCount
= Possible
;
700 "%a: BootCpuCount=%d MaxCpuCount=%u\n",
705 ASSERT (BootCpuCount
<= MaxCpuCount
);
707 PlatformInfoHob
->PcdCpuMaxLogicalProcessorNumber
= MaxCpuCount
;
708 PlatformInfoHob
->PcdCpuBootLogicalProcessorNumber
= BootCpuCount
;
712 Fetch the boot CPU count and the possible CPU count from QEMU, and expose
713 them to UefiCpuPkg modules. Set the MaxCpuCount field in PlatformInfoHob.
716 MaxCpuCountInitialization (
717 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
720 RETURN_STATUS PcdStatus
;
722 PlatformMaxCpuCountInitialization (PlatformInfoHob
);
724 PcdStatus
= PcdSet32S (PcdCpuBootLogicalProcessorNumber
, PlatformInfoHob
->PcdCpuBootLogicalProcessorNumber
);
725 ASSERT_RETURN_ERROR (PcdStatus
);
726 PcdStatus
= PcdSet32S (PcdCpuMaxLogicalProcessorNumber
, PlatformInfoHob
->PcdCpuMaxLogicalProcessorNumber
);
727 ASSERT_RETURN_ERROR (PcdStatus
);
731 Perform Platform PEI initialization.
733 @param FileHandle Handle of the file being invoked.
734 @param PeiServices Describes the list of possible PEI Services.
736 @return EFI_SUCCESS The PEIM initialized successfully.
742 IN EFI_PEI_FILE_HANDLE FileHandle
,
743 IN CONST EFI_PEI_SERVICES
**PeiServices
748 DEBUG ((DEBUG_INFO
, "Platform PEIM Loaded\n"));
750 mPlatformInfoHob
.SmmSmramRequire
= FeaturePcdGet (PcdSmmSmramRequire
);
751 mPlatformInfoHob
.SevEsIsEnabled
= MemEncryptSevEsIsEnabled ();
752 mPlatformInfoHob
.PcdPciMmio64Size
= PcdGet64 (PcdPciMmio64Size
);
753 mPlatformInfoHob
.DefaultMaxCpuNumber
= PcdGet32 (PcdCpuMaxLogicalProcessorNumber
);
755 PlatformDebugDumpCmos ();
757 if (QemuFwCfgS3Enabled ()) {
758 DEBUG ((DEBUG_INFO
, "S3 support was detected on QEMU\n"));
759 mPlatformInfoHob
.S3Supported
= TRUE
;
760 Status
= PcdSetBoolS (PcdAcpiS3Enable
, TRUE
);
761 ASSERT_EFI_ERROR (Status
);
765 BootModeInitialization (&mPlatformInfoHob
);
766 AddressWidthInitialization (&mPlatformInfoHob
);
769 // Query Host Bridge DID
771 mPlatformInfoHob
.HostBridgeDevId
= PciRead16 (OVMF_HOSTBRIDGE_DID
);
773 MaxCpuCountInitialization (&mPlatformInfoHob
);
775 if (mPlatformInfoHob
.SmmSmramRequire
) {
776 Q35BoardVerification ();
777 Q35TsegMbytesInitialization ();
778 Q35SmramAtDefaultSmbaseInitialization ();
783 PlatformQemuUc32BaseInitialization (&mPlatformInfoHob
);
785 InitializeRamRegions (&mPlatformInfoHob
);
787 if (mPlatformInfoHob
.BootMode
!= BOOT_ON_S3_RESUME
) {
788 if (!mPlatformInfoHob
.SmmSmramRequire
) {
789 ReserveEmuVariableNvStore ();
792 PeiFvInitialization ();
793 MemTypeInfoInitialization ();
794 MemMapInitialization (&mPlatformInfoHob
);
795 NoexecDxeInitialization ();
798 InstallClearCacheCallback ();
800 if (mPlatformInfoHob
.HostBridgeDevId
== 0xffff) {
801 MiscInitializationForMicrovm (&mPlatformInfoHob
);
803 MiscInitialization (&mPlatformInfoHob
);
806 InstallFeatureControlCallback ();