]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/PlatformPei/Platform.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {
45 {
46 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
47 &gEfiPeiMasterBootModePpiGuid,
48 NULL
49 }
50 };
51
52 VOID
53 MemMapInitialization (
54 IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
55 )
56 {
57 RETURN_STATUS PcdStatus;
58
59 PlatformMemMapInitialization (PlatformInfoHob);
60
61 if (PlatformInfoHob->HostBridgeDevId == 0xffff /* microvm */) {
62 return;
63 }
64
65 PcdStatus = PcdSet64S (PcdPciMmio32Base, PlatformInfoHob->PcdPciMmio32Base);
66 ASSERT_RETURN_ERROR (PcdStatus);
67 PcdStatus = PcdSet64S (PcdPciMmio32Size, PlatformInfoHob->PcdPciMmio32Size);
68 ASSERT_RETURN_ERROR (PcdStatus);
69
70 PcdStatus = PcdSet64S (PcdPciIoBase, PlatformInfoHob->PcdPciIoBase);
71 ASSERT_RETURN_ERROR (PcdStatus);
72 PcdStatus = PcdSet64S (PcdPciIoSize, PlatformInfoHob->PcdPciIoSize);
73 ASSERT_RETURN_ERROR (PcdStatus);
74 }
75
76 STATIC
77 VOID
78 NoexecDxeInitialization (
79 IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
80 )
81 {
82 RETURN_STATUS Status;
83
84 Status = PlatformNoexecDxeInitialization (PlatformInfoHob);
85 if (!RETURN_ERROR (Status)) {
86 Status = PcdSetBoolS (PcdSetNxForStack, PlatformInfoHob->PcdSetNxForStack);
87 ASSERT_RETURN_ERROR (Status);
88 }
89 }
90
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,
101 };
102
103 VOID
104 MicrovmInitialization (
105 VOID
106 )
107 {
108 FIRMWARE_CONFIG_ITEM FdtItem;
109 UINTN FdtSize;
110 UINTN FdtPages;
111 EFI_STATUS Status;
112 UINT64 *FdtHobData;
113 VOID *NewBase;
114
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__));
118 FdtItem = 0;
119 FdtSize = sizeof (EmptyFdt);
120 }
121
122 FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
123 NewBase = AllocatePages (FdtPages);
124 if (NewBase == NULL) {
125 DEBUG ((DEBUG_INFO, "%a: AllocatePages failed\n", __FUNCTION__));
126 return;
127 }
128
129 if (FdtItem) {
130 QemuFwCfgSelectItem (FdtItem);
131 QemuFwCfgReadBytes (FdtSize, NewBase);
132 } else {
133 CopyMem (NewBase, EmptyFdt, FdtSize);
134 }
135
136 FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof (*FdtHobData));
137 if (FdtHobData == NULL) {
138 DEBUG ((DEBUG_INFO, "%a: BuildGuidHob failed\n", __FUNCTION__));
139 return;
140 }
141
142 DEBUG ((
143 DEBUG_INFO,
144 "%a: fdt at 0x%x (size %d)\n",
145 __FUNCTION__,
146 NewBase,
147 FdtSize
148 ));
149 *FdtHobData = (UINTN)NewBase;
150 }
151
152 VOID
153 MiscInitializationForMicrovm (
154 IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
155 )
156 {
157 RETURN_STATUS PcdStatus;
158
159 ASSERT (PlatformInfoHob->HostBridgeDevId == 0xffff);
160
161 DEBUG ((DEBUG_INFO, "%a: microvm\n", __FUNCTION__));
162 //
163 // Disable A20 Mask
164 //
165 IoOr8 (0x92, BIT1);
166
167 //
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.)
171 //
172 BuildCpuHob (PlatformInfoHob->PhysMemAddressWidth, 16);
173
174 MicrovmInitialization ();
175 PcdStatus = PcdSet16S (
176 PcdOvmfHostBridgePciDevId,
177 MICROVM_PSEUDO_DEVICE_ID
178 );
179 ASSERT_RETURN_ERROR (PcdStatus);
180 }
181
182 VOID
183 MiscInitialization (
184 IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
185 )
186 {
187 RETURN_STATUS PcdStatus;
188
189 PlatformMiscInitialization (PlatformInfoHob);
190
191 PcdStatus = PcdSet16S (PcdOvmfHostBridgePciDevId, PlatformInfoHob->HostBridgeDevId);
192 ASSERT_RETURN_ERROR (PcdStatus);
193 }
194
195 VOID
196 BootModeInitialization (
197 IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
198 )
199 {
200 EFI_STATUS Status;
201
202 if (PlatformCmosRead8 (0xF) == 0xFE) {
203 PlatformInfoHob->BootMode = BOOT_ON_S3_RESUME;
204 }
205
206 PlatformCmosWrite8 (0xF, 0x00);
207
208 Status = PeiServicesSetBootMode (PlatformInfoHob->BootMode);
209 ASSERT_EFI_ERROR (Status);
210
211 Status = PeiServicesInstallPpi (mPpiBootMode);
212 ASSERT_EFI_ERROR (Status);
213 }
214
215 VOID
216 ReserveEmuVariableNvStore (
217 )
218 {
219 EFI_PHYSICAL_ADDRESS VariableStore;
220 RETURN_STATUS PcdStatus;
221
222 VariableStore = (EFI_PHYSICAL_ADDRESS)(UINTN)PlatformReserveEmuVariableNvStore ();
223 PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore);
224
225 #ifdef SECURE_BOOT_FEATURE_ENABLED
226 PlatformInitEmuVariableNvStore ((VOID *)(UINTN)VariableStore);
227 #endif
228
229 ASSERT_RETURN_ERROR (PcdStatus);
230 }
231
232 STATIC
233 VOID
234 S3Verification (
235 IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
236 )
237 {
238 #if defined (MDE_CPU_X64)
239 if (PlatformInfoHob->SmmSmramRequire && PlatformInfoHob->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 STATIC
263 VOID
264 Q35BoardVerification (
265 IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
266 )
267 {
268 if (PlatformInfoHob->HostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
269 return;
270 }
271
272 DEBUG ((
273 DEBUG_ERROR,
274 "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
275 "only DID=0x%04x (Q35) is supported\n",
276 __FUNCTION__,
277 PlatformInfoHob->HostBridgeDevId,
278 INTEL_Q35_MCH_DEVICE_ID
279 ));
280 ASSERT (FALSE);
281 CpuDeadLoop ();
282 }
283
284 /**
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.
287 **/
288 VOID
289 MaxCpuCountInitialization (
290 IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob
291 )
292 {
293 RETURN_STATUS PcdStatus;
294
295 PlatformMaxCpuCountInitialization (PlatformInfoHob);
296
297 PcdStatus = PcdSet32S (PcdCpuBootLogicalProcessorNumber, PlatformInfoHob->PcdCpuBootLogicalProcessorNumber);
298 ASSERT_RETURN_ERROR (PcdStatus);
299 PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, PlatformInfoHob->PcdCpuMaxLogicalProcessorNumber);
300 ASSERT_RETURN_ERROR (PcdStatus);
301 }
302
303 /**
304 * @brief Builds PlatformInfo Hob
305 */
306 EFI_HOB_PLATFORM_INFO *
307 BuildPlatformInfoHob (
308 VOID
309 )
310 {
311 EFI_HOB_PLATFORM_INFO PlatformInfoHob;
312 EFI_HOB_GUID_TYPE *GuidHob;
313
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);
318 }
319
320 /**
321 Perform Platform PEI initialization.
322
323 @param FileHandle Handle of the file being invoked.
324 @param PeiServices Describes the list of possible PEI Services.
325
326 @return EFI_SUCCESS The PEIM initialized successfully.
327
328 **/
329 EFI_STATUS
330 EFIAPI
331 InitializePlatform (
332 IN EFI_PEI_FILE_HANDLE FileHandle,
333 IN CONST EFI_PEI_SERVICES **PeiServices
334 )
335 {
336 EFI_HOB_PLATFORM_INFO *PlatformInfoHob;
337 EFI_STATUS Status;
338
339 DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));
340 PlatformInfoHob = BuildPlatformInfoHob ();
341
342 PlatformInfoHob->SmmSmramRequire = FeaturePcdGet (PcdSmmSmramRequire);
343 PlatformInfoHob->SevEsIsEnabled = MemEncryptSevEsIsEnabled ();
344 PlatformInfoHob->PcdPciMmio64Size = PcdGet64 (PcdPciMmio64Size);
345 PlatformInfoHob->DefaultMaxCpuNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
346
347 PlatformDebugDumpCmos ();
348
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);
354 }
355
356 S3Verification (PlatformInfoHob);
357 BootModeInitialization (PlatformInfoHob);
358
359 //
360 // Query Host Bridge DID
361 //
362 PlatformInfoHob->HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
363 AddressWidthInitialization (PlatformInfoHob);
364
365 MaxCpuCountInitialization (PlatformInfoHob);
366
367 if (PlatformInfoHob->SmmSmramRequire) {
368 Q35BoardVerification (PlatformInfoHob);
369 Q35TsegMbytesInitialization (PlatformInfoHob);
370 Q35SmramAtDefaultSmbaseInitialization (PlatformInfoHob);
371 }
372
373 PublishPeiMemory (PlatformInfoHob);
374
375 PlatformQemuUc32BaseInitialization (PlatformInfoHob);
376
377 InitializeRamRegions (PlatformInfoHob);
378
379 if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) {
380 if (!PlatformInfoHob->SmmSmramRequire) {
381 ReserveEmuVariableNvStore ();
382 }
383
384 PeiFvInitialization (PlatformInfoHob);
385 MemTypeInfoInitialization (PlatformInfoHob);
386 MemMapInitialization (PlatformInfoHob);
387 NoexecDxeInitialization (PlatformInfoHob);
388 }
389
390 InstallClearCacheCallback ();
391 AmdSevInitialize (PlatformInfoHob);
392 if (PlatformInfoHob->HostBridgeDevId == 0xffff) {
393 MiscInitializationForMicrovm (PlatformInfoHob);
394 } else {
395 MiscInitialization (PlatformInfoHob);
396 }
397
398 IntelTdxInitialize ();
399 InstallFeatureControlCallback (PlatformInfoHob);
400
401 return EFI_SUCCESS;
402 }