]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/PlatformPei/Platform.c
OvmfPkg/Microvm/pcie: mPhysMemAddressWidth tweak
[mirror_edk2.git] / OvmfPkg / PlatformPei / Platform.c
1 /**@file
2 Platform PEI driver
3
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 //
12 // The package level header files this module uses
13 //
14 #include <PiPei.h>
15
16 //
17 // The Library classes this module consumes
18 //
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>
41
42 #include "Platform.h"
43
44 EFI_HOB_PLATFORM_INFO mPlatformInfoHob = { 0 };
45
46 EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {
47 {
48 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
49 &gEfiPeiMasterBootModePpiGuid,
50 NULL
51 }
52 };
53
54 VOID
55 MemMapInitialization (
56 IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
57 )
58 {
59 RETURN_STATUS PcdStatus;
60
61 PlatformMemMapInitialization (PlatformInfoHob);
62
63 if (PlatformInfoHob->HostBridgeDevId == 0xffff /* microvm */) {
64 return;
65 }
66
67 PcdStatus = PcdSet64S (PcdPciMmio32Base, PlatformInfoHob->PcdPciMmio32Base);
68 ASSERT_RETURN_ERROR (PcdStatus);
69 PcdStatus = PcdSet64S (PcdPciMmio32Size, PlatformInfoHob->PcdPciMmio32Size);
70 ASSERT_RETURN_ERROR (PcdStatus);
71
72 PcdStatus = PcdSet64S (PcdPciIoBase, PlatformInfoHob->PcdPciIoBase);
73 ASSERT_RETURN_ERROR (PcdStatus);
74 PcdStatus = PcdSet64S (PcdPciIoSize, PlatformInfoHob->PcdPciIoSize);
75 ASSERT_RETURN_ERROR (PcdStatus);
76 }
77
78 VOID
79 NoexecDxeInitialization (
80 VOID
81 )
82 {
83 RETURN_STATUS Status;
84
85 Status = PlatformNoexecDxeInitialization (&mPlatformInfoHob);
86 if (!RETURN_ERROR (Status)) {
87 Status = PcdSetBoolS (PcdSetNxForStack, mPlatformInfoHob.PcdSetNxForStack);
88 ASSERT_RETURN_ERROR (Status);
89 }
90 }
91
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,
102 };
103
104 VOID
105 MicrovmInitialization (
106 VOID
107 )
108 {
109 FIRMWARE_CONFIG_ITEM FdtItem;
110 UINTN FdtSize;
111 UINTN FdtPages;
112 EFI_STATUS Status;
113 UINT64 *FdtHobData;
114 VOID *NewBase;
115
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__));
119 FdtItem = 0;
120 FdtSize = sizeof (EmptyFdt);
121 }
122
123 FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
124 NewBase = AllocatePages (FdtPages);
125 if (NewBase == NULL) {
126 DEBUG ((DEBUG_INFO, "%a: AllocatePages failed\n", __FUNCTION__));
127 return;
128 }
129
130 if (FdtItem) {
131 QemuFwCfgSelectItem (FdtItem);
132 QemuFwCfgReadBytes (FdtSize, NewBase);
133 } else {
134 CopyMem (NewBase, EmptyFdt, FdtSize);
135 }
136
137 FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof (*FdtHobData));
138 if (FdtHobData == NULL) {
139 DEBUG ((DEBUG_INFO, "%a: BuildGuidHob failed\n", __FUNCTION__));
140 return;
141 }
142
143 DEBUG ((
144 DEBUG_INFO,
145 "%a: fdt at 0x%x (size %d)\n",
146 __FUNCTION__,
147 NewBase,
148 FdtSize
149 ));
150 *FdtHobData = (UINTN)NewBase;
151 }
152
153 VOID
154 MiscInitializationForMicrovm (
155 IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
156 )
157 {
158 RETURN_STATUS PcdStatus;
159
160 ASSERT (PlatformInfoHob->HostBridgeDevId == 0xffff);
161
162 DEBUG ((DEBUG_INFO, "%a: microvm\n", __FUNCTION__));
163 //
164 // Disable A20 Mask
165 //
166 IoOr8 (0x92, BIT1);
167
168 //
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.)
172 //
173 BuildCpuHob (PlatformInfoHob->PhysMemAddressWidth, 16);
174
175 MicrovmInitialization ();
176 PcdStatus = PcdSet16S (
177 PcdOvmfHostBridgePciDevId,
178 MICROVM_PSEUDO_DEVICE_ID
179 );
180 ASSERT_RETURN_ERROR (PcdStatus);
181 }
182
183 VOID
184 MiscInitialization (
185 IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
186 )
187 {
188 RETURN_STATUS PcdStatus;
189
190 PlatformMiscInitialization (PlatformInfoHob);
191
192 PcdStatus = PcdSet16S (PcdOvmfHostBridgePciDevId, PlatformInfoHob->HostBridgeDevId);
193 ASSERT_RETURN_ERROR (PcdStatus);
194 }
195
196 VOID
197 BootModeInitialization (
198 IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
199 )
200 {
201 EFI_STATUS Status;
202
203 if (PlatformCmosRead8 (0xF) == 0xFE) {
204 PlatformInfoHob->BootMode = BOOT_ON_S3_RESUME;
205 }
206
207 PlatformCmosWrite8 (0xF, 0x00);
208
209 Status = PeiServicesSetBootMode (PlatformInfoHob->BootMode);
210 ASSERT_EFI_ERROR (Status);
211
212 Status = PeiServicesInstallPpi (mPpiBootMode);
213 ASSERT_EFI_ERROR (Status);
214 }
215
216 VOID
217 ReserveEmuVariableNvStore (
218 )
219 {
220 EFI_PHYSICAL_ADDRESS VariableStore;
221 RETURN_STATUS PcdStatus;
222
223 //
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
227 // a VM reboot.
228 //
229 VariableStore =
230 (EFI_PHYSICAL_ADDRESS)(UINTN)
231 AllocateRuntimePages (
232 EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize))
233 );
234 DEBUG ((
235 DEBUG_INFO,
236 "Reserved variable store memory: 0x%lX; size: %dkb\n",
237 VariableStore,
238 (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024
239 ));
240 PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore);
241 ASSERT_RETURN_ERROR (PcdStatus);
242 }
243
244 VOID
245 S3Verification (
246 VOID
247 )
248 {
249 #if defined (MDE_CPU_X64)
250 if (mPlatformInfoHob.SmmSmramRequire && mPlatformInfoHob.S3Supported) {
251 DEBUG ((
252 DEBUG_ERROR,
253 "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n",
254 __FUNCTION__
255 ));
256 DEBUG ((
257 DEBUG_ERROR,
258 "%a: Please disable S3 on the QEMU command line (see the README),\n",
259 __FUNCTION__
260 ));
261 DEBUG ((
262 DEBUG_ERROR,
263 "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n",
264 __FUNCTION__
265 ));
266 ASSERT (FALSE);
267 CpuDeadLoop ();
268 }
269
270 #endif
271 }
272
273 VOID
274 Q35BoardVerification (
275 VOID
276 )
277 {
278 if (mPlatformInfoHob.HostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
279 return;
280 }
281
282 DEBUG ((
283 DEBUG_ERROR,
284 "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
285 "only DID=0x%04x (Q35) is supported\n",
286 __FUNCTION__,
287 mPlatformInfoHob.HostBridgeDevId,
288 INTEL_Q35_MCH_DEVICE_ID
289 ));
290 ASSERT (FALSE);
291 CpuDeadLoop ();
292 }
293
294 /**
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.
297 **/
298 VOID
299 MaxCpuCountInitialization (
300 IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
301 )
302 {
303 RETURN_STATUS PcdStatus;
304
305 PlatformMaxCpuCountInitialization (PlatformInfoHob);
306
307 PcdStatus = PcdSet32S (PcdCpuBootLogicalProcessorNumber, PlatformInfoHob->PcdCpuBootLogicalProcessorNumber);
308 ASSERT_RETURN_ERROR (PcdStatus);
309 PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, PlatformInfoHob->PcdCpuMaxLogicalProcessorNumber);
310 ASSERT_RETURN_ERROR (PcdStatus);
311 }
312
313 /**
314 * @brief Builds PlatformInfo Hob
315 */
316 VOID
317 BuildPlatformInfoHob (
318 VOID
319 )
320 {
321 BuildGuidDataHob (&gUefiOvmfPkgPlatformInfoGuid, &mPlatformInfoHob, sizeof (EFI_HOB_PLATFORM_INFO));
322 }
323
324 /**
325 Perform Platform PEI initialization.
326
327 @param FileHandle Handle of the file being invoked.
328 @param PeiServices Describes the list of possible PEI Services.
329
330 @return EFI_SUCCESS The PEIM initialized successfully.
331
332 **/
333 EFI_STATUS
334 EFIAPI
335 InitializePlatform (
336 IN EFI_PEI_FILE_HANDLE FileHandle,
337 IN CONST EFI_PEI_SERVICES **PeiServices
338 )
339 {
340 EFI_STATUS Status;
341
342 DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));
343
344 mPlatformInfoHob.SmmSmramRequire = FeaturePcdGet (PcdSmmSmramRequire);
345 mPlatformInfoHob.SevEsIsEnabled = MemEncryptSevEsIsEnabled ();
346 mPlatformInfoHob.PcdPciMmio64Size = PcdGet64 (PcdPciMmio64Size);
347 mPlatformInfoHob.DefaultMaxCpuNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
348
349 PlatformDebugDumpCmos ();
350
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);
356 }
357
358 S3Verification ();
359 BootModeInitialization (&mPlatformInfoHob);
360
361 //
362 // Query Host Bridge DID
363 //
364 mPlatformInfoHob.HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
365 AddressWidthInitialization (&mPlatformInfoHob);
366
367 MaxCpuCountInitialization (&mPlatformInfoHob);
368
369 if (mPlatformInfoHob.SmmSmramRequire) {
370 Q35BoardVerification ();
371 Q35TsegMbytesInitialization ();
372 Q35SmramAtDefaultSmbaseInitialization ();
373 }
374
375 PublishPeiMemory ();
376
377 PlatformQemuUc32BaseInitialization (&mPlatformInfoHob);
378
379 InitializeRamRegions (&mPlatformInfoHob);
380
381 if (mPlatformInfoHob.BootMode != BOOT_ON_S3_RESUME) {
382 if (!mPlatformInfoHob.SmmSmramRequire) {
383 ReserveEmuVariableNvStore ();
384 }
385
386 PeiFvInitialization ();
387 MemTypeInfoInitialization ();
388 MemMapInitialization (&mPlatformInfoHob);
389 NoexecDxeInitialization ();
390 }
391
392 InstallClearCacheCallback ();
393 AmdSevInitialize ();
394 if (mPlatformInfoHob.HostBridgeDevId == 0xffff) {
395 MiscInitializationForMicrovm (&mPlatformInfoHob);
396 } else {
397 MiscInitialization (&mPlatformInfoHob);
398 }
399
400 IntelTdxInitialize ();
401 InstallFeatureControlCallback ();
402 BuildPlatformInfoHob ();
403
404 return EFI_SUCCESS;
405 }