Platform.c 17 KB

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