]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/XenPlatformPei/Platform.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / XenPlatformPei / Platform.c
CommitLineData
3b96221f
AP
1/**@file\r
2 Platform PEI driver\r
3\r
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>\r
5 Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>\r
6 Copyright (c) 2019, Citrix Systems, Inc.\r
7\r
8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9\r
10**/\r
11\r
12//\r
13// The package level header files this module uses\r
14//\r
15#include <PiPei.h>\r
16\r
17//\r
18// The Library classes this module consumes\r
19//\r
20#include <Library/BaseLib.h>\r
21#include <Library/DebugLib.h>\r
22#include <Library/HobLib.h>\r
23#include <Library/IoLib.h>\r
24#include <Library/MemoryAllocationLib.h>\r
25#include <Library/PcdLib.h>\r
26#include <Library/PciLib.h>\r
27#include <Library/PeimEntryPoint.h>\r
28#include <Library/PeiServicesLib.h>\r
cb0d2463 29#include <Library/QemuFwCfgS3Lib.h>\r
3b96221f
AP
30#include <Library/ResourcePublicationLib.h>\r
31#include <Guid/MemoryTypeInformation.h>\r
32#include <Ppi/MasterBootMode.h>\r
33#include <IndustryStandard/Pci22.h>\r
34#include <OvmfPlatforms.h>\r
35\r
36#include "Platform.h"\r
37#include "Cmos.h"\r
38\r
ac0a286f 39EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {\r
3b96221f
AP
40 { EfiACPIMemoryNVS, 0x004 },\r
41 { EfiACPIReclaimMemory, 0x008 },\r
42 { EfiReservedMemoryType, 0x004 },\r
43 { EfiRuntimeServicesData, 0x024 },\r
44 { EfiRuntimeServicesCode, 0x030 },\r
45 { EfiBootServicesCode, 0x180 },\r
46 { EfiBootServicesData, 0xF00 },\r
47 { EfiMaxMemoryType, 0x000 }\r
48};\r
49\r
ac0a286f 50EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {\r
3b96221f
AP
51 {\r
52 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
53 &gEfiPeiMasterBootModePpiGuid,\r
54 NULL\r
55 }\r
56};\r
57\r
ac0a286f 58UINT16 mHostBridgeDevId;\r
3b96221f 59\r
ac0a286f 60EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;\r
3b96221f
AP
61\r
62VOID\r
63AddIoMemoryBaseSizeHob (\r
ac0a286f
MK
64 EFI_PHYSICAL_ADDRESS MemoryBase,\r
65 UINT64 MemorySize\r
3b96221f
AP
66 )\r
67{\r
68 BuildResourceDescriptorHob (\r
69 EFI_RESOURCE_MEMORY_MAPPED_IO,\r
ac0a286f
MK
70 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
71 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
72 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
73 EFI_RESOURCE_ATTRIBUTE_TESTED,\r
3b96221f
AP
74 MemoryBase,\r
75 MemorySize\r
76 );\r
77}\r
78\r
79VOID\r
80AddReservedMemoryBaseSizeHob (\r
ac0a286f
MK
81 EFI_PHYSICAL_ADDRESS MemoryBase,\r
82 UINT64 MemorySize,\r
83 BOOLEAN Cacheable\r
3b96221f
AP
84 )\r
85{\r
86 BuildResourceDescriptorHob (\r
87 EFI_RESOURCE_MEMORY_RESERVED,\r
ac0a286f
MK
88 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
89 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
90 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
91 (Cacheable ?\r
92 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
93 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
94 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE :\r
95 0\r
96 ) |\r
97 EFI_RESOURCE_ATTRIBUTE_TESTED,\r
3b96221f
AP
98 MemoryBase,\r
99 MemorySize\r
100 );\r
101}\r
102\r
24465c38
AP
103VOID\r
104AddReservedMemoryRangeHob (\r
ac0a286f
MK
105 EFI_PHYSICAL_ADDRESS MemoryBase,\r
106 EFI_PHYSICAL_ADDRESS MemoryLimit,\r
107 BOOLEAN Cacheable\r
24465c38
AP
108 )\r
109{\r
ac0a286f
MK
110 AddReservedMemoryBaseSizeHob (\r
111 MemoryBase,\r
112 (UINT64)(MemoryLimit - MemoryBase),\r
113 Cacheable\r
114 );\r
24465c38
AP
115}\r
116\r
3b96221f
AP
117VOID\r
118AddIoMemoryRangeHob (\r
ac0a286f
MK
119 EFI_PHYSICAL_ADDRESS MemoryBase,\r
120 EFI_PHYSICAL_ADDRESS MemoryLimit\r
3b96221f
AP
121 )\r
122{\r
123 AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));\r
124}\r
125\r
3b96221f
AP
126VOID\r
127AddMemoryBaseSizeHob (\r
ac0a286f
MK
128 EFI_PHYSICAL_ADDRESS MemoryBase,\r
129 UINT64 MemorySize\r
3b96221f
AP
130 )\r
131{\r
132 BuildResourceDescriptorHob (\r
133 EFI_RESOURCE_SYSTEM_MEMORY,\r
ac0a286f
MK
134 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
135 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
136 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
137 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
138 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
139 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |\r
140 EFI_RESOURCE_ATTRIBUTE_TESTED,\r
3b96221f
AP
141 MemoryBase,\r
142 MemorySize\r
143 );\r
144}\r
145\r
3b96221f
AP
146VOID\r
147AddMemoryRangeHob (\r
ac0a286f
MK
148 EFI_PHYSICAL_ADDRESS MemoryBase,\r
149 EFI_PHYSICAL_ADDRESS MemoryLimit\r
3b96221f
AP
150 )\r
151{\r
152 AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));\r
153}\r
154\r
3b96221f
AP
155VOID\r
156MemMapInitialization (\r
157 VOID\r
158 )\r
159{\r
ac0a286f
MK
160 UINT64 PciIoBase;\r
161 UINT64 PciIoSize;\r
162 RETURN_STATUS PcdStatus;\r
3b96221f
AP
163\r
164 PciIoBase = 0xC000;\r
165 PciIoSize = 0x4000;\r
166\r
167 //\r
168 // Create Memory Type Information HOB\r
169 //\r
170 BuildGuidDataHob (\r
171 &gEfiMemoryTypeInformationGuid,\r
172 mDefaultMemoryTypeInformation,\r
ac0a286f 173 sizeof (mDefaultMemoryTypeInformation)\r
3b96221f
AP
174 );\r
175\r
176 //\r
177 // Video memory + Legacy BIOS region\r
178 //\r
179 AddIoMemoryRangeHob (0x0A0000, BASE_1MB);\r
180\r
181 //\r
182 // Add PCI IO Port space available for PCI resource allocations.\r
183 //\r
184 BuildResourceDescriptorHob (\r
185 EFI_RESOURCE_IO,\r
186 EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
187 EFI_RESOURCE_ATTRIBUTE_INITIALIZED,\r
188 PciIoBase,\r
189 PciIoSize\r
190 );\r
191 PcdStatus = PcdSet64S (PcdPciIoBase, PciIoBase);\r
192 ASSERT_RETURN_ERROR (PcdStatus);\r
193 PcdStatus = PcdSet64S (PcdPciIoSize, PciIoSize);\r
194 ASSERT_RETURN_ERROR (PcdStatus);\r
195}\r
196\r
197VOID\r
198PciExBarInitialization (\r
199 VOID\r
200 )\r
201{\r
202 union {\r
ac0a286f
MK
203 UINT64 Uint64;\r
204 UINT32 Uint32[2];\r
3b96221f
AP
205 } PciExBarBase;\r
206\r
207 //\r
208 // We only support the 256MB size for the MMCONFIG area:\r
209 // 256 buses * 32 devices * 8 functions * 4096 bytes config space.\r
210 //\r
211 // The masks used below enforce the Q35 requirements that the MMCONFIG area\r
212 // be (a) correctly aligned -- here at 256 MB --, (b) located under 64 GB.\r
213 //\r
214 // Note that (b) also ensures that the minimum address width we have\r
215 // determined in AddressWidthInitialization(), i.e., 36 bits, will suffice\r
216 // for DXE's page tables to cover the MMCONFIG area.\r
217 //\r
218 PciExBarBase.Uint64 = FixedPcdGet64 (PcdPciExpressBaseAddress);\r
219 ASSERT ((PciExBarBase.Uint32[1] & MCH_PCIEXBAR_HIGHMASK) == 0);\r
220 ASSERT ((PciExBarBase.Uint32[0] & MCH_PCIEXBAR_LOWMASK) == 0);\r
221\r
222 //\r
223 // Clear the PCIEXBAREN bit first, before programming the high register.\r
224 //\r
225 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW), 0);\r
226\r
227 //\r
228 // Program the high register. Then program the low register, setting the\r
229 // MMCONFIG area size and enabling decoding at once.\r
230 //\r
231 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_HIGH), PciExBarBase.Uint32[1]);\r
232 PciWrite32 (\r
233 DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW),\r
234 PciExBarBase.Uint32[0] | MCH_PCIEXBAR_BUS_FF | MCH_PCIEXBAR_EN\r
235 );\r
236}\r
237\r
238VOID\r
239MiscInitialization (\r
240 VOID\r
241 )\r
242{\r
ac0a286f
MK
243 UINTN PmCmd;\r
244 UINTN Pmba;\r
245 UINT32 PmbaAndVal;\r
246 UINT32 PmbaOrVal;\r
247 UINTN AcpiCtlReg;\r
248 UINT8 AcpiEnBit;\r
249 RETURN_STATUS PcdStatus;\r
3b96221f
AP
250\r
251 //\r
252 // Disable A20 Mask\r
253 //\r
254 IoOr8 (0x92, BIT1);\r
255\r
256 //\r
257 // Build the CPU HOB with guest RAM size dependent address width and 16-bits\r
258 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during\r
259 // S3 resume as well, so we build it unconditionally.)\r
260 //\r
261 BuildCpuHob (mPhysMemAddressWidth, 16);\r
262\r
263 //\r
264 // Determine platform type and save Host Bridge DID to PCD\r
265 //\r
266 switch (mHostBridgeDevId) {\r
267 case INTEL_82441_DEVICE_ID:\r
268 PmCmd = POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET);\r
269 Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);\r
270 PmbaAndVal = ~(UINT32)PIIX4_PMBA_MASK;\r
271 PmbaOrVal = PIIX4_PMBA_VALUE;\r
272 AcpiCtlReg = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC);\r
273 AcpiEnBit = PIIX4_PMREGMISC_PMIOSE;\r
274 break;\r
275 case INTEL_Q35_MCH_DEVICE_ID:\r
276 PmCmd = POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET);\r
277 Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);\r
278 PmbaAndVal = ~(UINT32)ICH9_PMBASE_MASK;\r
279 PmbaOrVal = ICH9_PMBASE_VALUE;\r
280 AcpiCtlReg = POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL);\r
281 AcpiEnBit = ICH9_ACPI_CNTL_ACPI_EN;\r
282 break;\r
283 default:\r
198a8dc9
AP
284 if (XenPvhDetected ()) {\r
285 //\r
286 // There is no PCI bus in this case\r
287 //\r
288 return;\r
289 }\r
ac0a286f
MK
290\r
291 DEBUG ((\r
292 DEBUG_ERROR,\r
293 "%a: Unknown Host Bridge Device ID: 0x%04x\n",\r
294 __FUNCTION__,\r
295 mHostBridgeDevId\r
296 ));\r
3b96221f
AP
297 ASSERT (FALSE);\r
298 return;\r
299 }\r
ac0a286f 300\r
3b96221f
AP
301 PcdStatus = PcdSet16S (PcdOvmfHostBridgePciDevId, mHostBridgeDevId);\r
302 ASSERT_RETURN_ERROR (PcdStatus);\r
303\r
304 //\r
305 // If the appropriate IOspace enable bit is set, assume the ACPI PMBA\r
306 // has been configured (e.g., by Xen) and skip the setup here.\r
307 // This matches the logic in AcpiTimerLibConstructor ().\r
308 //\r
309 if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) == 0) {\r
310 //\r
311 // The PEI phase should be exited with fully accessibe ACPI PM IO space:\r
312 // 1. set PMBA\r
313 //\r
314 PciAndThenOr32 (Pmba, PmbaAndVal, PmbaOrVal);\r
315\r
316 //\r
317 // 2. set PCICMD/IOSE\r
318 //\r
319 PciOr8 (PmCmd, EFI_PCI_COMMAND_IO_SPACE);\r
320\r
321 //\r
322 // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN)\r
323 //\r
324 PciOr8 (AcpiCtlReg, AcpiEnBit);\r
325 }\r
326\r
327 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {\r
328 //\r
329 // Set Root Complex Register Block BAR\r
330 //\r
331 PciWrite32 (\r
332 POWER_MGMT_REGISTER_Q35 (ICH9_RCBA),\r
333 ICH9_ROOT_COMPLEX_BASE | ICH9_RCBA_EN\r
334 );\r
335\r
336 //\r
337 // Set PCI Express Register Range Base Address\r
338 //\r
339 PciExBarInitialization ();\r
340 }\r
341}\r
342\r
3b96221f
AP
343VOID\r
344BootModeInitialization (\r
345 VOID\r
346 )\r
347{\r
ac0a286f 348 EFI_STATUS Status;\r
3b96221f
AP
349\r
350 if (CmosRead8 (0xF) == 0xFE) {\r
351 mBootMode = BOOT_ON_S3_RESUME;\r
352 }\r
ac0a286f 353\r
3b96221f
AP
354 CmosWrite8 (0xF, 0x00);\r
355\r
356 Status = PeiServicesSetBootMode (mBootMode);\r
357 ASSERT_EFI_ERROR (Status);\r
358\r
359 Status = PeiServicesInstallPpi (mPpiBootMode);\r
360 ASSERT_EFI_ERROR (Status);\r
361}\r
362\r
3b96221f
AP
363VOID\r
364ReserveEmuVariableNvStore (\r
365 )\r
366{\r
ac0a286f
MK
367 EFI_PHYSICAL_ADDRESS VariableStore;\r
368 RETURN_STATUS PcdStatus;\r
3b96221f
AP
369\r
370 //\r
371 // Allocate storage for NV variables early on so it will be\r
372 // at a consistent address. Since VM memory is preserved\r
373 // across reboots, this allows the NV variable storage to survive\r
374 // a VM reboot.\r
375 //\r
376 VariableStore =\r
377 (EFI_PHYSICAL_ADDRESS)(UINTN)\r
ac0a286f
MK
378 AllocateRuntimePages (\r
379 EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize))\r
380 );\r
381 DEBUG ((\r
382 DEBUG_INFO,\r
383 "Reserved variable store memory: 0x%lX; size: %dkb\n",\r
384 VariableStore,\r
385 (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024\r
386 ));\r
3b96221f
AP
387 PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore);\r
388 ASSERT_RETURN_ERROR (PcdStatus);\r
389}\r
390\r
3b96221f
AP
391VOID\r
392DebugDumpCmos (\r
393 VOID\r
394 )\r
395{\r
ac0a286f 396 UINT32 Loop;\r
3b96221f
AP
397\r
398 DEBUG ((DEBUG_INFO, "CMOS:\n"));\r
399\r
400 for (Loop = 0; Loop < 0x80; Loop++) {\r
401 if ((Loop % 0x10) == 0) {\r
402 DEBUG ((DEBUG_INFO, "%02x:", Loop));\r
403 }\r
ac0a286f 404\r
3b96221f
AP
405 DEBUG ((DEBUG_INFO, " %02x", CmosRead8 (Loop)));\r
406 if ((Loop % 0x10) == 0xf) {\r
407 DEBUG ((DEBUG_INFO, "\n"));\r
408 }\r
409 }\r
410}\r
411\r
3b96221f
AP
412/**\r
413 Perform Platform PEI initialization.\r
414\r
415 @param FileHandle Handle of the file being invoked.\r
416 @param PeiServices Describes the list of possible PEI Services.\r
417\r
418 @return EFI_SUCCESS The PEIM initialized successfully.\r
419\r
420**/\r
421EFI_STATUS\r
422EFIAPI\r
423InitializeXenPlatform (\r
424 IN EFI_PEI_FILE_HANDLE FileHandle,\r
425 IN CONST EFI_PEI_SERVICES **PeiServices\r
426 )\r
427{\r
ac0a286f 428 EFI_STATUS Status;\r
cb0d2463 429\r
3b96221f
AP
430 DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));\r
431\r
432 DebugDumpCmos ();\r
433\r
434 if (!XenDetect ()) {\r
435 DEBUG ((DEBUG_ERROR, "ERROR: Xen isn't detected\n"));\r
436 ASSERT (FALSE);\r
437 CpuDeadLoop ();\r
438 }\r
439\r
cb0d2463
LGHOL
440 //\r
441 // This S3 conditional test is mainly for HVM Direct Kernel Boot since\r
442 // QEMU fwcfg isn't really supported other than that.\r
443 //\r
444 if (QemuFwCfgS3Enabled ()) {\r
445 DEBUG ((DEBUG_INFO, "S3 support was detected on QEMU\n"));\r
446 Status = PcdSetBoolS (PcdAcpiS3Enable, TRUE);\r
447 ASSERT_EFI_ERROR (Status);\r
448 }\r
449\r
12998837
AP
450 XenConnect ();\r
451\r
3b96221f
AP
452 BootModeInitialization ();\r
453 AddressWidthInitialization ();\r
454\r
455 //\r
456 // Query Host Bridge DID\r
457 //\r
458 mHostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);\r
459\r
460 PublishPeiMemory ();\r
461\r
462 InitializeRamRegions ();\r
463\r
c75c6405 464 CalibrateLapicTimer ();\r
3b96221f
AP
465\r
466 if (mBootMode != BOOT_ON_S3_RESUME) {\r
467 ReserveEmuVariableNvStore ();\r
468 PeiFvInitialization ();\r
469 MemMapInitialization ();\r
470 }\r
471\r
472 InstallClearCacheCallback ();\r
473 AmdSevInitialize ();\r
474 MiscInitialization ();\r
475\r
476 return EFI_SUCCESS;\r
477}\r