summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/Bhyve/BhyveRfbDxe
diff options
context:
space:
mode:
authorRebecca Cran <rebecca@bsdio.com>2020-07-12 23:41:31 -0600
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2020-07-31 13:03:10 +0000
commit656419f922c047a3c48bd3f4ecea7d8e87d0b761 (patch)
tree28fea8684780003f1434ff1b494efad1ece7a1d0 /OvmfPkg/Bhyve/BhyveRfbDxe
parent137c2c6eff67f4750d77e8e40af6683c412d3ed0 (diff)
downloadedk2-656419f922c047a3c48bd3f4ecea7d8e87d0b761.tar.gz
edk2-656419f922c047a3c48bd3f4ecea7d8e87d0b761.tar.bz2
edk2-656419f922c047a3c48bd3f4ecea7d8e87d0b761.zip
Add BhyvePkg, to support the bhyve hypervisor
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> Message-Id: <20200713054131.479627-2-rebecca@bsdio.com> Acked-by: Laszlo Ersek <lersek@redhat.com>
Diffstat (limited to 'OvmfPkg/Bhyve/BhyveRfbDxe')
-rw-r--r--OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf68
-rw-r--r--OvmfPkg/Bhyve/BhyveRfbDxe/ComponentName.c201
-rw-r--r--OvmfPkg/Bhyve/BhyveRfbDxe/Gop.h149
-rw-r--r--OvmfPkg/Bhyve/BhyveRfbDxe/GopDriver.c543
-rw-r--r--OvmfPkg/Bhyve/BhyveRfbDxe/GopScreen.c393
-rw-r--r--OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.asm342
-rw-r--r--OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.c259
-rw-r--r--OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.h912
-rw-r--r--OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.sh80
9 files changed, 2947 insertions, 0 deletions
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