* [PATCH 1/1] Add BhyvePkg, to support the bhyve hypervisor
2020-07-13 5:41 [PATCH 0/1] Add BhyvePkg, to support the bhyve hypervisor Rebecca Cran
@ 2020-07-13 5:41 ` Rebecca Cran
2020-07-13 16:16 ` [edk2-devel] " Laszlo Ersek
2020-07-13 16:55 ` Laszlo Ersek
2020-07-13 5:43 ` [PATCH 0/1] " Liming Gao
1 sibling, 2 replies; 17+ messages in thread
From: Rebecca Cran @ 2020-07-13 5:41 UTC (permalink / raw)
To: devel
Cc: Ard Biesheuvel, Andrew Fish, Leif Lindholm, Jordan L Justen,
Michael D Kinney, Laszlo Ersek, Liming Gao, 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>
---
OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c | 251 +++
OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h | 77 +
.../Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf | 65 +
OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c | 132 ++
OvmfPkg/Bhyve/AcpiPlatformDxe/EntryPoint.c | 90 +
OvmfPkg/Bhyve/AcpiPlatformDxe/PciDecoding.c | 192 ++
OvmfPkg/Bhyve/AcpiTables/AcpiTables.inf | 39 +
OvmfPkg/Bhyve/AcpiTables/Dsdt.asl | 1140 +++++++++++
OvmfPkg/Bhyve/AcpiTables/Facp.aslc | 76 +
OvmfPkg/Bhyve/AcpiTables/Facs.aslc | 80 +
OvmfPkg/Bhyve/AcpiTables/Hpet.aslc | 72 +
OvmfPkg/Bhyve/AcpiTables/Madt.aslc | 145 ++
OvmfPkg/Bhyve/AcpiTables/Mcfg.aslc | 57 +
OvmfPkg/Bhyve/AcpiTables/Platform.h | 72 +
OvmfPkg/Bhyve/AcpiTables/Spcr.aslc | 63 +
OvmfPkg/Bhyve/AcpiTables/Ssdt.asl | 15 +
OvmfPkg/Bhyve/BhyvePkg.dec | 171 ++
OvmfPkg/Bhyve/BhyvePkgDefines.fdf.inc | 85 +
OvmfPkg/Bhyve/BhyvePkgX64.dsc | 847 +++++++++
OvmfPkg/Bhyve/BhyvePkgX64.fdf | 490 +++++
OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf | 68 +
OvmfPkg/Bhyve/BhyveRfbDxe/ComponentName.c | 201 ++
OvmfPkg/Bhyve/BhyveRfbDxe/Gop.h | 149 ++
OvmfPkg/Bhyve/BhyveRfbDxe/GopDriver.c | 543 ++++++
OvmfPkg/Bhyve/BhyveRfbDxe/GopScreen.c | 393 ++++
OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.asm | 342 ++++
OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.c | 259 +++
OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.h | 912 +++++++++
OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.sh | 80 +
OvmfPkg/Bhyve/FvmainCompactScratchEnd.fdf.inc | 65 +
OvmfPkg/Bhyve/Include/Library/BhyveFwCtlLib.h | 47 +
.../Library/BhyveFwCtlLib/BhyveFwCtlLib.c | 426 +++++
.../Library/BhyveFwCtlLib/BhyveFwCtlLib.inf | 41 +
.../PlatformBootManagerLib/BdsPlatform.c | 1660 +++++++++++++++++
.../PlatformBootManagerLib/BdsPlatform.h | 190 ++
.../PlatformBootManagerLib.inf | 75 +
.../PlatformBootManagerLib/PlatformData.c | 171 ++
OvmfPkg/Bhyve/License.txt | 68 +
OvmfPkg/Bhyve/PlatformPei/AmdSev.c | 106 ++
OvmfPkg/Bhyve/PlatformPei/ClearCache.c | 111 ++
OvmfPkg/Bhyve/PlatformPei/Cmos.c | 58 +
OvmfPkg/Bhyve/PlatformPei/Cmos.h | 50 +
OvmfPkg/Bhyve/PlatformPei/FeatureControl.c | 21 +
OvmfPkg/Bhyve/PlatformPei/Fv.c | 94 +
OvmfPkg/Bhyve/PlatformPei/MemDetect.c | 627 +++++++
OvmfPkg/Bhyve/PlatformPei/Platform.c | 607 ++++++
OvmfPkg/Bhyve/PlatformPei/Platform.h | 137 ++
OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf | 113 ++
OvmfPkg/Bhyve/SmbiosPlatformDxe/Bhyve.c | 43 +
.../SmbiosPlatformDxe/SmbiosPlatformDxe.c | 245 +++
.../SmbiosPlatformDxe/SmbiosPlatformDxe.h | 52 +
.../SmbiosPlatformDxe/SmbiosPlatformDxe.inf | 55 +
OvmfPkg/Bhyve/VarStore.fdf.inc | 115 ++
53 files changed, 12283 insertions(+)
create mode 100644 OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
create mode 100644 OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
create mode 100644 OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
create mode 100644 OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
create mode 100644 OvmfPkg/Bhyve/AcpiPlatformDxe/EntryPoint.c
create mode 100644 OvmfPkg/Bhyve/AcpiPlatformDxe/PciDecoding.c
create mode 100644 OvmfPkg/Bhyve/AcpiTables/AcpiTables.inf
create mode 100644 OvmfPkg/Bhyve/AcpiTables/Dsdt.asl
create mode 100644 OvmfPkg/Bhyve/AcpiTables/Facp.aslc
create mode 100644 OvmfPkg/Bhyve/AcpiTables/Facs.aslc
create mode 100644 OvmfPkg/Bhyve/AcpiTables/Hpet.aslc
create mode 100644 OvmfPkg/Bhyve/AcpiTables/Madt.aslc
create mode 100644 OvmfPkg/Bhyve/AcpiTables/Mcfg.aslc
create mode 100644 OvmfPkg/Bhyve/AcpiTables/Platform.h
create mode 100644 OvmfPkg/Bhyve/AcpiTables/Spcr.aslc
create mode 100644 OvmfPkg/Bhyve/AcpiTables/Ssdt.asl
create mode 100644 OvmfPkg/Bhyve/BhyvePkg.dec
create mode 100644 OvmfPkg/Bhyve/BhyvePkgDefines.fdf.inc
create mode 100644 OvmfPkg/Bhyve/BhyvePkgX64.dsc
create mode 100644 OvmfPkg/Bhyve/BhyvePkgX64.fdf
create mode 100644 OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf
create mode 100644 OvmfPkg/Bhyve/BhyveRfbDxe/ComponentName.c
create mode 100644 OvmfPkg/Bhyve/BhyveRfbDxe/Gop.h
create mode 100644 OvmfPkg/Bhyve/BhyveRfbDxe/GopDriver.c
create mode 100644 OvmfPkg/Bhyve/BhyveRfbDxe/GopScreen.c
create mode 100644 OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.asm
create mode 100644 OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.c
create mode 100644 OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.h
create mode 100644 OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.sh
create mode 100644 OvmfPkg/Bhyve/FvmainCompactScratchEnd.fdf.inc
create mode 100644 OvmfPkg/Bhyve/Include/Library/BhyveFwCtlLib.h
create mode 100644 OvmfPkg/Bhyve/Library/BhyveFwCtlLib/BhyveFwCtlLib.c
create mode 100644 OvmfPkg/Bhyve/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
create mode 100644 OvmfPkg/Bhyve/Library/PlatformBootManagerLib/BdsPlatform.c
create mode 100644 OvmfPkg/Bhyve/Library/PlatformBootManagerLib/BdsPlatform.h
create mode 100644 OvmfPkg/Bhyve/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
create mode 100644 OvmfPkg/Bhyve/Library/PlatformBootManagerLib/PlatformData.c
create mode 100644 OvmfPkg/Bhyve/License.txt
create mode 100644 OvmfPkg/Bhyve/PlatformPei/AmdSev.c
create mode 100644 OvmfPkg/Bhyve/PlatformPei/ClearCache.c
create mode 100644 OvmfPkg/Bhyve/PlatformPei/Cmos.c
create mode 100644 OvmfPkg/Bhyve/PlatformPei/Cmos.h
create mode 100644 OvmfPkg/Bhyve/PlatformPei/FeatureControl.c
create mode 100644 OvmfPkg/Bhyve/PlatformPei/Fv.c
create mode 100644 OvmfPkg/Bhyve/PlatformPei/MemDetect.c
create mode 100644 OvmfPkg/Bhyve/PlatformPei/Platform.c
create mode 100644 OvmfPkg/Bhyve/PlatformPei/Platform.h
create mode 100644 OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf
create mode 100644 OvmfPkg/Bhyve/SmbiosPlatformDxe/Bhyve.c
create mode 100644 OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.c
create mode 100644 OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.h
create mode 100644 OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
create mode 100644 OvmfPkg/Bhyve/VarStore.fdf.inc
diff --git a/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
new file mode 100644
index 0000000000..31bbf6c474
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
@@ -0,0 +1,251 @@
+/** @file
+ OVMF ACPI Platform Driver
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ 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/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
new file mode 100644
index 0000000000..d30cd11a1d
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
@@ -0,0 +1,77 @@
+/** @file
+ Sample ACPI Platform Driver
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ 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/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
new file mode 100644
index 0000000000..bf0f4877f0
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -0,0 +1,65 @@
+## @file
+# OVMF ACPI Platform Driver
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[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
+ OvmfPkg/Bhyve/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/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c b/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
new file mode 100644
index 0000000000..6d42264b65
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+ * Copyright (C) 2012, Red Hat, Inc.
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+#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/OvmfPkg/Bhyve/AcpiPlatformDxe/EntryPoint.c b/OvmfPkg/Bhyve/AcpiPlatformDxe/EntryPoint.c
new file mode 100644
index 0000000000..f66f892911
--- /dev/null
+++ b/OvmfPkg/Bhyve/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/OvmfPkg/Bhyve/AcpiPlatformDxe/PciDecoding.c b/OvmfPkg/Bhyve/AcpiPlatformDxe/PciDecoding.c
new file mode 100644
index 0000000000..73894106c9
--- /dev/null
+++ b/OvmfPkg/Bhyve/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);
+}
diff --git a/OvmfPkg/Bhyve/AcpiTables/AcpiTables.inf b/OvmfPkg/Bhyve/AcpiTables/AcpiTables.inf
new file mode 100644
index 0000000000..18a9e2aa78
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiTables/AcpiTables.inf
@@ -0,0 +1,39 @@
+## @file
+# Component description file for PlatformAcpiTables module.
+#
+# ACPI table data and ASL sources required to boot the platform.
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014, Pluribus Networks, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[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
+
diff --git a/OvmfPkg/Bhyve/AcpiTables/Dsdt.asl b/OvmfPkg/Bhyve/AcpiTables/Dsdt.asl
new file mode 100644
index 0000000000..17e2cf69e6
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiTables/Dsdt.asl
@@ -0,0 +1,1140 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+/*
+ * 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/OvmfPkg/Bhyve/AcpiTables/Facp.aslc b/OvmfPkg/Bhyve/AcpiTables/Facp.aslc
new file mode 100644
index 0000000000..b3d703eb89
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiTables/Facp.aslc
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+#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/OvmfPkg/Bhyve/AcpiTables/Facs.aslc b/OvmfPkg/Bhyve/AcpiTables/Facs.aslc
new file mode 100644
index 0000000000..05b6410dd5
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiTables/Facs.aslc
@@ -0,0 +1,80 @@
+/** @file
+ FACS Table
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/OvmfPkg/Bhyve/AcpiTables/Hpet.aslc b/OvmfPkg/Bhyve/AcpiTables/Hpet.aslc
new file mode 100644
index 0000000000..73bb784e43
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiTables/Hpet.aslc
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+#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/OvmfPkg/Bhyve/AcpiTables/Madt.aslc b/OvmfPkg/Bhyve/AcpiTables/Madt.aslc
new file mode 100644
index 0000000000..e8e956ed80
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiTables/Madt.aslc
@@ -0,0 +1,145 @@
+/** @file
+ MADT Table
+
+ This file contains a structure definition for the ACPI 1.0 Multiple APIC
+ Description Table (MADT).
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2014, Pluribus Networks, Inc.
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/OvmfPkg/Bhyve/AcpiTables/Mcfg.aslc b/OvmfPkg/Bhyve/AcpiTables/Mcfg.aslc
new file mode 100644
index 0000000000..62a98d30da
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiTables/Mcfg.aslc
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2015, Nahanni Systems, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+#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/OvmfPkg/Bhyve/AcpiTables/Platform.h b/OvmfPkg/Bhyve/AcpiTables/Platform.h
new file mode 100644
index 0000000000..fc43ab4114
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiTables/Platform.h
@@ -0,0 +1,72 @@
+/** @file
+ Platform specific defines for constructing ACPI tables
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2014, Pluribus Networks, Inc.
+ Copyright (c) 2012, 2013, Red Hat, Inc.
+ Copyright (c) 2008, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/OvmfPkg/Bhyve/AcpiTables/Spcr.aslc b/OvmfPkg/Bhyve/AcpiTables/Spcr.aslc
new file mode 100644
index 0000000000..ec5114ad15
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiTables/Spcr.aslc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2015, Nahanni Systems, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+#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/OvmfPkg/Bhyve/AcpiTables/Ssdt.asl b/OvmfPkg/Bhyve/AcpiTables/Ssdt.asl
new file mode 100644
index 0000000000..175ab3b7e6
--- /dev/null
+++ b/OvmfPkg/Bhyve/AcpiTables/Ssdt.asl
@@ -0,0 +1,15 @@
+/** @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) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (C) 2012 Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+DefinitionBlock ("Ssdt.aml", "SSDT", 1, "REDHAT", "OVMF ", 1) {
+}
diff --git a/OvmfPkg/Bhyve/BhyvePkg.dec b/OvmfPkg/Bhyve/BhyvePkg.dec
new file mode 100644
index 0000000000..8884b6276c
--- /dev/null
+++ b/OvmfPkg/Bhyve/BhyvePkg.dec
@@ -0,0 +1,171 @@
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014, Pluribus Networks, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = BhyvePkg
+ PACKAGE_GUID = 178345e1-6ac0-439d-a3df-9abf70dccd57
+ PACKAGE_VERSION = 0.1
+
+[Includes]
+ Include
+ ../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/OvmfPkg/Bhyve/BhyvePkgDefines.fdf.inc b/OvmfPkg/Bhyve/BhyvePkgDefines.fdf.inc
new file mode 100644
index 0000000000..66e0e4d270
--- /dev/null
+++ b/OvmfPkg/Bhyve/BhyvePkgDefines.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-Patent
+#
+##
+
+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/OvmfPkg/Bhyve/BhyvePkgX64.dsc b/OvmfPkg/Bhyve/BhyvePkgX64.dsc
new file mode 100644
index 0000000000..8eba48d109
--- /dev/null
+++ b/OvmfPkg/Bhyve/BhyvePkgX64.dsc
@@ -0,0 +1,847 @@
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# 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-Patent
+#
+##
+
+################################################################################
+#
+# 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 = OvmfPkg/Bhyve/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|OvmfPkg/Bhyve/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/BaseResetSystemLibBhyve.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|OvmfPkg/Bhyve/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|OvmfPkg/Bhyve/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.PcdDxeIplSupportUefiDecompress|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE
+
+[PcdsFixedAtBuild]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
+ 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
+
+ OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf
+ UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf {
+ <LibraryClasses>
+ }
+
+!if $(TPM_ENABLE) == TRUE
+ OvmfPkg/Bhyve/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|OvmfPkg/Bhyve/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
+
+ OvmfPkg/Bhyve/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
+ OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+
+ #
+ # ACPI Support
+ #
+ MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+ OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
+ OvmfPkg/Bhyve/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|OvmfPkg/Bhyve/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)
+ OvmfPkg/Bhyve/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/OvmfPkg/Bhyve/BhyvePkgX64.fdf b/OvmfPkg/Bhyve/BhyvePkgX64.fdf
new file mode 100644
index 0000000000..e2852aa5e1
--- /dev/null
+++ b/OvmfPkg/Bhyve/BhyvePkgX64.fdf
@@ -0,0 +1,490 @@
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# 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-Patent
+#
+##
+
+################################################################################
+
+[Defines]
+!include OvmfPkg/Bhyve/BhyvePkgDefines.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 OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf
+INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+INF UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+!if $(SMM_REQUIRE) == TRUE
+INF OvmfPkg/Bhyve/SmmAccess/SmmAccessPei.inf
+!endif
+
+!if $(TPM_ENABLE) == TRUE
+INF OvmfPkg/Bhyve/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 OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+
+INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+INF OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
+INF RuleOverride=ACPITABLE OvmfPkg/Bhyve/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
+!include NetworkPkg/Network.fdf.inc
+ 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 OvmfPkg/Bhyve/Csm/BhyveCsm16/BhyveCsm16.inf
+!endif
+
+INF OvmfPkg/PlatformDxe/Platform.inf
+INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+INF OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf
+
+!if $(SMM_REQUIRE) == TRUE
+INF OvmfPkg/Bhyve/SmmAccess/SmmAccess2Dxe.inf
+INF OvmfPkg/Bhyve/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
+
+#
+# TPM support
+#
+!if $(TPM_ENABLE) == TRUE
+INF SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
+!if $(TPM_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 FvmainCompactScratchEnd.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/OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf b/OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf
new file mode 100644
index 0000000000..8fd72cb78d
--- /dev/null
+++ b/OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf
@@ -0,0 +1,68 @@
+## @file
+# GOP driver
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# 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-Patent
+#
+##
+
+[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
+ OvmfPkg/Bhyve/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/OvmfPkg/Bhyve/BhyveRfbDxe/ComponentName.c b/OvmfPkg/Bhyve/BhyveRfbDxe/ComponentName.c
new file mode 100644
index 0000000000..673cd235a1
--- /dev/null
+++ b/OvmfPkg/Bhyve/BhyveRfbDxe/ComponentName.c
@@ -0,0 +1,201 @@
+/** @file
+
+Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+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-Patent
+
+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/OvmfPkg/Bhyve/BhyveRfbDxe/Gop.h b/OvmfPkg/Bhyve/BhyveRfbDxe/Gop.h
new file mode 100644
index 0000000000..d196a8e6cf
--- /dev/null
+++ b/OvmfPkg/Bhyve/BhyveRfbDxe/Gop.h
@@ -0,0 +1,149 @@
+/*++ @file
+
+Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+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-Patent
+
+**/
+
+#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/OvmfPkg/Bhyve/BhyveRfbDxe/GopDriver.c b/OvmfPkg/Bhyve/BhyveRfbDxe/GopDriver.c
new file mode 100644
index 0000000000..bab4fbda53
--- /dev/null
+++ b/OvmfPkg/Bhyve/BhyveRfbDxe/GopDriver.c
@@ -0,0 +1,543 @@
+/*++ @file
+
+Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+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-Patent
+
+**/
+
+#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/OvmfPkg/Bhyve/BhyveRfbDxe/GopScreen.c b/OvmfPkg/Bhyve/BhyveRfbDxe/GopScreen.c
new file mode 100644
index 0000000000..0760ffb722
--- /dev/null
+++ b/OvmfPkg/Bhyve/BhyveRfbDxe/GopScreen.c
@@ -0,0 +1,393 @@
+/*++ @file
+
+Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+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-Patent
+
+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/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.asm b/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.asm
new file mode 100644
index 0000000000..f7a1ec297f
--- /dev/null
+++ b/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.asm
@@ -0,0 +1,342 @@
+;------------------------------------------------------------------------------
+; @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) 2020, Rebecca Cran <rebecca@bsdio.com>
+; 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-Patent
+;
+;------------------------------------------------------------------------------
+
+; 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/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.c b/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.c
new file mode 100644
index 0000000000..740b966794
--- /dev/null
+++ b/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.c
@@ -0,0 +1,259 @@
+/** @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) 2020, Rebecca Cran <rebecca@bsdio.com>
+ 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-Patent
+
+**/
+
+#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/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.h b/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.h
new file mode 100644
index 0000000000..72b8a3f25f
--- /dev/null
+++ b/OvmfPkg/Bhyve/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/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.sh b/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.sh
new file mode 100644
index 0000000000..358b568338
--- /dev/null
+++ b/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+###
+# @file
+# Shell script to assemble and dump the fake Int10h handler from NASM source to
+# a C array.
+#
+# Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+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/OvmfPkg/Bhyve/FvmainCompactScratchEnd.fdf.inc b/OvmfPkg/Bhyve/FvmainCompactScratchEnd.fdf.inc
new file mode 100644
index 0000000000..46f5258329
--- /dev/null
+++ b/OvmfPkg/Bhyve/FvmainCompactScratchEnd.fdf.inc
@@ -0,0 +1,65 @@
+## @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-Patent
+##
+
+# 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/OvmfPkg/Bhyve/Include/Library/BhyveFwCtlLib.h b/OvmfPkg/Bhyve/Include/Library/BhyveFwCtlLib.h
new file mode 100644
index 0000000000..13028ec4b5
--- /dev/null
+++ b/OvmfPkg/Bhyve/Include/Library/BhyveFwCtlLib.h
@@ -0,0 +1,47 @@
+/** @file
+ bhyve firmware configuration access
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2015 Nahanni Systems
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/OvmfPkg/Bhyve/Library/BhyveFwCtlLib/BhyveFwCtlLib.c b/OvmfPkg/Bhyve/Library/BhyveFwCtlLib/BhyveFwCtlLib.c
new file mode 100644
index 0000000000..2c45ad70ca
--- /dev/null
+++ b/OvmfPkg/Bhyve/Library/BhyveFwCtlLib/BhyveFwCtlLib.c
@@ -0,0 +1,426 @@
+/** @file
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ 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-Patent
+
+**/
+
+#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];
+ UINT32 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/OvmfPkg/Bhyve/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf b/OvmfPkg/Bhyve/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
new file mode 100644
index 0000000000..e9819f4f96
--- /dev/null
+++ b/OvmfPkg/Bhyve/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
@@ -0,0 +1,41 @@
+## @file
+#
+# Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (C) 2015 Nahanni Systems
+# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[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
+ OvmfPkg/Bhyve/BhyvePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ IoLib
+ MemoryAllocationLib
+ IntrinsicLib
+
diff --git a/OvmfPkg/Bhyve/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Bhyve/Library/PlatformBootManagerLib/BdsPlatform.c
new file mode 100644
index 0000000000..3b94630ac7
--- /dev/null
+++ b/OvmfPkg/Bhyve/Library/PlatformBootManagerLib/BdsPlatform.c
@@ -0,0 +1,1660 @@
+/** @file
+ Platform BDS customizations.
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/OvmfPkg/Bhyve/Library/PlatformBootManagerLib/BdsPlatform.h b/OvmfPkg/Bhyve/Library/PlatformBootManagerLib/BdsPlatform.h
new file mode 100644
index 0000000000..382fe191a9
--- /dev/null
+++ b/OvmfPkg/Bhyve/Library/PlatformBootManagerLib/BdsPlatform.h
@@ -0,0 +1,190 @@
+/** @file
+ Platform BDS customizations include file.
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+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/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/OvmfPkg/Bhyve/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/OvmfPkg/Bhyve/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
new file mode 100644
index 0000000000..105123b5e2
--- /dev/null
+++ b/OvmfPkg/Bhyve/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
@@ -0,0 +1,75 @@
+## @file
+# Platform BDS customizations library.
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[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/OvmfPkg/Bhyve/Library/PlatformBootManagerLib/PlatformData.c b/OvmfPkg/Bhyve/Library/PlatformBootManagerLib/PlatformData.c
new file mode 100644
index 0000000000..73674d536d
--- /dev/null
+++ b/OvmfPkg/Bhyve/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) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/OvmfPkg/Bhyve/License.txt b/OvmfPkg/Bhyve/License.txt
new file mode 100644
index 0000000000..2930e5372a
--- /dev/null
+++ b/OvmfPkg/Bhyve/License.txt
@@ -0,0 +1,68 @@
+Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (C) 2018, Red Hat, Inc.
+Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
+Copyright (C) 2016, Red Hat, Inc.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+Copyright (c) 2015 Nahanni Systems
+Copyright (C) 2015, Red Hat, Inc.
+Copyright (C) 2014, Red Hat, Inc.
+Copyright (c) 2014, Pluribus Networks, Inc.
+Copyright (C) 2013, Red Hat, Inc.
+Copyright (c) 2012, 2013, Red Hat, Inc.
+Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
+Portions copyright (c) 2011, Apple Inc. All rights reserved.
+Portions copyright (c) 2010,Apple Inc. All rights reserved.<BR>
+
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+2. 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.
+
+Subject to the terms and conditions of this license, each copyright holder
+and contributor hereby grants to those receiving rights under this license
+a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+(except for failure to satisfy the conditions of this license) patent
+license to make, have made, use, offer to sell, sell, import, and otherwise
+transfer this software, where such license applies only to those patent
+claims, already acquired or hereafter acquired, licensable by such copyright
+holder or contributor that are necessarily infringed by:
+
+(a) their Contribution(s) (the licensed copyrights of copyright holders and
+ non-copyrightable additions of contributors, in source or binary form)
+ alone; or
+
+(b) combination of their Contribution(s) with the work of authorship to
+ which such Contribution(s) was added by such copyright holder or
+ contributor, if, at the time the Contribution is added, such addition
+ causes such combination to be necessarily infringed. The patent license
+ shall not apply to any other combinations which include the
+ Contribution.
+
+Except as expressly stated above, no rights or licenses from any copyright
+holder or contributor is granted under this license, whether expressly, by
+implication, estoppel or otherwise.
+
+DISCLAIMER
+
+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 HOLDERS 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.
+
diff --git a/OvmfPkg/Bhyve/PlatformPei/AmdSev.c b/OvmfPkg/Bhyve/PlatformPei/AmdSev.c
new file mode 100644
index 0000000000..e484f4b311
--- /dev/null
+++ b/OvmfPkg/Bhyve/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/OvmfPkg/Bhyve/PlatformPei/ClearCache.c b/OvmfPkg/Bhyve/PlatformPei/ClearCache.c
new file mode 100644
index 0000000000..5c538c59e0
--- /dev/null
+++ b/OvmfPkg/Bhyve/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/OvmfPkg/Bhyve/PlatformPei/Cmos.c b/OvmfPkg/Bhyve/PlatformPei/Cmos.c
new file mode 100644
index 0000000000..9b34e10b17
--- /dev/null
+++ b/OvmfPkg/Bhyve/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/OvmfPkg/Bhyve/PlatformPei/Cmos.h b/OvmfPkg/Bhyve/PlatformPei/Cmos.h
new file mode 100644
index 0000000000..3cd98799a3
--- /dev/null
+++ b/OvmfPkg/Bhyve/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/OvmfPkg/Bhyve/PlatformPei/FeatureControl.c b/OvmfPkg/Bhyve/PlatformPei/FeatureControl.c
new file mode 100644
index 0000000000..40d9ebdbe6
--- /dev/null
+++ b/OvmfPkg/Bhyve/PlatformPei/FeatureControl.c
@@ -0,0 +1,21 @@
+/**@file
+ Install a callback when necessary for setting the Feature Control MSR on all
+ processors.
+
+ Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+ 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/OvmfPkg/Bhyve/PlatformPei/Fv.c b/OvmfPkg/Bhyve/PlatformPei/Fv.c
new file mode 100644
index 0000000000..ee4ecab615
--- /dev/null
+++ b/OvmfPkg/Bhyve/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/OvmfPkg/Bhyve/PlatformPei/MemDetect.c b/OvmfPkg/Bhyve/PlatformPei/MemDetect.c
new file mode 100644
index 0000000000..1b556be69c
--- /dev/null
+++ b/OvmfPkg/Bhyve/PlatformPei/MemDetect.c
@@ -0,0 +1,627 @@
+/**@file
+ Memory Detection for Virtual Machines.
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+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/OvmfPkg/Bhyve/PlatformPei/Platform.c b/OvmfPkg/Bhyve/PlatformPei/Platform.c
new file mode 100644
index 0000000000..11658d478c
--- /dev/null
+++ b/OvmfPkg/Bhyve/PlatformPei/Platform.c
@@ -0,0 +1,607 @@
+/**@file
+ Platform PEI driver
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// 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/OvmfPkg/Bhyve/PlatformPei/Platform.h b/OvmfPkg/Bhyve/PlatformPei/Platform.h
new file mode 100644
index 0000000000..8239ca05ac
--- /dev/null
+++ b/OvmfPkg/Bhyve/PlatformPei/Platform.h
@@ -0,0 +1,137 @@
+/** @file
+ Platform PEI module include file.
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ 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/OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf b/OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf
new file mode 100644
index 0000000000..7288cff4c8
--- /dev/null
+++ b/OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf
@@ -0,0 +1,113 @@
+## @file
+# Platform PEI driver
+#
+# This module provides platform specific function to detect boot mode.
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[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
+
diff --git a/OvmfPkg/Bhyve/SmbiosPlatformDxe/Bhyve.c b/OvmfPkg/Bhyve/SmbiosPlatformDxe/Bhyve.c
new file mode 100644
index 0000000000..6ca976daa6
--- /dev/null
+++ b/OvmfPkg/Bhyve/SmbiosPlatformDxe/Bhyve.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+#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/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.c b/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.c
new file mode 100644
index 0000000000..59f5d77a3b
--- /dev/null
+++ b/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.c
@@ -0,0 +1,245 @@
+/** @file
+ This driver installs SMBIOS information for OVMF
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+ Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.h b/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.h
new file mode 100644
index 0000000000..1971827be4
--- /dev/null
+++ b/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.h
@@ -0,0 +1,52 @@
+/** @file
+ This driver installs SMBIOS information for OVMF
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+ Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+ );
+
+
+/**
+ 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/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.inf b/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
new file mode 100644
index 0000000000..a4cc6e7a56
--- /dev/null
+++ b/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
@@ -0,0 +1,55 @@
+## @file
+# This driver installs SMBIOS information for bhyve
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[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/OvmfPkg/Bhyve/VarStore.fdf.inc b/OvmfPkg/Bhyve/VarStore.fdf.inc
new file mode 100644
index 0000000000..a1e524e393
--- /dev/null
+++ b/OvmfPkg/Bhyve/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-Patent
+#
+##
+
+!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
--
2.25.1
^ permalink raw reply related [flat|nested] 17+ messages in thread