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
59 RETURN_STATUS PcdStatus
;
61 PlatformMemMapInitialization (PlatformInfoHob
);
63 if (PlatformInfoHob
->HostBridgeDevId
== 0xffff /* microvm */) {
67 PcdStatus
= PcdSet64S (PcdPciMmio32Base
, PlatformInfoHob
->PcdPciMmio32Base
);
68 ASSERT_RETURN_ERROR (PcdStatus
);
69 PcdStatus
= PcdSet64S (PcdPciMmio32Size
, PlatformInfoHob
->PcdPciMmio32Size
);
70 ASSERT_RETURN_ERROR (PcdStatus
);
72 PcdStatus
= PcdSet64S (PcdPciIoBase
, PlatformInfoHob
->PcdPciIoBase
);
73 ASSERT_RETURN_ERROR (PcdStatus
);
74 PcdStatus
= PcdSet64S (PcdPciIoSize
, PlatformInfoHob
->PcdPciIoSize
);
75 ASSERT_RETURN_ERROR (PcdStatus
);
79 NoexecDxeInitialization (
85 Status
= PlatformNoexecDxeInitialization (&mPlatformInfoHob
);
86 if (!RETURN_ERROR (Status
)) {
87 Status
= PcdSetBoolS (PcdSetNxForStack
, mPlatformInfoHob
.PcdSetNxForStack
);
88 ASSERT_RETURN_ERROR (Status
);
92 static const UINT8 EmptyFdt
[] = {
93 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x48,
94 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x48,
95 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11,
96 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
101 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09,
105 MicrovmInitialization (
109 FIRMWARE_CONFIG_ITEM FdtItem
;
116 Status
= QemuFwCfgFindFile ("etc/fdt", &FdtItem
, &FdtSize
);
117 if (EFI_ERROR (Status
)) {
118 DEBUG ((DEBUG_INFO
, "%a: no etc/fdt found in fw_cfg, using dummy\n", __FUNCTION__
));
120 FdtSize
= sizeof (EmptyFdt
);
123 FdtPages
= EFI_SIZE_TO_PAGES (FdtSize
);
124 NewBase
= AllocatePages (FdtPages
);
125 if (NewBase
== NULL
) {
126 DEBUG ((DEBUG_INFO
, "%a: AllocatePages failed\n", __FUNCTION__
));
131 QemuFwCfgSelectItem (FdtItem
);
132 QemuFwCfgReadBytes (FdtSize
, NewBase
);
134 CopyMem (NewBase
, EmptyFdt
, FdtSize
);
137 FdtHobData
= BuildGuidHob (&gFdtHobGuid
, sizeof (*FdtHobData
));
138 if (FdtHobData
== NULL
) {
139 DEBUG ((DEBUG_INFO
, "%a: BuildGuidHob failed\n", __FUNCTION__
));
145 "%a: fdt at 0x%x (size %d)\n",
150 *FdtHobData
= (UINTN
)NewBase
;
154 MiscInitializationForMicrovm (
155 IN EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
158 RETURN_STATUS PcdStatus
;
160 ASSERT (PlatformInfoHob
->HostBridgeDevId
== 0xffff);
162 DEBUG ((DEBUG_INFO
, "%a: microvm\n", __FUNCTION__
));
169 // Build the CPU HOB with guest RAM size dependent address width and 16-bits
170 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
171 // S3 resume as well, so we build it unconditionally.)
173 BuildCpuHob (PlatformInfoHob
->PhysMemAddressWidth
, 16);
175 MicrovmInitialization ();
176 PcdStatus
= PcdSet16S (
177 PcdOvmfHostBridgePciDevId
,
178 MICROVM_PSEUDO_DEVICE_ID
180 ASSERT_RETURN_ERROR (PcdStatus
);
185 IN EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
188 RETURN_STATUS PcdStatus
;
190 PlatformMiscInitialization (PlatformInfoHob
);
192 PcdStatus
= PcdSet16S (PcdOvmfHostBridgePciDevId
, PlatformInfoHob
->HostBridgeDevId
);
193 ASSERT_RETURN_ERROR (PcdStatus
);
197 BootModeInitialization (
198 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
203 if (PlatformCmosRead8 (0xF) == 0xFE) {
204 PlatformInfoHob
->BootMode
= BOOT_ON_S3_RESUME
;
207 PlatformCmosWrite8 (0xF, 0x00);
209 Status
= PeiServicesSetBootMode (PlatformInfoHob
->BootMode
);
210 ASSERT_EFI_ERROR (Status
);
212 Status
= PeiServicesInstallPpi (mPpiBootMode
);
213 ASSERT_EFI_ERROR (Status
);
217 ReserveEmuVariableNvStore (
220 EFI_PHYSICAL_ADDRESS VariableStore
;
221 RETURN_STATUS PcdStatus
;
224 // Allocate storage for NV variables early on so it will be
225 // at a consistent address. Since VM memory is preserved
226 // across reboots, this allows the NV variable storage to survive
230 (EFI_PHYSICAL_ADDRESS
)(UINTN
)
231 AllocateRuntimePages (
232 EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize
))
236 "Reserved variable store memory: 0x%lX; size: %dkb\n",
238 (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize
)) / 1024
240 PcdStatus
= PcdSet64S (PcdEmuVariableNvStoreReserved
, VariableStore
);
241 ASSERT_RETURN_ERROR (PcdStatus
);
249 #if defined (MDE_CPU_X64)
250 if (mPlatformInfoHob
.SmmSmramRequire
&& mPlatformInfoHob
.S3Supported
) {
253 "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n",
258 "%a: Please disable S3 on the QEMU command line (see the README),\n",
263 "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n",
274 Q35BoardVerification (
278 if (mPlatformInfoHob
.HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
284 "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
285 "only DID=0x%04x (Q35) is supported\n",
287 mPlatformInfoHob
.HostBridgeDevId
,
288 INTEL_Q35_MCH_DEVICE_ID
295 Fetch the boot CPU count and the possible CPU count from QEMU, and expose
296 them to UefiCpuPkg modules. Set the MaxCpuCount field in PlatformInfoHob.
299 MaxCpuCountInitialization (
300 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
303 RETURN_STATUS PcdStatus
;
305 PlatformMaxCpuCountInitialization (PlatformInfoHob
);
307 PcdStatus
= PcdSet32S (PcdCpuBootLogicalProcessorNumber
, PlatformInfoHob
->PcdCpuBootLogicalProcessorNumber
);
308 ASSERT_RETURN_ERROR (PcdStatus
);
309 PcdStatus
= PcdSet32S (PcdCpuMaxLogicalProcessorNumber
, PlatformInfoHob
->PcdCpuMaxLogicalProcessorNumber
);
310 ASSERT_RETURN_ERROR (PcdStatus
);
314 * @brief Builds PlatformInfo Hob
317 BuildPlatformInfoHob (
321 BuildGuidDataHob (&gUefiOvmfPkgPlatformInfoGuid
, &mPlatformInfoHob
, sizeof (EFI_HOB_PLATFORM_INFO
));
325 Perform Platform PEI initialization.
327 @param FileHandle Handle of the file being invoked.
328 @param PeiServices Describes the list of possible PEI Services.
330 @return EFI_SUCCESS The PEIM initialized successfully.
336 IN EFI_PEI_FILE_HANDLE FileHandle
,
337 IN CONST EFI_PEI_SERVICES
**PeiServices
342 DEBUG ((DEBUG_INFO
, "Platform PEIM Loaded\n"));
344 mPlatformInfoHob
.SmmSmramRequire
= FeaturePcdGet (PcdSmmSmramRequire
);
345 mPlatformInfoHob
.SevEsIsEnabled
= MemEncryptSevEsIsEnabled ();
346 mPlatformInfoHob
.PcdPciMmio64Size
= PcdGet64 (PcdPciMmio64Size
);
347 mPlatformInfoHob
.DefaultMaxCpuNumber
= PcdGet32 (PcdCpuMaxLogicalProcessorNumber
);
349 PlatformDebugDumpCmos ();
351 if (QemuFwCfgS3Enabled ()) {
352 DEBUG ((DEBUG_INFO
, "S3 support was detected on QEMU\n"));
353 mPlatformInfoHob
.S3Supported
= TRUE
;
354 Status
= PcdSetBoolS (PcdAcpiS3Enable
, TRUE
);
355 ASSERT_EFI_ERROR (Status
);
359 BootModeInitialization (&mPlatformInfoHob
);
362 // Query Host Bridge DID
364 mPlatformInfoHob
.HostBridgeDevId
= PciRead16 (OVMF_HOSTBRIDGE_DID
);
365 AddressWidthInitialization (&mPlatformInfoHob
);
367 MaxCpuCountInitialization (&mPlatformInfoHob
);
369 if (mPlatformInfoHob
.SmmSmramRequire
) {
370 Q35BoardVerification ();
371 Q35TsegMbytesInitialization ();
372 Q35SmramAtDefaultSmbaseInitialization ();
377 PlatformQemuUc32BaseInitialization (&mPlatformInfoHob
);
379 InitializeRamRegions (&mPlatformInfoHob
);
381 if (mPlatformInfoHob
.BootMode
!= BOOT_ON_S3_RESUME
) {
382 if (!mPlatformInfoHob
.SmmSmramRequire
) {
383 ReserveEmuVariableNvStore ();
386 PeiFvInitialization ();
387 MemTypeInfoInitialization ();
388 MemMapInitialization (&mPlatformInfoHob
);
389 NoexecDxeInitialization ();
392 InstallClearCacheCallback ();
394 if (mPlatformInfoHob
.HostBridgeDevId
== 0xffff) {
395 MiscInitializationForMicrovm (&mPlatformInfoHob
);
397 MiscInitialization (&mPlatformInfoHob
);
400 IntelTdxInitialize ();
401 InstallFeatureControlCallback ();
402 BuildPlatformInfoHob ();