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 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14
15 **/
16
17 //
18 // The package level header files this module uses
19 //
20 #include <PiPei.h>
21
22 //
23 // The Library classes this module consumes
24 //
25 #include <Library/BaseLib.h>
26 #include <Library/DebugLib.h>
27 #include <Library/HobLib.h>
28 #include <Library/IoLib.h>
29 #include <Library/MemoryAllocationLib.h>
30 #include <Library/PcdLib.h>
31 #include <Library/PciLib.h>
32 #include <Library/PeimEntryPoint.h>
33 #include <Library/PeiServicesLib.h>
34 #include <Library/QemuFwCfgLib.h>
35 #include <Library/ResourcePublicationLib.h>
36 #include <Guid/MemoryTypeInformation.h>
37 #include <Ppi/MasterBootMode.h>
38 #include <IndustryStandard/Pci22.h>
39 #include <OvmfPlatforms.h>
40
41 #include "Platform.h"
42 #include "Cmos.h"
43
44 EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
45 { EfiACPIMemoryNVS, 0x004 },
46 { EfiACPIReclaimMemory, 0x008 },
47 { EfiReservedMemoryType, 0x004 },
48 { EfiRuntimeServicesData, 0x024 },
49 { EfiRuntimeServicesCode, 0x030 },
50 { EfiBootServicesCode, 0x180 },
51 { EfiBootServicesData, 0xF00 },
52 { EfiMaxMemoryType, 0x000 }
53 };
54
55
56 EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {
57 {
58 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
59 &gEfiPeiMasterBootModePpiGuid,
60 NULL
61 }
62 };
63
64
65 UINT16 mHostBridgeDevId;
66
67 EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
68
69 BOOLEAN mS3Supported = FALSE;
70
71 UINT32 mMaxCpuCount;
72
73 VOID
AddIoMemoryBaseSizeHob(EFI_PHYSICAL_ADDRESS MemoryBase,UINT64 MemorySize)74 AddIoMemoryBaseSizeHob (
75 EFI_PHYSICAL_ADDRESS MemoryBase,
76 UINT64 MemorySize
77 )
78 {
79 BuildResourceDescriptorHob (
80 EFI_RESOURCE_MEMORY_MAPPED_IO,
81 EFI_RESOURCE_ATTRIBUTE_PRESENT |
82 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
83 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
84 EFI_RESOURCE_ATTRIBUTE_TESTED,
85 MemoryBase,
86 MemorySize
87 );
88 }
89
90 VOID
AddReservedMemoryBaseSizeHob(EFI_PHYSICAL_ADDRESS MemoryBase,UINT64 MemorySize,BOOLEAN Cacheable)91 AddReservedMemoryBaseSizeHob (
92 EFI_PHYSICAL_ADDRESS MemoryBase,
93 UINT64 MemorySize,
94 BOOLEAN Cacheable
95 )
96 {
97 BuildResourceDescriptorHob (
98 EFI_RESOURCE_MEMORY_RESERVED,
99 EFI_RESOURCE_ATTRIBUTE_PRESENT |
100 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
101 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
102 (Cacheable ?
103 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
104 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
105 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE :
106 0
107 ) |
108 EFI_RESOURCE_ATTRIBUTE_TESTED,
109 MemoryBase,
110 MemorySize
111 );
112 }
113
114 VOID
AddIoMemoryRangeHob(EFI_PHYSICAL_ADDRESS MemoryBase,EFI_PHYSICAL_ADDRESS MemoryLimit)115 AddIoMemoryRangeHob (
116 EFI_PHYSICAL_ADDRESS MemoryBase,
117 EFI_PHYSICAL_ADDRESS MemoryLimit
118 )
119 {
120 AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
121 }
122
123
124 VOID
AddMemoryBaseSizeHob(EFI_PHYSICAL_ADDRESS MemoryBase,UINT64 MemorySize)125 AddMemoryBaseSizeHob (
126 EFI_PHYSICAL_ADDRESS MemoryBase,
127 UINT64 MemorySize
128 )
129 {
130 BuildResourceDescriptorHob (
131 EFI_RESOURCE_SYSTEM_MEMORY,
132 EFI_RESOURCE_ATTRIBUTE_PRESENT |
133 EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
134 EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
135 EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
136 EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
137 EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
138 EFI_RESOURCE_ATTRIBUTE_TESTED,
139 MemoryBase,
140 MemorySize
141 );
142 }
143
144
145 VOID
AddMemoryRangeHob(EFI_PHYSICAL_ADDRESS MemoryBase,EFI_PHYSICAL_ADDRESS MemoryLimit)146 AddMemoryRangeHob (
147 EFI_PHYSICAL_ADDRESS MemoryBase,
148 EFI_PHYSICAL_ADDRESS MemoryLimit
149 )
150 {
151 AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
152 }
153
154
155 VOID
MemMapInitialization(VOID)156 MemMapInitialization (
157 VOID
158 )
159 {
160 UINT64 PciIoBase;
161 UINT64 PciIoSize;
162 RETURN_STATUS PcdStatus;
163
164 PciIoBase = 0xC000;
165 PciIoSize = 0x4000;
166
167 //
168 // Create Memory Type Information HOB
169 //
170 BuildGuidDataHob (
171 &gEfiMemoryTypeInformationGuid,
172 mDefaultMemoryTypeInformation,
173 sizeof(mDefaultMemoryTypeInformation)
174 );
175
176 //
177 // Video memory + Legacy BIOS region
178 //
179 AddIoMemoryRangeHob (0x0A0000, BASE_1MB);
180
181 if (!mXen) {
182 UINT32 TopOfLowRam;
183 UINT64 PciExBarBase;
184 UINT32 PciBase;
185 UINT32 PciSize;
186
187 TopOfLowRam = GetSystemMemorySizeBelow4gb ();
188 PciExBarBase = 0;
189 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
190 //
191 // The MMCONFIG area is expected to fall between the top of low RAM and
192 // the base of the 32-bit PCI host aperture.
193 //
194 PciExBarBase = FixedPcdGet64 (PcdPciExpressBaseAddress);
195 ASSERT (TopOfLowRam <= PciExBarBase);
196 ASSERT (PciExBarBase <= MAX_UINT32 - SIZE_256MB);
197 PciBase = (UINT32)(PciExBarBase + SIZE_256MB);
198 } else {
199 PciBase = (TopOfLowRam < BASE_2GB) ? BASE_2GB : TopOfLowRam;
200 }
201
202 //
203 // address purpose size
204 // ------------ -------- -------------------------
205 // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g)
206 // 0xFC000000 gap 44 MB
207 // 0xFEC00000 IO-APIC 4 KB
208 // 0xFEC01000 gap 1020 KB
209 // 0xFED00000 HPET 1 KB
210 // 0xFED00400 gap 111 KB
211 // 0xFED1C000 gap (PIIX4) / RCRB (ICH9) 16 KB
212 // 0xFED20000 gap 896 KB
213 // 0xFEE00000 LAPIC 1 MB
214 //
215 PciSize = 0xFC000000 - PciBase;
216 AddIoMemoryBaseSizeHob (PciBase, PciSize);
217 PcdStatus = PcdSet64S (PcdPciMmio32Base, PciBase);
218 ASSERT_RETURN_ERROR (PcdStatus);
219 PcdStatus = PcdSet64S (PcdPciMmio32Size, PciSize);
220 ASSERT_RETURN_ERROR (PcdStatus);
221
222 AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB);
223 AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB);
224 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
225 AddIoMemoryBaseSizeHob (ICH9_ROOT_COMPLEX_BASE, SIZE_16KB);
226 //
227 // Note: there should be an
228 //
229 // AddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB);
230 //
231 // call below, just like the one above for RCBA. However, Linux insists
232 // that the MMCONFIG area be marked in the E820 or UEFI memory map as
233 // "reserved memory" -- Linux does not content itself with a simple gap
234 // in the memory map wherever the MCFG ACPI table points to.
235 //
236 // This appears to be a safety measure. The PCI Firmware Specification
237 // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can
238 // *optionally* be returned in [...] EFIGetMemoryMap as reserved memory
239 // [...]". (Emphasis added here.)
240 //
241 // Normally we add memory resource descriptor HOBs in
242 // QemuInitializeRam(), and pre-allocate from those with memory
243 // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area
244 // is most definitely not RAM; so, as an exception, cover it with
245 // uncacheable reserved memory right here.
246 //
247 AddReservedMemoryBaseSizeHob (PciExBarBase, SIZE_256MB, FALSE);
248 BuildMemoryAllocationHob (PciExBarBase, SIZE_256MB,
249 EfiReservedMemoryType);
250 }
251 AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB);
252
253 //
254 // On Q35, the IO Port space is available for PCI resource allocations from
255 // 0x6000 up.
256 //
257 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
258 PciIoBase = 0x6000;
259 PciIoSize = 0xA000;
260 ASSERT ((ICH9_PMBASE_VALUE & 0xF000) < PciIoBase);
261 }
262 }
263
264 //
265 // Add PCI IO Port space available for PCI resource allocations.
266 //
267 BuildResourceDescriptorHob (
268 EFI_RESOURCE_IO,
269 EFI_RESOURCE_ATTRIBUTE_PRESENT |
270 EFI_RESOURCE_ATTRIBUTE_INITIALIZED,
271 PciIoBase,
272 PciIoSize
273 );
274 PcdStatus = PcdSet64S (PcdPciIoBase, PciIoBase);
275 ASSERT_RETURN_ERROR (PcdStatus);
276 PcdStatus = PcdSet64S (PcdPciIoSize, PciIoSize);
277 ASSERT_RETURN_ERROR (PcdStatus);
278 }
279
280 EFI_STATUS
GetNamedFwCfgBoolean(IN CHAR8 * FwCfgFileName,OUT BOOLEAN * Setting)281 GetNamedFwCfgBoolean (
282 IN CHAR8 *FwCfgFileName,
283 OUT BOOLEAN *Setting
284 )
285 {
286 EFI_STATUS Status;
287 FIRMWARE_CONFIG_ITEM FwCfgItem;
288 UINTN FwCfgSize;
289 UINT8 Value[3];
290
291 Status = QemuFwCfgFindFile (FwCfgFileName, &FwCfgItem, &FwCfgSize);
292 if (EFI_ERROR (Status)) {
293 return Status;
294 }
295 if (FwCfgSize > sizeof Value) {
296 return EFI_BAD_BUFFER_SIZE;
297 }
298 QemuFwCfgSelectItem (FwCfgItem);
299 QemuFwCfgReadBytes (FwCfgSize, Value);
300
301 if ((FwCfgSize == 1) ||
302 (FwCfgSize == 2 && Value[1] == '\n') ||
303 (FwCfgSize == 3 && Value[1] == '\r' && Value[2] == '\n')) {
304 switch (Value[0]) {
305 case '0':
306 case 'n':
307 case 'N':
308 *Setting = FALSE;
309 return EFI_SUCCESS;
310
311 case '1':
312 case 'y':
313 case 'Y':
314 *Setting = TRUE;
315 return EFI_SUCCESS;
316
317 default:
318 break;
319 }
320 }
321 return EFI_PROTOCOL_ERROR;
322 }
323
324 #define UPDATE_BOOLEAN_PCD_FROM_FW_CFG(TokenName) \
325 do { \
326 BOOLEAN Setting; \
327 RETURN_STATUS PcdStatus; \
328 \
329 if (!EFI_ERROR (GetNamedFwCfgBoolean ( \
330 "opt/ovmf/" #TokenName, &Setting))) { \
331 PcdStatus = PcdSetBoolS (TokenName, Setting); \
332 ASSERT_RETURN_ERROR (PcdStatus); \
333 } \
334 } while (0)
335
336 VOID
NoexecDxeInitialization(VOID)337 NoexecDxeInitialization (
338 VOID
339 )
340 {
341 UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdPropertiesTableEnable);
342 UPDATE_BOOLEAN_PCD_FROM_FW_CFG (PcdSetNxForStack);
343 }
344
345 VOID
PciExBarInitialization(VOID)346 PciExBarInitialization (
347 VOID
348 )
349 {
350 union {
351 UINT64 Uint64;
352 UINT32 Uint32[2];
353 } PciExBarBase;
354
355 //
356 // We only support the 256MB size for the MMCONFIG area:
357 // 256 buses * 32 devices * 8 functions * 4096 bytes config space.
358 //
359 // The masks used below enforce the Q35 requirements that the MMCONFIG area
360 // be (a) correctly aligned -- here at 256 MB --, (b) located under 64 GB.
361 //
362 // Note that (b) also ensures that the minimum address width we have
363 // determined in AddressWidthInitialization(), i.e., 36 bits, will suffice
364 // for DXE's page tables to cover the MMCONFIG area.
365 //
366 PciExBarBase.Uint64 = FixedPcdGet64 (PcdPciExpressBaseAddress);
367 ASSERT ((PciExBarBase.Uint32[1] & MCH_PCIEXBAR_HIGHMASK) == 0);
368 ASSERT ((PciExBarBase.Uint32[0] & MCH_PCIEXBAR_LOWMASK) == 0);
369
370 //
371 // Clear the PCIEXBAREN bit first, before programming the high register.
372 //
373 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW), 0);
374
375 //
376 // Program the high register. Then program the low register, setting the
377 // MMCONFIG area size and enabling decoding at once.
378 //
379 PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_HIGH), PciExBarBase.Uint32[1]);
380 PciWrite32 (
381 DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW),
382 PciExBarBase.Uint32[0] | MCH_PCIEXBAR_BUS_FF | MCH_PCIEXBAR_EN
383 );
384 }
385
386 VOID
MiscInitialization(VOID)387 MiscInitialization (
388 VOID
389 )
390 {
391 UINTN PmCmd;
392 UINTN Pmba;
393 UINT32 PmbaAndVal;
394 UINT32 PmbaOrVal;
395 UINTN AcpiCtlReg;
396 UINT8 AcpiEnBit;
397 RETURN_STATUS PcdStatus;
398
399 //
400 // Disable A20 Mask
401 //
402 IoOr8 (0x92, BIT1);
403
404 //
405 // Build the CPU HOB with guest RAM size dependent address width and 16-bits
406 // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
407 // S3 resume as well, so we build it unconditionally.)
408 //
409 BuildCpuHob (mPhysMemAddressWidth, 16);
410
411 //
412 // Determine platform type and save Host Bridge DID to PCD
413 //
414 switch (mHostBridgeDevId) {
415 case INTEL_82441_DEVICE_ID:
416 PmCmd = POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET);
417 Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
418 PmbaAndVal = ~(UINT32)PIIX4_PMBA_MASK;
419 PmbaOrVal = PIIX4_PMBA_VALUE;
420 AcpiCtlReg = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC);
421 AcpiEnBit = PIIX4_PMREGMISC_PMIOSE;
422 break;
423 case INTEL_Q35_MCH_DEVICE_ID:
424 PmCmd = POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET);
425 Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
426 PmbaAndVal = ~(UINT32)ICH9_PMBASE_MASK;
427 PmbaOrVal = ICH9_PMBASE_VALUE;
428 AcpiCtlReg = POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL);
429 AcpiEnBit = ICH9_ACPI_CNTL_ACPI_EN;
430 break;
431 default:
432 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
433 __FUNCTION__, mHostBridgeDevId));
434 ASSERT (FALSE);
435 return;
436 }
437 PcdStatus = PcdSet16S (PcdOvmfHostBridgePciDevId, mHostBridgeDevId);
438 ASSERT_RETURN_ERROR (PcdStatus);
439
440 //
441 // If the appropriate IOspace enable bit is set, assume the ACPI PMBA
442 // has been configured (e.g., by Xen) and skip the setup here.
443 // This matches the logic in AcpiTimerLibConstructor ().
444 //
445 if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) == 0) {
446 //
447 // The PEI phase should be exited with fully accessibe ACPI PM IO space:
448 // 1. set PMBA
449 //
450 PciAndThenOr32 (Pmba, PmbaAndVal, PmbaOrVal);
451
452 //
453 // 2. set PCICMD/IOSE
454 //
455 PciOr8 (PmCmd, EFI_PCI_COMMAND_IO_SPACE);
456
457 //
458 // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN)
459 //
460 PciOr8 (AcpiCtlReg, AcpiEnBit);
461 }
462
463 if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
464 //
465 // Set Root Complex Register Block BAR
466 //
467 PciWrite32 (
468 POWER_MGMT_REGISTER_Q35 (ICH9_RCBA),
469 ICH9_ROOT_COMPLEX_BASE | ICH9_RCBA_EN
470 );
471
472 //
473 // Set PCI Express Register Range Base Address
474 //
475 PciExBarInitialization ();
476 }
477 }
478
479
480 VOID
BootModeInitialization(VOID)481 BootModeInitialization (
482 VOID
483 )
484 {
485 EFI_STATUS Status;
486
487 if (CmosRead8 (0xF) == 0xFE) {
488 mBootMode = BOOT_ON_S3_RESUME;
489 }
490 CmosWrite8 (0xF, 0x00);
491
492 Status = PeiServicesSetBootMode (mBootMode);
493 ASSERT_EFI_ERROR (Status);
494
495 Status = PeiServicesInstallPpi (mPpiBootMode);
496 ASSERT_EFI_ERROR (Status);
497 }
498
499
500 VOID
ReserveEmuVariableNvStore()501 ReserveEmuVariableNvStore (
502 )
503 {
504 EFI_PHYSICAL_ADDRESS VariableStore;
505 RETURN_STATUS PcdStatus;
506
507 //
508 // Allocate storage for NV variables early on so it will be
509 // at a consistent address. Since VM memory is preserved
510 // across reboots, this allows the NV variable storage to survive
511 // a VM reboot.
512 //
513 VariableStore =
514 (EFI_PHYSICAL_ADDRESS)(UINTN)
515 AllocateAlignedRuntimePages (
516 EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)),
517 PcdGet32 (PcdFlashNvStorageFtwSpareSize)
518 );
519 DEBUG ((EFI_D_INFO,
520 "Reserved variable store memory: 0x%lX; size: %dkb\n",
521 VariableStore,
522 (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024
523 ));
524 PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore);
525 ASSERT_RETURN_ERROR (PcdStatus);
526 }
527
528
529 VOID
DebugDumpCmos(VOID)530 DebugDumpCmos (
531 VOID
532 )
533 {
534 UINT32 Loop;
535
536 DEBUG ((EFI_D_INFO, "CMOS:\n"));
537
538 for (Loop = 0; Loop < 0x80; Loop++) {
539 if ((Loop % 0x10) == 0) {
540 DEBUG ((EFI_D_INFO, "%02x:", Loop));
541 }
542 DEBUG ((EFI_D_INFO, " %02x", CmosRead8 (Loop)));
543 if ((Loop % 0x10) == 0xf) {
544 DEBUG ((EFI_D_INFO, "\n"));
545 }
546 }
547 }
548
549
550 VOID
S3Verification(VOID)551 S3Verification (
552 VOID
553 )
554 {
555 #if defined (MDE_CPU_X64)
556 if (FeaturePcdGet (PcdSmmSmramRequire) && mS3Supported) {
557 DEBUG ((EFI_D_ERROR,
558 "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n", __FUNCTION__));
559 DEBUG ((EFI_D_ERROR,
560 "%a: Please disable S3 on the QEMU command line (see the README),\n",
561 __FUNCTION__));
562 DEBUG ((EFI_D_ERROR,
563 "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n", __FUNCTION__));
564 ASSERT (FALSE);
565 CpuDeadLoop ();
566 }
567 #endif
568 }
569
570
571 /**
572 Fetch the number of boot CPUs from QEMU and expose it to UefiCpuPkg modules.
573 Set the mMaxCpuCount variable.
574 **/
575 VOID
MaxCpuCountInitialization(VOID)576 MaxCpuCountInitialization (
577 VOID
578 )
579 {
580 UINT16 ProcessorCount;
581 RETURN_STATUS PcdStatus;
582
583 QemuFwCfgSelectItem (QemuFwCfgItemSmpCpuCount);
584 ProcessorCount = QemuFwCfgRead16 ();
585 //
586 // If the fw_cfg key or fw_cfg entirely is unavailable, load mMaxCpuCount
587 // from the PCD default. No change to PCDs.
588 //
589 if (ProcessorCount == 0) {
590 mMaxCpuCount = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
591 return;
592 }
593 //
594 // Otherwise, set mMaxCpuCount to the value reported by QEMU.
595 //
596 mMaxCpuCount = ProcessorCount;
597 //
598 // Additionally, tell UefiCpuPkg modules (a) the exact number of VCPUs, (b)
599 // to wait, in the initial AP bringup, exactly as long as it takes for all of
600 // the APs to report in. For this, we set the longest representable timeout
601 // (approx. 71 minutes).
602 //
603 PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, ProcessorCount);
604 ASSERT_RETURN_ERROR (PcdStatus);
605 PcdStatus = PcdSet32S (PcdCpuApInitTimeOutInMicroSeconds, MAX_UINT32);
606 ASSERT_RETURN_ERROR (PcdStatus);
607 DEBUG ((DEBUG_INFO, "%a: QEMU reports %d processor(s)\n", __FUNCTION__,
608 ProcessorCount));
609 }
610
611
612 /**
613 Perform Platform PEI initialization.
614
615 @param FileHandle Handle of the file being invoked.
616 @param PeiServices Describes the list of possible PEI Services.
617
618 @return EFI_SUCCESS The PEIM initialized successfully.
619
620 **/
621 EFI_STATUS
622 EFIAPI
InitializePlatform(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)623 InitializePlatform (
624 IN EFI_PEI_FILE_HANDLE FileHandle,
625 IN CONST EFI_PEI_SERVICES **PeiServices
626 )
627 {
628 EFI_STATUS Status;
629
630 DEBUG ((EFI_D_ERROR, "Platform PEIM Loaded\n"));
631
632 DebugDumpCmos ();
633
634 XenDetect ();
635
636 if (QemuFwCfgS3Enabled ()) {
637 DEBUG ((EFI_D_INFO, "S3 support was detected on QEMU\n"));
638 mS3Supported = TRUE;
639 Status = PcdSetBoolS (PcdAcpiS3Enable, TRUE);
640 ASSERT_EFI_ERROR (Status);
641 }
642
643 S3Verification ();
644 BootModeInitialization ();
645 AddressWidthInitialization ();
646 MaxCpuCountInitialization ();
647
648 PublishPeiMemory ();
649
650 InitializeRamRegions ();
651
652 if (mXen) {
653 DEBUG ((EFI_D_INFO, "Xen was detected\n"));
654 InitializeXen ();
655 }
656
657 //
658 // Query Host Bridge DID
659 //
660 mHostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
661
662 if (mBootMode != BOOT_ON_S3_RESUME) {
663 ReserveEmuVariableNvStore ();
664 PeiFvInitialization ();
665 MemMapInitialization ();
666 NoexecDxeInitialization ();
667 }
668
669 MiscInitialization ();
670 InstallFeatureControlCallback ();
671
672 return EFI_SUCCESS;
673 }
674