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