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
,
56 PlatformMemMapInitialization (
57 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
62 RETURN_STATUS PcdStatus
;
72 // Video memory + Legacy BIOS region
74 PlatformAddIoMemoryRangeHob (0x0A0000, BASE_1MB
);
76 if (PlatformInfoHob
->HostBridgeDevId
== 0xffff /* microvm */) {
77 PlatformAddIoMemoryBaseSizeHob (MICROVM_GED_MMIO_BASE
, SIZE_4KB
);
78 PlatformAddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB
); /* ioapic #1 */
79 PlatformAddIoMemoryBaseSizeHob (0xFEC10000, SIZE_4KB
); /* ioapic #2 */
83 TopOfLowRam
= PlatformGetSystemMemorySizeBelow4gb (PlatformInfoHob
);
85 if (PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
87 // The MMCONFIG area is expected to fall between the top of low RAM and
88 // the base of the 32-bit PCI host aperture.
90 PciExBarBase
= FixedPcdGet64 (PcdPciExpressBaseAddress
);
91 ASSERT (TopOfLowRam
<= PciExBarBase
);
92 ASSERT (PciExBarBase
<= MAX_UINT32
- SIZE_256MB
);
93 PciBase
= (UINT32
)(PciExBarBase
+ SIZE_256MB
);
95 ASSERT (TopOfLowRam
<= PlatformInfoHob
->Uc32Base
);
96 PciBase
= PlatformInfoHob
->Uc32Base
;
100 // address purpose size
101 // ------------ -------- -------------------------
102 // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g)
103 // 0xFC000000 gap 44 MB
104 // 0xFEC00000 IO-APIC 4 KB
105 // 0xFEC01000 gap 1020 KB
106 // 0xFED00000 HPET 1 KB
107 // 0xFED00400 gap 111 KB
108 // 0xFED1C000 gap (PIIX4) / RCRB (ICH9) 16 KB
109 // 0xFED20000 gap 896 KB
110 // 0xFEE00000 LAPIC 1 MB
112 PciSize
= 0xFC000000 - PciBase
;
113 PlatformAddIoMemoryBaseSizeHob (PciBase
, PciSize
);
115 PlatformInfoHob
->PcdPciMmio32Base
= PciBase
;
116 PlatformInfoHob
->PcdPciMmio32Size
= PciSize
;
118 PlatformAddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB
);
119 PlatformAddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB
);
120 if (PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
121 PlatformAddIoMemoryBaseSizeHob (ICH9_ROOT_COMPLEX_BASE
, SIZE_16KB
);
123 // Note: there should be an
125 // PlatformAddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB);
127 // call below, just like the one above for RCBA. However, Linux insists
128 // that the MMCONFIG area be marked in the E820 or UEFI memory map as
129 // "reserved memory" -- Linux does not content itself with a simple gap
130 // in the memory map wherever the MCFG ACPI table points to.
132 // This appears to be a safety measure. The PCI Firmware Specification
133 // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can
134 // *optionally* be returned in [...] EFIGetMemoryMap as reserved memory
135 // [...]". (Emphasis added here.)
137 // Normally we add memory resource descriptor HOBs in
138 // QemuInitializeRam(), and pre-allocate from those with memory
139 // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area
140 // is most definitely not RAM; so, as an exception, cover it with
141 // uncacheable reserved memory right here.
143 PlatformAddReservedMemoryBaseSizeHob (PciExBarBase
, SIZE_256MB
, FALSE
);
144 BuildMemoryAllocationHob (
147 EfiReservedMemoryType
151 PlatformAddIoMemoryBaseSizeHob (PcdGet32 (PcdCpuLocalApicBaseAddress
), SIZE_1MB
);
154 // On Q35, the IO Port space is available for PCI resource allocations from
157 if (PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
160 ASSERT ((ICH9_PMBASE_VALUE
& 0xF000) < PciIoBase
);
164 // Add PCI IO Port space available for PCI resource allocations.
166 BuildResourceDescriptorHob (
168 EFI_RESOURCE_ATTRIBUTE_PRESENT
|
169 EFI_RESOURCE_ATTRIBUTE_INITIALIZED
,
174 PlatformInfoHob
->PcdPciIoBase
= PciIoBase
;
175 PlatformInfoHob
->PcdPciIoSize
= PciIoSize
;
179 MemMapInitialization (
180 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
183 RETURN_STATUS PcdStatus
;
185 PlatformMemMapInitialization (PlatformInfoHob
);
187 if (PlatformInfoHob
->HostBridgeDevId
== 0xffff /* microvm */) {
191 PcdStatus
= PcdSet64S (PcdPciMmio32Base
, PlatformInfoHob
->PcdPciMmio32Base
);
192 ASSERT_RETURN_ERROR (PcdStatus
);
193 PcdStatus
= PcdSet64S (PcdPciMmio32Size
, PlatformInfoHob
->PcdPciMmio32Size
);
194 ASSERT_RETURN_ERROR (PcdStatus
);
196 PcdStatus
= PcdSet64S (PcdPciIoBase
, PlatformInfoHob
->PcdPciIoBase
);
197 ASSERT_RETURN_ERROR (PcdStatus
);
198 PcdStatus
= PcdSet64S (PcdPciIoSize
, PlatformInfoHob
->PcdPciIoSize
);
199 ASSERT_RETURN_ERROR (PcdStatus
);
202 #define UPDATE_BOOLEAN_PCD_FROM_FW_CFG(TokenName) \
205 RETURN_STATUS PcdStatus; \
207 if (!RETURN_ERROR (QemuFwCfgParseBool ( \
208 "opt/ovmf/" #TokenName, &Setting))) { \
209 PcdStatus = PcdSetBoolS (TokenName, Setting); \
210 ASSERT_RETURN_ERROR (PcdStatus); \
215 NoexecDxeInitialization (
219 UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdSetNxForStack
);
223 PciExBarInitialization (
233 // We only support the 256MB size for the MMCONFIG area:
234 // 256 buses * 32 devices * 8 functions * 4096 bytes config space.
236 // The masks used below enforce the Q35 requirements that the MMCONFIG area
237 // be (a) correctly aligned -- here at 256 MB --, (b) located under 64 GB.
239 // Note that (b) also ensures that the minimum address width we have
240 // determined in AddressWidthInitialization(), i.e., 36 bits, will suffice
241 // for DXE's page tables to cover the MMCONFIG area.
243 PciExBarBase
.Uint64
= FixedPcdGet64 (PcdPciExpressBaseAddress
);
244 ASSERT ((PciExBarBase
.Uint32
[1] & MCH_PCIEXBAR_HIGHMASK
) == 0);
245 ASSERT ((PciExBarBase
.Uint32
[0] & MCH_PCIEXBAR_LOWMASK
) == 0);
248 // Clear the PCIEXBAREN bit first, before programming the high register.
250 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW
), 0);
253 // Program the high register. Then program the low register, setting the
254 // MMCONFIG area size and enabling decoding at once.
256 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_HIGH
), PciExBarBase
.Uint32
[1]);
258 DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW
),
259 PciExBarBase
.Uint32
[0] | MCH_PCIEXBAR_BUS_FF
| MCH_PCIEXBAR_EN
263 static const UINT8 EmptyFdt
[] = {
264 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x48,
265 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x48,
266 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11,
267 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09,
276 MicrovmInitialization (
280 FIRMWARE_CONFIG_ITEM FdtItem
;
287 Status
= QemuFwCfgFindFile ("etc/fdt", &FdtItem
, &FdtSize
);
288 if (EFI_ERROR (Status
)) {
289 DEBUG ((DEBUG_INFO
, "%a: no etc/fdt found in fw_cfg, using dummy\n", __FUNCTION__
));
291 FdtSize
= sizeof (EmptyFdt
);
294 FdtPages
= EFI_SIZE_TO_PAGES (FdtSize
);
295 NewBase
= AllocatePages (FdtPages
);
296 if (NewBase
== NULL
) {
297 DEBUG ((DEBUG_INFO
, "%a: AllocatePages failed\n", __FUNCTION__
));
302 QemuFwCfgSelectItem (FdtItem
);
303 QemuFwCfgReadBytes (FdtSize
, NewBase
);
305 CopyMem (NewBase
, EmptyFdt
, FdtSize
);
308 FdtHobData
= BuildGuidHob (&gFdtHobGuid
, sizeof (*FdtHobData
));
309 if (FdtHobData
== NULL
) {
310 DEBUG ((DEBUG_INFO
, "%a: BuildGuidHob failed\n", __FUNCTION__
));
316 "%a: fdt at 0x%x (size %d)\n",
321 *FdtHobData
= (UINTN
)NewBase
;
325 MiscInitializationForMicrovm (
326 IN EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
329 RETURN_STATUS PcdStatus
;
331 ASSERT (PlatformInfoHob
->HostBridgeDevId
== 0xffff);
333 DEBUG ((DEBUG_INFO
, "%a: microvm\n", __FUNCTION__
));
340 // Build the CPU HOB with guest RAM size dependent address width and 16-bits
341 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
342 // S3 resume as well, so we build it unconditionally.)
344 BuildCpuHob (PlatformInfoHob
->PhysMemAddressWidth
, 16);
346 MicrovmInitialization ();
347 PcdStatus
= PcdSet16S (
348 PcdOvmfHostBridgePciDevId
,
349 MICROVM_PSEUDO_DEVICE_ID
351 ASSERT_RETURN_ERROR (PcdStatus
);
356 IN EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
365 RETURN_STATUS PcdStatus
;
373 // Build the CPU HOB with guest RAM size dependent address width and 16-bits
374 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
375 // S3 resume as well, so we build it unconditionally.)
377 BuildCpuHob (PlatformInfoHob
->PhysMemAddressWidth
, 16);
380 // Determine platform type and save Host Bridge DID to PCD
382 switch (PlatformInfoHob
->HostBridgeDevId
) {
383 case INTEL_82441_DEVICE_ID
:
384 PmCmd
= POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET
);
385 Pmba
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA
);
386 PmbaAndVal
= ~(UINT32
)PIIX4_PMBA_MASK
;
387 PmbaOrVal
= PIIX4_PMBA_VALUE
;
388 AcpiCtlReg
= POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC
);
389 AcpiEnBit
= PIIX4_PMREGMISC_PMIOSE
;
391 case INTEL_Q35_MCH_DEVICE_ID
:
392 PmCmd
= POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET
);
393 Pmba
= POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE
);
394 PmbaAndVal
= ~(UINT32
)ICH9_PMBASE_MASK
;
395 PmbaOrVal
= ICH9_PMBASE_VALUE
;
396 AcpiCtlReg
= POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL
);
397 AcpiEnBit
= ICH9_ACPI_CNTL_ACPI_EN
;
399 case CLOUDHV_DEVICE_ID
:
404 "%a: Unknown Host Bridge Device ID: 0x%04x\n",
406 PlatformInfoHob
->HostBridgeDevId
412 PcdStatus
= PcdSet16S (PcdOvmfHostBridgePciDevId
, PlatformInfoHob
->HostBridgeDevId
);
413 ASSERT_RETURN_ERROR (PcdStatus
);
415 if (PlatformInfoHob
->HostBridgeDevId
== CLOUDHV_DEVICE_ID
) {
416 DEBUG ((DEBUG_INFO
, "%a: Cloud Hypervisor is done.\n", __FUNCTION__
));
421 // If the appropriate IOspace enable bit is set, assume the ACPI PMBA has
422 // been configured and skip the setup here. This matches the logic in
423 // AcpiTimerLibConstructor ().
425 if ((PciRead8 (AcpiCtlReg
) & AcpiEnBit
) == 0) {
427 // The PEI phase should be exited with fully accessibe ACPI PM IO space:
430 PciAndThenOr32 (Pmba
, PmbaAndVal
, PmbaOrVal
);
433 // 2. set PCICMD/IOSE
435 PciOr8 (PmCmd
, EFI_PCI_COMMAND_IO_SPACE
);
438 // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN)
440 PciOr8 (AcpiCtlReg
, AcpiEnBit
);
443 if (PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
445 // Set Root Complex Register Block BAR
448 POWER_MGMT_REGISTER_Q35 (ICH9_RCBA
),
449 ICH9_ROOT_COMPLEX_BASE
| ICH9_RCBA_EN
453 // Set PCI Express Register Range Base Address
455 PciExBarInitialization ();
460 BootModeInitialization (
461 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
466 if (PlatformCmosRead8 (0xF) == 0xFE) {
467 PlatformInfoHob
->BootMode
= BOOT_ON_S3_RESUME
;
470 PlatformCmosWrite8 (0xF, 0x00);
472 Status
= PeiServicesSetBootMode (PlatformInfoHob
->BootMode
);
473 ASSERT_EFI_ERROR (Status
);
475 Status
= PeiServicesInstallPpi (mPpiBootMode
);
476 ASSERT_EFI_ERROR (Status
);
480 ReserveEmuVariableNvStore (
483 EFI_PHYSICAL_ADDRESS VariableStore
;
484 RETURN_STATUS PcdStatus
;
487 // Allocate storage for NV variables early on so it will be
488 // at a consistent address. Since VM memory is preserved
489 // across reboots, this allows the NV variable storage to survive
493 (EFI_PHYSICAL_ADDRESS
)(UINTN
)
494 AllocateRuntimePages (
495 EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize
))
499 "Reserved variable store memory: 0x%lX; size: %dkb\n",
501 (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize
)) / 1024
503 PcdStatus
= PcdSet64S (PcdEmuVariableNvStoreReserved
, VariableStore
);
504 ASSERT_RETURN_ERROR (PcdStatus
);
512 #if defined (MDE_CPU_X64)
513 if (mPlatformInfoHob
.SmmSmramRequire
&& mPlatformInfoHob
.S3Supported
) {
516 "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n",
521 "%a: Please disable S3 on the QEMU command line (see the README),\n",
526 "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n",
537 Q35BoardVerification (
541 if (mPlatformInfoHob
.HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
547 "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
548 "only DID=0x%04x (Q35) is supported\n",
550 mPlatformInfoHob
.HostBridgeDevId
,
551 INTEL_Q35_MCH_DEVICE_ID
558 Fetch the boot CPU count and the possible CPU count from QEMU, and expose
559 them to UefiCpuPkg modules. Set the MaxCpuCount field in PlatformInfoHob.
562 PlatformMaxCpuCountInitialization (
563 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
570 // Try to fetch the boot CPU count.
572 QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount
);
573 BootCpuCount
= QemuFwCfgRead16 ();
574 if (BootCpuCount
== 0) {
576 // QEMU doesn't report the boot CPU count. (BootCpuCount == 0) will let
577 // MpInitLib count APs up to (PcdCpuMaxLogicalProcessorNumber - 1), or
578 // until PcdCpuApInitTimeOutInMicroSeconds elapses (whichever is reached
581 DEBUG ((DEBUG_WARN
, "%a: boot CPU count unavailable\n", __FUNCTION__
));
582 MaxCpuCount
= PlatformInfoHob
->DefaultMaxCpuNumber
;
585 // We will expose BootCpuCount to MpInitLib. MpInitLib will count APs up to
586 // (BootCpuCount - 1) precisely, regardless of timeout.
588 // Now try to fetch the possible CPU count.
593 CpuHpBase
= ((PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) ?
594 ICH9_CPU_HOTPLUG_BASE
: PIIX4_CPU_HOTPLUG_BASE
);
597 // If only legacy mode is available in the CPU hotplug register block, or
598 // the register block is completely missing, then the writes below are
601 // 1. Switch the hotplug register block to modern mode.
603 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, 0);
605 // 2. Select a valid CPU for deterministic reading of
606 // QEMU_CPUHP_R_CMD_DATA2.
608 // CPU#0 is always valid; it is the always present and non-removable
611 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, 0);
613 // 3. Send a command after which QEMU_CPUHP_R_CMD_DATA2 is specified to
614 // read as zero, and which does not invalidate the selector. (The
615 // selector may change, but it must not become invalid.)
617 // Send QEMU_CPUHP_CMD_GET_PENDING, as it will prove useful later.
619 IoWrite8 (CpuHpBase
+ QEMU_CPUHP_W_CMD
, QEMU_CPUHP_CMD_GET_PENDING
);
621 // 4. Read QEMU_CPUHP_R_CMD_DATA2.
623 // If the register block is entirely missing, then this is an unassigned
624 // IO read, returning all-bits-one.
626 // If only legacy mode is available, then bit#0 stands for CPU#0 in the
627 // "CPU present bitmap". CPU#0 is always present.
629 // Otherwise, QEMU_CPUHP_R_CMD_DATA2 is either still reserved (returning
630 // all-bits-zero), or it is specified to read as zero after the above
631 // steps. Both cases confirm modern mode.
633 CmdData2
= IoRead32 (CpuHpBase
+ QEMU_CPUHP_R_CMD_DATA2
);
634 DEBUG ((DEBUG_VERBOSE
, "%a: CmdData2=0x%x\n", __FUNCTION__
, CmdData2
));
637 // QEMU doesn't support the modern CPU hotplug interface. Assume that the
638 // possible CPU count equals the boot CPU count (precluding hotplug).
642 "%a: modern CPU hotplug interface unavailable\n",
645 MaxCpuCount
= BootCpuCount
;
648 // Grab the possible CPU count from the modern CPU hotplug interface.
650 UINT32 Present
, Possible
, Selected
;
656 // We've sent QEMU_CPUHP_CMD_GET_PENDING last; this ensures
657 // QEMU_CPUHP_RW_CMD_DATA can now be read usefully. However,
658 // QEMU_CPUHP_CMD_GET_PENDING may have selected a CPU with actual pending
659 // hotplug events; therefore, select CPU#0 forcibly.
661 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, Possible
);
667 // Read the status of the currently selected CPU. This will help with a
668 // sanity check against "BootCpuCount".
670 CpuStatus
= IoRead8 (CpuHpBase
+ QEMU_CPUHP_R_CPU_STAT
);
671 if ((CpuStatus
& QEMU_CPUHP_STAT_ENABLED
) != 0) {
676 // Attempt to select the next CPU.
679 IoWrite32 (CpuHpBase
+ QEMU_CPUHP_W_CPU_SEL
, Possible
);
681 // If the selection is successful, then the following read will return
682 // the selector (which we know is positive at this point). Otherwise,
683 // the read will return 0.
685 Selected
= IoRead32 (CpuHpBase
+ QEMU_CPUHP_RW_CMD_DATA
);
686 ASSERT (Selected
== Possible
|| Selected
== 0);
687 } while (Selected
> 0);
690 // Sanity check: fw_cfg and the modern CPU hotplug interface should
691 // return the same boot CPU count.
693 if (BootCpuCount
!= Present
) {
696 "%a: QEMU v2.7 reset bug: BootCpuCount=%d "
703 // The handling of QemuFwCfgItemSmpCpuCount, across CPU hotplug plus
704 // platform reset (including S3), was corrected in QEMU commit
705 // e3cadac073a9 ("pc: fix FW_CFG_NB_CPUS to account for -device added
706 // CPUs", 2016-11-16), part of release v2.8.0.
708 BootCpuCount
= (UINT16
)Present
;
711 MaxCpuCount
= Possible
;
717 "%a: BootCpuCount=%d MaxCpuCount=%u\n",
722 ASSERT (BootCpuCount
<= MaxCpuCount
);
724 PlatformInfoHob
->PcdCpuMaxLogicalProcessorNumber
= MaxCpuCount
;
725 PlatformInfoHob
->PcdCpuBootLogicalProcessorNumber
= BootCpuCount
;
729 Fetch the boot CPU count and the possible CPU count from QEMU, and expose
730 them to UefiCpuPkg modules. Set the MaxCpuCount field in PlatformInfoHob.
733 MaxCpuCountInitialization (
734 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
737 RETURN_STATUS PcdStatus
;
739 PlatformMaxCpuCountInitialization (PlatformInfoHob
);
741 PcdStatus
= PcdSet32S (PcdCpuBootLogicalProcessorNumber
, PlatformInfoHob
->PcdCpuBootLogicalProcessorNumber
);
742 ASSERT_RETURN_ERROR (PcdStatus
);
743 PcdStatus
= PcdSet32S (PcdCpuMaxLogicalProcessorNumber
, PlatformInfoHob
->PcdCpuMaxLogicalProcessorNumber
);
744 ASSERT_RETURN_ERROR (PcdStatus
);
748 Perform Platform PEI initialization.
750 @param FileHandle Handle of the file being invoked.
751 @param PeiServices Describes the list of possible PEI Services.
753 @return EFI_SUCCESS The PEIM initialized successfully.
759 IN EFI_PEI_FILE_HANDLE FileHandle
,
760 IN CONST EFI_PEI_SERVICES
**PeiServices
765 DEBUG ((DEBUG_INFO
, "Platform PEIM Loaded\n"));
767 mPlatformInfoHob
.SmmSmramRequire
= FeaturePcdGet (PcdSmmSmramRequire
);
768 mPlatformInfoHob
.SevEsIsEnabled
= MemEncryptSevEsIsEnabled ();
769 mPlatformInfoHob
.PcdPciMmio64Size
= PcdGet64 (PcdPciMmio64Size
);
770 mPlatformInfoHob
.DefaultMaxCpuNumber
= PcdGet32 (PcdCpuMaxLogicalProcessorNumber
);
772 PlatformDebugDumpCmos ();
774 if (QemuFwCfgS3Enabled ()) {
775 DEBUG ((DEBUG_INFO
, "S3 support was detected on QEMU\n"));
776 mPlatformInfoHob
.S3Supported
= TRUE
;
777 Status
= PcdSetBoolS (PcdAcpiS3Enable
, TRUE
);
778 ASSERT_EFI_ERROR (Status
);
782 BootModeInitialization (&mPlatformInfoHob
);
783 AddressWidthInitialization (&mPlatformInfoHob
);
786 // Query Host Bridge DID
788 mPlatformInfoHob
.HostBridgeDevId
= PciRead16 (OVMF_HOSTBRIDGE_DID
);
790 MaxCpuCountInitialization (&mPlatformInfoHob
);
792 if (mPlatformInfoHob
.SmmSmramRequire
) {
793 Q35BoardVerification ();
794 Q35TsegMbytesInitialization ();
795 Q35SmramAtDefaultSmbaseInitialization ();
800 PlatformQemuUc32BaseInitialization (&mPlatformInfoHob
);
802 InitializeRamRegions (&mPlatformInfoHob
);
804 if (mPlatformInfoHob
.BootMode
!= BOOT_ON_S3_RESUME
) {
805 if (!mPlatformInfoHob
.SmmSmramRequire
) {
806 ReserveEmuVariableNvStore ();
809 PeiFvInitialization ();
810 MemTypeInfoInitialization ();
811 MemMapInitialization (&mPlatformInfoHob
);
812 NoexecDxeInitialization ();
815 InstallClearCacheCallback ();
817 if (mPlatformInfoHob
.HostBridgeDevId
== 0xffff) {
818 MiscInitializationForMicrovm (&mPlatformInfoHob
);
820 MiscInitialization (&mPlatformInfoHob
);
823 InstallFeatureControlCallback ();