]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/PlatformPei/Platform.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / PlatformPei / Platform.c
CommitLineData
49ba9447 1/**@file\r
2 Platform PEI driver\r
3\r
a1726e30 4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
eec7d420 5 Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>\r
6\r
b26f0cf9 7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
49ba9447 8\r
9**/\r
10\r
11//\r
12// The package level header files this module uses\r
13//\r
14#include <PiPei.h>\r
15\r
16//\r
17// The Library classes this module consumes\r
18//\r
c802f893 19#include <Library/BaseMemoryLib.h>\r
5133d1f1 20#include <Library/BaseLib.h>\r
49ba9447 21#include <Library/DebugLib.h>\r
22#include <Library/HobLib.h>\r
23#include <Library/IoLib.h>\r
77ba993c 24#include <Library/MemoryAllocationLib.h>\r
25#include <Library/PcdLib.h>\r
49ba9447 26#include <Library/PciLib.h>\r
27#include <Library/PeimEntryPoint.h>\r
9ed65b10 28#include <Library/PeiServicesLib.h>\r
7cdba634 29#include <Library/QemuFwCfgLib.h>\r
687f7521 30#include <Library/QemuFwCfgS3Lib.h>\r
b3c1bc1c 31#include <Library/QemuFwCfgSimpleParserLib.h>\r
49ba9447 32#include <Library/ResourcePublicationLib.h>\r
9ed65b10 33#include <Ppi/MasterBootMode.h>\r
83357313 34#include <IndustryStandard/I440FxPiix4.h>\r
bf02d73e 35#include <IndustryStandard/Microvm.h>\r
931a0c74 36#include <IndustryStandard/Pci22.h>\r
83357313
LE
37#include <IndustryStandard/Q35MchIch9.h>\r
38#include <IndustryStandard/QemuCpuHotplug.h>\r
9a9b33b3 39#include <Library/MemEncryptSevLib.h>\r
97380beb 40#include <OvmfPlatforms.h>\r
49ba9447 41\r
42#include "Platform.h"\r
43\r
ac0a286f 44EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {\r
9ed65b10 45 {\r
46 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
47 &gEfiPeiMasterBootModePpiGuid,\r
48 NULL\r
49 }\r
50};\r
51\r
12e860a1
MX
52VOID\r
53MemMapInitialization (\r
54 IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
55 )\r
56{\r
57 RETURN_STATUS PcdStatus;\r
58\r
59 PlatformMemMapInitialization (PlatformInfoHob);\r
60\r
61 if (PlatformInfoHob->HostBridgeDevId == 0xffff /* microvm */) {\r
62 return;\r
63 }\r
64\r
65 PcdStatus = PcdSet64S (PcdPciMmio32Base, PlatformInfoHob->PcdPciMmio32Base);\r
66 ASSERT_RETURN_ERROR (PcdStatus);\r
67 PcdStatus = PcdSet64S (PcdPciMmio32Size, PlatformInfoHob->PcdPciMmio32Size);\r
68 ASSERT_RETURN_ERROR (PcdStatus);\r
69\r
70 PcdStatus = PcdSet64S (PcdPciIoBase, PlatformInfoHob->PcdPciIoBase);\r
71 ASSERT_RETURN_ERROR (PcdStatus);\r
72 PcdStatus = PcdSet64S (PcdPciIoSize, PlatformInfoHob->PcdPciIoSize);\r
73 ASSERT_RETURN_ERROR (PcdStatus);\r
74}\r
75\r
7dbb8a24 76STATIC\r
ab081a50
LE
77VOID\r
78NoexecDxeInitialization (\r
7dbb8a24 79 IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
ab081a50
LE
80 )\r
81{\r
cec82a64
MX
82 RETURN_STATUS Status;\r
83\r
7dbb8a24 84 Status = PlatformNoexecDxeInitialization (PlatformInfoHob);\r
cec82a64 85 if (!RETURN_ERROR (Status)) {\r
7dbb8a24 86 Status = PcdSetBoolS (PcdSetNxForStack, PlatformInfoHob->PcdSetNxForStack);\r
cec82a64
MX
87 ASSERT_RETURN_ERROR (Status);\r
88 }\r
ab081a50 89}\r
49ba9447 90\r
c802f893
GH
91static const UINT8 EmptyFdt[] = {\r
92 0xd0, 0x0d, 0xfe, 0xed, 0x00, 0x00, 0x00, 0x48,\r
93 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x48,\r
94 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x11,\r
95 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\r
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\r
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
99 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,\r
100 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09,\r
101};\r
102\r
79dcaf70
GH
103VOID\r
104MicrovmInitialization (\r
105 VOID\r
106 )\r
107{\r
108 FIRMWARE_CONFIG_ITEM FdtItem;\r
109 UINTN FdtSize;\r
110 UINTN FdtPages;\r
111 EFI_STATUS Status;\r
112 UINT64 *FdtHobData;\r
113 VOID *NewBase;\r
114\r
115 Status = QemuFwCfgFindFile ("etc/fdt", &FdtItem, &FdtSize);\r
116 if (EFI_ERROR (Status)) {\r
c802f893
GH
117 DEBUG ((DEBUG_INFO, "%a: no etc/fdt found in fw_cfg, using dummy\n", __FUNCTION__));\r
118 FdtItem = 0;\r
119 FdtSize = sizeof (EmptyFdt);\r
79dcaf70
GH
120 }\r
121\r
122 FdtPages = EFI_SIZE_TO_PAGES (FdtSize);\r
123 NewBase = AllocatePages (FdtPages);\r
124 if (NewBase == NULL) {\r
125 DEBUG ((DEBUG_INFO, "%a: AllocatePages failed\n", __FUNCTION__));\r
126 return;\r
127 }\r
128\r
c802f893
GH
129 if (FdtItem) {\r
130 QemuFwCfgSelectItem (FdtItem);\r
131 QemuFwCfgReadBytes (FdtSize, NewBase);\r
132 } else {\r
133 CopyMem (NewBase, EmptyFdt, FdtSize);\r
134 }\r
79dcaf70
GH
135\r
136 FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof (*FdtHobData));\r
137 if (FdtHobData == NULL) {\r
138 DEBUG ((DEBUG_INFO, "%a: BuildGuidHob failed\n", __FUNCTION__));\r
139 return;\r
140 }\r
141\r
142 DEBUG ((\r
143 DEBUG_INFO,\r
144 "%a: fdt at 0x%x (size %d)\n",\r
145 __FUNCTION__,\r
146 NewBase,\r
147 FdtSize\r
148 ));\r
149 *FdtHobData = (UINTN)NewBase;\r
150}\r
151\r
5a2574a8
MX
152VOID\r
153MiscInitializationForMicrovm (\r
154 IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
155 )\r
156{\r
157 RETURN_STATUS PcdStatus;\r
158\r
159 ASSERT (PlatformInfoHob->HostBridgeDevId == 0xffff);\r
160\r
161 DEBUG ((DEBUG_INFO, "%a: microvm\n", __FUNCTION__));\r
162 //\r
163 // Disable A20 Mask\r
164 //\r
165 IoOr8 (0x92, BIT1);\r
166\r
167 //\r
168 // Build the CPU HOB with guest RAM size dependent address width and 16-bits\r
169 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during\r
170 // S3 resume as well, so we build it unconditionally.)\r
171 //\r
172 BuildCpuHob (PlatformInfoHob->PhysMemAddressWidth, 16);\r
173\r
174 MicrovmInitialization ();\r
175 PcdStatus = PcdSet16S (\r
176 PcdOvmfHostBridgePciDevId,\r
177 MICROVM_PSEUDO_DEVICE_ID\r
178 );\r
179 ASSERT_RETURN_ERROR (PcdStatus);\r
180}\r
181\r
f53f449f
MX
182VOID\r
183MiscInitialization (\r
184 IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
185 )\r
186{\r
187 RETURN_STATUS PcdStatus;\r
188\r
189 PlatformMiscInitialization (PlatformInfoHob);\r
190\r
191 PcdStatus = PcdSet16S (PcdOvmfHostBridgePciDevId, PlatformInfoHob->HostBridgeDevId);\r
192 ASSERT_RETURN_ERROR (PcdStatus);\r
193}\r
194\r
9ed65b10 195VOID\r
196BootModeInitialization (\r
9a9b33b3 197 IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
9ed65b10 198 )\r
199{\r
ac0a286f 200 EFI_STATUS Status;\r
8f5ca05b 201\r
57bcfc3b 202 if (PlatformCmosRead8 (0xF) == 0xFE) {\r
9a9b33b3 203 PlatformInfoHob->BootMode = BOOT_ON_S3_RESUME;\r
8f5ca05b 204 }\r
ac0a286f 205\r
57bcfc3b 206 PlatformCmosWrite8 (0xF, 0x00);\r
667bf1e4 207\r
9a9b33b3 208 Status = PeiServicesSetBootMode (PlatformInfoHob->BootMode);\r
667bf1e4 209 ASSERT_EFI_ERROR (Status);\r
210\r
211 Status = PeiServicesInstallPpi (mPpiBootMode);\r
212 ASSERT_EFI_ERROR (Status);\r
9ed65b10 213}\r
214\r
77ba993c 215VOID\r
216ReserveEmuVariableNvStore (\r
217 )\r
218{\r
ac0a286f
MK
219 EFI_PHYSICAL_ADDRESS VariableStore;\r
220 RETURN_STATUS PcdStatus;\r
77ba993c 221\r
58eb8517
MX
222 VariableStore = (EFI_PHYSICAL_ADDRESS)(UINTN)PlatformReserveEmuVariableNvStore ();\r
223 PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore);\r
224\r
225 #ifdef SECURE_BOOT_FEATURE_ENABLED\r
226 PlatformInitEmuVariableNvStore ((VOID *)(UINTN)VariableStore);\r
227 #endif\r
228\r
32e083c7 229 ASSERT_RETURN_ERROR (PcdStatus);\r
77ba993c 230}\r
231\r
4bc2c748 232STATIC\r
5133d1f1
LE
233VOID\r
234S3Verification (\r
4bc2c748 235 IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
5133d1f1
LE
236 )\r
237{\r
ac0a286f 238 #if defined (MDE_CPU_X64)\r
4bc2c748 239 if (PlatformInfoHob->SmmSmramRequire && PlatformInfoHob->S3Supported) {\r
ac0a286f
MK
240 DEBUG ((\r
241 DEBUG_ERROR,\r
242 "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n",\r
243 __FUNCTION__\r
244 ));\r
245 DEBUG ((\r
246 DEBUG_ERROR,\r
5133d1f1 247 "%a: Please disable S3 on the QEMU command line (see the README),\n",\r
ac0a286f
MK
248 __FUNCTION__\r
249 ));\r
250 DEBUG ((\r
251 DEBUG_ERROR,\r
252 "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n",\r
253 __FUNCTION__\r
254 ));\r
5133d1f1
LE
255 ASSERT (FALSE);\r
256 CpuDeadLoop ();\r
257 }\r
5133d1f1 258\r
ac0a286f
MK
259 #endif\r
260}\r
5133d1f1 261\r
4bc2c748 262STATIC\r
e0ed7a9b
LE
263VOID\r
264Q35BoardVerification (\r
4bc2c748 265 IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
e0ed7a9b
LE
266 )\r
267{\r
4bc2c748 268 if (PlatformInfoHob->HostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {\r
e0ed7a9b
LE
269 return;\r
270 }\r
271\r
272 DEBUG ((\r
273 DEBUG_ERROR,\r
274 "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "\r
275 "only DID=0x%04x (Q35) is supported\n",\r
276 __FUNCTION__,\r
4bc2c748 277 PlatformInfoHob->HostBridgeDevId,\r
e0ed7a9b
LE
278 INTEL_Q35_MCH_DEVICE_ID\r
279 ));\r
280 ASSERT (FALSE);\r
281 CpuDeadLoop ();\r
282}\r
283\r
432e4acd
MX
284/**\r
285 Fetch the boot CPU count and the possible CPU count from QEMU, and expose\r
286 them to UefiCpuPkg modules. Set the MaxCpuCount field in PlatformInfoHob.\r
287**/\r
288VOID\r
289MaxCpuCountInitialization (\r
290 IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
291 )\r
292{\r
293 RETURN_STATUS PcdStatus;\r
294\r
295 PlatformMaxCpuCountInitialization (PlatformInfoHob);\r
296\r
297 PcdStatus = PcdSet32S (PcdCpuBootLogicalProcessorNumber, PlatformInfoHob->PcdCpuBootLogicalProcessorNumber);\r
298 ASSERT_RETURN_ERROR (PcdStatus);\r
299 PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, PlatformInfoHob->PcdCpuMaxLogicalProcessorNumber);\r
300 ASSERT_RETURN_ERROR (PcdStatus);\r
301}\r
302\r
cf17156d
MX
303/**\r
304 * @brief Builds PlatformInfo Hob\r
305 */\r
862614e2 306EFI_HOB_PLATFORM_INFO *\r
cf17156d
MX
307BuildPlatformInfoHob (\r
308 VOID\r
309 )\r
310{\r
862614e2
GH
311 EFI_HOB_PLATFORM_INFO PlatformInfoHob;\r
312 EFI_HOB_GUID_TYPE *GuidHob;\r
313\r
314 ZeroMem (&PlatformInfoHob, sizeof PlatformInfoHob);\r
315 BuildGuidDataHob (&gUefiOvmfPkgPlatformInfoGuid, &PlatformInfoHob, sizeof (EFI_HOB_PLATFORM_INFO));\r
316 GuidHob = GetFirstGuidHob (&gUefiOvmfPkgPlatformInfoGuid);\r
317 return (EFI_HOB_PLATFORM_INFO *)GET_GUID_HOB_DATA (GuidHob);\r
cf17156d
MX
318}\r
319\r
49ba9447 320/**\r
321 Perform Platform PEI initialization.\r
322\r
323 @param FileHandle Handle of the file being invoked.\r
324 @param PeiServices Describes the list of possible PEI Services.\r
325\r
326 @return EFI_SUCCESS The PEIM initialized successfully.\r
327\r
328**/\r
329EFI_STATUS\r
330EFIAPI\r
331InitializePlatform (\r
332 IN EFI_PEI_FILE_HANDLE FileHandle,\r
333 IN CONST EFI_PEI_SERVICES **PeiServices\r
334 )\r
335{\r
862614e2
GH
336 EFI_HOB_PLATFORM_INFO *PlatformInfoHob;\r
337 EFI_STATUS Status;\r
a1726e30 338\r
7707c9fd 339 DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));\r
862614e2 340 PlatformInfoHob = BuildPlatformInfoHob ();\r
49ba9447 341\r
862614e2
GH
342 PlatformInfoHob->SmmSmramRequire = FeaturePcdGet (PcdSmmSmramRequire);\r
343 PlatformInfoHob->SevEsIsEnabled = MemEncryptSevEsIsEnabled ();\r
344 PlatformInfoHob->PcdPciMmio64Size = PcdGet64 (PcdPciMmio64Size);\r
345 PlatformInfoHob->DefaultMaxCpuNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);\r
9a9b33b3 346\r
57bcfc3b 347 PlatformDebugDumpCmos ();\r
3ca15914 348\r
7cdba634 349 if (QemuFwCfgS3Enabled ()) {\r
70d5086c 350 DEBUG ((DEBUG_INFO, "S3 support was detected on QEMU\n"));\r
862614e2 351 PlatformInfoHob->S3Supported = TRUE;\r
9a9b33b3 352 Status = PcdSetBoolS (PcdAcpiS3Enable, TRUE);\r
a1726e30 353 ASSERT_EFI_ERROR (Status);\r
7cdba634
JJ
354 }\r
355\r
862614e2
GH
356 S3Verification (PlatformInfoHob);\r
357 BootModeInitialization (PlatformInfoHob);\r
869b17cc 358\r
d5e06444
LE
359 //\r
360 // Query Host Bridge DID\r
361 //\r
862614e2
GH
362 PlatformInfoHob->HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);\r
363 AddressWidthInitialization (PlatformInfoHob);\r
d5e06444 364\r
862614e2 365 MaxCpuCountInitialization (PlatformInfoHob);\r
83357313 366\r
862614e2
GH
367 if (PlatformInfoHob->SmmSmramRequire) {\r
368 Q35BoardVerification (PlatformInfoHob);\r
369 Q35TsegMbytesInitialization (PlatformInfoHob);\r
370 Q35SmramAtDefaultSmbaseInitialization (PlatformInfoHob);\r
23bfb5c0
LE
371 }\r
372\r
862614e2 373 PublishPeiMemory (PlatformInfoHob);\r
f76e9eba 374\r
862614e2 375 PlatformQemuUc32BaseInitialization (PlatformInfoHob);\r
49edde15 376\r
862614e2 377 InitializeRamRegions (PlatformInfoHob);\r
49ba9447 378\r
862614e2
GH
379 if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) {\r
380 if (!PlatformInfoHob->SmmSmramRequire) {\r
5e167d7e
LE
381 ReserveEmuVariableNvStore ();\r
382 }\r
ac0a286f 383\r
862614e2
GH
384 PeiFvInitialization (PlatformInfoHob);\r
385 MemTypeInfoInitialization (PlatformInfoHob);\r
386 MemMapInitialization (PlatformInfoHob);\r
387 NoexecDxeInitialization (PlatformInfoHob);\r
bd386eaf 388 }\r
49ba9447 389\r
d20ae95a 390 InstallClearCacheCallback ();\r
862614e2
GH
391 AmdSevInitialize (PlatformInfoHob);\r
392 if (PlatformInfoHob->HostBridgeDevId == 0xffff) {\r
393 MiscInitializationForMicrovm (PlatformInfoHob);\r
5a2574a8 394 } else {\r
862614e2 395 MiscInitialization (PlatformInfoHob);\r
5a2574a8
MX
396 }\r
397\r
cf17156d 398 IntelTdxInitialize ();\r
f6a196c7 399 InstallFeatureControlCallback (PlatformInfoHob);\r
49ba9447 400\r
401 return EFI_SUCCESS;\r
402}\r