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_PEI_PPI_DESCRIPTOR mPpiBootMode
[] = {
46 EFI_PEI_PPI_DESCRIPTOR_PPI
| EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST
,
47 &gEfiPeiMasterBootModePpiGuid
,
53 MemMapInitialization (
54 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
57 RETURN_STATUS PcdStatus
;
59 PlatformMemMapInitialization (PlatformInfoHob
);
61 if (PlatformInfoHob
->HostBridgeDevId
== 0xffff /* microvm */) {
65 PcdStatus
= PcdSet64S (PcdPciMmio32Base
, PlatformInfoHob
->PcdPciMmio32Base
);
66 ASSERT_RETURN_ERROR (PcdStatus
);
67 PcdStatus
= PcdSet64S (PcdPciMmio32Size
, PlatformInfoHob
->PcdPciMmio32Size
);
68 ASSERT_RETURN_ERROR (PcdStatus
);
70 PcdStatus
= PcdSet64S (PcdPciIoBase
, PlatformInfoHob
->PcdPciIoBase
);
71 ASSERT_RETURN_ERROR (PcdStatus
);
72 PcdStatus
= PcdSet64S (PcdPciIoSize
, PlatformInfoHob
->PcdPciIoSize
);
73 ASSERT_RETURN_ERROR (PcdStatus
);
78 NoexecDxeInitialization (
79 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
84 Status
= PlatformNoexecDxeInitialization (PlatformInfoHob
);
85 if (!RETURN_ERROR (Status
)) {
86 Status
= PcdSetBoolS (PcdSetNxForStack
, PlatformInfoHob
->PcdSetNxForStack
);
87 ASSERT_RETURN_ERROR (Status
);
91 static const UINT8 EmptyFdt
[] = {
92 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x48,
93 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x48,
94 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11,
95 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
100 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09,
104 MicrovmInitialization (
108 FIRMWARE_CONFIG_ITEM FdtItem
;
115 Status
= QemuFwCfgFindFile ("etc/fdt", &FdtItem
, &FdtSize
);
116 if (EFI_ERROR (Status
)) {
117 DEBUG ((DEBUG_INFO
, "%a: no etc/fdt found in fw_cfg, using dummy\n", __FUNCTION__
));
119 FdtSize
= sizeof (EmptyFdt
);
122 FdtPages
= EFI_SIZE_TO_PAGES (FdtSize
);
123 NewBase
= AllocatePages (FdtPages
);
124 if (NewBase
== NULL
) {
125 DEBUG ((DEBUG_INFO
, "%a: AllocatePages failed\n", __FUNCTION__
));
130 QemuFwCfgSelectItem (FdtItem
);
131 QemuFwCfgReadBytes (FdtSize
, NewBase
);
133 CopyMem (NewBase
, EmptyFdt
, FdtSize
);
136 FdtHobData
= BuildGuidHob (&gFdtHobGuid
, sizeof (*FdtHobData
));
137 if (FdtHobData
== NULL
) {
138 DEBUG ((DEBUG_INFO
, "%a: BuildGuidHob failed\n", __FUNCTION__
));
144 "%a: fdt at 0x%x (size %d)\n",
149 *FdtHobData
= (UINTN
)NewBase
;
153 MiscInitializationForMicrovm (
154 IN EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
157 RETURN_STATUS PcdStatus
;
159 ASSERT (PlatformInfoHob
->HostBridgeDevId
== 0xffff);
161 DEBUG ((DEBUG_INFO
, "%a: microvm\n", __FUNCTION__
));
168 // Build the CPU HOB with guest RAM size dependent address width and 16-bits
169 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
170 // S3 resume as well, so we build it unconditionally.)
172 BuildCpuHob (PlatformInfoHob
->PhysMemAddressWidth
, 16);
174 MicrovmInitialization ();
175 PcdStatus
= PcdSet16S (
176 PcdOvmfHostBridgePciDevId
,
177 MICROVM_PSEUDO_DEVICE_ID
179 ASSERT_RETURN_ERROR (PcdStatus
);
184 IN EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
187 RETURN_STATUS PcdStatus
;
189 PlatformMiscInitialization (PlatformInfoHob
);
191 PcdStatus
= PcdSet16S (PcdOvmfHostBridgePciDevId
, PlatformInfoHob
->HostBridgeDevId
);
192 ASSERT_RETURN_ERROR (PcdStatus
);
196 BootModeInitialization (
197 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
202 if (PlatformCmosRead8 (0xF) == 0xFE) {
203 PlatformInfoHob
->BootMode
= BOOT_ON_S3_RESUME
;
206 PlatformCmosWrite8 (0xF, 0x00);
208 Status
= PeiServicesSetBootMode (PlatformInfoHob
->BootMode
);
209 ASSERT_EFI_ERROR (Status
);
211 Status
= PeiServicesInstallPpi (mPpiBootMode
);
212 ASSERT_EFI_ERROR (Status
);
216 ReserveEmuVariableNvStore (
219 EFI_PHYSICAL_ADDRESS VariableStore
;
220 RETURN_STATUS PcdStatus
;
222 VariableStore
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)PlatformReserveEmuVariableNvStore ();
223 PcdStatus
= PcdSet64S (PcdEmuVariableNvStoreReserved
, VariableStore
);
225 #ifdef SECURE_BOOT_FEATURE_ENABLED
226 PlatformInitEmuVariableNvStore ((VOID
*)(UINTN
)VariableStore
);
229 ASSERT_RETURN_ERROR (PcdStatus
);
235 IN EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
238 #if defined (MDE_CPU_X64)
239 if (PlatformInfoHob
->SmmSmramRequire
&& PlatformInfoHob
->S3Supported
) {
242 "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n",
247 "%a: Please disable S3 on the QEMU command line (see the README),\n",
252 "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n",
264 Q35BoardVerification (
265 IN EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
268 if (PlatformInfoHob
->HostBridgeDevId
== INTEL_Q35_MCH_DEVICE_ID
) {
274 "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
275 "only DID=0x%04x (Q35) is supported\n",
277 PlatformInfoHob
->HostBridgeDevId
,
278 INTEL_Q35_MCH_DEVICE_ID
285 Fetch the boot CPU count and the possible CPU count from QEMU, and expose
286 them to UefiCpuPkg modules. Set the MaxCpuCount field in PlatformInfoHob.
289 MaxCpuCountInitialization (
290 IN OUT EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
293 RETURN_STATUS PcdStatus
;
295 PlatformMaxCpuCountInitialization (PlatformInfoHob
);
297 PcdStatus
= PcdSet32S (PcdCpuBootLogicalProcessorNumber
, PlatformInfoHob
->PcdCpuBootLogicalProcessorNumber
);
298 ASSERT_RETURN_ERROR (PcdStatus
);
299 PcdStatus
= PcdSet32S (PcdCpuMaxLogicalProcessorNumber
, PlatformInfoHob
->PcdCpuMaxLogicalProcessorNumber
);
300 ASSERT_RETURN_ERROR (PcdStatus
);
304 * @brief Builds PlatformInfo Hob
306 EFI_HOB_PLATFORM_INFO
*
307 BuildPlatformInfoHob (
311 EFI_HOB_PLATFORM_INFO PlatformInfoHob
;
312 EFI_HOB_GUID_TYPE
*GuidHob
;
314 ZeroMem (&PlatformInfoHob
, sizeof PlatformInfoHob
);
315 BuildGuidDataHob (&gUefiOvmfPkgPlatformInfoGuid
, &PlatformInfoHob
, sizeof (EFI_HOB_PLATFORM_INFO
));
316 GuidHob
= GetFirstGuidHob (&gUefiOvmfPkgPlatformInfoGuid
);
317 return (EFI_HOB_PLATFORM_INFO
*)GET_GUID_HOB_DATA (GuidHob
);
321 Perform Platform PEI initialization.
323 @param FileHandle Handle of the file being invoked.
324 @param PeiServices Describes the list of possible PEI Services.
326 @return EFI_SUCCESS The PEIM initialized successfully.
332 IN EFI_PEI_FILE_HANDLE FileHandle
,
333 IN CONST EFI_PEI_SERVICES
**PeiServices
336 EFI_HOB_PLATFORM_INFO
*PlatformInfoHob
;
339 DEBUG ((DEBUG_INFO
, "Platform PEIM Loaded\n"));
340 PlatformInfoHob
= BuildPlatformInfoHob ();
342 PlatformInfoHob
->SmmSmramRequire
= FeaturePcdGet (PcdSmmSmramRequire
);
343 PlatformInfoHob
->SevEsIsEnabled
= MemEncryptSevEsIsEnabled ();
344 PlatformInfoHob
->PcdPciMmio64Size
= PcdGet64 (PcdPciMmio64Size
);
345 PlatformInfoHob
->DefaultMaxCpuNumber
= PcdGet32 (PcdCpuMaxLogicalProcessorNumber
);
347 PlatformDebugDumpCmos ();
349 if (QemuFwCfgS3Enabled ()) {
350 DEBUG ((DEBUG_INFO
, "S3 support was detected on QEMU\n"));
351 PlatformInfoHob
->S3Supported
= TRUE
;
352 Status
= PcdSetBoolS (PcdAcpiS3Enable
, TRUE
);
353 ASSERT_EFI_ERROR (Status
);
356 S3Verification (PlatformInfoHob
);
357 BootModeInitialization (PlatformInfoHob
);
360 // Query Host Bridge DID
362 PlatformInfoHob
->HostBridgeDevId
= PciRead16 (OVMF_HOSTBRIDGE_DID
);
363 AddressWidthInitialization (PlatformInfoHob
);
365 MaxCpuCountInitialization (PlatformInfoHob
);
367 if (PlatformInfoHob
->SmmSmramRequire
) {
368 Q35BoardVerification (PlatformInfoHob
);
369 Q35TsegMbytesInitialization (PlatformInfoHob
);
370 Q35SmramAtDefaultSmbaseInitialization (PlatformInfoHob
);
373 PublishPeiMemory (PlatformInfoHob
);
375 PlatformQemuUc32BaseInitialization (PlatformInfoHob
);
377 InitializeRamRegions (PlatformInfoHob
);
379 if (PlatformInfoHob
->BootMode
!= BOOT_ON_S3_RESUME
) {
380 if (!PlatformInfoHob
->SmmSmramRequire
) {
381 ReserveEmuVariableNvStore ();
384 PeiFvInitialization (PlatformInfoHob
);
385 MemTypeInfoInitialization (PlatformInfoHob
);
386 MemMapInitialization (PlatformInfoHob
);
387 NoexecDxeInitialization (PlatformInfoHob
);
390 InstallClearCacheCallback ();
391 AmdSevInitialize (PlatformInfoHob
);
392 if (PlatformInfoHob
->HostBridgeDevId
== 0xffff) {
393 MiscInitializationForMicrovm (PlatformInfoHob
);
395 MiscInitialization (PlatformInfoHob
);
398 IntelTdxInitialize ();
399 InstallFeatureControlCallback ();