]>
Commit | Line | Data |
---|---|---|
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 |
44 | EFI_HOB_PLATFORM_INFO mPlatformInfoHob = { 0 };\r |
45 | \r | |
ac0a286f | 46 | EFI_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 |
54 | VOID\r |
55 | MemMapInitialization (\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 |
78 | VOID\r |
79 | NoexecDxeInitialization (\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 |
92 | static 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 |
104 | VOID\r |
105 | MicrovmInitialization (\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 |
153 | VOID\r |
154 | MiscInitializationForMicrovm (\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 |
183 | VOID\r |
184 | MiscInitialization (\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 | 196 | VOID\r |
197 | BootModeInitialization (\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 | 216 | VOID\r |
217 | ReserveEmuVariableNvStore (\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 |
244 | VOID\r |
245 | S3Verification (\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 |
273 | VOID\r |
274 | Q35BoardVerification (\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 | |
298 | VOID\r | |
299 | MaxCpuCountInitialization (\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 | |
49ba9447 | 313 | /**\r |
314 | Perform Platform PEI initialization.\r | |
315 | \r | |
316 | @param FileHandle Handle of the file being invoked.\r | |
317 | @param PeiServices Describes the list of possible PEI Services.\r | |
318 | \r | |
319 | @return EFI_SUCCESS The PEIM initialized successfully.\r | |
320 | \r | |
321 | **/\r | |
322 | EFI_STATUS\r | |
323 | EFIAPI\r | |
324 | InitializePlatform (\r | |
325 | IN EFI_PEI_FILE_HANDLE FileHandle,\r | |
326 | IN CONST EFI_PEI_SERVICES **PeiServices\r | |
327 | )\r | |
328 | {\r | |
ac0a286f | 329 | EFI_STATUS Status;\r |
a1726e30 | 330 | \r |
7707c9fd | 331 | DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));\r |
49ba9447 | 332 | \r |
3dd47f95 MX |
333 | mPlatformInfoHob.SmmSmramRequire = FeaturePcdGet (PcdSmmSmramRequire);\r |
334 | mPlatformInfoHob.SevEsIsEnabled = MemEncryptSevEsIsEnabled ();\r | |
335 | mPlatformInfoHob.PcdPciMmio64Size = PcdGet64 (PcdPciMmio64Size);\r | |
336 | mPlatformInfoHob.DefaultMaxCpuNumber = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);\r | |
9a9b33b3 | 337 | \r |
57bcfc3b | 338 | PlatformDebugDumpCmos ();\r |
3ca15914 | 339 | \r |
7cdba634 | 340 | if (QemuFwCfgS3Enabled ()) {\r |
70d5086c | 341 | DEBUG ((DEBUG_INFO, "S3 support was detected on QEMU\n"));\r |
9a9b33b3 MX |
342 | mPlatformInfoHob.S3Supported = TRUE;\r |
343 | Status = PcdSetBoolS (PcdAcpiS3Enable, TRUE);\r | |
a1726e30 | 344 | ASSERT_EFI_ERROR (Status);\r |
7cdba634 JJ |
345 | }\r |
346 | \r | |
5133d1f1 | 347 | S3Verification ();\r |
9a9b33b3 MX |
348 | BootModeInitialization (&mPlatformInfoHob);\r |
349 | AddressWidthInitialization (&mPlatformInfoHob);\r | |
869b17cc | 350 | \r |
d5e06444 LE |
351 | //\r |
352 | // Query Host Bridge DID\r | |
353 | //\r | |
9a9b33b3 | 354 | mPlatformInfoHob.HostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);\r |
d5e06444 | 355 | \r |
9a9b33b3 | 356 | MaxCpuCountInitialization (&mPlatformInfoHob);\r |
83357313 | 357 | \r |
9a9b33b3 | 358 | if (mPlatformInfoHob.SmmSmramRequire) {\r |
e0ed7a9b | 359 | Q35BoardVerification ();\r |
23bfb5c0 | 360 | Q35TsegMbytesInitialization ();\r |
73974f80 | 361 | Q35SmramAtDefaultSmbaseInitialization ();\r |
23bfb5c0 LE |
362 | }\r |
363 | \r | |
f76e9eba JJ |
364 | PublishPeiMemory ();\r |
365 | \r | |
f3801cf2 | 366 | PlatformQemuUc32BaseInitialization (&mPlatformInfoHob);\r |
49edde15 | 367 | \r |
9a9b33b3 | 368 | InitializeRamRegions (&mPlatformInfoHob);\r |
49ba9447 | 369 | \r |
9a9b33b3 MX |
370 | if (mPlatformInfoHob.BootMode != BOOT_ON_S3_RESUME) {\r |
371 | if (!mPlatformInfoHob.SmmSmramRequire) {\r | |
5e167d7e LE |
372 | ReserveEmuVariableNvStore ();\r |
373 | }\r | |
ac0a286f | 374 | \r |
bd386eaf | 375 | PeiFvInitialization ();\r |
d42fdd6f | 376 | MemTypeInfoInitialization ();\r |
9a9b33b3 | 377 | MemMapInitialization (&mPlatformInfoHob);\r |
ab081a50 | 378 | NoexecDxeInitialization ();\r |
bd386eaf | 379 | }\r |
49ba9447 | 380 | \r |
d20ae95a | 381 | InstallClearCacheCallback ();\r |
13b5d743 | 382 | AmdSevInitialize ();\r |
5a2574a8 MX |
383 | if (mPlatformInfoHob.HostBridgeDevId == 0xffff) {\r |
384 | MiscInitializationForMicrovm (&mPlatformInfoHob);\r | |
385 | } else {\r | |
386 | MiscInitialization (&mPlatformInfoHob);\r | |
387 | }\r | |
388 | \r | |
dbab9949 | 389 | InstallFeatureControlCallback ();\r |
49ba9447 | 390 | \r |
391 | return EFI_SUCCESS;\r | |
392 | }\r |