]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/PlatformPei/Platform.c
OvmfPkg/PlatformPei: Update ReserveEmuVariableNvStore
[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 VariableStore = (EFI_PHYSICAL_ADDRESS)(UINTN)PlatformReserveEmuVariableNvStore ();
224 PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore);
225
226 #ifdef SECURE_BOOT_FEATURE_ENABLED
227 PlatformInitEmuVariableNvStore ((VOID *)(UINTN)VariableStore);
228 #endif
229
230 ASSERT_RETURN_ERROR (PcdStatus);
231 }
232
233 VOID
234 S3Verification (
235 VOID
236 )
237 {
238 #if defined (MDE_CPU_X64)
239 if (mPlatformInfoHob.SmmSmramRequire && mPlatformInfoHob.S3Supported) {
240 DEBUG ((
241 DEBUG_ERROR,
242 "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n",
243 __FUNCTION__
244 ));
245 DEBUG ((
246 DEBUG_ERROR,
247 "%a: Please disable S3 on the QEMU command line (see the README),\n",
248 __FUNCTION__
249 ));
250 DEBUG ((
251 DEBUG_ERROR,
252 "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n",
253 __FUNCTION__
254 ));
255 ASSERT (FALSE);
256 CpuDeadLoop ();
257 }
258
259 #endif
260 }
261
262 VOID
263 Q35BoardVerification (
264 VOID
265 )
266 {
267 if (mPlatformInfoHob.HostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
268 return;
269 }
270
271 DEBUG ((
272 DEBUG_ERROR,
273 "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
274 "only DID=0x%04x (Q35) is supported\n",
275 __FUNCTION__,
276 mPlatformInfoHob.HostBridgeDevId,
277 INTEL_Q35_MCH_DEVICE_ID
278 ));
279 ASSERT (FALSE);
280 CpuDeadLoop ();
281 }
282
283 /**
284 Fetch the boot CPU count and the possible CPU count from QEMU, and expose
285 them to UefiCpuPkg modules. Set the MaxCpuCount field in PlatformInfoHob.
286 **/
287 VOID
288 MaxCpuCountInitialization (
289 IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
290 )
291 {
292 RETURN_STATUS PcdStatus;
293
294 PlatformMaxCpuCountInitialization (PlatformInfoHob);
295
296 PcdStatus = PcdSet32S (PcdCpuBootLogicalProcessorNumber, PlatformInfoHob->PcdCpuBootLogicalProcessorNumber);
297 ASSERT_RETURN_ERROR (PcdStatus);
298 PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, PlatformInfoHob->PcdCpuMaxLogicalProcessorNumber);
299 ASSERT_RETURN_ERROR (PcdStatus);
300 }
301
302 /**
303 * @brief Builds PlatformInfo Hob
304 */
305 VOID
306 BuildPlatformInfoHob (
307 VOID
308 )
309 {
310 BuildGuidDataHob (&gUefiOvmfPkgPlatformInfoGuid, &mPlatformInfoHob, sizeof (EFI_HOB_PLATFORM_INFO));
311 }
312
313 /**
314 Perform Platform PEI initialization.
315
316 @param FileHandle Handle of the file being invoked.
317 @param PeiServices Describes the list of possible PEI Services.
318
319 @return EFI_SUCCESS The PEIM initialized successfully.
320
321 **/
322 EFI_STATUS
323 EFIAPI
324 InitializePlatform (
325 IN EFI_PEI_FILE_HANDLE FileHandle,
326 IN CONST EFI_PEI_SERVICES **PeiServices
327 )
328 {
329 EFI_STATUS Status;
330
331 DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));
332
333 mPlatformInfoHob.SmmSmramRequire = FeaturePcdGet (PcdSmmSmramRequire);
334 mPlatformInfoHob.SevEsIsEnabled = MemEncryptSevEsIsEnabled ();
335 mPlatformInfoHob.PcdPciMmio64Size = PcdGet64 (PcdPciMmio64Size);
336 mPlatformInfoHob.DefaultMaxCpuNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
337
338 PlatformDebugDumpCmos ();
339
340 if (QemuFwCfgS3Enabled ()) {
341 DEBUG ((DEBUG_INFO, "S3 support was detected on QEMU\n"));
342 mPlatformInfoHob.S3Supported = TRUE;
343 Status = PcdSetBoolS (PcdAcpiS3Enable, TRUE);
344 ASSERT_EFI_ERROR (Status);
345 }
346
347 S3Verification ();
348 BootModeInitialization (&mPlatformInfoHob);
349
350 //
351 // Query Host Bridge DID
352 //
353 mPlatformInfoHob.HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
354 AddressWidthInitialization (&mPlatformInfoHob);
355
356 MaxCpuCountInitialization (&mPlatformInfoHob);
357
358 if (mPlatformInfoHob.SmmSmramRequire) {
359 Q35BoardVerification ();
360 Q35TsegMbytesInitialization ();
361 Q35SmramAtDefaultSmbaseInitialization ();
362 }
363
364 PublishPeiMemory ();
365
366 PlatformQemuUc32BaseInitialization (&mPlatformInfoHob);
367
368 InitializeRamRegions (&mPlatformInfoHob);
369
370 if (mPlatformInfoHob.BootMode != BOOT_ON_S3_RESUME) {
371 if (!mPlatformInfoHob.SmmSmramRequire) {
372 ReserveEmuVariableNvStore ();
373 }
374
375 PeiFvInitialization ();
376 MemTypeInfoInitialization ();
377 MemMapInitialization (&mPlatformInfoHob);
378 NoexecDxeInitialization ();
379 }
380
381 InstallClearCacheCallback ();
382 AmdSevInitialize ();
383 if (mPlatformInfoHob.HostBridgeDevId == 0xffff) {
384 MiscInitializationForMicrovm (&mPlatformInfoHob);
385 } else {
386 MiscInitialization (&mPlatformInfoHob);
387 }
388
389 IntelTdxInitialize ();
390 InstallFeatureControlCallback ();
391 BuildPlatformInfoHob ();
392
393 return EFI_SUCCESS;
394 }