public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor
@ 2020-04-21  3:09 Rebecca Cran
  2020-04-21  3:09 ` [PATCH v3 1/6] OvmfPkg: Add bhyve support into AcpiTimerLib Rebecca Cran
                   ` (6 more replies)
  0 siblings, 7 replies; 24+ messages in thread
From: Rebecca Cran @ 2020-04-21  3:09 UTC (permalink / raw)
  To: devel
  Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel, Leif Lindholm,
	Michael Kinney, Andrew Fish, Peter Grehan, Rebecca Cran

I noticed a few things wrong with the v2 series:

o BhyveFwCtlLibNull is no longer used, and could be deleted.
o Some changes from the v1 AcpiPlatformDxe patch were left in OvmfPkg.
o BhyvePkg/License.txt still referred to OvmfPkg. I've updated it so
  everything under BhyvePkg should be BSD-2-Clause.

This patch series can also be found at
https://git.bsdio.com/bcran/edk2-bhyve/commits/branch/master

Signed-off-by: Rebecca Cran <rebecca@bsdio.com>

Rebecca Cran (6):
  OvmfPkg: Add bhyve support into AcpiTimerLib
  OvmfPkg: Add QemuFwCfgLibNull
  OvmfPkg: Add VBE2 mode info structure to LegacyVgaBios.h
  Add BhyvePkg, to support the bhyve hypervisor
  BhyvePkg: Add PlatformPei
  BhyvePkg: Add AcpiPlatformDxe

 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c       |  250 +++
 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h       |   76 +
 BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf  |   64 +
 BhyvePkg/AcpiPlatformDxe/Bhyve.c              |  138 ++
 BhyvePkg/AcpiPlatformDxe/EntryPoint.c         |   90 +
 BhyvePkg/AcpiPlatformDxe/PciDecoding.c        |  192 ++
 BhyvePkg/AcpiTables/AcpiTables.inf            |   42 +
 BhyvePkg/AcpiTables/Dsdt.asl                  | 1134 +++++++++++
 BhyvePkg/AcpiTables/Facp.aslc                 |   75 +
 BhyvePkg/AcpiTables/Facs.aslc                 |   79 +
 BhyvePkg/AcpiTables/Hpet.aslc                 |   71 +
 BhyvePkg/AcpiTables/Madt.aslc                 |  144 ++
 BhyvePkg/AcpiTables/Mcfg.aslc                 |   56 +
 BhyvePkg/AcpiTables/Platform.h                |   71 +
 BhyvePkg/AcpiTables/Spcr.aslc                 |   62 +
 BhyvePkg/AcpiTables/Ssdt.asl                  |   14 +
 BhyvePkg/BhyvePkg.dec                         |  170 ++
 BhyvePkg/BhyvePkg.fdf.inc                     |   85 +
 BhyvePkg/BhyvePkgX64.dsc                      |  846 +++++++++
 BhyvePkg/BhyvePkgX64.fdf                      |  513 +++++
 BhyvePkg/BhyveRfbDxe/BhyveRfbDxe.inf          |   67 +
 BhyvePkg/BhyveRfbDxe/ComponentName.c          |  200 ++
 BhyvePkg/BhyveRfbDxe/Gop.h                    |  148 ++
 BhyvePkg/BhyveRfbDxe/GopDriver.c              |  542 ++++++
 BhyvePkg/BhyveRfbDxe/GopScreen.c              |  392 ++++
 BhyvePkg/BhyveRfbDxe/VbeShim.asm              |  341 ++++
 BhyvePkg/BhyveRfbDxe/VbeShim.c                |  258 +++
 BhyvePkg/BhyveRfbDxe/VbeShim.h                |  912 +++++++++
 BhyvePkg/BhyveRfbDxe/VbeShim.sh               |   79 +
 BhyvePkg/DecomprScratchEnd.fdf.inc            |   66 +
 BhyvePkg/Include/Library/BhyveFwCtlLib.h      |   46 +
 .../Library/BhyveFwCtlLib/BhyveFwCtlLib.c     |  425 +++++
 .../Library/BhyveFwCtlLib/BhyveFwCtlLib.inf   |   40 +
 .../PlatformBootManagerLib/BdsPlatform.c      | 1660 +++++++++++++++++
 .../PlatformBootManagerLib/BdsPlatform.h      |  191 ++
 .../PlatformBootManagerLib.inf                |   74 +
 .../PlatformBootManagerLib/PlatformData.c     |  171 ++
 BhyvePkg/License.txt                          |   44 +
 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 ++
 BhyvePkg/SmbiosPlatformDxe/Bhyve.c            |   42 +
 .../SmbiosPlatformDxe/SmbiosPlatformDxe.c     |  244 +++
 .../SmbiosPlatformDxe/SmbiosPlatformDxe.h     |   63 +
 .../SmbiosPlatformDxe/SmbiosPlatformDxe.inf   |   54 +
 BhyvePkg/VarStore.fdf.inc                     |  115 ++
 Maintainers.txt                               |    7 +
 OvmfPkg/Include/IndustryStandard/Bhyve.h      |   16 +
 .../Include/IndustryStandard/LegacyVgaBios.h  |   38 +
 OvmfPkg/Include/OvmfPlatforms.h               |    1 +
 .../AcpiTimerLib/BaseAcpiTimerLibBhyve.c      |   32 +
 .../AcpiTimerLib/BaseAcpiTimerLibBhyve.inf    |   30 +
 .../Library/QemuFwCfgLib/QemuFwCfgLibNull.inf |   37 +
 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c  |  209 +++
 61 files changed, 12651 insertions(+)
 create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c
 create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h
 create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
 create mode 100644 BhyvePkg/AcpiPlatformDxe/Bhyve.c
 create mode 100644 BhyvePkg/AcpiPlatformDxe/EntryPoint.c
 create mode 100644 BhyvePkg/AcpiPlatformDxe/PciDecoding.c
 create mode 100644 BhyvePkg/AcpiTables/AcpiTables.inf
 create mode 100644 BhyvePkg/AcpiTables/Dsdt.asl
 create mode 100644 BhyvePkg/AcpiTables/Facp.aslc
 create mode 100644 BhyvePkg/AcpiTables/Facs.aslc
 create mode 100644 BhyvePkg/AcpiTables/Hpet.aslc
 create mode 100644 BhyvePkg/AcpiTables/Madt.aslc
 create mode 100644 BhyvePkg/AcpiTables/Mcfg.aslc
 create mode 100644 BhyvePkg/AcpiTables/Platform.h
 create mode 100644 BhyvePkg/AcpiTables/Spcr.aslc
 create mode 100644 BhyvePkg/AcpiTables/Ssdt.asl
 create mode 100644 BhyvePkg/BhyvePkg.dec
 create mode 100644 BhyvePkg/BhyvePkg.fdf.inc
 create mode 100644 BhyvePkg/BhyvePkgX64.dsc
 create mode 100644 BhyvePkg/BhyvePkgX64.fdf
 create mode 100644 BhyvePkg/BhyveRfbDxe/BhyveRfbDxe.inf
 create mode 100644 BhyvePkg/BhyveRfbDxe/ComponentName.c
 create mode 100644 BhyvePkg/BhyveRfbDxe/Gop.h
 create mode 100644 BhyvePkg/BhyveRfbDxe/GopDriver.c
 create mode 100644 BhyvePkg/BhyveRfbDxe/GopScreen.c
 create mode 100644 BhyvePkg/BhyveRfbDxe/VbeShim.asm
 create mode 100644 BhyvePkg/BhyveRfbDxe/VbeShim.c
 create mode 100644 BhyvePkg/BhyveRfbDxe/VbeShim.h
 create mode 100644 BhyvePkg/BhyveRfbDxe/VbeShim.sh
 create mode 100644 BhyvePkg/DecomprScratchEnd.fdf.inc
 create mode 100644 BhyvePkg/Include/Library/BhyveFwCtlLib.h
 create mode 100644 BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c
 create mode 100644 BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
 create mode 100644 BhyvePkg/Library/PlatformBootManagerLib/BdsPlatform.c
 create mode 100644 BhyvePkg/Library/PlatformBootManagerLib/BdsPlatform.h
 create mode 100644 BhyvePkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
 create mode 100644 BhyvePkg/Library/PlatformBootManagerLib/PlatformData.c
 create mode 100644 BhyvePkg/License.txt
 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
 create mode 100644 BhyvePkg/SmbiosPlatformDxe/Bhyve.c
 create mode 100644 BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
 create mode 100644 BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
 create mode 100644 BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
 create mode 100644 BhyvePkg/VarStore.fdf.inc
 create mode 100644 OvmfPkg/Include/IndustryStandard/Bhyve.h
 create mode 100644 OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.c
 create mode 100644 OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf
 create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf
 create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c

-- 
2.20.1



^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH v3 1/6] OvmfPkg: Add bhyve support into AcpiTimerLib
  2020-04-21  3:09 [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor Rebecca Cran
@ 2020-04-21  3:09 ` 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
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 24+ messages in thread
From: Rebecca Cran @ 2020-04-21  3:09 UTC (permalink / raw)
  To: devel
  Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel, Leif Lindholm,
	Michael Kinney, Andrew Fish, Peter Grehan, Rebecca Cran

On bhyve, the ACPI timer is located at a fixed IO address; it need
not be programmed into, nor fetched from, the PMBA -- power
management base address -- register of the PCI host bridge.

Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/Include/IndustryStandard/Bhyve.h      | 16 ++++++++++
 OvmfPkg/Include/OvmfPlatforms.h               |  1 +
 .../AcpiTimerLib/BaseAcpiTimerLibBhyve.c      | 32 +++++++++++++++++++
 .../AcpiTimerLib/BaseAcpiTimerLibBhyve.inf    | 30 +++++++++++++++++
 4 files changed, 79 insertions(+)
 create mode 100644 OvmfPkg/Include/IndustryStandard/Bhyve.h
 create mode 100644 OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.c
 create mode 100644 OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf

diff --git a/OvmfPkg/Include/IndustryStandard/Bhyve.h b/OvmfPkg/Include/IndustryStandard/Bhyve.h
new file mode 100644
index 0000000000..02ce5587ee
--- /dev/null
+++ b/OvmfPkg/Include/IndustryStandard/Bhyve.h
@@ -0,0 +1,16 @@
+/** @file
+  Various register numbers and value bits based on FreeBSD's bhyve
+  at r359530.
+  - https://svnweb.freebsd.org/base?view=revision&revision=359530
+
+  Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __BHYVE_H__
+#define __BHYVE_H__
+
+#define BHYVE_ACPI_TIMER_IO_ADDR 0x408
+
+#endif // __BHYVE_H__
diff --git a/OvmfPkg/Include/OvmfPlatforms.h b/OvmfPkg/Include/OvmfPlatforms.h
index 59459231e8..77dd818e30 100644
--- a/OvmfPkg/Include/OvmfPlatforms.h
+++ b/OvmfPkg/Include/OvmfPlatforms.h
@@ -14,6 +14,7 @@
 #include <IndustryStandard/Pci22.h>
 #include <IndustryStandard/Q35MchIch9.h>
 #include <IndustryStandard/I440FxPiix4.h>
+#include <IndustryStandard/Bhyve.h>
 
 //
 // OVMF Host Bridge DID Address
diff --git a/OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.c b/OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.c
new file mode 100644
index 0000000000..f927e27188
--- /dev/null
+++ b/OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.c
@@ -0,0 +1,32 @@
+/** @file
+  Provide InternalAcpiGetTimerTick for the bhyve instance of the
+  Base ACPI Timer Library
+
+  Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+  Copyright (C) 2014, Gabriel L. Somlo <somlo@cmu.edu>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/IoLib.h>
+#include <OvmfPlatforms.h>
+
+/**
+  Internal function to read the current tick counter of ACPI.
+
+  Read the current ACPI tick counter using the counter address cached
+  by this instance's constructor.
+
+  @return The tick counter read.
+
+**/
+UINT32
+InternalAcpiGetTimerTick (
+  VOID
+  )
+{
+  //
+  // Return the current ACPI timer value.
+  //
+  return IoRead32 (BHYVE_ACPI_TIMER_IO_ADDR);
+}
diff --git a/OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf b/OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf
new file mode 100644
index 0000000000..14b7479e67
--- /dev/null
+++ b/OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf
@@ -0,0 +1,30 @@
+## @file
+#  Base ACPI Timer Library Instance for Bhyve.
+#
+#  Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+#  Copyright (C) 2014, Gabriel L. Somlo <somlo@cmu.edu>
+#  Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION    = 0x00010005
+  BASE_NAME      = BaseAcpiTimerLibBhyve
+  FILE_GUID      = A5E3B247-7302-11EA-9C04-3CECEF0C1C08
+  MODULE_TYPE    = BASE
+  VERSION_STRING = 1.0
+  LIBRARY_CLASS  = TimerLib
+
+[Sources]
+  AcpiTimerLib.c
+  AcpiTimerLib.h
+  BaseAcpiTimerLibBhyve.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+  IoLib
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 2/6] OvmfPkg: Add QemuFwCfgLibNull
  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-21  3:09 ` 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
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 24+ messages in thread
From: Rebecca Cran @ 2020-04-21  3:09 UTC (permalink / raw)
  To: devel
  Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel, Leif Lindholm,
	Michael Kinney, Andrew Fish, Peter Grehan, Rebecca Cran

Add a null implementation library for QemuFwCfgLib, in order to
support building PciHostBridgeLib for bhyve.

Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
---
 .../Library/QemuFwCfgLib/QemuFwCfgLibNull.inf |  37 ++++
 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c  | 209 ++++++++++++++++++
 2 files changed, 246 insertions(+)
 create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf
 create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c

diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf
new file mode 100644
index 0000000000..09f86c2b02
--- /dev/null
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf
@@ -0,0 +1,37 @@
+## @file
+#
+#  Stateful, implicitly initialized fw_cfg library.
+#
+#  Copyright (C) 2013, Red Hat, Inc.
+#  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = QemuFwCfgLibNull
+  FILE_GUID                      = B9D1A1F2-01E2-4732-982D-C7F9ED51AC6B
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = QemuFwCfgLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  QemuFwCfgLibInternal.h
+  QemuFwCfgNull.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+  DebugLib
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c
new file mode 100644
index 0000000000..e2cc5f3406
--- /dev/null
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c
@@ -0,0 +1,209 @@
+/** @file
+
+  Stateful and implicitly initialized fw_cfg library implementation.
+
+  Copyright (C) 2013, Red Hat, Inc.
+  Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/QemuFwCfg.h>
+
+/**
+  Returns a boolean indicating if the firmware configuration interface
+  is available or not.
+
+  This function may change fw_cfg state.
+
+  @retval    TRUE   The interface is available
+  @retval    FALSE  The interface is not available
+
+**/
+BOOLEAN
+EFIAPI
+QemuFwCfgIsAvailable (
+  VOID
+  )
+{
+  return FALSE;
+}
+
+
+/**
+  Selects a firmware configuration item for reading.
+
+  Following this call, any data read from this item will start from
+  the beginning of the configuration item's data.
+
+  @param[in] QemuFwCfgItem - Firmware Configuration item to read
+
+**/
+VOID
+EFIAPI
+QemuFwCfgSelectItem (
+  IN FIRMWARE_CONFIG_ITEM   QemuFwCfgItem
+  )
+{
+  ASSERT (FALSE);
+}
+
+
+/**
+  Reads firmware configuration bytes into a buffer
+
+  If called multiple times, then the data read will
+  continue at the offset of the firmware configuration
+  item where the previous read ended.
+
+  @param[in] Size - Size in bytes to read
+  @param[in] Buffer - Buffer to store data into
+
+**/
+VOID
+EFIAPI
+QemuFwCfgReadBytes (
+  IN UINTN                  Size,
+  IN VOID                   *Buffer  OPTIONAL
+  )
+{
+  ASSERT (FALSE);
+}
+
+
+/**
+  Writes firmware configuration bytes from a buffer
+
+  If called multiple times, then the data written will
+  continue at the offset of the firmware configuration
+  item where the previous write ended.
+
+  @param[in] Size - Size in bytes to write
+  @param[in] Buffer - Buffer to read data from
+
+**/
+VOID
+EFIAPI
+QemuFwCfgWriteBytes (
+  IN UINTN                  Size,
+  IN VOID                   *Buffer
+  )
+{
+  ASSERT (FALSE);
+}
+
+
+/**
+  Skip bytes in the firmware configuration item.
+
+  Increase the offset of the firmware configuration item without transferring
+  bytes between the item and a caller-provided buffer. Subsequent read, write
+  or skip operations will commence at the increased offset.
+
+  @param[in] Size  Number of bytes to skip.
+**/
+VOID
+EFIAPI
+QemuFwCfgSkipBytes (
+  IN UINTN                  Size
+  )
+{
+  ASSERT (FALSE);
+}
+
+
+/**
+  Reads a UINT8 firmware configuration value
+
+  @return    Value of Firmware Configuration item read
+
+**/
+UINT8
+EFIAPI
+QemuFwCfgRead8 (
+  VOID
+  )
+{
+  ASSERT (FALSE);
+  return 0;
+}
+
+
+/**
+  Reads a UINT16 firmware configuration value
+
+  @return    Value of Firmware Configuration item read
+
+**/
+UINT16
+EFIAPI
+QemuFwCfgRead16 (
+  VOID
+  )
+{
+  ASSERT (FALSE);
+  return 0;
+}
+
+
+/**
+  Reads a UINT32 firmware configuration value
+
+  @return    Value of Firmware Configuration item read
+
+**/
+UINT32
+EFIAPI
+QemuFwCfgRead32 (
+  VOID
+  )
+{
+  ASSERT (FALSE);
+  return 0;
+}
+
+
+/**
+  Reads a UINT64 firmware configuration value
+
+  @return    Value of Firmware Configuration item read
+
+**/
+UINT64
+EFIAPI
+QemuFwCfgRead64 (
+  VOID
+  )
+{
+  ASSERT (FALSE);
+  return 0;
+}
+
+
+/**
+  Find the configuration item corresponding to the firmware configuration file.
+
+  @param[in]  Name - Name of file to look up.
+  @param[out] Item - Configuration item corresponding to the file, to be passed
+                     to QemuFwCfgSelectItem ().
+  @param[out] Size - Number of bytes in the file.
+
+  @return    RETURN_SUCCESS       If file is found.
+             RETURN_NOT_FOUND     If file is not found.
+             RETURN_UNSUPPORTED   If firmware configuration is unavailable.
+
+**/
+RETURN_STATUS
+EFIAPI
+QemuFwCfgFindFile (
+  IN   CONST CHAR8           *Name,
+  OUT  FIRMWARE_CONFIG_ITEM  *Item,
+  OUT  UINTN                 *Size
+  )
+{
+  return RETURN_UNSUPPORTED;
+}
+
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 3/6] OvmfPkg: Add VBE2 mode info structure to LegacyVgaBios.h
  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-21  3:09 ` [PATCH v3 2/6] OvmfPkg: Add QemuFwCfgLibNull Rebecca Cran
@ 2020-04-21  3:09 ` 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
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 24+ messages in thread
From: Rebecca Cran @ 2020-04-21  3:09 UTC (permalink / raw)
  To: devel
  Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel, Leif Lindholm,
	Michael Kinney, Andrew Fish, Peter Grehan, Rebecca Cran

bhyve uses the older VESA BIOS Extensions 2.0, so add the mode info
structure to IndustryStandard/LegacyVgaBios.h

Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
---
 .../Include/IndustryStandard/LegacyVgaBios.h  | 38 +++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/OvmfPkg/Include/IndustryStandard/LegacyVgaBios.h b/OvmfPkg/Include/IndustryStandard/LegacyVgaBios.h
index 317dac3a56..38360a68b2 100644
--- a/OvmfPkg/Include/IndustryStandard/LegacyVgaBios.h
+++ b/OvmfPkg/Include/IndustryStandard/LegacyVgaBios.h
@@ -86,6 +86,44 @@ typedef struct {
   UINT32 MaxPixelClockHz;
   UINT8  Reserved[190];
 } VBE_MODE_INFO;
+
+typedef struct {
+  UINT16 ModeAttr;
+  UINT8  WindowAAttr;
+  UINT8  WindowBAttr;
+  UINT16 WindowGranularityKB;
+  UINT16 WindowSizeKB;
+  UINT16 WindowAStartSegment;
+  UINT16 WindowBStartSegment;
+  UINT32 WindowPositioningAddress;
+  UINT16 BytesPerScanLine;
+
+  UINT16 Width;
+  UINT16 Height;
+  UINT8  CharCellWidth;
+  UINT8  CharCellHeight;
+  UINT8  NumPlanes;
+  UINT8  BitsPerPixel;
+  UINT8  NumBanks;
+  UINT8  MemoryModel;
+  UINT8  BankSizeKB;
+  UINT8  NumImagePagesLessOne;
+  UINT8  Vbe3;
+
+  UINT8  RedMaskSize;
+  UINT8  RedMaskPos;
+  UINT8  GreenMaskSize;
+  UINT8  GreenMaskPos;
+  UINT8  BlueMaskSize;
+  UINT8  BlueMaskPos;
+  UINT8  ReservedMaskSize;
+  UINT8  ReservedMaskPos;
+  UINT8  DirectColorModeInfo;
+
+  UINT32 LfbAddress;
+  UINT32 OffScreenAddress;
+  UINT16 OffScreenSizeKB;
+} VBE2_MODE_INFO;
 #pragma pack ()
 
 #endif
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 4/6] Add BhyvePkg, to support the bhyve hypervisor
  2020-04-21  3:09 [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor Rebecca Cran
                   ` (2 preceding siblings ...)
  2020-04-21  3:09 ` [PATCH v3 3/6] OvmfPkg: Add VBE2 mode info structure to LegacyVgaBios.h Rebecca Cran
@ 2020-04-21  3:09 ` Rebecca Cran
  2020-04-23  9:19   ` [edk2-devel] " Laszlo Ersek
  2020-04-21  3:09 ` [PATCH v3 5/6] BhyvePkg: Add PlatformPei Rebecca Cran
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 24+ messages in thread
From: Rebecca Cran @ 2020-04-21  3:09 UTC (permalink / raw)
  To: devel
  Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel, Leif Lindholm,
	Michael Kinney, Andrew Fish, Peter Grehan, Rebecca Cran

BhyvePkg supports the bhyve hypervisor, which is a hypervisor/virtual
machine manager available on FreeBSD, macOS and Illumos.

Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
---
 BhyvePkg/AcpiTables/AcpiTables.inf            |   42 +
 BhyvePkg/AcpiTables/Dsdt.asl                  | 1134 +++++++++++
 BhyvePkg/AcpiTables/Facp.aslc                 |   75 +
 BhyvePkg/AcpiTables/Facs.aslc                 |   79 +
 BhyvePkg/AcpiTables/Hpet.aslc                 |   71 +
 BhyvePkg/AcpiTables/Madt.aslc                 |  144 ++
 BhyvePkg/AcpiTables/Mcfg.aslc                 |   56 +
 BhyvePkg/AcpiTables/Platform.h                |   71 +
 BhyvePkg/AcpiTables/Spcr.aslc                 |   62 +
 BhyvePkg/AcpiTables/Ssdt.asl                  |   14 +
 BhyvePkg/BhyvePkg.dec                         |  170 ++
 BhyvePkg/BhyvePkg.fdf.inc                     |   85 +
 BhyvePkg/BhyvePkgX64.dsc                      |  846 +++++++++
 BhyvePkg/BhyvePkgX64.fdf                      |  513 +++++
 BhyvePkg/BhyveRfbDxe/BhyveRfbDxe.inf          |   67 +
 BhyvePkg/BhyveRfbDxe/ComponentName.c          |  200 ++
 BhyvePkg/BhyveRfbDxe/Gop.h                    |  148 ++
 BhyvePkg/BhyveRfbDxe/GopDriver.c              |  542 ++++++
 BhyvePkg/BhyveRfbDxe/GopScreen.c              |  392 ++++
 BhyvePkg/BhyveRfbDxe/VbeShim.asm              |  341 ++++
 BhyvePkg/BhyveRfbDxe/VbeShim.c                |  258 +++
 BhyvePkg/BhyveRfbDxe/VbeShim.h                |  912 +++++++++
 BhyvePkg/BhyveRfbDxe/VbeShim.sh               |   79 +
 BhyvePkg/DecomprScratchEnd.fdf.inc            |   66 +
 BhyvePkg/Include/Library/BhyveFwCtlLib.h      |   46 +
 .../Library/BhyveFwCtlLib/BhyveFwCtlLib.c     |  425 +++++
 .../Library/BhyveFwCtlLib/BhyveFwCtlLib.inf   |   40 +
 .../PlatformBootManagerLib/BdsPlatform.c      | 1660 +++++++++++++++++
 .../PlatformBootManagerLib/BdsPlatform.h      |  191 ++
 .../PlatformBootManagerLib.inf                |   74 +
 .../PlatformBootManagerLib/PlatformData.c     |  171 ++
 BhyvePkg/License.txt                          |   44 +
 BhyvePkg/SmbiosPlatformDxe/Bhyve.c            |   42 +
 .../SmbiosPlatformDxe/SmbiosPlatformDxe.c     |  244 +++
 .../SmbiosPlatformDxe/SmbiosPlatformDxe.h     |   63 +
 .../SmbiosPlatformDxe/SmbiosPlatformDxe.inf   |   54 +
 BhyvePkg/VarStore.fdf.inc                     |  115 ++
 Maintainers.txt                               |    7 +
 38 files changed, 9543 insertions(+)
 create mode 100644 BhyvePkg/AcpiTables/AcpiTables.inf
 create mode 100644 BhyvePkg/AcpiTables/Dsdt.asl
 create mode 100644 BhyvePkg/AcpiTables/Facp.aslc
 create mode 100644 BhyvePkg/AcpiTables/Facs.aslc
 create mode 100644 BhyvePkg/AcpiTables/Hpet.aslc
 create mode 100644 BhyvePkg/AcpiTables/Madt.aslc
 create mode 100644 BhyvePkg/AcpiTables/Mcfg.aslc
 create mode 100644 BhyvePkg/AcpiTables/Platform.h
 create mode 100644 BhyvePkg/AcpiTables/Spcr.aslc
 create mode 100644 BhyvePkg/AcpiTables/Ssdt.asl
 create mode 100644 BhyvePkg/BhyvePkg.dec
 create mode 100644 BhyvePkg/BhyvePkg.fdf.inc
 create mode 100644 BhyvePkg/BhyvePkgX64.dsc
 create mode 100644 BhyvePkg/BhyvePkgX64.fdf
 create mode 100644 BhyvePkg/BhyveRfbDxe/BhyveRfbDxe.inf
 create mode 100644 BhyvePkg/BhyveRfbDxe/ComponentName.c
 create mode 100644 BhyvePkg/BhyveRfbDxe/Gop.h
 create mode 100644 BhyvePkg/BhyveRfbDxe/GopDriver.c
 create mode 100644 BhyvePkg/BhyveRfbDxe/GopScreen.c
 create mode 100644 BhyvePkg/BhyveRfbDxe/VbeShim.asm
 create mode 100644 BhyvePkg/BhyveRfbDxe/VbeShim.c
 create mode 100644 BhyvePkg/BhyveRfbDxe/VbeShim.h
 create mode 100644 BhyvePkg/BhyveRfbDxe/VbeShim.sh
 create mode 100644 BhyvePkg/DecomprScratchEnd.fdf.inc
 create mode 100644 BhyvePkg/Include/Library/BhyveFwCtlLib.h
 create mode 100644 BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c
 create mode 100644 BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
 create mode 100644 BhyvePkg/Library/PlatformBootManagerLib/BdsPlatform.c
 create mode 100644 BhyvePkg/Library/PlatformBootManagerLib/BdsPlatform.h
 create mode 100644 BhyvePkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
 create mode 100644 BhyvePkg/Library/PlatformBootManagerLib/PlatformData.c
 create mode 100644 BhyvePkg/License.txt
 create mode 100644 BhyvePkg/SmbiosPlatformDxe/Bhyve.c
 create mode 100644 BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
 create mode 100644 BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
 create mode 100644 BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
 create mode 100644 BhyvePkg/VarStore.fdf.inc

diff --git a/BhyvePkg/AcpiTables/AcpiTables.inf b/BhyvePkg/AcpiTables/AcpiTables.inf
new file mode 100644
index 0000000000..d8907e6b56
--- /dev/null
+++ b/BhyvePkg/AcpiTables/AcpiTables.inf
@@ -0,0 +1,42 @@
+## @file
+#  Component description file for PlatformAcpiTables module.
+#
+#  ACPI table data and ASL sources required to boot the platform.
+#
+#  Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2014, Pluribus Networks, Inc.^M
+#
+#  SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformAcpiTables
+  FILE_GUID                      = 7E374E25-8E01-4FEE-87F2-390C23C606CD
+  MODULE_TYPE                    = USER_DEFINED
+  VERSION_STRING                 = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  Platform.h
+  Madt.aslc
+  Facp.aslc
+  Facs.aslc
+  Dsdt.asl
+  Hpet.aslc
+  Spcr.aslc
+  Mcfg.aslc
+
+[Packages]
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[Pcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdDebugIoPort
+
diff --git a/BhyvePkg/AcpiTables/Dsdt.asl b/BhyvePkg/AcpiTables/Dsdt.asl
new file mode 100644
index 0000000000..a60d001ffd
--- /dev/null
+++ b/BhyvePkg/AcpiTables/Dsdt.asl
@@ -0,0 +1,1134 @@
+/*
+ * Intel ACPI Component Architecture
+ * AML Disassembler version 20100528
+ *
+ * Disassembly of DSDT.dat, Sat Apr 18 15:41:05 2015
+ *
+ *
+ * Original Table Header:
+ *     Signature        "DSDT"
+ *     Length           0x000008FA (2298)
+ *     Revision         0x02
+ *     Checksum         0xC4
+ *     OEM ID           "BHYVE "
+ *     OEM Table ID     "BVDSDT  "
+ *     OEM Revision     0x00000001 (1)
+ *     Compiler ID      "INTL"
+ *     Compiler Version 0x20150204 (538247684)
+ */
+DefinitionBlock ("DSDT.aml", "DSDT", 2, "BHYVE", "BVDSDT", 0x00000001)
+{
+    Name (_S5, Package (0x02)
+    {
+        0x05,
+        Zero
+    })
+    Name (PICM, Zero)
+    Method (_PIC, 1, NotSerialized)
+    {
+        Store (Arg0, PICM)
+    }
+
+    Scope (_SB)
+    {
+        Device (PC00)
+        {
+            Name (_HID, EisaId ("PNP0A03"))
+            Name (_ADR, Zero)
+            Method (_BBN, 0, NotSerialized)
+            {
+                Return (Zero)
+            }
+
+            Name (_CRS, ResourceTemplate ()
+            {
+                WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+                    0x0000,             // Granularity
+                    0x0000,             // Range Minimum
+                    0x00FF,             // Range Maximum
+                    0x0000,             // Translation Offset
+                    0x0100,             // Length
+                    ,, )
+                IO (Decode16,
+                    0x03C0,             // Range Minimum
+                    0x03C0,             // Range Maximum
+                    0x00,               // Alignment
+                    0x20,               // Length
+                    )
+                IO (Decode16,
+                    0x0CF8,             // Range Minimum
+                    0x0CF8,             // Range Maximum
+                    0x01,               // Alignment
+                    0x08,               // Length
+                    )
+                WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+                    0x0000,             // Granularity
+                    0x0000,             // Range Minimum
+                    0x0CF7,             // Range Maximum
+                    0x0000,             // Translation Offset
+                    0x0CF8,             // Length
+                    ,, , TypeStatic)
+                WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+                    0x0000,             // Granularity
+                    0x0D00,             // Range Minimum
+                    0xFFFF,             // Range Maximum
+                    0x0000,             // Translation Offset
+                    0xF300,             // Length
+                    ,, , TypeStatic)
+                DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+                    0x00000000,         // Granularity
+                    0x000A0000,         // Range Minimum
+                    0x000BFFFF,         // Range Maximum
+                    0x00000000,         // Translation Offset
+                    0x00020000,         // Length
+                    ,, , AddressRangeMemory, TypeStatic)
+                DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+                    0x00000000,         // Granularity
+                    0xC0000000,         // Range Minimum
+                    0xDFFFFFFF,         // Range Maximum
+                    0x00000000,         // Translation Offset
+                    0x20000000,         // Range Length
+                    ,, PW32)
+                DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+                    0x00000000,         // Granularity
+                    0xF0000000,         // Range Minimum
+                    0xF07FFFFF,         // Range Maximum
+                    0x00000000,         // Translation Offset
+                    0x00800000,         // Range Length
+                    ,, FB32)
+                QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+                    0x0000000000000000, // Granularity
+                    0x000000D000000000, // Range Minimum
+                    0x000000D0000FFFFF, // Range Maximum
+                    0x0000000000000000, // Translation Offset
+                    0x0000000000100000, // Length
+                    ,, , AddressRangeMemory, TypeStatic)
+            })
+            Name (PPRT, Package ()
+            {
+                Package () { 0x0000FFFF, 0, LPC.LNKF, Zero },
+                Package () { 0x0000FFFF, 1, LPC.LNKG, Zero },
+                Package () { 0x0000FFFF, 2, LPC.LNKH, Zero },
+                Package () { 0x0000FFFF, 3, LPC.LNKA, Zero },
+
+                Package () { 0x0001FFFF, 0, LPC.LNKG, Zero },
+                Package () { 0x0001FFFF, 1, LPC.LNKH, Zero },
+                Package () { 0x0001FFFF, 2, LPC.LNKA, Zero },
+                Package () { 0x0001FFFF, 3, LPC.LNKB, Zero },
+
+                Package () { 0x0002FFFF, 0, LPC.LNKH, Zero },
+                Package () { 0x0002FFFF, 1, LPC.LNKA, Zero },
+                Package () { 0x0002FFFF, 2, LPC.LNKB, Zero },
+                Package () { 0x0002FFFF, 3, LPC.LNKC, Zero },
+
+                Package () { 0x0003FFFF, 0, LPC.LNKA, Zero },
+                Package () { 0x0003FFFF, 1, LPC.LNKB, Zero },
+                Package () { 0x0003FFFF, 2, LPC.LNKC, Zero },
+                Package () { 0x0003FFFF, 3, LPC.LNKD, Zero },
+
+                Package () { 0x0004FFFF, 0, LPC.LNKB, Zero },
+                Package () { 0x0004FFFF, 1, LPC.LNKC, Zero },
+                Package () { 0x0004FFFF, 2, LPC.LNKD, Zero },
+                Package () { 0x0004FFFF, 3, LPC.LNKE, Zero },
+
+                Package () { 0x0005FFFF, 0, LPC.LNKC, Zero },
+                Package () { 0x0005FFFF, 1, LPC.LNKD, Zero },
+                Package () { 0x0005FFFF, 2, LPC.LNKE, Zero },
+                Package () { 0x0005FFFF, 3, LPC.LNKF, Zero },
+
+                Package () { 0x0006FFFF, 0, LPC.LNKD, Zero },
+                Package () { 0x0006FFFF, 1, LPC.LNKE, Zero },
+                Package () { 0x0006FFFF, 2, LPC.LNKF, Zero },
+                Package () { 0x0006FFFF, 3, LPC.LNKG, Zero },
+
+                Package () { 0x0007FFFF, 0, LPC.LNKE, Zero },
+                Package () { 0x0007FFFF, 1, LPC.LNKF, Zero },
+                Package () { 0x0007FFFF, 2, LPC.LNKG, Zero },
+                Package () { 0x0007FFFF, 3, LPC.LNKH, Zero },
+
+                Package () { 0x0008FFFF, 0, LPC.LNKF, Zero },
+                Package () { 0x0008FFFF, 1, LPC.LNKG, Zero },
+                Package () { 0x0008FFFF, 2, LPC.LNKH, Zero },
+                Package () { 0x0008FFFF, 3, LPC.LNKA, Zero },
+
+                Package () { 0x0009FFFF, 0, LPC.LNKG, Zero },
+                Package () { 0x0009FFFF, 1, LPC.LNKH, Zero },
+                Package () { 0x0009FFFF, 2, LPC.LNKA, Zero },
+                Package () { 0x0009FFFF, 3, LPC.LNKB, Zero },
+
+                Package () { 0x000AFFFF, 0, LPC.LNKH, Zero },
+                Package () { 0x000AFFFF, 1, LPC.LNKA, Zero },
+                Package () { 0x000AFFFF, 2, LPC.LNKB, Zero },
+                Package () { 0x000AFFFF, 3, LPC.LNKC, Zero },
+
+                Package () { 0x000BFFFF, 0, LPC.LNKA, Zero },
+                Package () { 0x000BFFFF, 1, LPC.LNKB, Zero },
+                Package () { 0x000BFFFF, 2, LPC.LNKC, Zero },
+                Package () { 0x000BFFFF, 3, LPC.LNKD, Zero },
+
+                Package () { 0x000CFFFF, 0, LPC.LNKB, Zero },
+                Package () { 0x000CFFFF, 1, LPC.LNKC, Zero },
+                Package () { 0x000CFFFF, 2, LPC.LNKD, Zero },
+                Package () { 0x000CFFFF, 3, LPC.LNKE, Zero },
+
+                Package () { 0x000DFFFF, 0, LPC.LNKC, Zero },
+                Package () { 0x000DFFFF, 1, LPC.LNKD, Zero },
+                Package () { 0x000DFFFF, 2, LPC.LNKE, Zero },
+                Package () { 0x000DFFFF, 3, LPC.LNKF, Zero },
+
+                Package () { 0x000EFFFF, 0, LPC.LNKD, Zero },
+                Package () { 0x000EFFFF, 1, LPC.LNKE, Zero },
+                Package () { 0x000EFFFF, 2, LPC.LNKF, Zero },
+                Package () { 0x000EFFFF, 3, LPC.LNKG, Zero },
+
+                Package () { 0x000FFFFF, 0, LPC.LNKE, Zero },
+                Package () { 0x000FFFFF, 1, LPC.LNKF, Zero },
+                Package () { 0x000FFFFF, 2, LPC.LNKG, Zero },
+                Package () { 0x000FFFFF, 3, LPC.LNKH, Zero },
+
+                Package () { 0x0010FFFF, 0, LPC.LNKF, Zero },
+                Package () { 0x0010FFFF, 1, LPC.LNKG, Zero },
+                Package () { 0x0010FFFF, 2, LPC.LNKH, Zero },
+                Package () { 0x0010FFFF, 3, LPC.LNKA, Zero },
+
+                Package () { 0x0011FFFF, 0, LPC.LNKG, Zero },
+                Package () { 0x0011FFFF, 1, LPC.LNKH, Zero },
+                Package () { 0x0011FFFF, 2, LPC.LNKA, Zero },
+                Package () { 0x0011FFFF, 3, LPC.LNKB, Zero },
+
+                Package () { 0x0012FFFF, 0, LPC.LNKH, Zero },
+                Package () { 0x0012FFFF, 1, LPC.LNKA, Zero },
+                Package () { 0x0012FFFF, 2, LPC.LNKB, Zero },
+                Package () { 0x0012FFFF, 3, LPC.LNKC, Zero },
+
+                Package () { 0x0013FFFF, 0, LPC.LNKA, Zero },
+                Package () { 0x0013FFFF, 1, LPC.LNKB, Zero },
+                Package () { 0x0013FFFF, 2, LPC.LNKC, Zero },
+                Package () { 0x0013FFFF, 3, LPC.LNKD, Zero },
+
+                Package () { 0x0014FFFF, 0, LPC.LNKB, Zero },
+                Package () { 0x0014FFFF, 1, LPC.LNKC, Zero },
+                Package () { 0x0014FFFF, 2, LPC.LNKD, Zero },
+                Package () { 0x0014FFFF, 3, LPC.LNKE, Zero },
+
+                Package () { 0x0015FFFF, 0, LPC.LNKC, Zero },
+                Package () { 0x0015FFFF, 1, LPC.LNKD, Zero },
+                Package () { 0x0015FFFF, 2, LPC.LNKE, Zero },
+                Package () { 0x0015FFFF, 3, LPC.LNKF, Zero },
+
+                Package () { 0x0016FFFF, 0, LPC.LNKD, Zero },
+                Package () { 0x0016FFFF, 1, LPC.LNKE, Zero },
+                Package () { 0x0016FFFF, 2, LPC.LNKF, Zero },
+                Package () { 0x0016FFFF, 3, LPC.LNKG, Zero },
+
+                Package () { 0x0017FFFF, 0, LPC.LNKE, Zero },
+                Package () { 0x0017FFFF, 1, LPC.LNKF, Zero },
+                Package () { 0x0017FFFF, 2, LPC.LNKG, Zero },
+                Package () { 0x0017FFFF, 3, LPC.LNKH, Zero },
+
+                Package () { 0x0018FFFF, 0, LPC.LNKF, Zero },
+                Package () { 0x0018FFFF, 1, LPC.LNKG, Zero },
+                Package () { 0x0018FFFF, 2, LPC.LNKH, Zero },
+                Package () { 0x0018FFFF, 3, LPC.LNKA, Zero },
+
+                Package () { 0x0019FFFF, 0, LPC.LNKG, Zero },
+                Package () { 0x0019FFFF, 1, LPC.LNKH, Zero },
+                Package () { 0x0019FFFF, 2, LPC.LNKA, Zero },
+                Package () { 0x0019FFFF, 3, LPC.LNKB, Zero },
+
+                Package () { 0x001AFFFF, 0, LPC.LNKH, Zero },
+                Package () { 0x001AFFFF, 1, LPC.LNKA, Zero },
+                Package () { 0x001AFFFF, 2, LPC.LNKB, Zero },
+                Package () { 0x001AFFFF, 3, LPC.LNKC, Zero },
+
+                Package () { 0x001BFFFF, 0, LPC.LNKA, Zero },
+                Package () { 0x001BFFFF, 1, LPC.LNKB, Zero },
+                Package () { 0x001BFFFF, 2, LPC.LNKC, Zero },
+                Package () { 0x001BFFFF, 3, LPC.LNKD, Zero },
+
+                Package () { 0x001CFFFF, 0, LPC.LNKB, Zero },
+                Package () { 0x001CFFFF, 1, LPC.LNKC, Zero },
+                Package () { 0x001CFFFF, 2, LPC.LNKD, Zero },
+                Package () { 0x001CFFFF, 3, LPC.LNKE, Zero },
+
+                Package () { 0x001DFFFF, 0, LPC.LNKC, Zero },
+                Package () { 0x001DFFFF, 1, LPC.LNKD, Zero },
+                Package () { 0x001DFFFF, 2, LPC.LNKE, Zero },
+                Package () { 0x001DFFFF, 3, LPC.LNKF, Zero },
+
+                Package () { 0x001EFFFF, 0, LPC.LNKD, Zero },
+                Package () { 0x001EFFFF, 1, LPC.LNKE, Zero },
+                Package () { 0x001EFFFF, 2, LPC.LNKF, Zero },
+                Package () { 0x001EFFFF, 3, LPC.LNKG, Zero },
+
+                Package () { 0x001FFFFF, 0, LPC.LNKE, Zero },
+                Package () { 0x001FFFFF, 1, LPC.LNKF, Zero },
+                Package () { 0x001FFFFF, 2, LPC.LNKG, Zero },
+                Package () { 0x001FFFFF, 3, LPC.LNKH, Zero }
+            })
+            Name (APRT, Package ()
+            {
+                Package () { 0x0000FFFF, 0, Zero, 0x15 },
+                Package () { 0x0000FFFF, 1, Zero, 0x16 },
+                Package () { 0x0000FFFF, 2, Zero, 0x17 },
+                Package () { 0x0000FFFF, 3, Zero, 0x10 },
+
+                Package () { 0x0001FFFF, 0, Zero, 0x16 },
+                Package () { 0x0001FFFF, 1, Zero, 0x17 },
+                Package () { 0x0001FFFF, 2, Zero, 0x10 },
+                Package () { 0x0001FFFF, 3, Zero, 0x11 },
+
+                Package () { 0x0002FFFF, 0, Zero, 0x17 },
+                Package () { 0x0002FFFF, 1, Zero, 0x10 },
+                Package () { 0x0002FFFF, 2, Zero, 0x11 },
+                Package () { 0x0002FFFF, 3, Zero, 0x12 },
+
+                Package () { 0x0003FFFF, 0, Zero, 0x10 },
+                Package () { 0x0003FFFF, 1, Zero, 0x11 },
+                Package () { 0x0003FFFF, 2, Zero, 0x12 },
+                Package () { 0x0003FFFF, 3, Zero, 0x13 },
+
+                Package () { 0x0004FFFF, 0, Zero, 0x11 },
+                Package () { 0x0004FFFF, 1, Zero, 0x12 },
+                Package () { 0x0004FFFF, 2, Zero, 0x13 },
+                Package () { 0x0004FFFF, 3, Zero, 0x14 },
+
+                Package () { 0x0005FFFF, 0, Zero, 0x12 },
+                Package () { 0x0005FFFF, 1, Zero, 0x13 },
+                Package () { 0x0005FFFF, 2, Zero, 0x14 },
+                Package () { 0x0005FFFF, 3, Zero, 0x15 },
+
+                Package () { 0x0006FFFF, 0, Zero, 0x13 },
+                Package () { 0x0006FFFF, 1, Zero, 0x14 },
+                Package () { 0x0006FFFF, 2, Zero, 0x15 },
+                Package () { 0x0006FFFF, 3, Zero, 0x16 },
+
+                Package () { 0x0007FFFF, 0, Zero, 0x14 },
+                Package () { 0x0007FFFF, 1, Zero, 0x15 },
+                Package () { 0x0007FFFF, 2, Zero, 0x16 },
+                Package () { 0x0007FFFF, 3, Zero, 0x17 },
+
+                Package () { 0x0008FFFF, 0, Zero, 0x15 },
+                Package () { 0x0008FFFF, 1, Zero, 0x16 },
+                Package () { 0x0008FFFF, 2, Zero, 0x17 },
+                Package () { 0x0008FFFF, 3, Zero, 0x10 },
+
+                Package () { 0x0009FFFF, 0, Zero, 0x16 },
+                Package () { 0x0009FFFF, 1, Zero, 0x17 },
+                Package () { 0x0009FFFF, 2, Zero, 0x10 },
+                Package () { 0x0009FFFF, 3, Zero, 0x11 },
+
+                Package () { 0x000AFFFF, 0, Zero, 0x17 },
+                Package () { 0x000AFFFF, 1, Zero, 0x10 },
+                Package () { 0x000AFFFF, 2, Zero, 0x11 },
+                Package () { 0x000AFFFF, 3, Zero, 0x12 },
+
+                Package () { 0x000BFFFF, 0, Zero, 0x10 },
+                Package () { 0x000BFFFF, 1, Zero, 0x11 },
+                Package () { 0x000BFFFF, 2, Zero, 0x12 },
+                Package () { 0x000BFFFF, 3, Zero, 0x13 },
+
+                Package () { 0x000CFFFF, 0, Zero, 0x11 },
+                Package () { 0x000CFFFF, 1, Zero, 0x12 },
+                Package () { 0x000CFFFF, 2, Zero, 0x13 },
+                Package () { 0x000CFFFF, 3, Zero, 0x14 },
+
+                Package () { 0x000DFFFF, 0, Zero, 0x12 },
+                Package () { 0x000DFFFF, 1, Zero, 0x13 },
+                Package () { 0x000DFFFF, 2, Zero, 0x14 },
+                Package () { 0x000DFFFF, 3, Zero, 0x15 },
+
+                Package () { 0x000EFFFF, 0, Zero, 0x13 },
+                Package () { 0x000EFFFF, 1, Zero, 0x14 },
+                Package () { 0x000EFFFF, 2, Zero, 0x15 },
+                Package () { 0x000EFFFF, 3, Zero, 0x16 },
+
+                Package () { 0x000FFFFF, 0, Zero, 0x14 },
+                Package () { 0x000FFFFF, 1, Zero, 0x15 },
+                Package () { 0x000FFFFF, 2, Zero, 0x16 },
+                Package () { 0x000FFFFF, 3, Zero, 0x17 },
+
+                Package () { 0x0010FFFF, 0, Zero, 0x15 },
+                Package () { 0x0010FFFF, 1, Zero, 0x16 },
+                Package () { 0x0010FFFF, 2, Zero, 0x17 },
+                Package () { 0x0010FFFF, 3, Zero, 0x10 },
+
+                Package () { 0x0011FFFF, 0, Zero, 0x16 },
+                Package () { 0x0011FFFF, 1, Zero, 0x17 },
+                Package () { 0x0011FFFF, 2, Zero, 0x10 },
+                Package () { 0x0011FFFF, 3, Zero, 0x11 },
+
+                Package () { 0x0012FFFF, 0, Zero, 0x17 },
+                Package () { 0x0012FFFF, 1, Zero, 0x10 },
+                Package () { 0x0012FFFF, 2, Zero, 0x11 },
+                Package () { 0x0012FFFF, 3, Zero, 0x12 },
+
+                Package () { 0x0013FFFF, 0, Zero, 0x10 },
+                Package () { 0x0013FFFF, 1, Zero, 0x11 },
+                Package () { 0x0013FFFF, 2, Zero, 0x12 },
+                Package () { 0x0013FFFF, 3, Zero, 0x13 },
+
+                Package () { 0x0014FFFF, 0, Zero, 0x11 },
+                Package () { 0x0014FFFF, 1, Zero, 0x12 },
+                Package () { 0x0014FFFF, 2, Zero, 0x13 },
+                Package () { 0x0014FFFF, 3, Zero, 0x14 },
+
+                Package () { 0x0015FFFF, 0, Zero, 0x12 },
+                Package () { 0x0015FFFF, 1, Zero, 0x13 },
+                Package () { 0x0015FFFF, 2, Zero, 0x14 },
+                Package () { 0x0015FFFF, 3, Zero, 0x15 },
+
+                Package () { 0x0016FFFF, 0, Zero, 0x13 },
+                Package () { 0x0016FFFF, 1, Zero, 0x14 },
+                Package () { 0x0016FFFF, 2, Zero, 0x15 },
+                Package () { 0x0016FFFF, 3, Zero, 0x16 },
+
+                Package () { 0x0017FFFF, 0, Zero, 0x14 },
+                Package () { 0x0017FFFF, 1, Zero, 0x15 },
+                Package () { 0x0017FFFF, 2, Zero, 0x16 },
+                Package () { 0x0017FFFF, 3, Zero, 0x17 },
+
+                Package () { 0x0018FFFF, 0, Zero, 0x15 },
+                Package () { 0x0018FFFF, 1, Zero, 0x16 },
+                Package () { 0x0018FFFF, 2, Zero, 0x17 },
+                Package () { 0x0018FFFF, 3, Zero, 0x10 },
+
+                Package () { 0x0019FFFF, 0, Zero, 0x16 },
+                Package () { 0x0019FFFF, 1, Zero, 0x17 },
+                Package () { 0x0019FFFF, 2, Zero, 0x10 },
+                Package () { 0x0019FFFF, 3, Zero, 0x11 },
+
+                Package () { 0x001AFFFF, 0, Zero, 0x17 },
+                Package () { 0x001AFFFF, 1, Zero, 0x10 },
+                Package () { 0x001AFFFF, 2, Zero, 0x11 },
+                Package () { 0x001AFFFF, 3, Zero, 0x12 },
+
+                Package () { 0x001BFFFF, 0, Zero, 0x10 },
+                Package () { 0x001BFFFF, 1, Zero, 0x11 },
+                Package () { 0x001BFFFF, 2, Zero, 0x12 },
+                Package () { 0x001BFFFF, 3, Zero, 0x13 },
+
+                Package () { 0x001CFFFF, 0, Zero, 0x11 },
+                Package () { 0x001CFFFF, 1, Zero, 0x12 },
+                Package () { 0x001CFFFF, 2, Zero, 0x13 },
+                Package () { 0x001CFFFF, 3, Zero, 0x14 },
+
+                Package () { 0x001DFFFF, 0, Zero, 0x12 },
+                Package () { 0x001DFFFF, 1, Zero, 0x13 },
+                Package () { 0x001DFFFF, 2, Zero, 0x14 },
+                Package () { 0x001DFFFF, 3, Zero, 0x15 },
+
+                Package () { 0x001EFFFF, 0, Zero, 0x13 },
+                Package () { 0x001EFFFF, 1, Zero, 0x14 },
+                Package () { 0x001EFFFF, 2, Zero, 0x15 },
+                Package () { 0x001EFFFF, 3, Zero, 0x16 },
+
+                Package () { 0x001FFFFF, 0, Zero, 0x14 },
+                Package () { 0x001FFFFF, 1, Zero, 0x15 },
+                Package () { 0x001FFFFF, 2, Zero, 0x16 },
+                Package () { 0x001FFFFF, 3, Zero, 0x17 }
+            })
+            Method (_PRT, 0, NotSerialized)
+            {
+                If (PICM)
+                {
+                    Return (APRT)
+                }
+                Else
+                {
+                    Return (PPRT)
+                }
+            }
+
+            Device (LPC)
+            {
+                Name (_ADR, 0x001F0000)
+                OperationRegion (LPCR, PCI_Config, Zero, 0x0100)
+                Field (LPCR, AnyAcc, NoLock, Preserve)
+                {
+                    Offset (0x60),
+                    PIRA,   8,
+                    PIRB,   8,
+                    PIRC,   8,
+                    PIRD,   8,
+                    Offset (0x68),
+                    PIRE,   8,
+                    PIRF,   8,
+                    PIRG,   8,
+                    PIRH,   8
+                }
+
+                Device (KBD)
+                {
+                  Name (_HID, EISAID ("PNP0303"))
+                  Name (_CID, EISAID ("PNP030B"))
+                  Name (_CRS, ResourceTemplate ()
+                  {
+                    IO (Decode16,
+                        0x0060,             // Range Minimum
+                        0x0060,             // Range Maximum
+                        0x00,               // Alignment
+                        0x01,               // Length
+                        )
+                    IO (Decode16,
+                        0x0064,             // Range Minimum
+                        0x0064,             // Range Maximum
+                        0x00,               // Alignment
+                        0x01,               // Length
+                        )
+                    IRQNoFlags ()
+                        {1}
+                  })
+                }
+
+                Device (MOU)
+                {
+                  Name (_HID, EISAID ("PNP0F03"))
+                  Name (_CID, EISAID ("PNP0F13"))
+                  Name (_CRS, ResourceTemplate ()
+                  {
+                    IRQNoFlags ()
+                        {12}
+                  })
+                }
+
+                Method (PIRV, 1, NotSerialized)
+                {
+                    If (And (Arg0, 0x80))
+                    {
+                        Return (Zero)
+                    }
+
+                    And (Arg0, 0x0F, Local0)
+                    If (LLess (Local0, 0x03))
+                    {
+                        Return (Zero)
+                    }
+
+                    If (LEqual (Local0, 0x08))
+                    {
+                        Return (Zero)
+                    }
+
+                    If (LEqual (Local0, 0x0D))
+                    {
+                        Return (Zero)
+                    }
+
+                    Return (One)
+                }
+
+                Device (LNKA)
+                {
+                    Name (_HID, EisaId ("PNP0C0F"))
+                    Name (_UID, One)
+                    Method (_STA, 0, NotSerialized)
+                    {
+                        If (PIRV (PIRA))
+                        {
+                            Return (0x0B)
+                        }
+                        Else
+                        {
+                            Return (0x09)
+                        }
+                    }
+
+                    Name (_PRS, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {3,4,5,6,7,9,10,11,12,14,15}
+                    })
+                    Name (CB01, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {}
+                    })
+                    CreateWordField (CB01, One, CIRA)
+                    Method (_CRS, 0, NotSerialized)
+                    {
+                        And (PIRA, 0x8F, Local0)
+                        If (PIRV (Local0))
+                        {
+                            ShiftLeft (One, Local0, CIRA)
+                        }
+                        Else
+                        {
+                            Store (Zero, CIRA)
+                        }
+
+                        Return (CB01)
+                    }
+
+                    Method (_DIS, 0, NotSerialized)
+                    {
+                        Store (0x80, PIRA)
+                    }
+
+                    Method (_SRS, 1, NotSerialized)
+                    {
+                        CreateWordField (Arg0, One, SIRA)
+                        FindSetRightBit (SIRA, Local0)
+                        Store (Decrement (Local0), PIRA)
+                    }
+                }
+
+                Device (LNKB)
+                {
+                    Name (_HID, EisaId ("PNP0C0F"))
+                    Name (_UID, 0x02)
+                    Method (_STA, 0, NotSerialized)
+                    {
+                        If (PIRV (PIRB))
+                        {
+                            Return (0x0B)
+                        }
+                        Else
+                        {
+                            Return (0x09)
+                        }
+                    }
+
+                    Name (_PRS, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {3,4,5,6,7,9,10,11,12,14,15}
+                    })
+                    Name (CB02, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {}
+                    })
+                    CreateWordField (CB02, One, CIRB)
+                    Method (_CRS, 0, NotSerialized)
+                    {
+                        And (PIRB, 0x8F, Local0)
+                        If (PIRV (Local0))
+                        {
+                            ShiftLeft (One, Local0, CIRB)
+                        }
+                        Else
+                        {
+                            Store (Zero, CIRB)
+                        }
+
+                        Return (CB02)
+                    }
+
+                    Method (_DIS, 0, NotSerialized)
+                    {
+                        Store (0x80, PIRB)
+                    }
+
+                    Method (_SRS, 1, NotSerialized)
+                    {
+                        CreateWordField (Arg0, One, SIRB)
+                        FindSetRightBit (SIRB, Local0)
+                        Store (Decrement (Local0), PIRB)
+                    }
+                }
+
+                Device (LNKC)
+                {
+                    Name (_HID, EisaId ("PNP0C0F"))
+                    Name (_UID, 0x03)
+                    Method (_STA, 0, NotSerialized)
+                    {
+                        If (PIRV (PIRC))
+                        {
+                            Return (0x0B)
+                        }
+                        Else
+                        {
+                            Return (0x09)
+                        }
+                    }
+
+                    Name (_PRS, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {3,4,5,6,7,9,10,11,12,14,15}
+                    })
+                    Name (CB03, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {}
+                    })
+                    CreateWordField (CB03, One, CIRC)
+                    Method (_CRS, 0, NotSerialized)
+                    {
+                        And (PIRC, 0x8F, Local0)
+                        If (PIRV (Local0))
+                        {
+                            ShiftLeft (One, Local0, CIRC)
+                        }
+                        Else
+                        {
+                            Store (Zero, CIRC)
+                        }
+
+                        Return (CB03)
+                    }
+
+                    Method (_DIS, 0, NotSerialized)
+                    {
+                        Store (0x80, PIRC)
+                    }
+
+                    Method (_SRS, 1, NotSerialized)
+                    {
+                        CreateWordField (Arg0, One, SIRC)
+                        FindSetRightBit (SIRC, Local0)
+                        Store (Decrement (Local0), PIRC)
+                    }
+                }
+
+                Device (LNKD)
+                {
+                    Name (_HID, EisaId ("PNP0C0F"))
+                    Name (_UID, 0x04)
+                    Method (_STA, 0, NotSerialized)
+                    {
+                        If (PIRV (PIRD))
+                        {
+                            Return (0x0B)
+                        }
+                        Else
+                        {
+                            Return (0x09)
+                        }
+                    }
+
+                    Name (_PRS, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {3,4,5,6,7,9,10,11,12,14,15}
+                    })
+                    Name (CB04, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {}
+                    })
+                    CreateWordField (CB04, One, CIRD)
+                    Method (_CRS, 0, NotSerialized)
+                    {
+                        And (PIRD, 0x8F, Local0)
+                        If (PIRV (Local0))
+                        {
+                            ShiftLeft (One, Local0, CIRD)
+                        }
+                        Else
+                        {
+                            Store (Zero, CIRD)
+                        }
+
+                        Return (CB04)
+                    }
+
+                    Method (_DIS, 0, NotSerialized)
+                    {
+                        Store (0x80, PIRD)
+                    }
+
+                    Method (_SRS, 1, NotSerialized)
+                    {
+                        CreateWordField (Arg0, One, SIRD)
+                        FindSetRightBit (SIRD, Local0)
+                        Store (Decrement (Local0), PIRD)
+                    }
+                }
+
+                Device (LNKE)
+                {
+                    Name (_HID, EisaId ("PNP0C0F"))
+                    Name (_UID, 0x05)
+                    Method (_STA, 0, NotSerialized)
+                    {
+                        If (PIRV (PIRE))
+                        {
+                            Return (0x0B)
+                        }
+                        Else
+                        {
+                            Return (0x09)
+                        }
+                    }
+
+                    Name (_PRS, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {3,4,5,6,7,9,10,11,12,14,15}
+                    })
+                    Name (CB05, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {}
+                    })
+                    CreateWordField (CB05, One, CIRE)
+                    Method (_CRS, 0, NotSerialized)
+                    {
+                        And (PIRE, 0x8F, Local0)
+                        If (PIRV (Local0))
+                        {
+                            ShiftLeft (One, Local0, CIRE)
+                        }
+                        Else
+                        {
+                            Store (Zero, CIRE)
+                        }
+
+                        Return (CB05)
+                    }
+
+                    Method (_DIS, 0, NotSerialized)
+                    {
+                        Store (0x80, PIRE)
+                    }
+
+                    Method (_SRS, 1, NotSerialized)
+                    {
+                        CreateWordField (Arg0, One, SIRE)
+                        FindSetRightBit (SIRE, Local0)
+                        Store (Decrement (Local0), PIRE)
+                    }
+                }
+
+                Device (LNKF)
+                {
+                    Name (_HID, EisaId ("PNP0C0F"))
+                    Name (_UID, 0x06)
+                    Method (_STA, 0, NotSerialized)
+                    {
+                        If (PIRV (PIRF))
+                        {
+                            Return (0x0B)
+                        }
+                        Else
+                        {
+                            Return (0x09)
+                        }
+                    }
+
+                    Name (_PRS, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {3,4,5,6,7,9,10,11,12,14,15}
+                    })
+                    Name (CB06, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {}
+                    })
+                    CreateWordField (CB06, One, CIRF)
+                    Method (_CRS, 0, NotSerialized)
+                    {
+                        And (PIRF, 0x8F, Local0)
+                        If (PIRV (Local0))
+                        {
+                            ShiftLeft (One, Local0, CIRF)
+                        }
+                        Else
+                        {
+                            Store (Zero, CIRF)
+                        }
+
+                        Return (CB06)
+                    }
+
+                    Method (_DIS, 0, NotSerialized)
+                    {
+                        Store (0x80, PIRF)
+                    }
+
+                    Method (_SRS, 1, NotSerialized)
+                    {
+                        CreateWordField (Arg0, One, SIRF)
+                        FindSetRightBit (SIRF, Local0)
+                        Store (Decrement (Local0), PIRF)
+                    }
+                }
+
+                Device (LNKG)
+                {
+                    Name (_HID, EisaId ("PNP0C0F"))
+                    Name (_UID, 0x07)
+                    Method (_STA, 0, NotSerialized)
+                    {
+                        If (PIRV (PIRG))
+                        {
+                            Return (0x0B)
+                        }
+                        Else
+                        {
+                            Return (0x09)
+                        }
+                    }
+
+                    Name (_PRS, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {3,4,5,6,7,9,10,11,12,14,15}
+                    })
+                    Name (CB07, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {}
+                    })
+                    CreateWordField (CB07, One, CIRG)
+                    Method (_CRS, 0, NotSerialized)
+                    {
+                        And (PIRG, 0x8F, Local0)
+                        If (PIRV (Local0))
+                        {
+                            ShiftLeft (One, Local0, CIRG)
+                        }
+                        Else
+                        {
+                            Store (Zero, CIRG)
+                        }
+
+                        Return (CB07)
+                    }
+
+                    Method (_DIS, 0, NotSerialized)
+                    {
+                        Store (0x80, PIRG)
+                    }
+
+                    Method (_SRS, 1, NotSerialized)
+                    {
+                        CreateWordField (Arg0, One, SIRG)
+                        FindSetRightBit (SIRG, Local0)
+                        Store (Decrement (Local0), PIRG)
+                    }
+                }
+
+                Device (LNKH)
+                {
+                    Name (_HID, EisaId ("PNP0C0F"))
+                    Name (_UID, 0x08)
+                    Method (_STA, 0, NotSerialized)
+                    {
+                        If (PIRV (PIRH))
+                        {
+                            Return (0x0B)
+                        }
+                        Else
+                        {
+                            Return (0x09)
+                        }
+                    }
+
+                    Name (_PRS, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {3,4,5,6,7,9,10,11,12,14,15}
+                    })
+                    Name (CB08, ResourceTemplate ()
+                    {
+                        IRQ (Level, ActiveLow, Shared, )
+                            {}
+                    })
+                    CreateWordField (CB08, One, CIRH)
+                    Method (_CRS, 0, NotSerialized)
+                    {
+                        And (PIRH, 0x8F, Local0)
+                        If (PIRV (Local0))
+                        {
+                            ShiftLeft (One, Local0, CIRH)
+                        }
+                        Else
+                        {
+                            Store (Zero, CIRH)
+                        }
+
+                        Return (CB08)
+                    }
+
+                    Method (_DIS, 0, NotSerialized)
+                    {
+                        Store (0x80, PIRH)
+                    }
+
+                    Method (_SRS, 1, NotSerialized)
+                    {
+                        CreateWordField (Arg0, One, SIRH)
+                        FindSetRightBit (SIRH, Local0)
+                        Store (Decrement (Local0), PIRH)
+                    }
+                }
+
+                Device (SIO)
+                {
+                    Name (_HID, EisaId ("PNP0C02"))
+                    Name (_CRS, ResourceTemplate ()
+                    {
+                        IO (Decode16,
+                            0x0220,             // Range Minimum
+                            0x0220,             // Range Maximum
+                            0x01,               // Alignment
+                            0x04,               // Length
+                            )
+                        IO (Decode16,
+                            0x0224,             // Range Minimum
+                            0x0224,             // Range Maximum
+                            0x01,               // Alignment
+                            0x04,               // Length
+                            )
+                        Memory32Fixed (ReadWrite,
+                            0xE0000000,         // Address Base
+                            0x10000000,         // Address Length
+                            )
+                        IO (Decode16,
+                            0x04D0,             // Range Minimum
+                            0x04D0,             // Range Maximum
+                            0x01,               // Alignment
+                            0x02,               // Length
+                            )
+                        IO (Decode16,
+                            0x0061,             // Range Minimum
+                            0x0061,             // Range Maximum
+                            0x01,               // Alignment
+                            0x01,               // Length
+                            )
+                        IO (Decode16,
+                            0x0400,             // Range Minimum
+                            0x0400,             // Range Maximum
+                            0x01,               // Alignment
+                            0x08,               // Length
+                            )
+                        IO (Decode16,
+                            0x00B2,             // Range Minimum
+                            0x00B2,             // Range Maximum
+                            0x01,               // Alignment
+                            0x01,               // Length
+                            )
+                        IO (Decode16,
+                            0x0084,             // Range Minimum
+                            0x0084,             // Range Maximum
+                            0x01,               // Alignment
+                            0x01,               // Length
+                            )
+                        IO (Decode16,
+                            0x0072,             // Range Minimum
+                            0x0072,             // Range Maximum
+                            0x01,               // Alignment
+                            0x06,               // Length
+                            )
+                    })
+                }
+
+                Device (COM1)
+                {
+                    Name (_HID, EisaId ("PNP0501"))
+                    Name (_UID, One)
+                    Name (_CRS, ResourceTemplate ()
+                    {
+                        IO (Decode16,
+                            0x03F8,             // Range Minimum
+                            0x03F8,             // Range Maximum
+                            0x01,               // Alignment
+                            0x08,               // Length
+                            )
+                        IRQNoFlags ()
+                            {4}
+                    })
+                }
+
+                Device (COM2)
+                {
+                    Name (_HID, EisaId ("PNP0501"))
+                    Name (_UID, 0x02)
+                    Name (_CRS, ResourceTemplate ()
+                    {
+                        IO (Decode16,
+                            0x02F8,             // Range Minimum
+                            0x02F8,             // Range Maximum
+                            0x01,               // Alignment
+                            0x08,               // Length
+                            )
+                        IRQNoFlags ()
+                            {3}
+                    })
+                }
+
+                Device (RTC)
+                {
+                    Name (_HID, EisaId ("PNP0B00"))
+                    Name (_CRS, ResourceTemplate ()
+                    {
+                        IO (Decode16,
+                            0x0070,             // Range Minimum
+                            0x0070,             // Range Maximum
+                            0x00,               // Alignment
+                            0x02,               // Length
+                            )
+                        IRQNoFlags ()
+                            {8}
+                        IO (Decode16,
+                            0x0072,             // Range Minimum
+                            0x0072,             // Range Maximum
+                            0x02,               // Alignment
+                            0x06,               // Length
+                            )
+                    })
+                }
+
+                Device (PIC)
+                {
+                    Name (_HID, EisaId ("PNP0000"))
+                    Name (_CRS, ResourceTemplate ()
+                    {
+                        IO (Decode16,
+                            0x0020,             // Range Minimum
+                            0x0020,             // Range Maximum
+                            0x01,               // Alignment
+                            0x02,               // Length
+                            )
+                        IO (Decode16,
+                            0x00A0,             // Range Minimum
+                            0x00A0,             // Range Maximum
+                            0x01,               // Alignment
+                            0x02,               // Length
+                            )
+                        IRQNoFlags ()
+                            {2}
+                    })
+                }
+
+                Device (TIMR)
+                {
+                    Name (_HID, EisaId ("PNP0100"))
+                    Name (_CRS, ResourceTemplate ()
+                    {
+                        IO (Decode16,
+                            0x0040,             // Range Minimum
+                            0x0040,             // Range Maximum
+                            0x01,               // Alignment
+                            0x04,               // Length
+                            )
+                        IRQNoFlags ()
+                            {0}
+                    })
+                }
+            }
+        }
+    }
+
+    Scope (_SB.PC00)
+    {
+        Device (HPET)
+        {
+            Name (_HID, EisaId ("PNP0103"))
+            Name (_UID, Zero)
+            Name (_CRS, ResourceTemplate ()
+            {
+                Memory32Fixed (ReadWrite,
+                    0xFED00000,         // Address Base
+                    0x00000400,         // Address Length
+                    )
+            })
+        }
+    }
+}
+
diff --git a/BhyvePkg/AcpiTables/Facp.aslc b/BhyvePkg/AcpiTables/Facp.aslc
new file mode 100644
index 0000000000..73afb4a9aa
--- /dev/null
+++ b/BhyvePkg/AcpiTables/Facp.aslc
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "Platform.h"
+
+#define EFI_ACPI_OEM_TABLE_ID     SIGNATURE_64('B','V','F','A','C','P',' ',' ')
+
+EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE FACP = {
+  {
+    EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+    sizeof (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE),
+    EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+    0,                          // to make sum of entire table == 0
+    {EFI_ACPI_OEM_ID},          // OEMID is a 6 bytes long field
+    EFI_ACPI_OEM_TABLE_ID,      // OEM table identification(8 bytes long)
+    EFI_ACPI_OEM_REVISION,      // OEM revision number
+    EFI_ACPI_CREATOR_ID,        // ASL compiler vendor ID
+    EFI_ACPI_CREATOR_REVISION   // ASL compiler revision number
+  },
+  0,                // Physical addesss of FACS
+  0,                // Physical address of DSDT
+  INT_MODEL,        // System Interrupt Model
+  RESERVED,         // reserved
+  SCI_INT_VECTOR,   // System vector of SCI interrupt
+  SMI_CMD_IO_PORT,  // Port address of SMI command port
+  ACPI_ENABLE,      // value to write to port smi_cmd to enable ACPI
+  ACPI_DISABLE,     // value to write to port smi_cmd to disable ACPI
+  S4BIOS_REQ,       // Value to write to SMI CMD port to enter the S4BIOS state
+  0,                // PState control
+  PM1a_EVT_BLK,     // Port address of Power Mgt 1a Event Reg Blk
+  PM1b_EVT_BLK,     // Port address of Power Mgt 1b Event Reg Blk
+  PM1a_CNT_BLK,     // Port address of Power Mgt 1a Ctrl Reg Blk
+  PM1b_CNT_BLK,     // Port address of Power Mgt 1b Ctrl Reg Blk
+  PM2_CNT_BLK,      // Port address of Power Mgt 2  Ctrl Reg Blk
+  PM_TMR_BLK,       // Port address of Power Mgt Timer Ctrl Reg Blk
+  GPE0_BLK,         // Port addr of General Purpose Event 0 Reg Blk
+  GPE1_BLK,         // Port addr of General Purpose Event 1 Reg Blk
+  PM1_EVT_LEN,      // Byte Length of ports at pm1X_evt_blk
+  PM1_CNT_LEN,      // Byte Length of ports at pm1X_cnt_blk
+  PM2_CNT_LEN,      // Byte Length of ports at pm2_cnt_blk
+  PM_TM_LEN,        // Byte Length of ports at pm_tm_blk
+  GPE0_BLK_LEN,     // Byte Length of ports at gpe0_blk
+  GPE1_BLK_LEN,     // Byte Length of ports at gpe1_blk
+  GPE1_BASE,        // offset in gpe model where gpe1 events start
+  0,                // _CST support
+  P_LVL2_LAT,       // worst case HW latency to enter/exit C2 state
+  P_LVL3_LAT,       // worst case HW latency to enter/exit C3 state
+  FLUSH_SIZE,       // Size of area read to flush caches
+  FLUSH_STRIDE,     // Stride used in flushing caches
+  DUTY_OFFSET,      // bit location of duty cycle field in p_cnt reg
+  DUTY_WIDTH,       // bit width of duty cycle field in p_cnt reg
+  DAY_ALRM,         // index to day-of-month alarm in RTC CMOS RAM
+  MON_ALRM,         // index to month-of-year alarm in RTC CMOS RAM
+  CENTURY,          // index to century in RTC CMOS RAM
+  IAPC_BOOT_ARCH,   // Boot architecture flag
+  RESERVED,         // reserved
+  FACP_FLAGS,
+  FACP_RESET_REG,
+  FACP_RESET_VAL,
+};
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from removing the
+  // data structure from the exeutable
+  //
+  return (VOID*)&FACP;
+}
diff --git a/BhyvePkg/AcpiTables/Facs.aslc b/BhyvePkg/AcpiTables/Facs.aslc
new file mode 100644
index 0000000000..b66d698df4
--- /dev/null
+++ b/BhyvePkg/AcpiTables/Facs.aslc
@@ -0,0 +1,79 @@
+/** @file
+  FACS Table
+
+  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+#include <IndustryStandard/Acpi.h>
+
+EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE FACS = {
+  EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE,
+  sizeof (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE),
+
+  //
+  // Hardware Signature will be updated at runtime
+  //
+  0x00000000,
+  0x00,
+  0x00,
+  0x00,
+  {
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE,
+    EFI_ACPI_RESERVED_BYTE
+  }
+};
+
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from removing the
+  // data structure from the exeutable
+  //
+  return (VOID*)&FACS;
+}
+
diff --git a/BhyvePkg/AcpiTables/Hpet.aslc b/BhyvePkg/AcpiTables/Hpet.aslc
new file mode 100644
index 0000000000..87a3cb767d
--- /dev/null
+++ b/BhyvePkg/AcpiTables/Hpet.aslc
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <IndustryStandard/HighPrecisionEventTimerTable.h>
+
+#include "Platform.h"
+
+#define EFI_ACPI_HPET_DESCRIPTION_TABLE_SIGNATURE  SIGNATURE_32('H', 'P', 'E', 'T')
+#define EFI_ACPI_OEM_TABLE_ID                      SIGNATURE_64('B','V','H','P','E','T',' ',' ')
+
+//
+// Ensure proper structure formats
+//
+#pragma pack (1)
+
+//
+// ACPI HPET structure
+//
+typedef struct {
+  EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER  Header;
+} EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_DESCRIPTION_TABLE;
+
+#pragma pack ()
+
+//
+// HPET Description Table
+//
+EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_DESCRIPTION_TABLE Hpet = {
+  {
+    {
+      EFI_ACPI_HPET_DESCRIPTION_TABLE_SIGNATURE,
+      sizeof (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_DESCRIPTION_TABLE),
+      EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_REVISION,
+      0x00,                              // Checksum will be updated at runtime
+      {EFI_ACPI_OEM_ID},
+      EFI_ACPI_OEM_TABLE_ID,
+      EFI_ACPI_OEM_REVISION,
+      EFI_ACPI_CREATOR_ID,
+      EFI_ACPI_CREATOR_REVISION
+    },
+
+    //
+    // HPET specific fields
+    //
+    0x0000A400,                          // EventTimerBlockId
+    {
+      EFI_ACPI_2_0_SYSTEM_MEMORY,
+      0,
+      0,
+      EFI_ACPI_RESERVED_BYTE,
+      0xFED00000,
+    },
+    0                                    // HpetNumber
+  }
+};
+
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from removing the
+  // data structure from the exeutable
+  //
+  return (VOID*)&Hpet;
+}
diff --git a/BhyvePkg/AcpiTables/Madt.aslc b/BhyvePkg/AcpiTables/Madt.aslc
new file mode 100644
index 0000000000..6fc2c36c8c
--- /dev/null
+++ b/BhyvePkg/AcpiTables/Madt.aslc
@@ -0,0 +1,144 @@
+/** @file
+  MADT Table
+
+  This file contains a structure definition for the ACPI 1.0 Multiple APIC
+  Description Table (MADT).
+
+  Copyright (c) 2014, Pluribus Networks, Inc.
+  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Platform.h>
+
+#define EFI_ACPI_OEM_TABLE_ID                      SIGNATURE_64('B','V','M','A','D','T',' ',' ')
+
+//
+// Local APIC address
+//
+#define EFI_ACPI_LOCAL_APIC_ADDRESS 0xFEE00000
+
+//
+// Multiple APIC Flags are defined in AcpiX.0.h
+//
+#define EFI_ACPI_1_0_MULTIPLE_APIC_FLAGS (EFI_ACPI_1_0_PCAT_COMPAT)
+
+//
+// Define the number of each table type.
+// This is where the table layout is modified.
+//
+#define EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT           1
+#define EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT      1
+#define EFI_ACPI_IO_APIC_COUNT                        1
+
+//
+// Ensure proper structure formats
+//
+#pragma pack (1)
+
+//
+// ACPI 1.0 MADT structure
+//
+typedef struct {
+  EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER   Header;
+
+#if EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT > 0
+  EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE           LocalApic[EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT];
+#endif
+
+#if EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT > 0
+  EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE      Iso[EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT];
+#endif
+
+#if EFI_ACPI_IO_APIC_COUNT > 0
+  EFI_ACPI_1_0_IO_APIC_STRUCTURE                        IoApic[EFI_ACPI_IO_APIC_COUNT];
+#endif
+
+} EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE;
+
+#pragma pack ()
+
+//
+// Multiple APIC Description Table
+//
+EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE Madt = {
+  {
+    {
+      EFI_ACPI_1_0_APIC_SIGNATURE,
+      sizeof (EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE),
+      EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
+      0x00,                                                     // Checksum will be updated at runtime
+      {EFI_ACPI_OEM_ID},
+      EFI_ACPI_OEM_TABLE_ID,
+      EFI_ACPI_OEM_REVISION,
+      EFI_ACPI_CREATOR_ID,
+      EFI_ACPI_CREATOR_REVISION
+    },
+
+    //
+    // MADT specific fields
+    //
+    EFI_ACPI_LOCAL_APIC_ADDRESS,
+    EFI_ACPI_1_0_MULTIPLE_APIC_FLAGS,
+  },
+
+  //
+  // Processor Local APIC Structure
+  //
+  {
+    {
+      EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC,                        // Type
+      sizeof (EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE),     // Length
+      0x00,                                                     // Processor ID
+      0x00,                                                     // Local APIC ID
+      0x00000001                                                // Flags - Enabled by default
+    }
+  },
+
+  //
+  // Interrupt Source Override Structure
+  //
+  {
+    {
+      //
+      // IRQ0=>IRQ2 Interrupt Source Override Structure
+      //
+      EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE,                   // Type
+      sizeof (EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE),// Length
+      0x00,                                                     // Bus - ISA
+      0x00,                                                     // Source - IRQ0
+      0x00000002,                                               // Global System Interrupt - IRQ2
+      0x0005                                                    // Flags - Conforms to specifications of the bus
+    },
+  },
+
+  //
+  // IO APIC Structure
+  //
+  {
+    {
+      EFI_ACPI_1_0_IO_APIC,                                     // Type
+      sizeof (EFI_ACPI_1_0_IO_APIC_STRUCTURE),                  // Length
+      0x01,                                                     // IO APIC ID
+      EFI_ACPI_RESERVED_BYTE,                                   // Reserved
+      0xFEC00000,                                               // IO APIC Address (physical)
+      0x00000000                                                // Global System Interrupt Base
+    }
+  },
+};
+
+
+VOID*
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from removing the
+  // data structure from the exeutable
+  //
+  return (VOID*)&Madt;
+}
diff --git a/BhyvePkg/AcpiTables/Mcfg.aslc b/BhyvePkg/AcpiTables/Mcfg.aslc
new file mode 100644
index 0000000000..ac8a7f0c91
--- /dev/null
+++ b/BhyvePkg/AcpiTables/Mcfg.aslc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, Nahanni Systems, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "Platform.h"
+
+#define EFI_ACPI_OEM_TABLE_ID                      SIGNATURE_64('B','V','M','C','F','G',' ',' ')
+
+#pragma pack(1)
+
+typedef struct {
+  EFI_ACPI_DESCRIPTION_HEADER   Header;
+  UINT64                        Reserved0;
+  UINT64                        BaseAddress;
+  UINT16                        PciSegmentGroupNumber;
+  UINT8                         StartBusNumber;
+  UINT8                         EndBusNumber;
+  UINT32                        Reserved1;
+} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE;
+
+#pragma pack()
+
+EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE MCFG = {
+  {
+    EFI_ACPI_2_0_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_SIGNATURE,
+    sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE),
+    EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
+    0,                          // to make sum of entire table == 0
+    {EFI_ACPI_OEM_ID},          // OEMID is a 6 bytes long field
+    EFI_ACPI_OEM_TABLE_ID,      // OEM table identification(8 bytes long)
+    EFI_ACPI_OEM_REVISION,      // OEM revision number
+    EFI_ACPI_CREATOR_ID,        // ASL compiler vendor ID
+    EFI_ACPI_CREATOR_REVISION   // ASL compiler revision number
+  },
+  0,                            // Reserved
+  0x00000000E0000000,           // BaseAddress
+  0x0000,                       // PciSegmentGroupNumber
+  0,                            // StartBusNumber
+  255,                          // EndBusNumber
+  0                             // Reserved
+};
+
+
+VOID *
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from removing the
+  // data structure from the exeutable
+  //
+  return (VOID*)&MCFG;
+}
diff --git a/BhyvePkg/AcpiTables/Platform.h b/BhyvePkg/AcpiTables/Platform.h
new file mode 100644
index 0000000000..4c029cc096
--- /dev/null
+++ b/BhyvePkg/AcpiTables/Platform.h
@@ -0,0 +1,71 @@
+/** @file
+  Platform specific defines for constructing ACPI tables
+
+  Copyright (c) 2014, Pluribus Networks, Inc.^M
+  Copyright (c) 2012, 2013, Red Hat, Inc.
+  Copyright (c) 2008, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+#ifndef _Platform_h_INCLUDED_
+#define _Platform_h_INCLUDED_
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+
+//
+// ACPI table information used to initialize tables.
+//
+#define EFI_ACPI_OEM_ID           'B','H','Y','V','E',' '   // OEMID 6 bytes long
+#define EFI_ACPI_OEM_REVISION     0x1
+#define EFI_ACPI_CREATOR_ID       SIGNATURE_32('B','H','Y','V')
+#define EFI_ACPI_CREATOR_REVISION 0x00000001
+
+#define INT_MODEL       0x01
+#define SCI_INT_VECTOR  0x0009
+#define SMI_CMD_IO_PORT 0xB2
+#define ACPI_ENABLE     0xA0
+#define ACPI_DISABLE    0xA1
+#define S4BIOS_REQ      0x00
+#define PM1a_EVT_BLK    0x00000400      /* TNXXX */
+#define PM1b_EVT_BLK    0x00000000
+#define PM1a_CNT_BLK    0x00000404      /* TNXXX */
+#define PM1b_CNT_BLK    0x00000000
+#define PM2_CNT_BLK     0x00000000
+#define PM_TMR_BLK      0x00000408
+#define GPE0_BLK        0x00000000
+#define GPE1_BLK        0x00000000
+#define PM1_EVT_LEN     0x04
+#define PM1_CNT_LEN     0x02
+#define PM2_CNT_LEN     0x00
+#define PM_TM_LEN       0x04
+#define GPE0_BLK_LEN    0x00
+#define GPE1_BLK_LEN    0x00
+#define GPE1_BASE       0x00
+#define RESERVED        0x00
+#define P_LVL2_LAT      0x0000
+#define P_LVL3_LAT      0x0000
+#define FLUSH_SIZE      0x0000
+#define FLUSH_STRIDE    0x0000
+#define DUTY_OFFSET     0x00
+#define DUTY_WIDTH      0x00
+#define DAY_ALRM        0x00
+#define MON_ALRM        0x00
+#define CENTURY         0x32
+#define IAPC_BOOT_ARCH  0x12    /* 8042 present, disable PCIe ASPM */
+#define FACP_FLAGS      (EFI_ACPI_1_0_WBINVD | EFI_ACPI_1_0_PROC_C1 |         \
+                        EFI_ACPI_1_0_SLP_BUTTON | EFI_ACPI_1_0_TMR_VAL_EXT |  \
+                        EFI_ACPI_2_0_RESET_REG_SUP |                          \
+                        EFI_ACPI_3_0_FORCE_APIC_PHYSICAL_DESTINATION_MODE)
+#define FACP_RESET_REG  {                                               \
+        EFI_ACPI_3_0_SYSTEM_IO,         /* Address Space ID */          \
+        8,                              /* Bit Width */                 \
+        0,                              /* Bit Offset */                \
+        EFI_ACPI_3_0_BYTE,              /* Byte Access */               \
+        0xCF9                           /* I/O Port */                  \
+}
+#define FACP_RESET_VAL  0x6
+#endif
diff --git a/BhyvePkg/AcpiTables/Spcr.aslc b/BhyvePkg/AcpiTables/Spcr.aslc
new file mode 100644
index 0000000000..737de56520
--- /dev/null
+++ b/BhyvePkg/AcpiTables/Spcr.aslc
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015, Nahanni Systems, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "Platform.h"
+
+#define EFI_ACPI_OEM_TABLE_ID     SIGNATURE_64('B','V','S','P','C','R',' ',' ')
+
+EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE SPCR = {
+  {
+    EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
+    sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE),
+    EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
+    0,                          // to make sum of entire table == 0
+    {EFI_ACPI_OEM_ID},          // OEMID is a 6 bytes long field
+    EFI_ACPI_OEM_TABLE_ID,      // OEM table identification(8 bytes long)
+    EFI_ACPI_OEM_REVISION,      // OEM revision number
+    EFI_ACPI_CREATOR_ID,        // ASL compiler vendor ID
+    EFI_ACPI_CREATOR_REVISION   // ASL compiler revision number
+  },
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_16550,
+  { 0 },                        // Reserved
+  {                             // BaseAddress
+    0x01,                       //   AddressSpaceId
+    0x08,                       //   RegisterBitWidth
+    0x00,                       //   RegisterBitOffset
+    0x00,                       //   Reserved
+    0x03F8                      //   Address (COM1)
+  },
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_8259,
+  4,                            // Irq
+  0,                            // GlobalSystemInterrupt
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200,
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY,
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1,
+  0x03,                         // FlowControl: RTS/CTS | DCD
+  EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_VT_UTF8,
+  0,                            // Language
+  0,                            // PciDeviceId
+  0,                            // PciVendorId
+  0,                            // PciBusNumber
+  0,                            // PciDeviceNumber
+  0,                            // PciFunctionNumber
+  0,                            // PciFlags
+  0,                            // PciSegment
+  0                             // Reserved
+};
+
+
+VOID *
+ReferenceAcpiTable (
+  VOID
+  )
+{
+  //
+  // Reference the table being generated to prevent the optimizer from removing the
+  // data structure from the exeutable
+  //
+  return (VOID*)&SPCR;
+}
diff --git a/BhyvePkg/AcpiTables/Ssdt.asl b/BhyvePkg/AcpiTables/Ssdt.asl
new file mode 100644
index 0000000000..94e6447d1e
--- /dev/null
+++ b/BhyvePkg/AcpiTables/Ssdt.asl
@@ -0,0 +1,14 @@
+/** @file
+  Placeholder for runtime-generated objects.
+
+  This empty table provides only a header for dynamic copying and extension,
+  and a trigger for QemuInstallAcpiSsdtTable().
+
+  Copyright (C) 2012 Red Hat, Inc.
+
+  SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+DefinitionBlock ("Ssdt.aml", "SSDT", 1, "REDHAT", "OVMF    ", 1) {
+}
diff --git a/BhyvePkg/BhyvePkg.dec b/BhyvePkg/BhyvePkg.dec
new file mode 100644
index 0000000000..fcdf1886b5
--- /dev/null
+++ b/BhyvePkg/BhyvePkg.dec
@@ -0,0 +1,170 @@
+#
+#  Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2014, Pluribus Networks, Inc.
+#
+#  SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+[Defines]
+  DEC_SPECIFICATION              = 0x00010005
+  PACKAGE_NAME                   = BhyvePkg
+  PACKAGE_GUID                   = 178345e1-6ac0-439d-a3df-9abf70dccd57
+  PACKAGE_VERSION                = 0.1
+
+[Includes]
+  Include
+  ../OvmfPkg/Include
+
+[LibraryClasses]
+  ##  @libraryclass  Save and restore variables using a file
+  #
+  NvVarsFileLib|Include/Library/NvVarsFileLib.h
+
+  ##  @libraryclass  Provides services to work with PCI capabilities in PCI
+  #                  config space.
+  PciCapLib|Include/Library/PciCapLib.h
+
+  ##  @libraryclass  Layered on top of PciCapLib, allows clients to plug an
+  #                  EFI_PCI_IO_PROTOCOL backend into PciCapLib, for config
+  #                  space access.
+  PciCapPciIoLib|Include/Library/PciCapPciIoLib.h
+
+  ##  @libraryclass  Layered on top of PciCapLib, allows clients to plug a
+  #                  PciSegmentLib backend into PciCapLib, for config space
+  #                  access.
+  PciCapPciSegmentLib|Include/Library/PciCapPciSegmentLib.h
+
+  ##  @libraryclass  Register a status code handler for printing the Boot
+  #                  Manager's LoadImage() and StartImage() preparations, and
+  #                  return codes, to the UEFI console.
+  PlatformBmPrintScLib|Include/Library/PlatformBmPrintScLib.h
+
+  ##  @libraryclass  Serialize (and deserialize) variables
+  #
+  SerializeVariablesLib|Include/Library/SerializeVariablesLib.h
+
+  ##  @libraryclass  Access bhyve's firmware control interface
+  #
+  BhyveFwCtlLib|Include/Library/BhyveFwCtlLib.h
+
+[Guids]
+  gUefiOvmfPkgTokenSpaceGuid          = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}
+  gOvmfPlatformConfigGuid             = {0x7235c51c, 0x0c80, 0x4cab, {0x87, 0xac, 0x3b, 0x08, 0x4a, 0x63, 0x04, 0xb1}}
+  gVirtioMmioTransportGuid            = {0x837dca9e, 0xe874, 0x4d82, {0xb2, 0x9a, 0x23, 0xfe, 0x0e, 0x23, 0xd1, 0xe2}}
+  gRootBridgesConnectedEventGroupGuid = {0x24a2d66f, 0xeedd, 0x4086, {0x90, 0x42, 0xf2, 0x6e, 0x47, 0x97, 0xee, 0x69}}
+
+[Protocols]
+  gVirtioDeviceProtocolGuid           = {0xfa920010, 0x6785, 0x4941, {0xb6, 0xec, 0x49, 0x8c, 0x57, 0x9f, 0x16, 0x0a}}
+  gIoMmuAbsentProtocolGuid            = {0xf8775d50, 0x8abd, 0x4adf, {0x92, 0xac, 0x85, 0x3e, 0x51, 0xf6, 0xc8, 0xdc}}
+
+[PcdsFixedAtBuild]
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize|0x0|UINT32|1
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|0x0|UINT32|0x15
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize|0x0|UINT32|0x16
+
+  ## This flag is used to control the destination port for PlatformDebugLibIoPort
+  gUefiOvmfPkgTokenSpaceGuid.PcdDebugIoPort|0x2F8|UINT16|4
+
+  ## When VirtioScsiDxe is instantiated for a HBA, the numbers of targets and
+  #  LUNs are retrieved from the host during virtio-scsi setup.
+  #  MdeModulePkg/Bus/Scsi/ScsiBusDxe then scans all MaxTarget * MaxLun
+  #  possible devices. This can take extremely long, for example with
+  #  MaxTarget=255 and MaxLun=16383. The *inclusive* constants below limit
+  #  MaxTarget and MaxLun, independently, should the host report higher values,
+  #  so that scanning the number of devices given by their product is still
+  #  acceptably fast.
+  gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxTargetLimit|31|UINT16|6
+  gUefiOvmfPkgTokenSpaceGuid.PcdVirtioScsiMaxLunLimit|7|UINT32|7
+
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|0x0|UINT32|0xa
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareBlockSize|0|UINT32|0xb
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase|0x0|UINT32|0xc
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwSpareBase|0x0|UINT32|0xd
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase|0x0|UINT32|0xe
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress|0x0|UINT32|0xf
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|0x0|UINT32|0x11
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize|0x0|UINT32|0x12
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|0x0|UINT32|0x13
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize|0x0|UINT32|0x14
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase|0x0|UINT32|0x18
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize|0x0|UINT32|0x19
+  gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize|0x0|UINT32|0x1a
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd|0x0|UINT32|0x1f
+
+  ## Pcd8259LegacyModeMask defines the default mask value for platform. This
+  #  value is determined.
+  #  1) If platform only support pure UEFI, value should be set to 0xFFFF or
+  #     0xFFFE; Because only clock interrupt is allowed in legacy mode in pure
+  #     UEFI platform.
+  #  2) If platform install CSM and use thunk module:
+  #     a) If thunk call provided by CSM binary requires some legacy interrupt
+  #        support, the corresponding bit should be opened as 0.
+  #        For example, if keyboard interfaces provided CSM binary use legacy
+  #        keyboard interrupt in 8259 bit 1, then the value should be set to
+  #        0xFFFC.
+  #     b) If all thunk call provied by CSM binary do not require legacy
+  #        interrupt support, value should be set to 0xFFFF or 0xFFFE.
+  #
+  #  The default value of legacy mode mask could be changed by
+  #  EFI_LEGACY_8259_PROTOCOL->SetMask(). But it is rarely need change it
+  #  except some special cases such as when initializing the CSM binary, it
+  #  should be set to 0xFFFF to mask all legacy interrupt. Please restore the
+  #  original legacy mask value if changing is made for these special case.
+  gUefiOvmfPkgTokenSpaceGuid.Pcd8259LegacyModeMask|0xFFFF|UINT16|0x3
+
+  ## Pcd8259LegacyModeEdgeLevel defines the default edge level for legacy
+  #  mode's interrrupt controller.
+  #  For the corresponding bits, 0 = Edge triggered and 1 = Level triggered.
+  gUefiOvmfPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0000|UINT16|0x5
+
+
+
+[PcdsDynamic, PcdsDynamicEx]
+  gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId|0|UINT16|0x1b
+  gUefiOvmfPkgTokenSpaceGuid.PcdQemuSmbiosValidated|FALSE|BOOLEAN|0x21
+
+  ## The IO port aperture shared by all PCI root bridges.
+  #
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase|0x0|UINT64|0x22
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize|0x0|UINT64|0x23
+
+  ## The 32-bit MMIO aperture shared by all PCI root bridges.
+  #
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base|0x0|UINT64|0x24
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size|0x0|UINT64|0x25
+
+  ## The 64-bit MMIO aperture shared by all PCI root bridges.
+  #
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base|0x0|UINT64|0x26
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size|0x0|UINT64|0x27
+
+  ## The following setting controls how many megabytes we configure as TSEG on
+  #  Q35, for SMRAM purposes. Permitted defaults are: 1, 2, 8. Other defaults
+  #  cause undefined behavior. During boot, the PCD is updated by PlatformPei
+  #  to reflect the extended TSEG size, if one is advertized by QEMU.
+  #
+  #  This PCD is only accessed if PcdSmmSmramRequire is TRUE (see below).
+  gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes|8|UINT16|0x20
+
+[PcdsFeatureFlag]
+  gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0x1c
+  gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN|0x1d
+
+  ## This feature flag enables SMM/SMRAM support. Note that it also requires
+  #  such support from the underlying QEMU instance; if that support is not
+  #  present, the firmware will reject continuing after a certain point.
+  #
+  #  The flag also acts as a general "security switch"; when TRUE, many
+  #  components will change behavior, with the goal of preventing a malicious
+  #  runtime OS from tampering with firmware structures (special memory ranges
+  #  used by OVMF, the varstore pflash chip, LockBox etc).
+  gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire|FALSE|BOOLEAN|0x1e
+
+[Protocols]
+gEfiLegacyBiosProtocolGuid          = {0xdb9a1e3d, 0x45cb, 0x4abb, {0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d}}
diff --git a/BhyvePkg/BhyvePkg.fdf.inc b/BhyvePkg/BhyvePkg.fdf.inc
new file mode 100644
index 0000000000..c3c2ab5292
--- /dev/null
+++ b/BhyvePkg/BhyvePkg.fdf.inc
@@ -0,0 +1,85 @@
+## @file
+#  FDF include file that defines the main macros and sets the dependent PCDs.
+#
+#  Copyright (C) 2014, Red Hat, Inc.
+#  Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+DEFINE BLOCK_SIZE        = 0x1000
+
+#
+# A firmware binary built with FD_SIZE_IN_KB=1024, and a firmware binary built
+# with FD_SIZE_IN_KB=2048, use the same variable store layout.
+#
+# Setting FD_SIZE_IN_KB to 4096 results in a different (much larger) variable
+# store structure that is incompatible with both of the above-mentioned
+# firmware binaries.
+#
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+DEFINE VARS_SIZE         = 0x20000
+DEFINE VARS_BLOCKS       = 0x20
+DEFINE VARS_LIVE_SIZE    = 0xE000
+DEFINE VARS_SPARE_SIZE   = 0x10000
+!endif
+
+!if $(FD_SIZE_IN_KB) == 1024
+DEFINE FW_BASE_ADDRESS   = 0xFFF00000
+DEFINE FW_SIZE           = 0x00100000
+DEFINE FW_BLOCKS         = 0x100
+DEFINE CODE_BASE_ADDRESS = 0xFFF20000
+DEFINE CODE_SIZE         = 0x000E0000
+DEFINE CODE_BLOCKS       = 0xE0
+DEFINE FVMAIN_SIZE       = 0x000CC000
+DEFINE SECFV_OFFSET      = 0x000EC000
+DEFINE SECFV_SIZE        = 0x14000
+!endif
+
+!if $(FD_SIZE_IN_KB) == 2048
+DEFINE FW_BASE_ADDRESS   = 0xFFE00000
+DEFINE FW_SIZE           = 0x00200000
+DEFINE FW_BLOCKS         = 0x200
+DEFINE CODE_BASE_ADDRESS = 0xFFE20000
+DEFINE CODE_SIZE         = 0x001E0000
+DEFINE CODE_BLOCKS       = 0x1E0
+DEFINE FVMAIN_SIZE       = 0x001AC000
+DEFINE SECFV_OFFSET      = 0x001CC000
+DEFINE SECFV_SIZE        = 0x34000
+!endif
+
+!if $(FD_SIZE_IN_KB) == 4096
+DEFINE VARS_SIZE         = 0x84000
+DEFINE VARS_BLOCKS       = 0x84
+DEFINE VARS_LIVE_SIZE    = 0x40000
+DEFINE VARS_SPARE_SIZE   = 0x42000
+
+DEFINE FW_BASE_ADDRESS   = 0xFFC00000
+DEFINE FW_SIZE           = 0x00400000
+DEFINE FW_BLOCKS         = 0x400
+DEFINE CODE_BASE_ADDRESS = 0xFFC84000
+DEFINE CODE_SIZE         = 0x0037C000
+DEFINE CODE_BLOCKS       = 0x37C
+DEFINE FVMAIN_SIZE       = 0x00348000
+DEFINE SECFV_OFFSET      = 0x003CC000
+DEFINE SECFV_SIZE        = 0x34000
+!endif
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress     = $(FW_BASE_ADDRESS)
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize    = $(FW_SIZE)
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareBlockSize = $(BLOCK_SIZE)
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase = $(FW_BASE_ADDRESS)
+SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize = $(VARS_LIVE_SIZE)
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase = gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize = $(BLOCK_SIZE)
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase = gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize
+SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize = $(BLOCK_SIZE)
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwSpareBase = gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize = $(VARS_SPARE_SIZE)
+
+DEFINE MEMFD_BASE_ADDRESS = 0x800000
diff --git a/BhyvePkg/BhyvePkgX64.dsc b/BhyvePkg/BhyvePkgX64.dsc
new file mode 100644
index 0000000000..51e565994c
--- /dev/null
+++ b/BhyvePkg/BhyvePkgX64.dsc
@@ -0,0 +1,846 @@
+#
+#  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+#  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+#  Copyright (c) 2014, Pluribus Networks, Inc.
+#
+#  SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+  PLATFORM_NAME                  = Bhyve
+  PLATFORM_GUID                  = 562b76ee-ceb2-4f4f-adfe-a4c8dc46e4ff
+  PLATFORM_VERSION               = 0.1
+  DSC_SPECIFICATION              = 0x00010005
+  OUTPUT_DIRECTORY               = Build/BhyveX64
+  SUPPORTED_ARCHITECTURES        = X64
+  BUILD_TARGETS                  = NOOPT|DEBUG|RELEASE
+  SKUID_IDENTIFIER               = DEFAULT
+  FLASH_DEFINITION               = BhyvePkg/BhyvePkgX64.fdf
+
+  #
+  # Defines for default states.  These can be changed on the command line.
+  # -D FLAG=VALUE
+  #
+  DEFINE SECURE_BOOT_ENABLE      = FALSE
+  DEFINE SMM_REQUIRE             = FALSE
+  DEFINE SOURCE_DEBUG_ENABLE     = FALSE
+  DEFINE TPM_ENABLE              = FALSE
+  DEFINE TPM_CONFIG_ENABLE       = FALSE
+
+  #
+  # Network definition
+  #
+  DEFINE NETWORK_TLS_ENABLE             = FALSE
+  DEFINE NETWORK_IP6_ENABLE             = FALSE
+  DEFINE NETWORK_HTTP_BOOT_ENABLE       = FALSE
+  DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE
+
+!include NetworkPkg/NetworkDefines.dsc.inc
+
+  #
+  # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
+  # one of the supported values, in place of any of the convenience macros, is
+  # permitted.
+  #
+!ifdef $(FD_SIZE_1MB)
+  DEFINE FD_SIZE_IN_KB           = 1024
+!else
+!ifdef $(FD_SIZE_2MB)
+  DEFINE FD_SIZE_IN_KB           = 2048
+!else
+!ifdef $(FD_SIZE_4MB)
+  DEFINE FD_SIZE_IN_KB           = 4096
+!else
+  DEFINE FD_SIZE_IN_KB           = 4096
+!endif
+!endif
+!endif
+
+[BuildOptions]
+  GCC:RELEASE_*_*_CC_FLAGS             = -DMDEPKG_NDEBUG
+  INTEL:RELEASE_*_*_CC_FLAGS           = /D MDEPKG_NDEBUG
+  MSFT:RELEASE_*_*_CC_FLAGS            = /D MDEPKG_NDEBUG
+!if $(TOOL_CHAIN_TAG) != "XCODE5" && $(TOOL_CHAIN_TAG) != "CLANGPDB"
+  GCC:*_*_*_CC_FLAGS                   = -mno-mmx -mno-sse
+!endif
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+  MSFT:*_*_X64_GENFW_FLAGS  = --keepexceptiontable
+  GCC:*_*_X64_GENFW_FLAGS   = --keepexceptiontable
+  INTEL:*_*_X64_GENFW_FLAGS = --keepexceptiontable
+!endif
+
+  #
+  # Disable deprecated APIs.
+  #
+  MSFT:*_*_*_CC_FLAGS = /D DISABLE_NEW_DEPRECATED_INTERFACES
+  INTEL:*_*_*_CC_FLAGS = /D DISABLE_NEW_DEPRECATED_INTERFACES
+  GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+
+[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER]
+  GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
+  XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
+  XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
+  CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
+
+# Force PE/COFF sections to be aligned at 4KB boundaries to support page level
+# protection of DXE_SMM_DRIVER/SMM_CORE modules
+[BuildOptions.common.EDKII.DXE_SMM_DRIVER, BuildOptions.common.EDKII.SMM_CORE]
+  GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000
+  XCODE:*_*_*_DLINK_FLAGS = -seg1addr 0x1000 -segalign 0x1000
+  XCODE:*_*_*_MTOC_FLAGS = -align 0x1000
+  CLANGPDB:*_*_*_DLINK_FLAGS = /ALIGN:4096
+
+################################################################################
+#
+# SKU Identification section - list of all SKU IDs supported by this Platform.
+#
+################################################################################
+[SkuIds]
+  0|DEFAULT
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this Platform.
+#
+################################################################################
+[LibraryClasses]
+  PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf
+  PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+  BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+  BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+  SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+  BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
+  SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+  CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+  PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+  UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+  UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+  HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+  SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+  UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+  BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
+  FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+  CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+  DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+  DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+  PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+  PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+  PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
+  PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
+  PciCapLib|OvmfPkg/Library/BasePciCapLib/BasePciCapLib.inf
+  PciCapPciSegmentLib|OvmfPkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.inf
+  PciCapPciIoLib|OvmfPkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.inf
+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf
+  OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+  SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
+  MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+  UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+  UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+  UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+  UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+  UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+  DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf
+  NvVarsFileLib|OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.inf
+  FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+  UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+  SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
+  SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
+  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf
+  QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf
+  BhyveFwCtlLib|BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
+  VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
+  MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
+  LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
+
+  CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
+  FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
+
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+  PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+  DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
+!else
+  PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+  DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+!endif
+
+  ResetSystemLib|OvmfPkg/Library/ResetSystemLib/ResetSystemLib.inf
+  LocalApicLib|UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
+  IoApicLib|PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf
+  DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+
+  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+!if $(NETWORK_TLS_ENABLE) == TRUE
+  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
+!else
+  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
+!endif
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+  PlatformSecureLib|BhyvePkg/Library/PlatformSecureLib/PlatformSecureLib.inf
+  AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+!else
+  AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
+!endif
+  VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+
+
+  #
+  # Network libraries
+  #
+!include NetworkPkg/NetworkLibs.dsc.inc
+
+!if $(NETWORK_TLS_ENABLE) == TRUE
+  TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
+!endif
+
+  ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+  ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
+  S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
+  SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf
+  OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
+  XenPlatformLib|OvmfPkg/Library/XenPlatformLib/XenPlatformLib.inf
+
+
+!if $(TPM_ENABLE) == TRUE
+  Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
+  Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf
+  Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf
+  TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
+!else
+  Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibNull/DxeTcg2PhysicalPresenceLib.inf
+  TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+!endif
+
+[LibraryClasses.common]
+  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+
+[LibraryClasses.common.SEC]
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+  DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
+!endif
+  ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+  ExtractGuidedSectionLib|MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+  DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+!endif
+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+  PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+  CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+
+[LibraryClasses.common.PEI_CORE]
+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+  PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+  PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+  ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+  OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+  DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+
+[LibraryClasses.common.PEIM]
+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+  PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+  ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+  OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+  PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+  DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+  PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+  ResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
+  ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+  DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+!endif
+  CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
+  PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+
+!if $(TPM_ENABLE) == TRUE
+  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
+  Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
+!endif
+
+[LibraryClasses.common.DXE_CORE]
+  HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
+  DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+  MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
+  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+  DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+  ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+  DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+  CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+  ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+  DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+  UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+  PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+[LibraryClasses.common.UEFI_DRIVER]
+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+  DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+  UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+  PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+  UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+  DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+  PlatformBootManagerLib|BhyvePkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+  PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf
+  CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+  LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxDxeLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+  DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+  PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+  MpInitLib|UefiCpuPkg/Library/MpInitLibUp/MpInitLibUp.inf
+!if $(TPM_ENABLE) == TRUE
+  Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf
+!endif
+
+[LibraryClasses.common.UEFI_APPLICATION]
+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+  DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+  PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+[LibraryClasses.common.DXE_SMM_DRIVER]
+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
+  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
+  MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf
+  SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+  DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+  CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+  DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
+!endif
+  BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+  PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+[LibraryClasses.common.SMM_CORE]
+  PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  SmmCorePlatformHookLib|MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
+  MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
+  ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+  HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+  SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
+  SmmServicesTableLib|MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+  DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+  DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+  PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform.
+#
+################################################################################
+[PcdsFeatureFlag]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport|FALSE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE
+
+[PcdsFixedAtBuild]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1
+  gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
+  gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
+!if $(NETWORK_TLS_ENABLE) == FALSE
+  # match PcdFlashNvStorageVariableSize purely for convenience
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000
+!endif
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8400
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8400
+!if $(NETWORK_TLS_ENABLE) == FALSE
+  # match PcdFlashNvStorageVariableSize purely for convenience
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x40000
+!endif
+!endif
+!if $(NETWORK_TLS_ENABLE) == TRUE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x80000
+  gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVolatileVariableSize|0x40000
+!endif
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
+
+  gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
+
+  # DEBUG_INIT      0x00000001  // Initialization
+  # DEBUG_WARN      0x00000002  // Warnings
+  # DEBUG_LOAD      0x00000004  // Load events
+  # DEBUG_FS        0x00000008  // EFI File system
+  # DEBUG_POOL      0x00000010  // Alloc & Free (pool)
+  # DEBUG_PAGE      0x00000020  // Alloc & Free (page)
+  # DEBUG_INFO      0x00000040  // Informational debug messages
+  # DEBUG_DISPATCH  0x00000080  // PEI/DXE/SMM Dispatchers
+  # DEBUG_VARIABLE  0x00000100  // Variable
+  # DEBUG_BM        0x00000400  // Boot Manager
+  # DEBUG_BLKIO     0x00001000  // BlkIo Driver
+  # DEBUG_NET       0x00004000  // SNP Driver
+  # DEBUG_UNDI      0x00010000  // UNDI Driver
+  # DEBUG_LOADFILE  0x00020000  // LoadFile
+  # DEBUG_EVENT     0x00080000  // Event messages
+  # DEBUG_GCD       0x00100000  // Global Coherency Database changes
+  # DEBUG_CACHE     0x00200000  // Memory range cachability changes
+  # DEBUG_VERBOSE   0x00400000  // Detailed debug messages that may
+  #                             // significantly impact boot performance
+  # DEBUG_ERROR     0x80000000  // Error
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
+
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
+!else
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
+!endif
+
+  # This PCD is used to set the base address of the PCI express hierarchy. It
+  # is only consulted when OVMF runs on Q35. In that case it is programmed into
+  # the PCIEXBAR register.
+  #
+  # On Q35 machine types that QEMU intends to support in the long term, QEMU
+  # never lets the RAM below 4 GB exceed 2816 MB.
+  gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xB0000000
+
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+  gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2
+!endif
+
+  #
+  # Network Pcds
+  #
+!include NetworkPkg/NetworkPcds.dsc.inc
+
+  # Point to the MdeModulePkg/Application/UiApp/UiApp.inf
+  gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand|FALSE
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|L"BHYVE"
+
+################################################################################
+#
+# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsDynamicDefault]
+  # only set when
+  #   ($(SMM_REQUIRE) == FALSE)
+  gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0
+  gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|TRUE
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|800
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|600
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable|FALSE
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId|0
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase|0x0
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize|0x0
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base|0x0
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size|0x0
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base|0x0
+  gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size|0x800000000
+
+  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0
+
+  # Set video resolution for text setup.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|640
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|480
+
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0208
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosDocRev|0x0
+  gUefiOvmfPkgTokenSpaceGuid.PcdQemuSmbiosValidated|FALSE
+
+  # Noexec settings for DXE.
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack|FALSE
+
+  # UefiCpuPkg PCDs related to initial AP bringup and general AP management.
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|64
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds|50000
+
+  # Set memory encryption mask
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0
+
+  gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x00
+
+!if $(TPM_ENABLE) == TRUE
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+!endif
+
+  # MdeModulePkg resolution sets up the system display resolution
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|0
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|0
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|0
+  gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|0
+
+[PcdsDynamicHii]
+!if $(TPM_ENABLE) == TRUE && $(TPM_CONFIG_ENABLE) == TRUE
+  gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x0|"1.3"|NV,BS
+  gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x8|3|NV,BS
+!endif
+
+################################################################################
+#
+# Components Section - list of all EDK II Modules needed by this Platform.
+#
+################################################################################
+[Components]
+  OvmfPkg/ResetVector/ResetVector.inf
+
+  #
+  # SEC Phase modules
+  #
+  OvmfPkg/Sec/SecMain.inf {
+    <LibraryClasses>
+      NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+  }
+
+  #
+  # PEI Phase modules
+  #
+  MdeModulePkg/Core/Pei/PeiMain.inf
+  MdeModulePkg/Universal/PCD/Pei/Pcd.inf  {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  }
+  MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  }
+  MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  }
+  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+
+  BhyvePkg/PlatformPei/PlatformPei.inf
+  UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf {
+    <LibraryClasses>
+  }
+
+!if $(TPM_ENABLE) == TRUE
+  BhyvePkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
+  SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf {
+    <LibraryClasses>
+      HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf
+      NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf
+      NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf
+      NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf
+      NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf
+      NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf
+  }
+!endif
+
+  #
+  # DXE Phase modules
+  #
+  MdeModulePkg/Core/Dxe/DxeMain.inf {
+    <LibraryClasses>
+      NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+      DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+  }
+
+  MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+  MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf  {
+   <LibraryClasses>
+      PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  }
+
+  MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+
+  MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf {
+    <LibraryClasses>
+!if $(SECURE_BOOT_ENABLE) == TRUE
+      NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
+!endif
+!if $(TPM_ENABLE) == TRUE
+      NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
+!endif
+  }
+
+  MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+  UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+  UefiCpuPkg/CpuDxe/CpuDxe.inf
+  PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf
+  OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf
+  OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf
+  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
+    <LibraryClasses>
+      PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+      NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
+  }
+  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  }
+  MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+  MdeModulePkg/Universal/Metronome/Metronome.inf
+  PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
+  MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
+  MdeModulePkg/Universal/BdsDxe/BdsDxe.inf {
+    <LibraryClasses>
+!ifdef $(CSM_ENABLE)
+      NULL|BhyvePkg/Csm/CsmSupportLib/CsmSupportLib.inf
+      NULL|OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf
+!endif
+  }
+  MdeModulePkg/Logo/LogoDxe.inf
+  MdeModulePkg/Application/UiApp/UiApp.inf {
+    <LibraryClasses>
+      NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+      NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
+      NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
+!ifdef $(CSM_ENABLE)
+      NULL|OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf
+      NULL|OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf
+!endif
+  }
+  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+  OvmfPkg/Virtio10Dxe/Virtio10.inf
+  OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+  OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
+  OvmfPkg/VirtioRngDxe/VirtioRng.inf
+  MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+  MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+  MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+  MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+  MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  }
+  MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf {
+    <LibraryClasses>
+      DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+      PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+  }
+  MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+  MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+  MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+  MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
+  MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+  FatPkg/EnhancedFatDxe/Fat.inf
+  MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+  OvmfPkg/SataControllerDxe/SataControllerDxe.inf
+  MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+  MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+  MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
+  MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+  MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+  MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+  MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+
+  BhyvePkg/BhyveRfbDxe/BhyveRfbDxe.inf {
+    <LibraryClasses>
+      BltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  }
+
+  #
+  # ISA Support
+  #
+  OvmfPkg/SioBusDxe/SioBusDxe.inf
+  MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf
+  MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
+  MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
+
+  #
+  # SMBIOS Support
+  #
+  MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+  BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+
+  #
+  # ACPI Support
+  #
+  MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+  BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
+  BhyvePkg/AcpiTables/AcpiTables.inf
+  MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
+  MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
+  MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
+
+  #
+  # Network Support
+  #
+!include NetworkPkg/NetworkComponents.dsc.inc
+
+!if $(NETWORK_TLS_ENABLE) == TRUE
+  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf {
+    <LibraryClasses>
+      NULL|BhyvePkg/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf
+  }
+!endif
+  OvmfPkg/VirtioNetDxe/VirtioNet.inf
+
+!ifdef $(CSM_ENABLE)
+  IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf {
+    <LibraryClasses>
+      PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+  }
+!endif
+#  OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf
+!ifdef $(CSM_ENABLE)
+  BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.inf
+!endif
+
+!if $(TOOL_CHAIN_TAG) != "XCODE5"
+  ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf {
+    <PcdsFixedAtBuild>
+      gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+  }
+!endif
+  ShellPkg/Application/Shell/Shell.inf {
+    <LibraryClasses>
+      ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
+      NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
+      NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
+      NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
+      NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
+      NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
+      NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
+      NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
+!if $(NETWORK_IP6_ENABLE) == TRUE
+      NULL|ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf
+!endif
+      HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+      PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+      BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
+
+    <PcdsFixedAtBuild>
+      gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF
+      gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+      gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
+  }
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+  OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf
+!endif
+
+  OvmfPkg/PlatformDxe/Platform.inf
+  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+  OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+
+
+  #
+  # Variable driver stack (non-SMM)
+  #
+  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+  OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
+    <LibraryClasses>
+      PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf
+  }
+  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
+    <LibraryClasses>
+      NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+  }
+
+
+  #
+  # TPM support
+  #
+!if $(TPM_ENABLE) == TRUE
+  SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf {
+    <LibraryClasses>
+      Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf
+      NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf
+      HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf
+      NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf
+      NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf
+      NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf
+      NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf
+      NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf
+  }
+!if $(TPM_CONFIG_ENABLE) == TRUE
+  SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
+!endif
+!endif
diff --git a/BhyvePkg/BhyvePkgX64.fdf b/BhyvePkg/BhyvePkgX64.fdf
new file mode 100644
index 0000000000..1b6764a1f2
--- /dev/null
+++ b/BhyvePkg/BhyvePkgX64.fdf
@@ -0,0 +1,513 @@
+#
+#  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+#  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+#  Copyright (c) 2014, Pluribus Networks, Inc.
+#
+#  SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+################################################################################
+
+[Defines]
+!include BhyvePkg.fdf.inc
+
+#
+# Build the variable store and the firmware code as one unified flash device
+# image.
+#
+[FD.BHYVE]
+BaseAddress   = $(FW_BASE_ADDRESS)
+Size          = $(FW_SIZE)
+ErasePolarity = 1
+BlockSize     = $(BLOCK_SIZE)
+NumBlocks     = $(FW_BLOCKS)
+
+!include VarStore.fdf.inc
+
+$(VARS_SIZE)|$(FVMAIN_SIZE)
+FV = FVMAIN_COMPACT
+
+$(SECFV_OFFSET)|$(SECFV_SIZE)
+FV = SECFV
+
+#
+# Build the variable store and the firmware code as separate flash device
+# images.
+#
+[FD.BHYVE_VARS]
+BaseAddress   = $(FW_BASE_ADDRESS)
+Size          = $(VARS_SIZE)
+ErasePolarity = 1
+BlockSize     = $(BLOCK_SIZE)
+NumBlocks     = $(VARS_BLOCKS)
+
+!include VarStore.fdf.inc
+
+[FD.BHYVE_CODE]
+BaseAddress   = $(CODE_BASE_ADDRESS)
+Size          = $(CODE_SIZE)
+ErasePolarity = 1
+BlockSize     = $(BLOCK_SIZE)
+NumBlocks     = $(CODE_BLOCKS)
+
+0x00000000|$(FVMAIN_SIZE)
+FV = FVMAIN_COMPACT
+
+$(FVMAIN_SIZE)|$(SECFV_SIZE)
+FV = SECFV
+
+################################################################################
+
+[FD.MEMFD]
+BaseAddress   = $(MEMFD_BASE_ADDRESS)
+Size          = 0xC00000
+ErasePolarity = 1
+BlockSize     = 0x10000
+NumBlocks     = 0xC0
+
+0x000000|0x006000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
+
+0x006000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize
+
+0x007000|0x001000
+gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+
+0x010000|0x010000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
+
+0x020000|0x0E0000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
+FV = PEIFV
+
+0x100000|0xB00000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
+FV = DXEFV
+
+################################################################################
+
+[FV.SECFV]
+FvNameGuid         = 763BED0D-DE9F-48F5-81F1-3E90E1B1A015
+BlockSize          = 0x1000
+FvAlignment        = 16
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+#
+# SEC Phase modules
+#
+# The code in this FV handles the initial firmware startup, and
+# decompresses the PEI and DXE FVs which handles the rest of the boot sequence.
+#
+INF  OvmfPkg/Sec/SecMain.inf
+
+INF  RuleOverride=RESET_VECTOR OvmfPkg/ResetVector/ResetVector.inf
+
+################################################################################
+[FV.PEIFV]
+FvNameGuid         = 6938079B-B503-4E3D-9D24-B28337A25806
+BlockSize          = 0x10000
+FvAlignment        = 16
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+APRIORI PEI {
+  INF  MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+}
+
+#
+#  PEI Phase modules
+#
+INF  MdeModulePkg/Core/Pei/PeiMain.inf
+INF  MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+INF  MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+INF  MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+INF  BhyvePkg/PlatformPei/PlatformPei.inf
+INF  MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+INF  UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+!if $(SMM_REQUIRE) == TRUE
+INF  BhyvePkg/SmmAccess/SmmAccessPei.inf
+!endif
+
+!if $(TPM2_ENABLE) == TRUE
+INF  BhyvePkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
+INF  SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
+!endif
+
+################################################################################
+
+[FV.DXEFV]
+FvForceRebase      = FALSE
+FvNameGuid         = 7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1
+BlockSize          = 0x10000
+FvAlignment        = 16
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+APRIORI DXE {
+  INF  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+  INF  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+  INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+!if $(SMM_REQUIRE) == FALSE
+  INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+!endif
+}
+
+#
+# DXE Phase modules
+#
+INF  MdeModulePkg/Core/Dxe/DxeMain.inf
+
+INF  MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+INF  MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+INF  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+
+INF  MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+INF  MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+INF  MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+INF  UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+INF  UefiCpuPkg/CpuDxe/CpuDxe.inf
+INF  PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf
+INF  OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf
+INF  OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf
+INF  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
+INF  MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+INF  MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+INF  MdeModulePkg/Universal/Metronome/Metronome.inf
+INF  PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
+
+INF  OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+INF  OvmfPkg/Virtio10Dxe/Virtio10.inf
+INF  OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+INF  OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
+INF  OvmfPkg/VirtioRngDxe/VirtioRng.inf
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+  INF  SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+!endif
+
+INF  MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+INF  MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+INF  MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+INF  MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+INF  MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+INF  MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+INF  MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+INF  MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
+INF  MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+INF  MdeModulePkg/Application/UiApp/UiApp.inf
+INF  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+INF  MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+INF  MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+INF  MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+INF  MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
+INF  MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+INF  MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+INF  MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+INF  OvmfPkg/SataControllerDxe/SataControllerDxe.inf
+INF  MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+INF  MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+INF  MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
+INF  MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+INF  MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+INF  MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+INF  MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+
+
+INF  OvmfPkg/SioBusDxe/SioBusDxe.inf
+INF  MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf
+INF  MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
+INF  MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
+
+INF  MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+INF  BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+
+INF  MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+INF  BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
+INF  RuleOverride=ACPITABLE BhyvePkg/AcpiTables/AcpiTables.inf
+INF  MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
+INF  MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
+INF  MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
+
+INF  FatPkg/EnhancedFatDxe/Fat.inf
+INF  MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+
+!if $(TOOL_CHAIN_TAG) != "XCODE5"
+INF  ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
+!endif
+INF  ShellPkg/Application/Shell/Shell.inf
+
+INF MdeModulePkg/Logo/LogoDxe.inf
+
+#
+# Network modules
+#
+!if $(E1000_ENABLE)
+  FILE DRIVER = 5D695E11-9B3F-4b83-B25F-4A8D5D69BE07 {
+    SECTION PE32 = Intel3.5/EFIX64/E3522X2.EFI
+  }
+!endif
+  INF  NetworkPkg/SnpDxe/SnpDxe.inf
+  INF  NetworkPkg/DpcDxe/DpcDxe.inf
+  INF  NetworkPkg/MnpDxe/MnpDxe.inf
+  INF  NetworkPkg/VlanConfigDxe/VlanConfigDxe.inf
+  INF  NetworkPkg/ArpDxe/ArpDxe.inf
+  INF  NetworkPkg/Dhcp4Dxe/Dhcp4Dxe.inf
+  INF  NetworkPkg/Ip4Dxe/Ip4Dxe.inf
+  INF  NetworkPkg/Mtftp4Dxe/Mtftp4Dxe.inf
+  INF  NetworkPkg/Udp4Dxe/Udp4Dxe.inf
+  INF  NetworkPkg/UefiPxeBcDxe/UefiPxeBcDxe.inf
+  INF  NetworkPkg/TcpDxe/TcpDxe.inf
+  INF  NetworkPkg/IScsiDxe/IScsiDxe.inf
+!if $(NETWORK_IP6_ENABLE) == TRUE
+  INF  NetworkPkg/Ip6Dxe/Ip6Dxe.inf
+  INF  NetworkPkg/Udp6Dxe/Udp6Dxe.inf
+  INF  NetworkPkg/Dhcp6Dxe/Dhcp6Dxe.inf
+  INF  NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf
+!endif
+!if $(HTTP_BOOT_ENABLE) == TRUE
+  INF  NetworkPkg/DnsDxe/DnsDxe.inf
+  INF  NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
+  INF  NetworkPkg/HttpDxe/HttpDxe.inf
+  INF  NetworkPkg/HttpBootDxe/HttpBootDxe.inf
+!endif
+!if $(TLS_ENABLE) == TRUE
+  INF  NetworkPkg/TlsDxe/TlsDxe.inf
+  INF  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
+!endif
+  INF  OvmfPkg/VirtioNetDxe/VirtioNet.inf
+
+!ifdef $(CSM_ENABLE)
+INF  IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf
+!endif
+#INF  OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf
+!ifdef $(CSM_ENABLE)
+INF  RuleOverride=CSM BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.inf
+!endif
+
+INF  OvmfPkg/PlatformDxe/Platform.inf
+INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+INF  OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+INF  BhyvePkg/BhyveRfbDxe/BhyveRfbDxe.inf
+
+!if $(SMM_REQUIRE) == TRUE
+INF  BhyvePkg/SmmAccess/SmmAccess2Dxe.inf
+INF  BhyvePkg/SmmControl2Dxe/SmmControl2Dxe.inf
+INF  UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf
+INF  MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
+INF  MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
+INF  UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf
+INF  MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf
+INF  UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+
+#
+# Variable driver stack (SMM)
+#
+INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf
+INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
+INF  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
+INF  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
+
+!else
+
+#
+# Variable driver stack (non-SMM)
+#
+INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+INF  OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
+INF  MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+INF  MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+!endif
+
+!if $(TPM2_ENABLE) == TRUE
+INF  SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
+!if $(TPM2_CONFIG_ENABLE) == TRUE
+INF  SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
+!endif
+!endif
+
+################################################################################
+
+[FV.FVMAIN_COMPACT]
+FvNameGuid         = 48DB5E17-707C-472D-91CD-1613E7EF51B0
+FvAlignment        = 16
+ERASE_POLARITY     = 1
+MEMORY_MAPPED      = TRUE
+STICKY_WRITE       = TRUE
+LOCK_CAP           = TRUE
+LOCK_STATUS        = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP  = TRUE
+WRITE_STATUS       = TRUE
+WRITE_LOCK_CAP     = TRUE
+WRITE_LOCK_STATUS  = TRUE
+READ_DISABLED_CAP  = TRUE
+READ_ENABLED_CAP   = TRUE
+READ_STATUS        = TRUE
+READ_LOCK_CAP      = TRUE
+READ_LOCK_STATUS   = TRUE
+
+FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
+   SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
+     #
+     # These firmware volumes will have files placed in them uncompressed,
+     # and then both firmware volumes will be compressed in a single
+     # compression operation in order to achieve better overall compression.
+     #
+     SECTION FV_IMAGE = PEIFV
+     SECTION FV_IMAGE = DXEFV
+   }
+ }
+
+!include DecomprScratchEnd.fdf.inc
+
+################################################################################
+
+[Rule.Common.SEC]
+  FILE SEC = $(NAMED_GUID) {
+    PE32     PE32           $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING ="$(MODULE_NAME)" Optional
+    VERSION  STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.PEI_CORE]
+  FILE PEI_CORE = $(NAMED_GUID) {
+    PE32     PE32   Align=Auto    $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING ="$(MODULE_NAME)" Optional
+    VERSION  STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.PEIM]
+  FILE PEIM = $(NAMED_GUID) {
+     PEI_DEPEX PEI_DEPEX Optional        $(INF_OUTPUT)/$(MODULE_NAME).depex
+     PE32      PE32   Align=Auto         $(INF_OUTPUT)/$(MODULE_NAME).efi
+     UI       STRING="$(MODULE_NAME)" Optional
+     VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.DXE_CORE]
+  FILE DXE_CORE = $(NAMED_GUID) {
+    PE32     PE32           $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING="$(MODULE_NAME)" Optional
+    VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.DXE_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX Optional      $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING="$(MODULE_NAME)" Optional
+    VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+    RAW ACPI  Optional               |.acpi
+    RAW ASL   Optional               |.aml
+  }
+
+[Rule.Common.DXE_RUNTIME_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX Optional      $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING="$(MODULE_NAME)" Optional
+    VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.UEFI_DRIVER]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX    DXE_DEPEX Optional      $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING="$(MODULE_NAME)" Optional
+    VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.UEFI_DRIVER.BINARY]
+  FILE DRIVER = $(NAMED_GUID) {
+    DXE_DEPEX DXE_DEPEX Optional      |.depex
+    PE32      PE32                    |.efi
+    UI        STRING="$(MODULE_NAME)" Optional
+    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.UEFI_APPLICATION]
+  FILE APPLICATION = $(NAMED_GUID) {
+    PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING="$(MODULE_NAME)" Optional
+    VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.UEFI_APPLICATION.BINARY]
+  FILE APPLICATION = $(NAMED_GUID) {
+    PE32      PE32                    |.efi
+    UI        STRING="$(MODULE_NAME)" Optional
+    VERSION   STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.USER_DEFINED.ACPITABLE]
+  FILE FREEFORM = $(NAMED_GUID) {
+    RAW ACPI               |.acpi
+    RAW ASL                |.aml
+  }
+
+[Rule.Common.USER_DEFINED.CSM]
+  FILE FREEFORM = $(NAMED_GUID) {
+    RAW BIN                |.bin
+  }
+
+[Rule.Common.SEC.RESET_VECTOR]
+  FILE RAW = $(NAMED_GUID) {
+    RAW BIN   Align = 16   |.bin
+  }
+
+[Rule.Common.SMM_CORE]
+  FILE SMM_CORE = $(NAMED_GUID) {
+    PE32     PE32           $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING="$(MODULE_NAME)" Optional
+    VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
+
+[Rule.Common.DXE_SMM_DRIVER]
+  FILE SMM = $(NAMED_GUID) {
+    SMM_DEPEX    SMM_DEPEX Optional      $(INF_OUTPUT)/$(MODULE_NAME).depex
+    PE32     PE32                    $(INF_OUTPUT)/$(MODULE_NAME).efi
+    UI       STRING="$(MODULE_NAME)" Optional
+    VERSION  STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+  }
diff --git a/BhyvePkg/BhyveRfbDxe/BhyveRfbDxe.inf b/BhyvePkg/BhyveRfbDxe/BhyveRfbDxe.inf
new file mode 100644
index 0000000000..64aaf22624
--- /dev/null
+++ b/BhyvePkg/BhyveRfbDxe/BhyveRfbDxe.inf
@@ -0,0 +1,67 @@
+## @file
+# GOP driver
+#
+# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+# Portions copyright (c) 2011, Apple Inc. All rights reserved.
+#
+#  SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = EmuGopDxe
+  FILE_GUID                      = 1b290126-5760-424e-8aa2-3faf4d0d7978
+  MODULE_TYPE                    = UEFI_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = InitializeEmuGop
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+#  DRIVER_BINDING                =  gEmuGopDriverBinding
+#  COMPONENT_NAME                =  gEmuGopComponentName
+#
+
+[Sources]
+  ComponentName.c
+  GopScreen.c
+  GopDriver.c
+  Gop.h
+  VbeShim.c
+
+
+[Packages]
+  MdePkg/MdePkg.dec
+  BhyvePkg/BhyvePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  BltLib
+  DebugLib
+  DevicePathLib
+  MemoryAllocationLib
+  PciLib
+  PcdLib
+  PrintLib
+  UefiLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+
+
+[Protocols]
+  gEfiGraphicsOutputProtocolGuid   # PROTOCOL BY_START
+  gEfiDevicePathProtocolGuid       # PROTOCOL TO_START
+  gEfiPciIoProtocolGuid            # PROTOCOL TO_START
+
+[Pcd]
+#  gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
+  gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
+
diff --git a/BhyvePkg/BhyveRfbDxe/ComponentName.c b/BhyvePkg/BhyveRfbDxe/ComponentName.c
new file mode 100644
index 0000000000..de2640cd33
--- /dev/null
+++ b/BhyvePkg/BhyveRfbDxe/ComponentName.c
@@ -0,0 +1,200 @@
+/** @file
+
+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2010,Apple Inc. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause
+
+Module Name:
+
+  ComponentName.c
+
+Abstract:
+
+**/
+
+#include "Gop.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+EmuGopComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  );
+
+EFI_STATUS
+EFIAPI
+EmuGopComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL     gEmuGopComponentName = {
+  EmuGopComponentNameGetDriverName,
+  EmuGopComponentNameGetControllerName,
+  "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gEmuGopComponentName2 = {
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) EmuGopComponentNameGetDriverName,
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) EmuGopComponentNameGetControllerName,
+  "en"
+};
+
+
+EFI_UNICODE_STRING_TABLE mEmuGopDriverNameTable[] = {
+  { "eng", L"Emulator GOP Driver" },
+  { NULL , NULL }
+};
+
+
+/**
+  Retrieves a Unicode string that is the user readable name of the driver.
+
+  This function retrieves the user readable name of a driver in the form of a
+  Unicode string. If the driver specified by This has a user readable name in
+  the language specified by Language, then a pointer to the driver name is
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+  by This does not support the language specified by Language,
+  then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language. This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified
+                                in RFC 4646 or ISO 639-2 language code format.
+
+  @param  DriverName[out]       A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                driver specified by This in the language
+                                specified by Language.
+
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by
+                                This and the language specified by Language was
+                                returned in DriverName.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuGopComponentNameGetDriverName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,
+  IN  CHAR8                        *Language,
+  OUT CHAR16                       **DriverName
+  )
+{
+  return LookupUnicodeString2 (
+           Language,
+           This->SupportedLanguages,
+           mEmuGopDriverNameTable,
+           DriverName,
+           (BOOLEAN)(This == &gEmuGopComponentName)
+           );
+}
+
+
+/**
+  Retrieves a Unicode string that is the user readable name of the controller
+  that is being managed by a driver.
+
+  This function retrieves the user readable name of the controller specified by
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the
+  driver specified by This has a user readable name in the language specified by
+  Language, then a pointer to the controller name is returned in ControllerName,
+  and EFI_SUCCESS is returned.  If the driver specified by This is not currently
+  managing the controller specified by ControllerHandle and ChildHandle,
+  then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
+  support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+  @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+                                EFI_COMPONENT_NAME_PROTOCOL instance.
+
+  @param  ControllerHandle[in]  The handle of a controller that the driver
+                                specified by This is managing.  This handle
+                                specifies the controller whose name is to be
+                                returned.
+
+  @param  ChildHandle[in]       The handle of the child controller to retrieve
+                                the name of.  This is an optional parameter that
+                                may be NULL.  It will be NULL for device
+                                drivers.  It will also be NULL for a bus drivers
+                                that wish to retrieve the name of the bus
+                                controller.  It will not be NULL for a bus
+                                driver that wishes to retrieve the name of a
+                                child controller.
+
+  @param  Language[in]          A pointer to a Null-terminated ASCII string
+                                array indicating the language.  This is the
+                                language of the driver name that the caller is
+                                requesting, and it must match one of the
+                                languages specified in SupportedLanguages. The
+                                number of languages supported by a driver is up
+                                to the driver writer. Language is specified in
+                                RFC 4646 or ISO 639-2 language code format.
+
+  @param  ControllerName[out]   A pointer to the Unicode string to return.
+                                This Unicode string is the name of the
+                                controller specified by ControllerHandle and
+                                ChildHandle in the language specified by
+                                Language from the point of view of the driver
+                                specified by This.
+
+  @retval EFI_SUCCESS           The Unicode string for the user readable name in
+                                the language specified by Language for the
+                                driver specified by This was returned in
+                                DriverName.
+
+  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+                                EFI_HANDLE.
+
+  @retval EFI_INVALID_PARAMETER Language is NULL.
+
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently
+                                managing the controller specified by
+                                ControllerHandle and ChildHandle.
+
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support
+                                the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuGopComponentNameGetControllerName (
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,
+  IN  EFI_HANDLE                                      ControllerHandle,
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
+  IN  CHAR8                                           *Language,
+  OUT CHAR16                                          **ControllerName
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/BhyvePkg/BhyveRfbDxe/Gop.h b/BhyvePkg/BhyveRfbDxe/Gop.h
new file mode 100644
index 0000000000..47895ce483
--- /dev/null
+++ b/BhyvePkg/BhyveRfbDxe/Gop.h
@@ -0,0 +1,148 @@
+/*++ @file
+
+Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2010,Apple Inc. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+#ifndef __UGA_H_
+#define __UGA_H_
+
+#include <Uefi.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/DriverSupportedEfiVersion.h>
+#include <Protocol/DevicePath.h>
+
+#include <Guid/EventGroup.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+
+#include <IndustryStandard/Pci.h>
+
+#define GRAPHICS_OUTPUT_INVALID_MODE_NUMBER 0xffff
+
+typedef struct {
+  UINT32                     HorizontalResolution;
+  UINT32                     VerticalResolution;
+  UINT32                     ColorDepth;
+  UINT32                     RefreshRate;
+} GOP_MODE_DATA;
+
+#define PIXEL_RED_SHIFT   0
+#define PIXEL_GREEN_SHIFT 3
+#define PIXEL_BLUE_SHIFT  6
+
+#define PIXEL_RED_MASK    (BIT7 | BIT6 | BIT5)
+#define PIXEL_GREEN_MASK  (BIT4 | BIT3 | BIT2)
+#define PIXEL_BLUE_MASK   (BIT1 | BIT0)
+
+#define PIXEL_TO_COLOR_BYTE(pixel, mask, shift) ((UINT8) ((pixel & mask) << shift))
+#define PIXEL_TO_RED_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel, PIXEL_RED_MASK, PIXEL_RED_SHIFT)
+#define PIXEL_TO_GREEN_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel, PIXEL_GREEN_MASK, PIXEL_GREEN_SHIFT)
+#define PIXEL_TO_BLUE_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel, PIXEL_BLUE_MASK, PIXEL_BLUE_SHIFT)
+
+#define RGB_BYTES_TO_PIXEL(Red, Green, Blue) \
+  (UINT8) ( (((Red) >> PIXEL_RED_SHIFT) & PIXEL_RED_MASK) | \
+            (((Green) >> PIXEL_GREEN_SHIFT) & PIXEL_GREEN_MASK) | \
+            (((Blue) >> PIXEL_BLUE_SHIFT) & PIXEL_BLUE_MASK) )
+
+#define PIXEL24_RED_MASK    0x00ff0000
+#define PIXEL24_GREEN_MASK  0x0000ff00
+#define PIXEL24_BLUE_MASK   0x000000ff
+
+extern EFI_DRIVER_BINDING_PROTOCOL gEmuGopDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gEmuGopComponentName;
+
+#define EMU_UGA_CLASS_NAME       L"EmuGopWindow"
+
+#define GOP_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('G', 'o', 'p', 'N')
+typedef struct {
+  UINT64                            Signature;
+
+  EFI_HANDLE                        Handle;
+  EFI_PCI_IO_PROTOCOL               *PciIo;
+  EFI_GRAPHICS_OUTPUT_PROTOCOL      GraphicsOutput;
+  EFI_DEVICE_PATH_PROTOCOL          *GopDevicePath;
+
+  EFI_UNICODE_STRING_TABLE          *ControllerNameTable;
+
+  //
+  // GOP Private Data for QueryMode ()
+  //
+  GOP_MODE_DATA                     *ModeData;
+
+  UINT64                            FbAddr;
+  UINT32                            FbSize;
+} GOP_PRIVATE_DATA;
+
+
+#define GOP_PRIVATE_DATA_FROM_THIS(a)  \
+         CR(a, GOP_PRIVATE_DATA, GraphicsOutput, GOP_PRIVATE_DATA_SIGNATURE)
+
+typedef struct {
+  UINT32            FbSize;
+  UINT16            Width;
+  UINT16            Height;
+  UINT16            Depth;
+  UINT16            RefreshRate;
+} BHYVE_FBUF_MEMREGS;
+
+//
+// Global Protocol Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL  gEmuGopDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL  gEmuGopComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gEmuGopComponentName2;
+
+//
+// Gop Hardware abstraction internal worker functions
+//
+EFI_STATUS
+EmuGopConstructor (
+  IN  GOP_PRIVATE_DATA    *Private
+  );
+
+EFI_STATUS
+EmuGopDestructor (
+  IN  GOP_PRIVATE_DATA    *Private
+  );
+
+VOID
+EFIAPI
+ShutdownGopEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  );
+
+VOID
+BhyveSetGraphicsMode (
+  GOP_PRIVATE_DATA  *Private,
+  UINT16             Width,
+  UINT16             Height,
+  UINT16             Depth
+  );
+
+VOID
+BhyveGetMemregs (
+  GOP_PRIVATE_DATA  *Private,
+  BHYVE_FBUF_MEMREGS *Memregs
+  );
+
+VOID
+InstallVbeShim (
+  IN CONST CHAR16         *CardName,
+  IN EFI_PHYSICAL_ADDRESS FrameBufferBase
+  );
+
+#endif
diff --git a/BhyvePkg/BhyveRfbDxe/GopDriver.c b/BhyvePkg/BhyveRfbDxe/GopDriver.c
new file mode 100644
index 0000000000..3445ce0140
--- /dev/null
+++ b/BhyvePkg/BhyveRfbDxe/GopDriver.c
@@ -0,0 +1,542 @@
+/*++ @file
+
+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2010,Apple Inc. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+#include "Gop.h"
+#include <IndustryStandard/Acpi.h>
+
+STATIC VOID
+BhyveGetGraphicsMode (
+  EFI_PCI_IO_PROTOCOL *PciIo,
+  UINT16              *Width,
+  UINT16              *Height,
+  UINT16              *Depth
+  );
+
+
+/**
+  Tests to see if this driver supports a given controller. If a child device is provided,
+  it further tests to see if this driver supports creating a handle for the specified child device.
+
+  This function checks to see if the driver specified by This supports the device specified by
+  ControllerHandle. Drivers will typically use the device path attached to
+  ControllerHandle and/or the services from the bus I/O abstraction attached to
+  ControllerHandle to determine if the driver supports ControllerHandle. This function
+  may be called many times during platform initialization. In order to reduce boot times, the tests
+  performed by this function must be very small, and take as little time as possible to execute. This
+  function must not change the state of any hardware devices, and this function must be aware that the
+  device specified by ControllerHandle may already be managed by the same driver or a
+  different driver. This function must match its calls to AllocatePages() with FreePages(),
+  AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+  Because ControllerHandle may have been previously started by the same driver, if a protocol is
+  already in the opened state, then it must not be closed with CloseProtocol(). This is required
+  to guarantee the state of ControllerHandle is not modified by this function.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to test. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For bus drivers, if this parameter is not NULL, then
+                                   the bus driver must determine if the bus controller specified
+                                   by ControllerHandle and the child controller specified
+                                   by RemainingDevicePath are both supported by this
+                                   bus driver.
+
+  @retval EFI_SUCCESS              The device specified by ControllerHandle and
+                                   RemainingDevicePath is supported by the driver specified by This.
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by the driver
+                                   specified by This.
+  @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
+                                   RemainingDevicePath is already being managed by a different
+                                   driver or an application that requires exclusive access.
+                                   Currently not implemented.
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
+                                   RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+EmuGopDriverBindingSupported (
+  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
+  IN  EFI_HANDLE                      Handle,
+  IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
+  )
+{
+  EFI_STATUS                Status;
+  EFI_PCI_IO_PROTOCOL       *PciIo;
+  PCI_TYPE00                Pci;
+  UINT16                    Width, Height, Depth;
+
+  //
+  // Open the IO Abstraction(s) needed to perform the supported test
+  //
+  Status = gBS->OpenProtocol (
+                  Handle,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &PciIo,
+                  This->DriverBindingHandle,
+                  Handle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // See if this is a PCI Framebuffer Controller by looking at the Command register and
+  // Class Code Register
+  //
+  Status = PciIo->Pci.Read (
+                        PciIo,
+                        EfiPciIoWidthUint32,
+                        PCI_BAR_IDX0,
+                        sizeof (Pci) / sizeof (UINT32),
+                        &Pci
+                        );
+  if (EFI_ERROR (Status)) {
+    Status = EFI_UNSUPPORTED;
+    goto Done;
+  }
+
+  Status = EFI_UNSUPPORTED;
+  if (Pci.Hdr.VendorId == 0xFB5D && Pci.Hdr.DeviceId == 0x40FB) {
+    DEBUG((DEBUG_INFO, "BHYVE framebuffer device detected\n"));
+    Status = EFI_SUCCESS;
+
+    BhyveGetGraphicsMode(PciIo, &Width, &Height, &Depth);
+    PcdSet32S (PcdVideoHorizontalResolution, Width);
+    PcdSet32S (PcdVideoVerticalResolution, Height);
+  }
+
+Done:
+  //
+  // Close the PCI I/O Protocol
+  //
+  gBS->CloseProtocol (
+        Handle,
+        &gEfiPciIoProtocolGuid,
+        This->DriverBindingHandle,
+        Handle
+        );
+
+  return Status;
+}
+
+
+/**
+  Starts a device controller or a bus controller.
+
+  The Start() function is designed to be invoked from the EFI boot service ConnectController().
+  As a result, much of the error checking on the parameters to Start() has been moved into this
+  common boot service. It is legal to call Start() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE.
+  2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+     EFI_DEVICE_PATH_PROTOCOL.
+  3. Prior to calling Start(), the Supported() function for the driver specified by This must
+     have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle     The handle of the controller to start. This handle
+                                   must support a protocol interface that supplies
+                                   an I/O abstraction to the driver.
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
+                                   parameter is ignored by device drivers, and is optional for bus
+                                   drivers. For a bus driver, if this parameter is NULL, then handles
+                                   for all the children of Controller are created by this driver.
+                                   If this parameter is not NULL and the first Device Path Node is
+                                   not the End of Device Path Node, then only the handle for the
+                                   child device specified by the first Device Path Node of
+                                   RemainingDevicePath is created by this driver.
+                                   If the first Device Path Node of RemainingDevicePath is
+                                   the End of Device Path Node, no child handle is created by this
+                                   driver.
+
+  @retval EFI_SUCCESS              The device was started.
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
+  @retval Others                   The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuGopDriverBindingStart (
+  IN  EFI_DRIVER_BINDING_PROTOCOL     *This,
+  IN  EFI_HANDLE                      Handle,
+  IN  EFI_DEVICE_PATH_PROTOCOL        *RemainingDevicePath
+  )
+{
+  BHYVE_FBUF_MEMREGS      Memregs;
+  GOP_PRIVATE_DATA        *Private;
+  EFI_STATUS              Status;
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;
+
+  //
+  // Allocate Private context data for SGO inteface.
+  //
+  Private = NULL;
+  Status = gBS->AllocatePool (
+                  EfiBootServicesData,
+                  sizeof (GOP_PRIVATE_DATA),
+                  (VOID **)&Private
+                  );
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  // Set up context record
+  //
+  Private->Signature           = GOP_PRIVATE_DATA_SIGNATURE;
+  Private->Handle              = Handle;
+  Private->ControllerNameTable = NULL;
+
+  //
+  // Open PCI I/O Protocol
+  //
+  Status = gBS->OpenProtocol (
+                  Handle,
+                  &gEfiPciIoProtocolGuid,
+                  (VOID **) &Private->PciIo,
+                  This->DriverBindingHandle,
+                  Handle,
+                  EFI_OPEN_PROTOCOL_BY_DRIVER
+                  );
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  //
+  // Check if fbuf mmio BAR is present
+  //
+  MmioDesc = NULL;
+  Status = Private->PciIo->GetBarAttributes (
+                      Private->PciIo,
+                      PCI_BAR_IDX0,
+                      NULL,
+                      (VOID**) &MmioDesc
+                      );
+  if (EFI_ERROR (Status) ||
+      MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
+    DEBUG ((DEBUG_INFO, "BHYVE GOP: No mmio bar\n"));
+  } else {
+    DEBUG ((DEBUG_INFO, "BHYVE GOP: Using mmio bar @ 0x%lx\n",
+            MmioDesc->AddrRangeMin));
+    BhyveGetMemregs(Private, &Memregs);
+    Private->FbSize = Memregs.FbSize;
+  }
+  if (MmioDesc != NULL) {
+    FreePool (MmioDesc);
+  }
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  //
+  // Check if fbuf frame-buffer BAR is present
+  //
+  MmioDesc = NULL;
+  Status = Private->PciIo->GetBarAttributes (
+                      Private->PciIo,
+                      PCI_BAR_IDX1,
+                      NULL,
+                      (VOID**) &MmioDesc
+                      );
+  if (EFI_ERROR (Status) ||
+      MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
+    DEBUG ((DEBUG_INFO, "BHYVE GOP: No frame-buffer bar\n"));
+  } else {
+    DEBUG ((DEBUG_INFO, "BHYVE GOP: Using frame-buffer bar @ 0x%lx\n",
+            MmioDesc->AddrRangeMin));
+    Private->FbAddr = MmioDesc->AddrRangeMin;
+    // XXX assert BAR is >= size
+  }
+
+  if (MmioDesc != NULL) {
+    FreePool (MmioDesc);
+  }
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  DEBUG ((DEBUG_INFO, "BHYVE GOP: Framebuf addr 0x%lx, size %x\n",
+         Private->FbAddr, Private->FbSize));
+
+  Status = EmuGopConstructor (Private);
+  if (EFI_ERROR (Status)) {
+    goto Done;
+  }
+
+  //
+  // Publish the Gop interface to the world
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Private->Handle,
+                  &gEfiGraphicsOutputProtocolGuid,    &Private->GraphicsOutput,
+                  NULL
+                  );
+
+  DEBUG((DEBUG_INFO, "BHYVE framebuffer device started\n"));
+
+  //
+  // Install int10 handler
+  //
+#ifndef CSM_ENABLE
+  InstallVbeShim (L"Framebuffer", Private->FbAddr);
+#endif
+
+Done:
+  if (EFI_ERROR (Status)) {
+    if (Private != NULL) {
+      //
+      // On Error Free back private data
+      //
+      if (Private->ControllerNameTable != NULL) {
+        FreeUnicodeStringTable (Private->ControllerNameTable);
+      }
+
+      gBS->FreePool (Private);
+    }
+  }
+
+  return Status;
+}
+
+
+
+/**
+  Stops a device controller or a bus controller.
+
+  The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+  As a result, much of the error checking on the parameters to Stop() has been moved
+  into this common boot service. It is legal to call Stop() from other locations,
+  but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+     same driver's Start() function.
+  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+     EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+     Start() function, and the Start() function must have called OpenProtocol() on
+     ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+  @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+  @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
+                                support a bus specific I/O protocol for the driver
+                                to use to stop the device.
+  @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
+  @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
+                                if NumberOfChildren is 0.
+
+  @retval EFI_SUCCESS           The device was stopped.
+  @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuGopDriverBindingStop (
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
+  IN  EFI_HANDLE                   Handle,
+  IN  UINTN                        NumberOfChildren,
+  IN  EFI_HANDLE                   *ChildHandleBuffer
+  )
+{
+  EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+  EFI_STATUS                   Status;
+  GOP_PRIVATE_DATA             *Private;
+
+  DEBUG((DEBUG_INFO, "BHYVE framebuffer device stopping\n"));
+
+  Status = gBS->OpenProtocol (
+                  Handle,
+                  &gEfiGraphicsOutputProtocolGuid,
+                  (VOID **)&GraphicsOutput,
+                  This->DriverBindingHandle,
+                  Handle,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    //
+    // If the GOP interface does not exist the driver is not started
+    //
+    return EFI_NOT_STARTED;
+  }
+
+  //
+  // Get our private context information
+  //
+  Private = GOP_PRIVATE_DATA_FROM_THIS (GraphicsOutput);
+
+  //
+  // Remove the SGO interface from the system
+  //
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  Private->Handle,
+                  &gEfiGraphicsOutputProtocolGuid,    &Private->GraphicsOutput,
+                  NULL
+                  );
+  if (!EFI_ERROR (Status)) {
+    //
+    // Shutdown the hardware
+    //
+    Status = EmuGopDestructor (Private);
+    if (EFI_ERROR (Status)) {
+      return EFI_DEVICE_ERROR;
+    }
+
+    gBS->CloseProtocol (
+          Handle,
+          &gEfiPciIoProtocolGuid,
+          This->DriverBindingHandle,
+          Private->Handle
+          );
+
+    //
+    // Free our instance data
+    //
+    FreeUnicodeStringTable (Private->ControllerNameTable);
+
+    gBS->FreePool (Private);
+
+  }
+
+  return Status;
+}
+
+
+///
+/// This protocol provides the services required to determine if a driver supports a given controller.
+/// If a controller is supported, then it also provides routines to start and stop the controller.
+///
+EFI_DRIVER_BINDING_PROTOCOL gEmuGopDriverBinding = {
+  EmuGopDriverBindingSupported,
+  EmuGopDriverBindingStart,
+  EmuGopDriverBindingStop,
+  0xa,
+  NULL,
+  NULL
+};
+
+
+
+/**
+  The user Entry Point for module EmuGop. The user code starts with this function.
+
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
+  @param[in] SystemTable    A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS       The entry point is executed successfully.
+  @retval other             Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeEmuGop (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  EFI_STATUS              Status;
+
+  Status = EfiLibInstallDriverBindingComponentName2 (
+             ImageHandle,
+             SystemTable,
+             &gEmuGopDriverBinding,
+             ImageHandle,
+             &gEmuGopComponentName,
+             &gEmuGopComponentName2
+             );
+  ASSERT_EFI_ERROR (Status);
+
+
+  return Status;
+}
+
+STATIC VOID
+BhyveGetGraphicsMode (
+  EFI_PCI_IO_PROTOCOL *PciIo,
+  UINT16              *Width,
+  UINT16              *Height,
+  UINT16              *Depth
+  )
+{
+  BHYVE_FBUF_MEMREGS BhyveRegs;
+  UINT64       Offset;
+  EFI_STATUS   Status;
+
+
+  Offset = (UINT64)&BhyveRegs.Width - (UINT64)&BhyveRegs;
+
+  Status = PciIo->Mem.Read (
+      PciIo,
+      EfiPciIoWidthUint16,
+      PCI_BAR_IDX0,
+      Offset,
+      3,
+      &BhyveRegs.Width
+      );
+
+  *Width  = BhyveRegs.Width;
+  *Height = BhyveRegs.Height;
+  *Depth  = BhyveRegs.Depth;
+
+  DEBUG ((DEBUG_INFO, "BHYVE Get Graphics Mode: w %d, h %d\n", *Width, *Height));
+
+  ASSERT_EFI_ERROR (Status);
+}
+
+VOID
+BhyveSetGraphicsMode (
+  GOP_PRIVATE_DATA  *Private,
+  UINT16             Width,
+  UINT16             Height,
+  UINT16             Depth
+  )
+{
+  BHYVE_FBUF_MEMREGS BhyveRegs;
+  UINT64       Offset;
+  EFI_STATUS   Status;
+
+  DEBUG ((DEBUG_INFO, "BHYVE Set Graphics Mode: w %d, h %d\n", Width, Height));
+
+  BhyveRegs.Width  = Width;
+  BhyveRegs.Height = Height;
+  BhyveRegs.Depth  = Depth;
+  Offset = (UINT64)&BhyveRegs.Width - (UINT64)&BhyveRegs;
+
+  Status = Private->PciIo->Mem.Write (
+      Private->PciIo,
+      EfiPciIoWidthUint16,
+      PCI_BAR_IDX0,
+      Offset,
+      3,
+      &BhyveRegs.Width
+      );
+  ASSERT_EFI_ERROR (Status);
+}
+
+VOID
+BhyveGetMemregs (
+  GOP_PRIVATE_DATA  *Private,
+  BHYVE_FBUF_MEMREGS *Memregs
+  )
+{
+  EFI_STATUS   Status;
+
+  Status = Private->PciIo->Mem.Read (
+      Private->PciIo,
+      EfiPciIoWidthUint32,
+      PCI_BAR_IDX0,
+      0,
+      3,
+      Memregs
+      );
+  ASSERT_EFI_ERROR (Status);
+
+  DEBUG ((DEBUG_INFO, "BHYVE Get Memregs, size %d width %d height %d\n",
+         Memregs->FbSize, Memregs->Width, Memregs->Height));
+}
diff --git a/BhyvePkg/BhyveRfbDxe/GopScreen.c b/BhyvePkg/BhyveRfbDxe/GopScreen.c
new file mode 100644
index 0000000000..a773b8fc46
--- /dev/null
+++ b/BhyvePkg/BhyveRfbDxe/GopScreen.c
@@ -0,0 +1,392 @@
+/*++ @file
+
+Copyright (c) 2015, Nahanni Systems, Inc.
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2010 - 2011, Apple Inc. All rights reserved.
+
+SPDX-License-Identifier: BSD-2-Clause
+
+Module Name:
+
+    EmuGopScreen.c
+
+Abstract:
+
+  This file produces the graphics abstration of UGA. It is called by
+  EmuGopDriver.c file which deals with the EFI 1.1 driver model.
+  This file just does graphics.
+
+**/
+
+#include "Gop.h"
+#include <Library/FrameBufferBltLib.h>
+
+
+EFI_EVENT               mGopScreenExitBootServicesEvent;
+
+GOP_MODE_DATA mGopModeData[] = {
+    { 0,     0,    32, 0 },    // Filled in with user-spec'd resolution
+    { 1024,  768,  32, 0 },
+    { 800,   600,  32, 0 },
+    { 640,   480,  32, 0 }
+    };
+
+STATIC
+VOID
+BhyveGopCompleteModeInfo (
+  IN  GOP_MODE_DATA  *ModeData,
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info
+  )
+{
+  Info->Version = 0;
+  if (ModeData->ColorDepth == 8) {
+    Info->PixelFormat = PixelBitMask;
+    Info->PixelInformation.RedMask = PIXEL_RED_MASK;
+    Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;
+    Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;
+    Info->PixelInformation.ReservedMask = 0;
+  } else if (ModeData->ColorDepth == 24) {
+    Info->PixelFormat = PixelBitMask;
+    Info->PixelInformation.RedMask = PIXEL24_RED_MASK;
+    Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;
+    Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;
+    Info->PixelInformation.ReservedMask = 0;
+  } else if (ModeData->ColorDepth == 32) {
+    DEBUG ((DEBUG_INFO, "%dx%d PixelBlueGreenRedReserved8BitPerColor\n",
+     ModeData->HorizontalResolution, ModeData->VerticalResolution));
+    Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
+  }
+  Info->PixelsPerScanLine = Info->HorizontalResolution;
+}
+
+
+/**
+  Returns information for an available graphics mode that the graphics device
+  and the set of active video output devices supports.
+
+  @param  This                  The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
+  @param  ModeNumber            The mode number to return information on.
+  @param  SizeOfInfo            A pointer to the size, in bytes, of the Info buffer.
+  @param  Info                  A pointer to callee allocated buffer that returns information about ModeNumber.
+
+  @retval EFI_SUCCESS           Mode information returned.
+  @retval EFI_BUFFER_TOO_SMALL  The Info buffer was too small.
+  @retval EFI_DEVICE_ERROR      A hardware error occurred trying to retrieve the video mode.
+  @retval EFI_NOT_STARTED       Video display is not initialized. Call SetMode ()
+  @retval EFI_INVALID_PARAMETER One of the input args was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuGopQuerytMode (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL          *This,
+  IN  UINT32                                ModeNumber,
+  OUT UINTN                                 *SizeOfInfo,
+  OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  **Info
+  )
+{
+  GOP_PRIVATE_DATA  *Private;
+  GOP_MODE_DATA     *ModeData;
+
+  Private = GOP_PRIVATE_DATA_FROM_THIS (This);
+
+  if (Info == NULL || SizeOfInfo == NULL || (UINTN) ModeNumber >= This->Mode->MaxMode) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+  if (*Info == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+  ModeData = &Private->ModeData[ModeNumber];
+  (*Info)->Version = 0;
+  (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
+  (*Info)->VerticalResolution   = ModeData->VerticalResolution;
+  (*Info)->PixelFormat = PixelBitMask;
+  (*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution;
+  BhyveGopCompleteModeInfo(ModeData, *Info);
+  return EFI_SUCCESS;
+}
+
+
+
+/**
+  Set the video device into the specified mode and clears the visible portions of
+  the output display to black.
+
+  @param  This              The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
+  @param  ModeNumber        Abstraction that defines the current video mode.
+
+  @retval EFI_SUCCESS       The graphics mode specified by ModeNumber was selected.
+  @retval EFI_DEVICE_ERROR  The device had an error and could not complete the request.
+  @retval EFI_UNSUPPORTED   ModeNumber is not supported by this device.
+
+**/
+
+FRAME_BUFFER_CONFIGURE *fbconf;
+
+EFI_STATUS
+EFIAPI
+EmuGopSetMode (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL  *This,
+  IN  UINT32                        ModeNumber
+  )
+{
+  GOP_PRIVATE_DATA                *Private;
+  GOP_MODE_DATA                   *ModeData;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL   Fill;
+  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
+
+  UINTN confsize = 0;
+  fbconf = NULL;
+
+  Private = GOP_PRIVATE_DATA_FROM_THIS (This);
+
+  if (ModeNumber >= This->Mode->MaxMode) {
+    // Tell bhyve that we are switching out of vesa
+    BhyveSetGraphicsMode(Private, 0, 0, 0);
+    return EFI_UNSUPPORTED;
+  }
+
+  DEBUG ((DEBUG_INFO, "BHYVE GopSetMode %d\n", ModeNumber));
+
+  ModeData = &Private->ModeData[ModeNumber];
+  This->Mode->Mode = ModeNumber;
+  Private->GraphicsOutput.Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
+  Private->GraphicsOutput.Mode->Info->VerticalResolution = ModeData->VerticalResolution;
+  Private->GraphicsOutput.Mode->Info->PixelsPerScanLine = ModeData->HorizontalResolution;
+
+  Info = This->Mode->Info;
+  BhyveGopCompleteModeInfo(ModeData, Info);
+
+  This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
+  This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
+  This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+  This->Mode->FrameBufferBase = Private->GraphicsOutput.Mode->FrameBufferBase;
+
+  /*
+  This->Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution
+                                * ((ModeData->ColorDepth + 7) / 8);
+  */
+  This->Mode->FrameBufferSize = Private->FbSize;
+  DEBUG ((DEBUG_INFO, "BHYVE GOP FrameBufferBase: 0x%x, FrameBufferSize: 0x%x\n", This->Mode->FrameBufferBase, This->Mode->FrameBufferSize));
+
+  BhyveSetGraphicsMode(Private, (UINT16)ModeData->HorizontalResolution, (UINT16)ModeData->VerticalResolution, (UINT16)ModeData->ColorDepth);
+
+  RETURN_STATUS ret = FrameBufferBltConfigure (
+    (VOID*)(UINTN) This->Mode->FrameBufferBase,
+    This->Mode->Info, fbconf, &confsize
+    );
+  if (ret == EFI_BUFFER_TOO_SMALL || ret == EFI_INVALID_PARAMETER) {
+          fbconf = AllocatePool(confsize);
+          ret = FrameBufferBltConfigure(
+                         (VOID*)(UINTN)This->Mode->FrameBufferBase,
+                         This->Mode->Info, fbconf, &confsize);
+          ASSERT(ret == EFI_SUCCESS);
+  }
+
+  Fill.Red   = 0;
+  Fill.Green = 0;
+  Fill.Blue  = 0;
+  This->Blt (
+          This,
+          &Fill,
+          EfiBltVideoFill,
+          0,
+          0,
+          0,
+          0,
+          ModeData->HorizontalResolution,
+          ModeData->VerticalResolution,
+          ModeData->HorizontalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+          );
+  return EFI_SUCCESS;
+}
+
+
+
+/**
+  Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer.
+
+  @param  This         Protocol instance pointer.
+  @param  BltBuffer    Buffer containing data to blit into video buffer. This
+                       buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+  @param  BltOperation Operation to perform on BlitBuffer and video memory
+  @param  SourceX      X coordinate of source for the BltBuffer.
+  @param  SourceY      Y coordinate of source for the BltBuffer.
+  @param  DestinationX X coordinate of destination for the BltBuffer.
+  @param  DestinationY Y coordinate of destination for the BltBuffer.
+  @param  Width        Width of rectangle in BltBuffer in pixels.
+  @param  Height       Hight of rectangle in BltBuffer in pixels.
+  @param  Delta        OPTIONAL
+
+  @retval EFI_SUCCESS           The Blt operation completed.
+  @retval EFI_INVALID_PARAMETER BltOperation is not valid.
+  @retval EFI_DEVICE_ERROR      A hardware error occured writting to the video buffer.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuGopBlt (
+  IN  EFI_GRAPHICS_OUTPUT_PROTOCOL            *This,
+  IN  EFI_GRAPHICS_OUTPUT_BLT_PIXEL           *BltBuffer,   OPTIONAL
+  IN  EFI_GRAPHICS_OUTPUT_BLT_OPERATION       BltOperation,
+  IN  UINTN                                   SourceX,
+  IN  UINTN                                   SourceY,
+  IN  UINTN                                   DestinationX,
+  IN  UINTN                                   DestinationY,
+  IN  UINTN                                   Width,
+  IN  UINTN                                   Height,
+  IN  UINTN                                   Delta         OPTIONAL
+  )
+{
+  EFI_TPL           OriginalTPL;
+  EFI_STATUS        Status;
+
+  if ((UINT32)BltOperation >= EfiGraphicsOutputBltOperationMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (Width == 0 || Height == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
+  // We would not want a timer based event (Cursor, ...) to come in while we are
+  // doing this operation.
+  //
+  OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
+
+  switch (BltOperation) {
+  case EfiBltVideoToBltBuffer:
+  case EfiBltBufferToVideo:
+  case EfiBltVideoFill:
+  case EfiBltVideoToVideo:
+    Status = FrameBufferBlt (
+     fbconf,
+      BltBuffer,
+      BltOperation,
+      SourceX,
+      SourceY,
+      DestinationX,
+      DestinationY,
+      Width,
+      Height,
+      Delta
+      );
+    break;
+
+  default:
+    Status = EFI_INVALID_PARAMETER;
+    ASSERT (FALSE);
+  }
+
+  gBS->RestoreTPL (OriginalTPL);
+
+  return Status;
+}
+
+
+//
+// Construction and Destruction functions
+//
+
+EFI_STATUS
+EmuGopConstructor (
+  GOP_PRIVATE_DATA    *Private
+  )
+{
+  // Set mode 0 to be the requested resolution
+  mGopModeData[0].HorizontalResolution = PcdGet32 ( PcdVideoHorizontalResolution);
+  mGopModeData[0].VerticalResolution = PcdGet32 ( PcdVideoVerticalResolution );
+
+  Private->ModeData = mGopModeData;
+
+  Private->GraphicsOutput.QueryMode      = EmuGopQuerytMode;
+  Private->GraphicsOutput.SetMode        = EmuGopSetMode;
+  Private->GraphicsOutput.Blt            = EmuGopBlt;
+
+  //
+  // Allocate buffer for Graphics Output Protocol mode information
+  //
+  Private->GraphicsOutput.Mode = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));
+  if (Private->GraphicsOutput.Mode == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  Private->GraphicsOutput.Mode->Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+  if (Private->GraphicsOutput.Mode->Info == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+
+  DEBUG ((DEBUG_INFO, "BHYVE Gop Constructor\n"));
+
+  Private->GraphicsOutput.Mode->MaxMode = sizeof(mGopModeData) / sizeof(GOP_MODE_DATA);
+  //
+  // Till now, we have no idea about the window size.
+  //
+  Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALID_MODE_NUMBER;
+  Private->GraphicsOutput.Mode->Info->Version = 0;
+  Private->GraphicsOutput.Mode->Info->HorizontalResolution = 0;
+  Private->GraphicsOutput.Mode->Info->VerticalResolution = 0;
+  Private->GraphicsOutput.Mode->Info->PixelFormat = PixelBitMask;
+  Private->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+  Private->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) Private->FbAddr;
+  Private->GraphicsOutput.Mode->FrameBufferSize = Private->FbSize;
+
+  return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+EmuGopDestructor (
+  GOP_PRIVATE_DATA     *Private
+  )
+{
+  //
+  // Free graphics output protocol occupied resource
+  //
+  if (Private->GraphicsOutput.Mode != NULL) {
+    if (Private->GraphicsOutput.Mode->Info != NULL) {
+      FreePool (Private->GraphicsOutput.Mode->Info);
+    }
+    FreePool (Private->GraphicsOutput.Mode);
+    Private->GraphicsOutput.Mode = NULL;
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+VOID
+EFIAPI
+ShutdownGopEvent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+/*++
+
+Routine Description:
+
+  This is the UGA screen's callback notification function for exit-boot-services.
+  All we do here is call EmuGopDestructor().
+
+Arguments:
+
+  Event   - not used
+  Context - pointer to the Private structure.
+
+Returns:
+
+  None.
+
+**/
+{
+  EmuGopDestructor (Context);
+}
+
diff --git a/BhyvePkg/BhyveRfbDxe/VbeShim.asm b/BhyvePkg/BhyveRfbDxe/VbeShim.asm
new file mode 100644
index 0000000000..fabca8c4e2
--- /dev/null
+++ b/BhyvePkg/BhyveRfbDxe/VbeShim.asm
@@ -0,0 +1,341 @@
+;------------------------------------------------------------------------------
+; @file
+; A minimal Int10h stub that allows the Windows 2008 R2 SP1 UEFI guest's buggy,
+; default VGA driver to switch to 1024x768x32.
+;
+; Copyright (C) 2015, Nahanni Systems, Inc.
+; Copyright (C) 2014, Red Hat, Inc.
+; Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause
+;
+;------------------------------------------------------------------------------
+
+; enable this macro for debug messages
+%define DEBUG
+
+%macro DebugLog 1
+%ifdef DEBUG
+  push       si
+  mov        si, %1
+  call       PrintStringSi
+  pop        si
+%endif
+%endmacro
+
+
+BITS 16
+ORG 0
+
+VbeInfo:
+TIMES 256 nop
+
+VbeModeInfo:
+VbeMode1:
+TIMES 50  nop
+VbeMode2:
+TIMES 50  nop
+VbeMode3:
+TIMES 50  nop
+VbeMode4:
+TIMES 50  nop
+TIMES 56  nop  ; filler for 256 bytes
+
+Handler:
+  cmp        ax, 0x4f00
+  je         GetInfo
+  cmp        ax, 0x4f01
+  je         GetModeInfo
+  cmp        ax, 0x4f02
+  je         SetMode
+  cmp        ax, 0x4f03
+  je         GetMode
+  cmp        ax, 0x4f10
+  je         GetPmCapabilities
+  cmp        ax, 0x4f15
+  je         ReadEdid
+  cmp        ah, 0x00
+  je         SetModeLegacy
+  DebugLog   StrUnkownFunction
+Hang:
+  jmp        Hang
+
+
+GetInfo:
+  push       es
+  push       di
+  push       ds
+  push       si
+  push       cx
+
+  DebugLog   StrEnterGetInfo
+
+  ; target (es:di) set on input
+  push       cs
+  pop        ds
+  mov        si, VbeInfo
+  ; source (ds:si) set now
+
+  mov        cx, 256
+  cld
+  rep movsb
+
+  pop        cx
+  pop        si
+  pop        ds
+  pop        di
+  pop        es
+  jmp        Success
+
+
+GetModeInfo:
+  push       es
+  push       di
+  push       ds
+  push       si
+  push       cx
+
+  DebugLog   StrEnterGetModeInfo
+
+  and        cx, ~0x4000 ; clear potentially set LFB bit in mode number
+
+  cmp        cx, 0x013f
+  je         gKnownMode1
+  cmp        cx, 0x0140
+  je         gKnownMode2
+  cmp        cx, 0x0141
+  je         gKnownMode3
+
+  DebugLog   StrUnkownMode
+  jmp        Hang
+gKnownMode1:
+  DebugLog   StrMode1
+  mov        si, VbeMode1
+  jmp        CopyModeInfo
+gKnownMode2:
+  DebugLog   StrMode2
+  mov        si, VbeMode2
+  jmp        CopyModeInfo
+gKnownMode3:
+  DebugLog   StrMode3
+  mov        si, VbeMode3
+  jmp        CopyModeInfo
+gKnownMode4:
+  DebugLog   StrMode4
+  mov        si, VbeMode4
+  jmp        CopyModeInfo
+
+CopyModeInfo:
+  ; target (es:di) set on input
+  push       cs
+  pop        ds
+  ;mov        si, VbeModeInfo
+  ; source (ds:si) set now
+
+  ;mov        cx, 256
+  mov        cx, 50
+  cld
+  rep movsb
+
+  pop        cx
+  pop        si
+  pop        ds
+  pop        di
+  pop        es
+  jmp        Success
+
+
+SetMode:
+  push       dx
+  push       ax
+
+  DebugLog   StrEnterSetMode
+
+  and        bx, ~0x4000 ; clear potentially set LFB bit in mode number
+  cmp        bx, 0x013f
+  je         KnownMode1
+  cmp        bx, 0x0140
+  je         KnownMode2
+  cmp        bx, 0x0141
+  je         KnownMode3
+  DebugLog   StrUnkownMode
+  jmp        Hang
+KnownMode1:
+  DebugLog   StrMode1
+  jmp        SetModeDone
+KnownMode2:
+  DebugLog   StrMode2
+  jmp        SetModeDone
+KnownMode3:
+  DebugLog   StrMode3
+  jmp        SetModeDone
+KnownMode4:
+  DebugLog   StrMode4
+
+SetModeDone:
+  mov        [CurMode], bl
+  mov        [CurMode+1], bh
+  pop        ax
+  pop        dx
+  jmp        Success
+
+
+GetMode:
+  DebugLog   StrEnterGetMode
+  mov        bl, [CurMode]
+  mov        bh, [CurMode+1]
+  jmp        Success
+
+
+GetPmCapabilities:
+  DebugLog   StrGetPmCapabilities
+  mov        bx, 0x0080
+  jmp        Success
+
+
+ReadEdid:
+  push       es
+  push       di
+  push       ds
+  push       si
+  push       cx
+
+  DebugLog   StrReadEdid
+
+  ; target (es:di) set on input
+  push       cs
+  pop        ds
+  mov        si, Edid
+  ; source (ds:si) set now
+
+  mov        cx, 128
+  cld
+  rep movsb
+
+  pop        cx
+  pop        si
+  pop        ds
+  pop        di
+  pop        es
+  jmp        Success
+
+
+SetModeLegacy:
+  DebugLog   StrEnterSetModeLegacy
+
+  cmp        al, 0x03
+  je         sKnownMode3
+  cmp        al, 0x12
+  je         sKnownMode4
+  DebugLog   StrUnkownMode
+  jmp        Hang
+sKnownMode3:
+  DebugLog   StrLegacyMode3
+  mov        al, 0 ; 0x30
+  jmp        SetModeLegacyDone
+sKnownMode4:
+  mov        al, 0 ;0x20
+SetModeLegacyDone:
+  DebugLog   StrExitSuccess
+  iret
+
+
+Success:
+  DebugLog   StrExitSuccess
+  mov        ax, 0x004f
+  iret
+
+
+Unsupported:
+  DebugLog   StrExitUnsupported
+  mov        ax, 0x024f
+  iret
+
+
+%ifdef DEBUG
+PrintStringSi:
+  pusha
+  push       ds ; save original
+  push       cs
+  pop        ds
+  mov        dx, 0x220             ; bhyve debug cons port
+  mov        ax, 0
+PrintStringSiLoop:
+  lodsb
+  cmp        al, 0
+  je         PrintStringSiDone
+  out        dx, al
+  jmp        PrintStringSiLoop
+PrintStringSiDone:
+  pop        ds ; restore original
+  popa
+  ret
+
+
+StrExitSuccess:
+  db 'vOk', 0x0d, 0x0a, 0
+
+StrExitUnsupported:
+  db 'vUnsupported', 0x0d, 0x0a, 0
+
+StrUnkownFunction:
+  db 'vUnknown Function', 0x0d, 0x0a, 0
+
+StrEnterGetInfo:
+  db 'vGetInfo', 0x0d, 0x0a, 0
+
+StrEnterGetModeInfo:
+  db 'vGetModeInfo', 0x0d, 0x0a, 0
+
+StrEnterGetMode:
+  db 'vGetMode', 0x0d, 0x0a, 0
+
+StrEnterSetMode:
+  db 'vSetMode', 0x0d, 0x0a, 0
+
+StrEnterSetModeLegacy:
+  db 'vSetModeLegacy', 0x0d, 0x0a, 0
+
+StrUnkownMode:
+  db 'vUnkown Mode', 0x0d, 0x0a, 0
+
+StrGetPmCapabilities:
+  db 'vGetPmCapabilities', 0x0d, 0x0a, 0
+
+StrReadEdid:
+  db 'vReadEdid', 0x0d, 0x0a, 0
+
+StrLegacyMode3:
+  db 'vLegacyMode3', 0x0d, 0x0a, 0
+
+
+StrMode1:
+  db 'mode_640x480x32', 0x0d, 0x0a, 0
+StrMode2:
+  db 'mode_800x600x32', 0x0d, 0x0a, 0
+StrMode3:
+  db 'mode_1024x768x32', 0x0d, 0x0a, 0
+StrMode4:
+  db 'mode_unused', 0x0d, 0x0a, 0
+%endif
+
+CurMode:
+  db 0x00, 0x00
+
+;
+; EDID stores monitor information. For now, just send back an null item.
+;
+Edid:
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+  db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
diff --git a/BhyvePkg/BhyveRfbDxe/VbeShim.c b/BhyvePkg/BhyveRfbDxe/VbeShim.c
new file mode 100644
index 0000000000..8dc1de3fed
--- /dev/null
+++ b/BhyvePkg/BhyveRfbDxe/VbeShim.c
@@ -0,0 +1,258 @@
+/** @file
+  Install a fake VGABIOS service handler (real mode Int10h) for the buggy
+  Windows 2008 R2 SP1 UEFI guest.
+
+  The handler is never meant to be directly executed by a VCPU; it's there for
+  the internal real mode emulator of Windows 2008 R2 SP1.
+
+  The code is based on Ralf Brown's Interrupt List:
+  <http://www.cs.cmu.edu/~ralf/files.html>
+  <http://www.ctyme.com/rbrown.htm>
+
+  Copyright (C) 2015, Nahanni Systems, Inc.
+  Copyright (C) 2014, Red Hat, Inc.
+  Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+#include <IndustryStandard/LegacyVgaBios.h>
+#include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+#include <Library/PrintLib.h>
+
+#include "Gop.h"
+#include "VbeShim.h"
+
+#pragma pack (1)
+typedef struct {
+  UINT16 Offset;
+  UINT16 Segment;
+} IVT_ENTRY;
+#pragma pack ()
+
+//
+// This string is displayed by Windows 2008 R2 SP1 in the Screen Resolution,
+// Advanced Settings dialog. It should be short.
+//
+STATIC CONST CHAR8 mProductRevision[] = "2.0";
+
+#define NUM_VBE_MODES 3
+STATIC CONST UINT16 vbeModeIds[] = {
+  0x13f,  // 640x480x32
+  0x140,  // 800x600x32
+  0x141   // 1024x768x32
+};
+
+// Modes can be toggled with bit-0
+#define VBE_MODE_ENABLED  0x00BB
+#define VBE_MODE_DISABLED 0x00BA
+
+STATIC VBE2_MODE_INFO vbeModes[] = {
+  { // 0x13f 640x480x32
+
+    // ModeAttr - BytesPerScanLine
+    VBE_MODE_DISABLED, 0x07, 0x00, 0x40, 0x40, 0xA000, 0x00, 0x0000, 640*4,
+    // Width, Height..., Vbe3
+    640, 480, 16, 8, 1, 32, 1, 0x06, 0, 0, 1,
+    // Masks
+    0x08, 0x10, 0x08, 0x08, 0x08, 0x00, 0x08, 0x18, 0x00,
+    // Framebuffer
+    0xdeadbeef, 0x0000, 0x0000
+  },
+  { // 0x140 800x600x32
+
+    // ModeAttr - BytesPerScanLine
+    VBE_MODE_DISABLED, 0x07, 0x00, 0x40, 0x40, 0xA000, 0x00, 0x0000, 800*4,
+    // Width, Height..., Vbe3
+    800, 600, 16, 8, 1, 32, 1, 0x06, 0, 0, 1,
+    // Masks
+    0x08, 0x10, 0x08, 0x08, 0x08, 0x00, 0x08, 0x18, 0x00,
+    // Framebuffer
+    0xdeadbeef, 0x0000, 0x0000
+  },
+  { // 0x141 1024x768x32
+
+    // ModeAttr - BytesPerScanLine
+    VBE_MODE_ENABLED, 0x07, 0x00, 0x40, 0x40, 0xA000, 0x00, 0x0000, 1024*4,
+    // Width, Height..., Vbe3
+    1024, 768, 16, 8, 1, 32, 1, 0x06, 0, 0, 1,
+    // Masks
+    0x08, 0x10, 0x08, 0x08, 0x08, 0x00, 0x08, 0x18, 0x00,
+    // Framebuffer
+    0xdeadbeef, 0x0000, 0x0000
+  }
+};
+
+/**
+  Install the VBE Info and VBE Mode Info structures, and the VBE service
+  handler routine in the C segment. Point the real-mode Int10h interrupt vector
+  to the handler. The only advertised mode is 1024x768x32.
+
+  @param[in] CardName         Name of the video card to be exposed in the
+                              Product Name field of the VBE Info structure.
+  @param[in] FrameBufferBase  Guest-physical base address of the video card's
+                              frame buffer.
+**/
+VOID
+InstallVbeShim (
+  IN CONST CHAR16         *CardName,
+  IN EFI_PHYSICAL_ADDRESS FrameBufferBase
+  )
+{
+  EFI_PHYSICAL_ADDRESS Segment0, SegmentC, SegmentF;
+  UINTN                Segment0Pages;
+  IVT_ENTRY            *Int0x10;
+  EFI_STATUS           Status;
+  UINTN                Pam1Address;
+  UINT8                Pam1;
+  UINTN                SegmentCPages;
+  VBE_INFO             *VbeInfoFull;
+  VBE_INFO_BASE        *VbeInfo;
+  UINT8                *Ptr;
+  UINTN                Printed;
+  VBE_MODE_INFO        *VbeModeInfo;
+  UINTN                i;
+
+  Segment0 = 0x00000;
+  SegmentC = 0xC0000;
+  SegmentF = 0xF0000;
+
+  //
+  // Attempt to cover the real mode IVT with an allocation. This is a UEFI
+  // driver, hence the arch protocols have been installed previously. Among
+  // those, the CPU arch protocol has configured the IDT, so we can overwrite
+  // the IVT used in real mode.
+  //
+  // The allocation request may fail, eg. if LegacyBiosDxe has already run.
+  //
+  Segment0Pages = 1;
+  Int0x10       = (IVT_ENTRY *)(UINTN)Segment0 + 0x10;
+  Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode,
+                  Segment0Pages, &Segment0);
+
+  if (EFI_ERROR (Status)) {
+    EFI_PHYSICAL_ADDRESS Handler;
+
+    //
+    // Check if a video BIOS handler has been installed previously -- we
+    // shouldn't override a real video BIOS with our shim, nor our own shim if
+    // it's already present.
+    //
+    Handler = (Int0x10->Segment << 4) + Int0x10->Offset;
+    if (Handler >= SegmentC && Handler < SegmentF) {
+      DEBUG ((DEBUG_VERBOSE, "%a: Video BIOS handler found at %04x:%04x\n",
+        __FUNCTION__, Int0x10->Segment, Int0x10->Offset));
+      return;
+    }
+
+    //
+    // Otherwise we'll overwrite the Int10h vector, even though we may not own
+    // the page at zero.
+    //
+    DEBUG ((DEBUG_VERBOSE, "%a: failed to allocate page at zero: %r\n",
+      __FUNCTION__, Status));
+  } else {
+    //
+    // We managed to allocate the page at zero. SVN r14218 guarantees that it
+    // is NUL-filled.
+    //
+    ASSERT (Int0x10->Segment == 0x0000);
+    ASSERT (Int0x10->Offset  == 0x0000);
+  }
+
+  //
+  // Put the shim in place first.
+  //
+  Pam1Address = PCI_LIB_ADDRESS (0, 0, 0, 0x5A);
+  //
+  // low nibble covers 0xC0000 to 0xC3FFF
+  // high nibble covers 0xC4000 to 0xC7FFF
+  // bit1 in each nibble is Write Enable
+  // bit0 in each nibble is Read Enable
+  //
+  Pam1 = PciRead8 (Pam1Address);
+  PciWrite8 (Pam1Address, Pam1 | (BIT1 | BIT0));
+
+  //
+  // We never added memory space durig PEI or DXE for the C segment, so we
+  // don't need to (and can't) allocate from there. Also, guest operating
+  // systems will see a hole in the UEFI memory map there.
+  //
+  SegmentCPages = 4;
+
+  ASSERT (sizeof mVbeShim <= EFI_PAGES_TO_SIZE (SegmentCPages));
+  CopyMem ((VOID *)(UINTN)SegmentC, mVbeShim, sizeof mVbeShim);
+
+  //
+  // Fill in the VBE INFO structure.
+  //
+  VbeInfoFull = (VBE_INFO *)(UINTN)SegmentC;
+  VbeInfo     = &VbeInfoFull->Base;
+  Ptr         = VbeInfoFull->Buffer;
+
+  CopyMem (VbeInfo->Signature, "VESA", 4);
+  VbeInfo->VesaVersion = 0x0200;
+
+  VbeInfo->OemNameAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+  CopyMem (Ptr, "FBSD", 5);
+  Ptr += 5;
+
+  VbeInfo->Capabilities = BIT1 | BIT0; // DAC can be switched into 8-bit mode
+
+  VbeInfo->ModeListAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+  for (i = 0; i < NUM_VBE_MODES; i ++) {
+     *(UINT16*)Ptr = vbeModeIds[i];  // mode number
+     Ptr += 2;
+  }
+  *(UINT16*)Ptr = 0xFFFF; // mode list terminator
+  Ptr += 2;
+
+  VbeInfo->VideoMem64K = (UINT16)((1024 * 768 * 4 + 65535) / 65536);
+  VbeInfo->OemSoftwareVersion = 0x0200;
+
+  VbeInfo->VendorNameAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+  CopyMem (Ptr, "FBSD", 5);
+  Ptr += 5;
+
+  VbeInfo->ProductNameAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+  Printed = AsciiSPrint ((CHAR8 *)Ptr,
+              sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer), "%s",
+              CardName);
+  Ptr += Printed + 1;
+
+  VbeInfo->ProductRevAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+  CopyMem (Ptr, mProductRevision, sizeof mProductRevision);
+  Ptr += sizeof mProductRevision;
+
+  ASSERT (sizeof VbeInfoFull->Buffer >= Ptr - VbeInfoFull->Buffer);
+  ZeroMem (Ptr, sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer));
+
+  //
+  // Fill in the VBE MODE INFO structure list
+  //
+  VbeModeInfo = (VBE_MODE_INFO *)(VbeInfoFull + 1);
+  Ptr = (UINT8 *)VbeModeInfo;
+  for (i = 0; i < NUM_VBE_MODES; i++) {
+    vbeModes[i].LfbAddress = (UINT32)FrameBufferBase;
+    CopyMem (Ptr, &vbeModes[i], 0x32);
+    Ptr += 0x32;
+  }
+
+  ZeroMem (Ptr, 56);     // Clear remaining bytes
+
+  //
+  // Clear Write Enable (bit1), keep Read Enable (bit0) set
+  //
+  PciWrite8 (Pam1Address, (Pam1 & ~BIT1) | BIT0);
+
+  //
+  // Second, point the Int10h vector at the shim.
+  //
+  Int0x10->Segment = (UINT16) ((UINT32)SegmentC >> 4);
+  Int0x10->Offset  = (UINT16) ((UINTN) (VbeModeInfo + 1) - SegmentC);
+
+  DEBUG ((DEBUG_INFO, "%a: VBE shim installed to %x:%x\n",
+         __FUNCTION__, Int0x10->Segment, Int0x10->Offset));
+}
diff --git a/BhyvePkg/BhyveRfbDxe/VbeShim.h b/BhyvePkg/BhyveRfbDxe/VbeShim.h
new file mode 100644
index 0000000000..72b8a3f25f
--- /dev/null
+++ b/BhyvePkg/BhyveRfbDxe/VbeShim.h
@@ -0,0 +1,912 @@
+//
+// THIS FILE WAS GENERATED BY "VbeShim.sh". DO NOT EDIT.
+//
+#ifndef _VBE_SHIM_H_
+#define _VBE_SHIM_H_
+STATIC CONST UINT8 mVbeShim[] = {
+  /* 00000000 nop                            */  0x90,
+  /* 00000001 nop                            */  0x90,
+  /* 00000002 nop                            */  0x90,
+  /* 00000003 nop                            */  0x90,
+  /* 00000004 nop                            */  0x90,
+  /* 00000005 nop                            */  0x90,
+  /* 00000006 nop                            */  0x90,
+  /* 00000007 nop                            */  0x90,
+  /* 00000008 nop                            */  0x90,
+  /* 00000009 nop                            */  0x90,
+  /* 0000000A nop                            */  0x90,
+  /* 0000000B nop                            */  0x90,
+  /* 0000000C nop                            */  0x90,
+  /* 0000000D nop                            */  0x90,
+  /* 0000000E nop                            */  0x90,
+  /* 0000000F nop                            */  0x90,
+  /* 00000010 nop                            */  0x90,
+  /* 00000011 nop                            */  0x90,
+  /* 00000012 nop                            */  0x90,
+  /* 00000013 nop                            */  0x90,
+  /* 00000014 nop                            */  0x90,
+  /* 00000015 nop                            */  0x90,
+  /* 00000016 nop                            */  0x90,
+  /* 00000017 nop                            */  0x90,
+  /* 00000018 nop                            */  0x90,
+  /* 00000019 nop                            */  0x90,
+  /* 0000001A nop                            */  0x90,
+  /* 0000001B nop                            */  0x90,
+  /* 0000001C nop                            */  0x90,
+  /* 0000001D nop                            */  0x90,
+  /* 0000001E nop                            */  0x90,
+  /* 0000001F nop                            */  0x90,
+  /* 00000020 nop                            */  0x90,
+  /* 00000021 nop                            */  0x90,
+  /* 00000022 nop                            */  0x90,
+  /* 00000023 nop                            */  0x90,
+  /* 00000024 nop                            */  0x90,
+  /* 00000025 nop                            */  0x90,
+  /* 00000026 nop                            */  0x90,
+  /* 00000027 nop                            */  0x90,
+  /* 00000028 nop                            */  0x90,
+  /* 00000029 nop                            */  0x90,
+  /* 0000002A nop                            */  0x90,
+  /* 0000002B nop                            */  0x90,
+  /* 0000002C nop                            */  0x90,
+  /* 0000002D nop                            */  0x90,
+  /* 0000002E nop                            */  0x90,
+  /* 0000002F nop                            */  0x90,
+  /* 00000030 nop                            */  0x90,
+  /* 00000031 nop                            */  0x90,
+  /* 00000032 nop                            */  0x90,
+  /* 00000033 nop                            */  0x90,
+  /* 00000034 nop                            */  0x90,
+  /* 00000035 nop                            */  0x90,
+  /* 00000036 nop                            */  0x90,
+  /* 00000037 nop                            */  0x90,
+  /* 00000038 nop                            */  0x90,
+  /* 00000039 nop                            */  0x90,
+  /* 0000003A nop                            */  0x90,
+  /* 0000003B nop                            */  0x90,
+  /* 0000003C nop                            */  0x90,
+  /* 0000003D nop                            */  0x90,
+  /* 0000003E nop                            */  0x90,
+  /* 0000003F nop                            */  0x90,
+  /* 00000040 nop                            */  0x90,
+  /* 00000041 nop                            */  0x90,
+  /* 00000042 nop                            */  0x90,
+  /* 00000043 nop                            */  0x90,
+  /* 00000044 nop                            */  0x90,
+  /* 00000045 nop                            */  0x90,
+  /* 00000046 nop                            */  0x90,
+  /* 00000047 nop                            */  0x90,
+  /* 00000048 nop                            */  0x90,
+  /* 00000049 nop                            */  0x90,
+  /* 0000004A nop                            */  0x90,
+  /* 0000004B nop                            */  0x90,
+  /* 0000004C nop                            */  0x90,
+  /* 0000004D nop                            */  0x90,
+  /* 0000004E nop                            */  0x90,
+  /* 0000004F nop                            */  0x90,
+  /* 00000050 nop                            */  0x90,
+  /* 00000051 nop                            */  0x90,
+  /* 00000052 nop                            */  0x90,
+  /* 00000053 nop                            */  0x90,
+  /* 00000054 nop                            */  0x90,
+  /* 00000055 nop                            */  0x90,
+  /* 00000056 nop                            */  0x90,
+  /* 00000057 nop                            */  0x90,
+  /* 00000058 nop                            */  0x90,
+  /* 00000059 nop                            */  0x90,
+  /* 0000005A nop                            */  0x90,
+  /* 0000005B nop                            */  0x90,
+  /* 0000005C nop                            */  0x90,
+  /* 0000005D nop                            */  0x90,
+  /* 0000005E nop                            */  0x90,
+  /* 0000005F nop                            */  0x90,
+  /* 00000060 nop                            */  0x90,
+  /* 00000061 nop                            */  0x90,
+  /* 00000062 nop                            */  0x90,
+  /* 00000063 nop                            */  0x90,
+  /* 00000064 nop                            */  0x90,
+  /* 00000065 nop                            */  0x90,
+  /* 00000066 nop                            */  0x90,
+  /* 00000067 nop                            */  0x90,
+  /* 00000068 nop                            */  0x90,
+  /* 00000069 nop                            */  0x90,
+  /* 0000006A nop                            */  0x90,
+  /* 0000006B nop                            */  0x90,
+  /* 0000006C nop                            */  0x90,
+  /* 0000006D nop                            */  0x90,
+  /* 0000006E nop                            */  0x90,
+  /* 0000006F nop                            */  0x90,
+  /* 00000070 nop                            */  0x90,
+  /* 00000071 nop                            */  0x90,
+  /* 00000072 nop                            */  0x90,
+  /* 00000073 nop                            */  0x90,
+  /* 00000074 nop                            */  0x90,
+  /* 00000075 nop                            */  0x90,
+  /* 00000076 nop                            */  0x90,
+  /* 00000077 nop                            */  0x90,
+  /* 00000078 nop                            */  0x90,
+  /* 00000079 nop                            */  0x90,
+  /* 0000007A nop                            */  0x90,
+  /* 0000007B nop                            */  0x90,
+  /* 0000007C nop                            */  0x90,
+  /* 0000007D nop                            */  0x90,
+  /* 0000007E nop                            */  0x90,
+  /* 0000007F nop                            */  0x90,
+  /* 00000080 nop                            */  0x90,
+  /* 00000081 nop                            */  0x90,
+  /* 00000082 nop                            */  0x90,
+  /* 00000083 nop                            */  0x90,
+  /* 00000084 nop                            */  0x90,
+  /* 00000085 nop                            */  0x90,
+  /* 00000086 nop                            */  0x90,
+  /* 00000087 nop                            */  0x90,
+  /* 00000088 nop                            */  0x90,
+  /* 00000089 nop                            */  0x90,
+  /* 0000008A nop                            */  0x90,
+  /* 0000008B nop                            */  0x90,
+  /* 0000008C nop                            */  0x90,
+  /* 0000008D nop                            */  0x90,
+  /* 0000008E nop                            */  0x90,
+  /* 0000008F nop                            */  0x90,
+  /* 00000090 nop                            */  0x90,
+  /* 00000091 nop                            */  0x90,
+  /* 00000092 nop                            */  0x90,
+  /* 00000093 nop                            */  0x90,
+  /* 00000094 nop                            */  0x90,
+  /* 00000095 nop                            */  0x90,
+  /* 00000096 nop                            */  0x90,
+  /* 00000097 nop                            */  0x90,
+  /* 00000098 nop                            */  0x90,
+  /* 00000099 nop                            */  0x90,
+  /* 0000009A nop                            */  0x90,
+  /* 0000009B nop                            */  0x90,
+  /* 0000009C nop                            */  0x90,
+  /* 0000009D nop                            */  0x90,
+  /* 0000009E nop                            */  0x90,
+  /* 0000009F nop                            */  0x90,
+  /* 000000A0 nop                            */  0x90,
+  /* 000000A1 nop                            */  0x90,
+  /* 000000A2 nop                            */  0x90,
+  /* 000000A3 nop                            */  0x90,
+  /* 000000A4 nop                            */  0x90,
+  /* 000000A5 nop                            */  0x90,
+  /* 000000A6 nop                            */  0x90,
+  /* 000000A7 nop                            */  0x90,
+  /* 000000A8 nop                            */  0x90,
+  /* 000000A9 nop                            */  0x90,
+  /* 000000AA nop                            */  0x90,
+  /* 000000AB nop                            */  0x90,
+  /* 000000AC nop                            */  0x90,
+  /* 000000AD nop                            */  0x90,
+  /* 000000AE nop                            */  0x90,
+  /* 000000AF nop                            */  0x90,
+  /* 000000B0 nop                            */  0x90,
+  /* 000000B1 nop                            */  0x90,
+  /* 000000B2 nop                            */  0x90,
+  /* 000000B3 nop                            */  0x90,
+  /* 000000B4 nop                            */  0x90,
+  /* 000000B5 nop                            */  0x90,
+  /* 000000B6 nop                            */  0x90,
+  /* 000000B7 nop                            */  0x90,
+  /* 000000B8 nop                            */  0x90,
+  /* 000000B9 nop                            */  0x90,
+  /* 000000BA nop                            */  0x90,
+  /* 000000BB nop                            */  0x90,
+  /* 000000BC nop                            */  0x90,
+  /* 000000BD nop                            */  0x90,
+  /* 000000BE nop                            */  0x90,
+  /* 000000BF nop                            */  0x90,
+  /* 000000C0 nop                            */  0x90,
+  /* 000000C1 nop                            */  0x90,
+  /* 000000C2 nop                            */  0x90,
+  /* 000000C3 nop                            */  0x90,
+  /* 000000C4 nop                            */  0x90,
+  /* 000000C5 nop                            */  0x90,
+  /* 000000C6 nop                            */  0x90,
+  /* 000000C7 nop                            */  0x90,
+  /* 000000C8 nop                            */  0x90,
+  /* 000000C9 nop                            */  0x90,
+  /* 000000CA nop                            */  0x90,
+  /* 000000CB nop                            */  0x90,
+  /* 000000CC nop                            */  0x90,
+  /* 000000CD nop                            */  0x90,
+  /* 000000CE nop                            */  0x90,
+  /* 000000CF nop                            */  0x90,
+  /* 000000D0 nop                            */  0x90,
+  /* 000000D1 nop                            */  0x90,
+  /* 000000D2 nop                            */  0x90,
+  /* 000000D3 nop                            */  0x90,
+  /* 000000D4 nop                            */  0x90,
+  /* 000000D5 nop                            */  0x90,
+  /* 000000D6 nop                            */  0x90,
+  /* 000000D7 nop                            */  0x90,
+  /* 000000D8 nop                            */  0x90,
+  /* 000000D9 nop                            */  0x90,
+  /* 000000DA nop                            */  0x90,
+  /* 000000DB nop                            */  0x90,
+  /* 000000DC nop                            */  0x90,
+  /* 000000DD nop                            */  0x90,
+  /* 000000DE nop                            */  0x90,
+  /* 000000DF nop                            */  0x90,
+  /* 000000E0 nop                            */  0x90,
+  /* 000000E1 nop                            */  0x90,
+  /* 000000E2 nop                            */  0x90,
+  /* 000000E3 nop                            */  0x90,
+  /* 000000E4 nop                            */  0x90,
+  /* 000000E5 nop                            */  0x90,
+  /* 000000E6 nop                            */  0x90,
+  /* 000000E7 nop                            */  0x90,
+  /* 000000E8 nop                            */  0x90,
+  /* 000000E9 nop                            */  0x90,
+  /* 000000EA nop                            */  0x90,
+  /* 000000EB nop                            */  0x90,
+  /* 000000EC nop                            */  0x90,
+  /* 000000ED nop                            */  0x90,
+  /* 000000EE nop                            */  0x90,
+  /* 000000EF nop                            */  0x90,
+  /* 000000F0 nop                            */  0x90,
+  /* 000000F1 nop                            */  0x90,
+  /* 000000F2 nop                            */  0x90,
+  /* 000000F3 nop                            */  0x90,
+  /* 000000F4 nop                            */  0x90,
+  /* 000000F5 nop                            */  0x90,
+  /* 000000F6 nop                            */  0x90,
+  /* 000000F7 nop                            */  0x90,
+  /* 000000F8 nop                            */  0x90,
+  /* 000000F9 nop                            */  0x90,
+  /* 000000FA nop                            */  0x90,
+  /* 000000FB nop                            */  0x90,
+  /* 000000FC nop                            */  0x90,
+  /* 000000FD nop                            */  0x90,
+  /* 000000FE nop                            */  0x90,
+  /* 000000FF nop                            */  0x90,
+  /* 00000100 nop                            */  0x90,
+  /* 00000101 nop                            */  0x90,
+  /* 00000102 nop                            */  0x90,
+  /* 00000103 nop                            */  0x90,
+  /* 00000104 nop                            */  0x90,
+  /* 00000105 nop                            */  0x90,
+  /* 00000106 nop                            */  0x90,
+  /* 00000107 nop                            */  0x90,
+  /* 00000108 nop                            */  0x90,
+  /* 00000109 nop                            */  0x90,
+  /* 0000010A nop                            */  0x90,
+  /* 0000010B nop                            */  0x90,
+  /* 0000010C nop                            */  0x90,
+  /* 0000010D nop                            */  0x90,
+  /* 0000010E nop                            */  0x90,
+  /* 0000010F nop                            */  0x90,
+  /* 00000110 nop                            */  0x90,
+  /* 00000111 nop                            */  0x90,
+  /* 00000112 nop                            */  0x90,
+  /* 00000113 nop                            */  0x90,
+  /* 00000114 nop                            */  0x90,
+  /* 00000115 nop                            */  0x90,
+  /* 00000116 nop                            */  0x90,
+  /* 00000117 nop                            */  0x90,
+  /* 00000118 nop                            */  0x90,
+  /* 00000119 nop                            */  0x90,
+  /* 0000011A nop                            */  0x90,
+  /* 0000011B nop                            */  0x90,
+  /* 0000011C nop                            */  0x90,
+  /* 0000011D nop                            */  0x90,
+  /* 0000011E nop                            */  0x90,
+  /* 0000011F nop                            */  0x90,
+  /* 00000120 nop                            */  0x90,
+  /* 00000121 nop                            */  0x90,
+  /* 00000122 nop                            */  0x90,
+  /* 00000123 nop                            */  0x90,
+  /* 00000124 nop                            */  0x90,
+  /* 00000125 nop                            */  0x90,
+  /* 00000126 nop                            */  0x90,
+  /* 00000127 nop                            */  0x90,
+  /* 00000128 nop                            */  0x90,
+  /* 00000129 nop                            */  0x90,
+  /* 0000012A nop                            */  0x90,
+  /* 0000012B nop                            */  0x90,
+  /* 0000012C nop                            */  0x90,
+  /* 0000012D nop                            */  0x90,
+  /* 0000012E nop                            */  0x90,
+  /* 0000012F nop                            */  0x90,
+  /* 00000130 nop                            */  0x90,
+  /* 00000131 nop                            */  0x90,
+  /* 00000132 nop                            */  0x90,
+  /* 00000133 nop                            */  0x90,
+  /* 00000134 nop                            */  0x90,
+  /* 00000135 nop                            */  0x90,
+  /* 00000136 nop                            */  0x90,
+  /* 00000137 nop                            */  0x90,
+  /* 00000138 nop                            */  0x90,
+  /* 00000139 nop                            */  0x90,
+  /* 0000013A nop                            */  0x90,
+  /* 0000013B nop                            */  0x90,
+  /* 0000013C nop                            */  0x90,
+  /* 0000013D nop                            */  0x90,
+  /* 0000013E nop                            */  0x90,
+  /* 0000013F nop                            */  0x90,
+  /* 00000140 nop                            */  0x90,
+  /* 00000141 nop                            */  0x90,
+  /* 00000142 nop                            */  0x90,
+  /* 00000143 nop                            */  0x90,
+  /* 00000144 nop                            */  0x90,
+  /* 00000145 nop                            */  0x90,
+  /* 00000146 nop                            */  0x90,
+  /* 00000147 nop                            */  0x90,
+  /* 00000148 nop                            */  0x90,
+  /* 00000149 nop                            */  0x90,
+  /* 0000014A nop                            */  0x90,
+  /* 0000014B nop                            */  0x90,
+  /* 0000014C nop                            */  0x90,
+  /* 0000014D nop                            */  0x90,
+  /* 0000014E nop                            */  0x90,
+  /* 0000014F nop                            */  0x90,
+  /* 00000150 nop                            */  0x90,
+  /* 00000151 nop                            */  0x90,
+  /* 00000152 nop                            */  0x90,
+  /* 00000153 nop                            */  0x90,
+  /* 00000154 nop                            */  0x90,
+  /* 00000155 nop                            */  0x90,
+  /* 00000156 nop                            */  0x90,
+  /* 00000157 nop                            */  0x90,
+  /* 00000158 nop                            */  0x90,
+  /* 00000159 nop                            */  0x90,
+  /* 0000015A nop                            */  0x90,
+  /* 0000015B nop                            */  0x90,
+  /* 0000015C nop                            */  0x90,
+  /* 0000015D nop                            */  0x90,
+  /* 0000015E nop                            */  0x90,
+  /* 0000015F nop                            */  0x90,
+  /* 00000160 nop                            */  0x90,
+  /* 00000161 nop                            */  0x90,
+  /* 00000162 nop                            */  0x90,
+  /* 00000163 nop                            */  0x90,
+  /* 00000164 nop                            */  0x90,
+  /* 00000165 nop                            */  0x90,
+  /* 00000166 nop                            */  0x90,
+  /* 00000167 nop                            */  0x90,
+  /* 00000168 nop                            */  0x90,
+  /* 00000169 nop                            */  0x90,
+  /* 0000016A nop                            */  0x90,
+  /* 0000016B nop                            */  0x90,
+  /* 0000016C nop                            */  0x90,
+  /* 0000016D nop                            */  0x90,
+  /* 0000016E nop                            */  0x90,
+  /* 0000016F nop                            */  0x90,
+  /* 00000170 nop                            */  0x90,
+  /* 00000171 nop                            */  0x90,
+  /* 00000172 nop                            */  0x90,
+  /* 00000173 nop                            */  0x90,
+  /* 00000174 nop                            */  0x90,
+  /* 00000175 nop                            */  0x90,
+  /* 00000176 nop                            */  0x90,
+  /* 00000177 nop                            */  0x90,
+  /* 00000178 nop                            */  0x90,
+  /* 00000179 nop                            */  0x90,
+  /* 0000017A nop                            */  0x90,
+  /* 0000017B nop                            */  0x90,
+  /* 0000017C nop                            */  0x90,
+  /* 0000017D nop                            */  0x90,
+  /* 0000017E nop                            */  0x90,
+  /* 0000017F nop                            */  0x90,
+  /* 00000180 nop                            */  0x90,
+  /* 00000181 nop                            */  0x90,
+  /* 00000182 nop                            */  0x90,
+  /* 00000183 nop                            */  0x90,
+  /* 00000184 nop                            */  0x90,
+  /* 00000185 nop                            */  0x90,
+  /* 00000186 nop                            */  0x90,
+  /* 00000187 nop                            */  0x90,
+  /* 00000188 nop                            */  0x90,
+  /* 00000189 nop                            */  0x90,
+  /* 0000018A nop                            */  0x90,
+  /* 0000018B nop                            */  0x90,
+  /* 0000018C nop                            */  0x90,
+  /* 0000018D nop                            */  0x90,
+  /* 0000018E nop                            */  0x90,
+  /* 0000018F nop                            */  0x90,
+  /* 00000190 nop                            */  0x90,
+  /* 00000191 nop                            */  0x90,
+  /* 00000192 nop                            */  0x90,
+  /* 00000193 nop                            */  0x90,
+  /* 00000194 nop                            */  0x90,
+  /* 00000195 nop                            */  0x90,
+  /* 00000196 nop                            */  0x90,
+  /* 00000197 nop                            */  0x90,
+  /* 00000198 nop                            */  0x90,
+  /* 00000199 nop                            */  0x90,
+  /* 0000019A nop                            */  0x90,
+  /* 0000019B nop                            */  0x90,
+  /* 0000019C nop                            */  0x90,
+  /* 0000019D nop                            */  0x90,
+  /* 0000019E nop                            */  0x90,
+  /* 0000019F nop                            */  0x90,
+  /* 000001A0 nop                            */  0x90,
+  /* 000001A1 nop                            */  0x90,
+  /* 000001A2 nop                            */  0x90,
+  /* 000001A3 nop                            */  0x90,
+  /* 000001A4 nop                            */  0x90,
+  /* 000001A5 nop                            */  0x90,
+  /* 000001A6 nop                            */  0x90,
+  /* 000001A7 nop                            */  0x90,
+  /* 000001A8 nop                            */  0x90,
+  /* 000001A9 nop                            */  0x90,
+  /* 000001AA nop                            */  0x90,
+  /* 000001AB nop                            */  0x90,
+  /* 000001AC nop                            */  0x90,
+  /* 000001AD nop                            */  0x90,
+  /* 000001AE nop                            */  0x90,
+  /* 000001AF nop                            */  0x90,
+  /* 000001B0 nop                            */  0x90,
+  /* 000001B1 nop                            */  0x90,
+  /* 000001B2 nop                            */  0x90,
+  /* 000001B3 nop                            */  0x90,
+  /* 000001B4 nop                            */  0x90,
+  /* 000001B5 nop                            */  0x90,
+  /* 000001B6 nop                            */  0x90,
+  /* 000001B7 nop                            */  0x90,
+  /* 000001B8 nop                            */  0x90,
+  /* 000001B9 nop                            */  0x90,
+  /* 000001BA nop                            */  0x90,
+  /* 000001BB nop                            */  0x90,
+  /* 000001BC nop                            */  0x90,
+  /* 000001BD nop                            */  0x90,
+  /* 000001BE nop                            */  0x90,
+  /* 000001BF nop                            */  0x90,
+  /* 000001C0 nop                            */  0x90,
+  /* 000001C1 nop                            */  0x90,
+  /* 000001C2 nop                            */  0x90,
+  /* 000001C3 nop                            */  0x90,
+  /* 000001C4 nop                            */  0x90,
+  /* 000001C5 nop                            */  0x90,
+  /* 000001C6 nop                            */  0x90,
+  /* 000001C7 nop                            */  0x90,
+  /* 000001C8 nop                            */  0x90,
+  /* 000001C9 nop                            */  0x90,
+  /* 000001CA nop                            */  0x90,
+  /* 000001CB nop                            */  0x90,
+  /* 000001CC nop                            */  0x90,
+  /* 000001CD nop                            */  0x90,
+  /* 000001CE nop                            */  0x90,
+  /* 000001CF nop                            */  0x90,
+  /* 000001D0 nop                            */  0x90,
+  /* 000001D1 nop                            */  0x90,
+  /* 000001D2 nop                            */  0x90,
+  /* 000001D3 nop                            */  0x90,
+  /* 000001D4 nop                            */  0x90,
+  /* 000001D5 nop                            */  0x90,
+  /* 000001D6 nop                            */  0x90,
+  /* 000001D7 nop                            */  0x90,
+  /* 000001D8 nop                            */  0x90,
+  /* 000001D9 nop                            */  0x90,
+  /* 000001DA nop                            */  0x90,
+  /* 000001DB nop                            */  0x90,
+  /* 000001DC nop                            */  0x90,
+  /* 000001DD nop                            */  0x90,
+  /* 000001DE nop                            */  0x90,
+  /* 000001DF nop                            */  0x90,
+  /* 000001E0 nop                            */  0x90,
+  /* 000001E1 nop                            */  0x90,
+  /* 000001E2 nop                            */  0x90,
+  /* 000001E3 nop                            */  0x90,
+  /* 000001E4 nop                            */  0x90,
+  /* 000001E5 nop                            */  0x90,
+  /* 000001E6 nop                            */  0x90,
+  /* 000001E7 nop                            */  0x90,
+  /* 000001E8 nop                            */  0x90,
+  /* 000001E9 nop                            */  0x90,
+  /* 000001EA nop                            */  0x90,
+  /* 000001EB nop                            */  0x90,
+  /* 000001EC nop                            */  0x90,
+  /* 000001ED nop                            */  0x90,
+  /* 000001EE nop                            */  0x90,
+  /* 000001EF nop                            */  0x90,
+  /* 000001F0 nop                            */  0x90,
+  /* 000001F1 nop                            */  0x90,
+  /* 000001F2 nop                            */  0x90,
+  /* 000001F3 nop                            */  0x90,
+  /* 000001F4 nop                            */  0x90,
+  /* 000001F5 nop                            */  0x90,
+  /* 000001F6 nop                            */  0x90,
+  /* 000001F7 nop                            */  0x90,
+  /* 000001F8 nop                            */  0x90,
+  /* 000001F9 nop                            */  0x90,
+  /* 000001FA nop                            */  0x90,
+  /* 000001FB nop                            */  0x90,
+  /* 000001FC nop                            */  0x90,
+  /* 000001FD nop                            */  0x90,
+  /* 000001FE nop                            */  0x90,
+  /* 000001FF nop                            */  0x90,
+  /* 00000200 cmp ax,0x4f00                  */  0x3D, 0x00, 0x4F,
+  /* 00000203 jz 0x237                       */  0x74, 0x32,
+  /* 00000205 cmp ax,0x4f01                  */  0x3D, 0x01, 0x4F,
+  /* 00000208 jz 0x257                       */  0x74, 0x4D,
+  /* 0000020A cmp ax,0x4f02                  */  0x3D, 0x02, 0x4F,
+  /* 0000020D jz word 0x2c8                  */  0x0F, 0x84, 0xB7, 0x00,
+  /* 00000211 cmp ax,0x4f03                  */  0x3D, 0x03, 0x4F,
+  /* 00000214 jz word 0x325                  */  0x0F, 0x84, 0x0D, 0x01,
+  /* 00000218 cmp ax,0x4f10                  */  0x3D, 0x10, 0x4F,
+  /* 0000021B jz word 0x337                  */  0x0F, 0x84, 0x18, 0x01,
+  /* 0000021F cmp ax,0x4f15                  */  0x3D, 0x15, 0x4F,
+  /* 00000222 jz word 0x344                  */  0x0F, 0x84, 0x1E, 0x01,
+  /* 00000226 cmp ah,0x0                     */  0x80, 0xFC, 0x00,
+  /* 00000229 jz word 0x363                  */  0x0F, 0x84, 0x36, 0x01,
+  /* 0000022D push si                        */  0x56,
+  /* 0000022E mov si,0x3d7                   */  0xBE, 0xD7, 0x03,
+  /* 00000231 call word 0x3ad                */  0xE8, 0x79, 0x01,
+  /* 00000234 pop si                         */  0x5E,
+  /* 00000235 jmp short 0x235                */  0xEB, 0xFE,
+  /* 00000237 push es                        */  0x06,
+  /* 00000238 push di                        */  0x57,
+  /* 00000239 push ds                        */  0x1E,
+  /* 0000023A push si                        */  0x56,
+  /* 0000023B push cx                        */  0x51,
+  /* 0000023C push si                        */  0x56,
+  /* 0000023D mov si,0x3eb                   */  0xBE, 0xEB, 0x03,
+  /* 00000240 call word 0x3ad                */  0xE8, 0x6A, 0x01,
+  /* 00000243 pop si                         */  0x5E,
+  /* 00000244 push cs                        */  0x0E,
+  /* 00000245 pop ds                         */  0x1F,
+  /* 00000246 mov si,0x0                     */  0xBE, 0x00, 0x00,
+  /* 00000249 mov cx,0x100                   */  0xB9, 0x00, 0x01,
+  /* 0000024C cld                            */  0xFC,
+  /* 0000024D rep movsb                      */  0xF3, 0xA4,
+  /* 0000024F pop cx                         */  0x59,
+  /* 00000250 pop si                         */  0x5E,
+  /* 00000251 pop ds                         */  0x1F,
+  /* 00000252 pop di                         */  0x5F,
+  /* 00000253 pop es                         */  0x07,
+  /* 00000254 jmp word 0x395                 */  0xE9, 0x3E, 0x01,
+  /* 00000257 push es                        */  0x06,
+  /* 00000258 push di                        */  0x57,
+  /* 00000259 push ds                        */  0x1E,
+  /* 0000025A push si                        */  0x56,
+  /* 0000025B push cx                        */  0x51,
+  /* 0000025C push si                        */  0x56,
+  /* 0000025D mov si,0x3f6                   */  0xBE, 0xF6, 0x03,
+  /* 00000260 call word 0x3ad                */  0xE8, 0x4A, 0x01,
+  /* 00000263 pop si                         */  0x5E,
+  /* 00000264 and cx,0xbfff                  */  0x81, 0xE1, 0xFF, 0xBF,
+  /* 00000268 cmp cx,0x13f                   */  0x81, 0xF9, 0x3F, 0x01,
+  /* 0000026C jz 0x284                       */  0x74, 0x16,
+  /* 0000026E cmp cx,0x140                   */  0x81, 0xF9, 0x40, 0x01,
+  /* 00000272 jz 0x291                       */  0x74, 0x1D,
+  /* 00000274 cmp cx,0x141                   */  0x81, 0xF9, 0x41, 0x01,
+  /* 00000278 jz 0x29e                       */  0x74, 0x24,
+  /* 0000027A push si                        */  0x56,
+  /* 0000027B mov si,0x42c                   */  0xBE, 0x2C, 0x04,
+  /* 0000027E call word 0x3ad                */  0xE8, 0x2C, 0x01,
+  /* 00000281 pop si                         */  0x5E,
+  /* 00000282 jmp short 0x235                */  0xEB, 0xB1,
+  /* 00000284 push si                        */  0x56,
+  /* 00000285 mov si,0x46b                   */  0xBE, 0x6B, 0x04,
+  /* 00000288 call word 0x3ad                */  0xE8, 0x22, 0x01,
+  /* 0000028B pop si                         */  0x5E,
+  /* 0000028C mov si,0x100                   */  0xBE, 0x00, 0x01,
+  /* 0000028F jmp short 0x2b8                */  0xEB, 0x27,
+  /* 00000291 push si                        */  0x56,
+  /* 00000292 mov si,0x47d                   */  0xBE, 0x7D, 0x04,
+  /* 00000295 call word 0x3ad                */  0xE8, 0x15, 0x01,
+  /* 00000298 pop si                         */  0x5E,
+  /* 00000299 mov si,0x132                   */  0xBE, 0x32, 0x01,
+  /* 0000029C jmp short 0x2b8                */  0xEB, 0x1A,
+  /* 0000029E push si                        */  0x56,
+  /* 0000029F mov si,0x48f                   */  0xBE, 0x8F, 0x04,
+  /* 000002A2 call word 0x3ad                */  0xE8, 0x08, 0x01,
+  /* 000002A5 pop si                         */  0x5E,
+  /* 000002A6 mov si,0x164                   */  0xBE, 0x64, 0x01,
+  /* 000002A9 jmp short 0x2b8                */  0xEB, 0x0D,
+  /* 000002AB push si                        */  0x56,
+  /* 000002AC mov si,0x4a2                   */  0xBE, 0xA2, 0x04,
+  /* 000002AF call word 0x3ad                */  0xE8, 0xFB, 0x00,
+  /* 000002B2 pop si                         */  0x5E,
+  /* 000002B3 mov si,0x196                   */  0xBE, 0x96, 0x01,
+  /* 000002B6 jmp short 0x2b8                */  0xEB, 0x00,
+  /* 000002B8 push cs                        */  0x0E,
+  /* 000002B9 pop ds                         */  0x1F,
+  /* 000002BA mov cx,0x32                    */  0xB9, 0x32, 0x00,
+  /* 000002BD cld                            */  0xFC,
+  /* 000002BE rep movsb                      */  0xF3, 0xA4,
+  /* 000002C0 pop cx                         */  0x59,
+  /* 000002C1 pop si                         */  0x5E,
+  /* 000002C2 pop ds                         */  0x1F,
+  /* 000002C3 pop di                         */  0x5F,
+  /* 000002C4 pop es                         */  0x07,
+  /* 000002C5 jmp word 0x395                 */  0xE9, 0xCD, 0x00,
+  /* 000002C8 push dx                        */  0x52,
+  /* 000002C9 push ax                        */  0x50,
+  /* 000002CA push si                        */  0x56,
+  /* 000002CB mov si,0x410                   */  0xBE, 0x10, 0x04,
+  /* 000002CE call word 0x3ad                */  0xE8, 0xDC, 0x00,
+  /* 000002D1 pop si                         */  0x5E,
+  /* 000002D2 and bx,0xbfff                  */  0x81, 0xE3, 0xFF, 0xBF,
+  /* 000002D6 cmp bx,0x13f                   */  0x81, 0xFB, 0x3F, 0x01,
+  /* 000002DA jz 0x2f3                       */  0x74, 0x17,
+  /* 000002DC cmp bx,0x140                   */  0x81, 0xFB, 0x40, 0x01,
+  /* 000002E0 jz 0x2fd                       */  0x74, 0x1B,
+  /* 000002E2 cmp bx,0x141                   */  0x81, 0xFB, 0x41, 0x01,
+  /* 000002E6 jz 0x307                       */  0x74, 0x1F,
+  /* 000002E8 push si                        */  0x56,
+  /* 000002E9 mov si,0x42c                   */  0xBE, 0x2C, 0x04,
+  /* 000002EC call word 0x3ad                */  0xE8, 0xBE, 0x00,
+  /* 000002EF pop si                         */  0x5E,
+  /* 000002F0 jmp word 0x235                 */  0xE9, 0x42, 0xFF,
+  /* 000002F3 push si                        */  0x56,
+  /* 000002F4 mov si,0x46b                   */  0xBE, 0x6B, 0x04,
+  /* 000002F7 call word 0x3ad                */  0xE8, 0xB3, 0x00,
+  /* 000002FA pop si                         */  0x5E,
+  /* 000002FB jmp short 0x319                */  0xEB, 0x1C,
+  /* 000002FD push si                        */  0x56,
+  /* 000002FE mov si,0x47d                   */  0xBE, 0x7D, 0x04,
+  /* 00000301 call word 0x3ad                */  0xE8, 0xA9, 0x00,
+  /* 00000304 pop si                         */  0x5E,
+  /* 00000305 jmp short 0x319                */  0xEB, 0x12,
+  /* 00000307 push si                        */  0x56,
+  /* 00000308 mov si,0x48f                   */  0xBE, 0x8F, 0x04,
+  /* 0000030B call word 0x3ad                */  0xE8, 0x9F, 0x00,
+  /* 0000030E pop si                         */  0x5E,
+  /* 0000030F jmp short 0x319                */  0xEB, 0x08,
+  /* 00000311 push si                        */  0x56,
+  /* 00000312 mov si,0x4a2                   */  0xBE, 0xA2, 0x04,
+  /* 00000315 call word 0x3ad                */  0xE8, 0x95, 0x00,
+  /* 00000318 pop si                         */  0x5E,
+  /* 00000319 mov [0x4b0],bl                 */  0x88, 0x1E, 0xB0, 0x04,
+  /* 0000031D mov [0x4b1],bh                 */  0x88, 0x3E, 0xB1, 0x04,
+  /* 00000321 pop ax                         */  0x58,
+  /* 00000322 pop dx                         */  0x5A,
+  /* 00000323 jmp short 0x395                */  0xEB, 0x70,
+  /* 00000325 push si                        */  0x56,
+  /* 00000326 mov si,0x405                   */  0xBE, 0x05, 0x04,
+  /* 00000329 call word 0x3ad                */  0xE8, 0x81, 0x00,
+  /* 0000032C pop si                         */  0x5E,
+  /* 0000032D mov bl,[0x4b0]                 */  0x8A, 0x1E, 0xB0, 0x04,
+  /* 00000331 mov bh,[0x4b1]                 */  0x8A, 0x3E, 0xB1, 0x04,
+  /* 00000335 jmp short 0x395                */  0xEB, 0x5E,
+  /* 00000337 push si                        */  0x56,
+  /* 00000338 mov si,0x43b                   */  0xBE, 0x3B, 0x04,
+  /* 0000033B call word 0x3ad                */  0xE8, 0x6F, 0x00,
+  /* 0000033E pop si                         */  0x5E,
+  /* 0000033F mov bx,0x80                    */  0xBB, 0x80, 0x00,
+  /* 00000342 jmp short 0x395                */  0xEB, 0x51,
+  /* 00000344 push es                        */  0x06,
+  /* 00000345 push di                        */  0x57,
+  /* 00000346 push ds                        */  0x1E,
+  /* 00000347 push si                        */  0x56,
+  /* 00000348 push cx                        */  0x51,
+  /* 00000349 push si                        */  0x56,
+  /* 0000034A mov si,0x450                   */  0xBE, 0x50, 0x04,
+  /* 0000034D call word 0x3ad                */  0xE8, 0x5D, 0x00,
+  /* 00000350 pop si                         */  0x5E,
+  /* 00000351 push cs                        */  0x0E,
+  /* 00000352 pop ds                         */  0x1F,
+  /* 00000353 mov si,0x4b2                   */  0xBE, 0xB2, 0x04,
+  /* 00000356 mov cx,0x80                    */  0xB9, 0x80, 0x00,
+  /* 00000359 cld                            */  0xFC,
+  /* 0000035A rep movsb                      */  0xF3, 0xA4,
+  /* 0000035C pop cx                         */  0x59,
+  /* 0000035D pop si                         */  0x5E,
+  /* 0000035E pop ds                         */  0x1F,
+  /* 0000035F pop di                         */  0x5F,
+  /* 00000360 pop es                         */  0x07,
+  /* 00000361 jmp short 0x395                */  0xEB, 0x32,
+  /* 00000363 push si                        */  0x56,
+  /* 00000364 mov si,0x41b                   */  0xBE, 0x1B, 0x04,
+  /* 00000367 call word 0x3ad                */  0xE8, 0x43, 0x00,
+  /* 0000036A pop si                         */  0x5E,
+  /* 0000036B cmp al,0x3                     */  0x3C, 0x03,
+  /* 0000036D jz 0x37e                       */  0x74, 0x0F,
+  /* 0000036F cmp al,0x12                    */  0x3C, 0x12,
+  /* 00000371 jz 0x38a                       */  0x74, 0x17,
+  /* 00000373 push si                        */  0x56,
+  /* 00000374 mov si,0x42c                   */  0xBE, 0x2C, 0x04,
+  /* 00000377 call word 0x3ad                */  0xE8, 0x33, 0x00,
+  /* 0000037A pop si                         */  0x5E,
+  /* 0000037B jmp word 0x235                 */  0xE9, 0xB7, 0xFE,
+  /* 0000037E push si                        */  0x56,
+  /* 0000037F mov si,0x45c                   */  0xBE, 0x5C, 0x04,
+  /* 00000382 call word 0x3ad                */  0xE8, 0x28, 0x00,
+  /* 00000385 pop si                         */  0x5E,
+  /* 00000386 mov al,0x0                     */  0xB0, 0x00,
+  /* 00000388 jmp short 0x38c                */  0xEB, 0x02,
+  /* 0000038A mov al,0x0                     */  0xB0, 0x00,
+  /* 0000038C push si                        */  0x56,
+  /* 0000038D mov si,0x3c2                   */  0xBE, 0xC2, 0x03,
+  /* 00000390 call word 0x3ad                */  0xE8, 0x1A, 0x00,
+  /* 00000393 pop si                         */  0x5E,
+  /* 00000394 iretw                          */  0xCF,
+  /* 00000395 push si                        */  0x56,
+  /* 00000396 mov si,0x3c2                   */  0xBE, 0xC2, 0x03,
+  /* 00000399 call word 0x3ad                */  0xE8, 0x11, 0x00,
+  /* 0000039C pop si                         */  0x5E,
+  /* 0000039D mov ax,0x4f                    */  0xB8, 0x4F, 0x00,
+  /* 000003A0 iretw                          */  0xCF,
+  /* 000003A1 push si                        */  0x56,
+  /* 000003A2 mov si,0x3c8                   */  0xBE, 0xC8, 0x03,
+  /* 000003A5 call word 0x3ad                */  0xE8, 0x05, 0x00,
+  /* 000003A8 pop si                         */  0x5E,
+  /* 000003A9 mov ax,0x24f                   */  0xB8, 0x4F, 0x02,
+  /* 000003AC iretw                          */  0xCF,
+  /* 000003AD pushaw                         */  0x60,
+  /* 000003AE push ds                        */  0x1E,
+  /* 000003AF push cs                        */  0x0E,
+  /* 000003B0 pop ds                         */  0x1F,
+  /* 000003B1 mov dx,0x220                   */  0xBA, 0x20, 0x02,
+  /* 000003B4 mov ax,0x0                     */  0xB8, 0x00, 0x00,
+  /* 000003B7 lodsb                          */  0xAC,
+  /* 000003B8 cmp al,0x0                     */  0x3C, 0x00,
+  /* 000003BA jz 0x3bf                       */  0x74, 0x03,
+  /* 000003BC out dx,al                      */  0xEE,
+  /* 000003BD jmp short 0x3b7                */  0xEB, 0xF8,
+  /* 000003BF pop ds                         */  0x1F,
+  /* 000003C0 popaw                          */  0x61,
+  /* 000003C1 ret                            */  0xC3,
+  /* 000003C2 jna 0x413                      */  0x76, 0x4F,
+  /* 000003C4 imul cx,[di],byte +0xa         */  0x6B, 0x0D, 0x0A,
+  /* 000003C7 add [bp+0x55],dh               */  0x00, 0x76, 0x55,
+  /* 000003CA outsb                          */  0x6E,
+  /* 000003CB jnc 0x442                      */  0x73, 0x75,
+  /* 000003CD jo 0x43f                       */  0x70, 0x70,
+  /* 000003CF outsw                          */  0x6F,
+  /* 000003D0 jc 0x446                       */  0x72, 0x74,
+  /* 000003D2 fs or ax,0xa                   */  0x65, 0x64, 0x0D, 0x0A, 0x00,
+  /* 000003D7 jna 0x42e                      */  0x76, 0x55,
+  /* 000003D9 outsb                          */  0x6E,
+  /* 000003DA imul bp,[bp+0x6f],byte +0x77   */  0x6B, 0x6E, 0x6F, 0x77,
+  /* 000003DE outsb                          */  0x6E,
+  /* 000003DF and [bp+0x75],al               */  0x20, 0x46, 0x75,
+  /* 000003E2 outsb                          */  0x6E,
+  /* 000003E3 arpl [si+0x69],si              */  0x63, 0x74, 0x69,
+  /* 000003E6 outsw                          */  0x6F,
+  /* 000003E7 outsb                          */  0x6E,
+  /* 000003E8 or ax,0xa                      */  0x0D, 0x0A, 0x00,
+  /* 000003EB jna 0x434                      */  0x76, 0x47,
+  /* 000003ED gs jz 0x439                    */  0x65, 0x74, 0x49,
+  /* 000003F0 outsb                          */  0x6E,
+  /* 000003F1 outsd                          */  0x66, 0x6F,
+  /* 000003F3 or ax,0xa                      */  0x0D, 0x0A, 0x00,
+  /* 000003F6 jna 0x43f                      */  0x76, 0x47,
+  /* 000003F8 gs jz 0x448                    */  0x65, 0x74, 0x4D,
+  /* 000003FB outsw                          */  0x6F,
+  /* 000003FC gs dec cx                      */  0x64, 0x65, 0x49,
+  /* 000003FF outsb                          */  0x6E,
+  /* 00000400 outsd                          */  0x66, 0x6F,
+  /* 00000402 or ax,0xa                      */  0x0D, 0x0A, 0x00,
+  /* 00000405 jna 0x44e                      */  0x76, 0x47,
+  /* 00000407 gs jz 0x457                    */  0x65, 0x74, 0x4D,
+  /* 0000040A outsw                          */  0x6F,
+  /* 0000040B gs or ax,0xa                   */  0x64, 0x65, 0x0D, 0x0A, 0x00,
+  /* 00000410 jna 0x465                      */  0x76, 0x53,
+  /* 00000412 gs jz 0x462                    */  0x65, 0x74, 0x4D,
+  /* 00000415 outsw                          */  0x6F,
+  /* 00000416 gs or ax,0xa                   */  0x64, 0x65, 0x0D, 0x0A, 0x00,
+  /* 0000041B jna 0x470                      */  0x76, 0x53,
+  /* 0000041D gs jz 0x46d                    */  0x65, 0x74, 0x4D,
+  /* 00000420 outsw                          */  0x6F,
+  /* 00000421 gs dec sp                      */  0x64, 0x65, 0x4C,
+  /* 00000424 gs a32 popaw                   */  0x65, 0x67, 0x61,
+  /* 00000427 arpl [bx+di+0xd],di            */  0x63, 0x79, 0x0D,
+  /* 0000042A or al,[bx+si]                  */  0x0A, 0x00,
+  /* 0000042C jna 0x483                      */  0x76, 0x55,
+  /* 0000042E outsb                          */  0x6E,
+  /* 0000042F imul bp,[bx+0x77],byte +0x6e   */  0x6B, 0x6F, 0x77, 0x6E,
+  /* 00000433 and [di+0x6f],cl               */  0x20, 0x4D, 0x6F,
+  /* 00000436 gs or ax,0xa                   */  0x64, 0x65, 0x0D, 0x0A, 0x00,
+  /* 0000043B jna 0x484                      */  0x76, 0x47,
+  /* 0000043D gs jz 0x490                    */  0x65, 0x74, 0x50,
+  /* 00000440 insw                           */  0x6D,
+  /* 00000441 inc bx                         */  0x43,
+  /* 00000442 popaw                          */  0x61,
+  /* 00000443 jo 0x4a6                       */  0x70, 0x61,
+  /* 00000445 bound bp,[bx+di+0x6c]          */  0x62, 0x69, 0x6C,
+  /* 00000448 imul si,[si+0x69],word 0x7365  */  0x69, 0x74, 0x69, 0x65, 0x73,
+  /* 0000044D or ax,0xa                      */  0x0D, 0x0A, 0x00,
+  /* 00000450 jna 0x4a4                      */  0x76, 0x52,
+  /* 00000452 gs popaw                       */  0x65, 0x61,
+  /* 00000454 fs inc bp                      */  0x64, 0x45,
+  /* 00000456 imul sp,[fs:si+0xd],word 0xa   */  0x64, 0x69, 0x64, 0x0D, 0x0A, 0x00,
+  /* 0000045C jna 0x4aa                      */  0x76, 0x4C,
+  /* 0000045E gs a32 popaw                   */  0x65, 0x67, 0x61,
+  /* 00000461 arpl [bx+di+0x4d],di           */  0x63, 0x79, 0x4D,
+  /* 00000464 outsw                          */  0x6F,
+  /* 00000465 xor cx,[gs:di]                 */  0x64, 0x65, 0x33, 0x0D,
+  /* 00000469 or al,[bx+si]                  */  0x0A, 0x00,
+  /* 0000046B insw                           */  0x6D,
+  /* 0000046C outsw                          */  0x6F,
+  /* 0000046D gs pop di                      */  0x64, 0x65, 0x5F,
+  /* 00000470 ss xor al,0x30                 */  0x36, 0x34, 0x30,
+  /* 00000473 js 0x4a9                       */  0x78, 0x34,
+  /* 00000475 cmp [bx+si],dh                 */  0x38, 0x30,
+  /* 00000477 js 0x4ac                       */  0x78, 0x33,
+  /* 00000479 xor cl,[di]                    */  0x32, 0x0D,
+  /* 0000047B or al,[bx+si]                  */  0x0A, 0x00,
+  /* 0000047D insw                           */  0x6D,
+  /* 0000047E outsw                          */  0x6F,
+  /* 0000047F gs pop di                      */  0x64, 0x65, 0x5F,
+  /* 00000482 cmp [bx+si],dh                 */  0x38, 0x30,
+  /* 00000484 xor [bx+si+0x36],bh            */  0x30, 0x78, 0x36,
+  /* 00000487 xor [bx+si],dh                 */  0x30, 0x30,
+  /* 00000489 js 0x4be                       */  0x78, 0x33,
+  /* 0000048B xor cl,[di]                    */  0x32, 0x0D,
+  /* 0000048D or al,[bx+si]                  */  0x0A, 0x00,
+  /* 0000048F insw                           */  0x6D,
+  /* 00000490 outsw                          */  0x6F,
+  /* 00000491 gs pop di                      */  0x64, 0x65, 0x5F,
+  /* 00000494 xor [bx+si],si                 */  0x31, 0x30,
+  /* 00000496 xor dh,[si]                    */  0x32, 0x34,
+  /* 00000498 js 0x4d1                       */  0x78, 0x37,
+  /* 0000049A cmp [ss:bx+si+0x33],bh         */  0x36, 0x38, 0x78, 0x33,
+  /* 0000049E xor cl,[di]                    */  0x32, 0x0D,
+  /* 000004A0 or al,[bx+si]                  */  0x0A, 0x00,
+  /* 000004A2 insw                           */  0x6D,
+  /* 000004A3 outsw                          */  0x6F,
+  /* 000004A4 gs pop di                      */  0x64, 0x65, 0x5F,
+  /* 000004A7 jnz 0x517                      */  0x75, 0x6E,
+  /* 000004A9 jnz 0x51e                      */  0x75, 0x73,
+  /* 000004AB fs or ax,0xa                   */  0x65, 0x64, 0x0D, 0x0A, 0x00,
+  /* 000004B0 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004B2 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004B4 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004B6 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004B8 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004BA add [bx+si],al                 */  0x00, 0x00,
+  /* 000004BC add [bx+si],al                 */  0x00, 0x00,
+  /* 000004BE add [bx+si],al                 */  0x00, 0x00,
+  /* 000004C0 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004C2 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004C4 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004C6 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004C8 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004CA add [bx+si],al                 */  0x00, 0x00,
+  /* 000004CC add [bx+si],al                 */  0x00, 0x00,
+  /* 000004CE add [bx+si],al                 */  0x00, 0x00,
+  /* 000004D0 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004D2 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004D4 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004D6 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004D8 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004DA add [bx+si],al                 */  0x00, 0x00,
+  /* 000004DC add [bx+si],al                 */  0x00, 0x00,
+  /* 000004DE add [bx+si],al                 */  0x00, 0x00,
+  /* 000004E0 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004E2 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004E4 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004E6 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004E8 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004EA add [bx+si],al                 */  0x00, 0x00,
+  /* 000004EC add [bx+si],al                 */  0x00, 0x00,
+  /* 000004EE add [bx+si],al                 */  0x00, 0x00,
+  /* 000004F0 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004F2 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004F4 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004F6 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004F8 add [bx+si],al                 */  0x00, 0x00,
+  /* 000004FA add [bx+si],al                 */  0x00, 0x00,
+  /* 000004FC add [bx+si],al                 */  0x00, 0x00,
+  /* 000004FE add [bx+si],al                 */  0x00, 0x00,
+  /* 00000500 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000502 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000504 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000506 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000508 add [bx+si],al                 */  0x00, 0x00,
+  /* 0000050A add [bx+si],al                 */  0x00, 0x00,
+  /* 0000050C add [bx+si],al                 */  0x00, 0x00,
+  /* 0000050E add [bx+si],al                 */  0x00, 0x00,
+  /* 00000510 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000512 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000514 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000516 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000518 add [bx+si],al                 */  0x00, 0x00,
+  /* 0000051A add [bx+si],al                 */  0x00, 0x00,
+  /* 0000051C add [bx+si],al                 */  0x00, 0x00,
+  /* 0000051E add [bx+si],al                 */  0x00, 0x00,
+  /* 00000520 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000522 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000524 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000526 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000528 add [bx+si],al                 */  0x00, 0x00,
+  /* 0000052A add [bx+si],al                 */  0x00, 0x00,
+  /* 0000052C add [bx+si],al                 */  0x00, 0x00,
+  /* 0000052E add [bx+si],al                 */  0x00, 0x00,
+  /* 00000530 add [bx+si],al                 */  0x00, 0x00,
+  /* 00000532 add [bx+si],al                 */  0x00, 0x00,
+};
+#endif
diff --git a/BhyvePkg/BhyveRfbDxe/VbeShim.sh b/BhyvePkg/BhyveRfbDxe/VbeShim.sh
new file mode 100644
index 0000000000..0be8fbb8e6
--- /dev/null
+++ b/BhyvePkg/BhyveRfbDxe/VbeShim.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+###
+# @file
+# Shell script to assemble and dump the fake Int10h handler from NASM source to
+# a C array.
+#
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+###
+
+set -e -u
+
+STEM=$(dirname -- "$0")/$(basename -- "$0" .sh)
+
+#
+# Install exit handler -- remove temporary files.
+#
+exit_handler()
+{
+  rm -f -- "$STEM".bin "$STEM".disasm "$STEM".offsets "$STEM".insns \
+      "$STEM".bytes
+}
+trap exit_handler EXIT
+
+#
+# Assemble the source file.
+#
+nasm -o "$STEM".bin -- "$STEM".asm
+
+#
+# Disassemble it, in order to get a binary dump associated with the source.
+# (ndisasm doesn't recognize the "--" end-of-options delimiter.)
+#
+ndisasm "$STEM".bin >"$STEM".disasm
+
+#
+# Create three files, each with one column of the disassembly.
+#
+# The first column contains the offsets, and it starts the comment.
+#
+cut -c 1-8 -- "$STEM".disasm \
+| sed -e 's,^,  /* ,' >"$STEM".offsets
+
+#
+# The second column contains the assembly-language instructions, and it closes
+# the comment. We first pad it to 30 characters.
+#
+cut -c 29- -- "$STEM".disasm \
+| sed -e 's,$,                              ,' \
+      -e 's,^\(.\{30\}\).*$,\1 */,' >"$STEM".insns
+
+#
+# The third column contains the bytes corresponding to the instruction,
+# represented as C integer constants. First strip trailing whitespace from the
+# middle column of the input disassembly, then process pairs of nibbles.
+#
+cut -c 11-28 -- "$STEM".disasm \
+| sed -e 's, \+$,,' -e 's/\(..\)/ 0x\1,/g' | sed 's/0x  ,//g' >"$STEM".bytes
+
+#
+# Write the output file, recombining the columns. The output should have CRLF
+# line endings.
+#
+{
+  printf '//\n'
+  printf '// THIS FILE WAS GENERATED BY "%s". DO NOT EDIT.\n' \
+      "$(basename -- "$0")"
+  printf '//\n'
+  printf '#ifndef _VBE_SHIM_H_\n'
+  printf '#define _VBE_SHIM_H_\n'
+  printf 'STATIC CONST UINT8 mVbeShim[] = {\n'
+  paste -d ' ' -- "$STEM".offsets "$STEM".insns "$STEM".bytes
+  printf '};\n'
+  printf '#endif\n'
+} \
+| unix2dos >"$STEM".h
diff --git a/BhyvePkg/DecomprScratchEnd.fdf.inc b/BhyvePkg/DecomprScratchEnd.fdf.inc
new file mode 100644
index 0000000000..9137e84638
--- /dev/null
+++ b/BhyvePkg/DecomprScratchEnd.fdf.inc
@@ -0,0 +1,66 @@
+## @file
+#  This FDF include file computes the end of the scratch buffer used in
+#  DecompressMemFvs() [OvmfPkg/Sec/SecMain.c]. It is based on the decompressed
+#  (ie. original) size of the LZMA-compressed section of the one FFS file in
+#  the FVMAIN_COMPACT firmware volume.
+#
+#  Copyright (C) 2015, Red Hat, Inc.
+#
+#  SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+# The GUID EE4E5898-3914-4259-9D6E-DC7BD79403CF means "LzmaCustomDecompress".
+# The decompressed output will have the following structure (see the file
+# "9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.guided.dummy" in the
+# Build/Ovmf*/*/FV/Ffs/9E21FD93-9C72-4c15-8C4B-E77F1DB2D792/ directory):
+#
+# Size                 Contents
+# -------------------  --------------------------------------------------------
+#                   4  EFI_COMMON_SECTION_HEADER, stating size 124 (0x7C) and
+#                      type 0x19 (EFI_SECTION_RAW). The purpose of this section
+#                      is to pad the start of PEIFV to 128 bytes.
+#                 120  Zero bytes (padding).
+#
+#                   4  EFI_COMMON_SECTION_HEADER, stating size
+#                      (PcdOvmfPeiMemFvSize + 4), and type 0x17
+#                      (EFI_SECTION_FIRMWARE_VOLUME_IMAGE).
+# PcdOvmfPeiMemFvSize  PEIFV. Note that the above sizes pad the offset of this
+#                      object to 128 bytes. See also the "guided.dummy.txt"
+#                      file in the same directory.
+#
+#                   4  EFI_COMMON_SECTION_HEADER, stating size 12 (0xC) and
+#                      type 0x19 (EFI_SECTION_RAW). The purpose of this section
+#                      is to pad the start of DXEFV to 16 bytes.
+#                   8  Zero bytes (padding).
+#
+#                   4  EFI_COMMON_SECTION_HEADER, stating size
+#                      (PcdOvmfDxeMemFvSize + 4), and type 0x17
+#                      (EFI_SECTION_FIRMWARE_VOLUME_IMAGE).
+# PcdOvmfDxeMemFvSize  DXEFV. Note that the above sizes pad the offset of this
+#                      object to 16 bytes. See also the "guided.dummy.txt" file
+#                      in the same directory.
+#
+# The total size after decompression is (128 + PcdOvmfPeiMemFvSize + 16 +
+# PcdOvmfDxeMemFvSize).
+
+DEFINE OUTPUT_SIZE = (128 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize + 16 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize)
+
+# LzmaCustomDecompressLib uses a constant scratch buffer size of 64KB; see
+# SCRATCH_BUFFER_REQUEST_SIZE in
+# "MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c".
+
+DEFINE DECOMP_SCRATCH_SIZE = 0x00010000
+
+# Note: when we use PcdOvmfDxeMemFvBase in this context, BaseTools have not yet
+# offset it with MEMFD's base address. For that reason we have to do it manually.
+#
+# The calculation below mirrors DecompressMemFvs() [OvmfPkg/Sec/SecMain.c].
+
+DEFINE OUTPUT_BASE                   = ($(MEMFD_BASE_ADDRESS) + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase + 0x00100000)
+DEFINE DECOMP_SCRATCH_BASE_UNALIGNED = ($(OUTPUT_BASE) + $(OUTPUT_SIZE))
+DEFINE DECOMP_SCRATCH_BASE_ALIGNMENT = 0x000FFFFF
+DEFINE DECOMP_SCRATCH_BASE_MASK      = 0xFFF00000
+DEFINE DECOMP_SCRATCH_BASE           = (($(DECOMP_SCRATCH_BASE_UNALIGNED) + $(DECOMP_SCRATCH_BASE_ALIGNMENT)) & $(DECOMP_SCRATCH_BASE_MASK))
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd = $(DECOMP_SCRATCH_BASE) + $(DECOMP_SCRATCH_SIZE)
diff --git a/BhyvePkg/Include/Library/BhyveFwCtlLib.h b/BhyvePkg/Include/Library/BhyveFwCtlLib.h
new file mode 100644
index 0000000000..307f9393a5
--- /dev/null
+++ b/BhyvePkg/Include/Library/BhyveFwCtlLib.h
@@ -0,0 +1,46 @@
+/** @file
+  bhyve firmware configuration access
+
+  Copyright (c) 2015 Nahanni Systems
+
+  SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+#ifndef __BHYVE_FW_CTL_LIB__
+#define __BHYVE_FW_CTL_LIB__
+
+/**
+  Sysctl-like interface to read host information via a dot-separated
+  ASCII OID.
+
+  The information is copied into the buffer specified by Item. The
+  size of the buffer is given by the location specified by Size
+  before the call, and that location gives the amount of data copied
+  after a successfull call, and after a call that returns a truncated
+  value with an error return of RETURN_BUFFER_TOO_SMALL.
+
+  The size of the available data can be determined by passing a NULL
+  argument for Item. The size will be returned in the location pointed
+  to by Size.
+
+  @param[]  Name    - ASCII OID name
+  @param[]  Data    - return buffer pointer
+  @param[]  Size    - pointer to length
+
+  @return    RETURN_SUCCESS          Valid data/len returned.
+          RETURN_UNSUPPORTED        f/w interface not present.
+          RETURN_NOT_FOUND      OID not found.
+        RETURN_BUFFER_TOO_SMALL      Return message truncated.
+        RETURN_INVALID_PARAMETER  Buffer too large
+        RETURN_PROTOCOL_ERROR     Unknown error from host
+ **/
+RETURN_STATUS
+EFIAPI
+BhyveFwCtlGet (
+  IN   CONST CHAR8    *Name,
+  OUT  VOID        *Item,
+  IN OUT  UINTN        *Size
+  );
+
+#endif
diff --git a/BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c b/BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c
new file mode 100644
index 0000000000..41bb725e2c
--- /dev/null
+++ b/BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c
@@ -0,0 +1,425 @@
+/** @file
+
+  Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
+  Copyright (C) 2013, Red Hat, Inc.
+  Copyright (c) 2015, Nahanni Systems.
+
+  SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+#include "Uefi.h"
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/BhyveFwCtlLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define FW_PORT        0x510
+#define FW_IPORT    0x511
+
+/* Transport protocol basic operations */
+#define OP_NULL        1
+#define OP_ECHO        2
+#define OP_GET        3
+#define OP_GET_LEN    4
+#define OP_SET        5
+
+/* Transport protocol error returns */
+#define T_ESUCCESS    0
+#define T_ENOENT    2
+#define T_E2BIG        7
+#define T_EMSGSIZE    40
+
+#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
+
+STATIC CONST CHAR8 mBhyveSig[4] = { 'B', 'H', 'Y', 'V' };
+
+STATIC BOOLEAN mBhyveFwCtlSupported = FALSE;
+
+STATIC INTN mBhyveFwCtlTxid = 0xa5;
+
+/* XXX Maybe a better inbuilt version of this ? */
+struct BIoVec {
+  VOID        *Base;
+  UINTN        Len;
+};
+
+struct MsgRxHdr {
+  UINT32    Sz;
+  UINT32    Op;
+  UINT32    TxId;
+  UINT32    Err;
+};
+
+STATIC
+RETURN_STATUS
+EFIAPI
+BhyveFwCtl_CvtErr (
+   IN UINT32    errno
+   )
+{
+  RETURN_STATUS        Status;
+
+  switch (errno) {
+  case T_ESUCCESS:
+    Status = RETURN_SUCCESS;
+    break;
+  case T_ENOENT:
+    Status = RETURN_NOT_FOUND;
+    break;
+  case T_E2BIG:
+    Status = RETURN_INVALID_PARAMETER;
+    break;
+  case T_EMSGSIZE:
+    Status = RETURN_BUFFER_TOO_SMALL;
+    break;
+  default:
+    Status = RETURN_PROTOCOL_ERROR;
+    break;
+  }
+
+  return Status;
+}
+
+STATIC
+UINTN
+EFIAPI
+BIov_WLen (
+   IN struct BIoVec b[]
+   )
+{
+  UINTN        i;
+  UINTN        tLen;
+
+  tLen = 0;
+
+  if (b != NULL) {
+    for (i = 0; b[i].Base != NULL; i++)
+      tLen += ROUNDUP (b[i].Len, sizeof(UINT32));
+  }
+
+  return tLen;
+}
+
+/**
+   Utility to send 1-3 bhyes of input as a 4-byte value
+   with trailing zeroes.
+ **/
+STATIC
+UINT32
+BIov_Send_Rem (
+   IN UINT32        *Data,
+   IN UINTN        Len
+   )
+{
+  union {
+    UINT8    c[4];
+    UINT32    w;
+  } u;
+  UINT8        *cdata;
+  UINTN        i;
+
+  cdata = (UINT8 *)Data;
+  u.w = 0;
+
+  for (i = 0; i < Len; i++)
+    u.c[i] = *cdata++;
+
+  return u.w;
+}
+
+/**
+   Send a block of data out the i/o port as 4-byte quantities,
+   appending trailing zeroes on the last if required.
+ **/
+STATIC
+VOID
+BIov_Send (
+  IN char    *Data,
+  IN UINTN    Len
+  )
+{
+  UINT32    *LData;
+
+  LData = (UINT32 *)Data;
+
+  while (Len > sizeof(UINT32)) {
+    IoWrite32 (FW_PORT, *LData++);
+    Len -= sizeof(UINT32);
+  }
+
+  if (Len > 0) {
+    IoWrite32 (FW_PORT, BIov_Send_Rem (LData, Len));
+  }
+}
+
+/**
+   Send data described by an array of iovecs out the i/o port.
+ **/
+STATIC
+VOID
+BIov_SendAll (
+   IN  struct BIoVec b[]
+   )
+{
+  INTN        i;
+
+  if (b != NULL) {
+    for (i = 0; b[i].Base; i++) {
+      BIov_Send (b[i].Base, b[i].Len);
+    }
+  }
+}
+
+/**
+   Prepend the transport header to a block of data and send.
+ **/
+STATIC
+VOID
+EFIAPI
+BhyveFwCtl_MsgSend(
+   IN  UINTN    OpCode,
+   IN  struct BIoVec Data[]
+   )
+{
+  struct BIoVec        hIov[4];
+  UINTN        Hdr[3];
+  UINTN            i;
+
+  /* Set up header as an iovec */
+  for (i = 0; i < 3; i++) {
+    hIov[i].Base = &Hdr[i];
+    hIov[i].Len  = sizeof(Hdr[0]);
+  }
+  hIov[i].Base = NULL;
+  hIov[i].Len = 0;
+
+  /* Initialize header */
+  Hdr[0] = BIov_WLen (hIov) + BIov_WLen (Data);
+  Hdr[1] = OpCode;
+  Hdr[2] = mBhyveFwCtlTxid;
+
+  /* Send header and data */
+  BIov_SendAll (hIov);
+  BIov_SendAll (Data);
+}
+
+/**
+   Read a transport response and optional data from the i/o port.
+ **/
+STATIC
+RETURN_STATUS
+EFIAPI
+BhyveFwCtl_MsgRecv(
+   OUT  struct MsgRxHdr    *Rhdr,
+   OUT  struct BIoVec    Data[]
+   )
+{
+  RETURN_STATUS        Status;
+  UINT32        *Dp;
+  UINT32        Rd;
+  UINTN         remLen;
+  INTN            oLen, xLen;
+
+  Rd = IoRead32 (FW_PORT);
+  if (Rd < sizeof(struct MsgRxHdr)) {
+    ;
+  }
+
+  /* Read in header and setup initial error */
+  Rhdr->Sz   = Rd;
+  Rhdr->Op   = IoRead32 (FW_PORT);
+  Rhdr->TxId = IoRead32 (FW_PORT);
+  Rhdr->Err  = IoRead32 (FW_PORT);
+
+  /* Convert transport errno into UEFI error status */
+  Status = BhyveFwCtl_CvtErr(Rhdr->Err);
+
+  remLen = Rd - sizeof(struct MsgRxHdr);
+  xLen = 0;
+
+  /*
+   * A few cases to handle:
+   *  - the user didn't supply a read buffer
+   *  - the buffer is too small for the response
+   *  - the response is zero-length
+   */
+  if (Data != NULL) {
+    Dp = (UINT32 *)Data[0].Base;
+    oLen = remLen;
+    if (remLen > Data[0].Len) {
+      Status = RETURN_BUFFER_TOO_SMALL;
+      xLen = remLen - Data[0].Len;
+      oLen = remLen = Data[0].Len;
+    }
+    while (remLen > 0) {
+      *Dp++ = IoRead32 (FW_PORT);
+      remLen -= sizeof(UINT32);
+    }
+    Data[0].Len = oLen;
+  } else {
+    /* No user data, but data returned - drop */
+    if (remLen > 0) {
+      Status = RETURN_BUFFER_TOO_SMALL;
+      xLen = remLen;
+    }
+  }
+
+  /* Drop additional data */
+  while (xLen > 0) {
+    (void) IoRead32 (FW_PORT);
+    xLen -= sizeof(UINT32);
+  }
+
+  return Status;
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+BhyveFwCtl_Msg(
+   IN   UINTN    OpCode,
+   IN   struct BIoVec Sdata[],
+   OUT  struct BIoVec Rdata[]
+   )
+{
+  struct MsgRxHdr     Rh;
+  RETURN_STATUS        Status;
+
+  Status = RETURN_SUCCESS;
+
+  BhyveFwCtl_MsgSend (OpCode, Sdata);
+  Status = BhyveFwCtl_MsgRecv (&Rh, Rdata);
+
+  mBhyveFwCtlTxid++;
+
+  return Status;
+}
+
+STATIC
+RETURN_STATUS
+EFIAPI
+BhyveFwCtlGetLen (
+  IN   CONST CHAR8    *Name,
+  IN OUT  UINTN        *Size
+  )
+{
+  struct BIoVec        Req[2], Resp[2];
+  RETURN_STATUS        Status;
+
+  Req[0].Base = (VOID *)Name;
+  Req[0].Len  = AsciiStrLen (Name) + 1;
+  Req[1].Base = NULL;
+
+  Resp[0].Base = Size;
+  Resp[0].Len  = sizeof(UINTN);
+  Resp[1].Base = NULL;
+
+  Status = BhyveFwCtl_Msg (OP_GET_LEN, Req, Resp);
+
+  return Status;
+}
+
+#define FMAXSZ    1024
+STATIC struct {
+  UINT64    fSize;
+  UINT32    fData[FMAXSZ];
+} FwGetvalBuf;
+
+STATIC
+RETURN_STATUS
+EFIAPI
+BhyveFwCtlGetVal (
+  IN   CONST CHAR8    *Name,
+  OUT  VOID        *Item,
+  IN OUT  UINTN        *Size
+  )
+{
+  struct BIoVec        Req[2], Resp[2];
+  RETURN_STATUS        Status;
+
+  /* Make sure temp buffer is larger than passed-in size */
+  if (*Size > sizeof(FwGetvalBuf.fData))
+      return RETURN_INVALID_PARAMETER;
+
+  Req[0].Base = (VOID *)Name;
+  Req[0].Len  = AsciiStrLen(Name) + 1;
+  Req[1].Base = NULL;
+
+  Resp[0].Base = &FwGetvalBuf;
+  Resp[0].Len  = sizeof(UINT64) + *Size;
+  Resp[1].Base = NULL;
+
+  Status = BhyveFwCtl_Msg (OP_GET, Req, Resp);
+
+  /*
+   * Copy out data on success (or on a truncated message).
+   * XXX This step can be eliminted with Msg() supporting
+   *     multiple iovecs.
+   */
+  if ((Status == RETURN_SUCCESS) || (Status == RETURN_BUFFER_TOO_SMALL)) {
+    *Size = FwGetvalBuf.fSize;
+    CopyMem (Item, FwGetvalBuf.fData, *Size);
+  }
+
+  return Status;
+}
+
+/**
+   Front end to the internal GET_LEN and GET protocols
+ **/
+RETURN_STATUS
+EFIAPI
+BhyveFwCtlGet (
+  IN   CONST CHAR8    *Name,
+  OUT  VOID        *Item,
+  IN OUT  UINTN        *Size
+  )
+{
+  RETURN_STATUS        Status;
+
+  if (mBhyveFwCtlSupported == FALSE)
+    return RETURN_UNSUPPORTED;
+
+  if (Item == NULL) {
+    Status = BhyveFwCtlGetLen (Name, Size);
+  } else {
+    Status = BhyveFwCtlGetVal (Name, Item, Size);
+  }
+
+  return Status;
+}
+
+
+/**
+   Library initialization. Probe the host to see if the f/w ctl
+   interface is supported.
+ **/
+RETURN_STATUS
+EFIAPI
+BhyveFwCtlInitialize (
+          VOID
+         )
+{
+  UINTN        i;
+  UINT8        ch;
+
+  DEBUG ((DEBUG_INFO, "FwCtlInitialize\n"));
+
+  IoWrite16 (FW_PORT, 0x0000);
+  for (i = 0; i < 4; i++) {
+    ch = IoRead8 (FW_IPORT);
+    if (ch != mBhyveSig[i]) {
+      DEBUG ((DEBUG_INFO, "Host f/w sig mismatch %c/%c\n", ch, mBhyveSig[i]));
+      return RETURN_SUCCESS;
+    }
+  }
+
+  mBhyveFwCtlSupported = TRUE;
+
+  return RETURN_SUCCESS;
+}
diff --git a/BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf b/BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
new file mode 100644
index 0000000000..4c5577f3b6
--- /dev/null
+++ b/BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
@@ -0,0 +1,40 @@
+## @file
+#
+#  Copyright (C) 2015 Nahanni Systems
+#  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = BhyveFwCtlLib
+  FILE_GUID                      = fd982666-67f9-11e5-a42a-0025908602f6
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = BhyveFwCtlLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER
+
+  CONSTRUCTOR                    = BhyveFwCtlInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = X64
+#
+
+[Sources]
+  BhyveFwCtlLib.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  BhyvePkg/BhyvePkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  DebugLib
+  IoLib
+  MemoryAllocationLib
+  IntrinsicLib
+
diff --git a/BhyvePkg/Library/PlatformBootManagerLib/BdsPlatform.c b/BhyvePkg/Library/PlatformBootManagerLib/BdsPlatform.c
new file mode 100644
index 0000000000..6a37a8fd3d
--- /dev/null
+++ b/BhyvePkg/Library/PlatformBootManagerLib/BdsPlatform.c
@@ -0,0 +1,1660 @@
+/** @file
+  Platform BDS customizations.
+
+  Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+#include "BdsPlatform.h"
+#include <Guid/RootBridgesConnectedEventGroup.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Library/PlatformBmPrintScLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+
+#include <Protocol/BlockIo.h>
+
+//
+// Global data
+//
+
+VOID          *mEfiDevPathNotifyReg;
+EFI_EVENT     mEfiDevPathEvent;
+VOID          *mEmuVariableEventReg;
+EFI_EVENT     mEmuVariableEvent;
+UINT16        mHostBridgeDevId;
+
+//
+// Table of host IRQs matching PCI IRQs A-D
+// (for configuring PCI Interrupt Line register)
+//
+CONST UINT8 PciHostIrqs[] = {
+  0x0a, 0x0a, 0x0b, 0x0b
+};
+
+//
+// Type definitions
+//
+
+typedef
+EFI_STATUS
+(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
+  IN EFI_HANDLE           Handle,
+  IN VOID                 *Instance,
+  IN VOID                 *Context
+  );
+
+/**
+  @param[in]  Handle - Handle of PCI device instance
+  @param[in]  PciIo - PCI IO protocol instance
+  @param[in]  Pci - PCI Header register block
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
+  IN EFI_HANDLE           Handle,
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN PCI_TYPE00           *Pci
+  );
+
+
+//
+// Function prototypes
+//
+
+EFI_STATUS
+VisitAllInstancesOfProtocol (
+  IN EFI_GUID                    *Id,
+  IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,
+  IN VOID                        *Context
+  );
+
+EFI_STATUS
+VisitAllPciInstancesOfProtocol (
+  IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+  );
+
+VOID
+InstallDevicePathCallback (
+  VOID
+  );
+
+VOID
+PlatformRegisterFvBootOption (
+  EFI_GUID                         *FileGuid,
+  CHAR16                           *Description,
+  UINT32                           Attributes
+  )
+{
+  EFI_STATUS                        Status;
+  INTN                              OptionIndex;
+  EFI_BOOT_MANAGER_LOAD_OPTION      NewOption;
+  EFI_BOOT_MANAGER_LOAD_OPTION      *BootOptions;
+  UINTN                             BootOptionCount;
+  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+  EFI_LOADED_IMAGE_PROTOCOL         *LoadedImage;
+  EFI_DEVICE_PATH_PROTOCOL          *DevicePath;
+
+  Status = gBS->HandleProtocol (
+                  gImageHandle,
+                  &gEfiLoadedImageProtocolGuid,
+                  (VOID **) &LoadedImage
+                  );
+  ASSERT_EFI_ERROR (Status);
+
+  EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
+  DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
+  ASSERT (DevicePath != NULL);
+  DevicePath = AppendDevicePathNode (
+                 DevicePath,
+                 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+                 );
+  ASSERT (DevicePath != NULL);
+
+  Status = EfiBootManagerInitializeLoadOption (
+             &NewOption,
+             LoadOptionNumberUnassigned,
+             LoadOptionTypeBoot,
+             Attributes,
+             Description,
+             DevicePath,
+             NULL,
+             0
+             );
+  ASSERT_EFI_ERROR (Status);
+  FreePool (DevicePath);
+
+  BootOptions = EfiBootManagerGetLoadOptions (
+                  &BootOptionCount, LoadOptionTypeBoot
+                  );
+
+  OptionIndex = EfiBootManagerFindLoadOption (
+                  &NewOption, BootOptions, BootOptionCount
+                  );
+
+  if (OptionIndex == -1) {
+    Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
+    ASSERT_EFI_ERROR (Status);
+  }
+  EfiBootManagerFreeLoadOption (&NewOption);
+  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+/**
+  Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
+  whose device paths do not resolve exactly to an FvFile in the system.
+
+  This removes any boot options that point to binaries built into the firmware
+  and have become stale due to any of the following:
+  - DXEFV's base address or size changed (historical),
+  - DXEFV's FvNameGuid changed,
+  - the FILE_GUID of the pointed-to binary changed,
+  - the referenced binary is no longer built into the firmware.
+
+  EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
+  avoids exact duplicates.
+**/
+VOID
+RemoveStaleFvFileOptions (
+  VOID
+  )
+{
+  EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+  UINTN                        BootOptionCount;
+  UINTN                        Index;
+
+  BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,
+                  LoadOptionTypeBoot);
+
+  for (Index = 0; Index < BootOptionCount; ++Index) {
+    EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
+    EFI_STATUS               Status;
+    EFI_HANDLE               FvHandle;
+
+    //
+    // If the device path starts with neither MemoryMapped(...) nor Fv(...),
+    // then keep the boot option.
+    //
+    Node1 = BootOptions[Index].FilePath;
+    if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&
+          DevicePathSubType (Node1) == HW_MEMMAP_DP) &&
+        !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&
+          DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {
+      continue;
+    }
+
+    //
+    // If the second device path node is not FvFile(...), then keep the boot
+    // option.
+    //
+    Node2 = NextDevicePathNode (Node1);
+    if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||
+        DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {
+      continue;
+    }
+
+    //
+    // Locate the Firmware Volume2 protocol instance that is denoted by the
+    // boot option. If this lookup fails (i.e., the boot option references a
+    // firmware volume that doesn't exist), then we'll proceed to delete the
+    // boot option.
+    //
+    SearchNode = Node1;
+    Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,
+                    &SearchNode, &FvHandle);
+
+    if (!EFI_ERROR (Status)) {
+      //
+      // The firmware volume was found; now let's see if it contains the FvFile
+      // identified by GUID.
+      //
+      EFI_FIRMWARE_VOLUME2_PROTOCOL     *FvProtocol;
+      MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
+      UINTN                             BufferSize;
+      EFI_FV_FILETYPE                   FoundType;
+      EFI_FV_FILE_ATTRIBUTES            FileAttributes;
+      UINT32                            AuthenticationStatus;
+
+      Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid,
+                      (VOID **)&FvProtocol);
+      ASSERT_EFI_ERROR (Status);
+
+      FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
+      //
+      // Buffer==NULL means we request metadata only: BufferSize, FoundType,
+      // FileAttributes.
+      //
+      Status = FvProtocol->ReadFile (
+                             FvProtocol,
+                             &FvFileNode->FvFileName, // NameGuid
+                             NULL,                    // Buffer
+                             &BufferSize,
+                             &FoundType,
+                             &FileAttributes,
+                             &AuthenticationStatus
+                             );
+      if (!EFI_ERROR (Status)) {
+        //
+        // The FvFile was found. Keep the boot option.
+        //
+        continue;
+      }
+    }
+
+    //
+    // Delete the boot option.
+    //
+    Status = EfiBootManagerDeleteLoadOptionVariable (
+               BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
+    DEBUG_CODE (
+      CHAR16 *DevicePathString;
+
+      DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,
+                           FALSE, FALSE);
+      DEBUG ((
+        EFI_ERROR (Status) ? EFI_D_WARN : DEBUG_VERBOSE,
+        "%a: removing stale Boot#%04x %s: %r\n",
+        __FUNCTION__,
+        (UINT32)BootOptions[Index].OptionNumber,
+        DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
+        Status
+        ));
+      if (DevicePathString != NULL) {
+        FreePool (DevicePathString);
+      }
+      );
+  }
+
+  EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+VOID
+PlatformRegisterOptionsAndKeys (
+  VOID
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_INPUT_KEY                Enter;
+  EFI_INPUT_KEY                F2;
+  EFI_INPUT_KEY                Esc;
+  EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
+
+  //
+  // Register ENTER as CONTINUE key
+  //
+  Enter.ScanCode    = SCAN_NULL;
+  Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
+  Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Map F2 to Boot Manager Menu
+  //
+  F2.ScanCode     = SCAN_F2;
+  F2.UnicodeChar  = CHAR_NULL;
+  Esc.ScanCode    = SCAN_ESC;
+  Esc.UnicodeChar = CHAR_NULL;
+  Status = EfiBootManagerGetBootManagerMenu (&BootOption);
+  ASSERT_EFI_ERROR (Status);
+  Status = EfiBootManagerAddKeyOptionVariable (
+             NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL
+             );
+  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
+  Status = EfiBootManagerAddKeyOptionVariable (
+             NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL
+             );
+  ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
+}
+
+EFI_STATUS
+EFIAPI
+ConnectRootBridge (
+  IN EFI_HANDLE  RootBridgeHandle,
+  IN VOID        *Instance,
+  IN VOID        *Context
+  );
+
+STATIC
+EFI_STATUS
+EFIAPI
+ConnectVirtioPciRng (
+  IN EFI_HANDLE Handle,
+  IN VOID       *Instance,
+  IN VOID       *Context
+  );
+
+STATIC
+VOID
+SaveS3BootScript (
+  VOID
+  );
+
+//
+// BDS Platform Functions
+//
+/**
+  Do the platform init, can be customized by OEM/IBV
+
+  Possible things that can be done in PlatformBootManagerBeforeConsole:
+
+  > Update console variable: 1. include hot-plug devices;
+  >                          2. Clear ConIn and add SOL for AMT
+  > Register new Driver#### or Boot####
+  > Register new Key####: e.g.: F12
+  > Signal ReadyToLock event
+  > Authentication action: 1. connect Auth devices;
+  >                        2. Identify auto logon user.
+**/
+VOID
+EFIAPI
+PlatformBootManagerBeforeConsole (
+  VOID
+  )
+{
+  EFI_HANDLE    Handle;
+  EFI_STATUS    Status;
+
+  DEBUG ((DEBUG_INFO, "PlatformBootManagerBeforeConsole\n"));
+  InstallDevicePathCallback ();
+
+  VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,
+    ConnectRootBridge, NULL);
+
+  //
+  // Signal the ACPI platform driver that it can download QEMU ACPI tables.
+  //
+  EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);
+
+  //
+  // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
+  // the preparation of S3 system information. That logic has a hard dependency
+  // on the presence of the FACS ACPI table. Since our ACPI tables are only
+  // installed after PCI enumeration completes, we must not trigger the S3 save
+  // earlier, hence we can't signal End-of-Dxe earlier.
+  //
+  EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
+
+  //
+  // Prevent further changes to LockBoxes or SMRAM.
+  //
+  Handle = NULL;
+  Status = gBS->InstallProtocolInterface (&Handle,
+                  &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,
+                  NULL);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Dispatch deferred images after EndOfDxe event and ReadyToLock
+  // installation.
+  //
+  EfiBootManagerDispatchDeferredImages ();
+
+  PlatformInitializeConsole (gPlatformConsole);
+
+  PlatformRegisterOptionsAndKeys ();
+
+  //
+  // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
+  // instances on Virtio PCI RNG devices.
+  //
+  VisitAllInstancesOfProtocol (&gEfiPciIoProtocolGuid, ConnectVirtioPciRng,
+    NULL);
+}
+
+
+EFI_STATUS
+EFIAPI
+ConnectRootBridge (
+  IN EFI_HANDLE  RootBridgeHandle,
+  IN VOID        *Instance,
+  IN VOID        *Context
+  )
+{
+  EFI_STATUS Status;
+
+  //
+  // Make the PCI bus driver connect the root bridge, non-recursively. This
+  // will produce a number of child handles with PciIo on them.
+  //
+  Status = gBS->ConnectController (
+                  RootBridgeHandle, // ControllerHandle
+                  NULL,             // DriverImageHandle
+                  NULL,             // RemainingDevicePath -- produce all
+                                    //   children
+                  FALSE             // Recursive
+                  );
+  return Status;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+ConnectVirtioPciRng (
+  IN EFI_HANDLE Handle,
+  IN VOID       *Instance,
+  IN VOID       *Context
+  )
+{
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  EFI_STATUS          Status;
+  UINT16              VendorId;
+  UINT16              DeviceId;
+  UINT8               RevisionId;
+  BOOLEAN             Virtio10;
+  UINT16              SubsystemId;
+
+  PciIo = Instance;
+
+  //
+  // Read and check VendorId.
+  //
+  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_VENDOR_ID_OFFSET,
+                        1, &VendorId);
+  if (EFI_ERROR (Status)) {
+    goto Error;
+  }
+  if (VendorId != VIRTIO_VENDOR_ID) {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Read DeviceId and RevisionId.
+  //
+  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_DEVICE_ID_OFFSET,
+                        1, &DeviceId);
+  if (EFI_ERROR (Status)) {
+    goto Error;
+  }
+  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_REVISION_ID_OFFSET,
+                        1, &RevisionId);
+  if (EFI_ERROR (Status)) {
+    goto Error;
+  }
+
+  //
+  // From DeviceId and RevisionId, determine whether the device is a
+  // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
+  // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
+  // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
+  // only be sanity-checked, and SubsystemId will decide.
+  //
+  if (DeviceId == 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE &&
+      RevisionId >= 0x01) {
+    Virtio10 = TRUE;
+  } else if (DeviceId >= 0x1000 && DeviceId <= 0x103F && RevisionId == 0x00) {
+    Virtio10 = FALSE;
+  } else {
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Read and check SubsystemId as dictated by Virtio10.
+  //
+  Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16,
+                        PCI_SUBSYSTEM_ID_OFFSET, 1, &SubsystemId);
+  if (EFI_ERROR (Status)) {
+    goto Error;
+  }
+  if ((Virtio10 && SubsystemId >= 0x40) ||
+      (!Virtio10 && SubsystemId == VIRTIO_SUBSYSTEM_ENTROPY_SOURCE)) {
+    Status = gBS->ConnectController (
+                    Handle, // ControllerHandle
+                    NULL,   // DriverImageHandle -- connect all drivers
+                    NULL,   // RemainingDevicePath -- produce all child handles
+                    FALSE   // Recursive -- don't follow child handles
+                    );
+    if (EFI_ERROR (Status)) {
+      goto Error;
+    }
+  }
+  return EFI_SUCCESS;
+
+Error:
+  DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, Status));
+  return Status;
+}
+
+
+/**
+  Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
+
+  @param[in] DeviceHandle  Handle of the LPC Bridge device.
+
+  @retval EFI_SUCCESS  Console devices on the LPC bridge have been added to
+                       ConOut, ConIn, and ErrOut.
+
+  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+                       from DeviceHandle.
+**/
+EFI_STATUS
+PrepareLpcBridgeDevicePath (
+  IN EFI_HANDLE                DeviceHandle
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
+  CHAR16                    *DevPathStr;
+
+  DevicePath = NULL;
+  Status = gBS->HandleProtocol (
+                  DeviceHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID*)&DevicePath
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  TempDevicePath = DevicePath;
+
+  //
+  // Register Keyboard
+  //
+  DevicePath = AppendDevicePathNode (DevicePath,
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
+
+  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+
+  //
+  // Register COM1
+  //
+  DevicePath = TempDevicePath;
+  gPnp16550ComPortDeviceNode.UID = 0;
+
+  DevicePath = AppendDevicePathNode (DevicePath,
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
+  DevicePath = AppendDevicePathNode (DevicePath,
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+  DevicePath = AppendDevicePathNode (DevicePath,
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+  //
+  // Print Device Path
+  //
+  DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+  if (DevPathStr != NULL) {
+    DEBUG((
+      DEBUG_INFO,
+      "BdsPlatform.c+%d: COM%d DevPath: %s\n",
+      __LINE__,
+      gPnp16550ComPortDeviceNode.UID + 1,
+      DevPathStr
+      ));
+    FreePool(DevPathStr);
+  }
+
+  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+  // Don't register COM2 which can be used for DBG instead so keep it clean
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetGopDevicePath (
+   IN  EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
+   OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
+   )
+{
+  UINTN                           Index;
+  EFI_STATUS                      Status;
+  EFI_HANDLE                      PciDeviceHandle;
+  EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL        *TempPciDevicePath;
+  UINTN                           GopHandleCount;
+  EFI_HANDLE                      *GopHandleBuffer;
+
+  if (PciDevicePath == NULL || GopDevicePath == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Initialize the GopDevicePath to be PciDevicePath
+  //
+  *GopDevicePath    = PciDevicePath;
+  TempPciDevicePath = PciDevicePath;
+
+  Status = gBS->LocateDevicePath (
+                  &gEfiDevicePathProtocolGuid,
+                  &TempPciDevicePath,
+                  &PciDeviceHandle
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Try to connect this handle, so that GOP driver could start on this
+  // device and create child handles with GraphicsOutput Protocol installed
+  // on them, then we get device paths of these child handles and select
+  // them as possible console device.
+  //
+  gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
+
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiGraphicsOutputProtocolGuid,
+                  NULL,
+                  &GopHandleCount,
+                  &GopHandleBuffer
+                  );
+  if (!EFI_ERROR (Status)) {
+    //
+    // Add all the child handles as possible Console Device
+    //
+    for (Index = 0; Index < GopHandleCount; Index++) {
+      Status = gBS->HandleProtocol (GopHandleBuffer[Index],
+                      &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
+      if (EFI_ERROR (Status)) {
+        continue;
+      }
+      if (CompareMem (
+            PciDevicePath,
+            TempDevicePath,
+            GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
+            ) == 0) {
+        //
+        // In current implementation, we only enable one of the child handles
+        // as console device, i.e. sotre one of the child handle's device
+        // path to variable "ConOut"
+        // In future, we could select all child handles to be console device
+        //
+
+        *GopDevicePath = TempDevicePath;
+
+        //
+        // Delete the PCI device's path that added by
+        // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
+        //
+        EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);
+        EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);
+      }
+    }
+    gBS->FreePool (GopHandleBuffer);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Add PCI display to ConOut.
+
+  @param[in] DeviceHandle  Handle of the PCI display device.
+
+  @retval EFI_SUCCESS  The PCI display device has been added to ConOut.
+
+  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+                       from DeviceHandle.
+**/
+EFI_STATUS
+PreparePciDisplayDevicePath (
+  IN EFI_HANDLE                DeviceHandle
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
+
+  DevicePath    = NULL;
+  GopDevicePath = NULL;
+  Status = gBS->HandleProtocol (
+                  DeviceHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID*)&DevicePath
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  GetGopDevicePath (DevicePath, &GopDevicePath);
+  DevicePath = GopDevicePath;
+
+  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Add PCI Serial to ConOut, ConIn, ErrOut.
+
+  @param[in] DeviceHandle  Handle of the PCI serial device.
+
+  @retval EFI_SUCCESS  The PCI serial device has been added to ConOut, ConIn,
+                       ErrOut.
+
+  @return              Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+                       from DeviceHandle.
+**/
+EFI_STATUS
+PreparePciSerialDevicePath (
+  IN EFI_HANDLE                DeviceHandle
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+
+  DevicePath = NULL;
+  Status = gBS->HandleProtocol (
+                  DeviceHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  (VOID*)&DevicePath
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  DevicePath = AppendDevicePathNode (DevicePath,
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+  DevicePath = AppendDevicePathNode (DevicePath,
+                 (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+  EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+  EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+  EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+VisitAllInstancesOfProtocol (
+  IN EFI_GUID                    *Id,
+  IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,
+  IN VOID                        *Context
+  )
+{
+  EFI_STATUS                Status;
+  UINTN                     HandleCount;
+  EFI_HANDLE                *HandleBuffer;
+  UINTN                     Index;
+  VOID                      *Instance;
+
+  //
+  // Start to check all the PciIo to find all possible device
+  //
+  HandleCount = 0;
+  HandleBuffer = NULL;
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  Id,
+                  NULL,
+                  &HandleCount,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (Index = 0; Index < HandleCount; Index++) {
+    Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    Status = (*CallBackFunction) (
+               HandleBuffer[Index],
+               Instance,
+               Context
+               );
+  }
+
+  gBS->FreePool (HandleBuffer);
+
+  return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+VisitingAPciInstance (
+  IN EFI_HANDLE  Handle,
+  IN VOID        *Instance,
+  IN VOID        *Context
+  )
+{
+  EFI_STATUS                Status;
+  EFI_PCI_IO_PROTOCOL       *PciIo;
+  PCI_TYPE00                Pci;
+
+  PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
+
+  //
+  // Check for all PCI device
+  //
+  Status = PciIo->Pci.Read (
+                    PciIo,
+                    EfiPciIoWidthUint32,
+                    0,
+                    sizeof (Pci) / sizeof (UINT32),
+                    &Pci
+                    );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
+           Handle,
+           PciIo,
+           &Pci
+           );
+
+}
+
+
+
+EFI_STATUS
+VisitAllPciInstances (
+  IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+  )
+{
+  return VisitAllInstancesOfProtocol (
+           &gEfiPciIoProtocolGuid,
+           VisitingAPciInstance,
+           (VOID*)(UINTN) CallBackFunction
+           );
+}
+
+
+/**
+  Do platform specific PCI Device check and add them to
+  ConOut, ConIn, ErrOut.
+
+  @param[in]  Handle - Handle of PCI device instance
+  @param[in]  PciIo - PCI IO protocol instance
+  @param[in]  Pci - PCI Header register block
+
+  @retval EFI_SUCCESS - PCI Device check and Console variable update
+                        successfully.
+  @retval EFI_STATUS - PCI Device check or Console variable update fail.
+
+**/
+EFI_STATUS
+EFIAPI
+DetectAndPreparePlatformPciDevicePath (
+  IN EFI_HANDLE           Handle,
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN PCI_TYPE00           *Pci
+  )
+{
+  EFI_STATUS                Status;
+
+  Status = PciIo->Attributes (
+    PciIo,
+    EfiPciIoAttributeOperationEnable,
+    EFI_PCI_DEVICE_ENABLE,
+    NULL
+    );
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Here we decide whether it is LPC Bridge
+  //
+  if ((IS_PCI_LPC (Pci)) ||
+      ((IS_PCI_ISA_PDECODE (Pci)) &&
+       (Pci->Hdr.VendorId == 0x8086) &&
+       (Pci->Hdr.DeviceId == 0x7000)
+      )
+     ) {
+    //
+    // Add IsaKeyboard to ConIn,
+    // add IsaSerial to ConOut, ConIn, ErrOut
+    //
+    DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));
+    PrepareLpcBridgeDevicePath (Handle);
+    return EFI_SUCCESS;
+  }
+  //
+  // Here we decide which Serial device to enable in PCI bus
+  //
+  if (IS_PCI_16550SERIAL (Pci)) {
+    //
+    // Add them to ConOut, ConIn, ErrOut.
+    //
+    DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));
+    PreparePciSerialDevicePath (Handle);
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Here we decide which display device to enable in PCI bus
+  //
+  if (IS_PCI_DISPLAY (Pci)) {
+    //
+    // Add them to ConOut.
+    //
+    DEBUG ((DEBUG_INFO, "Found PCI display device\n"));
+    PreparePciDisplayDevicePath (Handle);
+    return EFI_SUCCESS;
+  }
+
+  return Status;
+}
+
+
+/**
+  Connect the predefined platform default console device.
+
+  Always try to find and enable PCI display devices.
+
+  @param[in] PlatformConsole  Predefined platform default console device array.
+**/
+VOID
+PlatformInitializeConsole (
+  IN PLATFORM_CONSOLE_CONNECT_ENTRY   *PlatformConsole
+  )
+{
+  UINTN                              Index;
+
+  //
+  // Do platform specific PCI Device check and add them to ConOut, ConIn,
+  // ErrOut
+  //
+  VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
+
+  //
+  // Have chance to connect the platform default console,
+  // the platform default console is the minimum device group
+  // the platform should support
+  //
+  for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
+    //
+    // Update the console variable with the connect type
+    //
+    if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
+      EfiBootManagerUpdateConsoleVariable (ConIn,
+        PlatformConsole[Index].DevicePath, NULL);
+    }
+    if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
+      EfiBootManagerUpdateConsoleVariable (ConOut,
+        PlatformConsole[Index].DevicePath, NULL);
+    }
+    if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
+      EfiBootManagerUpdateConsoleVariable (ErrOut,
+        PlatformConsole[Index].DevicePath, NULL);
+    }
+  }
+}
+
+
+/**
+  Configure PCI Interrupt Line register for applicable devices
+  Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
+
+  @param[in]  Handle - Handle of PCI device instance
+  @param[in]  PciIo - PCI IO protocol instance
+  @param[in]  PciHdr - PCI Header register block
+
+  @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+SetPciIntLine (
+  IN EFI_HANDLE           Handle,
+  IN EFI_PCI_IO_PROTOCOL  *PciIo,
+  IN PCI_TYPE00           *PciHdr
+  )
+{
+  EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;
+  EFI_DEVICE_PATH_PROTOCOL  *DevPath;
+  UINTN                     RootSlot;
+  UINTN                     Idx;
+  UINT8                     IrqLine;
+  EFI_STATUS                Status;
+  UINT32                    RootBusNumber;
+
+  Status = EFI_SUCCESS;
+
+  if (PciHdr->Device.InterruptPin != 0) {
+
+    DevPathNode = DevicePathFromHandle (Handle);
+    ASSERT (DevPathNode != NULL);
+    DevPath = DevPathNode;
+
+    RootBusNumber = 0;
+    if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
+        DevicePathSubType (DevPathNode) == ACPI_DP &&
+        ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {
+      RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
+    }
+
+    //
+    // Compute index into PciHostIrqs[] table by walking
+    // the device path and adding up all device numbers
+    //
+    Status = EFI_NOT_FOUND;
+    RootSlot = 0;
+    Idx = PciHdr->Device.InterruptPin - 1;
+    while (!IsDevicePathEnd (DevPathNode)) {
+      if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
+          DevicePathSubType (DevPathNode) == HW_PCI_DP) {
+
+        Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
+
+        //
+        // Unlike SeaBIOS, which starts climbing from the leaf device
+        // up toward the root, we traverse the device path starting at
+        // the root moving toward the leaf node.
+        // The slot number of the top-level parent bridge is needed for
+        // Q35 cases with more than 24 slots on the root bus.
+        //
+        if (Status != EFI_SUCCESS) {
+          Status = EFI_SUCCESS;
+          RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
+        }
+      }
+
+      DevPathNode = NextDevicePathNode (DevPathNode);
+    }
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+    if (RootBusNumber == 0 && RootSlot == 0) {
+      DEBUG((
+        DEBUG_ERROR,
+        "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
+        __FUNCTION__
+        ));
+      ASSERT (FALSE);
+    }
+
+    //
+    // Final PciHostIrqs[] index calculation depends on the platform
+    // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
+    //
+    switch (mHostBridgeDevId) {
+      case 0x1275: // BHYVE
+      case INTEL_82441_DEVICE_ID:
+        Idx -= 1;
+        break;
+      case INTEL_Q35_MCH_DEVICE_ID:
+        //
+        // SeaBIOS contains the following comment:
+        // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
+        //  with a different starting index - see q35-acpi-dsdt.dsl.
+        //
+        //  Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
+        //
+        if (RootSlot > 24) {
+          //
+          // in this case, subtract back out RootSlot from Idx
+          // (SeaBIOS never adds it to begin with, but that would make our
+          //  device path traversal loop above too awkward)
+          //
+          Idx -= RootSlot;
+        }
+        break;
+      default:
+        ASSERT (FALSE); // should never get here
+    }
+    Idx %= ARRAY_SIZE (PciHostIrqs);
+    IrqLine = PciHostIrqs[Idx];
+
+    DEBUG_CODE_BEGIN ();
+    {
+      CHAR16        *DevPathString;
+      STATIC CHAR16 Fallback[] = L"<failed to convert>";
+      UINTN         Segment, Bus, Device, Function;
+
+      DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
+      if (DevPathString == NULL) {
+        DevPathString = Fallback;
+      }
+      Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+      ASSERT_EFI_ERROR (Status);
+
+      DEBUG ((DEBUG_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,
+        (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
+        IrqLine));
+
+      if (DevPathString != Fallback) {
+        FreePool (DevPathString);
+      }
+    }
+    DEBUG_CODE_END ();
+
+    //
+    // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
+    //
+    Status = PciIo->Pci.Write (
+               PciIo,
+               EfiPciIoWidthUint8,
+               PCI_INT_LINE_OFFSET,
+               1,
+               &IrqLine
+               );
+  }
+
+  return Status;
+}
+
+
+VOID
+PciAcpiInitialization (
+  )
+{
+  UINTN  Pmba;
+
+  //
+  // Query Host Bridge DID to determine platform type
+  //
+  mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
+  switch (mHostBridgeDevId) {
+    case 0x1275: // BHYVE
+    case INTEL_82441_DEVICE_ID:
+      Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
+      //
+      // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
+      //
+      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
+      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
+      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
+      PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
+      break;
+    case INTEL_Q35_MCH_DEVICE_ID:
+      Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
+      //
+      // 00:1f.0 LPC Bridge (Q35) LNK routing targets
+      //
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
+      PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
+      break;
+    default:
+      DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
+        __FUNCTION__, mHostBridgeDevId));
+      ASSERT (FALSE);
+      return;
+  }
+
+  //
+  // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
+  //
+  VisitAllPciInstances (SetPciIntLine);
+
+  //
+  // Set ACPI SCI_EN bit in PMCNTRL
+  //
+  IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
+}
+
+EFI_STATUS
+EFIAPI
+ConnectRecursivelyIfPciMassStorage (
+  IN EFI_HANDLE           Handle,
+  IN EFI_PCI_IO_PROTOCOL  *Instance,
+  IN PCI_TYPE00           *PciHeader
+  )
+{
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  CHAR16                    *DevPathStr;
+
+  //
+  // Recognize PCI Mass Storage, and Xen PCI devices
+  //
+  if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
+    DevicePath = NULL;
+    Status = gBS->HandleProtocol (
+                    Handle,
+                    &gEfiDevicePathProtocolGuid,
+                    (VOID*)&DevicePath
+                    );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    //
+    // Print Device Path
+    //
+    DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+    if (DevPathStr != NULL) {
+      DEBUG((
+        DEBUG_INFO,
+        "Found %s device: %s\n",
+        (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) ?
+         L"Mass Storage" :
+         L"Xen"
+         ),
+        DevPathStr
+        ));
+      FreePool(DevPathStr);
+    }
+
+    Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  This notification function is invoked when the
+  EMU Variable FVB has been changed.
+
+  @param  Event                 The event that occurred
+  @param  Context               For EFI compatibility.  Not used.
+
+**/
+VOID
+EFIAPI
+EmuVariablesUpdatedCallback (
+  IN  EFI_EVENT Event,
+  IN  VOID      *Context
+  )
+{
+  DEBUG ((DEBUG_INFO, "EmuVariablesUpdatedCallback\n"));
+  UpdateNvVarsOnFileSystem ();
+}
+
+
+EFI_STATUS
+EFIAPI
+VisitingFileSystemInstance (
+  IN EFI_HANDLE  Handle,
+  IN VOID        *Instance,
+  IN VOID        *Context
+  )
+{
+  EFI_STATUS      Status;
+  STATIC BOOLEAN  ConnectedToFileSystem = FALSE;
+  RETURN_STATUS   PcdStatus;
+
+  if (ConnectedToFileSystem) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  Status = ConnectNvVarsToFileSystem (Handle);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ConnectedToFileSystem = TRUE;
+  mEmuVariableEvent =
+    EfiCreateProtocolNotifyEvent (
+      &gEfiDevicePathProtocolGuid,
+      TPL_CALLBACK,
+      EmuVariablesUpdatedCallback,
+      NULL,
+      &mEmuVariableEventReg
+      );
+  PcdStatus = PcdSet64S (PcdEmuVariableEvent,
+                (UINT64)(UINTN) mEmuVariableEvent);
+  ASSERT_RETURN_ERROR (PcdStatus);
+
+  return EFI_SUCCESS;
+}
+
+
+VOID
+PlatformBdsRestoreNvVarsFromHardDisk (
+  )
+{
+  VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
+  VisitAllInstancesOfProtocol (
+    &gEfiSimpleFileSystemProtocolGuid,
+    VisitingFileSystemInstance,
+    NULL
+    );
+
+}
+
+/**
+  Connect with predefined platform connect sequence.
+
+  The OEM/IBV can customize with their own connect sequence.
+**/
+VOID
+PlatformBdsConnectSequence (
+  VOID
+  )
+{
+  UINTN         Index;
+
+  DEBUG ((DEBUG_INFO, "PlatformBdsConnectSequence\n"));
+
+  Index = 0;
+
+  //
+  // Here we can get the customized platform connect sequence
+  // Notes: we can connect with new variable which record the
+  // last time boots connect device path sequence
+  //
+  while (gPlatformConnectSequence[Index] != NULL) {
+    //
+    // Build the platform boot option
+    //
+    EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);
+    Index++;
+  }
+
+  //
+  // Just use the simple policy to connect all devices
+  //
+  DEBUG ((DEBUG_INFO, "EfiBootManagerConnectAll\n"));
+  EfiBootManagerConnectAll ();
+}
+
+/**
+  Save the S3 boot script.
+
+  Note that DxeSmmReadyToLock must be signaled after this function returns;
+  otherwise the script wouldn't be saved actually.
+**/
+#if defined(__GNUC__)
+__attribute__((unused))
+#endif
+STATIC
+VOID
+SaveS3BootScript (
+  VOID
+  )
+{
+  EFI_STATUS                 Status;
+  EFI_S3_SAVE_STATE_PROTOCOL *BootScript;
+  STATIC CONST UINT8         Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };
+
+  Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,
+                  (VOID **) &BootScript);
+  ASSERT_EFI_ERROR (Status);
+
+  //
+  // Despite the opcode documentation in the PI spec, the protocol
+  // implementation embeds a deep copy of the info in the boot script, rather
+  // than storing just a pointer to runtime or NVS storage.
+  //
+  Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,
+                         (UINT32) sizeof Info,
+                         (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);
+  ASSERT_EFI_ERROR (Status);
+}
+
+
+/**
+  Do the platform specific action after the console is ready
+
+  Possible things that can be done in PlatformBootManagerAfterConsole:
+
+  > Console post action:
+    > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
+    > Signal console ready platform customized event
+  > Run diagnostics like memory testing
+  > Connect certain devices
+  > Dispatch aditional option roms
+  > Special boot: e.g.: USB boot, enter UI
+**/
+VOID
+EFIAPI
+PlatformBootManagerAfterConsole (
+  VOID
+  )
+{
+  EFI_BOOT_MODE                      BootMode;
+
+  DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n"));
+
+  if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
+    DEBUG ((DEBUG_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
+      "from disk since flash variables appear to be supported.\n"));
+  } else {
+    //
+    // Try to restore variables from the hard disk early so
+    // they can be used for the other BDS connect operations.
+    //
+    /* XXX Calling this causes Keyboard to be removed from ConIn which
+       results in unresponsive guest boot loaders in the GUI. Restore it
+       when we figure out what is needed to get NvVars storage done
+       properly.
+     */
+    /*PlatformBdsRestoreNvVarsFromHardDisk ();*/
+  }
+
+  //
+  // Get current Boot Mode
+  //
+  BootMode = GetBootModeHob ();
+  DEBUG ((DEBUG_INFO, "Boot Mode:%x\n", BootMode));
+
+  //
+  // Go the different platform policy with different boot mode
+  // Notes: this part code can be change with the table policy
+  //
+  ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
+
+  //
+  // Logo show
+  //
+  BootLogoEnableLogo ();
+
+  //
+  // Set PCI Interrupt Line registers and ACPI SCI_EN
+  //
+  PciAcpiInitialization ();
+
+  //
+  // Process TPM PPI request
+  //
+  Tcg2PhysicalPresenceLibProcessRequest (NULL);
+
+  //
+  // Perform some platform specific connect sequence
+  //
+  PlatformBdsConnectSequence ();
+
+  EfiBootManagerRefreshAllBootOption ();
+
+  //
+  // Register UEFI Shell
+  //
+  PlatformRegisterFvBootOption (
+    &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE
+    );
+
+  RemoveStaleFvFileOptions ();
+
+  PlatformBmPrintScRegisterHandler ();
+}
+
+/**
+  This notification function is invoked when an instance of the
+  EFI_DEVICE_PATH_PROTOCOL is produced.
+
+  @param  Event                 The event that occurred
+  @param  Context               For EFI compatibility.  Not used.
+
+**/
+VOID
+EFIAPI
+NotifyDevPath (
+  IN  EFI_EVENT Event,
+  IN  VOID      *Context
+  )
+{
+  EFI_HANDLE                            Handle;
+  EFI_STATUS                            Status;
+  UINTN                                 BufferSize;
+  EFI_DEVICE_PATH_PROTOCOL             *DevPathNode;
+  ATAPI_DEVICE_PATH                    *Atapi;
+
+  //
+  // Examine all new handles
+  //
+  for (;;) {
+    //
+    // Get the next handle
+    //
+    BufferSize = sizeof (Handle);
+    Status = gBS->LocateHandle (
+              ByRegisterNotify,
+              NULL,
+              mEfiDevPathNotifyReg,
+              &BufferSize,
+              &Handle
+              );
+
+    //
+    // If not found, we're done
+    //
+    if (EFI_NOT_FOUND == Status) {
+      break;
+    }
+
+    if (EFI_ERROR (Status)) {
+      continue;
+    }
+
+    //
+    // Get the DevicePath protocol on that handle
+    //
+    Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid,
+                    (VOID **)&DevPathNode);
+    ASSERT_EFI_ERROR (Status);
+
+    while (!IsDevicePathEnd (DevPathNode)) {
+      //
+      // Find the handler to dump this device path node
+      //
+      if (
+           (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
+           (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
+         ) {
+        Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
+        PciOr16 (
+          PCI_LIB_ADDRESS (
+            0,
+            1,
+            1,
+            (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
+            ),
+          BIT15
+          );
+      }
+
+      //
+      // Next device path node
+      //
+      DevPathNode = NextDevicePathNode (DevPathNode);
+    }
+  }
+
+  return;
+}
+
+
+VOID
+InstallDevicePathCallback (
+  VOID
+  )
+{
+  DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));
+  mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
+                          &gEfiDevicePathProtocolGuid,
+                          TPL_CALLBACK,
+                          NotifyDevPath,
+                          NULL,
+                          &mEfiDevPathNotifyReg
+                          );
+}
+
+/**
+  This function is called each second during the boot manager waits the
+  timeout.
+
+  @param TimeoutRemain  The remaining timeout.
+**/
+VOID
+EFIAPI
+PlatformBootManagerWaitCallback (
+  UINT16          TimeoutRemain
+  )
+{
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;
+  EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;
+  UINT16                              Timeout;
+
+  Timeout = PcdGet16 (PcdPlatformBootTimeOut);
+
+  Black.Raw = 0x00000000;
+  White.Raw = 0x00FFFFFF;
+
+  BootLogoUpdateProgress (
+    White.Pixel,
+    Black.Pixel,
+    L"Start boot option",
+    White.Pixel,
+    (Timeout - TimeoutRemain) * 100 / Timeout,
+    0
+    );
+}
+
+/**
+  The function is called when no boot option could be launched,
+  including platform recovery options and options pointing to applications
+  built into firmware volumes.
+
+  If this function returns, BDS attempts to enter an infinite loop.
+**/
+VOID
+EFIAPI
+PlatformBootManagerUnableToBoot (
+  VOID
+  )
+{
+  EFI_STATUS                   Status;
+  EFI_INPUT_KEY                Key;
+  EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
+  UINTN                        Index;
+
+  //
+  // BootManagerMenu doesn't contain the correct information when return status
+  // is EFI_NOT_FOUND.
+  //
+  Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
+  if (EFI_ERROR (Status)) {
+    return;
+  }
+  //
+  // Normally BdsDxe does not print anything to the system console, but this is
+  // a last resort -- the end-user will likely not see any DEBUG messages
+  // logged in this situation.
+  //
+  // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
+  // here to see if it makes sense to request and wait for a keypress.
+  //
+  if (gST->ConIn != NULL) {
+    AsciiPrint (
+      "%a: No bootable option or device was found.\n"
+      "%a: Press any key to enter the Boot Manager Menu.\n",
+      gEfiCallerBaseName,
+      gEfiCallerBaseName
+      );
+    Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
+    ASSERT_EFI_ERROR (Status);
+    ASSERT (Index == 0);
+
+    //
+    // Drain any queued keys.
+    //
+    while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {
+      //
+      // just throw away Key
+      //
+    }
+  }
+
+  for (;;) {
+    EfiBootManagerBoot (&BootManagerMenu);
+  }
+}
diff --git a/BhyvePkg/Library/PlatformBootManagerLib/BdsPlatform.h b/BhyvePkg/Library/PlatformBootManagerLib/BdsPlatform.h
new file mode 100644
index 0000000000..9701baf906
--- /dev/null
+++ b/BhyvePkg/Library/PlatformBootManagerLib/BdsPlatform.h
@@ -0,0 +1,191 @@
+/** @file
+  Platform BDS customizations include file.
+
+  Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause
+
+Module Name:
+
+  BdsPlatform.h
+
+Abstract:
+
+  Head file for BDS Platform specific code
+
+**/
+
+#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/SmBios.h>
+#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/Virtio095.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/BootLogoLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+#include <Library/NvVarsFileLib.h>
+#include <Library/QemuFwCfgLib.h>
+#include <Library/QemuFwCfgS3Lib.h>
+#include <Library/QemuBootOrderLib.h>
+
+#include <Protocol/Decompress.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/S3SaveState.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/LoadedImage.h>
+
+#include <Guid/Acpi.h>
+#include <Guid/SmBios.h>
+#include <Guid/Mps.h>
+#include <Guid/HobList.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/EventGroup.h>
+#include <Guid/DebugAgentGuid.h>
+
+#include <OvmfPlatforms.h>
+
+extern EFI_DEVICE_PATH_PROTOCOL   *gPlatformConnectSequence[];
+extern ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode;
+extern ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode;
+extern UART_DEVICE_PATH           gUartDeviceNode;
+extern VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode;
+
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \
+  { \
+    { \
+      HARDWARE_DEVICE_PATH, \
+      HW_PCI_DP, \
+      { \
+        (UINT8) (sizeof (PCI_DEVICE_PATH)), \
+        (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
+      } \
+    }, \
+    (Func), \
+    (Dev) \
+  }
+
+#define PNPID_DEVICE_PATH_NODE(PnpId) \
+  { \
+    { \
+      ACPI_DEVICE_PATH, \
+      ACPI_DP, \
+      { \
+        (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+        (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
+      }, \
+    }, \
+    EISA_PNP_ID((PnpId)), \
+    0 \
+  }
+
+#define gPciIsaBridge \
+  PCI_DEVICE_PATH_NODE(0, 0x1f)
+
+#define gP2PBridge \
+  PCI_DEVICE_PATH_NODE(0, 0x1e)
+
+#define gPnpPs2Keyboard \
+  PNPID_DEVICE_PATH_NODE(0x0303)
+
+#define gPnp16550ComPort \
+  PNPID_DEVICE_PATH_NODE(0x0501)
+
+#define gUart \
+  { \
+    { \
+      MESSAGING_DEVICE_PATH, \
+      MSG_UART_DP, \
+      { \
+        (UINT8) (sizeof (UART_DEVICE_PATH)), \
+        (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \
+      } \
+    }, \
+    0, \
+    115200, \
+    8, \
+    1, \
+    1 \
+  }
+
+#define gPcAnsiTerminal \
+  { \
+    { \
+      MESSAGING_DEVICE_PATH, \
+      MSG_VENDOR_DP, \
+      { \
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \
+      } \
+    }, \
+    DEVICE_PATH_MESSAGING_PC_ANSI \
+  }
+
+#define gEndEntire \
+  { \
+    END_DEVICE_PATH_TYPE, \
+    END_ENTIRE_DEVICE_PATH_SUBTYPE, \
+    { \
+      END_DEVICE_PATH_LENGTH, \
+      0 \
+    } \
+  }
+
+#define PCI_CLASS_SCC          0x07
+#define PCI_SUBCLASS_SERIAL    0x00
+#define PCI_IF_16550           0x02
+#define IS_PCI_16550SERIAL(_p)           IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)
+#define IS_PCI_ISA_PDECODE(_p)        IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
+
+typedef struct {
+  EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
+  UINTN                     ConnectType;
+} PLATFORM_CONSOLE_CONNECT_ENTRY;
+
+#define CONSOLE_OUT BIT0
+#define CONSOLE_IN  BIT1
+#define STD_ERROR   BIT2
+extern PLATFORM_CONSOLE_CONNECT_ENTRY  gPlatformConsole[];
+
+//
+// Platform BDS Functions
+//
+
+VOID
+PlatformInitializeConsole (
+  IN PLATFORM_CONSOLE_CONNECT_ENTRY   *PlatformConsole
+  );
+
+/**
+  Loads and boots UEFI Linux via the FwCfg interface.
+
+  @retval    EFI_NOT_FOUND - The Linux kernel was not found
+
+**/
+EFI_STATUS
+TryRunningQemuKernel (
+  VOID
+  );
+
+#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
diff --git a/BhyvePkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/BhyvePkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
new file mode 100644
index 0000000000..b61e224782
--- /dev/null
+++ b/BhyvePkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
@@ -0,0 +1,74 @@
+## @file
+#  Platform BDS customizations library.
+#
+#  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformBootManagerLib
+  FILE_GUID                      = b0de5f0d-f676-42da-8d00-86997ee0dbb4
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformBootManagerLib|DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  BdsPlatform.c
+  PlatformData.c
+  BdsPlatform.h
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  SourceLevelDebugPkg/SourceLevelDebugPkg.dec
+  OvmfPkg/OvmfPkg.dec
+  SecurityPkg/SecurityPkg.dec
+  ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  MemoryAllocationLib
+  UefiBootServicesTableLib
+  BaseMemoryLib
+  DebugLib
+  PcdLib
+  UefiBootManagerLib
+  BootLogoLib
+  DevicePathLib
+  PciLib
+  NvVarsFileLib
+  ReportStatusCodeLib
+  UefiLib
+  PlatformBmPrintScLib
+  Tcg2PhysicalPresenceLib
+
+[Pcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
+  gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+
+[Pcd.IA32, Pcd.X64]
+  gEfiMdePkgTokenSpaceGuid.PcdFSBClock
+
+[Protocols]
+  gEfiDecompressProtocolGuid
+  gEfiPciRootBridgeIoProtocolGuid
+  gEfiS3SaveStateProtocolGuid                   # PROTOCOL SOMETIMES_CONSUMED
+  gEfiDxeSmmReadyToLockProtocolGuid             # PROTOCOL SOMETIMES_PRODUCED
+  gEfiLoadedImageProtocolGuid                   # PROTOCOL SOMETIMES_PRODUCED
+  gEfiFirmwareVolume2ProtocolGuid               # PROTOCOL SOMETIMES_CONSUMED
+
+[Guids]
+  gEfiEndOfDxeEventGroupGuid
+  gRootBridgesConnectedEventGroupGuid
+  gUefiShellFileGuid
diff --git a/BhyvePkg/Library/PlatformBootManagerLib/PlatformData.c b/BhyvePkg/Library/PlatformBootManagerLib/PlatformData.c
new file mode 100644
index 0000000000..59e51fd99a
--- /dev/null
+++ b/BhyvePkg/Library/PlatformBootManagerLib/PlatformData.c
@@ -0,0 +1,171 @@
+/** @file
+  Defined the platform specific device path which will be used by
+  platform Bbd to perform the platform policy connect.
+
+  Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+#include "BdsPlatform.h"
+#include <Guid/QemuRamfb.h>
+
+//
+// Debug Agent UART Device Path structure
+//
+#pragma pack(1)
+typedef struct {
+  VENDOR_DEVICE_PATH        VendorHardware;
+  UART_DEVICE_PATH          Uart;
+  VENDOR_DEVICE_PATH        TerminalType;
+  EFI_DEVICE_PATH_PROTOCOL  End;
+} VENDOR_UART_DEVICE_PATH;
+#pragma pack()
+
+//
+// USB Keyboard Device Path structure
+//
+#pragma pack (1)
+typedef struct {
+  USB_CLASS_DEVICE_PATH    Keyboard;
+  EFI_DEVICE_PATH_PROTOCOL End;
+} USB_KEYBOARD_DEVICE_PATH;
+#pragma pack ()
+
+//
+// QemuRamfb Device Path structure
+//
+#pragma pack (1)
+typedef struct {
+  VENDOR_DEVICE_PATH        Vendor;
+  ACPI_ADR_DEVICE_PATH      AcpiAdr;
+  EFI_DEVICE_PATH_PROTOCOL  End;
+} VENDOR_RAMFB_DEVICE_PATH;
+#pragma pack ()
+
+ACPI_HID_DEVICE_PATH       gPnpPs2KeyboardDeviceNode  = gPnpPs2Keyboard;
+ACPI_HID_DEVICE_PATH       gPnp16550ComPortDeviceNode = gPnp16550ComPort;
+UART_DEVICE_PATH           gUartDeviceNode            = gUart;
+VENDOR_DEVICE_PATH         gTerminalTypeDeviceNode    = gPcAnsiTerminal;
+
+//
+// Platform specific keyboard device path
+//
+
+
+//
+// Debug Agent UART Device Path
+//
+VENDOR_UART_DEVICE_PATH gDebugAgentUartDevicePath = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    EFI_DEBUG_AGENT_GUID,
+  },
+  {
+    {
+      MESSAGING_DEVICE_PATH,
+      MSG_UART_DP,
+      {
+        (UINT8) (sizeof (UART_DEVICE_PATH)),
+        (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)
+      }
+    },
+    0,  // Reserved
+    0,  // BaudRate - Default
+    0,  // DataBits - Default
+    0,  // Parity   - Default
+    0,  // StopBits - Default
+  },
+  gPcAnsiTerminal,
+  gEndEntire
+};
+
+STATIC USB_KEYBOARD_DEVICE_PATH gUsbKeyboardDevicePath = {
+  {
+    {
+      MESSAGING_DEVICE_PATH,
+      MSG_USB_CLASS_DP,
+      {
+        (UINT8)sizeof (USB_CLASS_DEVICE_PATH),
+        (UINT8)(sizeof (USB_CLASS_DEVICE_PATH) >> 8)
+      }
+    },
+    0xFFFF, // VendorId: any
+    0xFFFF, // ProductId: any
+    3,      // DeviceClass: HID
+    1,      // DeviceSubClass: boot
+    1       // DeviceProtocol: keyboard
+  },
+  gEndEntire
+};
+
+STATIC VENDOR_RAMFB_DEVICE_PATH gQemuRamfbDevicePath = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    QEMU_RAMFB_GUID,
+  },
+  {
+    {
+      ACPI_DEVICE_PATH,
+      ACPI_ADR_DP,
+      {
+        (UINT8) (sizeof (ACPI_ADR_DEVICE_PATH)),
+        (UINT8) ((sizeof (ACPI_ADR_DEVICE_PATH)) >> 8)
+      }
+    },
+    ACPI_DISPLAY_ADR (
+      1,                                       // DeviceIdScheme
+      0,                                       // HeadId
+      0,                                       // NonVgaOutput
+      1,                                       // BiosCanDetect
+      0,                                       // VendorInfo
+      ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL,  // Type
+      0,                                       // Port
+      0                                        // Index
+      ),
+  },
+  gEndEntire
+};
+
+//
+// Predefined platform default console device path
+//
+PLATFORM_CONSOLE_CONNECT_ENTRY   gPlatformConsole[] = {
+  {
+    (EFI_DEVICE_PATH_PROTOCOL *) &gDebugAgentUartDevicePath,
+    (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
+  },
+  {
+    (EFI_DEVICE_PATH_PROTOCOL *)&gUsbKeyboardDevicePath,
+    CONSOLE_IN
+  },
+  {
+    (EFI_DEVICE_PATH_PROTOCOL *)&gQemuRamfbDevicePath,
+    CONSOLE_OUT
+  },
+  {
+    NULL,
+    0
+  }
+};
+
+//
+// Predefined platform connect sequence
+//
+EFI_DEVICE_PATH_PROTOCOL    *gPlatformConnectSequence[] = { NULL };
+
diff --git a/BhyvePkg/License.txt b/BhyvePkg/License.txt
new file mode 100644
index 0000000000..d1bdbae60f
--- /dev/null
+++ b/BhyvePkg/License.txt
@@ -0,0 +1,44 @@
+Copyright (c) 2012, Intel Corporation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+  notice, this list of conditions and the following disclaimer in
+  the documentation and/or other materials provided with the
+  distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/BhyvePkg/SmbiosPlatformDxe/Bhyve.c b/BhyvePkg/SmbiosPlatformDxe/Bhyve.c
new file mode 100644
index 0000000000..7d6b79e27f
--- /dev/null
+++ b/BhyvePkg/SmbiosPlatformDxe/Bhyve.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "SmbiosPlatformDxe.h"
+
+#define BHYVE_SMBIOS_PHYSICAL_ADDRESS       0x000F0000
+#define BHYVE_SMBIOS_PHYSICAL_END           0x000FFFFF
+
+/**
+  Locates the bhyve SMBIOS data if it exists
+
+  @return SMBIOS_TABLE_ENTRY_POINT   Address of bhyve SMBIOS data
+
+**/
+SMBIOS_TABLE_ENTRY_POINT *
+GetBhyveSmbiosTables (
+  VOID
+  )
+{
+  UINT8                     *BhyveSmbiosPtr;
+  SMBIOS_TABLE_ENTRY_POINT  *BhyveSmbiosEntryPointStructure;
+
+  for (BhyveSmbiosPtr = (UINT8*)(UINTN) BHYVE_SMBIOS_PHYSICAL_ADDRESS;
+       BhyveSmbiosPtr < (UINT8*)(UINTN) BHYVE_SMBIOS_PHYSICAL_END;
+       BhyveSmbiosPtr += 0x10) {
+
+    BhyveSmbiosEntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) BhyveSmbiosPtr;
+
+    if (!AsciiStrnCmp ((CHAR8 *) BhyveSmbiosEntryPointStructure->AnchorString, "_SM_", 4) &&
+        !AsciiStrnCmp ((CHAR8 *) BhyveSmbiosEntryPointStructure->IntermediateAnchorString, "_DMI_", 5) &&
+        IsEntryPointStructureValid (BhyveSmbiosEntryPointStructure)) {
+
+      return BhyveSmbiosEntryPointStructure;
+
+    }
+  }
+
+  return NULL;
+}
diff --git a/BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c b/BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
new file mode 100644
index 0000000000..25ab7a8923
--- /dev/null
+++ b/BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
@@ -0,0 +1,244 @@
+/** @file
+  This driver installs SMBIOS information for OVMF
+
+  Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+  Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+#include "SmbiosPlatformDxe.h"
+
+#define TYPE0_STRINGS \
+  "EFI Development Kit II / OVMF\0"     /* Vendor */ \
+  "0.0.0\0"                             /* BiosVersion */ \
+  "02/06/2015\0"                        /* BiosReleaseDate */
+//
+// Type definition and contents of the default Type 0 SMBIOS table.
+//
+#pragma pack(1)
+typedef struct {
+  SMBIOS_TABLE_TYPE0 Base;
+  UINT8              Strings[sizeof(TYPE0_STRINGS)];
+} OVMF_TYPE0;
+#pragma pack()
+
+STATIC CONST OVMF_TYPE0 mOvmfDefaultType0 = {
+  {
+    // SMBIOS_STRUCTURE Hdr
+    {
+      EFI_SMBIOS_TYPE_BIOS_INFORMATION, // UINT8 Type
+      sizeof (SMBIOS_TABLE_TYPE0),      // UINT8 Length
+    },
+    1,     // SMBIOS_TABLE_STRING       Vendor
+    2,     // SMBIOS_TABLE_STRING       BiosVersion
+    0xE800,// UINT16                    BiosSegment
+    3,     // SMBIOS_TABLE_STRING       BiosReleaseDate
+    0,     // UINT8                     BiosSize
+    {      // MISC_BIOS_CHARACTERISTICS BiosCharacteristics
+      0,     // Reserved                                      :2
+      0,     // Unknown                                       :1
+      1,     // BiosCharacteristicsNotSupported               :1
+             // Remaining BiosCharacteristics bits left unset :60
+    },
+    {      // BIOSCharacteristicsExtensionBytes[2]
+      0,     // BiosReserved
+      0x1C   // SystemReserved = VirtualMachineSupported |
+             //                  UefiSpecificationSupported |
+             //                  TargetContentDistributionEnabled
+    },
+    0,     // UINT8                     SystemBiosMajorRelease
+    0,     // UINT8                     SystemBiosMinorRelease
+    0xFF,  // UINT8                     EmbeddedControllerFirmwareMajorRelease
+    0xFF   // UINT8                     EmbeddedControllerFirmwareMinorRelease
+  },
+  // Text strings (unformatted area)
+  TYPE0_STRINGS
+};
+
+
+/**
+  Validates the SMBIOS entry point structure
+
+  @param  EntryPointStructure  SMBIOS entry point structure
+
+  @retval TRUE   The entry point structure is valid
+  @retval FALSE  The entry point structure is not valid
+
+**/
+BOOLEAN
+IsEntryPointStructureValid (
+  IN SMBIOS_TABLE_ENTRY_POINT  *EntryPointStructure
+  )
+{
+  UINTN                     Index;
+  UINT8                     Length;
+  UINT8                     Checksum;
+  UINT8                     *BytePtr;
+
+  BytePtr = (UINT8*) EntryPointStructure;
+  Length = EntryPointStructure->EntryPointLength;
+  Checksum = 0;
+
+  for (Index = 0; Index < Length; Index++) {
+    Checksum = Checksum + (UINT8) BytePtr[Index];
+  }
+
+  if (Checksum != 0) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+
+/**
+  Get SMBIOS record length.
+
+  @param  SmbiosTable   SMBIOS pointer.
+
+**/
+UINTN
+SmbiosTableLength (
+  IN SMBIOS_STRUCTURE_POINTER SmbiosTable
+  )
+{
+  CHAR8  *AChar;
+  UINTN  Length;
+
+  AChar = (CHAR8 *)(SmbiosTable.Raw + SmbiosTable.Hdr->Length);
+
+  //
+  // Each structure shall be terminated by a double-null (SMBIOS spec.7.1)
+  //
+  while ((*AChar != 0) || (*(AChar + 1) != 0)) {
+    AChar ++;
+  }
+  Length = ((UINTN)AChar - (UINTN)SmbiosTable.Raw + 2);
+
+  return Length;
+}
+
+
+/**
+  Install all structures from the given SMBIOS structures block
+
+  @param  Smbios               SMBIOS protocol
+  @param  TableAddress         SMBIOS tables starting address
+
+**/
+EFI_STATUS
+InstallAllStructures (
+  IN EFI_SMBIOS_PROTOCOL       *Smbios,
+  IN UINT8                     *TableAddress
+  )
+{
+  EFI_STATUS                Status;
+  SMBIOS_STRUCTURE_POINTER  SmbiosTable;
+  EFI_SMBIOS_HANDLE         SmbiosHandle;
+  BOOLEAN                   NeedSmbiosType0;
+
+  SmbiosTable.Raw = TableAddress;
+  if (SmbiosTable.Raw == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  NeedSmbiosType0 = TRUE;
+
+  while (SmbiosTable.Hdr->Type != 127) {
+    //
+    // Log the SMBIOS data for this structure
+    //
+    SmbiosHandle = SmbiosTable.Hdr->Handle;
+    Status = Smbios->Add (
+                       Smbios,
+                       NULL,
+                       &SmbiosHandle,
+                       (EFI_SMBIOS_TABLE_HEADER*) SmbiosTable.Raw
+                       );
+    ASSERT_EFI_ERROR (Status);
+
+    if (SmbiosTable.Hdr->Type == 0) {
+      NeedSmbiosType0 = FALSE;
+    }
+
+    //
+    // Get the next structure address
+    //
+    SmbiosTable.Raw = (UINT8 *)(SmbiosTable.Raw + SmbiosTableLength (SmbiosTable));
+  }
+
+  if (NeedSmbiosType0) {
+    //
+    // Add OVMF default Type 0 (BIOS Information) table
+    //
+    SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+    Status = Smbios->Add (
+                       Smbios,
+                       NULL,
+                       &SmbiosHandle,
+                       (EFI_SMBIOS_TABLE_HEADER*) &mOvmfDefaultType0
+                       );
+    ASSERT_EFI_ERROR (Status);
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Installs SMBIOS information for OVMF
+
+  @param ImageHandle     Module's image handle
+  @param SystemTable     Pointer of EFI_SYSTEM_TABLE
+
+  @retval EFI_SUCCESS    Smbios data successfully installed
+  @retval Other          Smbios data was not installed
+
+**/
+EFI_STATUS
+EFIAPI
+SmbiosTablePublishEntry (
+  IN EFI_HANDLE           ImageHandle,
+  IN EFI_SYSTEM_TABLE     *SystemTable
+  )
+{
+  EFI_STATUS                Status;
+  EFI_SMBIOS_PROTOCOL       *Smbios;
+  SMBIOS_TABLE_ENTRY_POINT  *EntryPointStructure;
+  UINT8                     *SmbiosTables = NULL;
+
+  //
+  // Find the SMBIOS protocol
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiSmbiosProtocolGuid,
+                  NULL,
+                  (VOID**)&Smbios
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Add bhyve SMBIOS data
+  //
+  EntryPointStructure = GetBhyveSmbiosTables ();
+  if (EntryPointStructure != NULL) {
+    SmbiosTables = (UINT8*)(UINTN)EntryPointStructure->TableAddress;
+  }
+
+  if (SmbiosTables != NULL) {
+    Status = InstallAllStructures (Smbios, SmbiosTables);
+
+    //
+    // Free SmbiosTables if allocated by Qemu (i.e., NOT by Xen):
+    //
+    if (EntryPointStructure == NULL) {
+      FreePool (SmbiosTables);
+    }
+  }
+
+  return Status;
+}
diff --git a/BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h b/BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
new file mode 100644
index 0000000000..7c0fceab15
--- /dev/null
+++ b/BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
@@ -0,0 +1,63 @@
+/** @file
+  This driver installs SMBIOS information for OVMF
+
+  Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+  Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause
+
+**/
+
+#ifndef _SMBIOS_PLATFORM_DXE_H_
+#define _SMBIOS_PLATFORM_DXE_H_
+
+#include <PiDxe.h>
+
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/SmBios.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+
+/**
+  Locates the bhyve SMBIOS data if it exists
+
+  @return SMBIOS_TABLE_ENTRY_POINT   Address of bhyve SMBIOS data
+
+**/
+SMBIOS_TABLE_ENTRY_POINT *
+GetBhyveSmbiosTables (
+  VOID
+  );
+
+
+/**
+  Locates and extracts the QEMU SMBIOS table data if present in fw_cfg
+
+  @return             Address of extracted QEMU SMBIOS data
+
+**/
+UINT8 *
+GetQemuSmbiosTables (
+  VOID
+  );
+
+
+/**
+  Validates the SMBIOS entry point structure
+
+  @param  EntryPointStructure  SMBIOS entry point structure
+
+  @retval TRUE   The entry point structure is valid
+  @retval FALSE  The entry point structure is not valid
+
+**/
+BOOLEAN
+IsEntryPointStructureValid (
+  IN SMBIOS_TABLE_ENTRY_POINT  *EntryPointStructure
+  );
+
+#endif
diff --git a/BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf b/BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
new file mode 100644
index 0000000000..c400dcfabf
--- /dev/null
+++ b/BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
@@ -0,0 +1,54 @@
+## @file
+#  This driver installs SMBIOS information for OVMF
+#
+#  Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+#  Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SmbiosPlatformDxe
+  FILE_GUID                      = e2d8a63c-c239-484f-bb21-2917843cc382
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+
+  ENTRY_POINT                    = SmbiosTablePublishEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC ARM AARCH64
+#
+
+[Sources]
+  SmbiosPlatformDxe.h
+  SmbiosPlatformDxe.c
+  Bhyve.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+  UefiBootServicesTableLib
+  BaseMemoryLib
+  BaseLib
+  UefiDriverEntryPoint
+  DebugLib
+  HobLib
+  MemoryAllocationLib
+  PcdLib
+
+[Pcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdQemuSmbiosValidated
+
+[Protocols]
+  gEfiSmbiosProtocolGuid                      # PROTOCOL ALWAYS_CONSUMED
+
+[Depex]
+  gEfiSmbiosProtocolGuid
+
diff --git a/BhyvePkg/VarStore.fdf.inc b/BhyvePkg/VarStore.fdf.inc
new file mode 100644
index 0000000000..7c6729103d
--- /dev/null
+++ b/BhyvePkg/VarStore.fdf.inc
@@ -0,0 +1,115 @@
+## @file
+#  FDF include file with Layout Regions that define an empty variable store.
+#
+#  Copyright (C) 2014, Red Hat, Inc.
+#  Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause
+#
+##
+
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+0x00000000|0x0000e000
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+0x00000000|0x00040000
+!endif
+#NV_VARIABLE_STORE
+DATA = {
+  ## This is the EFI_FIRMWARE_VOLUME_HEADER
+  # ZeroVector []
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  # FileSystemGuid: gEfiSystemNvDataFvGuid         =
+  #   { 0xFFF12B8D, 0x7696, 0x4C8B,
+  #     { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
+  0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C,
+  0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+  # FvLength: 0x20000
+  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+  # FvLength: 0x84000
+  0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+!endif
+  # Signature "_FVH"       # Attributes
+  0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00,
+  # HeaderLength
+  0x48, 0x00,
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+  # CheckSum
+  0x19, 0xF9,
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+  # CheckSum
+  0xAF, 0xB8,
+!endif
+  # ExtHeaderOffset #Reserved #Revision
+  0x00, 0x00, 0x00, 0x02,
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+  # Blockmap[0]: 0x20 Blocks * 0x1000 Bytes / Block
+  0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+  # Blockmap[0]: 0x84 Blocks * 0x1000 Bytes / Block
+  0x84, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+!endif
+  # Blockmap[1]: End
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  ## This is the VARIABLE_STORE_HEADER
+  # It is compatible with SECURE_BOOT_ENABLE == FALSE as well.
+  # Signature: gEfiAuthenticatedVariableGuid =
+  #   { 0xaaf32c78, 0x947b, 0x439a,
+  #     { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 }}
+  0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43,
+  0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92,
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+  # Size: 0xe000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) -
+  #         0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0xdfb8
+  # This can speed up the Variable Dispatch a bit.
+  0xB8, 0xDF, 0x00, 0x00,
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+  # Size: 0x40000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) -
+  #          0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0x3ffb8
+  # This can speed up the Variable Dispatch a bit.
+  0xB8, 0xFF, 0x03, 0x00,
+!endif
+  # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32
+  0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+0x0000e000|0x00001000
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+0x00040000|0x00001000
+!endif
+#NV_EVENT_LOG
+
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+0x0000f000|0x00001000
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+0x00041000|0x00001000
+!endif
+#NV_FTW_WORKING
+DATA = {
+  # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid         =
+  #  { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65,  0x0, 0xfd, 0x9f, 0x1b, 0x95 }}
+  0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49,
+  0xa0, 0xce, 0x65,  0x0, 0xfd, 0x9f, 0x1b, 0x95,
+  # Crc:UINT32            #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved
+  0x2c, 0xaf, 0x2c, 0x64, 0xFE, 0xFF, 0xFF, 0xFF,
+  # WriteQueueSize: UINT64
+  0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+0x00010000|0x00010000
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+0x00042000|0x00042000
+!endif
+#NV_FTW_SPARE
diff --git a/Maintainers.txt b/Maintainers.txt
index 1733225722..1d1a681216 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -158,6 +158,13 @@ W: https://github.com/tianocore/tianocore.github.io/wiki/BaseTools
 M: Bob Feng <bob.c.feng@intel.com>
 M: Liming Gao <liming.gao@intel.com>
 
+BhyvePkg
+F: BhyvePkg/
+W: https://bhyve.org
+M: Rebecca Cran <rebecca@bsdio.com>
+R: Peter Grehan <grehan@freebsd.org>
+S: Maintained
+
 CryptoPkg
 F: CryptoPkg/
 W: https://github.com/tianocore/tianocore.github.io/wiki/CryptoPkg
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 5/6] BhyvePkg: Add PlatformPei
  2020-04-21  3:09 [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor Rebecca Cran
                   ` (3 preceding siblings ...)
  2020-04-21  3:09 ` [PATCH v3 4/6] Add BhyvePkg, to support the bhyve hypervisor Rebecca Cran
@ 2020-04-21  3:09 ` Rebecca Cran
  2020-04-23  9:24   ` [edk2-devel] " Laszlo Ersek
  2020-04-21  3:09 ` [PATCH v3 6/6] BhyvePkg: Add AcpiPlatformDxe Rebecca Cran
  2020-04-21 15:27 ` [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor Laszlo Ersek
  6 siblings, 1 reply; 24+ messages in thread
From: Rebecca Cran @ 2020-04-21  3:09 UTC (permalink / raw)
  To: devel
  Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel, Leif Lindholm,
	Michael Kinney, Andrew Fish, Peter Grehan, Rebecca Cran

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



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v3 6/6] BhyvePkg: Add AcpiPlatformDxe
  2020-04-21  3:09 [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor Rebecca Cran
                   ` (4 preceding siblings ...)
  2020-04-21  3:09 ` [PATCH v3 5/6] BhyvePkg: Add PlatformPei Rebecca Cran
@ 2020-04-21  3:09 ` 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
  6 siblings, 1 reply; 24+ messages in thread
From: Rebecca Cran @ 2020-04-21  3:09 UTC (permalink / raw)
  To: devel
  Cc: Jordan Justen, Laszlo Ersek, Ard Biesheuvel, Leif Lindholm,
	Michael Kinney, Andrew Fish, Peter Grehan, Rebecca Cran

Make a copy of OvmfPkg/AcpiPlatformDxe under BhyvePkg, with the changes
needed to support the bhyve hypervisor.

Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
---
 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c      | 250 +++++++++++++++++++
 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h      |  76 ++++++
 BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf |  64 +++++
 BhyvePkg/AcpiPlatformDxe/Bhyve.c             | 138 ++++++++++
 BhyvePkg/AcpiPlatformDxe/EntryPoint.c        |  90 +++++++
 BhyvePkg/AcpiPlatformDxe/PciDecoding.c       | 192 ++++++++++++++
 6 files changed, 810 insertions(+)
 create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c
 create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h
 create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
 create mode 100644 BhyvePkg/AcpiPlatformDxe/Bhyve.c
 create mode 100644 BhyvePkg/AcpiPlatformDxe/EntryPoint.c
 create mode 100644 BhyvePkg/AcpiPlatformDxe/PciDecoding.c

diff --git a/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c
new file mode 100644
index 0000000000..4814a9f1e6
--- /dev/null
+++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c
@@ -0,0 +1,250 @@
+/** @file
+  OVMF ACPI Platform Driver
+
+  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "AcpiPlatform.h"
+
+EFI_STATUS
+EFIAPI
+InstallAcpiTable (
+  IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol,
+  IN   VOID                          *AcpiTableBuffer,
+  IN   UINTN                         AcpiTableBufferSize,
+  OUT  UINTN                         *TableKey
+  )
+{
+  return AcpiProtocol->InstallAcpiTable (
+                         AcpiProtocol,
+                         AcpiTableBuffer,
+                         AcpiTableBufferSize,
+                         TableKey
+                         );
+}
+
+
+/**
+  Locate the first instance of a protocol.  If the protocol requested is an
+  FV protocol, then it will return the first FV that contains the ACPI table
+  storage file.
+
+  @param  Instance      Return pointer to the first instance of the protocol
+
+  @return EFI_SUCCESS           The function completed successfully.
+  @return EFI_NOT_FOUND         The protocol could not be located.
+  @return EFI_OUT_OF_RESOURCES  There are not enough resources to find the protocol.
+
+**/
+EFI_STATUS
+LocateFvInstanceWithTables (
+  OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_HANDLE                    *HandleBuffer;
+  UINTN                         NumberOfHandles;
+  EFI_FV_FILETYPE               FileType;
+  UINT32                        FvStatus;
+  EFI_FV_FILE_ATTRIBUTES        Attributes;
+  UINTN                         Size;
+  UINTN                         Index;
+  EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
+
+  FvStatus = 0;
+
+  //
+  // Locate protocol.
+  //
+  Status = gBS->LocateHandleBuffer (
+                   ByProtocol,
+                   &gEfiFirmwareVolume2ProtocolGuid,
+                   NULL,
+                   &NumberOfHandles,
+                   &HandleBuffer
+                   );
+  if (EFI_ERROR (Status)) {
+    //
+    // Defined errors at this time are not found and out of resources.
+    //
+    return Status;
+  }
+
+  //
+  // Looking for FV with ACPI storage file
+  //
+  for (Index = 0; Index < NumberOfHandles; Index++) {
+    //
+    // Get the protocol on this handle
+    // This should not fail because of LocateHandleBuffer
+    //
+    Status = gBS->HandleProtocol (
+                     HandleBuffer[Index],
+                     &gEfiFirmwareVolume2ProtocolGuid,
+                     (VOID**) &FvInstance
+                     );
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // See if it has the ACPI storage file
+    //
+    Status = FvInstance->ReadFile (
+                           FvInstance,
+                           (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
+                           NULL,
+                           &Size,
+                           &FileType,
+                           &Attributes,
+                           &FvStatus
+                           );
+
+    //
+    // If we found it, then we are done
+    //
+    if (Status == EFI_SUCCESS) {
+      *Instance = FvInstance;
+      break;
+    }
+  }
+
+  //
+  // Our exit status is determined by the success of the previous operations
+  // If the protocol was found, Instance already points to it.
+  //
+
+  //
+  // Free any allocated buffers
+  //
+  gBS->FreePool (HandleBuffer);
+
+  return Status;
+}
+
+
+/**
+  Find ACPI tables in an FV and install them.
+
+  This is now a fall-back path. Normally, we will search for tables provided
+  by the VMM first.
+
+  If that fails, we use this function to load the ACPI tables from an FV. The
+  sources for the FV based tables is located under OvmfPkg/AcpiTables.
+
+  @param  AcpiTable     Protocol instance pointer
+
+**/
+EFI_STATUS
+EFIAPI
+InstallOvmfFvTables (
+  IN  EFI_ACPI_TABLE_PROTOCOL     *AcpiTable
+  )
+{
+  EFI_STATUS                           Status;
+  EFI_FIRMWARE_VOLUME2_PROTOCOL        *FwVol;
+  INTN                                 Instance;
+  EFI_ACPI_COMMON_HEADER               *CurrentTable;
+  UINTN                                TableHandle;
+  UINT32                               FvStatus;
+  UINTN                                TableSize;
+  UINTN                                Size;
+  EFI_ACPI_TABLE_INSTALL_ACPI_TABLE    TableInstallFunction;
+
+  Instance     = 0;
+  CurrentTable = NULL;
+  TableHandle  = 0;
+
+  TableInstallFunction = BhyveInstallAcpiTable;
+
+  //
+  // set FwVol (and use an ASSERT() below) to suppress incorrect
+  // compiler/analyzer warnings
+  //
+  FwVol = NULL;
+  //
+  // Locate the firmware volume protocol
+  //
+  Status = LocateFvInstanceWithTables (&FwVol);
+  if (EFI_ERROR (Status)) {
+    return EFI_ABORTED;
+  }
+  ASSERT (FwVol != NULL);
+
+  //
+  // Read tables from the storage file.
+  //
+  while (Status == EFI_SUCCESS) {
+
+    Status = FwVol->ReadSection (
+                      FwVol,
+                      (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
+                      EFI_SECTION_RAW,
+                      Instance,
+                      (VOID**) &CurrentTable,
+                      &Size,
+                      &FvStatus
+                      );
+    if (!EFI_ERROR (Status)) {
+      //
+      // Add the table
+      //
+      TableHandle = 0;
+
+      TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length;
+      ASSERT (Size >= TableSize);
+
+      //
+      // Install ACPI table
+      //
+      Status = TableInstallFunction (
+                 AcpiTable,
+                 CurrentTable,
+                 TableSize,
+                 &TableHandle
+                 );
+
+      //
+      // Free memory allocated by ReadSection
+      //
+      gBS->FreePool (CurrentTable);
+
+      if (EFI_ERROR (Status)) {
+        return EFI_ABORTED;
+      }
+
+      //
+      // Increment the instance
+      //
+      Instance++;
+      CurrentTable = NULL;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Effective entrypoint of Acpi Platform driver.
+
+  @param  ImageHandle
+  @param  SystemTable
+
+  @return EFI_SUCCESS
+  @return EFI_LOAD_ERROR
+  @return EFI_OUT_OF_RESOURCES
+
+**/
+EFI_STATUS
+EFIAPI
+InstallAcpiTables (
+  IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiTable
+  )
+{
+  EFI_STATUS Status;
+
+  Status = InstallOvmfFvTables (AcpiTable);
+
+  return Status;
+}
+
diff --git a/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h
new file mode 100644
index 0000000000..157ff42c07
--- /dev/null
+++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h
@@ -0,0 +1,76 @@
+/** @file
+  Sample ACPI Platform Driver
+
+  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _ACPI_PLATFORM_H_INCLUDED_
+#define _ACPI_PLATFORM_H_INCLUDED_
+
+#include <PiDxe.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PciIo.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/XenPlatformLib.h>
+
+#include <IndustryStandard/Acpi.h>
+
+typedef struct {
+  EFI_PCI_IO_PROTOCOL *PciIo;
+  UINT64              PciAttributes;
+} ORIGINAL_ATTRIBUTES;
+
+typedef struct S3_CONTEXT S3_CONTEXT;
+
+EFI_STATUS
+EFIAPI
+InstallAcpiTable (
+  IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol,
+  IN   VOID                          *AcpiTableBuffer,
+  IN   UINTN                         AcpiTableBufferSize,
+  OUT  UINTN                         *TableKey
+  );
+
+EFI_STATUS
+EFIAPI
+BhyveInstallAcpiTable(
+  IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol,
+  IN   VOID                          *AcpiTableBuffer,
+  IN   UINTN                         AcpiTableBufferSize,
+  OUT  UINTN                         *TableKey
+  );
+
+EFI_STATUS
+EFIAPI
+InstallXenTables (
+  IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol
+  );
+
+EFI_STATUS
+EFIAPI
+InstallAcpiTables (
+  IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiTable
+  );
+
+VOID
+EnablePciDecoding (
+  OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
+  OUT UINTN               *Count
+  );
+
+VOID
+RestorePciDecoding (
+  IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
+  IN UINTN               Count
+  );
+
+#endif
+
diff --git a/BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf b/BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
new file mode 100644
index 0000000000..6e931d85c0
--- /dev/null
+++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -0,0 +1,64 @@
+## @file
+#  OVMF ACPI Platform Driver
+#
+#  Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = AcpiPlatform
+  FILE_GUID                      = D5F92408-BAB5-44CA-8A60-C212F01D7E9D
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = AcpiPlatformEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC
+#
+
+[Sources]
+  AcpiPlatform.c
+  AcpiPlatform.h
+  EntryPoint.c
+  PciDecoding.c
+  Bhyve.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  BhyvePkg/BhyvePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  UefiLib
+  PcdLib
+  BaseMemoryLib
+  DebugLib
+  UefiBootServicesTableLib
+  UefiDriverEntryPoint
+  BhyveFwCtlLib
+  MemoryAllocationLib
+  BaseLib
+  DxeServicesTableLib
+  OrderedCollectionLib
+
+[Protocols]
+  gEfiAcpiTableProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED
+  gEfiFirmwareVolume2ProtocolGuid               # PROTOCOL SOMETIMES_CONSUMED
+  gEfiPciIoProtocolGuid                         # PROTOCOL SOMETIMES_CONSUMED
+
+[Guids]
+  gRootBridgesConnectedEventGroupGuid
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
+
+[Depex]
+  gEfiAcpiTableProtocolGuid
diff --git a/BhyvePkg/AcpiPlatformDxe/Bhyve.c b/BhyvePkg/AcpiPlatformDxe/Bhyve.c
new file mode 100644
index 0000000000..7f1a5fd664
--- /dev/null
+++ b/BhyvePkg/AcpiPlatformDxe/Bhyve.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+ * Copyright (C) 2012, Red Hat, Inc.
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * 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.
+ */
+#include "AcpiPlatform.h"
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BhyveFwCtlLib.h>
+
+STATIC
+EFI_STATUS
+EFIAPI
+BhyveInstallAcpiMadtTable (
+  IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol,
+  IN   VOID                          *AcpiTableBuffer,
+  IN   UINTN                         AcpiTableBufferSize,
+  OUT  UINTN                         *TableKey
+  )
+{
+  UINT32                                              CpuCount;
+  UINTN                                               cSize;
+  UINTN                                               NewBufferSize;
+  EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt;
+  EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE         *LocalApic;
+  EFI_ACPI_1_0_IO_APIC_STRUCTURE                      *IoApic;
+  EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE    *Iso;
+  VOID                                                *Ptr;
+  UINTN                                               Loop;
+  EFI_STATUS                                          Status;
+
+  ASSERT (AcpiTableBufferSize >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+
+  // Query the host for the number of vCPUs
+  CpuCount = 0;
+  cSize = sizeof(CpuCount);
+  if (BhyveFwCtlGet ("hw.ncpu", &CpuCount, &cSize) == RETURN_SUCCESS) {
+    DEBUG ((DEBUG_INFO, "Retrieved CpuCount %d\n", CpuCount));
+    ASSERT (CpuCount >= 1);
+  } else {
+    DEBUG ((DEBUG_INFO, "CpuCount retrieval error\n"));
+    CpuCount = 1;
+  }
+
+  NewBufferSize = 1                     * sizeof (*Madt) +
+                  CpuCount              * sizeof (*LocalApic) +
+                  1                     * sizeof (*IoApic) +
+                  1                     * sizeof (*Iso);
+
+  Madt = AllocatePool (NewBufferSize);
+  if (Madt == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CopyMem (&(Madt->Header), AcpiTableBuffer, sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+  Madt->Header.Length    = (UINT32) NewBufferSize;
+  Madt->LocalApicAddress = 0xFEE00000;
+  Madt->Flags            = EFI_ACPI_1_0_PCAT_COMPAT;
+  Ptr = Madt + 1;
+
+  LocalApic = Ptr;
+  for (Loop = 0; Loop < CpuCount; ++Loop) {
+    LocalApic->Type            = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;
+    LocalApic->Length          = sizeof (*LocalApic);
+    LocalApic->AcpiProcessorId = (UINT8) Loop;
+    LocalApic->ApicId          = (UINT8) Loop;
+    LocalApic->Flags           = 1; // enabled
+    ++LocalApic;
+  }
+  Ptr = LocalApic;
+
+  IoApic = Ptr;
+  IoApic->Type             = EFI_ACPI_1_0_IO_APIC;
+  IoApic->Length           = sizeof (*IoApic);
+  IoApic->IoApicId         = (UINT8) CpuCount;
+  IoApic->Reserved         = EFI_ACPI_RESERVED_BYTE;
+  IoApic->IoApicAddress    = 0xFEC00000;
+  IoApic->SystemVectorBase = 0x00000000;
+  Ptr = IoApic + 1;
+
+  //
+  // IRQ0 (8254 Timer) => IRQ2 (PIC) Interrupt Source Override Structure
+  //
+  Iso = Ptr;
+  Iso->Type                        = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE;
+  Iso->Length                      = sizeof (*Iso);
+  Iso->Bus                         = 0x00; // ISA
+  Iso->Source                      = 0x00; // IRQ0
+  Iso->GlobalSystemInterruptVector = 0x00000002;
+  Iso->Flags                       = 0x0000; // Conforms to specs of the bus
+  Ptr = Iso + 1;
+
+  ASSERT ((UINTN) ((UINT8 *)Ptr - (UINT8 *)Madt) == NewBufferSize);
+  Status = InstallAcpiTable (AcpiProtocol, Madt, NewBufferSize, TableKey);
+
+  FreePool (Madt);
+
+  return Status;
+}
+
+EFI_STATUS
+EFIAPI
+BhyveInstallAcpiTable (
+  IN   EFI_ACPI_TABLE_PROTOCOL       *AcpiProtocol,
+  IN   VOID                          *AcpiTableBuffer,
+  IN   UINTN                         AcpiTableBufferSize,
+  OUT  UINTN                         *TableKey
+  )
+{
+  EFI_ACPI_DESCRIPTION_HEADER        *Hdr;
+  EFI_ACPI_TABLE_INSTALL_ACPI_TABLE  TableInstallFunction;
+
+  Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AcpiTableBuffer;
+  switch (Hdr->Signature) {
+  case EFI_ACPI_1_0_APIC_SIGNATURE:
+    TableInstallFunction = BhyveInstallAcpiMadtTable;
+    break;
+  default:
+    TableInstallFunction = InstallAcpiTable;
+  }
+
+  return TableInstallFunction (
+           AcpiProtocol,
+           AcpiTableBuffer,
+           AcpiTableBufferSize,
+           TableKey
+           );
+}
diff --git a/BhyvePkg/AcpiPlatformDxe/EntryPoint.c b/BhyvePkg/AcpiPlatformDxe/EntryPoint.c
new file mode 100644
index 0000000000..f66f892911
--- /dev/null
+++ b/BhyvePkg/AcpiPlatformDxe/EntryPoint.c
@@ -0,0 +1,90 @@
+/** @file
+  Entry point of OVMF ACPI Platform Driver
+
+  Copyright (C) 2015, Red Hat, Inc.
+  Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/RootBridgesConnectedEventGroup.h>
+#include "AcpiPlatform.h"
+
+STATIC
+EFI_ACPI_TABLE_PROTOCOL *
+FindAcpiTableProtocol (
+  VOID
+  )
+{
+  EFI_STATUS              Status;
+  EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+
+  Status = gBS->LocateProtocol (
+                  &gEfiAcpiTableProtocolGuid,
+                  NULL,
+                  (VOID**)&AcpiTable
+                  );
+  ASSERT_EFI_ERROR (Status);
+  return AcpiTable;
+}
+
+
+STATIC
+VOID
+EFIAPI
+OnRootBridgesConnected (
+  IN EFI_EVENT Event,
+  IN VOID      *Context
+  )
+{
+  EFI_STATUS Status;
+
+  DEBUG ((DEBUG_INFO,
+    "%a: root bridges have been connected, installing ACPI tables\n",
+    __FUNCTION__));
+  Status = InstallAcpiTables (FindAcpiTableProtocol ());
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "%a: InstallAcpiTables: %r\n", __FUNCTION__, Status));
+  }
+  gBS->CloseEvent (Event);
+}
+
+
+EFI_STATUS
+EFIAPI
+AcpiPlatformEntryPoint (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS Status;
+  EFI_EVENT  RootBridgesConnected;
+
+  //
+  // If the platform doesn't support PCI, or PCI enumeration has been disabled,
+  // install the tables at once, and let the entry point's return code reflect
+  // the full functionality.
+  //
+  if (PcdGetBool (PcdPciDisableBusEnumeration)) {
+    DEBUG ((DEBUG_INFO, "%a: PCI or its enumeration disabled, installing "
+      "ACPI tables\n", __FUNCTION__));
+    return InstallAcpiTables (FindAcpiTableProtocol ());
+  }
+
+  //
+  // Otherwise, delay installing the ACPI tables until root bridges are
+  // connected. The entry point's return status will only reflect the callback
+  // setup. (Note that we're a DXE_DRIVER; our entry point function is invoked
+  // strictly before BDS is entered and can connect the root bridges.)
+  //
+  Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+                  OnRootBridgesConnected, NULL /* Context */,
+                  &gRootBridgesConnectedEventGroupGuid, &RootBridgesConnected);
+  if (!EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_INFO,
+      "%a: waiting for root bridges to be connected, registered callback\n",
+      __FUNCTION__));
+  }
+
+  return Status;
+}
diff --git a/BhyvePkg/AcpiPlatformDxe/PciDecoding.c b/BhyvePkg/AcpiPlatformDxe/PciDecoding.c
new file mode 100644
index 0000000000..73894106c9
--- /dev/null
+++ b/BhyvePkg/AcpiPlatformDxe/PciDecoding.c
@@ -0,0 +1,192 @@
+/** @file
+  Temporarily enable IO and MMIO decoding for all PCI devices while QEMU
+  regenerates the ACPI tables.
+
+  Copyright (C) 2016, Red Hat, Inc.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/MemoryAllocationLib.h>
+
+#include "AcpiPlatform.h"
+
+
+/**
+  Collect all PciIo protocol instances in the system. Save their original
+  attributes, and enable IO and MMIO decoding for each.
+
+  This is a best effort function; it doesn't return status codes. Its
+  caller is supposed to proceed even if this function fails.
+
+  @param[out] OriginalAttributes  On output, a dynamically allocated array of
+                                  ORIGINAL_ATTRIBUTES elements. The array lists
+                                  the PciIo protocol instances found in the
+                                  system at the time of the call, plus the
+                                  original PCI attributes for each.
+
+                                  Before returning, the function enables IO and
+                                  MMIO decoding for each PciIo instance it
+                                  finds.
+
+                                  On error, or when no such instances are
+                                  found, OriginalAttributes is set to NULL.
+
+  @param[out] Count               On output, the number of elements in
+                                  OriginalAttributes. On error it is set to
+                                  zero.
+**/
+VOID
+EnablePciDecoding (
+  OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
+  OUT UINTN               *Count
+  )
+{
+  EFI_STATUS          Status;
+  UINTN               NoHandles;
+  EFI_HANDLE          *Handles;
+  ORIGINAL_ATTRIBUTES *OrigAttrs;
+  UINTN               Idx;
+
+  *OriginalAttributes = NULL;
+  *Count              = 0;
+
+  if (PcdGetBool (PcdPciDisableBusEnumeration)) {
+    //
+    // The platform downloads ACPI tables from QEMU in general, but there are
+    // no root bridges in this execution. We're done.
+    //
+    return;
+  }
+
+  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid,
+                  NULL /* SearchKey */, &NoHandles, &Handles);
+  if (Status == EFI_NOT_FOUND) {
+    //
+    // No PCI devices were found on either of the root bridges. We're done.
+    //
+    return;
+  }
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_WARN, "%a: LocateHandleBuffer(): %r\n", __FUNCTION__,
+      Status));
+    return;
+  }
+
+  OrigAttrs = AllocatePool (NoHandles * sizeof *OrigAttrs);
+  if (OrigAttrs == NULL) {
+    DEBUG ((DEBUG_WARN, "%a: AllocatePool(): out of resources\n",
+      __FUNCTION__));
+    goto FreeHandles;
+  }
+
+  for (Idx = 0; Idx < NoHandles; ++Idx) {
+    EFI_PCI_IO_PROTOCOL *PciIo;
+    UINT64              Attributes;
+
+    //
+    // Look up PciIo on the handle and stash it
+    //
+    Status = gBS->HandleProtocol (Handles[Idx], &gEfiPciIoProtocolGuid,
+                    (VOID**)&PciIo);
+    ASSERT_EFI_ERROR (Status);
+    OrigAttrs[Idx].PciIo = PciIo;
+
+    //
+    // Stash the current attributes
+    //
+    Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationGet, 0,
+                      &OrigAttrs[Idx].PciAttributes);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationGet: %r\n",
+        __FUNCTION__, Status));
+      goto RestoreAttributes;
+    }
+
+    //
+    // Retrieve supported attributes
+    //
+    Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSupported, 0,
+                      &Attributes);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationSupported: %r\n",
+        __FUNCTION__, Status));
+      goto RestoreAttributes;
+    }
+
+    //
+    // Enable IO and MMIO decoding
+    //
+    Attributes &= EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY;
+    Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationEnable,
+                      Attributes, NULL);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationEnable: %r\n",
+        __FUNCTION__, Status));
+      goto RestoreAttributes;
+    }
+  }
+
+  //
+  // Success
+  //
+  FreePool (Handles);
+  *OriginalAttributes = OrigAttrs;
+  *Count              = NoHandles;
+  return;
+
+RestoreAttributes:
+  while (Idx > 0) {
+    --Idx;
+    OrigAttrs[Idx].PciIo->Attributes (OrigAttrs[Idx].PciIo,
+                            EfiPciIoAttributeOperationSet,
+                            OrigAttrs[Idx].PciAttributes,
+                            NULL
+                            );
+  }
+  FreePool (OrigAttrs);
+
+FreeHandles:
+  FreePool (Handles);
+}
+
+
+/**
+  Restore the original PCI attributes saved with EnablePciDecoding().
+
+  @param[in] OriginalAttributes  The array allocated and populated by
+                                 EnablePciDecoding(). This parameter may be
+                                 NULL. If OriginalAttributes is NULL, then the
+                                 function is a no-op; otherwise the PciIo
+                                 attributes will be restored, and the
+                                 OriginalAttributes array will be freed.
+
+  @param[in] Count               The Count value stored by EnablePciDecoding(),
+                                 the number of elements in OriginalAttributes.
+                                 Count may be zero if and only if
+                                 OriginalAttributes is NULL.
+**/
+VOID
+RestorePciDecoding (
+  IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
+  IN UINTN               Count
+  )
+{
+  UINTN Idx;
+
+  ASSERT ((OriginalAttributes == NULL) == (Count == 0));
+  if (OriginalAttributes == NULL) {
+    return;
+  }
+
+  for (Idx = 0; Idx < Count; ++Idx) {
+    OriginalAttributes[Idx].PciIo->Attributes (
+                                     OriginalAttributes[Idx].PciIo,
+                                     EfiPciIoAttributeOperationSet,
+                                     OriginalAttributes[Idx].PciAttributes,
+                                     NULL
+                                     );
+  }
+  FreePool (OriginalAttributes);
+}
-- 
2.20.1



^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor
  2020-04-21  3:09 [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor Rebecca Cran
                   ` (5 preceding siblings ...)
  2020-04-21  3:09 ` [PATCH v3 6/6] BhyvePkg: Add AcpiPlatformDxe Rebecca Cran
@ 2020-04-21 15:27 ` Laszlo Ersek
  2020-04-21 15:38   ` Rebecca Cran
  6 siblings, 1 reply; 24+ messages in thread
From: Laszlo Ersek @ 2020-04-21 15:27 UTC (permalink / raw)
  To: Rebecca Cran, devel
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

Hi Rebecca,

On 04/21/20 05:09, Rebecca Cran wrote:
> I noticed a few things wrong with the v2 series:
> 
> o BhyveFwCtlLibNull is no longer used, and could be deleted.
> o Some changes from the v1 AcpiPlatformDxe patch were left in OvmfPkg.
> o BhyvePkg/License.txt still referred to OvmfPkg. I've updated it so
>   everything under BhyvePkg should be BSD-2-Clause.
> 
> This patch series can also be found at
> https://git.bsdio.com/bcran/edk2-bhyve/commits/branch/master
> 
> Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
> 
> Rebecca Cran (6):
>   OvmfPkg: Add bhyve support into AcpiTimerLib
>   OvmfPkg: Add QemuFwCfgLibNull
>   OvmfPkg: Add VBE2 mode info structure to LegacyVgaBios.h
>   Add BhyvePkg, to support the bhyve hypervisor
>   BhyvePkg: Add PlatformPei
>   BhyvePkg: Add AcpiPlatformDxe

Sorry, I'm confused by the structure of this series / updates in this
series.

(1) For example, I can't find the patch that adds
"BhyvePkg/BhyvePkgX64.dsc", in spite of the file being listed in the
cumulative diffstat below.

(2) I also don't really understand why v2 / v3 have been posted, given
that the bhyve-specific ResetSystemLib instance that I suggested under
v1, based on your proposed code, still depends on the ResetSystemLib
cleanup series that I posted. The idea is that you would base the new
bhyve ResetSystemLib instance on my ResetSystemLib refactoring.

Because my series has not been merged yet, for such a bhyve rebase you'd
have to pick up my patches from the list temporarily. That's a 100%
usable approach, but then, this v3 series of yours does not seem to
introduce *any* ResetSystemLib instance. Have you decided to postpone
that work for later?

(Unfortunately, I can't check the ResetSystemLib resolution that you use
in "BhyvePkgX64.dsc", because, again, the v3 series doesn't actually
*contain* "BhyvePkgX64.dsc".)

(3) Regarding the v2 set -- there you mention:

On 04/21/20 04:04, Rebecca Cran wrote:
> changing FILE_GUIDs to be unique
> (except AcpiTables, which needs to be the same between OvmfPkg and
> BhyvePkg),

and I don't understand that... Oh wait, I do: the GUID

  7E374E25-8E01-4FEE-87F2-390C23C606CD

is a well-known GUID (inside ek2, that is). It's not specific to
OvmfPkg. BaseTools calls the GUID "ACPI table storage", and it is
declared in "MdeModulePkg/MdeModulePkg.dec", as
"PcdAcpiTableStorageFile" ("FFS filename to find the ACPI tables").


In the end, please wait until I get around merging the ResetSystemLib
refactoring <https://bugzilla.tianocore.org/show_bug.cgi?id=2675>. Then,
please post a new, comprehensive bhyve set. Patch sets pending review on
a mailing list are not incremental; new versions entirely supersede
earlier versions. Patches are considered incremental only when (a)
earlier patches have been merged, or (b) there's an agreement that in
the particular situation a new patch (or a few patches) can be appended
to a pending series.

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor
  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
  0 siblings, 1 reply; 24+ messages in thread
From: Rebecca Cran @ 2020-04-21 15:38 UTC (permalink / raw)
  To: Laszlo Ersek, devel
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

On 4/21/20 9:27 AM, Laszlo Ersek wrote:

>
> (1) For example, I can't find the patch that adds
> "BhyvePkg/BhyvePkgX64.dsc", in spite of the file being listed in the
> cumulative diffstat below.

That's in the "Add BhyvePkg" patch.

> (2) I also don't really understand why v2 / v3 have been posted, given
> that the bhyve-specific ResetSystemLib instance that I suggested under
> v1, based on your proposed code, still depends on the ResetSystemLib
> cleanup series that I posted. The idea is that you would base the new
> bhyve ResetSystemLib instance on my ResetSystemLib refactoring.

Since the changes to ResetSystemLib aren't required for this series and 
will require rework, I removed them.

> Because my series has not been merged yet, for such a bhyve rebase you'd
> have to pick up my patches from the list temporarily. That's a 100%
> usable approach, but then, this v3 series of yours does not seem to
> introduce *any* ResetSystemLib instance. Have you decided to postpone
> that work for later?


Sorry, yes I have decided to postpone those changes since as you say I'd 
need to pick up your patches from the list.


> In the end, please wait until I get around merging the ResetSystemLib
> refactoring <https://bugzilla.tianocore.org/show_bug.cgi?id=2675>.

I'd prefer not to, since introducing BhyvePkg doesn't depend on the 
ResetSystemLib changes. Could this series not be committed, then a 
subsequent commit be made to use the ResetSystemLib changes?

> Then,
> please post a new, comprehensive bhyve set. Patch sets pending review on
> a mailing list are not incremental; new versions entirely supersede
> earlier versions. Patches are considered incremental only when (a)
> earlier patches have been merged, or (b) there's an agreement that in
> the particular situation a new patch (or a few patches) can be appended
> to a pending series.

I totally understand that. Both the v2 and v3 patch series are 
independent and comprehensive (except for the removal of the 
ResetSystemLib changes, and combining a couple of changes together that 
didn't need to be separate).


-- 

Rebecca Cran



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor
  2020-04-21 15:38   ` Rebecca Cran
@ 2020-04-22 15:21     ` Laszlo Ersek
  2020-04-22 16:48       ` Rebecca Cran
  0 siblings, 1 reply; 24+ messages in thread
From: Laszlo Ersek @ 2020-04-22 15:21 UTC (permalink / raw)
  To: Rebecca Cran, devel
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

On 04/21/20 17:38, Rebecca Cran wrote:
> On 4/21/20 9:27 AM, Laszlo Ersek wrote:
> 
>>
>> (1) For example, I can't find the patch that adds
>> "BhyvePkg/BhyvePkgX64.dsc", in spite of the file being listed in the
>> cumulative diffstat below.
> 
> That's in the "Add BhyvePkg" patch.

I'm very sorry; for some reason, I don't have your v3 4/6 patch in my
list folder, nor my INBOX! I don't understand why. I can see the patch
in at least one mailing list archive.

> 
>> (2) I also don't really understand why v2 / v3 have been posted, given
>> that the bhyve-specific ResetSystemLib instance that I suggested under
>> v1, based on your proposed code, still depends on the ResetSystemLib
>> cleanup series that I posted. The idea is that you would base the new
>> bhyve ResetSystemLib instance on my ResetSystemLib refactoring.
> 
> Since the changes to ResetSystemLib aren't required for this series and
> will require rework, I removed them.
> 
>> Because my series has not been merged yet, for such a bhyve rebase you'd
>> have to pick up my patches from the list temporarily. That's a 100%
>> usable approach, but then, this v3 series of yours does not seem to
>> introduce *any* ResetSystemLib instance. Have you decided to postpone
>> that work for later?
> 
> 
> Sorry, yes I have decided to postpone those changes since as you say I'd
> need to pick up your patches from the list.

OK, that makes sense -- but, without the ResetSystemLib instance, are
you able to boot the BhyvePkg platform firmware in a bhyve guest? Does
(for example) the "reset -c" UEFI Shell command work?

>> In the end, please wait until I get around merging the ResetSystemLib
>> refactoring <https://bugzilla.tianocore.org/show_bug.cgi?id=2675>.
> 
> I'd prefer not to, since introducing BhyvePkg doesn't depend on the
> ResetSystemLib changes. Could this series not be committed, then a
> subsequent commit be made to use the ResetSystemLib changes?

Yes, this ordering makes 100% sense -- assuming your v3 series passes
review and is *functional enough*.

Does the ResetSystem runtime service work, in v3?

Thanks!

(And I'm sorry about my slow responses, it's... difficult. :/)

Laszlo


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor
  2020-04-22 15:21     ` Laszlo Ersek
@ 2020-04-22 16:48       ` Rebecca Cran
  2020-04-24 10:11         ` Laszlo Ersek
  0 siblings, 1 reply; 24+ messages in thread
From: Rebecca Cran @ 2020-04-22 16:48 UTC (permalink / raw)
  To: Laszlo Ersek, devel
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

On 4/22/20 9:21 AM, Laszlo Ersek wrote:

> OK, that makes sense -- but, without the ResetSystemLib instance, are
> you able to boot the BhyvePkg platform firmware in a bhyve guest? Does
> (for example) the "reset -c" UEFI Shell command work?

"reset -c" works, but "reset -s" doesn't. But that's a long-standing 
bug, going back to the UDK2014-based builds so I don't think it's ever 
worked.

> Does the ResetSystem runtime service work, in v3?

Rebooting works, but powering off doesn't, but as mentioned above that's 
not a regression.


-- 
Rebecca Cran



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH v3 1/6] OvmfPkg: Add bhyve support into AcpiTimerLib
  2020-04-21  3:09 ` [PATCH v3 1/6] OvmfPkg: Add bhyve support into AcpiTimerLib Rebecca Cran
@ 2020-04-23  7:56   ` Laszlo Ersek
  0 siblings, 0 replies; 24+ messages in thread
From: Laszlo Ersek @ 2020-04-23  7:56 UTC (permalink / raw)
  To: devel, rebecca
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

On 04/21/20 05:09, Rebecca Cran wrote:
> On bhyve, the ACPI timer is located at a fixed IO address; it need
> not be programmed into, nor fetched from, the PMBA -- power
> management base address -- register of the PCI host bridge.
> 
> Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> ---
>  OvmfPkg/Include/IndustryStandard/Bhyve.h      | 16 ++++++++++
>  OvmfPkg/Include/OvmfPlatforms.h               |  1 +
>  .../AcpiTimerLib/BaseAcpiTimerLibBhyve.c      | 32 +++++++++++++++++++
>  .../AcpiTimerLib/BaseAcpiTimerLibBhyve.inf    | 30 +++++++++++++++++
>  4 files changed, 79 insertions(+)
>  create mode 100644 OvmfPkg/Include/IndustryStandard/Bhyve.h
>  create mode 100644 OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.c
>  create mode 100644 OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf

Thanks for the updates, my R-b stands.

(I've realized listing OvmfPkg.dec in the INF file is necessary for
including "OvmfPlatforms.h".)

Thanks!
Laszlo

> diff --git a/OvmfPkg/Include/IndustryStandard/Bhyve.h b/OvmfPkg/Include/IndustryStandard/Bhyve.h
> new file mode 100644
> index 0000000000..02ce5587ee
> --- /dev/null
> +++ b/OvmfPkg/Include/IndustryStandard/Bhyve.h
> @@ -0,0 +1,16 @@
> +/** @file
> +  Various register numbers and value bits based on FreeBSD's bhyve
> +  at r359530.
> +  - https://svnweb.freebsd.org/base?view=revision&revision=359530
> +
> +  Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef __BHYVE_H__
> +#define __BHYVE_H__
> +
> +#define BHYVE_ACPI_TIMER_IO_ADDR 0x408
> +
> +#endif // __BHYVE_H__
> diff --git a/OvmfPkg/Include/OvmfPlatforms.h b/OvmfPkg/Include/OvmfPlatforms.h
> index 59459231e8..77dd818e30 100644
> --- a/OvmfPkg/Include/OvmfPlatforms.h
> +++ b/OvmfPkg/Include/OvmfPlatforms.h
> @@ -14,6 +14,7 @@
>  #include <IndustryStandard/Pci22.h>
>  #include <IndustryStandard/Q35MchIch9.h>
>  #include <IndustryStandard/I440FxPiix4.h>
> +#include <IndustryStandard/Bhyve.h>
>  
>  //
>  // OVMF Host Bridge DID Address
> diff --git a/OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.c b/OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.c
> new file mode 100644
> index 0000000000..f927e27188
> --- /dev/null
> +++ b/OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.c
> @@ -0,0 +1,32 @@
> +/** @file
> +  Provide InternalAcpiGetTimerTick for the bhyve instance of the
> +  Base ACPI Timer Library
> +
> +  Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
> +  Copyright (C) 2014, Gabriel L. Somlo <somlo@cmu.edu>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Library/IoLib.h>
> +#include <OvmfPlatforms.h>
> +
> +/**
> +  Internal function to read the current tick counter of ACPI.
> +
> +  Read the current ACPI tick counter using the counter address cached
> +  by this instance's constructor.
> +
> +  @return The tick counter read.
> +
> +**/
> +UINT32
> +InternalAcpiGetTimerTick (
> +  VOID
> +  )
> +{
> +  //
> +  // Return the current ACPI timer value.
> +  //
> +  return IoRead32 (BHYVE_ACPI_TIMER_IO_ADDR);
> +}
> diff --git a/OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf b/OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf
> new file mode 100644
> index 0000000000..14b7479e67
> --- /dev/null
> +++ b/OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf
> @@ -0,0 +1,30 @@
> +## @file
> +#  Base ACPI Timer Library Instance for Bhyve.
> +#
> +#  Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
> +#  Copyright (C) 2014, Gabriel L. Somlo <somlo@cmu.edu>
> +#  Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010005
> +  BASE_NAME      = BaseAcpiTimerLibBhyve
> +  FILE_GUID      = A5E3B247-7302-11EA-9C04-3CECEF0C1C08
> +  MODULE_TYPE    = BASE
> +  VERSION_STRING = 1.0
> +  LIBRARY_CLASS  = TimerLib
> +
> +[Sources]
> +  AcpiTimerLib.c
> +  AcpiTimerLib.h
> +  BaseAcpiTimerLibBhyve.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  OvmfPkg/OvmfPkg.dec
> +
> +[LibraryClasses]
> +  IoLib
> 


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH v3 3/6] OvmfPkg: Add VBE2 mode info structure to LegacyVgaBios.h
  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   ` Laszlo Ersek
  0 siblings, 0 replies; 24+ messages in thread
From: Laszlo Ersek @ 2020-04-23  8:05 UTC (permalink / raw)
  To: devel, rebecca
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

On 04/21/20 05:09, Rebecca Cran wrote:
> bhyve uses the older VESA BIOS Extensions 2.0, so add the mode info
> structure to IndustryStandard/LegacyVgaBios.h
> 
> Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
> Acked-by: Laszlo Ersek <lersek@redhat.com>
> ---
>  .../Include/IndustryStandard/LegacyVgaBios.h  | 38 +++++++++++++++++++
>  1 file changed, 38 insertions(+)

Looks good, thanks; my A-b stands.

Laszlo

> diff --git a/OvmfPkg/Include/IndustryStandard/LegacyVgaBios.h b/OvmfPkg/Include/IndustryStandard/LegacyVgaBios.h
> index 317dac3a56..38360a68b2 100644
> --- a/OvmfPkg/Include/IndustryStandard/LegacyVgaBios.h
> +++ b/OvmfPkg/Include/IndustryStandard/LegacyVgaBios.h
> @@ -86,6 +86,44 @@ typedef struct {
>    UINT32 MaxPixelClockHz;
>    UINT8  Reserved[190];
>  } VBE_MODE_INFO;
> +
> +typedef struct {
> +  UINT16 ModeAttr;
> +  UINT8  WindowAAttr;
> +  UINT8  WindowBAttr;
> +  UINT16 WindowGranularityKB;
> +  UINT16 WindowSizeKB;
> +  UINT16 WindowAStartSegment;
> +  UINT16 WindowBStartSegment;
> +  UINT32 WindowPositioningAddress;
> +  UINT16 BytesPerScanLine;
> +
> +  UINT16 Width;
> +  UINT16 Height;
> +  UINT8  CharCellWidth;
> +  UINT8  CharCellHeight;
> +  UINT8  NumPlanes;
> +  UINT8  BitsPerPixel;
> +  UINT8  NumBanks;
> +  UINT8  MemoryModel;
> +  UINT8  BankSizeKB;
> +  UINT8  NumImagePagesLessOne;
> +  UINT8  Vbe3;
> +
> +  UINT8  RedMaskSize;
> +  UINT8  RedMaskPos;
> +  UINT8  GreenMaskSize;
> +  UINT8  GreenMaskPos;
> +  UINT8  BlueMaskSize;
> +  UINT8  BlueMaskPos;
> +  UINT8  ReservedMaskSize;
> +  UINT8  ReservedMaskPos;
> +  UINT8  DirectColorModeInfo;
> +
> +  UINT32 LfbAddress;
> +  UINT32 OffScreenAddress;
> +  UINT16 OffScreenSizeKB;
> +} VBE2_MODE_INFO;
>  #pragma pack ()
>  
>  #endif
> 


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH v3 2/6] OvmfPkg: Add QemuFwCfgLibNull
  2020-04-21  3:09 ` [PATCH v3 2/6] OvmfPkg: Add QemuFwCfgLibNull Rebecca Cran
@ 2020-04-23  8:21   ` Laszlo Ersek
  0 siblings, 0 replies; 24+ messages in thread
From: Laszlo Ersek @ 2020-04-23  8:21 UTC (permalink / raw)
  To: devel, rebecca
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

On 04/21/20 05:09, Rebecca Cran wrote:
> Add a null implementation library for QemuFwCfgLib, in order to
> support building PciHostBridgeLib for bhyve.
> 
> Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
> ---
>  .../Library/QemuFwCfgLib/QemuFwCfgLibNull.inf |  37 ++++
>  OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c  | 209 ++++++++++++++++++
>  2 files changed, 246 insertions(+)
>  create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf
>  create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c
> 
> diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf
> new file mode 100644
> index 0000000000..09f86c2b02
> --- /dev/null
> +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf
> @@ -0,0 +1,37 @@
> +## @file
> +#
> +#  Stateful, implicitly initialized fw_cfg library.

(1) This comment should be updated -- it should say (for example):

"Null implementation of the fw_cfg library".

(I could update this for you myself, but below there is another change
that I cannot do for you.)

> +#
> +#  Copyright (C) 2013, Red Hat, Inc.
> +#  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
> +#  Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>

(2) This is a new file; you should add your (C) on top (like you do in
patch#1). I can't add this for you.

> +#
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = QemuFwCfgLibNull
> +  FILE_GUID                      = B9D1A1F2-01E2-4732-982D-C7F9ED51AC6B
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = QemuFwCfgLib
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#

(3) Technically speaking, the null instance is suitable for all
architectures supported by edk2. I suggest simply dropping the
VALID_ARCHITECTURES comment block.

> +
> +[Sources]
> +  QemuFwCfgLibInternal.h

(4) We don't depend on this header file, please don't list it here.

> +  QemuFwCfgNull.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec

(5) I *think* MdeModulePkg.dec is not needed, as we don't consume any
content from MdeModulePkg. (The DebugLib class comes from MdePkg.)

> +  OvmfPkg/OvmfPkg.dec

Yes, this is necessary (because the lib class header that we'll include
comes from OvmfPkg).

> +
> +[LibraryClasses]
> +  DebugLib
> diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c
> new file mode 100644
> index 0000000000..e2cc5f3406
> --- /dev/null
> +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgNull.c
> @@ -0,0 +1,209 @@
> +/** @file
> +
> +  Stateful and implicitly initialized fw_cfg library implementation.

(6) Same as (1).

> +
> +  Copyright (C) 2013, Red Hat, Inc.
> +  Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
> +  Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/

(7) Same as (2).

> +
> +#include <Uefi.h>
> +#include <Library/DebugLib.h>
> +#include <IndustryStandard/QemuFwCfg.h>
> +

(8) I believe <Uefi.h> and <IndustryStandard/QemuFwCfg.h> can be dropped.

In exchange, <Library/QemuFwCfgLib.h> should be included. That's because
the lib class header declares the functions that this lib instance will
define (= implement). The lib class header also pulls in all
dependencies that are needed for the API declarations.

When you include <Library/QemuFwCfgLib.h>, please add it under
DebugLib.h, to keep the #include list sorted.


> +/**
> +  Returns a boolean indicating if the firmware configuration interface
> +  is available or not.
> +
> +  This function may change fw_cfg state.
> +
> +  @retval    TRUE   The interface is available
> +  @retval    FALSE  The interface is not available
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +QemuFwCfgIsAvailable (
> +  VOID
> +  )
> +{
> +  return FALSE;
> +}
> +
> +
> +/**
> +  Selects a firmware configuration item for reading.
> +
> +  Following this call, any data read from this item will start from
> +  the beginning of the configuration item's data.
> +
> +  @param[in] QemuFwCfgItem - Firmware Configuration item to read
> +
> +**/
> +VOID
> +EFIAPI
> +QemuFwCfgSelectItem (
> +  IN FIRMWARE_CONFIG_ITEM   QemuFwCfgItem
> +  )
> +{
> +  ASSERT (FALSE);
> +}
> +
> +
> +/**
> +  Reads firmware configuration bytes into a buffer
> +
> +  If called multiple times, then the data read will
> +  continue at the offset of the firmware configuration
> +  item where the previous read ended.
> +
> +  @param[in] Size - Size in bytes to read
> +  @param[in] Buffer - Buffer to store data into
> +
> +**/
> +VOID
> +EFIAPI
> +QemuFwCfgReadBytes (
> +  IN UINTN                  Size,
> +  IN VOID                   *Buffer  OPTIONAL
> +  )
> +{
> +  ASSERT (FALSE);
> +}
> +
> +
> +/**
> +  Writes firmware configuration bytes from a buffer
> +
> +  If called multiple times, then the data written will
> +  continue at the offset of the firmware configuration
> +  item where the previous write ended.
> +
> +  @param[in] Size - Size in bytes to write
> +  @param[in] Buffer - Buffer to read data from
> +
> +**/
> +VOID
> +EFIAPI
> +QemuFwCfgWriteBytes (
> +  IN UINTN                  Size,
> +  IN VOID                   *Buffer
> +  )
> +{
> +  ASSERT (FALSE);
> +}
> +
> +
> +/**
> +  Skip bytes in the firmware configuration item.
> +
> +  Increase the offset of the firmware configuration item without transferring
> +  bytes between the item and a caller-provided buffer. Subsequent read, write
> +  or skip operations will commence at the increased offset.
> +
> +  @param[in] Size  Number of bytes to skip.
> +**/
> +VOID
> +EFIAPI
> +QemuFwCfgSkipBytes (
> +  IN UINTN                  Size
> +  )
> +{
> +  ASSERT (FALSE);
> +}
> +
> +
> +/**
> +  Reads a UINT8 firmware configuration value
> +
> +  @return    Value of Firmware Configuration item read
> +
> +**/
> +UINT8
> +EFIAPI
> +QemuFwCfgRead8 (
> +  VOID
> +  )
> +{
> +  ASSERT (FALSE);
> +  return 0;
> +}
> +
> +
> +/**
> +  Reads a UINT16 firmware configuration value
> +
> +  @return    Value of Firmware Configuration item read
> +
> +**/
> +UINT16
> +EFIAPI
> +QemuFwCfgRead16 (
> +  VOID
> +  )
> +{
> +  ASSERT (FALSE);
> +  return 0;
> +}
> +
> +
> +/**
> +  Reads a UINT32 firmware configuration value
> +
> +  @return    Value of Firmware Configuration item read
> +
> +**/
> +UINT32
> +EFIAPI
> +QemuFwCfgRead32 (
> +  VOID
> +  )
> +{
> +  ASSERT (FALSE);
> +  return 0;
> +}
> +
> +
> +/**
> +  Reads a UINT64 firmware configuration value
> +
> +  @return    Value of Firmware Configuration item read
> +
> +**/
> +UINT64
> +EFIAPI
> +QemuFwCfgRead64 (
> +  VOID
> +  )
> +{
> +  ASSERT (FALSE);
> +  return 0;
> +}
> +
> +
> +/**
> +  Find the configuration item corresponding to the firmware configuration file.
> +
> +  @param[in]  Name - Name of file to look up.
> +  @param[out] Item - Configuration item corresponding to the file, to be passed
> +                     to QemuFwCfgSelectItem ().
> +  @param[out] Size - Number of bytes in the file.
> +
> +  @return    RETURN_SUCCESS       If file is found.
> +             RETURN_NOT_FOUND     If file is not found.
> +             RETURN_UNSUPPORTED   If firmware configuration is unavailable.
> +
> +**/
> +RETURN_STATUS
> +EFIAPI
> +QemuFwCfgFindFile (
> +  IN   CONST CHAR8           *Name,
> +  OUT  FIRMWARE_CONFIG_ITEM  *Item,
> +  OUT  UINTN                 *Size
> +  )
> +{
> +  return RETURN_UNSUPPORTED;
> +}
> +
> 

These parts are fine.

Thanks!
Laszlo


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH v3 4/6] Add BhyvePkg, to support the bhyve hypervisor
  2020-04-21  3:09 ` [PATCH v3 4/6] Add BhyvePkg, to support the bhyve hypervisor Rebecca Cran
@ 2020-04-23  9:19   ` Laszlo Ersek
  2020-04-23  9:42     ` Laszlo Ersek
  2020-04-23 20:08     ` Rebecca Cran
  0 siblings, 2 replies; 24+ messages in thread
From: Laszlo Ersek @ 2020-04-23  9:19 UTC (permalink / raw)
  To: devel, rebecca
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

On 04/21/20 05:09, Rebecca Cran wrote:
> BhyvePkg supports the bhyve hypervisor, which is a hypervisor/virtual
> machine manager available on FreeBSD, macOS and Illumos.
>
> Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
> ---
>  BhyvePkg/AcpiTables/AcpiTables.inf            |   42 +
>  BhyvePkg/AcpiTables/Dsdt.asl                  | 1134 +++++++++++
>  BhyvePkg/AcpiTables/Facp.aslc                 |   75 +
>  BhyvePkg/AcpiTables/Facs.aslc                 |   79 +
>  BhyvePkg/AcpiTables/Hpet.aslc                 |   71 +
>  BhyvePkg/AcpiTables/Madt.aslc                 |  144 ++
>  BhyvePkg/AcpiTables/Mcfg.aslc                 |   56 +
>  BhyvePkg/AcpiTables/Platform.h                |   71 +
>  BhyvePkg/AcpiTables/Spcr.aslc                 |   62 +
>  BhyvePkg/AcpiTables/Ssdt.asl                  |   14 +
>  BhyvePkg/BhyvePkg.dec                         |  170 ++
>  BhyvePkg/BhyvePkg.fdf.inc                     |   85 +
>  BhyvePkg/BhyvePkgX64.dsc                      |  846 +++++++++
>  BhyvePkg/BhyvePkgX64.fdf                      |  513 +++++
>  BhyvePkg/BhyveRfbDxe/BhyveRfbDxe.inf          |   67 +
>  BhyvePkg/BhyveRfbDxe/ComponentName.c          |  200 ++
>  BhyvePkg/BhyveRfbDxe/Gop.h                    |  148 ++
>  BhyvePkg/BhyveRfbDxe/GopDriver.c              |  542 ++++++
>  BhyvePkg/BhyveRfbDxe/GopScreen.c              |  392 ++++
>  BhyvePkg/BhyveRfbDxe/VbeShim.asm              |  341 ++++
>  BhyvePkg/BhyveRfbDxe/VbeShim.c                |  258 +++
>  BhyvePkg/BhyveRfbDxe/VbeShim.h                |  912 +++++++++
>  BhyvePkg/BhyveRfbDxe/VbeShim.sh               |   79 +
>  BhyvePkg/DecomprScratchEnd.fdf.inc            |   66 +
>  BhyvePkg/Include/Library/BhyveFwCtlLib.h      |   46 +
>  .../Library/BhyveFwCtlLib/BhyveFwCtlLib.c     |  425 +++++
>  .../Library/BhyveFwCtlLib/BhyveFwCtlLib.inf   |   40 +
>  .../PlatformBootManagerLib/BdsPlatform.c      | 1660 +++++++++++++++++
>  .../PlatformBootManagerLib/BdsPlatform.h      |  191 ++
>  .../PlatformBootManagerLib.inf                |   74 +
>  .../PlatformBootManagerLib/PlatformData.c     |  171 ++
>  BhyvePkg/License.txt                          |   44 +
>  BhyvePkg/SmbiosPlatformDxe/Bhyve.c            |   42 +
>  .../SmbiosPlatformDxe/SmbiosPlatformDxe.c     |  244 +++
>  .../SmbiosPlatformDxe/SmbiosPlatformDxe.h     |   63 +
>  .../SmbiosPlatformDxe/SmbiosPlatformDxe.inf   |   54 +
>  BhyvePkg/VarStore.fdf.inc                     |  115 ++
>  Maintainers.txt                               |    7 +
>  38 files changed, 9543 insertions(+)
>  create mode 100644 BhyvePkg/AcpiTables/AcpiTables.inf
>  create mode 100644 BhyvePkg/AcpiTables/Dsdt.asl
>  create mode 100644 BhyvePkg/AcpiTables/Facp.aslc
>  create mode 100644 BhyvePkg/AcpiTables/Facs.aslc
>  create mode 100644 BhyvePkg/AcpiTables/Hpet.aslc
>  create mode 100644 BhyvePkg/AcpiTables/Madt.aslc
>  create mode 100644 BhyvePkg/AcpiTables/Mcfg.aslc
>  create mode 100644 BhyvePkg/AcpiTables/Platform.h
>  create mode 100644 BhyvePkg/AcpiTables/Spcr.aslc
>  create mode 100644 BhyvePkg/AcpiTables/Ssdt.asl
>  create mode 100644 BhyvePkg/BhyvePkg.dec
>  create mode 100644 BhyvePkg/BhyvePkg.fdf.inc
>  create mode 100644 BhyvePkg/BhyvePkgX64.dsc
>  create mode 100644 BhyvePkg/BhyvePkgX64.fdf
>  create mode 100644 BhyvePkg/BhyveRfbDxe/BhyveRfbDxe.inf
>  create mode 100644 BhyvePkg/BhyveRfbDxe/ComponentName.c
>  create mode 100644 BhyvePkg/BhyveRfbDxe/Gop.h
>  create mode 100644 BhyvePkg/BhyveRfbDxe/GopDriver.c
>  create mode 100644 BhyvePkg/BhyveRfbDxe/GopScreen.c
>  create mode 100644 BhyvePkg/BhyveRfbDxe/VbeShim.asm
>  create mode 100644 BhyvePkg/BhyveRfbDxe/VbeShim.c
>  create mode 100644 BhyvePkg/BhyveRfbDxe/VbeShim.h
>  create mode 100644 BhyvePkg/BhyveRfbDxe/VbeShim.sh
>  create mode 100644 BhyvePkg/DecomprScratchEnd.fdf.inc
>  create mode 100644 BhyvePkg/Include/Library/BhyveFwCtlLib.h
>  create mode 100644 BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c
>  create mode 100644 BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
>  create mode 100644 BhyvePkg/Library/PlatformBootManagerLib/BdsPlatform.c
>  create mode 100644 BhyvePkg/Library/PlatformBootManagerLib/BdsPlatform.h
>  create mode 100644 BhyvePkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
>  create mode 100644 BhyvePkg/Library/PlatformBootManagerLib/PlatformData.c
>  create mode 100644 BhyvePkg/License.txt
>  create mode 100644 BhyvePkg/SmbiosPlatformDxe/Bhyve.c
>  create mode 100644 BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c
>  create mode 100644 BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h
>  create mode 100644 BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
>  create mode 100644 BhyvePkg/VarStore.fdf.inc
>
> diff --git a/BhyvePkg/AcpiTables/AcpiTables.inf b/BhyvePkg/AcpiTables/AcpiTables.inf
> new file mode 100644
> index 0000000000..d8907e6b56
> --- /dev/null
> +++ b/BhyvePkg/AcpiTables/AcpiTables.inf
> @@ -0,0 +1,42 @@
> +## @file
> +#  Component description file for PlatformAcpiTables module.
> +#
> +#  ACPI table data and ASL sources required to boot the platform.
> +#
> +#  Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
> +#  Copyright (c) 2014, Pluribus Networks, Inc.^M
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause
> +#
> +##

(1) The "^M" character sequence seems bogus.

(2) If you are contributing this new file in "Pluribus Networks, Inc"
colors, then please extend the year to 2020 on that line. Otherwise, if
you are contributing this on your own behalf (as work derived from
Pluribus Networks's earlier work), then please add your own (C) on top
as well, marking the year 2020.

My point is that the year is 2020, when this file is being introduced in
edk2. Thus, there should be a (C) notice naming the year 2020.

[...]

> diff --git a/BhyvePkg/AcpiTables/Dsdt.asl b/BhyvePkg/AcpiTables/Dsdt.asl
> new file mode 100644
> index 0000000000..a60d001ffd
> --- /dev/null
> +++ b/BhyvePkg/AcpiTables/Dsdt.asl
> @@ -0,0 +1,1134 @@
> +/*
> + * Intel ACPI Component Architecture
> + * AML Disassembler version 20100528
> + *
> + * Disassembly of DSDT.dat, Sat Apr 18 15:41:05 2015
> + *
> + *
> + * Original Table Header:
> + *     Signature        "DSDT"
> + *     Length           0x000008FA (2298)
> + *     Revision         0x02
> + *     Checksum         0xC4
> + *     OEM ID           "BHYVE "
> + *     OEM Table ID     "BVDSDT  "
> + *     OEM Revision     0x00000001 (1)
> + *     Compiler ID      "INTL"
> + *     Compiler Version 0x20150204 (538247684)
> + */

(3) It's fine to include a decompiled DSDT ASL in the git tree; the INF
file does reference this file.

I'm requesting one of two things, dependent on your *plans* to update
this file in the future.

(3a) If this file should always be re-generated with "iasl -d" -- i.e.,
never edited manually --, then please add a comment at the top, to the
effect of:

  generated file -- DO NOT EDIT

(3b) If this file is meant as a starting point only, and is supposed to
receive manual updates over time, then it needs a (C) notice, and an
SPDX-License-Identifier, in my opinion.

[...]

> diff --git a/BhyvePkg/AcpiTables/Facp.aslc b/BhyvePkg/AcpiTables/Facp.aslc
> new file mode 100644
> index 0000000000..73afb4a9aa
> --- /dev/null
> +++ b/BhyvePkg/AcpiTables/Facp.aslc
> @@ -0,0 +1,75 @@
> +/*
> + * Copyright (c) 2014, Pluribus Networks, Inc.
> + *
> + * SPDX-License-Identifier: BSD-2-Clause
> + */

(4) Same as (2).

[...]

> diff --git a/BhyvePkg/AcpiTables/Facs.aslc b/BhyvePkg/AcpiTables/Facs.aslc
> new file mode 100644
> index 0000000000..b66d698df4
> --- /dev/null
> +++ b/BhyvePkg/AcpiTables/Facs.aslc
> @@ -0,0 +1,79 @@
> +/** @file
> +  FACS Table
> +
> +  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause
> +
> +**/

(5) Same as (2).

This issue seems to affect the rest of the newly added files; I wouldn't
like to point it out repeatedly.

Please refresh the copyright notices on all of the new files -- and not
just in this patch, but also in the rest of the series.

(Obviously, I could be wrong about this; feedback (especially from other
stewards) is appreciated.)

[...]

> diff --git a/BhyvePkg/AcpiTables/Platform.h b/BhyvePkg/AcpiTables/Platform.h
> new file mode 100644
> index 0000000000..4c029cc096
> --- /dev/null
> +++ b/BhyvePkg/AcpiTables/Platform.h
> @@ -0,0 +1,71 @@
> +/** @file
> +  Platform specific defines for constructing ACPI tables
> +
> +  Copyright (c) 2014, Pluribus Networks, Inc.^M
> +  Copyright (c) 2012, 2013, Red Hat, Inc.
> +  Copyright (c) 2008, Intel Corporation. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause
> +
> +**/

(6) Same as (1) -- bogus "^M".

[...]

> diff --git a/BhyvePkg/License.txt b/BhyvePkg/License.txt
> new file mode 100644
> index 0000000000..d1bdbae60f
> --- /dev/null
> +++ b/BhyvePkg/License.txt
> @@ -0,0 +1,44 @@
> +Copyright (c) 2012, Intel Corporation. All rights reserved.

(7) Since you are introducing this package now -- would it make sense to
collect all the copyrights from the files being added under BhyvePkg,
and collect them here?

(This would include the new (C) notices that I'm requesting in this very
review.)

(8) Please spell out the SPDX identifier here, for the license text that
follows below.

> +
> +Redistribution and use in source and binary forms, with or without
> +modification, are permitted provided that the following conditions
> +are met:
> +
> +* Redistributions of source code must retain the above copyright
> +  notice, this list of conditions and the following disclaimer.
> +* Redistributions in binary form must reproduce the above copyright
> +  notice, this list of conditions and the following disclaimer in
> +  the documentation and/or other materials provided with the
> +  distribution.
> +
> +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
> +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> +COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
> +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
> +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
> +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> +POSSIBILITY OF SUCH DAMAGE.

The 2-clause BSDL <https://spdx.org/licenses/BSD-2-Clause.html> seems to
end at this spot.

The text that follows below is the MIT license
<https://spdx.org/licenses/MIT.html>:

> +
> +
> +Permission is hereby granted, free of charge, to any person obtaining a copy
> +of this software and associated documentation files (the "Software"), to deal
> +in the Software without restriction, including without limitation the rights
> +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> +copies of the Software, and to permit persons to whom the Software is
> +furnished to do so, subject to the following conditions:
> +
> +The above copyright notice and this permission notice shall be included in
> +all copies or substantial portions of the Software.
> +
> +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> +THE SOFTWARE.

(9) I think we should delete the MIT license. At this stage, I can't see
anything MIT-covered under BhyvePkg. Do you agree?

(10) *However*, in the subsequent patches (#5 and #6), you are
introducing content (PlatformPei and AcpiPlatformDxe) that is under
BSD-2-Clause-Patent.

Meaning that BhyvePkg needs a License.txt that's similar to
OvmfPkg/License.txt:

- it should list *two* licenses,

- the license blocks should be separated visually (e.g. a long line of
  "====="),

- both license blocks should have their SPDX identifiers,

- the "default" license -- BSD-2-Clause-Patent --should be at the top,

- the "non-default" license -- namely BSD-2-Clause -- should be at the
  bottom, and it should *list* the modules that are covered by it.


(11) You should also extend the "Readme.md" file in the project root
directory please. Simply search that file for "OvmfPkg/License.txt", and
then you'll understand what I'm requesting -- just list
"BhyvePkg/License.txt" there, similarly to how OvmfPkg's is.

[...]

> diff --git a/Maintainers.txt b/Maintainers.txt
> index 1733225722..1d1a681216 100644
> --- a/Maintainers.txt
> +++ b/Maintainers.txt
> @@ -158,6 +158,13 @@ W: https://github.com/tianocore/tianocore.github.io/wiki/BaseTools
>  M: Bob Feng <bob.c.feng@intel.com>
>  M: Liming Gao <liming.gao@intel.com>
>
> +BhyvePkg
> +F: BhyvePkg/
> +W: https://bhyve.org
> +M: Rebecca Cran <rebecca@bsdio.com>
> +R: Peter Grehan <grehan@freebsd.org>
> +S: Maintained
> +
>  CryptoPkg
>  F: CryptoPkg/
>  W: https://github.com/tianocore/tianocore.github.io/wiki/CryptoPkg
>

This hunk looks fine; I highly appreciate it. We'll need Peter to ACK
this patch of the series in particular, on the edk2-devel list, please.

Thanks!
Laszlo


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH v3 5/6] BhyvePkg: Add PlatformPei
  2020-04-21  3:09 ` [PATCH v3 5/6] BhyvePkg: Add PlatformPei Rebecca Cran
@ 2020-04-23  9:24   ` Laszlo Ersek
  0 siblings, 0 replies; 24+ messages in thread
From: Laszlo Ersek @ 2020-04-23  9:24 UTC (permalink / raw)
  To: devel, rebecca
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

On 04/21/20 05:09, Rebecca Cran wrote:
> 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

- There are multiple files added in this patch (MemDetect.c, Platform.c,
PlatformPei.inf) that still don't use the SPDX-License-Identifier
format, but spell out the license texts verbatim.

Please fix up those.

- Also, please refresh the copyright notices / years on these files,
like I request under patch#4, in point (2).

With those updates, I think I'll be ready to ACK this patch.

Thanks,
Laszlo

> 
> 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
> +
> 


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH v3 4/6] Add BhyvePkg, to support the bhyve hypervisor
  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-23 20:08     ` Rebecca Cran
  1 sibling, 1 reply; 24+ messages in thread
From: Laszlo Ersek @ 2020-04-23  9:42 UTC (permalink / raw)
  To: devel, rebecca
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

On 04/23/20 11:19, Laszlo Ersek wrote:

> (10) *However*, in the subsequent patches (#5 and #6), you are
> introducing content (PlatformPei and AcpiPlatformDxe) that is under
> BSD-2-Clause-Patent.
> 
> Meaning that BhyvePkg needs a License.txt that's similar to
> OvmfPkg/License.txt:
> 
> - it should list *two* licenses,
> 
> - the license blocks should be separated visually (e.g. a long line of
>   "====="),
> 
> - both license blocks should have their SPDX identifiers,
> 
> - the "default" license -- BSD-2-Clause-Patent --should be at the top,
> 
> - the "non-default" license -- namely BSD-2-Clause -- should be at the
>   bottom, and it should *list* the modules that are covered by it.

I'm just realizing that, unfortunately, patches #5 and #6 introduce
modules where each module *in itself* is not consistently covered by a
single license.

In other words, PlatformPei is a mix of BSD-2-Clause-Patent and
BSD-2-Clause. So is AcpiPlatformDxe.

BUt, I *think* the language seen in "OvmfPkg/License.txt" should
accommodate that too. It goes:

  Some files are subject to the following license, the [...] license.
  Those files are located in:
  - [directory]
  - [directory]

It says "some files", and where they are. It doesn't seem to imply that
*all* files under those directories are covered by the non-default license.

So please just list all those module directories in this (non-default)
part of "BhyvePkg/License.txt" that have *at least one* file covered by
"BSD-2-Clause".

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH v3 6/6] BhyvePkg: Add AcpiPlatformDxe
  2020-04-21  3:09 ` [PATCH v3 6/6] BhyvePkg: Add AcpiPlatformDxe Rebecca Cran
@ 2020-04-23  9:44   ` Laszlo Ersek
  0 siblings, 0 replies; 24+ messages in thread
From: Laszlo Ersek @ 2020-04-23  9:44 UTC (permalink / raw)
  To: devel, rebecca
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

On 04/21/20 05:09, Rebecca Cran wrote:
> Make a copy of OvmfPkg/AcpiPlatformDxe under BhyvePkg, with the changes
> needed to support the bhyve hypervisor.
> 
> Signed-off-by: Rebecca Cran <rebecca@bsdio.com>
> ---
>  BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c      | 250 +++++++++++++++++++
>  BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h      |  76 ++++++
>  BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf |  64 +++++
>  BhyvePkg/AcpiPlatformDxe/Bhyve.c             | 138 ++++++++++
>  BhyvePkg/AcpiPlatformDxe/EntryPoint.c        |  90 +++++++
>  BhyvePkg/AcpiPlatformDxe/PciDecoding.c       | 192 ++++++++++++++
>  6 files changed, 810 insertions(+)
>  create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c
>  create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h
>  create mode 100644 BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
>  create mode 100644 BhyvePkg/AcpiPlatformDxe/Bhyve.c
>  create mode 100644 BhyvePkg/AcpiPlatformDxe/EntryPoint.c
>  create mode 100644 BhyvePkg/AcpiPlatformDxe/PciDecoding.c
> 
> diff --git a/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c
> new file mode 100644
> index 0000000000..4814a9f1e6
> --- /dev/null
> +++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c
> @@ -0,0 +1,250 @@
> +/** @file
> +  OVMF ACPI Platform Driver
> +
> +  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/

(1) Please add your (C) notice, with the year 2020.


> diff --git a/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h
> new file mode 100644
> index 0000000000..157ff42c07
> --- /dev/null
> +++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h
> @@ -0,0 +1,76 @@
> +/** @file
> +  Sample ACPI Platform Driver
> +
> +  Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/

(2) Same as (1).

> diff --git a/BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf b/BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
> new file mode 100644
> index 0000000000..6e931d85c0
> --- /dev/null
> +++ b/BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
> @@ -0,0 +1,64 @@
> +## @file
> +#  OVMF ACPI Platform Driver
> +#
> +#  Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
> +#
> +#  SPDX-License-Identifier: BSD-2-Clause
> +##

(3) Same as (1).

> diff --git a/BhyvePkg/AcpiPlatformDxe/Bhyve.c b/BhyvePkg/AcpiPlatformDxe/Bhyve.c
> new file mode 100644
> index 0000000000..7f1a5fd664
> --- /dev/null
> +++ b/BhyvePkg/AcpiPlatformDxe/Bhyve.c
> @@ -0,0 +1,138 @@
> +/*
> + * Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
> + * Copyright (C) 2012, Red Hat, Inc.
> + * Copyright (c) 2014, Pluribus Networks, Inc.
> + *
> + * 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.
> + */

(4) please use the SPDX ID format.

> diff --git a/BhyvePkg/AcpiPlatformDxe/EntryPoint.c b/BhyvePkg/AcpiPlatformDxe/EntryPoint.c
> new file mode 100644
> index 0000000000..f66f892911
> --- /dev/null
> +++ b/BhyvePkg/AcpiPlatformDxe/EntryPoint.c
> @@ -0,0 +1,90 @@
> +/** @file
> +  Entry point of OVMF ACPI Platform Driver
> +
> +  Copyright (C) 2015, Red Hat, Inc.
> +  Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/

(5) Same as (1).

> diff --git a/BhyvePkg/AcpiPlatformDxe/PciDecoding.c b/BhyvePkg/AcpiPlatformDxe/PciDecoding.c
> new file mode 100644
> index 0000000000..73894106c9
> --- /dev/null
> +++ b/BhyvePkg/AcpiPlatformDxe/PciDecoding.c
> @@ -0,0 +1,192 @@
> +/** @file
> +  Temporarily enable IO and MMIO decoding for all PCI devices while QEMU
> +  regenerates the ACPI tables.
> +
> +  Copyright (C) 2016, Red Hat, Inc.
> +
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/

(6) Same as (1).

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH v3 4/6] Add BhyvePkg, to support the bhyve hypervisor
  2020-04-23  9:19   ` [edk2-devel] " Laszlo Ersek
  2020-04-23  9:42     ` Laszlo Ersek
@ 2020-04-23 20:08     ` Rebecca Cran
  2020-04-24 10:11       ` Laszlo Ersek
  1 sibling, 1 reply; 24+ messages in thread
From: Rebecca Cran @ 2020-04-23 20:08 UTC (permalink / raw)
  To: devel, Laszlo Ersek
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan


> On Apr 23, 2020, at 3:19 AM, Laszlo Ersek <lersek@redhat.com> wrote:
> 
> (2) If you are contributing this new file in "Pluribus Networks, Inc"
> colors, then please extend the year to 2020 on that line. Otherwise, if
> you are contributing this on your own behalf (as work derived from
> Pluribus Networks's earlier work), then please add your own (C) on top
> as well, marking the year 2020.
> 
> My point is that the year is 2020, when this file is being introduced in
> edk2. Thus, there should be a (C) notice naming the year 2020.

Unfortunately I’m not contributing for Pluribus Networks — that’s why we have to keep some files are BSD-2-Clause.
Should I add my own copyright line for _all_ files I’m adding under BhyvePkg, or just those that have new/changed content? For example there are several files such as BhyvePkg/PlatformPei/AmdSev.c that I copied verbatim from OvmfPkg that I’d feel especially uncomfortable with claiming copyright over.

> (9) I think we should delete the MIT license. At this stage, I can't see
> anything MIT-covered under BhyvePkg. Do you agree?

Yes, I agree. I’ll proceed with that change.

— 
Rebecca Cran



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH v3 4/6] Add BhyvePkg, to support the bhyve hypervisor
  2020-04-23  9:42     ` Laszlo Ersek
@ 2020-04-24  5:54       ` Rebecca Cran
  2020-04-24 12:22         ` Laszlo Ersek
  0 siblings, 1 reply; 24+ messages in thread
From: Rebecca Cran @ 2020-04-24  5:54 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: devel, Jordan Justen, Ard Biesheuvel, Leif Lindholm,
	Michael Kinney, Andrew Fish, Peter Grehan


> On Apr 23, 2020, at 3:42 AM, Laszlo Ersek <lersek@redhat.com> wrote:
> 
> BUt, I *think* the language seen in "OvmfPkg/License.txt" should
> accommodate that too. It goes:
> 
>  Some files are subject to the following license, the [...] license.
>  Those files are located in:
>  - [directory]
>  - [directory]
> 
> It says "some files", and where they are. It doesn't seem to imply that
> *all* files under those directories are covered by the non-default license.
> 
> So please just list all those module directories in this (non-default)
> part of "BhyvePkg/License.txt" that have *at least one* file covered by
> "BSD-2-Clause".


Would it also be ok to use the following language?

Some files are subject to the following license, the BSD-2-Clause license.
Those files are located in:

AcpiPlatformDxe/Bhyve.c
PlatformPei/MemDetect.c
PlatformPei/Platform.c


I think I’ve fixed the rest of the changes you’ve requested. I’m ready to send the v4 series once I get clarification about whether I should add my own copyright line to files I’ve copied from OvmfPkg and made no changes to, or only deletions or other very minor changes.

— 
Rebecca Cran

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH v3 4/6] Add BhyvePkg, to support the bhyve hypervisor
  2020-04-23 20:08     ` Rebecca Cran
@ 2020-04-24 10:11       ` Laszlo Ersek
  2020-04-24 16:00         ` Rebecca Cran
  0 siblings, 1 reply; 24+ messages in thread
From: Laszlo Ersek @ 2020-04-24 10:11 UTC (permalink / raw)
  To: Rebecca Cran, devel
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

On 04/23/20 22:08, Rebecca Cran wrote:
> 
>> On Apr 23, 2020, at 3:19 AM, Laszlo Ersek <lersek@redhat.com> wrote:
>>
>> (2) If you are contributing this new file in "Pluribus Networks, Inc"
>> colors, then please extend the year to 2020 on that line. Otherwise, if
>> you are contributing this on your own behalf (as work derived from
>> Pluribus Networks's earlier work), then please add your own (C) on top
>> as well, marking the year 2020.
>>
>> My point is that the year is 2020, when this file is being introduced in
>> edk2. Thus, there should be a (C) notice naming the year 2020.
> 
> Unfortunately I’m not contributing for Pluribus Networks — that’s why we have to keep some files are BSD-2-Clause.
> Should I add my own copyright line for _all_ files I’m adding under BhyvePkg, or just those that have new/changed content? For example there are several files such as BhyvePkg/PlatformPei/AmdSev.c that I copied verbatim from OvmfPkg that I’d feel especially uncomfortable with claiming copyright over.

If you're 100% sure that you are copying a file from elsewhere in the
tree, as it was at some particular commit of the git history, without
any changes introduced at all as part of the copying, then I guess it's
OK to not add your own copyright.

Normally, this is not difficult to verify for a reviewer, as the
"--find-copies-harder" option of "git show" can find the origin (the
file) of the copy, and display the copy (the new file) in terms of
changes to the origin.

However, the above only works in reference to the *direct pre-patch
state* of the tree. In other words, "--find-copies-harder" cannot
identify a file that, checked out at an *earlier* commit, could be
considered the origin of the copy you are creating *now*.

And given that some of these files were forked from edk2 master in 2014
or so (?), it's not easy to tell whether any difference *now* flagged by
"--find-copies-harder" is

- a difference introduced genuinely by your forking,
- or a more recent change to the *original* that has not been
forward-ported to your fork.

In such cases the ideal solution is to rebase the work; in other words,
re-fork the bhyve stuff from current edk2 / OvmfPkg content. But, I'm
not sure you have capacity for that; it may not be necessary even
functionally speaking; and even to me as the initial reviewer of
BhyvePkg content as one of the stewards, it only matters because of the
copyright notices. (And obviously I'm not a lawyer...)

So, if you are *completely* sure you didn't change anything on those
copies, relative to their fork-off point originals, then I guess it's OK
to not add your (C).

Thanks,
Laszlo

>> (9) I think we should delete the MIT license. At this stage, I can't see
>> anything MIT-covered under BhyvePkg. Do you agree?
> 
> Yes, I agree. I’ll proceed with that change.
> 
> — 
> Rebecca Cran
> 
> 


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v3 0/6] Add BhyvePkg, to support the bhyve hypervisor
  2020-04-22 16:48       ` Rebecca Cran
@ 2020-04-24 10:11         ` Laszlo Ersek
  0 siblings, 0 replies; 24+ messages in thread
From: Laszlo Ersek @ 2020-04-24 10:11 UTC (permalink / raw)
  To: Rebecca Cran, devel
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan

On 04/22/20 18:48, Rebecca Cran wrote:
> On 4/22/20 9:21 AM, Laszlo Ersek wrote:
> 
>> OK, that makes sense -- but, without the ResetSystemLib instance, are
>> you able to boot the BhyvePkg platform firmware in a bhyve guest? Does
>> (for example) the "reset -c" UEFI Shell command work?
> 
> "reset -c" works, but "reset -s" doesn't. But that's a long-standing
> bug, going back to the UDK2014-based builds so I don't think it's ever
> worked.
> 
>> Does the ResetSystem runtime service work, in v3?
> 
> Rebooting works, but powering off doesn't, but as mentioned above that's
> not a regression.
> 
> 

OK, thanks!
Laszlo


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH v3 4/6] Add BhyvePkg, to support the bhyve hypervisor
  2020-04-24  5:54       ` Rebecca Cran
@ 2020-04-24 12:22         ` Laszlo Ersek
  0 siblings, 0 replies; 24+ messages in thread
From: Laszlo Ersek @ 2020-04-24 12:22 UTC (permalink / raw)
  To: Rebecca Cran
  Cc: devel, Jordan Justen, Ard Biesheuvel, Leif Lindholm,
	Michael Kinney, Andrew Fish, Peter Grehan

On 04/24/20 07:54, Rebecca Cran wrote:
> 
>> On Apr 23, 2020, at 3:42 AM, Laszlo Ersek <lersek@redhat.com> wrote:
>>
>> BUt, I *think* the language seen in "OvmfPkg/License.txt" should
>> accommodate that too. It goes:
>>
>>  Some files are subject to the following license, the [...] license.
>>  Those files are located in:
>>  - [directory]
>>  - [directory]
>>
>> It says "some files", and where they are. It doesn't seem to imply that
>> *all* files under those directories are covered by the non-default license.
>>
>> So please just list all those module directories in this (non-default)
>> part of "BhyvePkg/License.txt" that have *at least one* file covered by
>> "BSD-2-Clause".
> 
> 
> Would it also be ok to use the following language?
> 
> Some files are subject to the following license, the BSD-2-Clause license.
> Those files are located in:
> 
> AcpiPlatformDxe/Bhyve.c
> PlatformPei/MemDetect.c
> PlatformPei/Platform.c

probably "located *at*" (not "in"), if we are listing the files
themselves. And yes, this is entirely OK, as long as you can collect
those files individually!

> I think I’ve fixed the rest of the changes you’ve requested. I’m ready to send the v4 series once I get clarification about whether I should add my own copyright line to files I’ve copied from OvmfPkg and made no changes to, or only deletions or other very minor changes.

I've attempted to answer that under your other email.

Thanks!
Laszlo


^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [edk2-devel] [PATCH v3 4/6] Add BhyvePkg, to support the bhyve hypervisor
  2020-04-24 10:11       ` Laszlo Ersek
@ 2020-04-24 16:00         ` Rebecca Cran
  0 siblings, 0 replies; 24+ messages in thread
From: Rebecca Cran @ 2020-04-24 16:00 UTC (permalink / raw)
  To: devel, Laszlo Ersek
  Cc: Jordan Justen, Ard Biesheuvel, Leif Lindholm, Michael Kinney,
	Andrew Fish, Peter Grehan


> On Apr 24, 2020, at 4:11 AM, Laszlo Ersek <lersek@redhat.com> wrote:
> 
> So, if you are *completely* sure you didn't change anything on those
> copies, relative to their fork-off point originals, then I guess it's OK
> to not add your (C).

Okay. There are some that are really simple, since I did re-sync them:

bcran@photon:~/src/uefi/edk2$ diff -U3 BhyvePkg/FvmainCompactScratchEnd.fdf.inc OvmfPkg/FvmainCompactScratchEnd.fdf.inc 
bcran@photon:~/src/uefi/edk2$ 
bcran@photon:~/src/uefi/edk2$ diff -U3 BhyvePkg/VarStore.fdf.inc OvmfPkg/VarStore.fdf.inc 
bcran@photon:~/src/uefi/edk2$ 
bcran@photon:~/src/uefi/edk2$ diff -U3 BhyvePkg/PlatformPei/AmdSev.c OvmfPkg/PlatformPei/AmdSev.c 
bcran@photon:~/src/uefi/edk2$
bcran@photon:~/src/uefi/edk2$ diff -U3 BhyvePkg/PlatformPei/ClearCache.c OvmfPkg/PlatformPei/ClearCache.c 
bcran@photon:~/src/uefi/edk2$ 
…

— 
Rebecca Cran

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2020-04-24 16:00 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH v3 5/6] BhyvePkg: Add PlatformPei Rebecca Cran
2020-04-23  9:24   ` [edk2-devel] " 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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox