public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Rebecca Cran" <rebecca@bsdio.com>
To: devel@edk2.groups.io
Cc: Jordan Justen <jordan.l.justen@intel.com>,
	Laszlo Ersek <lersek@redhat.com>,
	Ard Biesheuvel <ard.biesheuvel@arm.com>,
	Leif Lindholm <leif.lindholm@linaro.org>,
	Michael Kinney <michael.d.kinney@intel.com>,
	Andrew Fish <afish@apple.com>, Peter Grehan <grehan@freebsd.org>,
	Rebecca Cran <rebecca@bsdio.com>
Subject: [PATCH v3 5/6] BhyvePkg: Add PlatformPei
Date: Mon, 20 Apr 2020 21:09:54 -0600	[thread overview]
Message-ID: <20200421030955.114850-6-rebecca@bsdio.com> (raw)
In-Reply-To: <20200421030955.114850-1-rebecca@bsdio.com>

Make a copy of OvmfPkg/PlatformPei under BhyvePkg with the changes
that are needed to support the bhyve hypervisor.

Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
---
 BhyvePkg/PlatformPei/AmdSev.c         | 106 +++++
 BhyvePkg/PlatformPei/ClearCache.c     | 111 +++++
 BhyvePkg/PlatformPei/Cmos.c           |  58 +++
 BhyvePkg/PlatformPei/Cmos.h           |  50 ++
 BhyvePkg/PlatformPei/FeatureControl.c |  20 +
 BhyvePkg/PlatformPei/Fv.c             |  94 ++++
 BhyvePkg/PlatformPei/MemDetect.c      | 631 ++++++++++++++++++++++++++
 BhyvePkg/PlatformPei/Platform.c       | 612 +++++++++++++++++++++++++
 BhyvePkg/PlatformPei/Platform.h       | 136 ++++++
 BhyvePkg/PlatformPei/PlatformPei.inf  | 117 +++++
 10 files changed, 1935 insertions(+)
 create mode 100644 BhyvePkg/PlatformPei/AmdSev.c
 create mode 100644 BhyvePkg/PlatformPei/ClearCache.c
 create mode 100644 BhyvePkg/PlatformPei/Cmos.c
 create mode 100644 BhyvePkg/PlatformPei/Cmos.h
 create mode 100644 BhyvePkg/PlatformPei/FeatureControl.c
 create mode 100644 BhyvePkg/PlatformPei/Fv.c
 create mode 100644 BhyvePkg/PlatformPei/MemDetect.c
 create mode 100644 BhyvePkg/PlatformPei/Platform.c
 create mode 100644 BhyvePkg/PlatformPei/Platform.h
 create mode 100644 BhyvePkg/PlatformPei/PlatformPei.inf

diff --git a/BhyvePkg/PlatformPei/AmdSev.c b/BhyvePkg/PlatformPei/AmdSev.c
new file mode 100644
index 0000000000..e484f4b311
--- /dev/null
+++ b/BhyvePkg/PlatformPei/AmdSev.c
@@ -0,0 +1,106 @@
+/**@file
+  Initialize Secure Encrypted Virtualization (SEV) support
+
+  Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+//
+// The package level header files this module uses
+//
+#include <IndustryStandard/Q35MchIch9.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/PcdLib.h>
+#include <PiPei.h>
+#include <Register/Amd/Cpuid.h>
+#include <Register/Cpuid.h>
+#include <Register/Intel/SmramSaveStateMap.h>
+
+#include "Platform.h"
+
+/**
+
+  Function checks if SEV support is available, if present then it sets
+  the dynamic PcdPteMemoryEncryptionAddressOrMask with memory encryption mask.
+
+  **/
+VOID
+AmdSevInitialize (
+  VOID
+  )
+{
+  CPUID_MEMORY_ENCRYPTION_INFO_EBX  Ebx;
+  UINT64                            EncryptionMask;
+  RETURN_STATUS                     PcdStatus;
+
+  //
+  // Check if SEV is enabled
+  //
+  if (!MemEncryptSevIsEnabled ()) {
+    return;
+  }
+
+  //
+  // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position)
+  //
+  AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL);
+  EncryptionMask = LShiftU64 (1, Ebx.Bits.PtePosBits);
+
+  //
+  // Set Memory Encryption Mask PCD
+  //
+  PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask);
+  ASSERT_RETURN_ERROR (PcdStatus);
+
+  DEBUG ((DEBUG_INFO, "SEV is enabled (mask 0x%lx)\n", EncryptionMask));
+
+  //
+  // Set Pcd to Deny the execution of option ROM when security
+  // violation.
+  //
+  PcdStatus = PcdSet32S (PcdOptionRomImageVerificationPolicy, 0x4);
+  ASSERT_RETURN_ERROR (PcdStatus);
+
+  //
+  // When SMM is required, cover the pages containing the initial SMRAM Save
+  // State Map with a memory allocation HOB:
+  //
+  // There's going to be a time interval between our decrypting those pages for
+  // SMBASE relocation and re-encrypting the same pages after SMBASE
+  // relocation. We shall ensure that the DXE phase stay away from those pages
+  // until after re-encryption, in order to prevent an information leak to the
+  // hypervisor.
+  //
+  if (FeaturePcdGet (PcdSmmSmramRequire) && (mBootMode != BOOT_ON_S3_RESUME)) {
+    RETURN_STATUS LocateMapStatus;
+    UINTN         MapPagesBase;
+    UINTN         MapPagesCount;
+
+    LocateMapStatus = MemEncryptSevLocateInitialSmramSaveStateMapPages (
+                        &MapPagesBase,
+                        &MapPagesCount
+                        );
+    ASSERT_RETURN_ERROR (LocateMapStatus);
+
+    if (mQ35SmramAtDefaultSmbase) {
+      //
+      // The initial SMRAM Save State Map has been covered as part of a larger
+      // reserved memory allocation in InitializeRamRegions().
+      //
+      ASSERT (SMM_DEFAULT_SMBASE <= MapPagesBase);
+      ASSERT (
+        (MapPagesBase + EFI_PAGES_TO_SIZE (MapPagesCount) <=
+         SMM_DEFAULT_SMBASE + MCH_DEFAULT_SMBASE_SIZE)
+        );
+    } else {
+      BuildMemoryAllocationHob (
+        MapPagesBase,                      // BaseAddress
+        EFI_PAGES_TO_SIZE (MapPagesCount), // Length
+        EfiBootServicesData                // MemoryType
+        );
+    }
+  }
+}
diff --git a/BhyvePkg/PlatformPei/ClearCache.c b/BhyvePkg/PlatformPei/ClearCache.c
new file mode 100644
index 0000000000..5c538c59e0
--- /dev/null
+++ b/BhyvePkg/PlatformPei/ClearCache.c
@@ -0,0 +1,111 @@
+/**@file
+  Install a callback to clear cache on all processors.
+  This is for conformance with the TCG "Platform Reset Attack Mitigation
+  Specification". Because clearing the CPU caches at boot doesn't impact
+  performance significantly, do it unconditionally, for simplicity's
+  sake.
+
+  Copyright (C) 2018, Red Hat, Inc.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/MpServices.h>
+
+#include "Platform.h"
+
+/**
+  Invalidate data & instruction caches.
+  All APs execute this function in parallel. The BSP executes the function
+  separately.
+
+  @param[in,out] WorkSpace  Pointer to the input/output argument workspace
+                            shared by all processors.
+**/
+STATIC
+VOID
+EFIAPI
+ClearCache (
+  IN OUT VOID *WorkSpace
+  )
+{
+  WriteBackInvalidateDataCache ();
+  InvalidateInstructionCache ();
+}
+
+/**
+  Notification function called when EFI_PEI_MP_SERVICES_PPI becomes available.
+
+  @param[in] PeiServices      Indirect reference to the PEI Services Table.
+  @param[in] NotifyDescriptor Address of the notification descriptor data
+                              structure.
+  @param[in] Ppi              Address of the PPI that was installed.
+
+  @return  Status of the notification. The status code returned from this
+           function is ignored.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ClearCacheOnMpServicesAvailable (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  )
+{
+  EFI_PEI_MP_SERVICES_PPI *MpServices;
+  EFI_STATUS              Status;
+
+  DEBUG ((DEBUG_INFO, "%a: %a\n", gEfiCallerBaseName, __FUNCTION__));
+
+  //
+  // Clear cache on all the APs in parallel.
+  //
+  MpServices = Ppi;
+  Status = MpServices->StartupAllAPs (
+                         (CONST EFI_PEI_SERVICES **)PeiServices,
+                         MpServices,
+                         ClearCache,          // Procedure
+                         FALSE,               // SingleThread
+                         0,                   // TimeoutInMicroSeconds: inf.
+                         NULL                 // ProcedureArgument
+                         );
+  if (EFI_ERROR (Status) && Status != EFI_NOT_STARTED) {
+    DEBUG ((DEBUG_ERROR, "%a: StartupAllAps(): %r\n", __FUNCTION__, Status));
+    return Status;
+  }
+
+  //
+  // Now clear cache on the BSP too.
+  //
+  ClearCache (NULL);
+  return EFI_SUCCESS;
+}
+
+//
+// Notification object for registering the callback, for when
+// EFI_PEI_MP_SERVICES_PPI becomes available.
+//
+STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mMpServicesNotify = {
+  EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | // Flags
+  EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+  &gEfiPeiMpServicesPpiGuid,               // Guid
+  ClearCacheOnMpServicesAvailable          // Notify
+};
+
+VOID
+InstallClearCacheCallback (
+  VOID
+  )
+{
+  EFI_STATUS           Status;
+
+  Status = PeiServicesNotifyPpi (&mMpServicesNotify);
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: failed to set up MP Services callback: %r\n",
+      __FUNCTION__, Status));
+  }
+}
diff --git a/BhyvePkg/PlatformPei/Cmos.c b/BhyvePkg/PlatformPei/Cmos.c
new file mode 100644
index 0000000000..9b34e10b17
--- /dev/null
+++ b/BhyvePkg/PlatformPei/Cmos.c
@@ -0,0 +1,58 @@
+/** @file
+  PC/AT CMOS access routines
+
+  Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include "Cmos.h"
+#include "Library/IoLib.h"
+
+/**
+  Reads 8-bits of CMOS data.
+
+  Reads the 8-bits of CMOS data at the location specified by Index.
+  The 8-bit read value is returned.
+
+  @param  Index  The CMOS location to read.
+
+  @return The value read.
+
+**/
+UINT8
+EFIAPI
+CmosRead8 (
+  IN      UINTN                     Index
+  )
+{
+  IoWrite8 (0x70, (UINT8) Index);
+  return IoRead8 (0x71);
+}
+
+
+/**
+  Writes 8-bits of CMOS data.
+
+  Writes 8-bits of CMOS data to the location specified by Index
+  with the value specified by Value and returns Value.
+
+  @param  Index  The CMOS location to write.
+  @param  Value  The value to write to CMOS.
+
+  @return The value written to CMOS.
+
+**/
+UINT8
+EFIAPI
+CmosWrite8 (
+  IN      UINTN                     Index,
+  IN      UINT8                     Value
+  )
+{
+  IoWrite8 (0x70, (UINT8) Index);
+  IoWrite8 (0x71, Value);
+  return Value;
+}
+
diff --git a/BhyvePkg/PlatformPei/Cmos.h b/BhyvePkg/PlatformPei/Cmos.h
new file mode 100644
index 0000000000..3cd98799a3
--- /dev/null
+++ b/BhyvePkg/PlatformPei/Cmos.h
@@ -0,0 +1,50 @@
+/** @file
+  PC/AT CMOS access routines
+
+  Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __CMOS_H__
+#define __CMOS_H__
+
+/**
+  Reads 8-bits of CMOS data.
+
+  Reads the 8-bits of CMOS data at the location specified by Index.
+  The 8-bit read value is returned.
+
+  @param  Index  The CMOS location to read.
+
+  @return The value read.
+
+**/
+UINT8
+EFIAPI
+CmosRead8 (
+  IN      UINTN                     Index
+  );
+
+/**
+  Writes 8-bits of CMOS data.
+
+  Writes 8-bits of CMOS data to the location specified by Index
+  with the value specified by Value and returns Value.
+
+  @param  Index  The CMOS location to write.
+  @param  Value  The value to write to CMOS.
+
+  @return The value written to CMOS.
+
+**/
+UINT8
+EFIAPI
+CmosWrite8 (
+  IN      UINTN                     Index,
+  IN      UINT8                     Value
+  );
+
+
+#endif
+
diff --git a/BhyvePkg/PlatformPei/FeatureControl.c b/BhyvePkg/PlatformPei/FeatureControl.c
new file mode 100644
index 0000000000..418b11a370
--- /dev/null
+++ b/BhyvePkg/PlatformPei/FeatureControl.c
@@ -0,0 +1,20 @@
+/**@file
+  Install a callback when necessary for setting the Feature Control MSR on all
+  processors.
+
+  Copyright (C) 2016, Red Hat, Inc.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Platform.h"
+
+VOID
+InstallFeatureControlCallback (
+  VOID
+  )
+{
+  //
+  // Nothing to do.
+  //
+}
diff --git a/BhyvePkg/PlatformPei/Fv.c b/BhyvePkg/PlatformPei/Fv.c
new file mode 100644
index 0000000000..ee4ecab615
--- /dev/null
+++ b/BhyvePkg/PlatformPei/Fv.c
@@ -0,0 +1,94 @@
+/** @file
+  Build FV related hobs for platform.
+
+  Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PiPei.h"
+#include "Platform.h"
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+
+
+/**
+  Publish PEI & DXE (Decompressed) Memory based FVs to let PEI
+  and DXE know about them.
+
+  @retval EFI_SUCCESS   Platform PEI FVs were initialized successfully.
+
+**/
+EFI_STATUS
+PeiFvInitialization (
+  VOID
+  )
+{
+  BOOLEAN SecureS3Needed;
+
+  DEBUG ((DEBUG_INFO, "Platform PEI Firmware Volume Initialization\n"));
+
+  //
+  // Create a memory allocation HOB for the PEI FV.
+  //
+  // Allocate as ACPI NVS is S3 is supported
+  //
+  BuildMemoryAllocationHob (
+    PcdGet32 (PcdOvmfPeiMemFvBase),
+    PcdGet32 (PcdOvmfPeiMemFvSize),
+    mS3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
+    );
+
+  //
+  // Let DXE know about the DXE FV
+  //
+  BuildFvHob (PcdGet32 (PcdOvmfDxeMemFvBase), PcdGet32 (PcdOvmfDxeMemFvSize));
+
+  SecureS3Needed = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire);
+
+  //
+  // Create a memory allocation HOB for the DXE FV.
+  //
+  // If "secure" S3 is needed, then SEC will decompress both PEI and DXE
+  // firmware volumes at S3 resume too, hence we need to keep away the OS from
+  // DXEFV as well. Otherwise we only need to keep away DXE itself from the
+  // DXEFV area.
+  //
+  BuildMemoryAllocationHob (
+    PcdGet32 (PcdOvmfDxeMemFvBase),
+    PcdGet32 (PcdOvmfDxeMemFvSize),
+    SecureS3Needed ? EfiACPIMemoryNVS : EfiBootServicesData
+    );
+
+  //
+  // Additionally, said decompression will use temporary memory above the end
+  // of DXEFV, so let's keep away the OS from there too.
+  //
+  if (SecureS3Needed) {
+    UINT32 DxeMemFvEnd;
+
+    DxeMemFvEnd = PcdGet32 (PcdOvmfDxeMemFvBase) +
+                  PcdGet32 (PcdOvmfDxeMemFvSize);
+    BuildMemoryAllocationHob (
+      DxeMemFvEnd,
+      PcdGet32 (PcdOvmfDecompressionScratchEnd) - DxeMemFvEnd,
+      EfiACPIMemoryNVS
+      );
+  }
+
+  //
+  // Let PEI know about the DXE FV so it can find the DXE Core
+  //
+  PeiServicesInstallFvInfoPpi (
+    NULL,
+    (VOID *)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase),
+    PcdGet32 (PcdOvmfDxeMemFvSize),
+    NULL,
+    NULL
+    );
+
+  return EFI_SUCCESS;
+}
+
diff --git a/BhyvePkg/PlatformPei/MemDetect.c b/BhyvePkg/PlatformPei/MemDetect.c
new file mode 100644
index 0000000000..1e18886248
--- /dev/null
+++ b/BhyvePkg/PlatformPei/MemDetect.c
@@ -0,0 +1,631 @@
+/**@file
+  Memory Detection for Virtual Machines.
+
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+  MemDetect.c
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <IndustryStandard/E820.h>
+#include <IndustryStandard/Q35MchIch9.h>
+#include <PiPei.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Library/MtrrLib.h>
+
+#include "Platform.h"
+#include "Cmos.h"
+
+UINT8 mPhysMemAddressWidth;
+
+STATIC UINT32 mS3AcpiReservedMemoryBase;
+STATIC UINT32 mS3AcpiReservedMemorySize;
+
+STATIC UINT16 mQ35TsegMbytes;
+
+BOOLEAN mQ35SmramAtDefaultSmbase = FALSE;
+
+VOID
+Q35TsegMbytesInitialization (
+  VOID
+  )
+{
+  UINT16        ExtendedTsegMbytes;
+  RETURN_STATUS PcdStatus;
+
+  if (mHostBridgeDevId != INTEL_Q35_MCH_DEVICE_ID) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
+      "only DID=0x%04x (Q35) is supported\n",
+      __FUNCTION__,
+      mHostBridgeDevId,
+      INTEL_Q35_MCH_DEVICE_ID
+      ));
+    ASSERT (FALSE);
+    CpuDeadLoop ();
+  }
+
+  //
+  // Check if QEMU offers an extended TSEG.
+  //
+  // This can be seen from writing MCH_EXT_TSEG_MB_QUERY to the MCH_EXT_TSEG_MB
+  // register, and reading back the register.
+  //
+  // On a QEMU machine type that does not offer an extended TSEG, the initial
+  // write overwrites whatever value a malicious guest OS may have placed in
+  // the (unimplemented) register, before entering S3 or rebooting.
+  // Subsequently, the read returns MCH_EXT_TSEG_MB_QUERY unchanged.
+  //
+  // On a QEMU machine type that offers an extended TSEG, the initial write
+  // triggers an update to the register. Subsequently, the value read back
+  // (which is guaranteed to differ from MCH_EXT_TSEG_MB_QUERY) tells us the
+  // number of megabytes.
+  //
+  PciWrite16 (DRAMC_REGISTER_Q35 (MCH_EXT_TSEG_MB), MCH_EXT_TSEG_MB_QUERY);
+  ExtendedTsegMbytes = PciRead16 (DRAMC_REGISTER_Q35 (MCH_EXT_TSEG_MB));
+  if (ExtendedTsegMbytes == MCH_EXT_TSEG_MB_QUERY) {
+    mQ35TsegMbytes = PcdGet16 (PcdQ35TsegMbytes);
+    return;
+  }
+
+  DEBUG ((
+    DEBUG_INFO,
+    "%a: QEMU offers an extended TSEG (%d MB)\n",
+    __FUNCTION__,
+    ExtendedTsegMbytes
+    ));
+  PcdStatus = PcdSet16S (PcdQ35TsegMbytes, ExtendedTsegMbytes);
+  ASSERT_RETURN_ERROR (PcdStatus);
+  mQ35TsegMbytes = ExtendedTsegMbytes;
+}
+
+
+UINT32
+GetSystemMemorySizeBelow4gb (
+  VOID
+  )
+{
+  UINT8 Cmos0x34;
+  UINT8 Cmos0x35;
+
+  //
+  // CMOS 0x34/0x35 specifies the system memory above 16 MB.
+  // * CMOS(0x35) is the high byte
+  // * CMOS(0x34) is the low byte
+  // * The size is specified in 64kb chunks
+  // * Since this is memory above 16MB, the 16MB must be added
+  //   into the calculation to get the total memory size.
+  //
+
+  Cmos0x34 = (UINT8) CmosRead8 (0x34);
+  Cmos0x35 = (UINT8) CmosRead8 (0x35);
+
+  return (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);
+}
+
+
+STATIC
+UINT64
+GetSystemMemorySizeAbove4gb (
+  )
+{
+  UINT32 Size;
+  UINTN  CmosIndex;
+
+  //
+  // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.
+  // * CMOS(0x5d) is the most significant size byte
+  // * CMOS(0x5c) is the middle size byte
+  // * CMOS(0x5b) is the least significant size byte
+  // * The size is specified in 64kb chunks
+  //
+
+  Size = 0;
+  for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {
+    Size = (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex);
+  }
+
+  return LShiftU64 (Size, 16);
+}
+
+
+/**
+  Return the highest address that DXE could possibly use, plus one.
+**/
+STATIC
+UINT64
+GetFirstNonAddress (
+  VOID
+  )
+{
+  UINT64               FirstNonAddress;
+  UINT64               Pci64Base, Pci64Size;
+  RETURN_STATUS        PcdStatus;
+
+  FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb ();
+
+  //
+  // If DXE is 32-bit, then we're done; PciBusDxe will degrade 64-bit MMIO
+  // resources to 32-bit anyway. See DegradeResource() in
+  // "PciResourceSupport.c".
+  //
+#ifdef MDE_CPU_IA32
+  if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+    return FirstNonAddress;
+  }
+#endif
+
+  //
+  // Otherwise, in order to calculate the highest address plus one, we must
+  // consider the 64-bit PCI host aperture too. Fetch the default size.
+  //
+  Pci64Size = PcdGet64 (PcdPciMmio64Size);
+
+  if (Pci64Size == 0) {
+    if (mBootMode != BOOT_ON_S3_RESUME) {
+      DEBUG ((DEBUG_INFO, "%a: disabling 64-bit PCI host aperture\n",
+        __FUNCTION__));
+      PcdStatus = PcdSet64S (PcdPciMmio64Size, 0);
+      ASSERT_RETURN_ERROR (PcdStatus);
+    }
+
+    //
+    // There's nothing more to do; the amount of memory above 4GB fully
+    // determines the highest address plus one. The memory hotplug area (see
+    // below) plays no role for the firmware in this case.
+    //
+    return FirstNonAddress;
+  }
+
+  //
+  // SeaBIOS aligns both boundaries of the 64-bit PCI host aperture to 1GB, so
+  // that the host can map it with 1GB hugepages. Follow suit.
+  //
+  Pci64Base = ALIGN_VALUE (FirstNonAddress, (UINT64)SIZE_1GB);
+  Pci64Size = ALIGN_VALUE (Pci64Size, (UINT64)SIZE_1GB);
+
+  //
+  // The 64-bit PCI host aperture should also be "naturally" aligned. The
+  // alignment is determined by rounding the size of the aperture down to the
+  // next smaller or equal power of two. That is, align the aperture by the
+  // largest BAR size that can fit into it.
+  //
+  Pci64Base = ALIGN_VALUE (Pci64Base, GetPowerOfTwo64 (Pci64Size));
+
+  if (mBootMode != BOOT_ON_S3_RESUME) {
+    //
+    // The core PciHostBridgeDxe driver will automatically add this range to
+    // the GCD memory space map through our PciHostBridgeLib instance; here we
+    // only need to set the PCDs.
+    //
+    PcdStatus = PcdSet64S (PcdPciMmio64Base, Pci64Base);
+    ASSERT_RETURN_ERROR (PcdStatus);
+    PcdStatus = PcdSet64S (PcdPciMmio64Size, Pci64Size);
+    ASSERT_RETURN_ERROR (PcdStatus);
+
+    DEBUG ((DEBUG_INFO, "%a: Pci64Base=0x%Lx Pci64Size=0x%Lx\n",
+      __FUNCTION__, Pci64Base, Pci64Size));
+  }
+
+  //
+  // The useful address space ends with the 64-bit PCI host aperture.
+  //
+  FirstNonAddress = Pci64Base + Pci64Size;
+  return FirstNonAddress;
+}
+
+
+/**
+  Initialize the mPhysMemAddressWidth variable, based on guest RAM size.
+**/
+VOID
+AddressWidthInitialization (
+  VOID
+  )
+{
+  UINT64 FirstNonAddress;
+
+  //
+  // As guest-physical memory size grows, the permanent PEI RAM requirements
+  // are dominated by the identity-mapping page tables built by the DXE IPL.
+  // The DXL IPL keys off of the physical address bits advertized in the CPU
+  // HOB. To conserve memory, we calculate the minimum address width here.
+  //
+  FirstNonAddress      = GetFirstNonAddress ();
+  mPhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);
+
+  //
+  // If FirstNonAddress is not an integral power of two, then we need an
+  // additional bit.
+  //
+  if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) {
+    ++mPhysMemAddressWidth;
+  }
+
+  //
+  // The minimum address width is 36 (covers up to and excluding 64 GB, which
+  // is the maximum for Ia32 + PAE). The theoretical architecture maximum for
+  // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 bits. We
+  // can simply assert that here, since 48 bits are good enough for 256 TB.
+  //
+  if (mPhysMemAddressWidth <= 36) {
+    mPhysMemAddressWidth = 36;
+  }
+  ASSERT (mPhysMemAddressWidth <= 48);
+}
+
+
+/**
+  Calculate the cap for the permanent PEI memory.
+**/
+STATIC
+UINT32
+GetPeiMemoryCap (
+  VOID
+  )
+{
+  BOOLEAN Page1GSupport;
+  UINT32  RegEax;
+  UINT32  RegEdx;
+  UINT32  Pml4Entries;
+  UINT32  PdpEntries;
+  UINTN   TotalPages;
+
+  //
+  // If DXE is 32-bit, then just return the traditional 64 MB cap.
+  //
+#ifdef MDE_CPU_IA32
+  if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+    return SIZE_64MB;
+  }
+#endif
+
+  //
+  // Dependent on physical address width, PEI memory allocations can be
+  // dominated by the page tables built for 64-bit DXE. So we key the cap off
+  // of those. The code below is based on CreateIdentityMappingPageTables() in
+  // "MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c".
+  //
+  Page1GSupport = FALSE;
+  if (PcdGetBool (PcdUse1GPageTable)) {
+    AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+    if (RegEax >= 0x80000001) {
+      AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+      if ((RegEdx & BIT26) != 0) {
+        Page1GSupport = TRUE;
+      }
+    }
+  }
+
+  if (mPhysMemAddressWidth <= 39) {
+    Pml4Entries = 1;
+    PdpEntries = 1 << (mPhysMemAddressWidth - 30);
+    ASSERT (PdpEntries <= 0x200);
+  } else {
+    Pml4Entries = 1 << (mPhysMemAddressWidth - 39);
+    ASSERT (Pml4Entries <= 0x200);
+    PdpEntries = 512;
+  }
+
+  TotalPages = Page1GSupport ? Pml4Entries + 1 :
+                               (PdpEntries + 1) * Pml4Entries + 1;
+  ASSERT (TotalPages <= 0x40201);
+
+  //
+  // Add 64 MB for miscellaneous allocations. Note that for
+  // mPhysMemAddressWidth values close to 36, the cap will actually be
+  // dominated by this increment.
+  //
+  return (UINT32)(EFI_PAGES_TO_SIZE (TotalPages) + SIZE_64MB);
+}
+
+
+/**
+  Publish PEI core memory
+
+  @return EFI_SUCCESS     The PEIM initialized successfully.
+
+**/
+EFI_STATUS
+PublishPeiMemory (
+  VOID
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_PHYSICAL_ADDRESS        MemoryBase;
+  UINT64                      MemorySize;
+  UINT32                      LowerMemorySize;
+  UINT32                      PeiMemoryCap;
+
+  LowerMemorySize = GetSystemMemorySizeBelow4gb ();
+  if (FeaturePcdGet (PcdSmmSmramRequire)) {
+    //
+    // TSEG is chipped from the end of low RAM
+    //
+    LowerMemorySize -= mQ35TsegMbytes * SIZE_1MB;
+  }
+
+  //
+  // If S3 is supported, then the S3 permanent PEI memory is placed next,
+  // downwards. Its size is primarily dictated by CpuMpPei. The formula below
+  // is an approximation.
+  //
+  if (mS3Supported) {
+    mS3AcpiReservedMemorySize = SIZE_512KB +
+      mMaxCpuCount *
+      PcdGet32 (PcdCpuApStackSize);
+    mS3AcpiReservedMemoryBase = LowerMemorySize - mS3AcpiReservedMemorySize;
+    LowerMemorySize = mS3AcpiReservedMemoryBase;
+  }
+
+  if (mBootMode == BOOT_ON_S3_RESUME) {
+    MemoryBase = mS3AcpiReservedMemoryBase;
+    MemorySize = mS3AcpiReservedMemorySize;
+  } else {
+    PeiMemoryCap = GetPeiMemoryCap ();
+    DEBUG ((DEBUG_INFO, "%a: mPhysMemAddressWidth=%d PeiMemoryCap=%u KB\n",
+      __FUNCTION__, mPhysMemAddressWidth, PeiMemoryCap >> 10));
+
+    //
+    // Determine the range of memory to use during PEI
+    //
+    // Technically we could lay the permanent PEI RAM over SEC's temporary
+    // decompression and scratch buffer even if "secure S3" is needed, since
+    // their lifetimes don't overlap. However, PeiFvInitialization() will cover
+    // RAM up to PcdOvmfDecompressionScratchEnd with an EfiACPIMemoryNVS memory
+    // allocation HOB, and other allocations served from the permanent PEI RAM
+    // shouldn't overlap with that HOB.
+    //
+    MemoryBase = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire) ?
+      PcdGet32 (PcdOvmfDecompressionScratchEnd) :
+      PcdGet32 (PcdOvmfDxeMemFvBase) + PcdGet32 (PcdOvmfDxeMemFvSize);
+    MemorySize = LowerMemorySize - MemoryBase;
+    if (MemorySize > PeiMemoryCap) {
+      MemoryBase = LowerMemorySize - PeiMemoryCap;
+      MemorySize = PeiMemoryCap;
+    }
+  }
+
+  //
+  // Publish this memory to the PEI Core
+  //
+  Status = PublishSystemMemory(MemoryBase, MemorySize);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
+
+
+/**
+  Peform Memory Detection for QEMU / KVM
+
+**/
+STATIC
+VOID
+QemuInitializeRam (
+  VOID
+  )
+{
+  UINT64                      LowerMemorySize;
+  UINT64                      UpperMemorySize;
+  MTRR_SETTINGS               MtrrSettings;
+  EFI_STATUS                  Status;
+
+  DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
+
+  //
+  // Determine total memory size available
+  //
+  LowerMemorySize = GetSystemMemorySizeBelow4gb ();
+  UpperMemorySize = GetSystemMemorySizeAbove4gb ();
+
+  if (mBootMode == BOOT_ON_S3_RESUME) {
+    //
+    // Create the following memory HOB as an exception on the S3 boot path.
+    //
+    // Normally we'd create memory HOBs only on the normal boot path. However,
+    // CpuMpPei specifically needs such a low-memory HOB on the S3 path as
+    // well, for "borrowing" a subset of it temporarily, for the AP startup
+    // vector.
+    //
+    // CpuMpPei saves the original contents of the borrowed area in permanent
+    // PEI RAM, in a backup buffer allocated with the normal PEI services.
+    // CpuMpPei restores the original contents ("returns" the borrowed area) at
+    // End-of-PEI. End-of-PEI in turn is emitted by S3Resume2Pei before
+    // transferring control to the OS's wakeup vector in the FACS.
+    //
+    // We expect any other PEIMs that "borrow" memory similarly to CpuMpPei to
+    // restore the original contents. Furthermore, we expect all such PEIMs
+    // (CpuMpPei included) to claim the borrowed areas by producing memory
+    // allocation HOBs, and to honor preexistent memory allocation HOBs when
+    // looking for an area to borrow.
+    //
+    AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
+  } else {
+    //
+    // Create memory HOBs
+    //
+    AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
+
+    if (FeaturePcdGet (PcdSmmSmramRequire)) {
+      UINT32 TsegSize;
+
+      TsegSize = mQ35TsegMbytes * SIZE_1MB;
+      AddMemoryRangeHob (BASE_1MB, LowerMemorySize - TsegSize);
+      AddReservedMemoryBaseSizeHob (LowerMemorySize - TsegSize, TsegSize,
+        TRUE);
+    } else {
+      AddMemoryRangeHob (BASE_1MB, LowerMemorySize);
+    }
+
+    if (UpperMemorySize != 0) {
+      AddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);
+    }
+  }
+
+  //
+  // We'd like to keep the following ranges uncached:
+  // - [640 KB, 1 MB)
+  // - [LowerMemorySize, 4 GB)
+  //
+  // Everything else should be WB. Unfortunately, programming the inverse (ie.
+  // keeping the default UC, and configuring the complement set of the above as
+  // WB) is not reliable in general, because the end of the upper RAM can have
+  // practically any alignment, and we may not have enough variable MTRRs to
+  // cover it exactly.
+  //
+  if (IsMtrrSupported ()) {
+    MtrrGetAllMtrrs (&MtrrSettings);
+
+    //
+    // MTRRs disabled, fixed MTRRs disabled, default type is uncached
+    //
+    ASSERT ((MtrrSettings.MtrrDefType & BIT11) == 0);
+    ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);
+    ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 0);
+
+    //
+    // flip default type to writeback
+    //
+    SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);
+    ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);
+    MtrrSettings.MtrrDefType |= BIT11 | BIT10 | 6;
+    MtrrSetAllMtrrs (&MtrrSettings);
+
+    //
+    // Set memory range from 640KB to 1MB to uncacheable
+    //
+    Status = MtrrSetMemoryAttribute (BASE_512KB + BASE_128KB,
+               BASE_1MB - (BASE_512KB + BASE_128KB), CacheUncacheable);
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // Set memory range from the "top of lower RAM" (RAM below 4GB) to 4GB as
+    // uncacheable
+    //
+    Status = MtrrSetMemoryAttribute (LowerMemorySize,
+               SIZE_4GB - LowerMemorySize, CacheUncacheable);
+    ASSERT_EFI_ERROR (Status);
+  }
+}
+
+/**
+  Publish system RAM and reserve memory regions
+
+**/
+VOID
+InitializeRamRegions (
+  VOID
+  )
+{
+  QemuInitializeRam ();
+
+  if (mS3Supported && mBootMode != BOOT_ON_S3_RESUME) {
+    //
+    // This is the memory range that will be used for PEI on S3 resume
+    //
+    BuildMemoryAllocationHob (
+      mS3AcpiReservedMemoryBase,
+      mS3AcpiReservedMemorySize,
+      EfiACPIMemoryNVS
+      );
+
+    //
+    // Cover the initial RAM area used as stack and temporary PEI heap.
+    //
+    // This is reserved as ACPI NVS so it can be used on S3 resume.
+    //
+    BuildMemoryAllocationHob (
+      PcdGet32 (PcdOvmfSecPeiTempRamBase),
+      PcdGet32 (PcdOvmfSecPeiTempRamSize),
+      EfiACPIMemoryNVS
+      );
+
+    //
+    // SEC stores its table of GUIDed section handlers here.
+    //
+    BuildMemoryAllocationHob (
+      PcdGet64 (PcdGuidedExtractHandlerTableAddress),
+      PcdGet32 (PcdGuidedExtractHandlerTableSize),
+      EfiACPIMemoryNVS
+      );
+
+#ifdef MDE_CPU_X64
+    //
+    // Reserve the initial page tables built by the reset vector code.
+    //
+    // Since this memory range will be used by the Reset Vector on S3
+    // resume, it must be reserved as ACPI NVS.
+    //
+    BuildMemoryAllocationHob (
+      (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfSecPageTablesBase),
+      (UINT64)(UINTN) PcdGet32 (PcdOvmfSecPageTablesSize),
+      EfiACPIMemoryNVS
+      );
+#endif
+  }
+
+  if (mBootMode != BOOT_ON_S3_RESUME) {
+    if (!FeaturePcdGet (PcdSmmSmramRequire)) {
+      //
+      // Reserve the lock box storage area
+      //
+      // Since this memory range will be used on S3 resume, it must be
+      // reserved as ACPI NVS.
+      //
+      // If S3 is unsupported, then various drivers might still write to the
+      // LockBox area. We ought to prevent DXE from serving allocation requests
+      // such that they would overlap the LockBox storage.
+      //
+      ZeroMem (
+        (VOID*)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase),
+        (UINTN) PcdGet32 (PcdOvmfLockBoxStorageSize)
+        );
+      BuildMemoryAllocationHob (
+        (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase),
+        (UINT64)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageSize),
+        mS3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
+        );
+    }
+
+    if (FeaturePcdGet (PcdSmmSmramRequire)) {
+      UINT32 TsegSize;
+
+      //
+      // Make sure the TSEG area that we reported as a reserved memory resource
+      // cannot be used for reserved memory allocations.
+      //
+      TsegSize = mQ35TsegMbytes * SIZE_1MB;
+      BuildMemoryAllocationHob (
+        GetSystemMemorySizeBelow4gb() - TsegSize,
+        TsegSize,
+        EfiReservedMemoryType
+        );
+    }
+  }
+}
diff --git a/BhyvePkg/PlatformPei/Platform.c b/BhyvePkg/PlatformPei/Platform.c
new file mode 100644
index 0000000000..10719d6f08
--- /dev/null
+++ b/BhyvePkg/PlatformPei/Platform.c
@@ -0,0 +1,612 @@
+/**@file
+  Platform PEI driver
+
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
+
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Library/LocalApicLib.h>
+#include <Guid/MemoryTypeInformation.h>
+#include <Ppi/MasterBootMode.h>
+#include <IndustryStandard/Pci22.h>
+#include <OvmfPlatforms.h>
+
+#include "Platform.h"
+#include "Cmos.h"
+
+EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
+  { EfiACPIMemoryNVS,       0x004 },
+  { EfiACPIReclaimMemory,   0x008 },
+  { EfiReservedMemoryType,  0x004 },
+  { EfiRuntimeServicesData, 0x024 },
+  { EfiRuntimeServicesCode, 0x030 },
+  { EfiBootServicesCode,    0x180 },
+  { EfiBootServicesData,    0xF00 },
+  { EfiMaxMemoryType,       0x000 }
+};
+
+
+EFI_PEI_PPI_DESCRIPTOR   mPpiBootMode[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+    &gEfiPeiMasterBootModePpiGuid,
+    NULL
+  }
+};
+
+
+UINT16 mHostBridgeDevId;
+
+EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
+
+BOOLEAN mS3Supported = FALSE;
+
+UINT32 mMaxCpuCount;
+
+VOID
+AddIoMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize
+  )
+{
+  BuildResourceDescriptorHob (
+    EFI_RESOURCE_MEMORY_MAPPED_IO,
+      EFI_RESOURCE_ATTRIBUTE_PRESENT     |
+      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_TESTED,
+    MemoryBase,
+    MemorySize
+    );
+}
+
+VOID
+AddReservedMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize,
+  BOOLEAN                     Cacheable
+  )
+{
+  BuildResourceDescriptorHob (
+    EFI_RESOURCE_MEMORY_RESERVED,
+      EFI_RESOURCE_ATTRIBUTE_PRESENT     |
+      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+      (Cacheable ?
+       EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+       EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+       EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE :
+       0
+       ) |
+      EFI_RESOURCE_ATTRIBUTE_TESTED,
+    MemoryBase,
+    MemorySize
+    );
+}
+
+VOID
+AddIoMemoryRangeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  EFI_PHYSICAL_ADDRESS        MemoryLimit
+  )
+{
+  AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+
+VOID
+AddMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize
+  )
+{
+  BuildResourceDescriptorHob (
+    EFI_RESOURCE_SYSTEM_MEMORY,
+      EFI_RESOURCE_ATTRIBUTE_PRESENT |
+      EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+      EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+      EFI_RESOURCE_ATTRIBUTE_TESTED,
+    MemoryBase,
+    MemorySize
+    );
+}
+
+
+VOID
+AddMemoryRangeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  EFI_PHYSICAL_ADDRESS        MemoryLimit
+  )
+{
+  AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+
+VOID
+MemMapInitialization (
+  VOID
+  )
+{
+  UINT64        PciIoBase;
+  UINT64        PciIoSize;
+  RETURN_STATUS PcdStatus;
+
+  PciIoBase = 0xC000;
+  PciIoSize = 0x4000;
+
+  //
+  // Create Memory Type Information HOB
+  //
+  BuildGuidDataHob (
+    &gEfiMemoryTypeInformationGuid,
+    mDefaultMemoryTypeInformation,
+    sizeof(mDefaultMemoryTypeInformation)
+    );
+
+  //
+  // Video memory + Legacy BIOS region
+  //
+  AddIoMemoryRangeHob (0x0A0000, BASE_1MB);
+
+  if (TRUE) {
+    UINT32  TopOfLowRam;
+    UINT64  PciExBarBase;
+    UINT32  PciBase;
+    UINT32  PciSize;
+
+    TopOfLowRam = GetSystemMemorySizeBelow4gb ();
+    PciExBarBase = 0;
+    if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
+      //
+      // The MMCONFIG area is expected to fall between the top of low RAM and
+      // the base of the 32-bit PCI host aperture.
+      //
+      PciExBarBase = FixedPcdGet64 (PcdPciExpressBaseAddress);
+      ASSERT (TopOfLowRam <= PciExBarBase);
+      ASSERT (PciExBarBase <= MAX_UINT32 - SIZE_256MB);
+      PciBase = (UINT32)(PciExBarBase + SIZE_256MB);
+    } else {
+      PciBase = (TopOfLowRam < BASE_2GB) ? BASE_2GB : TopOfLowRam;
+    }
+
+    //
+    // address       purpose   size
+    // ------------  --------  -------------------------
+    // max(top, 2g)  PCI MMIO  0xFC000000 - max(top, 2g)
+    // 0xFC000000    gap                           44 MB
+    // 0xFEC00000    IO-APIC                        4 KB
+    // 0xFEC01000    gap                         1020 KB
+    // 0xFED00000    HPET                           1 KB
+    // 0xFED00400    gap                          111 KB
+    // 0xFED1C000    gap (PIIX4) / RCRB (ICH9)     16 KB
+    // 0xFED20000    gap                          896 KB
+    // 0xFEE00000    LAPIC                          1 MB
+    //
+    PciSize = 0xFC000000 - PciBase;
+    AddIoMemoryBaseSizeHob (PciBase, PciSize);
+    PcdStatus = PcdSet64S (PcdPciMmio32Base, PciBase);
+    ASSERT_RETURN_ERROR (PcdStatus);
+    PcdStatus = PcdSet64S (PcdPciMmio32Size, PciSize);
+    ASSERT_RETURN_ERROR (PcdStatus);
+
+    AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB);
+    AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB);
+    if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
+      AddIoMemoryBaseSizeHob (ICH9_ROOT_COMPLEX_BASE, SIZE_16KB);
+      //
+      // Note: there should be an
+      //
+      //   AddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB);
+      //
+      // call below, just like the one above for RCBA. However, Linux insists
+      // that the MMCONFIG area be marked in the E820 or UEFI memory map as
+      // "reserved memory" -- Linux does not content itself with a simple gap
+      // in the memory map wherever the MCFG ACPI table points to.
+      //
+      // This appears to be a safety measure. The PCI Firmware Specification
+      // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can
+      // *optionally* be returned in [...] EFIGetMemoryMap as reserved memory
+      // [...]". (Emphasis added here.)
+      //
+      // Normally we add memory resource descriptor HOBs in
+      // QemuInitializeRam(), and pre-allocate from those with memory
+      // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area
+      // is most definitely not RAM; so, as an exception, cover it with
+      // uncacheable reserved memory right here.
+      //
+      AddReservedMemoryBaseSizeHob (PciExBarBase, SIZE_256MB, FALSE);
+      BuildMemoryAllocationHob (PciExBarBase, SIZE_256MB,
+        EfiReservedMemoryType);
+    }
+    AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB);
+
+    //
+    // On Q35, the IO Port space is available for PCI resource allocations from
+    // 0x6000 up.
+    //
+    if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
+      PciIoBase = 0x6000;
+      PciIoSize = 0xA000;
+      ASSERT ((ICH9_PMBASE_VALUE & 0xF000) < PciIoBase);
+    }
+  }
+
+  //
+  // Add PCI IO Port space available for PCI resource allocations.
+  //
+  BuildResourceDescriptorHob (
+    EFI_RESOURCE_IO,
+    EFI_RESOURCE_ATTRIBUTE_PRESENT     |
+    EFI_RESOURCE_ATTRIBUTE_INITIALIZED,
+    PciIoBase,
+    PciIoSize
+    );
+  PcdStatus = PcdSet64S (PcdPciIoBase, PciIoBase);
+  ASSERT_RETURN_ERROR (PcdStatus);
+  PcdStatus = PcdSet64S (PcdPciIoSize, PciIoSize);
+  ASSERT_RETURN_ERROR (PcdStatus);
+}
+
+VOID
+NoexecDxeInitialization (
+  VOID
+  )
+{
+}
+
+VOID
+PciExBarInitialization (
+  VOID
+  )
+{
+  union {
+    UINT64 Uint64;
+    UINT32 Uint32[2];
+  } PciExBarBase;
+
+  //
+  // We only support the 256MB size for the MMCONFIG area:
+  // 256 buses * 32 devices * 8 functions * 4096 bytes config space.
+  //
+  // The masks used below enforce the Q35 requirements that the MMCONFIG area
+  // be (a) correctly aligned -- here at 256 MB --, (b) located under 64 GB.
+  //
+  // Note that (b) also ensures that the minimum address width we have
+  // determined in AddressWidthInitialization(), i.e., 36 bits, will suffice
+  // for DXE's page tables to cover the MMCONFIG area.
+  //
+  PciExBarBase.Uint64 = FixedPcdGet64 (PcdPciExpressBaseAddress);
+  ASSERT ((PciExBarBase.Uint32[1] & MCH_PCIEXBAR_HIGHMASK) == 0);
+  ASSERT ((PciExBarBase.Uint32[0] & MCH_PCIEXBAR_LOWMASK) == 0);
+
+  //
+  // Clear the PCIEXBAREN bit first, before programming the high register.
+  //
+  PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW), 0);
+
+  //
+  // Program the high register. Then program the low register, setting the
+  // MMCONFIG area size and enabling decoding at once.
+  //
+  PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_HIGH), PciExBarBase.Uint32[1]);
+  PciWrite32 (
+    DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW),
+    PciExBarBase.Uint32[0] | MCH_PCIEXBAR_BUS_FF | MCH_PCIEXBAR_EN
+    );
+}
+
+VOID
+MiscInitialization (
+  VOID
+  )
+{
+  UINTN         PmCmd;
+  UINTN         Pmba;
+  UINT32        PmbaAndVal;
+  UINT32        PmbaOrVal;
+  UINTN         AcpiCtlReg;
+  UINT8         AcpiEnBit;
+  RETURN_STATUS PcdStatus;
+
+  //
+  // Disable A20 Mask
+  //
+  IoOr8 (0x92, BIT1);
+
+  //
+  // Build the CPU HOB with guest RAM size dependent address width and 16-bits
+  // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
+  // S3 resume as well, so we build it unconditionally.)
+  //
+  BuildCpuHob (mPhysMemAddressWidth, 16);
+
+  //
+  // Determine platform type and save Host Bridge DID to PCD
+  //
+  switch (mHostBridgeDevId) {
+    case 0x1275: // BHYVE
+    case INTEL_82441_DEVICE_ID:
+      PmCmd      = POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET);
+      Pmba       = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
+      PmbaAndVal = ~(UINT32)PIIX4_PMBA_MASK;
+      PmbaOrVal  = PIIX4_PMBA_VALUE;
+      AcpiCtlReg = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC);
+      AcpiEnBit  = PIIX4_PMREGMISC_PMIOSE;
+      break;
+    case INTEL_Q35_MCH_DEVICE_ID:
+      PmCmd      = POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET);
+      Pmba       = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
+      PmbaAndVal = ~(UINT32)ICH9_PMBASE_MASK;
+      PmbaOrVal  = ICH9_PMBASE_VALUE;
+      AcpiCtlReg = POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL);
+      AcpiEnBit  = ICH9_ACPI_CNTL_ACPI_EN;
+      break;
+    default:
+      DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
+        __FUNCTION__, mHostBridgeDevId));
+      ASSERT (FALSE);
+      return;
+  }
+  PcdStatus = PcdSet16S (PcdOvmfHostBridgePciDevId, mHostBridgeDevId);
+  ASSERT_RETURN_ERROR (PcdStatus);
+
+  //
+  // If the appropriate IOspace enable bit is set, assume the ACPI PMBA
+  // has been configured (e.g., by Xen) and skip the setup here.
+  // This matches the logic in AcpiTimerLibConstructor ().
+  //
+  if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) == 0) {
+    //
+    // The PEI phase should be exited with fully accessibe ACPI PM IO space:
+    // 1. set PMBA
+    //
+    PciAndThenOr32 (Pmba, PmbaAndVal, PmbaOrVal);
+
+    //
+    // 2. set PCICMD/IOSE
+    //
+    PciOr8 (PmCmd, EFI_PCI_COMMAND_IO_SPACE);
+
+    //
+    // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN)
+    //
+    PciOr8 (AcpiCtlReg, AcpiEnBit);
+  }
+
+  if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
+    //
+    // Set Root Complex Register Block BAR
+    //
+    PciWrite32 (
+      POWER_MGMT_REGISTER_Q35 (ICH9_RCBA),
+      ICH9_ROOT_COMPLEX_BASE | ICH9_RCBA_EN
+      );
+
+    //
+    // Set PCI Express Register Range Base Address
+    //
+    PciExBarInitialization ();
+  }
+}
+
+
+VOID
+BootModeInitialization (
+  VOID
+  )
+{
+  EFI_STATUS    Status;
+
+  if (CmosRead8 (0xF) == 0xFE) {
+    mBootMode = BOOT_ON_S3_RESUME;
+  }
+  CmosWrite8 (0xF, 0x00);
+
+  Status = PeiServicesSetBootMode (mBootMode);
+  ASSERT_EFI_ERROR (Status);
+
+  Status = PeiServicesInstallPpi (mPpiBootMode);
+  ASSERT_EFI_ERROR (Status);
+}
+
+
+VOID
+ReserveEmuVariableNvStore (
+  )
+{
+  EFI_PHYSICAL_ADDRESS VariableStore;
+  RETURN_STATUS        PcdStatus;
+
+  //
+  // Allocate storage for NV variables early on so it will be
+  // at a consistent address.  Since VM memory is preserved
+  // across reboots, this allows the NV variable storage to survive
+  // a VM reboot.
+  //
+  VariableStore =
+    (EFI_PHYSICAL_ADDRESS)(UINTN)
+      AllocateRuntimePages (
+        EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize))
+        );
+  DEBUG ((DEBUG_INFO,
+          "Reserved variable store memory: 0x%lX; size: %dkb\n",
+          VariableStore,
+          (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024
+        ));
+  PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore);
+  ASSERT_RETURN_ERROR (PcdStatus);
+}
+
+
+VOID
+DebugDumpCmos (
+  VOID
+  )
+{
+  UINT32 Loop;
+
+  DEBUG ((DEBUG_INFO, "CMOS:\n"));
+
+  for (Loop = 0; Loop < 0x80; Loop++) {
+    if ((Loop % 0x10) == 0) {
+      DEBUG ((DEBUG_INFO, "%02x:", Loop));
+    }
+    DEBUG ((DEBUG_INFO, " %02x", CmosRead8 (Loop)));
+    if ((Loop % 0x10) == 0xf) {
+      DEBUG ((DEBUG_INFO, "\n"));
+    }
+  }
+}
+
+
+VOID
+S3Verification (
+  VOID
+  )
+{
+#if defined (MDE_CPU_X64)
+  if (FeaturePcdGet (PcdSmmSmramRequire) && mS3Supported) {
+    DEBUG ((DEBUG_ERROR,
+      "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n", __FUNCTION__));
+    DEBUG ((DEBUG_ERROR,
+      "%a: Please disable S3 on the QEMU command line (see the README),\n",
+      __FUNCTION__));
+    DEBUG ((DEBUG_ERROR,
+      "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n", __FUNCTION__));
+    ASSERT (FALSE);
+    CpuDeadLoop ();
+  }
+#endif
+}
+
+
+/**
+  Fetch the number of boot CPUs from QEMU and expose it to UefiCpuPkg modules.
+  Set the mMaxCpuCount variable.
+**/
+VOID
+MaxCpuCountInitialization (
+  VOID
+  )
+{
+  UINT16        ProcessorCount = 0;
+  RETURN_STATUS PcdStatus;
+
+  //
+  // If the fw_cfg key or fw_cfg entirely is unavailable, load mMaxCpuCount
+  // from the PCD default. No change to PCDs.
+  //
+  if (ProcessorCount == 0) {
+    mMaxCpuCount = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+    return;
+  }
+  //
+  // Otherwise, set mMaxCpuCount to the value reported by QEMU.
+  //
+  mMaxCpuCount = ProcessorCount;
+  //
+  // Additionally, tell UefiCpuPkg modules (a) the exact number of VCPUs, (b)
+  // to wait, in the initial AP bringup, exactly as long as it takes for all of
+  // the APs to report in. For this, we set the longest representable timeout
+  // (approx. 71 minutes).
+  //
+  PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, ProcessorCount);
+  ASSERT_RETURN_ERROR (PcdStatus);
+  PcdStatus = PcdSet32S (PcdCpuApInitTimeOutInMicroSeconds, MAX_UINT32);
+  ASSERT_RETURN_ERROR (PcdStatus);
+  DEBUG ((DEBUG_INFO, "%a: QEMU reports %d processor(s)\n", __FUNCTION__,
+    ProcessorCount));
+}
+
+
+/**
+  Perform Platform PEI initialization.
+
+  @param  FileHandle      Handle of the file being invoked.
+  @param  PeiServices     Describes the list of possible PEI Services.
+
+  @return EFI_SUCCESS     The PEIM initialized successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePlatform (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));
+
+  //
+  // Initialize Local APIC Timer hardware and disable Local APIC Timer
+  // interrupts before initializing the Debug Agent and the debug timer is
+  // enabled.
+  //
+  InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
+  DisableApicTimerInterrupt ();
+
+  DebugDumpCmos ();
+
+  BootModeInitialization ();
+  AddressWidthInitialization ();
+  MaxCpuCountInitialization ();
+
+  //
+  // Query Host Bridge DID
+  //
+  mHostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
+
+  if (FeaturePcdGet (PcdSmmSmramRequire)) {
+    Q35TsegMbytesInitialization ();
+  }
+
+  PublishPeiMemory ();
+
+  InitializeRamRegions ();
+
+  if (mBootMode != BOOT_ON_S3_RESUME) {
+    if (!FeaturePcdGet (PcdSmmSmramRequire)) {
+      ReserveEmuVariableNvStore ();
+    }
+    PeiFvInitialization ();
+    MemMapInitialization ();
+    NoexecDxeInitialization ();
+  }
+
+  InstallClearCacheCallback ();
+  AmdSevInitialize ();
+  MiscInitialization ();
+  InstallFeatureControlCallback ();
+
+  return EFI_SUCCESS;
+}
diff --git a/BhyvePkg/PlatformPei/Platform.h b/BhyvePkg/PlatformPei/Platform.h
new file mode 100644
index 0000000000..0484ec9e6b
--- /dev/null
+++ b/BhyvePkg/PlatformPei/Platform.h
@@ -0,0 +1,136 @@
+/** @file
+  Platform PEI module include file.
+
+  Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _PLATFORM_PEI_H_INCLUDED_
+#define _PLATFORM_PEI_H_INCLUDED_
+
+#include <IndustryStandard/E820.h>
+
+VOID
+AddIoMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize
+  );
+
+VOID
+AddIoMemoryRangeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  EFI_PHYSICAL_ADDRESS        MemoryLimit
+  );
+
+VOID
+AddMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize
+  );
+
+VOID
+AddMemoryRangeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  EFI_PHYSICAL_ADDRESS        MemoryLimit
+  );
+
+VOID
+AddReservedMemoryBaseSizeHob (
+  EFI_PHYSICAL_ADDRESS        MemoryBase,
+  UINT64                      MemorySize,
+  BOOLEAN                     Cacheable
+  );
+
+VOID
+AddressWidthInitialization (
+  VOID
+  );
+
+VOID
+Q35TsegMbytesInitialization (
+  VOID
+  );
+
+VOID
+Q35SmramAtDefaultSmbaseInitialization (
+  VOID
+  );
+
+EFI_STATUS
+PublishPeiMemory (
+  VOID
+  );
+
+UINT32
+GetSystemMemorySizeBelow4gb (
+  VOID
+  );
+
+VOID
+QemuUc32BaseInitialization (
+  VOID
+  );
+
+VOID
+InitializeRamRegions (
+  VOID
+  );
+
+EFI_STATUS
+PeiFvInitialization (
+  VOID
+  );
+
+VOID
+MemTypeInfoInitialization (
+  VOID
+  );
+
+VOID
+InstallFeatureControlCallback (
+  VOID
+  );
+
+VOID
+InstallClearCacheCallback (
+  VOID
+  );
+
+EFI_STATUS
+InitializeXen (
+  VOID
+  );
+
+BOOLEAN
+XenDetect (
+  VOID
+  );
+
+VOID
+AmdSevInitialize (
+  VOID
+  );
+
+extern BOOLEAN mXen;
+
+VOID
+XenPublishRamRegions (
+  VOID
+  );
+
+extern EFI_BOOT_MODE mBootMode;
+
+extern BOOLEAN mS3Supported;
+
+extern UINT8 mPhysMemAddressWidth;
+
+extern UINT32 mMaxCpuCount;
+
+extern UINT16 mHostBridgeDevId;
+
+extern BOOLEAN mQ35SmramAtDefaultSmbase;
+
+extern UINT32 mQemuUc32Base;
+
+#endif // _PLATFORM_PEI_H_INCLUDED_
diff --git a/BhyvePkg/PlatformPei/PlatformPei.inf b/BhyvePkg/PlatformPei/PlatformPei.inf
new file mode 100644
index 0000000000..137c69a97d
--- /dev/null
+++ b/BhyvePkg/PlatformPei/PlatformPei.inf
@@ -0,0 +1,117 @@
+## @file
+#  Platform PEI driver
+#
+#  This module provides platform specific function to detect boot mode.
+#  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  This program and the accompanying materials
+#  are licensed and made available under the terms and conditions of the BSD License
+#  which accompanies this distribution. The full text of the license may be found at
+#  http://opensource.org/licenses/bsd-license.php
+#
+#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformPei
+  FILE_GUID                      = aa89d903-345b-4ab2-9abf-030b5efb5d50
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializePlatform
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  AmdSev.c
+  ClearCache.c
+  Cmos.c
+  Cmos.h
+  FeatureControl.c
+  Fv.c
+  MemDetect.c
+  Platform.c
+  Platform.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SecurityPkg/SecurityPkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[Guids]
+  gEfiMemoryTypeInformationGuid
+
+[LibraryClasses]
+  BaseLib
+  CacheMaintenanceLib
+  DebugLib
+  HobLib
+  IoLib
+  PciLib
+  ResourcePublicationLib
+  PeiServicesLib
+  PeiServicesTablePointerLib
+  PeimEntryPoint
+  MtrrLib
+  MemEncryptSevLib
+  PcdLib
+  LocalApicLib
+
+[Pcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize
+  gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd
+  gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes
+  gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+  gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
+  gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize
+
+[FixedPcd]
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+[FeaturePcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
+
+[Ppis]
+  gEfiPeiMasterBootModePpiGuid
+  gEfiPeiMpServicesPpiGuid
+
+[Depex]
+  TRUE
+
-- 
2.20.1



  parent reply	other threads:[~2020-04-21  3:10 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-21  3:09 [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor Rebecca Cran
2020-04-21  3:09 ` [PATCH v3 1/6] OvmfPkg: Add bhyve support into AcpiTimerLib Rebecca Cran
2020-04-23  7:56   ` [edk2-devel] " Laszlo Ersek
2020-04-21  3:09 ` [PATCH v3 2/6] OvmfPkg: Add QemuFwCfgLibNull Rebecca Cran
2020-04-23  8:21   ` [edk2-devel] " Laszlo Ersek
2020-04-21  3:09 ` [PATCH v3 3/6] OvmfPkg: Add VBE2 mode info structure to LegacyVgaBios.h Rebecca Cran
2020-04-23  8:05   ` [edk2-devel] " Laszlo Ersek
2020-04-21  3:09 ` [PATCH v3 4/6] Add BhyvePkg, to support the bhyve hypervisor Rebecca Cran
2020-04-23  9:19   ` [edk2-devel] " Laszlo Ersek
2020-04-23  9:42     ` Laszlo Ersek
2020-04-24  5:54       ` Rebecca Cran
2020-04-24 12:22         ` Laszlo Ersek
2020-04-23 20:08     ` Rebecca Cran
2020-04-24 10:11       ` Laszlo Ersek
2020-04-24 16:00         ` Rebecca Cran
2020-04-21  3:09 ` Rebecca Cran [this message]
2020-04-23  9:24   ` [edk2-devel] [PATCH v3 5/6] BhyvePkg: Add PlatformPei Laszlo Ersek
2020-04-21  3:09 ` [PATCH v3 6/6] BhyvePkg: Add AcpiPlatformDxe Rebecca Cran
2020-04-23  9:44   ` [edk2-devel] " Laszlo Ersek
2020-04-21 15:27 ` [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor Laszlo Ersek
2020-04-21 15:38   ` Rebecca Cran
2020-04-22 15:21     ` Laszlo Ersek
2020-04-22 16:48       ` Rebecca Cran
2020-04-24 10:11         ` Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200421030955.114850-6-rebecca@bsdio.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox