diff --git BaseTools/Conf/tools_def.template BaseTools/Conf/tools_def.template
index f008024..3fb1216 100644
--- BaseTools/Conf/tools_def.template
+++ BaseTools/Conf/tools_def.template
@@ -307,6 +307,10 @@ DEFINE SOURCERY_CYGWIN_TOOLS = /cygdrive/c/Program Files/CodeSourcery/Sourcery G
# Required to build platforms or ACPI tables:
# Intel(r) ACPI Compiler v20101013 from
# http://www.acpica.org/downloads/previous_releases.php
+# FBSDGCC -FreeBSD- Requires:
+# GCC 4.8
+# Intel(r) ACPI Compiler iasl from the base system.
+# TODO: there needs to be a ports version of acpi tools v20101013.
# GCC44 -Linux,Windows- Requires:
# GCC 4.4 targeting x86_64-linux-gnu
# Optional:
@@ -4003,6 +4007,57 @@ DEFINE GCC49_AARCH64_ASLDLINK_FLAGS = DEF(GCC_ARM_AARCH64_ASLDLINK_FLAGS)
*_UNIXGCC_IPF_SYMRENAME_FLAGS = DEF(GCC_IPF_SYMRENAME_FLAGS)
*_UNIXGCC_IPF_RC_FLAGS = DEF(GCC_IPF_RC_FLAGS)
+####################################################################################
+#
+# FreeBSD GCC And Intel Linux ACPI Compiler
+#
+####################################################################################
+# FBSDGCC - FreeBSD GCC, currently gcc 4.8
+# ASL - Intel Linux ACPI Source Language Compiler (iasl)
+*_FBSDGCC_*_*_FAMILY = GCC
+
+*_FBSDGCC_*_MAKE_PATH = /usr/local/bin/gmake
+*_FBSDGCC_*_ASL_PATH = /usr/sbin/iasl
+
+*_FBSDGCC_X64_DLINK_FLAGS = DEF(GCC_IA32_X64_DLINK_FLAGS) --image-base=0
+*_FBSDGCC_X64_ASLDLINK_FLAGS = DEF(GCC_IA32_X64_ASLDLINK_FLAGS)
+*_FBSDGCC_*_ASM_FLAGS = DEF(GCC_ASM_FLAGS)
+*_FBSDGCC_*_PP_FLAGS = DEF(GCC_PP_FLAGS)
+*_FBSDGCC_*_ASLPP_FLAGS = DEF(GCC_ASLPP_FLAGS)
+*_FBSDGCC_*_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS)
+*_FBSDGCC_*_VFRPP_FLAGS = DEF(GCC_VFRPP_FLAGS)
+*_FBSDGCC_*_APP_FLAGS =
+*_FBSDGCC_*_ASL_FLAGS = DEF(IASL_FLAGS)
+*_FBSDGCC_*_ASL_OUTFLAGS = DEF(IASL_OUTFLAGS)
+
+##################
+# No FreeBSD IA32 definitions
+##################
+
+##################
+# X64 definitions
+##################
+# Env vars are needed for other locations in the build (e.g. tools)
+*_FBSDGCC_X64_OBJCOPY_PATH = ENV(OBJCOPY)
+*_FBSDGCC_X64_CC_PATH = ENV(CC)
+*_FBSDGCC_X64_SLINK_PATH = ENV(AR)
+*_FBSDGCC_X64_DLINK_PATH = ENV(LD)
+*_FBSDGCC_X64_ASLDLINK_PATH = ENV(LD)
+*_FBSDGCC_X64_ASM_PATH = ENV(CC)
+*_FBSDGCC_X64_PP_PATH = ENV(CC)
+*_FBSDGCC_X64_VFRPP_PATH = ENV(CC)
+*_FBSDGCC_X64_ASLCC_PATH = ENV(CC)
+*_FBSDGCC_X64_ASLPP_PATH = ENV(CC)
+*_FBSDGCC_X64_RC_PATH = ENV(OBJCOPY)
+
+*_FBSDGCC_X64_ASLCC_FLAGS = DEF(GCC_ASLCC_FLAGS) -m64
+*_FBSDGCC_X64_ASLDLINK_FLAGS = DEF(GCC48_IA32_X64_ASLDLINK_FLAGS) -m elf_x86_64
+*_FBSDGCC_X64_ASM_FLAGS = DEF(GCC48_ASM_FLAGS) -m64
+*_FBSDGCC_X64_CC_FLAGS = DEF(GCC48_X64_CC_FLAGS)
+*_FBSDGCC_X64_DLINK_FLAGS = DEF(GCC48_X64_DLINK_FLAGS)
+*_FBSDGCC_X64_RC_FLAGS = DEF(GCC_X64_RC_FLAGS)
+*_FBSDGCC_X64_OBJCOPY_FLAGS =
+
####################################################################################
#
diff --git BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile
index 406725d..dfcf3ee 100644
--- BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile
+++ BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile
@@ -114,7 +114,7 @@ PCCTS_H=../h
#
# UNIX
#
-CC=cc
+CC?=cc
COPT=-O
ANTLR=${BIN_DIR}/antlr
DLG=${BIN_DIR}/dlg
diff --git BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c
new file mode 100644
index 0000000..cabce28
--- /dev/null
+++ BhyvePkg/AcpiPlatformDxe/AcpiPlatform.c
@@ -0,0 +1,260 @@
+/** @file
+ OVMF ACPI Platform Driver
+
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "AcpiPlatform.h"
+
+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 parses them. This function is useful for QEMU and KVM.
+
+ @param AcpiTable Protocol instance pointer
+
+**/
+EFI_STATUS
+EFIAPI
+FindAcpiTablesInFv (
+ 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;
+
+ //
+ // Locate the firmware volume protocol
+ //
+ Status = LocateFvInstanceWithTables (&FwVol);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ //
+ // 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;
+}
+
+/**
+ Entrypoint of Acpi Platform driver.
+
+ @param ImageHandle
+ @param SystemTable
+
+ @return EFI_SUCCESS
+ @return EFI_LOAD_ERROR
+ @return EFI_OUT_OF_RESOURCES
+
+**/
+EFI_STATUS
+EFIAPI
+AcpiPlatformEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+
+ //
+ // Find the AcpiTable protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ NULL,
+ (VOID**)&AcpiTable
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ Status = FindAcpiTablesInFv (AcpiTable);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h
new file mode 100644
index 0000000..b9fe97f
--- /dev/null
+++ BhyvePkg/AcpiPlatformDxe/AcpiPlatform.h
@@ -0,0 +1,51 @@
+/** @file
+ Sample ACPI Platform Driver
+
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _ACPI_PLATFORM_H_INCLUDED_
+#define _ACPI_PLATFORM_H_INCLUDED_
+
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+EFI_STATUS
+EFIAPI
+InstallAcpiTable (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
+ IN VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ );
+
+#ifndef NOT_BHYVE
+EFI_STATUS
+EFIAPI
+BhyveInstallAcpiTable (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
+ IN VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ );
+#endif
+
+#endif
+
diff --git BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
new file mode 100644
index 0000000..1bc012e
--- /dev/null
+++ BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -0,0 +1,65 @@
+## @file
+# OVMF ACPI Platform Driver
+#
+# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiPlatform
+ FILE_GUID = 49970331-E3FA-4637-9ABC-3B7868676970
+ 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 IPF EBC
+#
+
+[Sources]
+ AcpiPlatform.c
+ Bhyve.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ BhyvePkg/BhyvePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ PcAtChipsetPkg/PcAtChipsetPkg.dec
+
+[LibraryClasses]
+ UefiLib
+ DxeServicesLib
+ PcdLib
+ BaseMemoryLib
+ DebugLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ HobLib
+ BhyveFwCtlLib
+ MemoryAllocationLib
+ BaseLib
+ DxeServicesTableLib
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+ gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFdBaseAddress
+
+[Depex]
+ gEfiAcpiTableProtocolGuid
+
diff --git BhyvePkg/AcpiPlatformDxe/Bhyve.c BhyvePkg/AcpiPlatformDxe/Bhyve.c
new file mode 100644
index 0000000..0f15568
--- /dev/null
+++ BhyvePkg/AcpiPlatformDxe/Bhyve.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ * Copyright (C) 2012, Red Hat, Inc.
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+#include "AcpiPlatform.h"
+
+#include
+#include
+#include
+
+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 ((EFI_D_INFO, "Retrieved CpuCount %d\n", CpuCount));
+ ASSERT (CpuCount >= 1);
+ } else {
+ DEBUG ((EFI_D_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 BhyvePkg/BhyveAcpiTables/BhyveAcpiTables.inf BhyvePkg/BhyveAcpiTables/BhyveAcpiTables.inf
new file mode 100644
index 0000000..b3c68e0
--- /dev/null
+++ BhyvePkg/BhyveAcpiTables/BhyveAcpiTables.inf
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2014, Pluribus Networks, Inc.
+#
+# This program and the accompanying materials are licensed and made
+# available under the terms and conditions of the BSD License which
+# accompanies this distribution. The full text of the license may be
+# found at http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+# BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED.
+#
+
+[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 IPF EBC
+#
+
+[Sources]
+ Platform.h
+ Madt.aslc
+ Facp.aslc
+ Facs.aslc
+ Dsdt.asl
+ Hpet.aslc
+ Spcr.aslc
+ Mcfg.aslc
+
+[Packages]
+ MdePkg/MdePkg.dec
diff --git BhyvePkg/BhyveAcpiTables/Dsdt.asl BhyvePkg/BhyveAcpiTables/Dsdt.asl
new file mode 100644
index 0000000..a180b52
--- /dev/null
+++ BhyvePkg/BhyveAcpiTables/Dsdt.asl
@@ -0,0 +1,824 @@
+/*
+ * 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 () { 0x0003FFFF, Zero, LPC.LNKA, Zero },
+ Package () { 0x0004FFFF, Zero, LPC.LNKB, Zero },
+ Package () { 0x0005FFFF, Zero, LPC.LNKC, Zero },
+ Package () { 0x0006FFFF, Zero, LPC.LNKD, Zero }
+ })
+ Name (APRT, Package ()
+ {
+ Package () { 0x0003FFFF, Zero, Zero, 0x10 },
+ Package () { 0x0004FFFF, Zero, Zero, 0x11 },
+ Package () { 0x0005FFFF, Zero, Zero, 0x12 },
+ Package () { 0x0006FFFF, Zero, Zero, 0x13 }
+ })
+ 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 BhyvePkg/BhyveAcpiTables/Facp.aslc BhyvePkg/BhyveAcpiTables/Facp.aslc
new file mode 100644
index 0000000..53552cb
--- /dev/null
+++ BhyvePkg/BhyveAcpiTables/Facp.aslc
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include "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 BhyvePkg/BhyveAcpiTables/Facs.aslc BhyvePkg/BhyveAcpiTables/Facs.aslc
new file mode 100644
index 0000000..6a457fe
--- /dev/null
+++ BhyvePkg/BhyveAcpiTables/Facs.aslc
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+
+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 BhyvePkg/BhyveAcpiTables/Hpet.aslc BhyvePkg/BhyveAcpiTables/Hpet.aslc
new file mode 100644
index 0000000..f9abc44
--- /dev/null
+++ BhyvePkg/BhyveAcpiTables/Hpet.aslc
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+
+#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 BhyvePkg/BhyveAcpiTables/Madt.aslc BhyvePkg/BhyveAcpiTables/Madt.aslc
new file mode 100644
index 0000000..8b66f68
--- /dev/null
+++ BhyvePkg/BhyveAcpiTables/Madt.aslc
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+
+#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 BhyvePkg/BhyveAcpiTables/Mcfg.aslc BhyvePkg/BhyveAcpiTables/Mcfg.aslc
new file mode 100644
index 0000000..fe7a5f7
--- /dev/null
+++ BhyvePkg/BhyveAcpiTables/Mcfg.aslc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, Nahanni Systems, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include "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 BhyvePkg/BhyveAcpiTables/Platform.h BhyvePkg/BhyveAcpiTables/Platform.h
new file mode 100644
index 0000000..0f5d8e3
--- /dev/null
+++ BhyvePkg/BhyveAcpiTables/Platform.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#ifndef _Platform_h_INCLUDED_
+#define _Platform_h_INCLUDED_
+
+#include
+#include
+#include
+
+//
+// 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)
+#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 BhyvePkg/BhyveAcpiTables/Spcr.aslc BhyvePkg/BhyveAcpiTables/Spcr.aslc
new file mode 100644
index 0000000..7225c25
--- /dev/null
+++ BhyvePkg/BhyveAcpiTables/Spcr.aslc
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, Nahanni Systems, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include "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 BhyvePkg/BhyvePkg.dec BhyvePkg/BhyvePkg.dec
new file mode 100644
index 0000000..036ff4c
--- /dev/null
+++ BhyvePkg/BhyvePkg.dec
@@ -0,0 +1,67 @@
+#
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+# Copyright (c) 2014, Pluribus Networks, Inc.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = BhyvePkg
+ PACKAGE_GUID = a68f96c3-6040-11e4-83ce-4437e6b8ac70
+ PACKAGE_VERSION = 0.1
+
+[Includes]
+ Include
+
+[LibraryClasses]
+ ## @libraryclass Save and restore variables using a file
+ #
+ NvVarsFileLib|Include/Library/NvVarsFileLib.h
+
+ ## @libraryclass Serialize (and deserialize) variables
+ #
+ SerializeVariablesLib|Include/Library/SerializeVariablesLib.h
+
+ ## @libraryclass Access bhyve's firmware control interface
+ #
+ BhyveFwCtlLib|Include/Library/BhyveFwCtlLib.h
+
+[Guids]
+ gUefiBhyvePkgTokenSpaceGuid = {0x93bb96af, 0xb9f2, 0x4eb8, {0x94, 0x62, 0xe0, 0xba, 0x74, 0x56, 0x42, 0x36}}
+
+[PcdsFixedAtBuild]
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveMemFvBase|0x0|UINT32|0
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveMemFvSize|0x0|UINT32|1
+
+ ## This flag is used to control the destination port for PlatformDebugLibIoPort
+ #gUefiBhyvePkgTokenSpaceGuid.PcdDebugIoPort|0x220|UINT16|4
+ gUefiBhyvePkgTokenSpaceGuid.PcdDebugIoPort|0x2F8|UINT16|4
+
+ ## This flag determines the Power Management Base Address of choice, written
+ # to PIIX4 function 3 offset 0x40-0x43 bits [15:6].
+ gUefiBhyvePkgTokenSpaceGuid.PcdAcpiPmBaseAddress|0xB000|UINT16|5
+
+[PcdsFixedAtBuild]
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFlashNvStorageEventLogBase|0x0|UINT32|0x8
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFlashNvStorageEventLogSize|0x0|UINT32|0x9
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFirmwareFdSize|0x0|UINT32|0xa
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFirmwareBlockSize|0|UINT32|0xb
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFlashNvStorageVariableBase|0x0|UINT32|0xc
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFlashNvStorageFtwSpareBase|0x0|UINT32|0xd
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFlashNvStorageFtwWorkingBase|0x0|UINT32|0xe
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFdBaseAddress|0x0|UINT32|0xf
+
+[PcdsDynamic, PcdsDynamicEx]
+ gUefiBhyvePkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFlashVariablesEnable|FALSE|BOOLEAN|0x10
+
+[PcdsFeatureFlag]
+ gUefiBhyvePkgTokenSpaceGuid.PcdSecureBootEnable|FALSE|BOOLEAN|3
diff --git BhyvePkg/BhyvePkgX64.dsc BhyvePkg/BhyvePkgX64.dsc
new file mode 100644
index 0000000..a2aa124
--- /dev/null
+++ BhyvePkg/BhyvePkgX64.dsc
@@ -0,0 +1,590 @@
+#
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+# Copyright (c) 2014, Pluribus Networks, Inc.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+################################################################################
+#
+# 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 = DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+ FLASH_DEFINITION = BhyvePkg/BhyvePkgX64.fdf
+
+ #
+ # Defines for default states. These can be changed on the command line.
+ # -D FLAG=VALUE
+ #
+ DEFINE SECURE_BOOT_ENABLE = FALSE
+
+[BuildOptions]
+ GCC:*_UNIXGCC_*_CC_FLAGS = -DMDEPKG_NDEBUG
+ GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
+ INTEL:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
+ MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
+!ifdef $(CSM_ENABLE)
+ GCC:*_*_*_CC_FLAGS = -mno-mmx -mno-sse -DCSM_ENABLE
+!else
+ GCC:*_*_*_CC_FLAGS = -mno-mmx -mno-sse
+!endif
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ MSFT:*_*_X64_GENFW_FLAGS = --keepexceptiontable
+ GCC:*_*_X64_GENFW_FLAGS = --keepexceptiontable
+ INTEL:*_*_X64_GENFW_FLAGS = --keepexceptiontable
+!endif
+
+################################################################################
+#
+# 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|BhyvePkg/Library/AcpiTimerLib/AcpiTimerLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.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
+ GenericBdsLib|IntelFrameworkModulePkg/Library/GenericBdsLib/GenericBdsLib.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
+ PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.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|BhyvePkg/Library/NvVarsFileLib/NvVarsFileLib.inf
+ FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+ SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
+ NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
+ IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf
+ UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
+ DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
+ UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
+ SerializeVariablesLib|BhyvePkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
+ BhyveFwCtlLib|BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
+ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
+ LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
+
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ 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|BhyvePkg/Library/ResetSystemLib/ResetSystemLib.inf
+ LocalApicLib|UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
+ IoApicLib|PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ PlatformSecureLib|BhyvePkg/Library/PlatformSecureLib/PlatformSecureLib.inf
+ IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
+ TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
+!endif
+
+[LibraryClasses.common]
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+!endif
+
+[LibraryClasses.common.SEC]
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|BhyvePkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ 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|BhyvePkg/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|BhyvePkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ PeiResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.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|BhyvePkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+ 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|BhyvePkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+!endif
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+
+[LibraryClasses.common.UEFI_DRIVER]
+ 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|BhyvePkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.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|BhyvePkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
+ IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf
+ UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
+ DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
+ PlatformBdsLib|BhyvePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+
+[LibraryClasses.common.UEFI_APPLICATION]
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|BhyvePkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform.
+#
+################################################################################
+[PcdsFeatureFlag]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ gUefiBhyvePkgTokenSpaceGuid.PcdSecureBootEnable|TRUE
+!endif
+
+[PcdsFixedAtBuild]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1
+ gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxFvSupported|6
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPeiCoreMaxPeimPerFv|32
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
+!else
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x400
+!endif
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x8000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
+
+ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
+!else
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
+!endif
+
+!ifdef $(SOURCE_DEBUG_ENABLE)
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2
+!endif
+
+!ifndef $(USE_OLD_SHELL)
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 }
+!endif
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ # override the default values from SecurityPkg to ensure images from all sources are verified in secure boot
+ gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x04
+ gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy|0x04
+ gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy|0x04
+!endif
+
+ # IRQs 5, 9, 10, 11 are level-triggered
+ gPcAtChipsetPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0E20
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand|FALSE
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|L"BHYVE"
+
+################################################################################
+#
+# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsDynamicDefault]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
+
+ # MdeModulePkg resolution sets up the system display resolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|0
+
+ # Intel framework used by the EFI setup console.
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|0
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|0
+ #gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupConOutColumn|0
+ #gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdSetupConOutRow|0
+
+################################################################################
+#
+# Components Section - list of all EDK II Modules needed by this Platform.
+#
+################################################################################
+[Components]
+ BhyvePkg/ResetVector/ResetVector.inf
+
+ #
+ # SEC Phase modules
+ #
+ BhyvePkg/Sec/SecMain.inf {
+
+ NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ }
+
+ #
+ # PEI Phase modules
+ #
+ MdeModulePkg/Core/Pei/PeiMain.inf
+ MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
+
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf
+ MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+
+ BhyvePkg/PlatformPei/PlatformPei.inf {
+
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ }
+
+ #
+ # DXE Phase modules
+ #
+ MdeModulePkg/Core/Dxe/DxeMain.inf {
+
+ NULL|IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ }
+
+ IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf
+ MdeModulePkg/Universal/PCD/Dxe/Pcd.inf {
+
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+
+ MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf {
+
+ NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
+ }
+!else
+ MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+!endif
+
+ MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+ PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf
+ UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+ UefiCpuPkg/CpuDxe/CpuDxe.inf
+!ifdef $(NOT_BHYVE)
+ PcAtChipsetPkg/8254TimerDxe/8254Timer.inf
+!endif
+ PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf
+ DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
+ DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
+ PcAtChipsetPkg/KbcResetDxe/Reset.inf
+ MdeModulePkg/Universal/Metronome/Metronome.inf {
+
+ TimerLib|BhyvePkg/Library/AcpiTimerLib/AcpiTimerLib.inf
+ }
+
+ PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf {
+
+ TimerLib|BhyvePkg/Library/AcpiTimerLib/AcpiTimerLib.inf
+ }
+
+ IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf {
+
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ TimerLib|BhyvePkg/Library/AcpiTimerLib/AcpiTimerLib.inf
+!ifdef $(CSM_ENABLE)
+ NULL|BhyvePkg/Csm/CsmSupportLib/CsmSupportLib.inf
+!endif
+ }
+
+ OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+ OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+ BhyvePkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
+
+ PlatformFvbLib|BhyvePkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf
+ }
+ MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.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 {
+
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+ MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf {
+
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+ MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf {
+
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+ MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf {
+
+ 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/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+!ifdef $(NOT_BHYVE)
+ IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf
+ PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf
+!endif
+ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+ MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+
+ #
+ # ISA Support
+ #
+ PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf
+ IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
+ IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf
+ IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
+ IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf
+
+ #
+ # SMBIOS Support
+ #
+ MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+ BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+
+ #
+ # ACPI Support
+ #
+ MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+ BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
+!ifdef $(NOT_BHYVE)
+ BhyvePkg/AcpiTables/AcpiTables.inf
+!else
+ BhyvePkg/BhyveAcpiTables/BhyveAcpiTables.inf
+!endif
+
+ #
+ # Network Support
+ #
+ MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf
+ MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf
+ MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf
+ MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf
+ MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf
+ MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf
+ MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf
+ MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf
+ MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf
+ MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf
+ MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf
+ MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
+ MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf
+ OvmfPkg/VirtioNetDxe/VirtioNet.inf
+
+ #
+ # Usb Support
+ #
+ MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
+ MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
+ MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+ MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+ MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+
+!ifndef $(NOT_BHYVE)
+ # SATA
+ DuetPkg/SataControllerDxe/SataControllerDxe.inf
+ MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+ MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+!endif
+
+!ifdef $(CSM_ENABLE)
+ IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf
+!endif
+ IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf
+!ifdef $(CSM_ENABLE)
+!ifdef $(NOT_BHYVE)
+ BhyvePkg/Csm/Csm16/Csm16.inf
+!else
+ BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.inf
+!endif
+!endif
+
+!ifndef $(USE_OLD_SHELL)
+ ShellPkg/Application/Shell/Shell.inf {
+
+ 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
+ HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+ FileHandleLib|ShellPkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ SortLib|ShellPkg/Library/UefiSortLib/UefiSortLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ PathLib|ShellPkg/Library/BasePathLib/BasePathLib.inf
+# SafeBlockIoLib|ShellPkg/Library/SafeBlockIoLib/SafeBlockIoLib.inf
+# SafeOpenProtocolLib|ShellPkg/Library/SafeOpenProtocolLib/SafeOpenProtocolLib.inf
+ BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
+
+
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
+ }
+!endif
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf {
+
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
+ }
+ BhyvePkg/SecureBootConfigDxe/SecureBootConfigDxe.inf
+!endif
diff --git BhyvePkg/BhyvePkgX64.fdf BhyvePkg/BhyvePkgX64.fdf
new file mode 100644
index 0000000..6b7a324
--- /dev/null
+++ BhyvePkg/BhyvePkgX64.fdf
@@ -0,0 +1,501 @@
+#
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+# Copyright (c) 2014, Pluribus Networks, Inc.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+################################################################################
+
+#
+# Default flash size for DEBUG build is 2MB. For RELEASE it is 1MB.
+#
+# Defining FD_SIZE_1MB or FD_SIZE_2MB on the build command line can
+# override this.
+#
+[Defines]
+!if $(TARGET) == RELEASE
+!ifndef $(FD_SIZE_2MB)
+DEFINE FD_SIZE_1MB=
+!endif
+!endif
+
+!ifdef $(FD_SIZE_1MB)
+[FD.BHYVE]
+BaseAddress = 0xFFF00000|gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFdBaseAddress
+Size = 0x00100000|gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFirmwareFdSize
+ErasePolarity = 1
+BlockSize = 0x1000|gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFirmwareBlockSize
+NumBlocks = 0x100
+!else
+[FD.BHYVE]
+BaseAddress = 0xFFE00000|gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFdBaseAddress
+Size = 0x00200000|gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFirmwareFdSize
+ErasePolarity = 1
+BlockSize = 0x1000|gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFirmwareBlockSize
+NumBlocks = 0x200
+!endif
+
+0x00000000|0x0000e000
+gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFlashNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+#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,
+ # FvLength: 0x20000
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ # Signature "_FVH" # Attributes
+ 0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00,
+ # HeaderLength # CheckSum # ExtHeaderOffset #Reserved #Revision
+ 0x48, 0x00, 0x19, 0xF9, 0x00, 0x00, 0x00, 0x02,
+ # Blockmap[0]: 0x20 Blocks * 0x1000 Bytes / Block
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+ # Blockmap[1]: End
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is the VARIABLE_STORE_HEADER
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ # 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,
+!else
+ # Signature: gEfiVariableGuid =
+ # { 0xddcf3616, 0x3275, 0x4164,
+ # { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }}
+ 0x16, 0x36, 0xcf, 0xdd, 0x75, 0x32, 0x64, 0x41,
+ 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d,
+!endif
+ # 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,
+ # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32
+ 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+0x0000e000|0x00001000
+#NV_EVENT_LOG
+gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFlashNvStorageEventLogBase|gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFlashNvStorageEventLogSize
+
+0x0000f000|0x00001000
+gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFlashNvStorageFtwWorkingBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+#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
+}
+
+0x00010000|0x00010000
+#NV_FTW_SPARE
+gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFlashNvStorageFtwSpareBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+!ifdef $(FD_SIZE_1MB)
+0x00020000|0x000CC000
+FV = FVMAIN_COMPACT
+
+0x000EC000|0x14000
+FV = SECFV
+
+!else
+0x00020000|0x001AC000
+FV = FVMAIN_COMPACT
+
+0x001CC000|0x34000
+FV = SECFV
+!endif
+
+################################################################################
+
+[FD.MEMFD]
+BaseAddress = 0x800000|gUefiBhyvePkgTokenSpaceGuid.PcdBhyveMemFvBase
+Size = 0x800000|gUefiBhyvePkgTokenSpaceGuid.PcdBhyveMemFvSize
+ErasePolarity = 1
+BlockSize = 0x10000
+NumBlocks = 0x80
+
+0x0|0x800000
+FV = MAINFV
+
+################################################################################
+
+[FV.SECFV]
+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 MAINFV which handles the majority of the boot sequence.
+#
+INF BhyvePkg/Sec/SecMain.inf
+
+INF RuleOverride=RESET_VECTOR BhyvePkg/ResetVector/ResetVector.inf
+
+################################################################################
+[FV.MAINFV]
+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
+
+#
+# Files to be placed in MAIN FV
+#
+# This firmware volume will have files placed in it uncompressed,
+# and then then entire firmware volume will be compressed in a
+# single compression operation in order to achieve better
+# overall compression.
+#
+
+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 IntelFrameworkModulePkg/Universal/StatusCode/Pei/StatusCodePei.inf
+INF BhyvePkg/PlatformPei/PlatformPei.inf
+INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+
+FILE FV_IMAGE = A4EF5A93-3F1B-4232-A1C4-F0910E6D1D9C {
+ SECTION COMPRESS PI_NONE {
+ SECTION FV_IMAGE = DXEFV
+ }
+}
+
+################################################################################
+
+[FV.DXEFV]
+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
+}
+
+#
+# DXE Phase modules
+#
+INF MdeModulePkg/Core/Dxe/DxeMain.inf
+
+INF IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.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 PcAtChipsetPkg/8259InterruptControllerDxe/8259.inf
+INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+INF UefiCpuPkg/CpuDxe/CpuDxe.inf
+!ifdef $(NOT_BHYVE)
+INF PcAtChipsetPkg/8254TimerDxe/8254Timer.inf
+!endif
+INF PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf
+INF DuetPkg/PciRootBridgeNoEnumerationDxe/PciRootBridgeNoEnumeration.inf
+INF DuetPkg/PciBusNoEnumerationDxe/PciBusNoEnumeration.inf
+INF PcAtChipsetPkg/KbcResetDxe/Reset.inf
+INF MdeModulePkg/Universal/Metronome/Metronome.inf
+INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
+
+INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+INF BhyvePkg/EmuVariableFvbRuntimeDxe/Fvb.inf
+INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ INF SecurityPkg/VariableAuthenticated/RuntimeDxe/VariableRuntimeDxe.inf
+ INF BhyvePkg/SecureBootConfigDxe/SecureBootConfigDxe.inf
+!else
+ INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.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 IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.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/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+!ifndef $(NOT_BHYVE)
+INF DuetPkg/SataControllerDxe/SataControllerDxe.inf
+INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+!endif
+INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+!ifdef $(NOT_BHYVE)
+INF IntelFrameworkModulePkg/Bus/Pci/IdeBusDxe/IdeBusDxe.inf
+INF PcAtChipsetPkg/Bus/Pci/IdeControllerDxe/IdeControllerDxe.inf
+!endif
+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 PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf
+INF IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf
+
+!ifndef $(SOURCE_DEBUG_ENABLE)
+INF IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf
+!endif
+
+INF IntelFrameworkModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2keyboardDxe.inf
+INF IntelFrameworkModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
+
+INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+INF BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+
+INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+INF BhyvePkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
+!ifdef $(NOT_BHYVE)
+INF RuleOverride=ACPITABLE BhyvePkg/AcpiTables/AcpiTables.inf
+!else
+INF RuleOverride=ACPITABLE BhyvePkg/BhyveAcpiTables/BhyveAcpiTables.inf
+!endif
+
+INF RuleOverride = BINARY FatBinPkg/EnhancedFatDxe/Fat.inf
+
+!ifndef $(USE_OLD_SHELL)
+INF ShellPkg/Application/Shell/Shell.inf
+!else
+INF RuleOverride = BINARY EdkShellBinPkg/FullShell/FullShell.inf
+!endif
+
+FILE FREEFORM = PCD(gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile) {
+ SECTION RAW = MdeModulePkg/Logo/Logo.bmp
+}
+
+#
+# Network modules
+#
+!if $(E1000_ENABLE)
+ FILE DRIVER = 5D695E11-9B3F-4b83-B25F-4A8D5D69BE07 {
+ SECTION PE32 = Intel3.5/EFIX64/E3507X2.EFI
+ }
+!endif
+ INF MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf
+ INF MdeModulePkg/Universal/Network/DpcDxe/DpcDxe.inf
+ INF MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf
+ INF MdeModulePkg/Universal/Network/VlanConfigDxe/VlanConfigDxe.inf
+ INF MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf
+ INF MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf
+ INF MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf
+ INF MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf
+ INF MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Dxe.inf
+ INF MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf
+ INF MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf
+ INF MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
+ INF MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf
+ INF OvmfPkg/VirtioNetDxe/VirtioNet.inf
+
+#
+# Usb Support
+#
+INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
+INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+
+!ifdef $(CSM_ENABLE)
+INF IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf
+!endif
+INF IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf
+!ifdef $(CSM_ENABLE)
+INF RuleOverride=CSM BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.inf
+!endif
+
+
+################################################################################
+
+[FV.FVMAIN_COMPACT]
+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 {
+ SECTION FV_IMAGE = MAINFV
+ }
+ }
+
+################################################################################
+
+[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=32 $(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=32 $(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)
+ }
+
+[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
+ }
diff --git BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.c BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.c
new file mode 100644
index 0000000..627c4f0
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.c
@@ -0,0 +1,688 @@
+/*
+ * Copyright (c) 2015, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "BhyveCsm16.h"
+
+#include "Debug.h"
+#include "Keyboard.h"
+#include "Legacy8254.h"
+#include "Memory.h"
+#include "Mmu.h"
+#include "Printf.h"
+#include "Smbios.h"
+#include "String.h"
+#include "Video.h"
+
+#define SIGNATURE_16(A, B) ((A) | (B << 8))
+#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16))
+
+EFI_SYSTEM_TABLE *gST;
+EFI_BOOT_SERVICES *gBS;
+EFI_RUNTIME_SERVICES *gRT;
+
+EFI_LEGACY_MP_TABLE_FLOATING_POINTER mMpTableFP;
+EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER mAcpiRsdPtr;
+SMBIOS_TABLE_STRUCTURE mSmbiosTableStructure;
+
+EFI_COMPATIBILITY16_TABLE mEfiCompatibility16Table = {
+ SIGNATURE_32 ('I', 'F', 'E', '$'),
+ 0,
+ sizeof (EFI_COMPATIBILITY16_TABLE),
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ F_SEGMENT,
+ 0x400
+};
+
+UINT32 mHiPmmMemory;
+UINT32 mPML4;
+IA32_IDT_GATE_DESCRIPTOR *mIdtEntries;
+IA32_DESCRIPTOR mIDT;
+UINT32 mStack;
+
+UINT8 __attribute__((section (".tail"))) mBuildDate[] = BUILD_DATE;
+
+extern VOID *_end;
+
+VOID
+Loop(VOID)
+{
+ DEBUG(("XXX Loop()\n"));
+ for (;;) ;
+ //__asm__ __volatile__ ("iretq");
+}
+
+extern VOID X64InterruptVectorEntry0x40(VOID);
+extern VOID X64InterruptVectorEntry0x41(VOID);
+
+#if 0
+#include "FakeIdt.h" // XXX Test Idts
+#endif
+
+STATIC
+VOID
+CsmLegacy16InitializeYourself(EFI_IA32_REGISTER_SET *Regs)
+{
+ EFI_TO_COMPATIBILITY16_INIT_TABLE *EfiToLegacy16InitTable;
+ IA32_IDT_GATE_DESCRIPTOR IdtEntry;
+ UINTN Index;
+
+ DEBUG (("XXX CsmLegacy16InitializeYourself()\n"));
+
+ EfiToLegacy16InitTable = (EFI_TO_COMPATIBILITY16_INIT_TABLE *)(UINT64)((Regs->X.ES << 4) + (Regs->X.BX));
+
+ for (Index = 0; Index < 256; Index++) {
+ *(((UINT32 *)0) + Index) = *(((UINT32 *)&IVT) + Index);
+ }
+
+ ESegmentInitializePool(0xE0000, 0xEFFFF);
+ FSegmentInitializePool((UINT32)(UINT64)&_end, 0xFFFFF);
+
+ gST = (EFI_SYSTEM_TABLE *)(UINT64)mEfiCompatibility16Table.EfiSystemTable;
+ gBS = gST->BootServices;
+ gRT = gST->RuntimeServices;
+
+ mHiPmmMemory = EfiToLegacy16InitTable->HiPmmMemory;
+ mStack = mHiPmmMemory + 0x1000 - 0x8;
+
+ mPML4 = mHiPmmMemory + 0x1000;
+ CreateIdentityMappingPageTables(mPML4);
+ WriteCr3((VOID *)(UINT64)mPML4);
+
+ mIdtEntries = (IA32_IDT_GATE_DESCRIPTOR *)(UINTN)mHiPmmMemory + 0x1000 + 0x6000;
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Loop;
+ IdtEntry.Bits.Selector = 0x8;
+ IdtEntry.Bits.Reserved_0 = 0;
+ IdtEntry.Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Loop) >> 16);
+ IdtEntry.Bits.OffsetUpper = 0;
+ for (Index = 0; Index < 256; Index++) {
+ CopyMem (&mIdtEntries[Index], &IdtEntry, sizeof (IdtEntry));
+ }
+
+#ifdef FAKE_IDTS
+ InitFakeIdtEntries();
+#endif
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)X64InterruptVectorEntry0x40;
+ IdtEntry.Bits.Selector = 0x8;
+ IdtEntry.Bits.Reserved_0 = 0;
+ IdtEntry.Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)X64InterruptVectorEntry0x40) >> 16);
+ IdtEntry.Bits.OffsetUpper = 0;
+ CopyMem (&mIdtEntries[0x40], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)X64InterruptVectorEntry0x41;
+ IdtEntry.Bits.Selector = 0x8;
+ IdtEntry.Bits.Reserved_0 = 0;
+ IdtEntry.Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)X64InterruptVectorEntry0x41) >> 16);
+ IdtEntry.Bits.OffsetUpper = 0;
+ CopyMem (&mIdtEntries[0x41], &IdtEntry, sizeof (IdtEntry));
+
+ mIDT.Base = (UINTN)mIdtEntries;
+ mIDT.Limit = (UINT16)((sizeof (IA32_IDT_GATE_DESCRIPTOR) * 256) - 1);
+
+
+ /*
+ * This isn't possible at compile time because of the cast from a
+ * 64-bit value to a 32-bit one.
+ */
+ mEfiCompatibility16Table.AcpiRsdPtrPointer = (UINT32)(UINT64)&mAcpiRsdPtr;
+
+ Regs->X.AX = 0;
+}
+
+STATIC
+VOID
+CsmLegacy16UpdateBbs(EFI_IA32_REGISTER_SET *Regs)
+{
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;
+ DEBUG (("XXX CsmLegacy16UpdateBbs() Regs->AX = 0x%x, Regs->X.BX = 0x%x, Regs->X.CX = 0x%x, Regs->X.DX = 0x%x, Regs->X.ES = 0x%x\n", Regs->X.AX, Regs->X.BX, Regs->X.CX, Regs->X.DX, Regs->X.ES));
+
+ EfiToLegacy16BootTable = (EFI_TO_COMPATIBILITY16_BOOT_TABLE *)(UINT64)((Regs->X.ES << 4) + (Regs->X.BX));
+
+ Regs->X.AX = 0;
+}
+
+extern VOID JumpLongModeToRealMode(UINT16 Stack);
+
+//
+// Extract INT32 from char array
+//
+#define UNPACK_INT32(a) (INT32)( (((UINT8 *) a)[0] << 0) | \
+ (((UINT8 *) a)[1] << 8) | \
+ (((UINT8 *) a)[2] << 16) | \
+ (((UINT8 *) a)[3] << 24) )
+
+//
+// Extract UINT32 from char array
+//
+#define UNPACK_UINT32(a) (UINT32)( (((UINT8 *) a)[0] << 0) | \
+ (((UINT8 *) a)[1] << 8) | \
+ (((UINT8 *) a)[2] << 16) | \
+ (((UINT8 *) a)[3] << 24) )
+
+VOID *mBootSector = (VOID *)0x7C00;
+
+EFI_HANDLE *mDeviceHandle;
+EFI_BLOCK_IO_PROTOCOL *mDeviceBlockIo;
+UINT8 mDriveNumber;
+
+BDA *mBdaPtr = (BDA *)(UINTN)0x400;
+
+VOID
+EnterRealMode(EFI_IA32_REGISTER_SET *Regs, UINT16 Segment, UINT16 Offset)
+{
+ VOID *Stack;
+
+ Stack = (VOID *)(0x2000 - 0x8);
+
+ Stack -= 2;
+ /* EFLAGS image */
+ *(UINT16 *)(Stack) = 0;
+
+ Stack -= 2;
+ /* return code segment selector */
+ *(UINT16 *)(Stack) = Segment;
+
+ Stack -= 2;
+ /* return instruction pointer */
+ *(UINT16 *)(Stack) = Offset;
+
+ Stack -= 4;
+ /* junk (old argument to LongToReal) */
+ *(UINT16 *)(Stack) = 0x0;
+
+ Stack -= 4;
+ /* junk (old frame pointer) */
+ *(UINT16 *)(Stack) = 0;
+
+ Stack -= sizeof (EFI_IA32_REGISTER_SET);
+ CopyMem(Stack, Regs, sizeof (EFI_IA32_REGISTER_SET));
+
+ Stack -= 4;
+ /* stack pointer */
+ *(UINT32 *)(Stack) = (UINT32)(UINTN)(Stack + 4);
+
+ Stack -= 4;
+ /* %cr3 */
+ *(UINT32 *)(Stack) = mPML4;
+
+ JumpLongModeToRealMode((UINT16)(UINTN)Stack);
+}
+
+VOID
+BootElTorito(EFI_BLOCK_IO_PROTOCOL *Device)
+{
+ EFI_STATUS Status;
+ CDROM_VOLUME_DESCRIPTOR *VolDescriptor;
+ ELTORITO_CATALOG *Catalog;
+ UINT32 Lba;
+ UINTN Check;
+ UINTN Index;
+ UINT16 *CheckBuffer;
+ UINTN MaxIndex;
+ EFI_IA32_REGISTER_SET Regs;
+
+ DEBUG (("XXX BootElTorito() Device=%p\n", Device));
+
+ if (Device->Media->BlockSize != 2048) {
+ return;
+ }
+
+ Status = gBS->AllocatePool (EfiRuntimeServicesData, Device->Media->BlockSize, (VOID **)&VolDescriptor);
+ if (EFI_ERROR (Status)) {
+ DEBUG (("XXX BootElTorito() AllocatePool() failed\n"));
+ return;
+ }
+ ZeroMem(VolDescriptor, Device->Media->BlockSize);
+
+ do {
+ Status = Device->ReadBlocks(Device, Device->Media->MediaId, 17, Device->Media->BlockSize, VolDescriptor);
+ } while (Status == EFI_MEDIA_CHANGED);
+
+ if (EFI_ERROR (Status) && (Status != EFI_MEDIA_CHANGED)) {
+ DEBUG (("XXX BootElTorito() unable to read volume descriptor: %r\n", Status));
+ return;
+ }
+
+ if (CompareMem (VolDescriptor->BootRecordVolume.SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) {
+ DEBUG (("XXX BootElTorito() invalid El Torito signature\n"));
+ return;
+ }
+
+ Lba = UNPACK_INT32 (VolDescriptor->BootRecordVolume.EltCatalog);
+
+ Catalog = (ELTORITO_CATALOG *) VolDescriptor;
+
+ Status = Device->ReadBlocks(Device, Device->Media->MediaId, Lba, Device->Media->BlockSize, Catalog);
+ if (EFI_ERROR (Status)) {
+ DEBUG (("XXX BootElTorito() unable to read catalog\n"));
+ return;
+ }
+
+ if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) {
+ DEBUG (("XXX BootElTorito() invalid boot catalog signature\n"));
+ return;
+ }
+
+ // Validation Entry
+ Check = 0;
+ CheckBuffer = (UINT16 *) Catalog;
+ for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) {
+ Check += CheckBuffer[Index];
+ }
+ if ((Check & 0xFFFF) != 0) {
+ DEBUG (("XXX BootElTorito() boot catalog header checksum failed\n"));
+ return;
+ }
+
+ // Initial/Default Entry
+ Catalog += 1;
+ if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) {
+ DEBUG (("XXX BootElTorito() not bootable\n"));
+ return;
+ }
+ if (Catalog->Boot.MediaType != ELTORITO_NO_EMULATION) {
+ DEBUG (("XXX BootElTorito() unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType));
+ return;
+ }
+
+ Status = Device->ReadBlocks(Device, Device->Media->MediaId, Catalog->Boot.Lba, Catalog->Boot.SectorCount * Device->Media->BlockSize, mBootSector);
+ if (EFI_ERROR(Status)) {
+ DEBUG (("XXX BootElTorito() unable to read boot sector\n"));
+ return;
+ }
+
+ ZeroMem(&Regs, sizeof (EFI_IA32_REGISTER_SET));
+ Regs.E.EDX = mDriveNumber;
+ EnterRealMode(&Regs, 0, (UINT16)(UINTN)mBootSector);
+}
+
+VOID
+BootMbr(EFI_BLOCK_IO_PROTOCOL *Device)
+{
+ EFI_STATUS Status;
+ MASTER_BOOT_RECORD *Mbr;
+ UINTN Index;
+ UINT32 StartingLBA;
+ UINT32 SizeInLBA;
+ EFI_IA32_REGISTER_SET Regs;
+
+ DEBUG (("XXX BootMbr() Device=%p\n", Device));
+
+ if (Device->Media->BlockSize != 512) {
+ return;
+ }
+
+ Mbr = (MASTER_BOOT_RECORD *)mBootSector;
+ // Read the MBR
+ Status = Device->ReadBlocks(Device, Device->Media->MediaId, 0, Device->Media->BlockSize, Mbr);
+ if (EFI_ERROR(Status)) {
+ DEBUG (("XXX BootMbr() unable to read MBR: %r\n", Status));
+ return;
+ }
+
+ if (Mbr->Signature != MBR_SIGNATURE) {
+ DEBUG (("XXX BootMbr() invalid MBR signature 0x%04x (not 0xAA55)\n", Mbr->Signature));
+ return;
+ }
+
+ ZeroMem(&Regs, sizeof (EFI_IA32_REGISTER_SET));
+ Regs.E.EDX = mDriveNumber;
+ EnterRealMode(&Regs, 0, (UINT16)(UINTN)mBootSector);
+}
+
+EFI_GUID gEfiEventCsmBootGuid = { 0x05253738, 0x5BD2, 0x4311, { 0xB3, 0x8D, 0x8D, 0xE4, 0x64, 0x69, 0x17, 0x10 }};
+EFI_GUID gEfiEventCsmPrepareToBootGuid = { 0X6B145B5F, 0X6E45, 0X4BCC, { 0XAD, 0XDE, 0X31, 0X23, 0X71, 0X7D, 0X27, 0X0C }};
+EFI_EVENT mCsmPrepareToBootEvent;
+EFI_EVENT mCsmBootEvent;
+
+VOID
+EFIAPI
+CsmPrepareToBootEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_GUID gEfiBlockIoProtocolGuid = EFI_BLOCK_IO_PROTOCOL_GUID;
+ EFI_GUID gEfiDevicePathProtocolGuid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+ EFI_GUID gEfiDevicePathToTextProtocolGuid = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathToTextProtocol;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+
+ DEBUG (("XXX CsmPrepareToBootEvent()\n"));
+
+ Status = gBS->LocateProtocol (
+ &gEfiDevicePathToTextProtocolGuid,
+ NULL,
+ (VOID **)&DevicePathToTextProtocol
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG (("XXX CsmPrepareToBootEvent() LocateProtocol() gEfiDevicePathToTextProtocolGuid failed\n"));
+ goto Fail;
+ }
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR(Status)) {
+ DEBUG (("XXX LocateHandleBuffer() gEfiBlockIoProtocolGuid failed\n"));
+ goto Fail;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ CHAR16* DevicePathTxt;
+
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (DevicePath, FALSE, TRUE);
+ DEBUG (("XXX Handle = %p DevicePathTxt = %s\n", HandleBuffer[Index], DevicePathTxt));
+
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **) &BlockIo
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ if (Index >= HandleCount) {
+ goto Fail;
+ }
+
+ mDeviceHandle = HandleBuffer[Index];
+ mDeviceBlockIo = BlockIo;
+ if (mDeviceBlockIo->Media->RemovableMedia) {
+ // set the cdrom drive number greater than 'BDA NumberOfDrives'
+ mDriveNumber = 0x80 + mBdaPtr->NumberOfDrives;
+ } else {
+ mDriveNumber = 0x80;
+ }
+
+ return;
+
+Fail:
+ DEBUG (("XXX CsmPrepareToBootEvent() Fail: spinning...\n"));
+ for (;;) {
+ }
+}
+
+EFI_LEGACY_8259_PROTOCOL *mLegacy8259;
+
+VOID
+EFIAPI
+CsmBootEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_GUID gEfiLegacy8259ProtocolGuid = EFI_LEGACY_8259_PROTOCOL_GUID;
+ EFI_STATUS Status;
+
+ DEBUG (("XXX CsmBootEvent()\n"));
+ DEBUG (("XXX Eflags = 0x%x\n", ReadEflags()));
+ DEBUG (("XXX Tsc = 0x%lx\n", ReadTsc()));
+
+ DisableInterrupts();
+
+ Status = gBS->LocateProtocol(&gEfiLegacy8259ProtocolGuid,
+ NULL, (VOID **) &mLegacy8259);
+
+ //
+ // Set the 8259 Master base to 0x68 and the 8259 Slave base to 0x70
+ // Initialize the keyboard and controller
+ //
+ KeyboardInitialize();
+
+ //
+ // Initialize the VGA
+ //
+ VGAInitialize();
+
+ //
+ // Set the 8259 Master and Slaves base interrupt vectors
+ //
+ mLegacy8259->SetVectorBase(mLegacy8259,
+ LEGACY8259_MODE_BASE_VECTOR_MASTER,
+ LEGACY8259_MODE_BASE_VECTOR_SLAVE);
+
+ mLegacy8259->EnableIrq(mLegacy8259, Efi8259Irq0, FALSE);
+ mLegacy8259->EnableIrq(mLegacy8259, Efi8259Irq1, TRUE);
+
+ Legacy8254SetCount (0xffff);
+
+ //
+ // RaiseTPL() can enable interrupts. We don't want that, so neuter it.
+ //
+ *(UINT8 *)gST->BootServices->RaiseTPL = 0xc3;
+ *(UINT8 *)gST->BootServices->RestoreTPL = 0xc3;
+
+ if (mDeviceBlockIo->Media->RemovableMedia && mDeviceBlockIo->Media->ReadOnly) {
+ BootElTorito(mDeviceBlockIo);
+ } else {
+ BootMbr(mDeviceBlockIo);
+ }
+}
+
+STATIC
+VOID
+CsmLegacy16PrepareToBoot(EFI_IA32_REGISTER_SET *Regs)
+{
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE *EfiToLegacy16BootTable;
+ UINT8 OldEfiRaiseTpl;
+ UINT8 OldEfiRestoreTpl;
+ EFI_STATUS Status;
+
+ DEBUG (("XXX CsmLegacy16PrepareToBoot() Regs->AX = 0x%x, Regs->X.BX = 0x%x, Regs->X.CX = 0x%x, Regs->X.DX = 0x%x\n", Regs->X.AX, Regs->X.BX, Regs->X.CX, Regs->X.DX));
+
+ EfiToLegacy16BootTable = (EFI_TO_COMPATIBILITY16_BOOT_TABLE *)(UINT64)((Regs->X.ES << 4) + (Regs->X.BX));
+
+ CopyMem (&mMpTableFP,
+ (VOID *)(UINT64)mEfiCompatibility16Table.MpTablePtr,
+ sizeof (EFI_LEGACY_MP_TABLE_FLOATING_POINTER));
+
+ CopyMem (&mSmbiosTableStructure,
+ (VOID *)(UINT64)EfiToLegacy16BootTable->SmbiosTable,
+ sizeof (SMBIOS_TABLE_STRUCTURE));
+
+ OldEfiRaiseTpl = *(UINT8 *)gST->BootServices->RaiseTPL;
+ *(UINT8 *)gST->BootServices->RaiseTPL = 0xc3;
+ OldEfiRestoreTpl = *(UINT8 *)gST->BootServices->RestoreTPL;
+ *(UINT8 *)gST->BootServices->RestoreTPL = 0xc3;
+
+ Status = gST->BootServices->CreateEventEx (
+ EVT_RUNTIME | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ CsmPrepareToBootEvent,
+ NULL,
+ &gEfiEventCsmPrepareToBootGuid,
+ &mCsmPrepareToBootEvent
+ );
+ gST->BootServices->SignalEvent (mCsmPrepareToBootEvent);
+
+ Status = gST->BootServices->CreateEventEx (
+ EVT_RUNTIME | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ CsmBootEvent,
+ NULL,
+ &gEfiEventCsmBootGuid,
+ &mCsmBootEvent
+ );
+
+ *(UINT8 *)gST->BootServices->RaiseTPL = OldEfiRaiseTpl;
+ *(UINT8 *)gST->BootServices->RestoreTPL = OldEfiRestoreTpl;
+
+ Regs->X.AX = 0;
+}
+
+STATIC
+VOID
+CsmLegacy16Boot(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX CsmLegacy16Boot()\n"));
+
+ gST->BootServices->SignalEvent (mCsmBootEvent);
+
+ /*
+ * Return to give our 'callback' a chance to run.
+ */
+}
+
+STATIC
+VOID
+CsmLegacy16DispatchOprom(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX CsmLegacy16DispatchOprom() Regs->AX = 0x%x, Regs->X.BX = 0x%x, Regs->X.CX = 0x%x, Regs->X.DX = 0x%x\n", Regs->X.AX, Regs->X.BX, Regs->X.CX, Regs->X.DX));
+
+ Regs->X.AX = 0;
+}
+
+STATIC
+VOID
+CsmLegacy16GetTableAddress(EFI_IA32_REGISTER_SET *Regs)
+{
+ EFI_STATUS Status;
+ UINT32 Address;
+
+ DEBUG (("XXX CsmLegacy16GetTableAddress() Regs->AX = 0x%x, Regs->X.BX = 0x%x, Regs->X.CX = 0x%x, Regs->X.DX = 0x%x\n", Regs->X.AX, Regs->X.BX, Regs->X.CX, Regs->X.DX));
+
+ switch (Regs->X.BX) {
+ case 0x0:
+ case 0x2:
+ Status = ESegmentAllocatePool(Regs->X.CX, Regs->X.DX, &Address);
+ Regs->X.BX = Address & 0xFFFF;
+ Regs->X.DS = E_SEGMENT;
+ Regs->X.AX = 0;
+ break;
+ case 0x1:
+ Status = FSegmentAllocatePool(Regs->X.CX, Regs->X.DX, &Address);
+ Regs->X.BX = Address & 0xFFFF;
+ Regs->X.DS = F_SEGMENT;
+ Regs->X.AX = 0;
+ break;
+ default:
+ Regs->X.AX = -1;
+ break;
+ }
+}
+
+VOID
+CsmMain(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX CsmMain() Regs->X.AX=0x%x\n", Regs->X.AX));
+
+ switch (Regs->X.AX) {
+ case Legacy16InitializeYourself:
+ CsmLegacy16InitializeYourself(Regs);
+ break;
+ case Legacy16UpdateBbs:
+ CsmLegacy16UpdateBbs(Regs);
+ break;
+ case Legacy16PrepareToBoot:
+ CsmLegacy16PrepareToBoot(Regs);
+ break;
+ case Legacy16Boot:
+ CsmLegacy16Boot(Regs);
+ break;
+ case Legacy16DispatchOprom:
+ CsmLegacy16DispatchOprom(Regs);
+ break;
+ case Legacy16GetTableAddress:
+ CsmLegacy16GetTableAddress(Regs);
+ break;
+ default:
+ Regs->X.AX = -1;
+ break;
+ }
+}
+
+VOID
+InterruptVector0x00(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x00()\n"));
+}
+
+VOID
+InterruptVector0x01(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x01()\n"));
+}
+
+VOID
+InterruptVector0x02(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x02()\n"));
+}
+
+VOID
+InterruptVector0x03(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x03()\n"));
+}
+
+VOID
+InterruptVector0x04(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x04()\n"));
+}
+
+VOID
+InterruptVector0x05(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x05()\n"));
+}
+
+VOID
+InterruptVector0x06(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x06()\n"));
+}
+
+VOID
+InterruptVector0x07(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x07()\n"));
+}
diff --git BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.h BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.h
new file mode 100644
index 0000000..fb6b05f
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+ * Copyright (c) 2015, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#ifndef _BHYVE_CSM16_H_
+#define _BHYVE_CSM16_H_
+
+#include
+#include
+#include
+#include
+
+#include "BiosInterface.h"
+
+#define E_SEGMENT 0xE000
+#define F_SEGMENT 0xF000
+
+#define LEGACY8259_MODE_BASE_VECTOR_MASTER 0x40
+#define LEGACY8259_MODE_BASE_VECTOR_SLAVE 0x48
+
+#define CPU_EFLAGS_IF 0x200
+
+extern VOID *IVT;
+extern VOID *_end;
+
+extern EFI_SYSTEM_TABLE *gST;
+extern EFI_BOOT_SERVICES *gBS;
+extern EFI_RUNTIME_SERVICES *gRT;
+
+extern EFI_HANDLE *mDeviceHandle;
+extern EFI_BLOCK_IO_PROTOCOL *mDeviceBlockIo;
+extern UINT8 mDriveNumber;
+extern EFI_COMPATIBILITY16_TABLE mEfiCompatibility16Table;
+extern EFI_LEGACY_8259_PROTOCOL *mLegacy8259;
+
+extern BDA *mBdaPtr;
+
+#define IA32_IDT_GATE_TYPE_INTERRUPT_32 0x8E
+
+///
+/// Byte packed structure for an x64 Interrupt Gate Descriptor.
+///
+typedef union {
+ struct {
+ UINT32 OffsetLow:16; ///< Offset bits 15..0.
+ UINT32 Selector:16; ///< Selector.
+ UINT32 Reserved_0:8; ///< Reserved.
+ UINT32 GateType:8; ///< Gate Type. See #defines above.
+ UINT32 OffsetHigh:16; ///< Offset bits 31..16.
+ UINT32 OffsetUpper:32; ///< Offset bits 63..32.
+ UINT32 Reserved_1:32; ///< Reserved.
+ } Bits;
+ struct {
+ UINT64 Uint64;
+ UINT64 Uint64_1;
+ } Uint128;
+} IA32_IDT_GATE_DESCRIPTOR;
+
+///
+/// Byte packed structure for an IDTR, GDTR, LDTR descriptor.
+///
+#pragma pack (1)
+typedef struct {
+ UINT16 Limit;
+ UINTN Base;
+} IA32_DESCRIPTOR;
+#pragma pack ()
+
+STATIC inline
+EFIAPI
+IoRead8 (
+ IN UINTN Port
+ )
+{
+ UINT8 Data;
+
+ __asm__ __volatile__ ("inb %w1,%b0" : "=a" (Data) : "d" ((UINT16)Port));
+ return Data;
+}
+
+STATIC inline
+UINT8
+EFIAPI
+IoWrite8 (
+ IN UINTN Port,
+ IN UINT8 Value
+ )
+{
+ __asm__ __volatile__ ("outb %b0,%w1" : : "a" (Value), "d" ((UINT16)Port));
+ return Value;
+}
+
+STATIC inline
+UINT8
+EFIAPI
+IoWrite32 (
+ IN UINTN Port,
+ IN UINT32 Value
+ )
+{
+ __asm__ __volatile__ ("outl %0,%w1" : : "a" (Value), "d" ((UINT16)Port));
+ return Value;
+}
+
+STATIC inline
+VOID
+EnableInterrupts (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("sti"::: "memory");
+}
+
+STATIC inline
+VOID
+DisableInterrupts (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("cli"::: "memory");
+}
+
+STATIC inline
+UINTN
+EFIAPI
+ReadEflags (
+ VOID
+ )
+{
+ UINTN Eflags;
+
+ __asm__ __volatile__ (
+ "pushfq; pop %0"
+ : "=r" (Eflags)
+ );
+
+ return Eflags;
+}
+
+STATIC inline
+UINT64
+EFIAPI
+ReadTsc (
+ VOID
+ )
+{
+ UINT32 Low, High;
+
+ __asm __volatile__ ("rdtsc" : "=a" (Low), "=d" (High));
+ return (Low | ((UINT64)High << 32));
+}
+
+STATIC inline
+VOID *
+EFIAPI
+WriteCr3 (
+ VOID *Cr3
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%cr3"
+ :
+ : "r" (Cr3)
+ );
+ return Cr3;
+}
+
+STATIC inline
+VOID
+WriteIdtr (
+ IN CONST IA32_DESCRIPTOR *Idtr
+ )
+{
+ __asm__ __volatile__ (
+ "lidt %0"
+ :
+ : "m" (*Idtr)
+ );
+}
+
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.inf BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.inf
new file mode 100644
index 0000000..9fe1a1a
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/BhyveCsm16.inf
@@ -0,0 +1,22 @@
+#
+# Copyright (c) 2014, Pluribus Networks, Inc.
+#
+# This program and the accompanying materials are licensed and made
+# available under the terms and conditions of the BSD License which
+# accompanies this distribution. The full text of the license may be
+# found at http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+# BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED.
+#
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BhyveCsm16
+ FILE_GUID = 1547B4F3-3E8A-4FEF-81C8-328ED647AB1A
+ MODULE_TYPE = USER_DEFINED
+ VERSION_STRING = 1.0
+
+[Binaries]
+ BIN|Bin/BhyveCsm16.bin|*
\ No newline at end of file
diff --git BhyvePkg/Csm/BhyveCsm16/BhyveCsm16Asm.S BhyvePkg/Csm/BhyveCsm16/BhyveCsm16Asm.S
new file mode 100644
index 0000000..cb4e02c
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/BhyveCsm16Asm.S
@@ -0,0 +1,960 @@
+/*
+ * Copyright (c) 2015, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#define CODE64_SEL 0x0008
+#define DATA64_SEL 0x0010
+#define CODE16_SEL 0x0018
+#define DATA16_SEL 0x0020
+
+#define PAGE_PRESENT (1 << 0)
+#define PAGE_WRITE (1 << 1)
+#define PAGE_SIZE (1 << 7)
+
+#define sizeofEFI_IA32_REGISTER_SET 48
+#define offsetofEFI_IA32_REGISTER_SET_X_AX 0
+#define offsetofEFI_IA32_REGISTER_SET_E_EAX 0
+#define offsetofEFI_IA32_REGISTER_SET_X_BX 4
+#define offsetofEFI_IA32_REGISTER_SET_E_EBX 4
+#define offsetofEFI_IA32_REGISTER_SET_X_CX 8
+#define offsetofEFI_IA32_REGISTER_SET_E_ECX 8
+#define offsetofEFI_IA32_REGISTER_SET_X_DX 12
+#define offsetofEFI_IA32_REGISTER_SET_E_EDX 12
+#define offsetofEFI_IA32_REGISTER_SET_E_ESI 16
+#define offsetofEFI_IA32_REGISTER_SET_E_EDI 20
+#define offsetofEFI_IA32_REGISTER_SET_X_FLAGS 24
+#define offsetofEFI_IA32_REGISTER_SET_X_ES 28
+#define offsetofEFI_IA32_REGISTER_SET_X_CS 30
+#define offsetofEFI_IA32_REGISTER_SET_X_SS 32
+#define offsetofEFI_IA32_REGISTER_SET_X_DS 34
+#define offsetofEFI_IA32_REGISTER_SET_X_FS 36
+#define offsetofEFI_IA32_REGISTER_SET_X_GS 38
+#define offsetofEFI_IA32_REGISTER_SET_X_BP 40
+#define offsetofEFI_IA32_REGISTER_SET_X_SP 44
+
+
+ .code16
+ .org 0x0
+ .global IVT
+IVT: .word InterruptVectorEntry0x00 - IVT, 0xf000 /* 0x00 */
+ .word InterruptVectorEntry0x01 - IVT, 0xf000 /* 0x01 */
+ .word InterruptVectorEntry0x02 - IVT, 0xf000 /* 0x02 */
+ .word InterruptVectorEntry0x03 - IVT, 0xf000 /* 0x03 */
+ .word InterruptVectorEntry0x04 - IVT, 0xf000 /* 0x04 */
+ .word InterruptVectorEntry0x05 - IVT, 0xf000 /* 0x05 */
+ .word InterruptVectorEntry0x06 - IVT, 0xf000 /* 0x06 */
+ .word InterruptVectorEntry0x07 - IVT, 0xf000 /* 0x07 */
+ .word InterruptVectorEntry0x08 - IVT, 0xf000 /* 0x08 */
+ .word InterruptVectorEntry0x09 - IVT, 0xf000 /* 0x09 */
+ .word InterruptVectorEntry0x0a - IVT, 0xf000 /* 0x0a */
+ .word InterruptVectorEntry0x0b - IVT, 0xf000 /* 0x0b */
+ .word InterruptVectorEntry0x0c - IVT, 0xf000 /* 0x0c */
+ .word InterruptVectorEntry0x0d - IVT, 0xf000 /* 0x0d */
+ .word InterruptVectorEntry0x0e - IVT, 0xf000 /* 0x0e */
+ .word InterruptVectorEntry0x0f - IVT, 0xf000 /* 0x0f */
+ .word InterruptVectorEntry0x10 - IVT, 0xf000 /* 0x10 */
+ .word InterruptVectorEntry0x11 - IVT, 0xf000 /* 0x11 */
+ .word InterruptVectorEntry0x12 - IVT, 0xf000 /* 0x12 */
+ .word InterruptVectorEntry0x13 - IVT, 0xf000 /* 0x13 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x14 */
+ .word InterruptVectorEntry0x15 - IVT, 0xf000 /* 0x15 */
+ .word InterruptVectorEntry0x16 - IVT, 0xf000 /* 0x16 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x17 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x18 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x19 */
+ .word InterruptVectorEntry0x1a - IVT, 0xf000 /* 0x1a */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x1b */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x1c */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x1d */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x1e */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x1f */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x20 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x21 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x22 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x23 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x24 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x25 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x26 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x27 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x28 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x29 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x2a */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x2b */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x2c */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x2d */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x2e */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x2f */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x30 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x31 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x32 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x33 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x34 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x35 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x36 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x37 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x38 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x39 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x3a */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x3b */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x3c */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x3d */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x3e */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x3f */
+ .word InterruptVectorEntry0x40 - IVT, 0xf000 /* 0x40 */
+ .word InterruptVectorEntry0x41 - IVT, 0xf000 /* 0x41 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x42 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x43 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x44 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x45 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x46 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x47 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x48 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x49 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x4a */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x4b */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x4c */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x4d */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x4e */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x4f */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x50 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x51 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x52 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x53 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x54 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x55 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x56 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x57 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x58 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x59 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x5a */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x5b */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x5c */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x5d */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x5e */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x5f */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x60 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x61 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x62 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x63 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x64 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x65 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x66 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x67 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x68 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x69 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x6a */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x6b */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x6c */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x6d */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x6e */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x6f */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x70 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x71 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x72 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x73 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x74 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x75 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x76 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x77 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x78 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x79 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x7a */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x7b */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x7c */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x7d */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x7e */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x7f */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x80 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x81 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x82 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x83 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x84 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x85 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x86 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x87 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x88 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x89 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x8a */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x8b */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x8c */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x8d */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x8e */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x8f */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x90 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x91 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x92 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x93 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x94 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x95 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x96 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x97 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x98 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x99 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x9a */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x9b */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x9c */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x9d */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x9e */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0x9f */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xa0 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xa1 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xa2 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xa3 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xa4 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xa5 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xa6 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xa7 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xa8 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xa9 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xaa */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xab */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xac */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xad */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xae */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xaf */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xb0 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xb1 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xb2 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xb3 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xb4 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xb5 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xb6 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xb7 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xb8 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xb9 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xba */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xbb */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xbc */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xbd */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xbe */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xbf */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xc0 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xc1 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xc2 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xc3 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xc4 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xc5 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xc6 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xc7 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xc8 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xc9 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xca */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xcb */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xcc */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xcd */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xce */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xcf */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xd0 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xd1 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xd2 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xd3 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xd4 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xd5 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xd6 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xd7 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xd8 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xd9 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xda */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xdb */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xdc */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xdd */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xde */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xdf */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xe0 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xe1 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xe2 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xe3 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xe4 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xe5 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xe6 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xe7 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xe8 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xe9 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xea */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xeb */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xec */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xed */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xee */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xef */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xf0 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xf1 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xf2 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xf3 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xf4 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xf5 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xf6 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xf7 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xf8 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xf9 */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xfa */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xfb */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xfc */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xfd */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xfe */
+ .word InterruptVectorEntryNop - IVT, 0xf000 /* 0xff */
+
+ /*
+ * Register AX denotes the function that is requested.
+ */
+ .global CsmEntry
+CsmEntry:
+ cli
+
+ /*
+ * Juggle the stack to make to it 'iret'-able.
+ */
+ sub $2, %sp
+ pushf
+ push %bp
+ push %ax
+ mov %sp, %bp
+ mov 8(%bp), %ax
+ mov %ax, 6(%bp)
+ mov 10(%bp), %ax
+ mov %ax, 8(%bp)
+ mov 4(%bp), %ax
+ mov %ax, 10(%bp)
+ pop %ax
+ pop %bp
+ add $2, %sp
+
+ /* Backup stack. */
+ push %bp
+ mov %sp, %bp
+
+ sub $(sizeofEFI_IA32_REGISTER_SET), %sp
+ mov %eax, (offsetofEFI_IA32_REGISTER_SET_E_EAX-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %ebx, (offsetofEFI_IA32_REGISTER_SET_E_EBX-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %ecx, (offsetofEFI_IA32_REGISTER_SET_E_ECX-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %edx, (offsetofEFI_IA32_REGISTER_SET_E_EDX-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %esi, (offsetofEFI_IA32_REGISTER_SET_E_ESI-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %edi, (offsetofEFI_IA32_REGISTER_SET_E_EDI-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %es, (offsetofEFI_IA32_REGISTER_SET_X_DS-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %es, (offsetofEFI_IA32_REGISTER_SET_X_ES-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %fs, (offsetofEFI_IA32_REGISTER_SET_X_FS-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %gs, (offsetofEFI_IA32_REGISTER_SET_X_GS-sizeofEFI_IA32_REGISTER_SET)(%bp)
+
+ /* Translate stack pointer */
+ mov %ss, %eax
+ shll $4, %eax
+ addl %esp, %eax
+
+ /* Set up segment registers. */
+ xor %dx, %dx
+ mov %dx, %ss
+ mov %dx, %ds
+ mov %dx, %es
+ mov %dx, %fs
+ mov %dx, %gs
+ cld
+
+ /* Set up new stack and save miscellaneous registers. */
+ mov $(0x7000 - 0x8), %sp
+ pushl %eax
+ mov %cr3, %ecx
+ pushl %ecx
+
+ /* Point edi to free space. */
+ mov $0x8000, %edi
+
+ /* Zero out the 24KB buffer. */
+ push %di
+ mov $(6*(4096/4)), %ecx
+ xor %eax, %eax
+ cld
+ rep stos %eax,(%di)
+ pop %di
+
+ push %di
+ lea 0x1000(%di), %eax /* Put the address of the Page Directory Pointer Table Entry in to EAX. */
+ mov %eax, %ebx
+ or $(PAGE_PRESENT | PAGE_WRITE), %eax
+ mov %eax, (%edi)
+
+ add $0x1000, %edi
+ xor %esi, %esi
+ xor %ecx, %ecx
+1:
+ cmp $4, %ecx
+ je 4f
+
+ add $0x1000, %edi
+ mov %edi, %eax /* Put the address of the Page Directory in to EAX.*/
+ or $(PAGE_PRESENT | PAGE_WRITE), %eax
+ mov %eax, (%ebx,%ecx,8)
+
+ xor %edx, %edx
+2:
+ cmp $512, %edx
+ je 3f
+
+ mov %esi, %eax
+ or $(PAGE_PRESENT | PAGE_WRITE | PAGE_SIZE), %eax
+ mov %eax, (%edi,%edx,8)
+ add $0x200000, %esi
+
+ inc %edx
+ jmp 2b
+3: inc %ecx
+ jmp 1b
+4:
+ pop %di
+
+ /* Load GDT */
+ addr32 lgdt (GDT.Pointer)
+
+ mov %cr0, %eax
+#define PE_BIT 0x1
+ or $PE_BIT, %eax
+ mov %eax, %cr0
+
+ jmp 1f
+1:
+ /* Setup %ds, %ss and %es to address 4gb of linear memory */
+ mov $(DATA64_SEL), %ax
+ mov %ax, %ds
+ mov %ax, %ss
+ mov %ax, %es
+
+ /* Load a zero length IDT so that any NMI causes a triple fault. */
+ addr32 lidt (IDT.Pointer)
+
+ /* Enter long mode. */
+ mov %edi, %edx /* Point CR3 at the PML4. */
+ mov %edx, %cr3
+
+ mov $0x6a0, %eax /* Set the PAE and PGE bit. */
+ mov %eax, %cr4
+
+ mov $0xC0000080, %ecx /* Read from the EFER MSR. */
+ rdmsr
+ or $0x100, %eax /* Set the LME bit. */
+ wrmsr
+
+ mov %cr0, %ebx /* Activate long mode - */
+ or $0x80000000, %ebx /* - by enabling paging and */
+ mov %ebx, %cr0 /* - protection simultaneously. */
+
+ /* Setup %cs with 64 bit segment */
+ data32 ljmp $CODE64_SEL, $(1f)
+1:
+ .code64
+ /* For good measure reload other segments */
+ mov $DATA64_SEL, %eax
+ mov %eax, %ss
+ mov %eax, %ds
+ mov %eax, %es
+
+ mov 4(%rsp), %rdi
+ call CsmMain
+
+ cli
+ lgdt (GDT.Pointer64)
+ /* Load CS with 16 bit segment and flush the instruction cache. */
+ push $CODE16_SEL
+ push $(2f - 0xf0000)
+ retfq
+
+ .code16
+ /* Disable paging. */
+2: mov %cr0, %edx
+ and $0x7FFFFFFF, %edx
+ mov %edx, %cr0
+
+ /* Flush the TLB. */
+ xor %edx, %edx
+ mov %edx, %cr3
+
+ mov $DATA16_SEL, %edx /* Load DS with 16 bit segment */
+ mov %edx, %ss
+ mov %edx, %ds
+ mov %edx, %es
+ mov %edx, %fs
+ mov %edx, %gs
+
+ addr32 lidt (IVT.Pointer)
+
+ /* Disable protection */
+ mov %cr0, %edx
+ and $0xFFFFFFFE, %edx
+ mov %edx, %cr0
+
+ /* Disable long mode */
+ mov $0xC0000080, %ecx
+ rdmsr
+ btcl $8, %eax
+ wrmsr
+
+ /* Clear PAE and PGE bits. */
+ /*
+ mov %cr4, %eax
+ and $~0xa0, %eax
+ mov %eax, %cr4
+ */
+
+ ljmp $0xf000, $(3f - 0xf0000)
+
+3: xor %dx, %dx
+ mov %dx, %ss
+ mov %dx, %ds
+ mov %dx, %es
+ mov %dx, %fs
+ mov %dx, %gs
+
+ /* Restore stack and miscellaneous registers. */
+ popl %edx
+ mov %edx, %cr3
+
+ popl %edx
+ mov %dx, %sp
+ add $(sizeofEFI_IA32_REGISTER_SET), %sp
+ shrl $16, %edx
+ shll $12, %edx
+ mov %dx, %ss
+
+ mov (offsetofEFI_IA32_REGISTER_SET_E_EAX-sizeofEFI_IA32_REGISTER_SET)(%bp), %eax
+ mov (offsetofEFI_IA32_REGISTER_SET_E_EBX-sizeofEFI_IA32_REGISTER_SET)(%bp), %ebx
+ mov (offsetofEFI_IA32_REGISTER_SET_E_ECX-sizeofEFI_IA32_REGISTER_SET)(%bp), %ecx
+ mov (offsetofEFI_IA32_REGISTER_SET_E_EDX-sizeofEFI_IA32_REGISTER_SET)(%bp), %edx
+ mov (offsetofEFI_IA32_REGISTER_SET_E_ESI-sizeofEFI_IA32_REGISTER_SET)(%bp), %esi
+ mov (offsetofEFI_IA32_REGISTER_SET_E_EDI-sizeofEFI_IA32_REGISTER_SET)(%bp), %edi
+ mov (offsetofEFI_IA32_REGISTER_SET_X_DS-sizeofEFI_IA32_REGISTER_SET)(%bp), %ds
+ mov (offsetofEFI_IA32_REGISTER_SET_X_ES-sizeofEFI_IA32_REGISTER_SET)(%bp), %es
+ mov (offsetofEFI_IA32_REGISTER_SET_X_FS-sizeofEFI_IA32_REGISTER_SET)(%bp), %fs
+ mov (offsetofEFI_IA32_REGISTER_SET_X_GS-sizeofEFI_IA32_REGISTER_SET)(%bp), %gs
+
+ pop %bp
+ iret
+
+ .align 8
+IVT.Pointer:
+ .word 0x3ff
+ .long 0
+
+ .align 8
+IDT:
+IDT.End:
+IDT.Pointer:
+ .word (IDT.End - IDT) /* 16-bit Size (Limit) of IDT. */
+ .long (IDT) /* 32-bit Base Address of IDT. */
+
+ .align 8
+GDT:
+GDT.NULL: /* Null Descriptor - should be present. */
+ .word 0x0000
+ .word 0x0000
+ .byte 0x0
+ .byte 0x0
+ .byte 0x0
+ .byte 0x0
+GDT.Code64: /* 64-bit code descriptor. */
+ .word 0xffff /* limit (low) */
+ .word 0x0000 /* base (low) */
+ .byte 0x0 /* base (middle) */
+ .byte 0x9b /* present, ring 0, type='code, read, accessed' */
+ .byte 0xaf /* G=1, 64-bit code segment, limit (high) */
+ .byte 0x0 /* base (high) */
+GDT.Data64: /* 64-bit data descriptor. */
+ .word 0xffff /* limit (low */
+ .word 0x0000 /* base (low) */
+ .byte 0x0 /* base (middle) */
+ .byte 0x93 /* present, ring 0, type='data, read/write,accessed' */
+ .byte 0xcf /* G=1, B=1, limit (high) */
+ .byte 0x0 /* base (high) */
+GDT.Code16: /* 16-bit code descriptor. */
+ .word 0xffff /* limit (low) */
+ .word 0x0000 /* base (low) */
+ .byte 0xf /* base (middle) */
+ .byte 0x9b /* present, ring 0, type='code, read, accessed' */
+ .byte 0x8f /* G=1, limit (high) */
+ .byte 0x0 /* base (high) */
+GDT.Data16: /* 16-bit data descriptor. */
+ .word 0xffff /* limit (low) */
+ .word 0x0000 /* base (low) */
+ .byte 0x0 /* base (middle) */
+ .byte 0x93 /* present, ring 0, type='data, read/write,accessed' */
+ .byte 0x8f /* G=1, B=0, limit (high) */
+ .byte 0x0 /* base (high) */
+GDT.End:
+
+GDT.Pointer:
+ .word (GDT.End - GDT) - 1 /* 16-bit Size (Limit) of GDT. */
+ .long (GDT) /* 32-bit Base Address of GDT. */
+GDT.Pointer64:
+ .word (GDT.End - GDT) - 1 /* 16-bit Size (Limit) of GDT. */
+ .quad (GDT) /* 64-bit Base Address of GDT. */
+
+ .code16
+RealToLong:
+ cli
+
+ /* Backup stack. */
+ push %ebp
+ mov %sp, %bp
+
+ sub $(sizeofEFI_IA32_REGISTER_SET), %sp
+ mov %eax, (offsetofEFI_IA32_REGISTER_SET_E_EAX-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %ebx, (offsetofEFI_IA32_REGISTER_SET_E_EBX-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %ecx, (offsetofEFI_IA32_REGISTER_SET_E_ECX-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %edx, (offsetofEFI_IA32_REGISTER_SET_E_EDX-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %esi, (offsetofEFI_IA32_REGISTER_SET_E_ESI-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %edi, (offsetofEFI_IA32_REGISTER_SET_E_EDI-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %ds, (offsetofEFI_IA32_REGISTER_SET_X_DS-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %es, (offsetofEFI_IA32_REGISTER_SET_X_ES-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %fs, (offsetofEFI_IA32_REGISTER_SET_X_FS-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov %gs, (offsetofEFI_IA32_REGISTER_SET_X_GS-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ xor %eax, %eax
+ mov (0)(%bp), %eax
+ mov %eax, (offsetofEFI_IA32_REGISTER_SET_X_BP-sizeofEFI_IA32_REGISTER_SET)(%bp)
+ mov (4+4+2+2)(%bp), %ax
+ mov %eax, (offsetofEFI_IA32_REGISTER_SET_X_FLAGS-sizeofEFI_IA32_REGISTER_SET)(%bp)
+
+ /* Save stack pointer and segment */
+ mov %ss, %eax
+ shll $16, %eax
+ addl %esp, %eax
+
+ /* Set up %ds so we can access the GDT. */
+ mov $0xf000, %dx
+ mov %dx, %ds
+
+ /* Load GDT */
+ addr32 lgdt (GDT.Pointer - 0xf0000)
+
+ /* Enter protected mode. */
+ mov %cr0, %edx
+#define PE_BIT 0x1
+ or $PE_BIT, %edx
+ mov %edx, %cr0
+
+ jmp 1f
+1:
+ /* Setup %ds, %ss and %es to address 4gb of linear memory */
+ mov $(DATA16_SEL), %dx
+ mov %dx, %ds
+ mov %dx, %ss
+ mov %dx, %es
+
+ /* Set up new stack and save miscellaneous registers. */
+ addr32 mov mStack, %esp
+ mov %esp, %ebp
+ sub $8, %esp
+ mov %eax, -4(%ebp)
+ mov %cr3, %ecx
+ mov %ecx, -8(%ebp)
+
+ /* Load a zero length IDT so that any NMI causes a triple fault. */
+ addr32 lidt (IDT.Pointer)
+
+ /* Enter long mode. */
+ addr32 mov mPML4, %edx /* Point CR3 at the PML4. */
+ mov %edx, %cr3
+
+ mov $0x6a0, %eax /* Set the PAE and PGE bit. */
+ mov %eax, %cr4
+
+ mov $0xC0000080, %ecx /* Read from the EFER MSR. */
+ rdmsr
+ or $0x100, %eax /* Set the LME bit. */
+ wrmsr
+
+ mov %cr0, %ebx /* Activate long mode - */
+ or $0x80000000, %ebx /* - by enabling paging and */
+ mov %ebx, %cr0 /* - protection simultaneously. */
+
+ /* Setup %cs with 64 bit segment */
+ data32 ljmp $CODE64_SEL, $(1f)
+1:
+ .code64
+ /* For good measure reload other segments */
+ mov $DATA64_SEL, %eax
+ mov %eax, %ss
+ mov %eax, %ds
+ mov %eax, %es
+
+ lidt mIDT
+
+ /* Translate stack */
+ mov 4(%rsp), %eax
+ mov %rax, %rdi
+ shll $16, %eax
+ shrl $16, %eax
+ shrl $16, %edi
+ shll $4, %edi
+ add %eax, %edi
+ mov sizeofEFI_IA32_REGISTER_SET+4(%rdi), %eax
+ call *%rax
+
+LongToReal:
+ cli
+ lgdt (GDT.Pointer64)
+
+ /* Load CS with 16 bit segment and flush the instruction cache. */
+ push $CODE16_SEL
+ push $(2f - 0xf0000)
+ retfq
+
+ .code16
+ /* Disable paging. */
+2: mov %cr0, %edx
+ and $0x7FFFFFFF, %edx
+ mov %edx, %cr0
+
+ /* Flush the TLB. */
+ xor %edx, %edx
+ mov %edx, %cr3
+
+ mov $DATA16_SEL, %edx /* Load DS with 16 bit segment */
+ mov %edx, %ss
+ mov %edx, %ds
+ mov %edx, %es
+ mov %edx, %fs
+ mov %edx, %gs
+
+ addr32 lidt (IVT.Pointer)
+
+ /* Disable protection. */
+ mov %cr0, %edx
+ and $0xFFFFFFFE, %edx
+ mov %edx, %cr0
+
+ /* Disable long mode */
+ mov $0xC0000080, %ecx
+ rdmsr
+ btcl $8, %eax
+ wrmsr
+
+ /* Clear PAE and PGE bits. */
+ /*
+ mov %cr4, %eax
+ and $~0xA0, %eax
+ mov %eax, %cr4
+ */
+
+ ljmp $0xf000, $(3f - 0xf0000)
+
+3: xor %dx, %dx
+ mov %dx, %ss
+ mov %dx, %ds
+ mov %dx, %es
+ mov %dx, %fs
+ mov %dx, %gs
+
+ /* Restore stack and miscellaneous registers. */
+ mov %esp, %ebp
+ mov (%ebp), %edx
+ mov %edx, %cr3
+ mov 4(%ebp), %edx
+
+ movzx %dx, %esp
+ add $(sizeofEFI_IA32_REGISTER_SET), %sp
+ mov %sp, %bp
+ shrl $16, %edx
+ mov %dx, %ss
+
+ mov (offsetofEFI_IA32_REGISTER_SET_X_FLAGS-sizeofEFI_IA32_REGISTER_SET)(%bp), %eax
+ mov %ax, (4+4+2+2)(%bp)
+ mov (offsetofEFI_IA32_REGISTER_SET_X_BP-sizeofEFI_IA32_REGISTER_SET)(%bp), %eax
+ mov %eax, (0)(%bp)
+ mov (offsetofEFI_IA32_REGISTER_SET_E_EAX-sizeofEFI_IA32_REGISTER_SET)(%bp), %eax
+ mov (offsetofEFI_IA32_REGISTER_SET_E_EBX-sizeofEFI_IA32_REGISTER_SET)(%bp), %ebx
+ mov (offsetofEFI_IA32_REGISTER_SET_E_ECX-sizeofEFI_IA32_REGISTER_SET)(%bp), %ecx
+ mov (offsetofEFI_IA32_REGISTER_SET_E_EDX-sizeofEFI_IA32_REGISTER_SET)(%bp), %edx
+ mov (offsetofEFI_IA32_REGISTER_SET_E_ESI-sizeofEFI_IA32_REGISTER_SET)(%bp), %esi
+ mov (offsetofEFI_IA32_REGISTER_SET_E_EDI-sizeofEFI_IA32_REGISTER_SET)(%bp), %edi
+ mov (offsetofEFI_IA32_REGISTER_SET_X_DS-sizeofEFI_IA32_REGISTER_SET)(%bp), %ds
+ mov (offsetofEFI_IA32_REGISTER_SET_X_ES-sizeofEFI_IA32_REGISTER_SET)(%bp), %es
+ mov (offsetofEFI_IA32_REGISTER_SET_X_FS-sizeofEFI_IA32_REGISTER_SET)(%bp), %fs
+ mov (offsetofEFI_IA32_REGISTER_SET_X_GS-sizeofEFI_IA32_REGISTER_SET)(%bp), %gs
+
+ pop %ebp
+ add $4, %sp /* throw away argument */
+ iret
+
+ .code64
+.global JumpLongModeToRealMode
+JumpLongModeToRealMode:
+ movzx %di, %rsp
+ jmp LongToReal
+
+ .code64
+InterruptVectorNop:
+ ret
+
+ .code16
+InterruptVectorEntry0x00:
+ data32 push $(InterruptVector0x00)
+ jmp RealToLong
+InterruptVectorEntry0x01:
+ data32 push $(InterruptVector0x01)
+ jmp RealToLong
+InterruptVectorEntry0x02:
+ data32 push $(InterruptVector0x02)
+ jmp RealToLong
+InterruptVectorEntry0x03:
+ data32 push $(InterruptVector0x03)
+ jmp RealToLong
+InterruptVectorEntry0x04:
+ data32 push $(InterruptVector0x04)
+ jmp RealToLong
+InterruptVectorEntry0x05:
+ data32 push $(InterruptVector0x05)
+ jmp RealToLong
+InterruptVectorEntry0x06:
+ data32 push $(InterruptVector0x06)
+ jmp RealToLong
+InterruptVectorEntry0x07:
+ data32 push $(InterruptVector0x07)
+ jmp RealToLong
+InterruptVectorEntry0x08:
+ data32 push $(InterruptVector0x08)
+ jmp RealToLong
+InterruptVectorEntry0x09:
+ data32 push $(InterruptVector0x09)
+ jmp RealToLong
+InterruptVectorEntry0x0a:
+ data32 push $(InterruptVector0x0a)
+ jmp RealToLong
+InterruptVectorEntry0x0b:
+ data32 push $(InterruptVector0x0b)
+ jmp RealToLong
+InterruptVectorEntry0x0c:
+ data32 push $(InterruptVector0x0c)
+ jmp RealToLong
+InterruptVectorEntry0x0d:
+ data32 push $(InterruptVector0x0d)
+ jmp RealToLong
+InterruptVectorEntry0x0e:
+ data32 push $(InterruptVector0x0e)
+ jmp RealToLong
+InterruptVectorEntry0x0f:
+ data32 push $(InterruptVector0x0f)
+ jmp RealToLong
+InterruptVectorEntry0x10:
+ data32 push $(InterruptVector0x10)
+ jmp RealToLong
+InterruptVectorEntry0x11:
+ data32 push $(InterruptVector0x11)
+ jmp RealToLong
+InterruptVectorEntry0x12:
+ data32 push $(InterruptVector0x12)
+ jmp RealToLong
+InterruptVectorEntry0x13:
+ data32 push $(InterruptVector0x13)
+ jmp RealToLong
+InterruptVectorEntry0x15:
+ data32 push $(InterruptVector0x15)
+ jmp RealToLong
+InterruptVectorEntry0x16:
+ data32 push $(InterruptVector0x16)
+ jmp RealToLong
+InterruptVectorEntry0x1a:
+ data32 push $(InterruptVector0x1a)
+ jmp RealToLong
+InterruptVectorEntry0x40:
+ data32 push $(InterruptVector0x08)
+ jmp RealToLong
+InterruptVectorEntry0x41:
+ data32 push $(InterruptVector0x09)
+ jmp RealToLong
+InterruptVectorEntryNop:
+ data32 push $(InterruptVectorNop)
+ jmp RealToLong
+
+
+ .code64
+ .global X64InterruptVectorEntry0x40
+X64InterruptVectorEntry0x40:
+ pushq %rbp
+ movq %rsp, %rbp
+
+ pushfq
+ pushq %rdi
+ pushq %rsi
+ pushq %rax
+ pushq %rbx
+ pushq %rcx
+ pushq %rdx
+ pushq %r8
+ pushq %r9
+ pushq %r10
+ pushq %r11
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ call InterruptVector0x08
+
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %r11
+ popq %r10
+ popq %r9
+ popq %r8
+ popq %rdx
+ popq %rcx
+ popq %rbx
+ popq %rax
+ popq %rsi
+ popq %rdi
+ popfq
+
+ movq %rbp, %rsp
+ popq %rbp
+ iretq
+
+ .global X64InterruptVectorEntry0x41
+X64InterruptVectorEntry0x41:
+ pushq %rbp
+ movq %rsp, %rbp
+
+ pushfq
+ pushq %rdi
+ pushq %rsi
+ pushq %rax
+ pushq %rbx
+ pushq %rcx
+ pushq %rdx
+ pushq %r8
+ pushq %r9
+ pushq %r10
+ pushq %r11
+ pushq %r12
+ pushq %r13
+ pushq %r14
+ pushq %r15
+
+ call InterruptVector0x09
+
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %r11
+ popq %r10
+ popq %r9
+ popq %r8
+ popq %rdx
+ popq %rcx
+ popq %rbx
+ popq %rax
+ popq %rsi
+ popq %rdi
+ popfq
+
+ movq %rbp, %rsp
+ popq %rbp
+ iretq
+
diff --git BhyvePkg/Csm/BhyveCsm16/Bios.c BhyvePkg/Csm/BhyveCsm16/Bios.c
new file mode 100644
index 0000000..3cfedf6
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Bios.c
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) 2015, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+#include
+
+#include "BhyveCsm16.h"
+
+#include "Debug.h"
+#include "Edd.h"
+#include "Printf.h"
+#include "String.h"
+
+#pragma pack(1)
+typedef struct {
+ UINT64 BaseAddr;
+ UINT64 Length;
+ UINT32 Type;
+} EFI_E820_ENTRY64;
+#pragma pack()
+
+/*
+ * Equipment Determination
+ */
+VOID
+InterruptVector0x11(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x11()\n"));
+ DEBUG (("XXX InterruptVector0x11() Regs->H.AL=0%x\n", Regs->H.AL));
+ DEBUG (("XXX InterruptVector0x11() Regs->H.AH=0%x\n", Regs->H.AH));
+ DEBUG (("XXX InterruptVector0x11() Regs->X.AX=0%x\n", Regs->X.AX));
+ Regs->X.AX = 0;
+}
+
+/*
+ * Conventional Memory Size
+ */
+VOID
+InterruptVector0x12(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x12()\n"));
+ DEBUG (("XXX InterruptVector0x12() Regs->H.AL=0%x\n", Regs->H.AL));
+ DEBUG (("XXX InterruptVector0x12() Regs->H.AH=0%x\n", Regs->H.AH));
+ DEBUG (("XXX InterruptVector0x12() Regs->X.AX=0%x\n", Regs->X.AX));
+
+ /*
+ * Report just 640kb which isn't quite true.
+ */
+ Regs->E.EFlags.CF = 0;
+ Regs->E.EAX = 640;
+}
+
+VOID
+InterruptVector0x13(EFI_IA32_REGISTER_SET *Regs)
+{
+ EFI_STATUS Status;
+ EDD_DEVICE_ADDRESS_PACKET *AddressPacket;
+ EDD_DRIVE_PARAMETERS *DriveParameters;
+ EDD_DEVICE_SPECIFICATION_PACKET *SpecificationPacket;
+ UINT16 DriveNumber;
+ UINT16 NumberOfHeads, NumberOfCylinders, NumberOfSectorsPerTrack;
+ UINT16 Head, Cylinder, Sector;
+ EFI_LBA Lba;
+ UINT16 NumberOfBlocks;
+
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x13()\n"));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x13() Regs->H.AL=0%x\n", Regs->H.AL));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x13() Regs->H.AH=0%x\n", Regs->H.AH));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x13() Regs->X.AX=0%x\n", Regs->X.AX));
+
+
+ switch (Regs->H.AH) {
+ case 0x00: /* Reset */
+ Regs->E.EFlags.CF = 0;
+ break;
+ case 0x02: /* Read */
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x13() Read Drive=0x%x Pointer=0x%x:0x%x\n", Regs->H.DL, Regs->E.ES, Regs->X.BX));
+ DPRINTF (DBG_VERB, ("XXX Segment 0x%x Offset=0x%x\n", Regs->E.ES, Regs->X.BX));
+ DriveNumber = Regs->H.DL;
+ if (DriveNumber != mDriveNumber ||
+ mDeviceBlockIo->Media->RemovableMedia) {
+ Regs->E.EFlags.CF = 1; /* Error */
+ Regs->H.AH = 0;
+ } else {
+ NumberOfBlocks = Regs->H.AL;
+ Head = (Regs->H.DH & 0x3f);
+ Cylinder = (Regs->H.CL & 0xc0) << 2;
+ Cylinder |= Regs->H.CH & 0xff;
+ Sector = (Regs->H.CL & 0x3f);
+ DPRINTF (DBG_INFO, ("XXX NumberOfBlocks 0x%x\n", NumberOfBlocks));
+ DPRINTF (DBG_INFO, ("XXX Head = %d Cylinder = %d Sector = %d\n", Head, Cylinder, Sector));
+
+ NumberOfHeads = 16;
+ NumberOfSectorsPerTrack = 63;
+ NumberOfCylinders = ((mDeviceBlockIo->Media->LastBlock + 1) * mDeviceBlockIo->Media->BlockSize) / (NumberOfHeads * NumberOfSectorsPerTrack);
+ if (NumberOfCylinders > 16383) {
+ NumberOfCylinders = 16383;
+ }
+
+ DPRINTF (DBG_INFO, ("XXX Heads = %d Cylinders = %d Sectors = %d\n", NumberOfHeads, NumberOfCylinders, NumberOfSectorsPerTrack));
+
+ Lba = (Cylinder * NumberOfHeads + Head) * NumberOfSectorsPerTrack + (Sector - 1);
+ DPRINTF (DBG_INFO, ("XXX Lba = 0x%lx\n", Lba));
+ Status = mDeviceBlockIo->ReadBlocks(mDeviceBlockIo, mDeviceBlockIo->Media->MediaId, Lba, NumberOfBlocks * mDeviceBlockIo->Media->BlockSize, (VOID *)(UINT64)((Regs->E.ES << 4) + (UINT16)Regs->X.BX));
+
+ DPRINTF (DBG_INFO, ("XXX Status = 0x%x\n", Status));
+ Regs->E.EFlags.CF = 0;
+ Regs->H.AH = 0;
+ }
+ break;
+ case 0x08: /* Drive Parameters */
+ DPRINTF (DBG_INFO, ("XXX InterruptVector0x13() Drive Parameters Drive=0x%x\n", Regs->H.DL));
+ DriveNumber = Regs->H.DL;
+ if (DriveNumber != mDriveNumber ||
+ mDeviceBlockIo->Media->RemovableMedia) {
+ Regs->E.EFlags.CF = 1; /* Error */
+ Regs->H.AH = 0xff;
+ Regs->H.CL = 1;
+ Regs->H.DH = 1;
+ Regs->H.CH = 1;
+ DPRINTF (DBG_INFO, (" Drive Params error x\n"));
+ } else {
+ UINT16 NumberOfHeads, NumberOfCylinders, NumberOfSectorsPerTrack;
+ UINT16 MaxHead, MaxCylinder, MaxSector;
+
+ DPRINTF (DBG_INFO, (" Drive Params call\n"));
+
+ NumberOfHeads = 16;
+ NumberOfSectorsPerTrack = 63;
+ NumberOfCylinders = ((mDeviceBlockIo->Media->LastBlock + 1) * mDeviceBlockIo->Media->BlockSize) / (NumberOfHeads * NumberOfSectorsPerTrack);
+ if (NumberOfCylinders > 16383) {
+ NumberOfCylinders = 16383;
+ }
+
+ MaxHead = NumberOfHeads - 1;
+ MaxCylinder = NumberOfCylinders - 1;
+ MaxSector = NumberOfSectorsPerTrack; /* index starts with 1! */
+
+ Regs->E.EFlags.CF = 0;
+ Regs->E.EAX = 0;
+ Regs->H.DL = mDriveNumber;
+ Regs->H.DH = (MaxHead & 0x3f);
+ Regs->H.CL = ((MaxCylinder >> 2) & 0xc0) | (MaxSector & 0x3f);
+ Regs->H.CH = MaxCylinder & 0xff;
+ }
+ break;
+ case 0x15: /* DASD Type */
+ DPRINTF (DBG_INFO, ("XXX InterruptVector0x13 DASD Type Drive=0x%x\n", Regs->H.DL));
+ DriveNumber = Regs->H.DL;
+ if (DriveNumber != mDriveNumber) {
+ Regs->E.EFlags.CF = 0;
+ Regs->H.AH = 0x0; /* Drive not present */
+ } else {
+ Regs->E.EFlags.CF = 0;
+ Regs->H.AH = 0x3; /* Fixed disk present */
+ }
+ break;
+ case 0x41: /* Check Extensions Present */
+ DPRINTF (DBG_INFO, ("XXX InterruptVector0x13() Check Extensions Present Drive=0x%x Regs->X.BX=0%x\n", Regs->H.DL, Regs->X.BX));
+ DriveNumber = Regs->H.DL;
+ if (DriveNumber != mDriveNumber || Regs->X.BX != 0x55aa) {
+ Regs->E.EFlags.CF = 1;
+ Regs->H.AH = 0x1; /* Invalid Command */
+ } else {
+ Regs->E.EFlags.CF = 0;
+ Regs->H.AH = 0x21; /* EDD 1.1 */
+ Regs->X.BX = 0xaa55;
+ if (mDeviceBlockIo->Media->RemovableMedia) {
+ /* Fixed disk access & Drive locking and ejecting & Enhanced
+ * disk drive support */
+ Regs->X.CX = 0x7;
+ } else {
+ /* Fixed disk access & Enhanced disk drive support */
+ Regs->X.CX = 0x5;
+ }
+ }
+ break;
+ case 0x42: /* Extended Read */
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x13() Extended Read Drive=0%x Packet=0x%x:0x%x\n", Regs->H.DL, Regs->E.DS, Regs->X.SI));
+ AddressPacket = (EDD_DEVICE_ADDRESS_PACKET *)(UINT64)((Regs->X.DS << 4) + (Regs->X.SI));
+
+ DPRINTF (DBG_VERB, ("XXX Packet->NumberOfBlocks=%d\n", AddressPacket->NumberOfBlocks));
+ DPRINTF (DBG_VERB, ("XXX Packet->Lba=0x%llx\n", AddressPacket->Lba));
+ DPRINTF (DBG_VERB, ("XXX Packet->SegOffset=0x%x\n", AddressPacket->SegOffset));
+ DPRINTF (DBG_VERB, ("XXX Packet->TransferBuffer=0x%llx\n", AddressPacket->TransferBuffer));
+ DPRINTF (DBG_VERB, ("XXX Segment 0x%x Offset=0x%x %x\n", AddressPacket->SegOffset >> 16, AddressPacket->SegOffset & 0xffff, (((AddressPacket->SegOffset >> 16) << 4) + (UINT16)AddressPacket->SegOffset)));
+
+ Status = mDeviceBlockIo->ReadBlocks(mDeviceBlockIo, mDeviceBlockIo->Media->MediaId, AddressPacket->Lba, AddressPacket->NumberOfBlocks * mDeviceBlockIo->Media->BlockSize, (VOID *)(UINT64)(((AddressPacket->SegOffset >> 16) << 4) + (UINT16)AddressPacket->SegOffset));
+
+ DPRINTF (DBG_VERB, ("XXX Status = 0x%x\n", Status));
+ Regs->E.EFlags.CF = 0;
+ Regs->H.AH = 0;
+ break;
+ case 0x48: /* Extended Drive Parameters */
+ DPRINTF (DBG_INFO, ("XXX InterruptVector0x13() Extended Drive Parameters Drive=0%x Packet=0x%x:0x%x\n", Regs->H.DL, Regs->E.DS, Regs->X.SI));
+ DriveNumber = Regs->H.DL;
+ DriveParameters = (EDD_DRIVE_PARAMETERS *)(UINT64)((Regs->X.DS << 4) + (Regs->X.SI));
+ if (DriveNumber != mDriveNumber ||
+ DriveParameters->StructureSize < 26) {
+ Regs->E.EFlags.CF = 1; /* Error */
+ Regs->H.AH = 0;
+ } else {
+ DriveParameters->Flags = 0;
+ if (mDeviceBlockIo->Media->RemovableMedia) {
+ DriveParameters->Flags |= (EDD_DEVICE_REMOVABLE | EDD_DEVICE_CHANGE | EDD_DEVICE_LOCKABLE);
+ } else {
+ NumberOfHeads = 16;
+ NumberOfSectorsPerTrack = 63;
+ NumberOfCylinders = ((mDeviceBlockIo->Media->LastBlock + 1) * mDeviceBlockIo->Media->BlockSize) / (NumberOfHeads * NumberOfSectorsPerTrack);
+ if (NumberOfCylinders > 16383) {
+ NumberOfCylinders = 16383;
+ }
+
+ DriveParameters->MaxCylinders = NumberOfCylinders;
+ DriveParameters->MaxHeads = NumberOfHeads;
+ DriveParameters->SectorsPerTrack = NumberOfSectorsPerTrack;
+
+ DriveParameters->Flags |= EDD_GEOMETRY_VALID;
+ }
+
+ DriveParameters->PhysicalSectors = mDeviceBlockIo->Media->LastBlock + 1;
+ DriveParameters->BytesPerSector = mDeviceBlockIo->Media->BlockSize;
+ DriveParameters->Fdpt = 0xffffffff;
+
+ Regs->E.EFlags.CF = 0;
+ Regs->H.AH = 0;
+ }
+ break;
+ case 0x4b: /* Terminate Disk Emulation */
+ switch (Regs->H.AL) {
+ case 0x0: /* Return Status and Terminate Emulation */
+ Regs->E.EFlags.CF = 1; /* System not in emulation mode. */
+ break;
+ case 0x1: /* Return Status only, Do Not Terminate Emulation */
+ SpecificationPacket = (EDD_DEVICE_SPECIFICATION_PACKET *)(UINT64)((Regs->X.DS << 4) + (Regs->X.SI));
+ SpecificationPacket->BootMediaType = 0; /* No Emulation */
+ if (mDeviceBlockIo->Media->RemovableMedia && mDeviceBlockIo->Media->ReadOnly) {
+ SpecificationPacket->DriveNumber = mDriveNumber;
+ } else {
+ /* Definitely it's a "no emulation" drive. */
+ SpecificationPacket->DriveNumber = 0xff;
+ }
+ Regs->E.EFlags.CF = 0;
+ Regs->X.AX = 0;
+ break;
+ }
+ break;
+ default:
+ DPRINTF (DBG_CRIT, ("!!! unhandled int13 %x\n", Regs->H.AH));
+ }
+}
+
+VOID
+InterruptVector0x15(EFI_IA32_REGISTER_SET *Regs)
+{
+ UINT32 Signature;
+ UINT32 Continuation;
+ VOID *BufferPointer;
+ UINT32 BufferLength;
+ UINTN Length;
+
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x15()\n"));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x15() Regs->H.AL=0%x\n", Regs->H.AL));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x15() Regs->H.AH=0%x\n", Regs->H.AH));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x15() Regs->X.AX=0%x\n", Regs->X.AX));
+
+
+ switch (Regs->H.AH) {
+ case 0x00:
+ switch (Regs->H.AL) {
+ case 0xc0: /* Byte-swapped Return System Configuration Parameters */
+ /* Work around grub 0.97 bug with ah/al swapped */
+ Regs->E.EFlags.CF = 1;
+ Regs->H.AH = 0x86;
+ break;
+ default:
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x15 AH=0x00 unhandled\n"));
+ break;
+ }
+ break;
+ case 0x24:
+ switch (Regs->H.AL) {
+ case 0x00: /* Disable A20 */
+ Regs->E.EFlags.CF = 0;
+ Regs->H.AH = 0;
+ break;
+ case 0x01: /* Enable A20 */
+ Regs->E.EFlags.CF = 0;
+ Regs->H.AH = 0;
+ break;
+ default:
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x15 AH=0x24 unhandled\n"));
+ break;
+ }
+ break;
+ case 0x53:
+ switch (Regs->H.AL) {
+ case 0x0: /* Advanced Power Management Installation Check */
+ /*
+ * APM not present
+ */
+ Regs->E.EFlags.CF = 1;
+ Regs->E.EAX = 0x86;
+ break;
+ case 0x4: /* Advanced Power Management Interface Disconnect */
+ /*
+ * Interface not connected
+ */
+ Regs->E.EFlags.CF = 1;
+ Regs->E.EAX = 0x03;
+ break;
+ default:
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x15 AH=0x53 unhandled\n"));
+ break;
+ }
+ break;
+ case 0x88: /* Get Extended Memory Size */
+ DPRINTF (DBG_INFO, ("XXX Get Extended Memory Size\n"));
+ /*
+ * Report 15mb contiguous starting at 1024k as available which
+ * isn't quite true.
+ */
+ Regs->E.EFlags.CF = 0;
+ Regs->E.EAX = 15360;
+ break;
+ case 0xc0: /* Return System Configuration Parameters */
+ /*
+ * Not supported.
+ */
+ Regs->H.AH = 0x86;
+ Regs->E.EFlags.CF = 1;
+ break;
+ case 0xe8:
+ switch (Regs->H.AL) {
+ case 0x20: /* Query System Address Map */
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x15() Regs->X.EBX=0%x\n", Regs->E.EBX));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x15() Regs->X.ECX=0%x\n", Regs->E.ECX));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x15() Regs->X.EDX=0%x\n", Regs->E.EDX));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x15() Regs->X.ES=0%x\n", Regs->X.ES));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x15() Regs->X.DI=0%x\n", Regs->X.DI));
+
+ Signature = Regs->E.EDX;
+ BufferPointer = (VOID *)(UINT64)((Regs->X.ES << 4) + (Regs->X.DI));
+ BufferLength = Regs->E.ECX;
+ Continuation = Regs->E.EBX;
+
+ if (Signature == SIGNATURE_32 ('P', 'A', 'M', 'S') &&
+ BufferLength >= sizeof (EFI_E820_ENTRY64) &&
+ Continuation < mEfiCompatibility16Table.E820Length) {
+ EFI_E820_ENTRY64 *EfiE820Entry64;
+
+ EfiE820Entry64 = (EFI_E820_ENTRY64 *)(UINT64)(mEfiCompatibility16Table.E820Pointer + Continuation);
+
+ CopyMem (BufferPointer,
+ EfiE820Entry64,
+ sizeof (EFI_E820_ENTRY64));
+ Continuation += sizeof (EFI_E820_ENTRY64);
+ if (mEfiCompatibility16Table.E820Length <= Continuation) {
+ Continuation = 0;
+ }
+
+ Regs->E.EFlags.CF = 0;
+ Regs->E.EAX = SIGNATURE_32 ('P', 'A', 'M', 'S');
+ Regs->E.ECX = sizeof (EFI_E820_ENTRY64);
+ Regs->E.EBX = Continuation;
+ Regs->E.EDX = 0;
+ } else {
+ Regs->E.EFlags.CF = 1;
+ Regs->E.EAX = 0;
+ }
+ break;
+ default:
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x15 AH=0xe8 unhandled\n"));
+ break;
+ }
+ break;
+ case 0xec:
+ switch (Regs->H.AL) {
+ case 0x00: /* Detect Target Operating Mode */
+ DPRINTF (DBG_VERB, ("XXX 0x15 - Detect Op Mode Regs->X.EBX=0%x\n", Regs->E.EBX));
+ switch (Regs->H.BL) {
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ Regs->H.AH = 0x00;
+ Regs->E.EFlags.CF = 0;
+ break;
+ default:
+ Regs->H.AH = 0x00;
+ Regs->E.EFlags.CF = 1;
+ break;
+ }
+ break;
+ default:
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x15 AH=0xec unhandled\n"));
+ break;
+ }
+ break;
+ case 0x86:
+ DPRINTF (DBG_VERB, ("XXX 0x15 - 0x86 wait\n"));
+ Regs->H.AL = 0x00;
+ Regs->E.EFlags.CF = 0;
+ break;
+ default:
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x15 unhandled AH %x AL %x\n", Regs->H.AH, Regs->H.AL));
+ break;
+ }
+}
+
+/*
+ * Real-Time Clock & PCI
+ */
+VOID
+InterruptVector0x1a(EFI_IA32_REGISTER_SET *Regs)
+{
+ EFI_TIME BootTime;
+
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x1a() Regs->H.AL=0%x\n", Regs->H.AL));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x1a() Regs->H.AH=0%x\n", Regs->H.AH));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x1a() Regs->X.AX=0%x\n", Regs->X.AX));
+
+ switch (Regs->H.AH) {
+ case 0x0: /* Get RTC Counter */
+ //DPRINTF (DBG_VERB, ("XXX InterruptVector0x1a() Get RTC Count\n"));
+ Regs->H.AL = 0;
+ Regs->X.CX = (mBdaPtr->TimerCounter) >> 16;
+ Regs->X.DX = (mBdaPtr->TimerCounter) & 0xFFFF;
+ break;
+ case 0x2: /* Get Real-Time Clock Time */
+ //DPRINTF (DBG_VERB, ("XXX InterruptVector0x1a() Get Real-Time Clock Time\n"));
+ gRT->GetTime (&BootTime, NULL);
+ Regs->H.CH = DecimalToBcd8(BootTime.Hour);
+ Regs->H.CL = BootTime.Minute;
+ Regs->H.DH = BootTime.Second;
+ Regs->H.DL = BootTime.Daylight ? 1 : 0;
+ Regs->X.Flags.CF = 0;
+ break;
+ case 0x4: /* Read Real-Time Clock Date */ // XXX Leon
+ gRT->GetTime (&BootTime, NULL);
+ Regs->H.CH = DecimalToBcd8(20);
+ Regs->H.CL = DecimalToBcd8((UINT8)(BootTime.Year-2000));
+ Regs->H.DH = DecimalToBcd8(BootTime.Month);
+ Regs->H.DL = DecimalToBcd8(BootTime.Day);
+ Regs->X.Flags.CF = 0;
+ break;
+ case 0xB1:
+ //DPRINTF (DBG_VERB, ("XXX InterruptVector0x1a() 0xB1 Regs->H.AL=0x%x\n", Regs->H.AL));
+ Regs->E.EDX = SIGNATURE_32 ('P', 'C', 'I', ' ');
+ Regs->H.AH = 0x0;
+ Regs->H.AL = 0x0;
+ Regs->H.BL = 0x02;
+ Regs->H.BH = 0x10;
+ Regs->X.Flags.CF = 0;
+ break;
+ case 0xBB:
+ // TPM
+ Regs->E.EAX = 0;
+ break;
+ default:
+ DPRINTF (DBG_WARN, ("XXXX int1a unhandled %x\n", Regs->H.AH));
+ break;
+ }
+}
+
+VOID
+InterruptVector0x08(EFI_IA32_REGISTER_SET *Regs)
+{
+ EFI_TIME BootTime;
+ UINT32 LocalTime;
+
+ //DPRINTF (DBG_VERB, ("XXX InterruptVector0x08()\n"));
+
+ gRT->GetTime (&BootTime, NULL);
+ LocalTime = BootTime.Hour * 3600 + BootTime.Minute * 60 + BootTime.Second;
+
+ //
+ // Multiply result by 18.2 for number of ticks since midnight.
+ // Use 182/10 to avoid floating point math.
+ //
+ LocalTime = (LocalTime * 182) / 10;
+ mBdaPtr->TimerCounter = LocalTime;
+
+ mLegacy8259->EndOfInterrupt (mLegacy8259, Efi8259Irq0);
+}
+
+VOID
+InterruptVector0x0a(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x0a()\n"));
+
+ mLegacy8259->EndOfInterrupt (mLegacy8259, Efi8259Irq2);
+}
+
+VOID
+InterruptVector0x0b(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x0b()\n"));
+
+ mLegacy8259->EndOfInterrupt (mLegacy8259, Efi8259Irq3);
+}
+
+VOID
+InterruptVector0x0c(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x0c()\n"));
+
+ mLegacy8259->EndOfInterrupt (mLegacy8259, Efi8259Irq4);
+}
+
+VOID
+InterruptVector0x0d(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x0d()\n"));
+
+ mLegacy8259->EndOfInterrupt (mLegacy8259, Efi8259Irq5);
+}
+
+VOID
+InterruptVector0x0e(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x0e()\n"));
+
+ mLegacy8259->EndOfInterrupt (mLegacy8259, Efi8259Irq6);
+}
+
+VOID
+InterruptVector0x0f(EFI_IA32_REGISTER_SET *Regs)
+{
+ DEBUG (("XXX InterruptVector0x0f()\n"));
+
+ mLegacy8259->EndOfInterrupt (mLegacy8259, Efi8259Irq7);
+}
diff --git BhyvePkg/Csm/BhyveCsm16/BiosInterface.h BhyvePkg/Csm/BhyveCsm16/BiosInterface.h
new file mode 100644
index 0000000..0d897fa
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/BiosInterface.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+ * Copyright (c) 2015, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+#ifndef _BIOS_INTERFACE_
+#define _BIOS_INTERFACE_
+
+/*
+ 40:00-01 Com1
+ 40:02-03 Com2
+ 40:04-05 Com3
+ 40:06-07 Com4
+ 40:08-09 Lpt1
+ 40:0A-0B Lpt2
+ 40:0C-0D Lpt3
+ 40:0E-0E Ebda segment
+ 40:10-11 MachineConfig
+ 40:12 Bda12 - skip
+ 40:13-14 MemSize below 1MB
+ 40:15-16 Bda15_16 - skip
+ 40:17 Keyboard Status 1
+ 40:18 Keyboard Status 2
+ 40:19 Bda19 - skip
+ 40:1A-1B Key buffer head
+ 40:1C-1D Key buffer tail
+ 40:1E-3D Key buffer
+ 40:3E-3F FloppyData 3E = Calibration status 3F = Motor status
+ 40:40 FloppyTimeout
+ 40:41-49 Bda41_49 - skip
+ 40:4A Text Columns
+ 40:4B-4F Bda4B_4F - skip
+ 40:50-5F Cursor postion
+ 40:60-6B Bda60_6B - skip
+ 40:6C-6F Timer Counter
+ 40:70-74 Bda70_74 - skip
+ 40:75 Number of HDD drives
+ 40:76-77 Bda76_77 - skip
+ 40:78-79 78 = Lpt1 timeout, 79 = Lpt2 timeout
+ 40:7A-7B 7A = Lpt3 timeout, 7B = Lpt4 timeout
+ 40:7C-7D 7C = Com1 timeout, 7D = Com2 timeout
+ 40:7E-7F 7E = Com3 timeout, 7F = Com4 timeout
+ 40:80-81 Pointer to start of key buffer
+ 40:82-83 Pointer to end of key buffer
+ 40:84 Number of text rows minus 1
+ 40:85-86 Number of scan lines per character
+ 40:87 Video mode options
+ 40:88 Video features bit and switches
+ 40:89 Video display data area
+ 40:8A Video Display Combination Code (DCC)
+ 40:8B-8F Bda8B_8F - skip
+ 40:90 Floppy data rate
+ 40:91-95 Bda91_95 - skip
+ 40:96 Keyboard Status 3
+ 40:97 Keyboard Status 4
+ 40:98-101 skip
+*/
+#pragma pack(1)
+typedef struct {
+ UINT16 Com1;
+ UINT16 Com2;
+ UINT16 Com3;
+ UINT16 Com4;
+ UINT16 Lpt1;
+ UINT16 Lpt2;
+ UINT16 Lpt3;
+ UINT16 Ebda;
+ UINT16 MachineConfig;
+ UINT8 Bda12;
+ UINT16 MemSize;
+ UINT8 Bda15_16[0x02];
+ UINT8 KeyboardStatus1;
+ UINT8 KeyboardStatus2;
+ UINT8 Bda19;
+ UINT16 KeyBufferHead;
+ UINT16 KeyBufferTail;
+ UINT16 KeyBuffer[0x10];
+ UINT16 FloppyData;
+ UINT8 FloppyTimeout;
+ UINT8 Bda41_49[0x09];
+ UINT8 TextColumns;
+ UINT8 Bda4B_4F[0x05];
+ UINT16 CursorPosition[0x08];
+ UINT8 Bda60_6B[0xC];
+ UINT32 TimerCounter;
+ UINT8 Bda70_74[0x5];
+ UINT8 NumberOfDrives;
+ UINT8 Bda76_77[0x02];
+ UINT16 Lpt1_2Timeout;
+ UINT16 Lpt3_4Timeout;
+ UINT16 Com1_2Timeout;
+ UINT16 Com3_4Timeout;
+ UINT16 KeyBufferStart;
+ UINT16 KeyBufferEnd;
+ UINT8 TextRowsMinusOne;
+ UINT16 ScanLinesPerChar;
+ UINT8 VideoModeOptions;
+ UINT8 VideoFeatureBitsSwitches;
+ UINT8 VideoDisplayDataArea;
+ UINT8 VideoDCC;
+ UINT8 Bda8B_8F[0x05];
+ UINT8 FloppyXRate;
+ UINT8 Bda91_95[0x05];
+ UINT8 KeyboardStatus3;
+ UINT8 KeyboardStatus4;
+} BDA;
+#pragma pack()
+
+//
+// 0040:0017 - KEYBOARD - STATUS FLAGS 1
+// 7 Insert active
+// 6 Caps Lock active
+// 5 Num Lock active
+// 4 Scroll Lock active
+// 3 either Alt pressed
+// 2 either Ctrl pressed
+// 1 Left Shift pressed
+// 0 Right Shift pressed
+#define KBSF1_INSERT_BIT (0x1 << 7)
+#define KBSF1_CAPS_LOCK_BIT (0x1 << 6)
+#define KBSF1_NUM_LOCK_BIT (0x1 << 5)
+#define KBSF1_SCROLL_LOCK_BIT (0x1 << 4)
+#define KBSF1_ALT_PRESSED (0x1 << 3)
+#define KBSF1_CTRL_PRESSED (0x1 << 2)
+#define KBSF1_LEFT_SHIFT_PRESSED (0x1 << 1)
+#define KBSF1_RIGHT_SHIFT_PRESSED (0x1 << 0)
+
+// 0040:0018 - KEYBOARD - STATUS FLAGS 2
+// 7: insert key is depressed
+// 6: caps-lock key is depressed
+// 5: num-lock key is depressed
+// 4: scroll lock key is depressed
+// 3: suspend key has been toggled
+// 2: system key is pressed and held
+// 1: left ALT key is pressed
+// 0: left CTRL key is pressed
+#define KBSF2_SUSPEND_PRESSED (0x1 << 3)
+#define KBSF2_SYSREQ_PRESSED (0x1 << 2)
+#define KBSF2_LEFT_ALT_PRESSED (0x1 << 1)
+#define KBSF2_LEFT_CTRL_PRESSED (0x1 << 0)
+
+// 0040:0096 - KEYBOARD - STATUS FLAGS 3
+// 4: 101/102 enhanced keyboard installed
+// 1: last scancode was E0
+// 0: last scancode was E1
+#define KBSF3_LAST_CODE_WAS_E1 (0x1 << 0)
+#define KBSF3_LAST_CODE_WAS_E0 (0x1 << 1)
+#define KBSF3_ENHANCED_KBD (0x1 << 4)
+
+// 0040:0097 - KEYBOARD - STATUS FLAGS 4
+
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/Debug.h BhyvePkg/Csm/BhyveCsm16/Debug.h
new file mode 100644
index 0000000..73415a7
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Debug.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#ifndef _BHYVECSM16_DEBUG_H_
+#define _BHYVECSM16_DEBUG_H_
+
+#define DBG_VERB 3
+#define DBG_INFO 2
+#define DBG_WARN 1
+#define DBG_CRIT 0
+
+#ifdef DEBUG_PORT
+#define DEBUG(Expression) \
+ do { \
+ DebugPrint Expression; \
+ } while (FALSE)
+
+extern UINTN DebugLevel;
+#define DPRINTF(Level, Expression) \
+ if (Level <= DebugLevel) \
+ DebugPrint Expression
+
+
+#else
+#define DEBUG(Expression) \
+ do { \
+ } while (FALSE);
+
+#define DPRINTF(Level, Expression) \
+ do {
+ } while (FALSE);
+#endif
+
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/Edd.h BhyvePkg/Csm/BhyveCsm16/Edd.h
new file mode 100644
index 0000000..e24086e
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Edd.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#ifndef _BHYVECSM16_EDD_H_
+#define _BHYVECSM16_EDD_H_
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 Controller;
+ UINT32 Reserved;
+} EDD_PCI;
+
+typedef struct {
+ UINT16 Base;
+ UINT16 Reserved;
+ UINT32 Reserved2;
+} EDD_LEGACY;
+
+typedef union {
+ EDD_PCI Pci;
+ EDD_LEGACY Legacy;
+} EDD_INTERFACE_PATH;
+
+typedef struct {
+ UINT8 Master;
+ UINT8 Reserved[15];
+} EDD_ATA;
+
+typedef struct {
+ UINT8 Master;
+ UINT8 Lun;
+ UINT8 Reserved[14];
+} EDD_ATAPI;
+
+typedef struct {
+ UINT16 Pun;
+ UINT64 Lun;
+ UINT8 Reserved[6];
+} EDD_SCSI;
+
+typedef struct {
+ UINT64 SerialNumber;
+ UINT64 Reserved;
+} EDD_USB;
+
+typedef struct {
+ UINT64 Guid;
+ UINT64 Reserved;
+} EDD_1394;
+
+typedef struct {
+ UINT64 Wwn;
+ UINT64 Lun;
+} EDD_FIBRE;
+
+typedef union {
+ EDD_ATA Ata;
+ EDD_ATAPI Atapi;
+ EDD_SCSI Scsi;
+ EDD_USB Usb;
+ EDD_1394 FireWire;
+ EDD_FIBRE FibreChannel;
+} EDD_DEVICE_PATH;
+
+//
+// EDD_DRIVE_PARAMETERS.Flags defines
+//
+#define EDD_GEOMETRY_VALID 0x02
+#define EDD_DEVICE_REMOVABLE 0x04
+#define EDD_WRITE_VERIFY_SUPPORTED 0x08
+#define EDD_DEVICE_CHANGE 0x10
+#define EDD_DEVICE_LOCKABLE 0x20
+
+typedef struct {
+ UINT16 StructureSize;
+ UINT16 Flags;
+ UINT32 MaxCylinders;
+ UINT32 MaxHeads;
+ UINT32 SectorsPerTrack;
+ UINT64 PhysicalSectors;
+ UINT16 BytesPerSector;
+ UINT32 Fdpt;
+ UINT16 Key;
+ UINT8 DevicePathLength;
+ UINT8 Reserved1;
+ UINT16 Reserved2;
+ CHAR8 HostBusType[4];
+ CHAR8 InterfaceType[8];
+ EDD_INTERFACE_PATH InterfacePath;
+ EDD_DEVICE_PATH DevicePath;
+ UINT8 Reserved3;
+ UINT8 Checksum;
+} EDD_DRIVE_PARAMETERS;
+
+typedef struct {
+ UINT8 PacketSizeInBytes;
+ UINT8 Reserved1;
+ UINT8 NumberOfBlocks;
+ UINT8 Reserved2;
+ UINT32 SegOffset;
+ UINT64 Lba;
+ UINT64 TransferBuffer;
+} EDD_DEVICE_ADDRESS_PACKET;
+
+typedef struct {
+ UINT8 PacketSizeInBytes;
+ UINT8 BootMediaType;
+ UINT8 DriveNumber;
+ UINT8 ControllerIndex;
+ UINT32 Lba;
+ UINT16 DeviceSpecification;
+ UINT16 UserBufferSegment;
+ UINT16 LoadSegment;
+ UINT16 LoadSectorCount;
+ UINT8 CylinderCount;
+ UINT8 SectorCount;
+ UINT8 HeadCount;
+} EDD_DEVICE_SPECIFICATION_PACKET;
+
+#pragma pack()
+
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/FakeIdt.h BhyvePkg/Csm/BhyveCsm16/FakeIdt.h
new file mode 100644
index 0000000..8e0a458
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/FakeIdt.h
@@ -0,0 +1,2593 @@
+// Fake Idt handlers. Restrict which set of Idt handlers are registered
+// otherwise build output becomes oversaturated.
+
+#define FAKE_IDTS
+#define XBLOCK 1
+
+#if XBLOCK == 1
+VOID
+Fidt_0(VOID)
+{
+ DEBUG(("Idt 0\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_1(VOID)
+{
+ DEBUG(("Idt 1\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_2(VOID)
+{
+ DEBUG(("Idt 2\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_3(VOID)
+{
+ DEBUG(("Idt 3\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_4(VOID)
+{
+ DEBUG(("Idt 4\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_5(VOID)
+{
+ DEBUG(("Idt 5\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_6(VOID)
+{
+ DEBUG(("Idt 6\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_7(VOID)
+{
+ DEBUG(("Idt 7\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_8(VOID)
+{
+ DEBUG(("Idt 8\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_9(VOID)
+{
+ DEBUG(("Idt 9\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_10(VOID)
+{
+ DEBUG(("Idt 10\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_11(VOID)
+{
+ DEBUG(("Idt 11\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_12(VOID)
+{
+ DEBUG(("Idt 12\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_13(VOID)
+{
+ DEBUG(("Idt 13\n"));
+ for(;;);
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_14(VOID)
+{
+ DEBUG(("Idt 14\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_15(VOID)
+{
+ DEBUG(("Idt 15\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_16(VOID)
+{
+ DEBUG(("Idt 16\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_17(VOID)
+{
+ DEBUG(("Idt 17\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_18(VOID)
+{
+ DEBUG(("Idt 18\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_19(VOID)
+{
+ DEBUG(("Idt 19\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_20(VOID)
+{
+ DEBUG(("Idt 20\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_21(VOID)
+{
+ DEBUG(("Idt 21\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_22(VOID)
+{
+ DEBUG(("Idt 22\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_23(VOID)
+{
+ DEBUG(("Idt 23\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_24(VOID)
+{
+ DEBUG(("Idt 24\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_25(VOID)
+{
+ DEBUG(("Idt 25\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_26(VOID)
+{
+ DEBUG(("Idt 26\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_27(VOID)
+{
+ DEBUG(("Idt 27\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_28(VOID)
+{
+ DEBUG(("Idt 28\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_29(VOID)
+{
+ DEBUG(("Idt 29\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_30(VOID)
+{
+ DEBUG(("Idt 30\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_31(VOID)
+{
+ DEBUG(("Idt 31\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_32(VOID)
+{
+ DEBUG(("Idt 32\n"));
+__asm__ __volatile__ ("outb %b0,%w1" : : "a" (0), "d" ((UINT16)0x488));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_33(VOID)
+{
+ DEBUG(("Idt 33\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_34(VOID)
+{
+ DEBUG(("Idt 34\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_35(VOID)
+{
+ DEBUG(("Idt 35\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_36(VOID)
+{
+ DEBUG(("Idt 36\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_37(VOID)
+{
+ DEBUG(("Idt 37\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_38(VOID)
+{
+ DEBUG(("Idt 38\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_39(VOID)
+{
+ DEBUG(("Idt 39\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_40(VOID)
+{
+ DEBUG(("Idt 40\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_41(VOID)
+{
+ DEBUG(("Idt 41\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_42(VOID)
+{
+ DEBUG(("Idt 42\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_43(VOID)
+{
+ DEBUG(("Idt 43\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_44(VOID)
+{
+ DEBUG(("Idt 44\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_45(VOID)
+{
+ DEBUG(("Idt 45\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_46(VOID)
+{
+ DEBUG(("Idt 46\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_47(VOID)
+{
+ DEBUG(("Idt 47\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_48(VOID)
+{
+ DEBUG(("Idt 48\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_49(VOID)
+{
+ DEBUG(("Idt 49\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_50(VOID)
+{
+ DEBUG(("Idt 50\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_51(VOID)
+{
+ DEBUG(("Idt 51\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_52(VOID)
+{
+ DEBUG(("Idt 52\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_53(VOID)
+{
+ DEBUG(("Idt 53\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_54(VOID)
+{
+ DEBUG(("Idt 54\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_55(VOID)
+{
+ DEBUG(("Idt 55\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_56(VOID)
+{
+ DEBUG(("Idt 56\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_57(VOID)
+{
+ DEBUG(("Idt 57\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_58(VOID)
+{
+ DEBUG(("Idt 58\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_59(VOID)
+{
+ DEBUG(("Idt 59\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_60(VOID)
+{
+ DEBUG(("Idt 60\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_61(VOID)
+{
+ DEBUG(("Idt 61\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_62(VOID)
+{
+ DEBUG(("Idt 62\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_63(VOID)
+{
+ DEBUG(("Idt 63\n"));
+ __asm__ __volatile__ ("iretq");
+}
+#elif XBLOCK == 2
+VOID
+Fidt_64(VOID)
+{
+ DEBUG(("Idt 64\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_65(VOID)
+{
+ DEBUG(("Idt 65\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_66(VOID)
+{
+ DEBUG(("Idt 66\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_67(VOID)
+{
+ DEBUG(("Idt 67\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_68(VOID)
+{
+ DEBUG(("Idt 68\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_69(VOID)
+{
+ DEBUG(("Idt 69\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_70(VOID)
+{
+ DEBUG(("Idt 70\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_71(VOID)
+{
+ DEBUG(("Idt 71\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_72(VOID)
+{
+ DEBUG(("Idt 72\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_73(VOID)
+{
+ DEBUG(("Idt 73\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_74(VOID)
+{
+ DEBUG(("Idt 74\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_75(VOID)
+{
+ DEBUG(("Idt 75\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_76(VOID)
+{
+ DEBUG(("Idt 76\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_77(VOID)
+{
+ DEBUG(("Idt 77\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_78(VOID)
+{
+ DEBUG(("Idt 78\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_79(VOID)
+{
+ DEBUG(("Idt 79\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_80(VOID)
+{
+ DEBUG(("Idt 80\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_81(VOID)
+{
+ DEBUG(("Idt 81\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_82(VOID)
+{
+ DEBUG(("Idt 82\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_83(VOID)
+{
+ DEBUG(("Idt 83\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_84(VOID)
+{
+ DEBUG(("Idt 84\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_85(VOID)
+{
+ DEBUG(("Idt 85\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_86(VOID)
+{
+ DEBUG(("Idt 86\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_87(VOID)
+{
+ DEBUG(("Idt 87\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_88(VOID)
+{
+ DEBUG(("Idt 88\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_89(VOID)
+{
+ DEBUG(("Idt 89\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_90(VOID)
+{
+ DEBUG(("Idt 90\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_91(VOID)
+{
+ DEBUG(("Idt 91\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_92(VOID)
+{
+ DEBUG(("Idt 92\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_93(VOID)
+{
+ DEBUG(("Idt 93\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_94(VOID)
+{
+ DEBUG(("Idt 94\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_95(VOID)
+{
+ DEBUG(("Idt 95\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_96(VOID)
+{
+ DEBUG(("Idt 96\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_97(VOID)
+{
+ DEBUG(("Idt 97\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_98(VOID)
+{
+ DEBUG(("Idt 98\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_99(VOID)
+{
+ DEBUG(("Idt 99\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_100(VOID)
+{
+ DEBUG(("Idt 100\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_101(VOID)
+{
+ DEBUG(("Idt 101\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_102(VOID)
+{
+ DEBUG(("Idt 102\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_103(VOID)
+{
+ DEBUG(("Idt 103\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_104(VOID)
+{
+ DEBUG(("Idt 104\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_105(VOID)
+{
+ DEBUG(("Idt 105\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_106(VOID)
+{
+ DEBUG(("Idt 106\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_107(VOID)
+{
+ DEBUG(("Idt 107\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_108(VOID)
+{
+ DEBUG(("Idt 108\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_109(VOID)
+{
+ DEBUG(("Idt 109\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_110(VOID)
+{
+ DEBUG(("Idt 110\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_111(VOID)
+{
+ DEBUG(("Idt 111\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_112(VOID)
+{
+ DEBUG(("Idt 112\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_113(VOID)
+{
+ DEBUG(("Idt 113\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_114(VOID)
+{
+ DEBUG(("Idt 114\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_115(VOID)
+{
+ DEBUG(("Idt 115\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_116(VOID)
+{
+ DEBUG(("Idt 116\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_117(VOID)
+{
+ DEBUG(("Idt 117\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_118(VOID)
+{
+ DEBUG(("Idt 118\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_119(VOID)
+{
+ DEBUG(("Idt 119\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_120(VOID)
+{
+ DEBUG(("Idt 120\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_121(VOID)
+{
+ DEBUG(("Idt 121\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_122(VOID)
+{
+ DEBUG(("Idt 122\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_123(VOID)
+{
+ DEBUG(("Idt 123\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_124(VOID)
+{
+ DEBUG(("Idt 124\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_125(VOID)
+{
+ DEBUG(("Idt 125\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_126(VOID)
+{
+ DEBUG(("Idt 126\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_127(VOID)
+{
+ DEBUG(("Idt 127\n"));
+ __asm__ __volatile__ ("iretq");
+}
+#elif XBLOCK == 3
+VOID
+Fidt_128(VOID)
+{
+ DEBUG(("Idt 128\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_129(VOID)
+{
+ DEBUG(("Idt 129\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_130(VOID)
+{
+ DEBUG(("Idt 130\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_131(VOID)
+{
+ DEBUG(("Idt 131\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_132(VOID)
+{
+ DEBUG(("Idt 132\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_133(VOID)
+{
+ DEBUG(("Idt 133\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_134(VOID)
+{
+ DEBUG(("Idt 134\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_135(VOID)
+{
+ DEBUG(("Idt 135\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_136(VOID)
+{
+ DEBUG(("Idt 136\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_137(VOID)
+{
+ DEBUG(("Idt 137\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_138(VOID)
+{
+ DEBUG(("Idt 138\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_139(VOID)
+{
+ DEBUG(("Idt 139\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_140(VOID)
+{
+ DEBUG(("Idt 140\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_141(VOID)
+{
+ DEBUG(("Idt 141\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_142(VOID)
+{
+ DEBUG(("Idt 142\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_143(VOID)
+{
+ DEBUG(("Idt 143\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_144(VOID)
+{
+ DEBUG(("Idt 144\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_145(VOID)
+{
+ DEBUG(("Idt 145\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_146(VOID)
+{
+ DEBUG(("Idt 146\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_147(VOID)
+{
+ DEBUG(("Idt 147\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_148(VOID)
+{
+ DEBUG(("Idt 148\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_149(VOID)
+{
+ DEBUG(("Idt 149\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_150(VOID)
+{
+ DEBUG(("Idt 150\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_151(VOID)
+{
+ DEBUG(("Idt 151\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_152(VOID)
+{
+ DEBUG(("Idt 152\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_153(VOID)
+{
+ DEBUG(("Idt 153\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_154(VOID)
+{
+ DEBUG(("Idt 154\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_155(VOID)
+{
+ DEBUG(("Idt 155\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_156(VOID)
+{
+ DEBUG(("Idt 156\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_157(VOID)
+{
+ DEBUG(("Idt 157\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_158(VOID)
+{
+ DEBUG(("Idt 158\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_159(VOID)
+{
+ DEBUG(("Idt 159\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_160(VOID)
+{
+ DEBUG(("Idt 160\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_161(VOID)
+{
+ DEBUG(("Idt 161\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_162(VOID)
+{
+ DEBUG(("Idt 162\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_163(VOID)
+{
+ DEBUG(("Idt 163\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_164(VOID)
+{
+ DEBUG(("Idt 164\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_165(VOID)
+{
+ DEBUG(("Idt 165\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_166(VOID)
+{
+ DEBUG(("Idt 166\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_167(VOID)
+{
+ DEBUG(("Idt 167\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_168(VOID)
+{
+ DEBUG(("Idt 168\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_169(VOID)
+{
+ DEBUG(("Idt 169\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_170(VOID)
+{
+ DEBUG(("Idt 170\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_171(VOID)
+{
+ DEBUG(("Idt 171\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_172(VOID)
+{
+ DEBUG(("Idt 172\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_173(VOID)
+{
+ DEBUG(("Idt 173\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_174(VOID)
+{
+ DEBUG(("Idt 174\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_175(VOID)
+{
+ DEBUG(("Idt 175\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_176(VOID)
+{
+ DEBUG(("Idt 176\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_177(VOID)
+{
+ DEBUG(("Idt 177\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_178(VOID)
+{
+ DEBUG(("Idt 178\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_179(VOID)
+{
+ DEBUG(("Idt 179\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_180(VOID)
+{
+ DEBUG(("Idt 180\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_181(VOID)
+{
+ DEBUG(("Idt 181\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_182(VOID)
+{
+ DEBUG(("Idt 182\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_183(VOID)
+{
+ DEBUG(("Idt 183\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_184(VOID)
+{
+ DEBUG(("Idt 184\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_185(VOID)
+{
+ DEBUG(("Idt 185\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_186(VOID)
+{
+ DEBUG(("Idt 186\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_187(VOID)
+{
+ DEBUG(("Idt 187\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_188(VOID)
+{
+ DEBUG(("Idt 188\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_189(VOID)
+{
+ DEBUG(("Idt 189\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_190(VOID)
+{
+ DEBUG(("Idt 190\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_191(VOID)
+{
+ DEBUG(("Idt 191\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_192(VOID)
+{
+ DEBUG(("Idt 192\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_193(VOID)
+{
+ DEBUG(("Idt 193\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_194(VOID)
+{
+ DEBUG(("Idt 194\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_195(VOID)
+{
+ DEBUG(("Idt 195\n"));
+ __asm__ __volatile__ ("iretq");
+}
+#elif XBLOCK == 4
+VOID
+Fidt_196(VOID)
+{
+ DEBUG(("Idt 196\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_197(VOID)
+{
+ DEBUG(("Idt 197\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_198(VOID)
+{
+ DEBUG(("Idt 198\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_199(VOID)
+{
+ DEBUG(("Idt 199\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_200(VOID)
+{
+ DEBUG(("Idt 200\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_201(VOID)
+{
+ DEBUG(("Idt 201\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_202(VOID)
+{
+ DEBUG(("Idt 202\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_203(VOID)
+{
+ DEBUG(("Idt 203\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_204(VOID)
+{
+ DEBUG(("Idt 204\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_205(VOID)
+{
+ DEBUG(("Idt 205\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_206(VOID)
+{
+ DEBUG(("Idt 206\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_207(VOID)
+{
+ DEBUG(("Idt 207\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_208(VOID)
+{
+ DEBUG(("Idt 208\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_209(VOID)
+{
+ DEBUG(("Idt 209\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_210(VOID)
+{
+ DEBUG(("Idt 210\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_211(VOID)
+{
+ DEBUG(("Idt 211\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_212(VOID)
+{
+ DEBUG(("Idt 212\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_213(VOID)
+{
+ DEBUG(("Idt 213\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_214(VOID)
+{
+ DEBUG(("Idt 214\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_215(VOID)
+{
+ DEBUG(("Idt 215\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_216(VOID)
+{
+ DEBUG(("Idt 216\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_217(VOID)
+{
+ DEBUG(("Idt 217\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_218(VOID)
+{
+ DEBUG(("Idt 218\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_219(VOID)
+{
+ DEBUG(("Idt 219\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_220(VOID)
+{
+ DEBUG(("Idt 220\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_221(VOID)
+{
+ DEBUG(("Idt 221\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_222(VOID)
+{
+ DEBUG(("Idt 222\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_223(VOID)
+{
+ DEBUG(("Idt 223\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_224(VOID)
+{
+ DEBUG(("Idt 224\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_225(VOID)
+{
+ DEBUG(("Idt 225\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_226(VOID)
+{
+ DEBUG(("Idt 226\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_227(VOID)
+{
+ DEBUG(("Idt 227\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_228(VOID)
+{
+ DEBUG(("Idt 228\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_229(VOID)
+{
+ DEBUG(("Idt 229\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_230(VOID)
+{
+ DEBUG(("Idt 230\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_231(VOID)
+{
+ DEBUG(("Idt 231\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_232(VOID)
+{
+ DEBUG(("Idt 232\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_233(VOID)
+{
+ DEBUG(("Idt 233\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_234(VOID)
+{
+ DEBUG(("Idt 234\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_235(VOID)
+{
+ DEBUG(("Idt 235\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_236(VOID)
+{
+ DEBUG(("Idt 236\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_237(VOID)
+{
+ DEBUG(("Idt 237\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_238(VOID)
+{
+ DEBUG(("Idt 238\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_239(VOID)
+{
+ DEBUG(("Idt 239\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_240(VOID)
+{
+ DEBUG(("Idt 240\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_241(VOID)
+{
+ DEBUG(("Idt 241\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_242(VOID)
+{
+ DEBUG(("Idt 242\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_243(VOID)
+{
+ DEBUG(("Idt 243\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_244(VOID)
+{
+ DEBUG(("Idt 244\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_245(VOID)
+{
+ DEBUG(("Idt 245\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_246(VOID)
+{
+ DEBUG(("Idt 246\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_247(VOID)
+{
+ DEBUG(("Idt 247\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_248(VOID)
+{
+ DEBUG(("Idt 248\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_249(VOID)
+{
+ DEBUG(("Idt 249\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_250(VOID)
+{
+ DEBUG(("Idt 250\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_251(VOID)
+{
+ DEBUG(("Idt 251\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_252(VOID)
+{
+ DEBUG(("Idt 252\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_253(VOID)
+{
+ DEBUG(("Idt 253\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_254(VOID)
+{
+ DEBUG(("Idt 254\n"));
+ __asm__ __volatile__ ("iretq");
+}
+VOID
+Fidt_255(VOID)
+{
+ DEBUG(("Idt 255\n"));
+ __asm__ __volatile__ ("iretq");
+}
+#endif
+
+STATIC VOID
+InitFakeIdtEntries(VOID)
+{
+ IA32_IDT_GATE_DESCRIPTOR IdtEntry;
+
+ IdtEntry.Bits.Selector = 0x8;
+ IdtEntry.Bits.Reserved_0 = 0;
+ IdtEntry.Bits.GateType = IA32_IDT_GATE_TYPE_INTERRUPT_32;
+ IdtEntry.Bits.OffsetUpper = 0;
+
+#if XBLOCK == 1
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_0;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_0) >> 16);
+ CopyMem(&mIdtEntries[0], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_1;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_1) >> 16);
+ CopyMem(&mIdtEntries[1], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_2;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_2) >> 16);
+ CopyMem(&mIdtEntries[2], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_3;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_3) >> 16);
+ CopyMem(&mIdtEntries[3], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_4;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_4) >> 16);
+ CopyMem(&mIdtEntries[4], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_5;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_5) >> 16);
+ CopyMem(&mIdtEntries[5], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_6;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_6) >> 16);
+ CopyMem(&mIdtEntries[6], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_7;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_7) >> 16);
+ CopyMem(&mIdtEntries[7], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_8;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_8) >> 16);
+ CopyMem(&mIdtEntries[8], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_9;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_9) >> 16);
+ CopyMem(&mIdtEntries[9], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_10;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_10) >> 16);
+ CopyMem(&mIdtEntries[10], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_11;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_11) >> 16);
+ CopyMem(&mIdtEntries[11], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_12;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_12) >> 16);
+ CopyMem(&mIdtEntries[12], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_13;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_13) >> 16);
+ CopyMem(&mIdtEntries[13], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_14;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_14) >> 16);
+ CopyMem(&mIdtEntries[14], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_15;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_15) >> 16);
+ CopyMem(&mIdtEntries[15], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_16;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_16) >> 16);
+ CopyMem(&mIdtEntries[16], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_17;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_17) >> 16);
+ CopyMem(&mIdtEntries[17], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_18;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_18) >> 16);
+ CopyMem(&mIdtEntries[18], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_19;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_19) >> 16);
+ CopyMem(&mIdtEntries[19], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_20;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_20) >> 16);
+ CopyMem(&mIdtEntries[20], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_21;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_21) >> 16);
+ CopyMem(&mIdtEntries[21], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_22;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_22) >> 16);
+ CopyMem(&mIdtEntries[22], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_23;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_23) >> 16);
+ CopyMem(&mIdtEntries[23], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_24;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_24) >> 16);
+ CopyMem(&mIdtEntries[24], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_25;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_25) >> 16);
+ CopyMem(&mIdtEntries[25], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_26;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_26) >> 16);
+ CopyMem(&mIdtEntries[26], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_27;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_27) >> 16);
+ CopyMem(&mIdtEntries[27], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_28;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_28) >> 16);
+ CopyMem(&mIdtEntries[28], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_29;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_29) >> 16);
+ CopyMem(&mIdtEntries[29], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_30;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_30) >> 16);
+ CopyMem(&mIdtEntries[30], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_31;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_31) >> 16);
+ CopyMem(&mIdtEntries[31], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_32;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_32) >> 16);
+ CopyMem(&mIdtEntries[32], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_33;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_33) >> 16);
+ CopyMem(&mIdtEntries[33], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_34;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_34) >> 16);
+ CopyMem(&mIdtEntries[34], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_35;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_35) >> 16);
+ CopyMem(&mIdtEntries[35], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_36;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_36) >> 16);
+ CopyMem(&mIdtEntries[36], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_37;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_37) >> 16);
+ CopyMem(&mIdtEntries[37], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_38;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_38) >> 16);
+ CopyMem(&mIdtEntries[38], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_39;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_39) >> 16);
+ CopyMem(&mIdtEntries[39], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_40;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_40) >> 16);
+ CopyMem(&mIdtEntries[40], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_41;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_41) >> 16);
+ CopyMem(&mIdtEntries[41], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_42;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_42) >> 16);
+ CopyMem(&mIdtEntries[42], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_43;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_43) >> 16);
+ CopyMem(&mIdtEntries[43], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_44;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_44) >> 16);
+ CopyMem(&mIdtEntries[44], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_45;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_45) >> 16);
+ CopyMem(&mIdtEntries[45], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_46;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_46) >> 16);
+ CopyMem(&mIdtEntries[46], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_47;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_47) >> 16);
+ CopyMem(&mIdtEntries[47], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_48;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_48) >> 16);
+ CopyMem(&mIdtEntries[48], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_49;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_49) >> 16);
+ CopyMem(&mIdtEntries[49], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_50;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_50) >> 16);
+ CopyMem(&mIdtEntries[50], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_51;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_51) >> 16);
+ CopyMem(&mIdtEntries[51], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_52;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_52) >> 16);
+ CopyMem(&mIdtEntries[52], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_53;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_53) >> 16);
+ CopyMem(&mIdtEntries[53], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_54;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_54) >> 16);
+ CopyMem(&mIdtEntries[54], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_55;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_55) >> 16);
+ CopyMem(&mIdtEntries[55], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_56;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_56) >> 16);
+ CopyMem(&mIdtEntries[56], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_57;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_57) >> 16);
+ CopyMem(&mIdtEntries[57], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_58;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_58) >> 16);
+ CopyMem(&mIdtEntries[58], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_59;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_59) >> 16);
+ CopyMem(&mIdtEntries[59], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_60;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_60) >> 16);
+ CopyMem(&mIdtEntries[60], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_61;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_61) >> 16);
+ CopyMem(&mIdtEntries[61], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_62;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_62) >> 16);
+ CopyMem(&mIdtEntries[62], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_63;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_63) >> 16);
+ CopyMem(&mIdtEntries[63], &IdtEntry, sizeof (IdtEntry));
+
+#elif XBLOCK == 2
+/*
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_64;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_64) >> 16);
+ CopyMem(&mIdtEntries[64], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_65;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_65) >> 16);
+ CopyMem(&mIdtEntries[65], &IdtEntry, sizeof (IdtEntry));
+*/
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_66;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_66) >> 16);
+ CopyMem(&mIdtEntries[66], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_67;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_67) >> 16);
+ CopyMem(&mIdtEntries[67], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_68;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_68) >> 16);
+ CopyMem(&mIdtEntries[68], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_69;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_69) >> 16);
+ CopyMem(&mIdtEntries[69], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_70;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_70) >> 16);
+ CopyMem(&mIdtEntries[70], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_71;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_71) >> 16);
+ CopyMem(&mIdtEntries[71], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_72;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_72) >> 16);
+ CopyMem(&mIdtEntries[72], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_73;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_73) >> 16);
+ CopyMem(&mIdtEntries[73], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_74;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_74) >> 16);
+ CopyMem(&mIdtEntries[74], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_75;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_75) >> 16);
+ CopyMem(&mIdtEntries[75], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_76;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_76) >> 16);
+ CopyMem(&mIdtEntries[76], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_77;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_77) >> 16);
+ CopyMem(&mIdtEntries[77], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_78;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_78) >> 16);
+ CopyMem(&mIdtEntries[78], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_79;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_79) >> 16);
+ CopyMem(&mIdtEntries[79], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_80;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_80) >> 16);
+ CopyMem(&mIdtEntries[80], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_81;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_81) >> 16);
+ CopyMem(&mIdtEntries[81], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_82;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_82) >> 16);
+ CopyMem(&mIdtEntries[82], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_83;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_83) >> 16);
+ CopyMem(&mIdtEntries[83], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_84;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_84) >> 16);
+ CopyMem(&mIdtEntries[84], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_85;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_85) >> 16);
+ CopyMem(&mIdtEntries[85], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_86;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_86) >> 16);
+ CopyMem(&mIdtEntries[86], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_87;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_87) >> 16);
+ CopyMem(&mIdtEntries[87], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_88;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_88) >> 16);
+ CopyMem(&mIdtEntries[88], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_89;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_89) >> 16);
+ CopyMem(&mIdtEntries[89], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_90;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_90) >> 16);
+ CopyMem(&mIdtEntries[90], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_91;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_91) >> 16);
+ CopyMem(&mIdtEntries[91], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_92;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_92) >> 16);
+ CopyMem(&mIdtEntries[92], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_93;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_93) >> 16);
+ CopyMem(&mIdtEntries[93], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_94;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_94) >> 16);
+ CopyMem(&mIdtEntries[94], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_95;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_95) >> 16);
+ CopyMem(&mIdtEntries[95], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_96;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_96) >> 16);
+ CopyMem(&mIdtEntries[96], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_97;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_97) >> 16);
+ CopyMem(&mIdtEntries[97], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_98;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_98) >> 16);
+ CopyMem(&mIdtEntries[98], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_99;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_99) >> 16);
+ CopyMem(&mIdtEntries[99], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_100;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_100) >> 16);
+ CopyMem(&mIdtEntries[100], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_101;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_101) >> 16);
+ CopyMem(&mIdtEntries[101], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_102;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_102) >> 16);
+ CopyMem(&mIdtEntries[102], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_103;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_103) >> 16);
+ CopyMem(&mIdtEntries[103], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_104;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_104) >> 16);
+ CopyMem(&mIdtEntries[104], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_105;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_105) >> 16);
+ CopyMem(&mIdtEntries[105], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_106;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_106) >> 16);
+ CopyMem(&mIdtEntries[106], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_107;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_107) >> 16);
+ CopyMem(&mIdtEntries[107], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_108;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_108) >> 16);
+ CopyMem(&mIdtEntries[108], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_109;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_109) >> 16);
+ CopyMem(&mIdtEntries[109], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_110;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_110) >> 16);
+ CopyMem(&mIdtEntries[110], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_111;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_111) >> 16);
+ CopyMem(&mIdtEntries[111], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_112;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_112) >> 16);
+ CopyMem(&mIdtEntries[112], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_113;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_113) >> 16);
+ CopyMem(&mIdtEntries[113], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_114;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_114) >> 16);
+ CopyMem(&mIdtEntries[114], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_115;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_115) >> 16);
+ CopyMem(&mIdtEntries[115], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_116;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_116) >> 16);
+ CopyMem(&mIdtEntries[116], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_117;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_117) >> 16);
+ CopyMem(&mIdtEntries[117], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_118;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_118) >> 16);
+ CopyMem(&mIdtEntries[118], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_119;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_119) >> 16);
+ CopyMem(&mIdtEntries[119], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_120;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_120) >> 16);
+ CopyMem(&mIdtEntries[120], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_121;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_121) >> 16);
+ CopyMem(&mIdtEntries[121], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_122;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_122) >> 16);
+ CopyMem(&mIdtEntries[122], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_123;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_123) >> 16);
+ CopyMem(&mIdtEntries[123], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_124;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_124) >> 16);
+ CopyMem(&mIdtEntries[124], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_125;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_125) >> 16);
+ CopyMem(&mIdtEntries[125], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_126;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_126) >> 16);
+ CopyMem(&mIdtEntries[126], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_127;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_127) >> 16);
+ CopyMem(&mIdtEntries[127], &IdtEntry, sizeof (IdtEntry));
+
+#elif XBLOCK == 3
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_128;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_128) >> 16);
+ CopyMem(&mIdtEntries[128], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_129;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_129) >> 16);
+ CopyMem(&mIdtEntries[129], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_130;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_130) >> 16);
+ CopyMem(&mIdtEntries[130], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_131;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_131) >> 16);
+ CopyMem(&mIdtEntries[131], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_132;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_132) >> 16);
+ CopyMem(&mIdtEntries[132], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_133;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_133) >> 16);
+ CopyMem(&mIdtEntries[133], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_134;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_134) >> 16);
+ CopyMem(&mIdtEntries[134], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_135;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_135) >> 16);
+ CopyMem(&mIdtEntries[135], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_136;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_136) >> 16);
+ CopyMem(&mIdtEntries[136], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_137;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_137) >> 16);
+ CopyMem(&mIdtEntries[137], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_138;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_138) >> 16);
+ CopyMem(&mIdtEntries[138], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_139;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_139) >> 16);
+ CopyMem(&mIdtEntries[139], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_140;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_140) >> 16);
+ CopyMem(&mIdtEntries[140], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_141;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_141) >> 16);
+ CopyMem(&mIdtEntries[141], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_142;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_142) >> 16);
+ CopyMem(&mIdtEntries[142], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_143;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_143) >> 16);
+ CopyMem(&mIdtEntries[143], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_144;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_144) >> 16);
+ CopyMem(&mIdtEntries[144], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_145;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_145) >> 16);
+ CopyMem(&mIdtEntries[145], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_146;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_146) >> 16);
+ CopyMem(&mIdtEntries[146], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_147;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_147) >> 16);
+ CopyMem(&mIdtEntries[147], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_148;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_148) >> 16);
+ CopyMem(&mIdtEntries[148], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_149;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_149) >> 16);
+ CopyMem(&mIdtEntries[149], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_150;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_150) >> 16);
+ CopyMem(&mIdtEntries[150], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_151;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_151) >> 16);
+ CopyMem(&mIdtEntries[151], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_152;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_152) >> 16);
+ CopyMem(&mIdtEntries[152], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_153;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_153) >> 16);
+ CopyMem(&mIdtEntries[153], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_154;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_154) >> 16);
+ CopyMem(&mIdtEntries[154], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_155;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_155) >> 16);
+ CopyMem(&mIdtEntries[155], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_156;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_156) >> 16);
+ CopyMem(&mIdtEntries[156], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_157;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_157) >> 16);
+ CopyMem(&mIdtEntries[157], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_158;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_158) >> 16);
+ CopyMem(&mIdtEntries[158], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_159;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_159) >> 16);
+ CopyMem(&mIdtEntries[159], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_160;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_160) >> 16);
+ CopyMem(&mIdtEntries[160], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_161;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_161) >> 16);
+ CopyMem(&mIdtEntries[161], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_162;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_162) >> 16);
+ CopyMem(&mIdtEntries[162], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_163;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_163) >> 16);
+ CopyMem(&mIdtEntries[163], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_164;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_164) >> 16);
+ CopyMem(&mIdtEntries[164], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_165;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_165) >> 16);
+ CopyMem(&mIdtEntries[165], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_166;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_166) >> 16);
+ CopyMem(&mIdtEntries[166], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_167;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_167) >> 16);
+ CopyMem(&mIdtEntries[167], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_168;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_168) >> 16);
+ CopyMem(&mIdtEntries[168], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_169;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_169) >> 16);
+ CopyMem(&mIdtEntries[169], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_170;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_170) >> 16);
+ CopyMem(&mIdtEntries[170], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_171;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_171) >> 16);
+ CopyMem(&mIdtEntries[171], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_172;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_172) >> 16);
+ CopyMem(&mIdtEntries[172], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_173;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_173) >> 16);
+ CopyMem(&mIdtEntries[173], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_174;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_174) >> 16);
+ CopyMem(&mIdtEntries[174], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_175;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_175) >> 16);
+ CopyMem(&mIdtEntries[175], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_176;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_176) >> 16);
+ CopyMem(&mIdtEntries[176], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_177;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_177) >> 16);
+ CopyMem(&mIdtEntries[177], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_178;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_178) >> 16);
+ CopyMem(&mIdtEntries[178], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_179;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_179) >> 16);
+ CopyMem(&mIdtEntries[179], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_180;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_180) >> 16);
+ CopyMem(&mIdtEntries[180], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_181;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_181) >> 16);
+ CopyMem(&mIdtEntries[181], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_182;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_182) >> 16);
+ CopyMem(&mIdtEntries[182], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_183;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_183) >> 16);
+ CopyMem(&mIdtEntries[183], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_184;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_184) >> 16);
+ CopyMem(&mIdtEntries[184], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_185;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_185) >> 16);
+ CopyMem(&mIdtEntries[185], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_186;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_186) >> 16);
+ CopyMem(&mIdtEntries[186], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_187;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_187) >> 16);
+ CopyMem(&mIdtEntries[187], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_188;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_188) >> 16);
+ CopyMem(&mIdtEntries[188], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_189;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_189) >> 16);
+ CopyMem(&mIdtEntries[189], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_190;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_190) >> 16);
+ CopyMem(&mIdtEntries[190], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_191;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_191) >> 16);
+ CopyMem(&mIdtEntries[191], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_192;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_192) >> 16);
+ CopyMem(&mIdtEntries[192], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_193;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_193) >> 16);
+ CopyMem(&mIdtEntries[193], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_194;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_194) >> 16);
+ CopyMem(&mIdtEntries[194], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_195;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_195) >> 16);
+ CopyMem(&mIdtEntries[195], &IdtEntry, sizeof (IdtEntry));
+
+#elif XBLOCK == 4
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_196;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_196) >> 16);
+ CopyMem(&mIdtEntries[196], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_197;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_197) >> 16);
+ CopyMem(&mIdtEntries[197], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_198;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_198) >> 16);
+ CopyMem(&mIdtEntries[198], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_199;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_199) >> 16);
+ CopyMem(&mIdtEntries[199], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_200;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_200) >> 16);
+ CopyMem(&mIdtEntries[200], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_201;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_201) >> 16);
+ CopyMem(&mIdtEntries[201], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_202;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_202) >> 16);
+ CopyMem(&mIdtEntries[202], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_203;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_203) >> 16);
+ CopyMem(&mIdtEntries[203], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_204;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_204) >> 16);
+ CopyMem(&mIdtEntries[204], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_205;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_205) >> 16);
+ CopyMem(&mIdtEntries[205], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_206;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_206) >> 16);
+ CopyMem(&mIdtEntries[206], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_207;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_207) >> 16);
+ CopyMem(&mIdtEntries[207], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_208;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_208) >> 16);
+ CopyMem(&mIdtEntries[208], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_209;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_209) >> 16);
+ CopyMem(&mIdtEntries[209], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_210;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_210) >> 16);
+ CopyMem(&mIdtEntries[210], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_211;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_211) >> 16);
+ CopyMem(&mIdtEntries[211], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_212;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_212) >> 16);
+ CopyMem(&mIdtEntries[212], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_213;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_213) >> 16);
+ CopyMem(&mIdtEntries[213], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_214;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_214) >> 16);
+ CopyMem(&mIdtEntries[214], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_215;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_215) >> 16);
+ CopyMem(&mIdtEntries[215], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_216;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_216) >> 16);
+ CopyMem(&mIdtEntries[216], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_217;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_217) >> 16);
+ CopyMem(&mIdtEntries[217], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_218;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_218) >> 16);
+ CopyMem(&mIdtEntries[218], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_219;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_219) >> 16);
+ CopyMem(&mIdtEntries[219], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_220;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_220) >> 16);
+ CopyMem(&mIdtEntries[220], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_221;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_221) >> 16);
+ CopyMem(&mIdtEntries[221], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_222;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_222) >> 16);
+ CopyMem(&mIdtEntries[222], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_223;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_223) >> 16);
+ CopyMem(&mIdtEntries[223], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_224;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_224) >> 16);
+ CopyMem(&mIdtEntries[224], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_225;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_225) >> 16);
+ CopyMem(&mIdtEntries[225], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_226;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_226) >> 16);
+ CopyMem(&mIdtEntries[226], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_227;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_227) >> 16);
+ CopyMem(&mIdtEntries[227], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_228;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_228) >> 16);
+ CopyMem(&mIdtEntries[228], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_229;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_229) >> 16);
+ CopyMem(&mIdtEntries[229], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_230;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_230) >> 16);
+ CopyMem(&mIdtEntries[230], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_231;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_231) >> 16);
+ CopyMem(&mIdtEntries[231], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_232;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_232) >> 16);
+ CopyMem(&mIdtEntries[232], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_233;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_233) >> 16);
+ CopyMem(&mIdtEntries[233], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_234;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_234) >> 16);
+ CopyMem(&mIdtEntries[234], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_235;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_235) >> 16);
+ CopyMem(&mIdtEntries[235], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_236;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_236) >> 16);
+ CopyMem(&mIdtEntries[236], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_237;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_237) >> 16);
+ CopyMem(&mIdtEntries[237], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_238;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_238) >> 16);
+ CopyMem(&mIdtEntries[238], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_239;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_239) >> 16);
+ CopyMem(&mIdtEntries[239], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_240;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_240) >> 16);
+ CopyMem(&mIdtEntries[240], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_241;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_241) >> 16);
+ CopyMem(&mIdtEntries[241], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_242;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_242) >> 16);
+ CopyMem(&mIdtEntries[242], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_243;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_243) >> 16);
+ CopyMem(&mIdtEntries[243], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_244;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_244) >> 16);
+ CopyMem(&mIdtEntries[244], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_245;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_245) >> 16);
+ CopyMem(&mIdtEntries[245], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_246;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_246) >> 16);
+ CopyMem(&mIdtEntries[246], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_247;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_247) >> 16);
+ CopyMem(&mIdtEntries[247], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_248;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_248) >> 16);
+ CopyMem(&mIdtEntries[248], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_249;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_249) >> 16);
+ CopyMem(&mIdtEntries[249], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_250;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_250) >> 16);
+ CopyMem(&mIdtEntries[250], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_251;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_251) >> 16);
+ CopyMem(&mIdtEntries[251], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_252;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_252) >> 16);
+ CopyMem(&mIdtEntries[252], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_253;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_253) >> 16);
+ CopyMem(&mIdtEntries[253], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_254;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_254) >> 16);
+ CopyMem(&mIdtEntries[254], &IdtEntry, sizeof (IdtEntry));
+
+ IdtEntry.Bits.OffsetLow = (UINT16)(UINTN)Fidt_255;
+ IdtEntry.Bits.OffsetHigh = (UINT16)(((UINTN)Fidt_255) >> 16);
+ CopyMem(&mIdtEntries[255], &IdtEntry, sizeof (IdtEntry));
+#endif
+}
+
+
diff --git BhyvePkg/Csm/BhyveCsm16/GNUmakefile BhyvePkg/Csm/BhyveCsm16/GNUmakefile
new file mode 100644
index 0000000..f345730
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/GNUmakefile
@@ -0,0 +1,68 @@
+#
+# Copyright (c) 2014, Pluribus Networks, Inc.
+#
+# This program and the accompanying materials are licensed and made
+# available under the terms and conditions of the BSD License which
+# accompanies this distribution. The full text of the license may be
+# found at http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+# BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+# EXPRESS OR IMPLIED.
+#
+
+CC ?= gcc
+LD ?= ld
+OBJCOPY ?= objcopy
+ASFLAGS = -m64 -nostdinc -nostdlib -ffreestanding
+CFLAGS = -m64 -nostdinc -nostdlib -ffreestanding \
+ -fno-common -fshort-wchar -mno-red-zone \
+ -mno-mmx -mno-sse -Wimplicit-function-declaration
+
+CPPFLAGS = -DEFIAPI="__attribute__((ms_abi))" \
+ -DNO_BUILTIN_VA_FUNCS \
+ ${DEBUG_PORT} \
+ -DBUILD_DATE=${BUILD_DATE} \
+ -I${WORKSPACE}/MdePkg/Include \
+ -I${WORKSPACE}/MdePkg/Include/X64 \
+ -I${WORKSPACE}/IntelFrameworkPkg/Include \
+ -I${WORKSPACE}/BhyvePkg/Include
+
+OBJECTS = Bin/BhyveCsm16Asm.o \
+ Bin/BhyveCsm16.o \
+ Bin/Bios.o \
+ Bin/Legacy8254.o \
+ Bin/Keyboard.o \
+ Bin/Memory.o \
+ Bin/Mmu.o \
+ Bin/Printf.o \
+ Bin/String.o \
+ Bin/Video.o \
+ Bin/ter-u16n-IBM-CP437.o
+
+DEBUG_PORT = -DDEBUG_PORT=0x220
+
+BUILD_DATE = \"$(shell date +%D)\"
+
+MKDIR = mkdir -p
+
+all: init Bin/BhyveCsm16.bin
+
+init:
+ @$(MKDIR) Bin
+
+Bin/%.c: %.bdf
+ awk -f bdf_to_c.awk $< > $@
+
+Bin/%.o: %.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+Bin/%.o: %.S
+ $(CC) $(ASFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+Bin/BhyveCsm16.bin: linker.lds $(OBJECTS)
+ $(LD) -Tlinker.lds -m elf_x86_64_fbsd -o Bin/BhyveCsm16.raw.o -Map Bin/BhyveCsm16.bin.map $(OBJECTS)
+ $(OBJCOPY) --only-section .raw --output-target binary --pad-to 0x100000 Bin/BhyveCsm16.raw.o Bin/BhyveCsm16.bin
+
+clean:
+ $(RM) $(OBJECTS) Bin/BhyveCsm16.raw.o Bin/BhyveCsm16.bin.map
diff --git BhyvePkg/Csm/BhyveCsm16/Keyboard.c BhyvePkg/Csm/BhyveCsm16/Keyboard.c
new file mode 100644
index 0000000..a87746a
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Keyboard.c
@@ -0,0 +1,728 @@
+/*
+ * Copyright (c) 2015, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+
+#include "BhyveCsm16.h"
+
+#include "Debug.h"
+#include "Printf.h"
+
+#define KEYBOARD_MAX_TRY 256
+
+#define KEYBOARD_8042_DATA_REGISTER 0x60
+#define KEYBOARD_8042_STATUS_REGISTER 0x64
+#define KEYBOARD_8042_COMMAND_REGISTER 0x64
+
+#define KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA 0x1
+#define KEYBOARD_STATUS_REGISTER_HAS_INPUT_DATA 0x2
+
+#define KEYBOARD_8042_COMMAND_WRITE 0x60
+#define KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE 0xA7
+#define KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST 0xAA
+#define KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE 0xAD
+#define KEYBOARD_8042_COMMAND_ENABLE_KEYBOARD_INTERFACE 0xAE
+
+#define KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET 0xF0
+#define KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA 0xF4
+#define KEYBOARD_8048_RETURN_8042_ACK 0xFA
+
+// KEYBOARD COMMAND BYTE
+// 7: Reserved
+// 6: PC/XT translation mode convert
+// 5: Disable Auxiliary device interface
+// 4: Disable keyboard interface
+// 3: Reserved
+// 2: System Flag: selftest successful
+// 1: Enable Auxiliary device interrupt
+// 0: Enable Keyboard interrupt
+#define KEYBOARD_CMMBYTE_TRANSLATE (0x1 << 6)
+#define KEYBOARD_CMMBYTE_DISABLE_AUX (0x1 << 5)
+#define KEYBOARD_CMMBYTE_DISABLE_KB (0x1 << 4)
+#define KEYBOARD_CMMBYTE_SELFTEST_OK (0x1 << 2)
+#define KEYBOARD_CMMBYTE_ENABLE_AUXINT (0x1 << 1)
+#define KEYBOARD_CMMBYTE_ENABLE_KBINT (0x1 << 0)
+
+STATIC UINT8
+KeyReadStatusRegister(VOID)
+{
+ return (IoRead8(KEYBOARD_8042_STATUS_REGISTER));
+}
+
+STATIC UINT8
+KeyReadDataRegister(VOID)
+{
+ return (IoRead8(KEYBOARD_8042_DATA_REGISTER));
+}
+
+STATIC VOID
+KeyWriteDataRegister(UINT8 Data)
+{
+ IoWrite8(KEYBOARD_8042_DATA_REGISTER, Data);
+}
+
+STATIC VOID
+KeyWriteCommandRegister(UINT8 Data)
+{
+ IoWrite8(KEYBOARD_8042_COMMAND_REGISTER, Data);
+}
+
+EFI_STATUS
+KeyboardWaitForValue(UINT8 Value)
+{
+ UINTN TryTime;
+ UINT8 Data;
+
+ DEBUG (("XXX KeyboardWaitForValue() Value=0x%x\n", Value));
+ for (TryTime = 0; TryTime < KEYBOARD_MAX_TRY; TryTime++) {
+ if ((KeyReadStatusRegister() & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) != 0) {
+ Data = KeyReadDataRegister();
+ DEBUG (("XXX KeyboardWaitForValue() Data=0%x\n", Data));
+ if (Data == Value)
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_TIMEOUT;
+}
+
+STATIC EFI_STATUS
+KeyboardRead(UINT8 *Data)
+{
+ if (KeyReadStatusRegister() & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) {
+ *Data = KeyReadDataRegister();
+ return EFI_SUCCESS;
+ }
+
+ return EFI_TIMEOUT;
+}
+
+STATIC EFI_STATUS
+KeyboardWrite (
+ IN UINT8 Data
+ )
+{
+ UINTN TryTime;
+
+ //
+ // Wait For Input Buffer Empty
+ //
+ for (TryTime = 0; TryTime < KEYBOARD_MAX_TRY; TryTime++) {
+ if ((KeyReadStatusRegister() & KEYBOARD_STATUS_REGISTER_HAS_INPUT_DATA) == 0)
+ break;
+ }
+
+ if (TryTime == KEYBOARD_MAX_TRY) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ KeyWriteDataRegister(Data);
+
+ return EFI_SUCCESS;
+}
+
+STATIC EFI_STATUS
+KeyboardCommand (
+ IN UINT8 Data
+ )
+{
+ UINTN TryTime;
+
+ //
+ // Wait For Input Buffer Empty
+ //
+ for (TryTime = 0; TryTime < KEYBOARD_MAX_TRY; TryTime++) {
+ if ((KeyReadStatusRegister() & KEYBOARD_STATUS_REGISTER_HAS_INPUT_DATA) == 0)
+ break;
+ }
+
+ if (TryTime == KEYBOARD_MAX_TRY) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ KeyWriteCommandRegister(Data);
+
+ //
+ // Wait For Input Buffer Empty again
+ //
+ for (TryTime = 0; TryTime < KEYBOARD_MAX_TRY; TryTime++) {
+ if ((KeyReadStatusRegister() & KEYBOARD_STATUS_REGISTER_HAS_INPUT_DATA) == 0)
+ break;
+ }
+
+ if (TryTime == KEYBOARD_MAX_TRY) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ return EFI_SUCCESS;
+}
+
+#define SCANCODE_CONTROL 0x1d
+#define SCANCODE_L_SHIFT 0x2a
+#define SCANCODE_R_SHIFT 0x36
+#define SCANCODE_ALT 0x38
+#define SCANCODE_CAPS_LOCK 0x3a
+#define SCANCODE_NUM_LOCK 0x45
+#define SCANCODE_SCROLL_LOCK 0x46
+#define SCANCODE_INSERT 0x52
+
+struct KeyEntry {
+ UINT16 Normal;
+ UINT16 Shift;
+ UINT16 Control;
+ UINT16 Alt;
+};
+
+struct KeyEntry KeyOneByteEntries[] = {
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 0 */
+ { 0x011b, 0x011b, 0x011b, 0xffff }, /* key 1 - Escape key */
+ { 0x0231, 0x0221, 0xffff, 0x7800 }, /* key 2 - '1' */
+ { 0x0332, 0x0340, 0x0300, 0x7900 }, /* key 3 - '2' */
+ { 0x0433, 0x0423, 0xffff, 0x7a00 }, /* key 4 - '3' */
+ { 0x0534, 0x0524, 0xffff, 0x7b00 }, /* key 5 - '4' */
+ { 0x0635, 0x0625, 0xffff, 0x7c00 }, /* key 6 - '5' */
+ { 0x0736, 0x075e, 0x071e, 0x7d00 }, /* key 7 - '6' */
+ { 0x0837, 0x0826, 0xffff, 0x7e00 }, /* key 8 - '7' */
+ { 0x0938, 0x092a, 0xffff, 0x7f00 }, /* key 9 - '8' */
+ { 0x0a39, 0x0a28, 0xffff, 0x8000 }, /* key 10 - '9' */
+ { 0x0b30, 0x0b29, 0xffff, 0x8100 }, /* key 11 - '0' */
+ { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200 }, /* key 12 - '-' */
+ { 0x0d3d, 0x0d2b, 0xffff, 0x8300 }, /* key 13 - '=' */
+ { 0x0e08, 0x0e08, 0x0e7f, 0xffff }, /* key 14 - backspace */
+ { 0x0f09, 0x0f00, 0xffff, 0xffff }, /* key 15 - tab */
+ { 0x1071, 0x1051, 0x1011, 0x1000 }, /* key 16 - 'Q' */
+ { 0x1177, 0x1157, 0x1117, 0x1100 }, /* key 17 - 'W' */
+ { 0x1265, 0x1245, 0x1205, 0x1200 }, /* key 18 - 'E' */
+ { 0x1372, 0x1352, 0x1312, 0x1300 }, /* key 19 - 'R' */
+ { 0x1474, 0x1454, 0x1414, 0x1400 }, /* key 20 - 'T' */
+ { 0x1579, 0x1559, 0x1519, 0x1500 }, /* key 21 - 'Y' */
+ { 0x1675, 0x1655, 0x1615, 0x1600 }, /* key 22 - 'U' */
+ { 0x1769, 0x1749, 0x1709, 0x1700 }, /* key 23 - 'I' */
+ { 0x186f, 0x184f, 0x180f, 0x1800 }, /* key 24 - 'O' */
+ { 0x1970, 0x1950, 0x1910, 0x1900 }, /* key 25 - 'P' */
+ { 0x1a5b, 0x1a7b, 0x1a1b, 0xffff }, /* key 26 - '[' */
+ { 0x1b5d, 0x1b7d, 0x1b1d, 0xffff }, /* key 27 - ']' */
+ { 0x1c0d, 0x1c0d, 0x1c0a, 0xffff }, /* key 28 - CR */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 29 - left control */
+ { 0x1e61, 0x1e41, 0x1e01, 0x1e00 }, /* key 30 - 'A' */
+ { 0x1f73, 0x1f53, 0x1f13, 0x1f00 }, /* key 31 - 'S' */
+ { 0x2064, 0x2044, 0x2004, 0x2000 }, /* key 32 - 'D' */
+ { 0x2166, 0x2146, 0x2106, 0x2100 }, /* key 33 - 'F' */
+ { 0x2267, 0x2247, 0x2207, 0x2200 }, /* key 34 - 'G' */
+ { 0x2368, 0x2348, 0x2308, 0x2300 }, /* key 35 - 'H' */
+ { 0x246a, 0x244a, 0x240a, 0x2400 }, /* key 36 - 'J' */
+ { 0x256b, 0x254b, 0x250b, 0x2500 }, /* key 37 - 'K' */
+ { 0x266c, 0x264c, 0x260c, 0x2600 }, /* key 38 - 'L' */
+ { 0x273b, 0x273a, 0xffff, 0xffff }, /* key 39 - ';' */
+ { 0x2827, 0x2822, 0xffff, 0xffff }, /* key 40 - ''' */
+ { 0x2960, 0x297e, 0xffff, 0xffff }, /* key 41 - '`' */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 42 - left shift */
+ { 0x2b5c, 0x2b7c, 0x2b1c, 0xffff }, /* key 43 - '' */
+ { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00 }, /* key 44 - 'Z' */
+ { 0x2d78, 0x2d58, 0x2d18, 0x2d00 }, /* key 45 - 'X' */
+ { 0x2e63, 0x2e43, 0x2e03, 0x2e00 }, /* key 46 - 'C' */
+ { 0x2f76, 0x2f56, 0x2f16, 0x2f00 }, /* key 47 - 'V' */
+ { 0x3062, 0x3042, 0x3002, 0x3000 }, /* key 48 - 'B' */
+ { 0x316e, 0x314e, 0x310e, 0x3100 }, /* key 49 - 'N' */
+ { 0x326d, 0x324d, 0x320d, 0x3200 }, /* key 50 - 'M' */
+ { 0x332c, 0x333c, 0xffff, 0xffff }, /* key 51 - ',' */
+ { 0x342e, 0x343e, 0xffff, 0xffff }, /* key 52 - '.' */
+ { 0x352f, 0x353f, 0xffff, 0xffff }, /* key 53 - '/' */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 54 - right shift - */
+ { 0x372a, 0xffff, 0x3772, 0xffff }, /* key 55 - prt-scr - */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 56 - left alt - */
+ { 0x3920, 0x3920, 0x3920, 0x3920 }, /* key 57 - space bar */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 58 - caps-lock - */
+ { 0x3b00, 0x5400, 0x5e00, 0x6800 }, /* key 59 - F1 */
+ { 0x3c00, 0x5500, 0x5f00, 0x6900 }, /* key 60 - F2 */
+ { 0x3d00, 0x5600, 0x6000, 0x6a00 }, /* key 61 - F3 */
+ { 0x3e00, 0x5700, 0x6100, 0x6b00 }, /* key 62 - F4 */
+ { 0x3f00, 0x5800, 0x6200, 0x6c00 }, /* key 63 - F5 */
+ { 0x4000, 0x5900, 0x6300, 0x6d00 }, /* key 64 - F6 */
+ { 0x4100, 0x5a00, 0x6400, 0x6e00 }, /* key 65 - F7 */
+ { 0x4200, 0x5b00, 0x6500, 0x6f00 }, /* key 66 - F8 */
+ { 0x4300, 0x5c00, 0x6600, 0x7000 }, /* key 67 - F9 */
+ { 0x4400, 0x5d00, 0x6700, 0x7100 }, /* key 68 - F10 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 69 - num-lock - */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 70 - scroll-lock - */
+ { 0x4700, 0x4737, 0x7700, 0xffff }, /* key 71 - home */
+ { 0x4800, 0x4838, 0xffff, 0xffff }, /* key 72 - cursor up */
+ { 0x4900, 0x4939, 0x8400, 0xffff }, /* key 73 - page up */
+ { 0x4a2d, 0x4a2d, 0xffff, 0xffff }, /* key 74 - minus sign */
+ { 0x4b00, 0x4b34, 0x7300, 0xffff }, /* key 75 - cursor left */
+ { 0xffff, 0x4c35, 0xffff, 0xffff }, /* key 76 - center key */
+ { 0x4d00, 0x4d36, 0x7400, 0xffff }, /* key 77 - cursor right */
+ { 0x4e2b, 0x4e2b, 0xffff, 0xffff }, /* key 78 - plus sign */
+ { 0x4f00, 0x4f31, 0x7500, 0xffff }, /* key 79 - end */
+ { 0x5000, 0x5032, 0xffff, 0xffff }, /* key 80 - cursor down */
+ { 0x5100, 0x5133, 0x7600, 0xffff }, /* key 81 - page down */
+ { 0x5200, 0x5230, 0xffff, 0xffff }, /* key 82 - insert */
+ { 0x5300, 0x532e, 0xffff, 0xffff }, /* key 83 - delete */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 84 - sys key */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 85 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key 86 */
+ { 0x8500, 0x5787, 0x8900, 0x8b00 }, /* key 87 - F11 */
+ { 0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */
+};
+
+struct KeyEntry KeyTwoByteEntries[] = {
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 0 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 1 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 2 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 3 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 4 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 5 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 6 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 7 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 8 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 9 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 a */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 b */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 c */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 d */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 e */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 f */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 10 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 11 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 12 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 13 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 14 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 15 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 16 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 17 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 18 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 19 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 1a */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 1b */
+ { 0x1c0d, 0x1c0d, 0x1c0a, 0xffff }, /* key e0 1c - numeric keypad enter */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 1d - right control */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 1e */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 1f */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 20 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 21 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 22 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 23 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 24 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 25 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 26 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 27 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 28 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 29 */
+ { 0xffff, 0xffff, 0x7200, 0xffff }, /* key e0 2a - numlock */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 2b */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 2c */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 2d */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 2e */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 2f */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 30 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 31 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 32 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 33 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 34 */
+ { 0x352f, 0x352f, 0xffff, 0xffff }, /* key e0 35 - '/' */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 36 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 37 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 38 - right alt */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 39 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 3a */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 3b */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 3c */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 3d */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 3e */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 3f */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 40 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 41 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 42 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 43 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 44 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 45 */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 46 */
+ { 0x4700, 0x4700, 0x7700, 0xffff }, /* key e0 47 - home */
+ { 0x4800, 0x4800, 0xffff, 0xffff }, /* key e0 48 - cursor up */
+ { 0x4900, 0x4900, 0x8400, 0xffff }, /* key e0 49 - page up */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 4a */
+ { 0x4b00, 0x4b00, 0x7300, 0xffff }, /* key e0 4b - cursor left */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 4c */
+ { 0x4d00, 0x4d00, 0x7400, 0xffff }, /* key e0 4d - cursor right */
+ { 0xffff, 0xffff, 0xffff, 0xffff }, /* key e0 4e */
+ { 0x4f00, 0x4f00, 0x7500, 0xffff }, /* key e0 4f - end */
+ { 0x5000, 0x5000, 0xffff, 0xffff }, /* key e0 50 - cursor down */
+ { 0x5100, 0x5100, 0x7600, 0xffff }, /* key e0 51 - page down */
+ { 0x5200, 0x5200, 0xffff, 0xffff }, /* key e0 52 - insert */
+ { 0x5300, 0x5300, 0xffff, 0xffff }, /* key e0 53 - delete */
+};
+
+static VOID
+ProcessReleasedScancode(UINT8 Scancode)
+{
+ switch (Scancode) {
+ case SCANCODE_INSERT:
+ mBdaPtr->KeyboardStatus1 &= ~KBSF1_INSERT_BIT;
+ break;
+ case SCANCODE_CAPS_LOCK:
+ mBdaPtr->KeyboardStatus1 &= ~KBSF1_CAPS_LOCK_BIT;
+ break;
+ case SCANCODE_NUM_LOCK:
+ mBdaPtr->KeyboardStatus1 &= ~KBSF1_NUM_LOCK_BIT;
+ break;
+ case SCANCODE_SCROLL_LOCK:
+ mBdaPtr->KeyboardStatus1 &= ~KBSF1_SCROLL_LOCK_BIT;
+ break;
+ case SCANCODE_ALT:
+ mBdaPtr->KeyboardStatus1 &= ~KBSF1_ALT_PRESSED;
+ break;
+ case SCANCODE_CONTROL:
+ mBdaPtr->KeyboardStatus1 &= ~KBSF1_CTRL_PRESSED;
+ break;
+ case SCANCODE_L_SHIFT:
+ mBdaPtr->KeyboardStatus1 &= ~KBSF1_LEFT_SHIFT_PRESSED;
+ break;
+ case SCANCODE_R_SHIFT:
+ mBdaPtr->KeyboardStatus1 &= ~KBSF1_RIGHT_SHIFT_PRESSED;
+ break;
+ }
+}
+
+static VOID
+ProcessPressedScancode(UINT8 Scancode)
+{
+ struct KeyEntry *KeyEntries;
+ UINT16 Key;
+ UINT16 Newtail;
+
+ DEBUG (("XXX ProcessPressedScancode()\n"));
+ switch (Scancode) {
+ case SCANCODE_INSERT:
+ mBdaPtr->KeyboardStatus1 |= KBSF1_INSERT_BIT;
+ break;
+ case SCANCODE_CAPS_LOCK:
+ mBdaPtr->KeyboardStatus1 |= KBSF1_CAPS_LOCK_BIT;
+ break;
+ case SCANCODE_NUM_LOCK:
+ mBdaPtr->KeyboardStatus1 |= KBSF1_NUM_LOCK_BIT;
+ break;
+ case SCANCODE_SCROLL_LOCK:
+ mBdaPtr->KeyboardStatus1 |= KBSF1_SCROLL_LOCK_BIT;
+ break;
+ case SCANCODE_ALT:
+ mBdaPtr->KeyboardStatus1 |= KBSF1_ALT_PRESSED;
+ break;
+ case SCANCODE_CONTROL:
+ mBdaPtr->KeyboardStatus1 |= KBSF1_CTRL_PRESSED;
+ break;
+ case SCANCODE_L_SHIFT:
+ mBdaPtr->KeyboardStatus1 |= KBSF1_LEFT_SHIFT_PRESSED;
+ break;
+ case SCANCODE_R_SHIFT:
+ mBdaPtr->KeyboardStatus1 |= KBSF1_RIGHT_SHIFT_PRESSED;
+ break;
+ }
+
+ if ((mBdaPtr->KeyboardStatus3 & KBSF3_LAST_CODE_WAS_E0) != 0) {
+ DEBUG(("XXX E0 Scancode = 0x%x\n", Scancode));
+ KeyEntries = KeyTwoByteEntries;
+ DEBUG(("XXX KeyEntries = 0x%p\n", KeyEntries));
+ DEBUG(("XXX KeyEntries[0].Normal = 0x%x\n", KeyEntries[0].Normal));
+ DEBUG(("XXX KeyEntries[0x10].Normal = 0x%x\n", KeyEntries[0x10].Normal));
+ DEBUG(("XXX KeyEntries[0x1c].Normal = 0x%x\n", KeyEntries[0x1c].Normal));
+ DEBUG(("XXX KeyEntries[0x35].Normal = 0x%x\n", KeyEntries[0x35].Normal));
+ DEBUG(("XXX KeyEntries[0x50].Normal = 0x%x\n", KeyEntries[0x50].Normal));
+ } else {
+ KeyEntries = KeyOneByteEntries;
+ }
+
+ if ((mBdaPtr->KeyboardStatus1 & KBSF1_ALT_PRESSED) != 0) {
+ Key = KeyEntries[Scancode].Alt;
+ } else if ((mBdaPtr->KeyboardStatus1 & KBSF1_CTRL_PRESSED) != 0) {
+ Key = KeyEntries[Scancode].Control;
+ } else if ((mBdaPtr->KeyboardStatus1 & KBSF1_LEFT_SHIFT_PRESSED) != 0 ||
+ (mBdaPtr->KeyboardStatus1 & KBSF1_RIGHT_SHIFT_PRESSED) != 0) {
+ Key = KeyEntries[Scancode].Shift;
+ } else {
+ Key = KeyEntries[Scancode].Normal;
+ }
+
+ DEBUG(("XXX Key = 0x%x\n", Key));
+ if (Key == 0xffff)
+ return;
+
+ Newtail = mBdaPtr->KeyBufferTail + 2;
+ if (Newtail == mBdaPtr->KeyBufferEnd)
+ Newtail = mBdaPtr->KeyBufferStart;
+
+ if (Newtail == mBdaPtr->KeyBufferHead)
+ return;
+
+ *(UINT16 *)((UINT8 *)(UINTN)0x400 + mBdaPtr->KeyBufferTail) = Key;
+ mBdaPtr->KeyBufferTail = Newtail;
+}
+
+static VOID
+ProcessScancode(UINT8 Scancode)
+{
+ DEBUG(("XXX ProcessScancode() 0x%x\n", Scancode));
+ if (Scancode == 0xe0) {
+ mBdaPtr->KeyboardStatus3 |= KBSF3_LAST_CODE_WAS_E0;
+ return;
+ }
+ if (Scancode == 0xe1) {
+ mBdaPtr->KeyboardStatus3 |= KBSF3_LAST_CODE_WAS_E1;
+ return;
+ }
+
+ if ((Scancode & 0x80) != 0) {
+ ProcessReleasedScancode(Scancode & 0x7F);
+ } else {
+ ProcessPressedScancode(Scancode);
+ }
+
+ if (Scancode != 0xe0) {
+ mBdaPtr->KeyboardStatus3 &= ~KBSF3_LAST_CODE_WAS_E0;
+ }
+ if (Scancode != 0xe1) {
+ mBdaPtr->KeyboardStatus3 &= ~KBSF3_LAST_CODE_WAS_E1;
+ }
+}
+
+STATIC VOID
+InterruptVector0x16ReadScancode(EFI_IA32_REGISTER_SET *Regs)
+{
+ UINT16 Key;
+
+ DEBUG (("XXX InterruptVector0x16ReadScancode()\n"));
+ DEBUG (("XXX KeyBufferHead = 0x%x KeyBufferTail = 0x%x\n", mBdaPtr->KeyBufferHead, mBdaPtr->KeyBufferTail));
+
+ do {
+ EnableInterrupts();
+ DisableInterrupts();
+ } while (mBdaPtr->KeyBufferHead == mBdaPtr->KeyBufferTail);
+
+ Key = *(UINT16 *)((UINT8 *)(UINTN)0x400 + mBdaPtr->KeyBufferHead);
+ Regs->X.AX = Key;
+ Regs->E.EFlags.ZF = 0;
+ switch (Regs->H.AL) {
+ case '\n':
+ DEBUG (("XXX InterruptVector0x16ReadScancode() Regs->H.AL=0%x '\\n'\n", Regs->H.AL));
+ break;
+ case '\r':
+ DEBUG (("XXX InterruptVector0x16ReadScancode() Regs->H.AL=0%x '\\r'\n", Regs->H.AL));
+ break;
+ default:
+ DEBUG (("XXX InterruptVector0x16ReadScancode() Regs->H.AL=0%x ('%c')\n", Regs->H.AL, Regs->H.AL));
+ break;
+ }
+ DEBUG (("XXX InterruptVector0x16ReadScancode() Regs->H.AH=0%x\n", Regs->H.AH));
+ DEBUG (("XXX InterruptVector0x16ReadScancode() Regs->X.AX=0%x\n", Regs->X.AX));
+
+ mBdaPtr->KeyBufferHead += 2;
+ if (mBdaPtr->KeyBufferHead == mBdaPtr->KeyBufferEnd)
+ mBdaPtr->KeyBufferHead = mBdaPtr->KeyBufferStart;
+
+ DEBUG (("XXX InterruptVector0x16ReadScancode() KeyBufferHead = 0x%x KeyBufferTail = 0x%x\n", mBdaPtr->KeyBufferHead, mBdaPtr->KeyBufferTail));
+}
+
+STATIC VOID
+InterruptVector0x16PreviewScancode(EFI_IA32_REGISTER_SET *Regs)
+{
+ UINT16 Key;
+
+ //DEBUG (("XXX InterruptVector0x16PreviewScancode()\n"));
+ //DEBUG (("XXX InterruptVector0x16PreviewScancode() KeyBufferHead = 0x%x KeyBufferTail = 0x%x\n", mBdaPtr->KeyBufferHead, mBdaPtr->KeyBufferTail));
+ if (mBdaPtr->KeyBufferHead == mBdaPtr->KeyBufferTail) {
+ Regs->E.EFlags.ZF = 1;
+ } else {
+ Regs->E.EFlags.ZF = 0;
+ Key = *(UINT16 *)((UINT8 *)(UINTN)0x400 + mBdaPtr->KeyBufferHead);
+ Regs->X.AX = Key;
+ switch (Regs->H.AL) {
+ case '\n':
+// DEBUG (("XXX InterruptVector0x16PreviewScancode() Regs->H.AL=0%x '\\n'\n", Regs->H.AL));
+ break;
+ case '\r':
+// DEBUG (("XXX InterruptVector0x16PreviewScancode() Regs->H.AL=0%x '\\r'\n", Regs->H.AL));
+ break;
+ default:
+// DEBUG (("XXX InterruptVector0x16PreviewScancode() Regs->H.AL=0%x ('%c')\n", Regs->H.AL, Regs->H.AL));
+ break;
+ }
+// DEBUG (("XXX InterruptVector0x16PreviewScancode() Regs->H.AH=0%x\n", Regs->H.AH));
+// DEBUG (("XXX InterruptVector0x16PreviewScancode() Regs->X.AX=0%x\n", Regs->X.AX));
+ }
+}
+
+/*
+ * Keyboard I/O
+ */
+VOID
+InterruptVector0x16(EFI_IA32_REGISTER_SET *Regs)
+{
+// DEBUG (("XXX InterruptVector0x16() Regs->H.AL=0%x\n", Regs->H.AL));
+// DEBUG (("XXX InterruptVector0x16() Regs->H.AH=0%x\n", Regs->H.AH));
+// DEBUG (("XXX InterruptVector0x16() Regs->X.AX=0%x\n", Regs->X.AX));
+
+ EnableInterrupts();
+ DisableInterrupts();
+
+ switch (Regs->H.AH) {
+ case 0x0: /* Read Keyboard Input */
+// DEBUG (("XXX InterruptVector0x16() Read Keyboard Input\n"));
+ InterruptVector0x16ReadScancode(Regs);
+ break;
+ case 0x1: /* Query Keyboard Status / Preview Key */
+// DEBUG (("XXX InterruptVector0x16() Query Keyboard Status / Preview Key\n"));
+ InterruptVector0x16PreviewScancode(Regs);
+ break;
+ case 0x2: /* Read Keyboard Shift Status */
+// DEBUG (("XXX InterruptVector0x16() Read Keyboard Shift Status\n"));
+ Regs->H.AL = mBdaPtr->KeyboardStatus1;
+ DEBUG (("XXX Regs->H.AL = 0x%x\n", Regs->H.AL));
+ break;
+ case 0x3: /* Set Keyboard Typematic Rate */
+ break;
+ case 0x5: /* Store keycode */
+ Regs->H.AL = 1;
+ break;
+ case 0x10:
+// DEBUG (("XXX InterruptVector0x16() Read Extended Keyboard Input\n"));
+ InterruptVector0x16ReadScancode(Regs);
+ break;
+ case 0x11: /* Query Extended Keyboard Status / Preview Key */
+// DEBUG (("XXX InterruptVector0x16() Query Extended Keyboard Status / Preview Key\n"));
+ InterruptVector0x16PreviewScancode(Regs);
+ break;
+ case 0x12: /* Read Extended Keyboard Shift Status */
+// DEBUG (("XXX InterruptVector0x16() Read Extended Keyboard Shift Status\n"));
+ Regs->H.AL = mBdaPtr->KeyboardStatus1;
+ Regs->H.AH = mBdaPtr->KeyboardStatus2;
+ break;
+ default:
+ DEBUG (("XXX InterruptVector0x16() Regs->H.AL=0%x\n", Regs->H.AL));
+ DEBUG (("XXX InterruptVector0x16() Regs->H.AH=0%x\n", Regs->H.AH));
+ DEBUG (("XXX InterruptVector0x16() Regs->X.AX=0%x\n", Regs->X.AX));
+ DEBUG (("XXX keyboard unhandled\n"));
+// for (;;) ;
+ break;
+ }
+}
+
+VOID
+KeyboardInitialize(VOID)
+{
+ EFI_STATUS Status;
+ UINT8 CommandByte;
+ UINTN TryTime;
+
+ mBdaPtr->KeyBufferStart = 0x1E;
+ mBdaPtr->KeyBufferEnd = 0x3E;
+ mBdaPtr->KeyBufferHead = mBdaPtr->KeyBufferTail = mBdaPtr->KeyBufferStart;
+
+ mBdaPtr->KeyboardStatus3 = KBSF3_ENHANCED_KBD;
+
+ if ((KeyReadStatusRegister() & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) != 0) {
+ while (!EFI_ERROR (Status) && TryTime < KEYBOARD_MAX_TRY) {
+ Status = KeyboardRead(&CommandByte);
+ TryTime ++;
+ }
+
+ if (TryTime == KEYBOARD_MAX_TRY) {
+ return;
+ }
+ }
+
+ Status = KeyboardCommand(KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = KeyboardCommand(KEYBOARD_8042_COMMAND_DISABLE_MOUSE_INTERFACE);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = KeyboardCommand(KEYBOARD_8042_COMMAND_CONTROLLER_SELF_TEST);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = KeyboardWaitForValue(0x55);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = KeyboardWrite(KEYBOARD_8048_COMMAND_SELECT_SCAN_CODE_SET);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = KeyboardWaitForValue(KEYBOARD_8048_RETURN_8042_ACK);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = KeyboardWrite(0x02); // scan code set 2
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = KeyboardWaitForValue(KEYBOARD_8048_RETURN_8042_ACK);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = KeyboardWrite(KEYBOARD_8048_COMMAND_CLEAR_OUTPUT_DATA);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = KeyboardWaitForValue(KEYBOARD_8048_RETURN_8042_ACK);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = KeyboardCommand(KEYBOARD_8042_COMMAND_WRITE);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ Status = KeyboardWrite(KEYBOARD_CMMBYTE_TRANSLATE |
+ KEYBOARD_CMMBYTE_DISABLE_AUX |
+ KEYBOARD_CMMBYTE_SELFTEST_OK |
+ KEYBOARD_CMMBYTE_ENABLE_KBINT);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ DEBUG (("XXX KeyboardInitialize() done (0x%lx)\n", ReadTsc()));
+}
+
+VOID
+InterruptVector0x09(EFI_IA32_REGISTER_SET *Regs)
+{
+ UINT8 Data;
+
+ DEBUG (("XXX InterruptVector0x09() (0x%lx)\n", ReadTsc()));
+
+ KeyboardCommand(KEYBOARD_8042_COMMAND_DISABLE_KEYBOARD_INTERFACE);
+
+ if ((KeyReadStatusRegister() & KEYBOARD_STATUS_REGISTER_HAS_OUTPUT_DATA) != 0) {
+ Data = KeyReadDataRegister();
+ ProcessScancode(Data);
+ }
+
+ KeyboardCommand(KEYBOARD_8042_COMMAND_ENABLE_KEYBOARD_INTERFACE);
+
+ mLegacy8259->EndOfInterrupt(mLegacy8259, Efi8259Irq1);
+
+ DEBUG (("XXX InterruptVector0x09() done\n"));
+}
+
diff --git BhyvePkg/Csm/BhyveCsm16/Keyboard.h BhyvePkg/Csm/BhyveCsm16/Keyboard.h
new file mode 100644
index 0000000..168a440
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Keyboard.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#ifndef _BHYVECSM16_KEYBOARD_H_
+#define _BHYVECSM16_KEYBOARD_H_
+
+VOID
+KeyboardInitialize(VOID);
+
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/Legacy8254.c BhyvePkg/Csm/BhyveCsm16/Legacy8254.c
new file mode 100644
index 0000000..8e93746
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Legacy8254.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+
+#include "BhyveCsm16.h"
+
+#include "Debug.h"
+#include "Legacy8254.h"
+
+//
+// 8254 Timer registers
+//
+#define LEGACY_8254_TIMER0_COUNT_PORT 0x40
+#define LEGACY_8254_TIMER_CONTROL_PORT 0x43
+
+//
+// Timer 0, Read/Write LSB then MSB, Rate generator, binary count use.
+//
+#define LEGACY_8254_TIMER0_CONTROL_WORD 0x34
+
+VOID
+Legacy8254SetCount (
+ IN UINT16 Count
+ )
+{
+ DEBUG(("XXX Legacy8254SetCount() Count=0x%x\n", Count));
+ IoWrite8 (LEGACY_8254_TIMER_CONTROL_PORT, LEGACY_8254_TIMER0_CONTROL_WORD);
+ IoWrite8 (LEGACY_8254_TIMER0_COUNT_PORT, (UINT8) (Count & 0xFF));
+ IoWrite8 (LEGACY_8254_TIMER0_COUNT_PORT, (UINT8) ((Count >> 8) & 0xFF));
+}
+
+
diff --git BhyvePkg/Csm/BhyveCsm16/Legacy8254.h BhyvePkg/Csm/BhyveCsm16/Legacy8254.h
new file mode 100644
index 0000000..7ab4abd
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Legacy8254.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#ifndef _BHYVECSM16_LEGACY8254_H_
+#define _BHYVECSM16_LEGACY8254_H_
+
+VOID
+Legacy8254SetCount (
+ IN UINT16 Count
+ );
+
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/Memory.c BhyvePkg/Csm/BhyveCsm16/Memory.c
new file mode 100644
index 0000000..f3d4793
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Memory.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+
+#include "Debug.h"
+#include "Printf.h"
+
+struct MemPool {
+ UINT32 MemPoolBase;
+ UINT32 MemPoolSize;
+};
+
+struct MemPool ESegmentMemPool;
+struct MemPool FSegmentMemPool;
+
+VOID
+ESegmentInitializePool (
+ UINT32 MemoryBase,
+ UINT32 MemoryMax
+ )
+{
+ DEBUG (("XXX ESegmentInitializePool() Base 0x%x Max 0x%x\n",
+ MemoryBase, MemoryMax));
+
+ ESegmentMemPool.MemPoolBase = MemoryBase;
+ ESegmentMemPool.MemPoolSize = MemoryMax - MemoryBase;
+}
+
+VOID
+FSegmentInitializePool (
+ UINT32 MemoryBase,
+ UINT32 MemoryMax
+ )
+{
+ DEBUG (("XXX FSegmentInitializePool() Base 0x%x Max 0x%x\n",
+ MemoryBase, MemoryMax));
+
+ FSegmentMemPool.MemPoolBase = MemoryBase;
+ FSegmentMemPool.MemPoolSize = MemoryMax - MemoryBase;
+}
+
+EFI_STATUS
+ESegmentAllocatePool (
+ UINT32 MemorySize,
+ UINT32 Alignment,
+ UINT32 *Address
+ )
+{
+ UINT32 Base;
+
+ DEBUG (("XXX ESegmentAllocatePool() Size 0x%x Alignment = 0x%x\n",
+ MemorySize, Alignment));
+
+ Base = ((ESegmentMemPool.MemPoolBase + (Alignment - 1)) & ~(Alignment - 1));
+ if (Base - ESegmentMemPool.MemPoolBase > ESegmentMemPool.MemPoolSize) {
+ return (-1);
+ }
+
+ DEBUG (("XXX ESegmentAllocatePool() Address = 0x%x\n", Base));
+ *Address = Base;
+ ESegmentMemPool.MemPoolSize -= (Base - ESegmentMemPool.MemPoolBase + MemorySize);
+ ESegmentMemPool.MemPoolBase = Base + MemorySize;
+
+ return (EFI_SUCCESS);
+}
+
+EFI_STATUS
+FSegmentAllocatePool (
+ UINT32 MemorySize,
+ UINT32 Alignment,
+ UINT32 *Address
+ )
+{
+ UINT32 Base;
+
+ DEBUG (("XXX FSegmentAllocatePool() Size 0x%x Alignment = 0x%x\n",
+ MemorySize, Alignment));
+
+ Base = ((FSegmentMemPool.MemPoolBase + (Alignment - 1)) & ~(Alignment - 1));
+ if (Base - FSegmentMemPool.MemPoolBase > FSegmentMemPool.MemPoolSize) {
+ return (-1);
+ }
+
+ DEBUG (("XXX FSegmentAllocatePool() Address = 0x%x\n", Base));
+ *Address = Base;
+ FSegmentMemPool.MemPoolSize -= (Base - FSegmentMemPool.MemPoolBase + MemorySize);
+ FSegmentMemPool.MemPoolBase = Base + MemorySize;
+
+ return (EFI_SUCCESS);
+}
diff --git BhyvePkg/Csm/BhyveCsm16/Memory.h BhyvePkg/Csm/BhyveCsm16/Memory.h
new file mode 100644
index 0000000..1b23517
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Memory.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#ifndef _BHYVECSM16_MEMORY_H_
+#define _BHYVECSM16_MEMORY_H_
+
+VOID
+ESegmentInitializePool (
+ UINT32 MemoryBase,
+ UINT32 MemoryMax
+ );
+
+VOID
+FSegmentInitializePool (
+ UINT32 MemoryBase,
+ UINT32 MemoryMax
+ );
+
+
+EFI_STATUS
+ESegmentAllocatePool (
+ UINT32 MemorySize,
+ UINT32 Alignment,
+ UINT32 *Address
+ );
+
+EFI_STATUS
+FSegmentAllocatePool (
+ UINT32 MemorySize,
+ UINT32 Alignment,
+ UINT32 *Address
+ );
+
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/Mmu.c BhyvePkg/Csm/BhyveCsm16/Mmu.c
new file mode 100644
index 0000000..dd38350
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Mmu.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+
+#include "Mmu.h"
+
+#define EFI_MAX_ENTRY_NUM 512
+
+#define EFI_PML4_ENTRY_NUM 1
+#define EFI_PDPTE_ENTRY_NUM 4
+#define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM
+
+#define EFI_SIZE_OF_PAGE 0x1000
+#define EFI_PAGE_SIZE_2M 0x200000
+
+/*
+ * Create 4G PAE 2M pagetable
+ */
+VOID
+CreateIdentityMappingPageTables (
+ UINT8 *PageTablePtr
+ )
+{
+ UINT64 PageAddress;
+ int PML4Index;
+ int PDPTEIndex;
+ int PDEIndex;
+ X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry;
+ X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry;
+ X64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB;
+
+ PageAddress = 0;
+
+ //
+ // Page Table structure 3 level 2MB.
+ //
+ // Page-Map-Level-4-Table : bits 47-39
+ // Page-Directory-Pointer-Table : bits 38-30
+ //
+ // Page Table 2MB : Page-Directory(2M) : bits 29-21
+ //
+ //
+
+ PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;
+
+ for (PML4Index = 0; PML4Index < EFI_PML4_ENTRY_NUM; PML4Index++, PageMapLevel4Entry++) {
+ //
+ // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry
+ //
+ PageTablePtr += EFI_SIZE_OF_PAGE;
+ PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr;
+
+ //
+ // Make a Page-Map-Level-4-Table Entry
+ //
+ PageMapLevel4Entry->Uint64 = (UINT64)PageDirectoryPointerEntry;
+ PageMapLevel4Entry->Bits.ReadWrite = 1;
+ PageMapLevel4Entry->Bits.Present = 1;
+
+ for (PDPTEIndex = 0; PDPTEIndex < EFI_PDPTE_ENTRY_NUM; PDPTEIndex++, PageDirectoryPointerEntry++) {
+ //
+ // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry
+ //
+ PageTablePtr += EFI_SIZE_OF_PAGE;
+ PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)PageTablePtr;
+
+ //
+ // Make a Page-Directory-Pointer-Table Entry
+ //
+ PageDirectoryPointerEntry->Uint64 = (UINT64)PageDirectoryEntry2MB;
+ PageDirectoryPointerEntry->Bits.ReadWrite = 1;
+ PageDirectoryPointerEntry->Bits.Present = 1;
+
+ for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry2MB++) {
+ //
+ // Make a Page-Directory Entry
+ //
+ PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress;
+ PageDirectoryEntry2MB->Bits.ReadWrite = 1;
+ PageDirectoryEntry2MB->Bits.Present = 1;
+ PageDirectoryEntry2MB->Bits.MustBe1 = 1;
+
+ PageAddress += EFI_PAGE_SIZE_2M;
+ }
+ }
+ }
+}
diff --git BhyvePkg/Csm/BhyveCsm16/Mmu.h BhyvePkg/Csm/BhyveCsm16/Mmu.h
new file mode 100644
index 0000000..7dddd5c
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Mmu.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#ifndef _BHYVECSM16_MMU_H_
+#define _BHYVECSM16_MMU_H_
+
+#pragma pack(1)
+
+//
+// Page-Map Level-4 Offset (PML4) and
+// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
+//
+
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Reserved:1; // Reserved
+ UINT64 MustBeZero:2; // Must Be Zero
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K;
+
+//
+// Page Table Entry 2MB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 MustBe1:1; // Must be 1
+ UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PAT:1; //
+ UINT64 MustBeZero:8; // Must be zero;
+ UINT64 PageTableBaseAddress:31; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} X64_PAGE_TABLE_ENTRY_2M;
+
+#pragma pack()
+
+VOID
+CreateIdentityMappingPageTables (
+ UINT8 *PageTablePtr;
+ );
+
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/Printf.c BhyvePkg/Csm/BhyveCsm16/Printf.c
new file mode 100644
index 0000000..595a79a
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Printf.c
@@ -0,0 +1,912 @@
+/*
+ * Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+
+#include "BhyveCsm16.h"
+
+#define MAX_DEBUG_MESSAGE_LENGTH 256
+
+//
+// Print primitives
+//
+#define PREFIX_SIGN BIT1
+#define PREFIX_BLANK BIT2
+#define LONG_TYPE BIT4
+#define OUTPUT_UNICODE BIT6
+#define FORMAT_UNICODE BIT8
+#define PAD_TO_WIDTH BIT9
+#define ARGUMENT_UNICODE BIT10
+#define PRECISION BIT11
+#define ARGUMENT_REVERSED BIT12
+#define COUNT_ONLY_NO_PRINT BIT13
+
+UINTN DebugLevel = 1;
+
+//
+// Record date and time information
+//
+typedef struct {
+ UINT16 Year;
+ UINT8 Month;
+ UINT8 Day;
+ UINT8 Hour;
+ UINT8 Minute;
+ UINT8 Second;
+ UINT8 Pad1;
+ UINT32 Nanosecond;
+ INT16 TimeZone;
+ UINT8 Daylight;
+ UINT8 Pad2;
+} TIME;
+
+///
+/// Define the maximum number of characters that are required to
+/// encode with a NULL terminator a decimal, hexadecimal, GUID,
+/// or TIME value.
+///
+/// Maximum Length Decimal String = 28
+/// "-9,223,372,036,854,775,808"
+/// Maximum Length Hexadecimal String = 17
+/// "FFFFFFFFFFFFFFFF"
+/// Maximum Length GUID = 37
+/// "00000000-0000-0000-0000-000000000000"
+/// Maximum Length TIME = 18
+/// "12/12/2006 12:12"
+///
+#define MAXIMUM_VALUE_CHARACTERS 38
+
+///
+/// Flags bitmask values use in UnicodeValueToString() and
+/// AsciiValueToString()
+///
+#define LEFT_JUSTIFY 0x01
+#define COMMA_TYPE 0x08
+#define PREFIX_ZERO 0x20
+#define RADIX_HEX 0x80
+
+CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
+
+STATIC UINTN
+EFIAPI
+BasePrintLibSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN UINTN Flags,
+ IN CONST CHAR8 *FormatString,
+ ...
+ );
+
+STATIC UINT16
+ReadUnaligned16 (
+ IN CONST UINT16 *Buffer
+ )
+{
+#if 0
+ ASSERT (Buffer != NULL);
+#endif
+
+ return *Buffer;
+}
+
+STATIC UINT32
+ReadUnaligned32 (
+ IN CONST UINT32 *Buffer
+ )
+{
+#if 0
+ ASSERT (Buffer != NULL);
+#endif
+
+ return *Buffer;
+}
+
+STATIC UINT64
+InternalMathDivRemU64x32 (
+ IN UINT64 Dividend,
+ IN UINT32 Divisor,
+ OUT UINT32 *Remainder OPTIONAL
+ )
+{
+ if (Remainder != NULL) {
+ *Remainder = (UINT32)(Dividend % Divisor);
+ }
+ return Dividend / Divisor;
+}
+
+STATIC UINT64
+DivU64x32Remainder (
+ IN UINT64 Dividend,
+ IN UINT32 Divisor,
+ OUT UINT32 *Remainder OPTIONAL
+ )
+{
+#if 0
+ ASSERT (Divisor != 0);
+#endif
+ return InternalMathDivRemU64x32 (Dividend, Divisor, Remainder);
+}
+
+STATIC CHAR8 *
+BasePrintLibFillBuffer (
+ OUT CHAR8 *Buffer,
+ IN CHAR8 *EndBuffer,
+ IN INTN Length,
+ IN UINTN Character,
+ IN INTN Increment
+ )
+{
+ INTN Index;
+
+ for (Index = 0; Index < Length && Buffer < EndBuffer; Index++) {
+ *Buffer = (CHAR8) Character;
+ if (Increment != 1) {
+ *(Buffer + 1) = (CHAR8)(Character >> 8);
+ }
+ Buffer += Increment;
+ }
+
+ return Buffer;
+}
+
+STATIC CHAR8 *
+BasePrintLibValueToString (
+ IN OUT CHAR8 *Buffer,
+ IN INT64 Value,
+ IN UINTN Radix
+ )
+{
+ UINT32 Remainder;
+
+ //
+ // Loop to convert one digit at a time in reverse order
+ //
+ *Buffer = 0;
+ do {
+ Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder);
+ *(++Buffer) = mHexStr[Remainder];
+ } while (Value != 0);
+
+ //
+ // Return pointer of the end of filled buffer.
+ //
+ return Buffer;
+}
+
+STATIC UINTN
+EFIAPI
+BasePrintLibSPrintMarker (
+ OUT CHAR8 *Buffer,
+ IN UINTN BufferSize,
+ IN UINTN Flags,
+ IN CONST CHAR8 *Format,
+ IN VA_LIST VaListMarker, OPTIONAL
+ IN BASE_LIST BaseListMarker OPTIONAL
+ )
+{
+ CHAR8 *OriginalBuffer;
+ CHAR8 *EndBuffer;
+ CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];
+ UINT32 BytesPerOutputCharacter;
+ UINTN BytesPerFormatCharacter;
+ UINTN FormatMask;
+ UINTN FormatCharacter;
+ UINTN Width;
+ UINTN Precision;
+ INT64 Value;
+ CONST CHAR8 *ArgumentString;
+ UINTN Character;
+ GUID *TmpGuid;
+ TIME *TmpTime;
+ UINTN Count;
+ UINTN ArgumentMask;
+ INTN BytesPerArgumentCharacter;
+ UINTN ArgumentCharacter;
+ BOOLEAN Done;
+ UINTN Index;
+ CHAR8 Prefix;
+ BOOLEAN ZeroPad;
+ BOOLEAN Comma;
+ UINTN Digits;
+ UINTN Radix;
+ RETURN_STATUS Status;
+ UINT32 GuidData1;
+ UINT16 GuidData2;
+ UINT16 GuidData3;
+ UINTN LengthToReturn;
+
+ //
+ // If you change this code be sure to match the 2 versions of this function.
+ // Nearly identical logic is found in the BasePrintLib and
+ // DxePrintLibPrint2Protocol (both PrintLib instances).
+ //
+
+ if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {
+ if (BufferSize == 0) {
+ Buffer = NULL;
+ }
+ } else {
+ //
+ // We can run without a Buffer for counting only.
+ //
+ if (BufferSize == 0) {
+ return 0;
+ }
+#if 0
+ ASSERT (Buffer != NULL);
+#endif
+ }
+
+ if ((Flags & OUTPUT_UNICODE) != 0) {
+ BytesPerOutputCharacter = 2;
+ } else {
+ BytesPerOutputCharacter = 1;
+ }
+
+ LengthToReturn = 0;
+
+ //
+ // Reserve space for the Null terminator.
+ //
+ BufferSize--;
+ OriginalBuffer = Buffer;
+
+ //
+ // Set the tag for the end of the input Buffer.
+ //
+ EndBuffer = Buffer + BufferSize * BytesPerOutputCharacter;
+
+ if ((Flags & FORMAT_UNICODE) != 0) {
+ //
+ // Make sure format string cannot contain more than PcdMaximumUnicodeStringLength
+ // Unicode characters if PcdMaximumUnicodeStringLength is not zero.
+ //
+#if 0
+ ASSERT (StrSize ((CHAR16 *) Format) != 0);
+#endif
+ BytesPerFormatCharacter = 2;
+ FormatMask = 0xffff;
+ } else {
+ //
+ // Make sure format string cannot contain more than PcdMaximumAsciiStringLength
+ // Ascii characters if PcdMaximumAsciiStringLength is not zero.
+ //
+#if 0
+ ASSERT (AsciiStrSize (Format) != 0);
+#endif
+ BytesPerFormatCharacter = 1;
+ FormatMask = 0xff;
+ }
+
+ //
+ // Get the first character from the format string
+ //
+ FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
+
+ //
+ // Loop until the end of the format string is reached or the output buffer is full
+ //
+ while (FormatCharacter != 0 && Buffer < EndBuffer) {
+ //
+ // Clear all the flag bits except those that may have been passed in
+ //
+ Flags &= (OUTPUT_UNICODE | FORMAT_UNICODE | COUNT_ONLY_NO_PRINT);
+
+ //
+ // Set the default width to zero, and the default precision to 1
+ //
+ Width = 0;
+ Precision = 1;
+ Prefix = 0;
+ Comma = FALSE;
+ ZeroPad = FALSE;
+ Count = 0;
+ Digits = 0;
+
+ switch (FormatCharacter) {
+ case '%':
+ //
+ // Parse Flags and Width
+ //
+ for (Done = FALSE; !Done; ) {
+ Format += BytesPerFormatCharacter;
+ FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
+ switch (FormatCharacter) {
+ case '.':
+ Flags |= PRECISION;
+ break;
+ case '-':
+ Flags |= LEFT_JUSTIFY;
+ break;
+ case '+':
+ Flags |= PREFIX_SIGN;
+ break;
+ case ' ':
+ Flags |= PREFIX_BLANK;
+ break;
+ case ',':
+ Flags |= COMMA_TYPE;
+ break;
+ case 'L':
+ case 'l':
+ Flags |= LONG_TYPE;
+ break;
+ case '*':
+ if ((Flags & PRECISION) == 0) {
+ Flags |= PAD_TO_WIDTH;
+ if (BaseListMarker == NULL) {
+ Width = VA_ARG (VaListMarker, UINTN);
+ } else {
+ Width = BASE_ARG (BaseListMarker, UINTN);
+ }
+ } else {
+ if (BaseListMarker == NULL) {
+ Precision = VA_ARG (VaListMarker, UINTN);
+ } else {
+ Precision = BASE_ARG (BaseListMarker, UINTN);
+ }
+ }
+ break;
+ case '0':
+ if ((Flags & PRECISION) == 0) {
+ Flags |= PREFIX_ZERO;
+ }
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ for (Count = 0; ((FormatCharacter >= '0') && (FormatCharacter <= '9')); ){
+ Count = (Count * 10) + FormatCharacter - '0';
+ Format += BytesPerFormatCharacter;
+ FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
+ }
+ Format -= BytesPerFormatCharacter;
+ if ((Flags & PRECISION) == 0) {
+ Flags |= PAD_TO_WIDTH;
+ Width = Count;
+ } else {
+ Precision = Count;
+ }
+ break;
+
+ case '\0':
+ //
+ // Make no output if Format string terminates unexpectedly when
+ // looking up for flag, width, precision and type.
+ //
+ Format -= BytesPerFormatCharacter;
+ Precision = 0;
+ //
+ // break skipped on purpose.
+ //
+ default:
+ Done = TRUE;
+ break;
+ }
+ }
+
+ //
+ // Handle each argument type
+ //
+ switch (FormatCharacter) {
+ case 'p':
+ //
+ // Flag space, +, 0, L & l are invalid for type p.
+ //
+ Flags &= ~(PREFIX_BLANK | PREFIX_SIGN | PREFIX_ZERO | LONG_TYPE);
+ if (sizeof (VOID *) > 4) {
+ Flags |= LONG_TYPE;
+ }
+ //
+ // break skipped on purpose
+ //
+ case 'X':
+ Flags |= PREFIX_ZERO;
+ //
+ // break skipped on purpose
+ //
+ case 'x':
+ Flags |= RADIX_HEX;
+ //
+ // break skipped on purpose
+ //
+ case 'd':
+ if ((Flags & LONG_TYPE) == 0) {
+ //
+ // 'd','x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
+ // This assumption is made so the format string definition is compatible with the ANSI C
+ // Specification for formatted strings. It is recommended that the Base Types be used
+ // everywhere, but in this one case, compliance with ANSI C is more important, and
+ // provides an implementation that is compatible with that largest possible set of CPU
+ // architectures. This is why the type "int" is used in this one case.
+ //
+ if (BaseListMarker == NULL) {
+ Value = VA_ARG (VaListMarker, int);
+ } else {
+ Value = BASE_ARG (BaseListMarker, int);
+ }
+ } else {
+ if (BaseListMarker == NULL) {
+ Value = VA_ARG (VaListMarker, INT64);
+ } else {
+ Value = BASE_ARG (BaseListMarker, INT64);
+ }
+ }
+ if ((Flags & PREFIX_BLANK) != 0) {
+ Prefix = ' ';
+ }
+ if ((Flags & PREFIX_SIGN) != 0) {
+ Prefix = '+';
+ }
+ if ((Flags & COMMA_TYPE) != 0) {
+ Comma = TRUE;
+ }
+ if ((Flags & RADIX_HEX) == 0) {
+ Radix = 10;
+ if (Comma) {
+ Flags &= (~PREFIX_ZERO);
+ Precision = 1;
+ }
+ if (Value < 0) {
+ Flags |= PREFIX_SIGN;
+ Prefix = '-';
+ Value = -Value;
+ }
+ } else {
+ Radix = 16;
+ Comma = FALSE;
+ if ((Flags & LONG_TYPE) == 0 && Value < 0) {
+ //
+ // 'd','x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
+ // This assumption is made so the format string definition is compatible with the ANSI C
+ // Specification for formatted strings. It is recommended that the Base Types be used
+ // everywhere, but in this one case, compliance with ANSI C is more important, and
+ // provides an implementation that is compatible with that largest possible set of CPU
+ // architectures. This is why the type "unsigned int" is used in this one case.
+ //
+ Value = (unsigned int)Value;
+ }
+ }
+ //
+ // Convert Value to a reversed string
+ //
+ Count = BasePrintLibValueToString (ValueBuffer, Value, Radix) - ValueBuffer;
+ if (Value == 0 && Precision == 0) {
+ Count = 0;
+ }
+ ArgumentString = (CHAR8 *)ValueBuffer + Count;
+
+ Digits = Count % 3;
+ if (Digits != 0) {
+ Digits = 3 - Digits;
+ }
+ if (Comma && Count != 0) {
+ Count += ((Count - 1) / 3);
+ }
+ if (Prefix != 0) {
+ Count++;
+ Precision++;
+ }
+ Flags |= ARGUMENT_REVERSED;
+ ZeroPad = TRUE;
+ if ((Flags & PREFIX_ZERO) != 0) {
+ if ((Flags & LEFT_JUSTIFY) == 0) {
+ if ((Flags & PAD_TO_WIDTH) != 0) {
+ if ((Flags & PRECISION) == 0) {
+ Precision = Width;
+ }
+ }
+ }
+ }
+ break;
+
+ case 's':
+ case 'S':
+ Flags |= ARGUMENT_UNICODE;
+ //
+ // break skipped on purpose
+ //
+ case 'a':
+ if (BaseListMarker == NULL) {
+ ArgumentString = VA_ARG (VaListMarker, CHAR8 *);
+ } else {
+ ArgumentString = BASE_ARG (BaseListMarker, CHAR8 *);
+ }
+ if (ArgumentString == NULL) {
+ Flags &= (~ARGUMENT_UNICODE);
+ ArgumentString = "";
+ }
+ //
+ // Set the default precision for string to be zero if not specified.
+ //
+ if ((Flags & PRECISION) == 0) {
+ Precision = 0;
+ }
+ break;
+
+ case 'c':
+ if (BaseListMarker == NULL) {
+ Character = VA_ARG (VaListMarker, UINTN) & 0xffff;
+ } else {
+ Character = BASE_ARG (BaseListMarker, UINTN) & 0xffff;
+ }
+ ArgumentString = (CHAR8 *)&Character;
+ Flags |= ARGUMENT_UNICODE;
+ break;
+
+ case 'g':
+ if (BaseListMarker == NULL) {
+ TmpGuid = VA_ARG (VaListMarker, GUID *);
+ } else {
+ TmpGuid = BASE_ARG (BaseListMarker, GUID *);
+ }
+ if (TmpGuid == NULL) {
+ ArgumentString = "";
+ } else {
+ GuidData1 = ReadUnaligned32 (&(TmpGuid->Data1));
+ GuidData2 = ReadUnaligned16 (&(TmpGuid->Data2));
+ GuidData3 = ReadUnaligned16 (&(TmpGuid->Data3));
+ BasePrintLibSPrint (
+ ValueBuffer,
+ MAXIMUM_VALUE_CHARACTERS,
+ 0,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ GuidData1,
+ GuidData2,
+ GuidData3,
+ TmpGuid->Data4[0],
+ TmpGuid->Data4[1],
+ TmpGuid->Data4[2],
+ TmpGuid->Data4[3],
+ TmpGuid->Data4[4],
+ TmpGuid->Data4[5],
+ TmpGuid->Data4[6],
+ TmpGuid->Data4[7]
+ );
+ ArgumentString = ValueBuffer;
+ }
+ break;
+
+ case 't':
+ if (BaseListMarker == NULL) {
+ TmpTime = VA_ARG (VaListMarker, TIME *);
+ } else {
+ TmpTime = BASE_ARG (BaseListMarker, TIME *);
+ }
+ if (TmpTime == NULL) {
+ ArgumentString = "";
+ } else {
+ BasePrintLibSPrint (
+ ValueBuffer,
+ MAXIMUM_VALUE_CHARACTERS,
+ 0,
+ "%02d/%02d/%04d %02d:%02d",
+ TmpTime->Month,
+ TmpTime->Day,
+ TmpTime->Year,
+ TmpTime->Hour,
+ TmpTime->Minute
+ );
+ ArgumentString = ValueBuffer;
+ }
+ break;
+
+#if 0
+ case 'r':
+ if (BaseListMarker == NULL) {
+ Status = VA_ARG (VaListMarker, RETURN_STATUS);
+ } else {
+ Status = BASE_ARG (BaseListMarker, RETURN_STATUS);
+ }
+ ArgumentString = ValueBuffer;
+ if (RETURN_ERROR (Status)) {
+ //
+ // Clear error bit
+ //
+ Index = Status & ~MAX_BIT;
+ if (Index > 0 && Index <= ERROR_STATUS_NUMBER) {
+ ArgumentString = mStatusString [Index + WARNING_STATUS_NUMBER];
+ }
+ } else {
+ Index = Status;
+ if (Index <= WARNING_STATUS_NUMBER) {
+ ArgumentString = mStatusString [Index];
+ }
+ }
+ if (ArgumentString == ValueBuffer) {
+ BasePrintLibSPrint ((CHAR8 *) ValueBuffer, MAXIMUM_VALUE_CHARACTERS, 0, "%08X", Status);
+ }
+ break;
+#endif
+
+ case '\r':
+ Format += BytesPerFormatCharacter;
+ FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
+ if (FormatCharacter == '\n') {
+ //
+ // Translate '\r\n' to '\r\n'
+ //
+ ArgumentString = "\r\n";
+ } else {
+ //
+ // Translate '\r' to '\r'
+ //
+ ArgumentString = "\r";
+ Format -= BytesPerFormatCharacter;
+ }
+ break;
+
+ case '\n':
+ //
+ // Translate '\n' to '\r\n' and '\n\r' to '\r\n'
+ //
+ ArgumentString = "\r\n";
+ Format += BytesPerFormatCharacter;
+ FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
+ if (FormatCharacter != '\r') {
+ Format -= BytesPerFormatCharacter;
+ }
+ break;
+
+ case '%':
+ default:
+ //
+ // if the type is '%' or unknown, then print it to the screen
+ //
+ ArgumentString = (CHAR8 *)&FormatCharacter;
+ Flags |= ARGUMENT_UNICODE;
+ break;
+ }
+ break;
+
+ case '\r':
+ Format += BytesPerFormatCharacter;
+ FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
+ if (FormatCharacter == '\n') {
+ //
+ // Translate '\r\n' to '\r\n'
+ //
+ ArgumentString = "\r\n";
+ } else {
+ //
+ // Translate '\r' to '\r'
+ //
+ ArgumentString = "\r";
+ Format -= BytesPerFormatCharacter;
+ }
+ break;
+
+ case '\n':
+ //
+ // Translate '\n' to '\r\n' and '\n\r' to '\r\n'
+ //
+ ArgumentString = "\r\n";
+ Format += BytesPerFormatCharacter;
+ FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
+ if (FormatCharacter != '\r') {
+ Format -= BytesPerFormatCharacter;
+ }
+ break;
+
+ default:
+ ArgumentString = (CHAR8 *)&FormatCharacter;
+ Flags |= ARGUMENT_UNICODE;
+ break;
+ }
+
+ //
+ // Retrieve the ArgumentString attriubutes
+ //
+ if ((Flags & ARGUMENT_UNICODE) != 0) {
+ ArgumentMask = 0xffff;
+ BytesPerArgumentCharacter = 2;
+ } else {
+ ArgumentMask = 0xff;
+ BytesPerArgumentCharacter = 1;
+ }
+ if ((Flags & ARGUMENT_REVERSED) != 0) {
+ BytesPerArgumentCharacter = -BytesPerArgumentCharacter;
+ } else {
+ //
+ // Compute the number of characters in ArgumentString and store it in Count
+ // ArgumentString is either null-terminated, or it contains Precision characters
+ //
+ for (Count = 0; Count < Precision || ((Flags & PRECISION) == 0); Count++) {
+ ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask;
+ if (ArgumentCharacter == 0) {
+ break;
+ }
+ }
+ }
+
+ if (Precision < Count) {
+ Precision = Count;
+ }
+
+ //
+ // Pad before the string
+ //
+ if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) {
+ LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);
+ if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);
+ }
+ }
+
+ if (ZeroPad) {
+ if (Prefix != 0) {
+ LengthToReturn += (1 * BytesPerOutputCharacter);
+ if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);
+ }
+ }
+ LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);
+ if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, '0', BytesPerOutputCharacter);
+ }
+ } else {
+ LengthToReturn += ((Precision - Count) * BytesPerOutputCharacter);
+ if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Precision - Count, ' ', BytesPerOutputCharacter);
+ }
+ if (Prefix != 0) {
+ LengthToReturn += (1 * BytesPerOutputCharacter);
+ if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, Prefix, BytesPerOutputCharacter);
+ }
+ }
+ }
+
+ //
+ // Output the Prefix character if it is present
+ //
+ Index = 0;
+ if (Prefix != 0) {
+ Index++;
+ }
+
+ //
+ // Copy the string into the output buffer performing the required type conversions
+ //
+ while (Index < Count) {
+ ArgumentCharacter = ((*ArgumentString & 0xff) | (*(ArgumentString + 1) << 8)) & ArgumentMask;
+
+ LengthToReturn += (1 * BytesPerOutputCharacter);
+ if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ArgumentCharacter, BytesPerOutputCharacter);
+ }
+ ArgumentString += BytesPerArgumentCharacter;
+ Index++;
+ if (Comma) {
+ Digits++;
+ if (Digits == 3) {
+ Digits = 0;
+ Index++;
+ if (Index < Count) {
+ LengthToReturn += (1 * BytesPerOutputCharacter);
+ if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ',', BytesPerOutputCharacter);
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Pad after the string
+ //
+ if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) {
+ LengthToReturn += ((Width - Precision) * BytesPerOutputCharacter);
+ if ((Flags & COUNT_ONLY_NO_PRINT) == 0 && Buffer != NULL) {
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, Width - Precision, ' ', BytesPerOutputCharacter);
+ }
+ }
+
+ //
+ // Get the next character from the format string
+ //
+ Format += BytesPerFormatCharacter;
+
+ //
+ // Get the next character from the format string
+ //
+ FormatCharacter = ((*Format & 0xff) | (*(Format + 1) << 8)) & FormatMask;
+ }
+
+ if ((Flags & COUNT_ONLY_NO_PRINT) != 0) {
+ return (LengthToReturn / BytesPerOutputCharacter);
+ }
+
+#if 0
+ ASSERT (Buffer != NULL);
+#endif
+ //
+ // Null terminate the Unicode or ASCII string
+ //
+ BasePrintLibFillBuffer (Buffer, EndBuffer + BytesPerOutputCharacter, 1, 0, BytesPerOutputCharacter);
+ //
+ // Make sure output buffer cannot contain more than PcdMaximumUnicodeStringLength
+ // Unicode characters if PcdMaximumUnicodeStringLength is not zero.
+ //
+#if 0
+ ASSERT ((((Flags & OUTPUT_UNICODE) == 0)) || (StrSize ((CHAR16 *) OriginalBuffer) != 0));
+#endif
+ //
+ // Make sure output buffer cannot contain more than PcdMaximumAsciiStringLength
+ // ASCII characters if PcdMaximumAsciiStringLength is not zero.
+ //
+#if 0
+ ASSERT ((((Flags & OUTPUT_UNICODE) != 0)) || (AsciiStrSize (OriginalBuffer) != 0));
+#endif
+
+ return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter);
+}
+
+STATIC UINTN
+EFIAPI
+BasePrintLibSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN UINTN Flags,
+ IN CONST CHAR8 *FormatString,
+ ...
+ )
+{
+ VA_LIST Marker;
+ UINTN NumberOfPrinted;
+
+ VA_START (Marker, FormatString);
+ NumberOfPrinted = BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, Flags, FormatString, Marker, NULL);
+ VA_END (Marker);
+ return NumberOfPrinted;
+}
+
+STATIC UINTN
+EFIAPI
+AsciiVSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ IN VA_LIST Marker
+ )
+{
+ return BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, 0, FormatString, Marker, NULL);
+}
+
+#ifdef DEBUG_PORT
+VOID
+EFIAPI
+DebugPrint (
+ IN CONST CHAR8 *Format,
+ ...
+ )
+{
+ CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
+ VA_LIST Marker;
+ UINT8 *Ptr;
+
+ VA_START (Marker, Format);
+ AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
+ VA_END (Marker);
+
+ for (Ptr = (UINT8 *) Buffer; *Ptr; Ptr++) {
+ IoWrite32 (DEBUG_PORT, *Ptr);
+ }
+}
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/Printf.h BhyvePkg/Csm/BhyveCsm16/Printf.h
new file mode 100644
index 0000000..1c10fd1
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Printf.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#ifndef _BHYVECSM16_PRINTF_H_
+#define _BHYVECSM16_PRINTF_H_
+
+#ifdef DEBUG_PORT
+VOID
+EFIAPI
+DebugPrint (
+ IN CONST CHAR8 *Format,
+ ...
+ );
+#endif
+
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/Smbios.h BhyvePkg/Csm/BhyveCsm16/Smbios.h
new file mode 100644
index 0000000..1100caa
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Smbios.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#ifndef _BHYVECSM16_SMBIOS_H_
+#define _BHYVECSM16_SMBIOS_H_
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 AnchorString[4];
+ UINT8 EntryPointStructureChecksum;
+ UINT8 EntryPointLength;
+ UINT8 MajorVersion;
+ UINT8 MinorVersion;
+ UINT16 MaxStructureSize;
+ UINT8 EntryPointRevision;
+ UINT8 FormattedArea[5];
+ UINT8 IntermediateAnchorString[5];
+ UINT8 IntermediateChecksum;
+ UINT16 TableLength;
+ UINT32 TableAddress;
+ UINT16 NumberOfSmbiosStructures;
+ UINT8 SmbiosBcdRevision;
+} SMBIOS_TABLE_STRUCTURE;
+
+#pragma pack()
+
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/String.c BhyvePkg/Csm/BhyveCsm16/String.c
new file mode 100644
index 0000000..2abaa62
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/String.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+
+#include "Printf.h"
+#include "String.h"
+
+UINTN
+EFIAPI
+StrLen (
+ IN CONST CHAR16 *String
+ )
+{
+ UINTN Length;
+
+ for (Length = 0; *String != L'\0'; String++) {
+ Length++;
+ }
+
+ return Length;
+}
+
+INTN
+EFIAPI
+StrCmp (
+ IN CONST CHAR16 *FirstString,
+ IN CONST CHAR16 *SecondString
+ )
+{
+ while ((*FirstString != L'\0') && (*FirstString == *SecondString)) {
+ FirstString++;
+ SecondString++;
+ }
+ return *FirstString - *SecondString;
+}
+
+CHAR16 *
+EFIAPI
+StrStr (
+ IN CONST CHAR16 *String,
+ IN CONST CHAR16 *SearchString
+)
+{
+ CONST CHAR16 *FirstMatch;
+ CONST CHAR16 *SearchStringTmp;
+
+ if (*SearchString == L'\0') {
+ return (CHAR16 *) String;
+ }
+
+ while (*String != L'\0') {
+ SearchStringTmp = SearchString;
+ FirstMatch = String;
+
+ while ((*String == *SearchStringTmp)
+ && (*String != L'\0')) {
+ String++;
+ SearchStringTmp++;
+ }
+
+ if (*SearchStringTmp == L'\0') {
+ return (CHAR16 *) FirstMatch;
+ }
+
+ if (*String == L'\0') {
+ return NULL;
+ }
+
+ String = FirstMatch + 1;
+ }
+
+ return NULL;
+}
+
+BOOLEAN
+EFIAPI
+StrEndsWith (
+ IN CONST CHAR16 *String,
+ IN CONST CHAR16 *SearchString)
+{
+ UINTN Length, SearchLength;
+
+ Length = StrLen(String);
+ SearchLength = StrLen(SearchString);
+ if (SearchLength > Length) {
+ return FALSE;
+ }
+
+ return !StrCmp(String + Length - SearchLength, SearchString);
+}
+
+INTN
+EFIAPI
+CompareMem (
+ IN CONST VOID *DestinationBuffer,
+ IN CONST VOID *SourceBuffer,
+ IN UINTN Length
+ )
+{
+ while ((--Length != 0) &&
+ (*(INT8*)DestinationBuffer == *(INT8*)SourceBuffer)) {
+ DestinationBuffer = (INT8*)DestinationBuffer + 1;
+ SourceBuffer = (INT8*)SourceBuffer + 1;
+ }
+ return (INTN)*(UINT8*)DestinationBuffer - (INTN)*(UINT8*)SourceBuffer;
+}
+
+VOID *
+EFIAPI
+CopyMem (
+ OUT VOID *DestinationBuffer,
+ IN CONST VOID *SourceBuffer,
+ IN UINTN Length
+ )
+{
+ UINT8 *Destination8;
+ CONST UINT8 *Source8;
+
+ if (SourceBuffer > DestinationBuffer) {
+ Destination8 = (UINT8*)DestinationBuffer;
+ Source8 = (CONST UINT8*)SourceBuffer;
+ while (Length-- != 0) {
+ *(Destination8++) = *(Source8++);
+ }
+ } else if (SourceBuffer < DestinationBuffer) {
+ Destination8 = (UINT8*)DestinationBuffer + Length;
+ Source8 = (CONST UINT8*)SourceBuffer + Length;
+ while (Length-- != 0) {
+ *(--Destination8) = *(--Source8);
+ }
+ }
+ return DestinationBuffer;
+}
+
+VOID *
+EFIAPI
+ZeroMem (
+ OUT VOID *Buffer,
+ IN UINTN Length
+ )
+{
+ do {
+ ((UINT16*)Buffer)[--Length] = 0;
+ } while (Length != 0);
+ return Buffer;
+}
+
+UINT8
+DecimalToBcd8 (
+ UINT8 Value
+ )
+{
+#if 0
+ ASSERT (Value < 100);
+#endif
+ return (UINT8) (((Value / 10) << 4) | (Value % 10));
+}
diff --git BhyvePkg/Csm/BhyveCsm16/String.h BhyvePkg/Csm/BhyveCsm16/String.h
new file mode 100644
index 0000000..b984475
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/String.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#ifndef _BHYVECSM16_STRING_H_
+#define _BHYVECSM16_STRING_H_
+
+BOOLEAN
+EFIAPI
+StrEndsWith (
+ IN CONST CHAR16 *String,
+ IN CONST CHAR16 *SearchString);
+
+INTN
+EFIAPI
+CompareMem (
+ IN CONST VOID *DestinationBuffer,
+ IN CONST VOID *SourceBuffer,
+ IN UINTN Length
+ );
+
+VOID *
+EFIAPI
+CopyMem (
+ OUT VOID *DestinationBuffer,
+ IN CONST VOID *SourceBuffer,
+ IN UINTN Length
+ );
+
+VOID *
+EFIAPI
+ZeroMem (
+ OUT VOID *Buffer,
+ IN UINTN Length
+ );
+
+UINT8
+DecimalToBcd8 (
+ IN UINT8 Value
+ );
+
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/Video.c BhyvePkg/Csm/BhyveCsm16/Video.c
new file mode 100644
index 0000000..4a6283d
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Video.c
@@ -0,0 +1,935 @@
+/*
+ * Copyright (c) 2015, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+
+#include "BhyveCsm16.h"
+
+#define DEBUG_PORT 0x220
+#include "Debug.h"
+#include "Printf.h"
+#include "String.h"
+
+#define VGA_BUF_ADDR 0xA0000
+#define VGA_BUF_LENGTH 0x10000
+
+#define VGA_GFX_INDEX 0x3CE
+#define VGA_GFX_DATA 0x3CF
+
+#define VGA_CRTC_INDEX 0x3D4
+#define VGA_CRTC_DATA 0x3D5
+
+#define VGA_WRITE_ATTR_INDEX 0x3C0
+#define VGA_WRITE_ATTR_DATA 0x3C0
+
+#define VGA_SEQ_INDEX 0x3C4
+#define VGA_SEQ_DATA 0x3C5
+
+#define VGA_PALETTE_WRITE 0x3C8
+#define VGA_PALETTE_READ 0x3C7
+#define VGA_PALETTE_DATA 0x3C9
+
+#define VGA_INPUT_STATUS_1 0x3DA
+#define VGA_WRITE_MISC_PORT 0x3C2
+
+#define VGA_READ_FEATURE_PORT 0x3CA
+#define VGA_WRITE_FEATURE_PORT 0x3DA
+
+#define VGA_SEQ_CNT 5
+#define VGA_CRT_CNT 25
+#define VGA_ATR_CNT 21
+#define VGA_GFX_CNT 9
+
+enum MemoryModel {
+ MemoryModelText,
+ MemoryModelPackedPixel
+};
+
+struct VGAState {
+ enum MemoryModel MemoryModel;
+
+ /* Miscellaneous output register. */
+ unsigned char MiscOutput;
+
+ /* Sequencer registers. */
+ unsigned char SequencerData[VGA_SEQ_CNT];
+
+ /* CRT Controller registers. */
+ unsigned char CRTCData[VGA_CRT_CNT];
+
+ /* Graphics controller registers. */
+ unsigned char GraphicsData[VGA_GFX_CNT];
+
+ /* Attribute controller registers. */
+ unsigned char AttrData[VGA_ATR_CNT];
+};
+
+static const struct VGAState VGAMode3 = {
+ MemoryModelText,
+
+ /* Miscellaneous output register. */
+ 0x67,
+
+ /* Sequencer registers. */
+ { 0x01, 0x00, 0x03, 0x00, 0x02 },
+
+ /* CRT controller registers. */
+ {
+ 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f,
+ 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x8e, 0x8f, 0x28,
+ 0x1f, 0x96, 0xb9, 0xa3, 0xff,
+ },
+
+ /* Graphics controller registers. */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff },
+
+ /* Attribute controller registers. */
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x0c, 0x00, 0x0f, 0x08, 0x00,
+ },
+};
+
+static const struct VGAState VGAMode12 = {
+ MemoryModelPackedPixel,
+
+ /* Miscellaneous output register. */
+ 0xe3,
+
+ /* Sequencer registers. */
+ {0x03, 0x21, 0x0f, 0x00, 0x06},
+
+ /* CRT controller registers. */
+ {
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xea, 0x8c,
+ 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, 0xff,
+ },
+
+ /* Graphics controller registers. */
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff },
+
+ /* Attribute controller registers. */
+ {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x01, 0x00, 0x0f, 0x00, 0x00,
+ },
+};
+
+STATIC CONST UINT8 colorData[4] = {
+ 0x00, 0x15, 0x2a, 0x3f,
+};
+
+#define palette_entry(r,g,b) (((r) << 4)|((g) << 2)|(b))
+
+static const unsigned char mode_03_palette[] = {
+ palette_entry(0, 0, 0),
+ palette_entry(0, 0, 2),
+ palette_entry(0, 2, 0),
+ palette_entry(0, 2, 2),
+ palette_entry(2, 0, 0),
+ palette_entry(2, 0, 2),
+ palette_entry(2, 2, 0),
+ palette_entry(2, 2, 2),
+ palette_entry(0, 0, 1),
+ palette_entry(0, 0, 3),
+ palette_entry(0, 2, 1),
+ palette_entry(0, 2, 3),
+ palette_entry(2, 0, 1),
+ palette_entry(2, 0, 3),
+ palette_entry(2, 2, 1),
+ palette_entry(2, 2, 3),
+ palette_entry(0, 1, 0),
+ palette_entry(0, 1, 2),
+ palette_entry(0, 3, 0),
+ palette_entry(0, 3, 2),
+ palette_entry(2, 1, 0),
+ palette_entry(2, 1, 2),
+ palette_entry(2, 3, 0),
+ palette_entry(2, 3, 2),
+ palette_entry(0, 1, 1),
+ palette_entry(0, 1, 3),
+ palette_entry(0, 3, 1),
+ palette_entry(0, 3, 3),
+ palette_entry(2, 1, 1),
+ palette_entry(2, 1, 3),
+ palette_entry(2, 3, 1),
+ palette_entry(2, 3, 3),
+ palette_entry(1, 0, 0),
+ palette_entry(1, 0, 2),
+ palette_entry(1, 2, 0),
+ palette_entry(1, 2, 2),
+ palette_entry(3, 0, 0),
+ palette_entry(3, 0, 2),
+ palette_entry(3, 2, 0),
+ palette_entry(3, 2, 2),
+ palette_entry(1, 0, 1),
+ palette_entry(1, 0, 3),
+ palette_entry(1, 2, 1),
+ palette_entry(1, 2, 3),
+ palette_entry(3, 0, 1),
+ palette_entry(3, 0, 3),
+ palette_entry(3, 2, 1),
+ palette_entry(3, 2, 3),
+ palette_entry(1, 1, 0),
+ palette_entry(1, 1, 2),
+ palette_entry(1, 3, 0),
+ palette_entry(1, 3, 2),
+ palette_entry(3, 1, 0),
+ palette_entry(3, 1, 2),
+ palette_entry(3, 3, 0),
+ palette_entry(3, 3, 2),
+ palette_entry(1, 1, 1),
+ palette_entry(1, 1, 3),
+ palette_entry(1, 3, 1),
+ palette_entry(1, 3, 3),
+ palette_entry(3, 1, 1),
+ palette_entry(3, 1, 3),
+ palette_entry(3, 3, 1),
+ palette_entry(3, 3, 3),
+};
+
+extern unsigned char FONTDATA[];
+
+STATIC const struct VGAState *CurrentState;
+
+STATIC int CurrentVideoMode;
+STATIC int CurrentActivePage;
+
+STATIC VOID
+VGASetFont(VOID)
+{
+ UINT8 *to, *from;
+ int i, j;
+
+ DPRINTF(DBG_WARN, ("XXX VGASetFont()\n"));
+
+ /* Sync-reset the sequencer registers */
+ IoWrite8(VGA_SEQ_INDEX, 0x00);
+ IoWrite8(VGA_SEQ_DATA, 0x01); /* Low order two bits are reset bits */
+
+ /*
+ * Enable write to plane 2
+ */
+ IoWrite8(VGA_SEQ_INDEX, 0x02);
+ IoWrite8(VGA_SEQ_DATA, 0x04);
+
+ /*
+ * Sequentially access data
+ */
+ IoWrite8(VGA_SEQ_INDEX, 0x04);
+ IoWrite8(VGA_SEQ_DATA, 0x07);
+
+ /* Sync-reset ended */
+ IoWrite8(VGA_SEQ_INDEX, 0x00);
+ IoWrite8(VGA_SEQ_DATA, 0x03); /* Low order two bits are reset bits */
+
+ /*
+ * Select plane 2 Read Mode 0
+ */
+ IoWrite8(VGA_GFX_INDEX, 0x04);
+ IoWrite8(VGA_GFX_DATA, 0x02);
+
+ /*
+ * System addresses sequentially access data, follow Memory
+ * Mode register bit 2 in the sequencer
+ */
+ IoWrite8(VGA_GFX_INDEX, 0x05);
+ IoWrite8(VGA_GFX_DATA, 0x00);
+
+ /*
+ * Set the range of host memory addresses decoded by VGA
+ * hardware -- A0000h-BFFFFh (128K region)
+ */
+ IoWrite8(VGA_GFX_INDEX, 0x06);
+ IoWrite8(VGA_GFX_DATA, 0x00);
+
+ /*
+ * This assumes 8x16 characters, which yield the traditional 80x25
+ * screen.
+ */
+ for (i = 0; i < 256; i++) {
+ from = &FONTDATA[i * 16];
+ to = (UINT8 *)VGA_BUF_ADDR + i * 0x20;
+ for (j = 0; j < 16; j++)
+ *to++ = *from++;
+ }
+
+ /* Sync-reset the sequencer registers */
+ IoWrite8(VGA_SEQ_INDEX, 0x00);
+ IoWrite8(VGA_SEQ_DATA, 0x01); /* Low order two bits are reset bits */
+
+ /* Enable write to plane 0 and 1 */
+ IoWrite8(VGA_SEQ_INDEX, 0x02);
+ IoWrite8(VGA_SEQ_DATA, 0x03);
+
+ /*
+ * Enable character map selection and odd/even addressing
+ */
+ IoWrite8(VGA_SEQ_INDEX, 0x04);
+ IoWrite8(VGA_SEQ_DATA, 0x03);
+
+ /*
+ * Select font map
+ */
+ IoWrite8(VGA_SEQ_INDEX, 0x03);
+ IoWrite8(VGA_SEQ_DATA, 0x00);
+
+ /* Sync-reset ended */
+ IoWrite8(VGA_SEQ_INDEX, 0x00);
+ IoWrite8(VGA_SEQ_DATA, 0x03); /* Low order two bits are reset bits */
+
+ /* Select plane 0 */
+ IoWrite8(VGA_GFX_INDEX, 0x04);
+ IoWrite8(VGA_GFX_DATA, 0x00);
+
+ /* Enable odd/even addressing mode */
+ IoWrite8(VGA_GFX_INDEX, 0x05);
+ IoWrite8(VGA_GFX_DATA, 0x10);
+
+ /*
+ * Set the range of host memory addresses decoded by VGA
+ * hardware -- B8000h-BFFFFh (32K region)
+ */
+ IoWrite8(VGA_GFX_INDEX, 0x06);
+ IoWrite8(VGA_GFX_DATA, 0x0e);
+}
+
+STATIC VOID
+VGASetCursorPosition(UINTN Page, UINT8 X, UINT8 Y)
+{
+ BDA *BdaPtr = (BDA *)(UINTN)0x400;
+ UINT16 CursorLocation;
+
+ DPRINTF (DBG_VERB, ("XXX VGASetCursorPosition() Page %d X %d Y %d\n", Page, X, Y));
+ BdaPtr->CursorPosition[Page] = (Y << 8) | X;
+
+ CursorLocation = (Y * mBdaPtr->TextColumns + X);
+ DPRINTF (DBG_VERB, ("XXX VGASetCursorPosition() CursorLocation = 0x%x\n", CursorLocation));
+ IoWrite8(VGA_CRTC_INDEX, 0xe);
+ IoWrite8(VGA_CRTC_DATA, CursorLocation >> 8);
+ IoWrite8(VGA_CRTC_INDEX, 0xf);
+ IoWrite8(VGA_CRTC_DATA, CursorLocation & 0xFF);
+}
+
+STATIC VOID
+VGAGetCursorPosition(UINTN Page, UINT8 *X, UINT8 *Y)
+{
+ BDA *BdaPtr = (BDA *)(UINTN)0x400;
+ UINT16 XY;
+
+ XY = BdaPtr->CursorPosition[Page];
+ *X = XY & 0xff;
+ *Y = XY >> 8;
+ DPRINTF (DBG_VERB, ("XXX VGAGetCursorPosition() Page %d X %d Y %d\n", Page, *X, *Y));
+}
+
+
+STATIC VOID
+VGASetVideoMode(UINTN ModeNumber, BOOLEAN Retain)
+{
+ int j, k;
+
+ DPRINTF (DBG_INFO, ("XXX VGASetVideoMode() Mode=0x%x Retain=%s\n", ModeNumber, Retain ? L"TRUE" : L"FALSE"));
+
+ switch (ModeNumber) {
+ case 0x3:
+ CurrentState = &VGAMode3;
+ mBdaPtr->TextColumns = 80;
+ mBdaPtr->TextRowsMinusOne = 25 - 1;
+ mBdaPtr->ScanLinesPerChar = 16;
+ break;
+ case 0x12:
+ CurrentState = &VGAMode12;
+ mBdaPtr->TextColumns = 80;
+ mBdaPtr->TextRowsMinusOne = 30 - 1;
+ mBdaPtr->ScanLinesPerChar = 16;
+ break;
+ default:
+ DPRINTF (DBG_CRIT, ("XXX spinning \n"));
+ for (;;);
+ return;
+ }
+
+ /* Turn the video off while we are doing this.... */
+ IoWrite8(VGA_SEQ_INDEX, 1);
+ IoWrite8(VGA_SEQ_DATA, CurrentState->SequencerData[1]);
+
+ /* Set the attribute flip-flop to "index" */
+ IoRead8(VGA_INPUT_STATUS_1);
+
+ /* Give palette to CPU, turns off video */
+ IoWrite8(VGA_WRITE_ATTR_INDEX, 0x00);
+
+ /* Set the general registers */
+ IoWrite8(VGA_WRITE_MISC_PORT, CurrentState->MiscOutput);
+ IoWrite8(VGA_WRITE_FEATURE_PORT, 0x00);
+
+ /* Load the sequencer registers */
+ for (k = 0; k < VGA_SEQ_CNT; k++) {
+ IoWrite8(VGA_SEQ_INDEX, k);
+ IoWrite8(VGA_SEQ_DATA, CurrentState->SequencerData[k]);
+ }
+ IoWrite8(VGA_SEQ_INDEX, 0x00);
+ IoWrite8(VGA_SEQ_DATA, 0x03); /* Low order two bits are reset bits */
+
+ /* Load the CRTC registers.
+ * CRTC registers 0-7 are locked by a bit in register 0x11. We need
+ * to unlock these registers before we can start setting them.
+ */
+ IoWrite8(VGA_CRTC_INDEX, 0x11);
+ IoWrite8(VGA_CRTC_DATA, 0x00); /* Unlocks registers 0-7 */
+ for (k = 0; k < VGA_CRT_CNT; k++) {
+ IoWrite8(VGA_CRTC_INDEX, k);
+ IoWrite8(VGA_CRTC_DATA, CurrentState->CRTCData[k]);
+ }
+
+ /* Load the attribute registers */
+ IoRead8(VGA_INPUT_STATUS_1); /* Set the attribute flip-flop to "index" */
+ for (k = 0; k < VGA_ATR_CNT; k++) {
+ IoWrite8(VGA_WRITE_ATTR_INDEX, k);
+ IoWrite8(VGA_WRITE_ATTR_DATA, CurrentState->AttrData[k]);
+ }
+
+ /* Load graphics registers */
+ for (k = 0; k < VGA_GFX_CNT; k++) {
+ IoWrite8(VGA_GFX_INDEX, k);
+ IoWrite8(VGA_GFX_DATA, CurrentState->GraphicsData[k]);
+ }
+
+ /* Set up the palette. */
+ IoWrite8(VGA_PALETTE_WRITE, 0);
+ for (k = 0; k < 256; k++) {
+ j = mode_03_palette[k % 64];
+ IoWrite8(VGA_PALETTE_DATA, colorData[(j >> 4) & 3]);
+ IoWrite8(VGA_PALETTE_DATA, colorData[(j >> 2) & 3]);
+ IoWrite8(VGA_PALETTE_DATA, colorData[j & 3]);
+ }
+
+ /* Re-enable video */
+ if (!Retain) {
+ /* First, clear memory to zeros */
+ ZeroMem((VOID *)VGA_BUF_ADDR, VGA_BUF_LENGTH);
+
+ switch (ModeNumber) {
+ case 0x3:
+#if 1
+ for (k = 0; k < 25; k++) {
+ for (j = 0; j < 80; j++) {
+ *(UINT8 *)((UINTN)0xB8000 + (k * mBdaPtr->TextColumns + j) * 2) = ' ';
+ *(UINT8 *)((UINTN)0xB8000 + ((k * mBdaPtr->TextColumns + j) * 2) + 1) = 0x7;
+ }
+ }
+#endif
+ break;
+ }
+ }
+
+ /* Set the attribute flip-flop to "index" */
+ IoRead8(VGA_INPUT_STATUS_1);
+
+ /* Give the palette back to the VGA */
+ IoWrite8(VGA_WRITE_ATTR_INDEX, 0x20);
+
+ // Really re-enable video.
+ IoWrite8(VGA_SEQ_INDEX, 1);
+ IoWrite8(VGA_SEQ_DATA, (CurrentState->SequencerData[1] & ~0x20));
+
+ switch (ModeNumber) {
+ case 0x3:
+ VGASetFont();
+ break;
+ }
+
+ for (k = 0; k < 8; k++) {
+ VGASetCursorPosition(k, 0, 0);
+ }
+
+ CurrentVideoMode = ModeNumber;
+}
+
+STATIC VOID
+VGAReadCharPosition(UINTN Page, UINTN X, UINTN Y, UINT8 *Ch, INT8 *Attr)
+{
+ BDA *BdaPtr = (BDA *)(UINTN)0x400;
+
+ *Ch = *(UINT8 *)((UINTN)0xB8000 + (Y * BdaPtr->TextColumns + X) * 2);
+ *Attr = *(UINT8 *)((UINTN)0xB8000 + ((Y * BdaPtr->TextColumns + X) * 2) + 1);
+ DPRINTF (DBG_VERB, ("XXX VGAReadCharPosition() X %d Y %d Attr 0x%x/Char '%c'\n", X, Y, *(UINT8 *)((UINTN)0xB8000 + ((Y * BdaPtr->TextColumns + X) * 2) + 1), *(UINT8 *)((UINTN)0xB8000 + (Y * BdaPtr->TextColumns + X) * 2) ));
+}
+
+STATIC VOID
+VGAReadChar(UINT8 *Ch, UINT8 *Attr)
+{
+ UINT8 X, Y;
+
+ VGAGetCursorPosition(CurrentActivePage, &X, &Y);
+ VGAReadCharPosition(CurrentActivePage, X, Y, Ch, Attr);
+}
+
+STATIC VOID
+VGAWriteCharPositionPackedPixel(UINTN X, UINTN Y, UINT8 Ch, UINT8 Color)
+{
+ UINTN N, Offset;
+ UINT8 *Pattern;
+
+ DPRINTF (DBG_VERB, ("XXX VGAWriteCharPositionPackedPixel() X %d Y %d Char '%c' Color 0x%x\n", X, Y, Ch, Color));
+
+ /*
+ * Enable all planes
+ */
+ IoWrite8(VGA_SEQ_INDEX, 0x02);
+ IoWrite8(VGA_SEQ_DATA, 0x0f);
+
+ /*
+ * Use set/reset to produce color
+ */
+ IoWrite8(VGA_GFX_INDEX, 0x00);
+ IoWrite8(VGA_GFX_DATA, Color);
+ IoWrite8(VGA_GFX_INDEX, 0x01);
+ IoWrite8(VGA_GFX_DATA, 0xf);
+
+ /*
+ * Select write mode 3
+ */
+ IoWrite8(VGA_GFX_INDEX, 0x05);
+ IoWrite8(VGA_GFX_DATA, 0x03);
+
+ /*
+ * Select function 'replace' and no rotate
+ */
+ IoWrite8(VGA_GFX_INDEX, 0x03);
+ IoWrite8(VGA_GFX_DATA, 0x00);
+
+ for (N = 0; N < 16; N++) {
+ Offset = (Y * 16 + N) * mBdaPtr->TextColumns + X;
+ Pattern = &FONTDATA[Ch * 16];
+
+ /*
+ * Setup the bit mask.
+ */
+ IoWrite8(VGA_GFX_INDEX, 0x08);
+ IoWrite8(VGA_GFX_DATA, Pattern[N]);
+
+ *((UINT8 *)VGA_BUF_ADDR + Offset) = Pattern[N];
+ }
+}
+
+STATIC VOID
+VGAWriteCharPosition(UINTN X, UINTN Y, UINT8 Ch, INT8 Attr)
+{
+ BDA *BdaPtr = (BDA *)(UINTN)0x400;
+
+ switch (CurrentState->MemoryModel) {
+ case MemoryModelText:
+ DPRINTF (DBG_VERB, ("XXX VGAWriteCharPosition() X %d Y %d Attr 0x%x/Char '%c'\n", X, Y, Attr, Ch));
+ *(UINT8 *)((UINTN)0xB8000 + (Y * BdaPtr->TextColumns + X) * 2) = Ch;
+ if (Attr >= 0)
+ *(UINT8 *)((UINTN)0xB8000 + ((Y * BdaPtr->TextColumns + X) * 2) + 1) = Attr;
+ break;
+ case MemoryModelPackedPixel:
+ VGAWriteCharPositionPackedPixel(X, Y, Ch, Attr);
+ break;
+ }
+}
+
+STATIC VOID
+VGAWriteChars(UINTN Page, UINTN Count, UINT8 Ch, UINT8 Attr)
+{
+ UINT8 X, Y;
+
+ VGAGetCursorPosition(Page, &X, &Y);
+ while (Count--) {
+ VGAWriteCharPosition(X + Count, Y, Ch, Attr);
+ }
+}
+
+STATIC VOID
+VGAWriteTeletype(UINT8 Ch)
+{
+ BDA *BdaPtr = (BDA *)(UINTN)0x400;
+ UINT8 X, Y;
+
+ VGAGetCursorPosition(CurrentActivePage, &X, &Y);
+
+ switch (Ch) {
+ case 0x07: /* bell */
+ break;
+ case 0x08: /* backspace */
+ if (X > 0) {
+ X--;
+ }
+ break;
+ case 0x09: /* tab */
+ X = X + ((X + 8) & ~7);
+ break;
+ case 0x0a: /* new line */
+ Y++;
+ break;
+ case 0x0b: /* vertical tab */
+ break;
+ case 0x0c: /* form feed */
+ break;
+ case 0x0d: /* carriage return */
+ X = 0;
+ break;
+ default:
+ VGAWriteCharPosition(X++, Y, Ch, -1);
+ break;
+ }
+
+ if (X >= BdaPtr->TextColumns) {
+ X = 0;
+ Y++;
+ }
+ if (Y >= (BdaPtr->TextRowsMinusOne + 1)) {
+ Y = (BdaPtr->TextRowsMinusOne + 1) - 1;
+ }
+
+ VGASetCursorPosition(CurrentActivePage, X, Y);
+}
+
+STATIC VOID
+VGAScrollUp(UINTN X1, UINTN Y1, UINTN X2, UINTN Y2, UINTN Lines, UINT8 FillAttr)
+{
+ BDA *BdaPtr = (BDA *)(UINTN)0x400;
+ UINTN X, Y;
+ UINT8 Ch, Attr;
+
+ DPRINTF(DBG_VERB, ("XXX VGAScrollUp() X1 %d Y1 %d X2 %d Y2 %d Lines %d Attr 0x%x\n", X1, Y1, X2, Y2, Lines, Attr));
+
+
+#if 0 /* XXX */
+ if (X2 > 79)
+ for (;;) ;
+#endif
+
+ if (Lines == 0)
+ Lines = (BdaPtr->TextRowsMinusOne + 1);
+
+ Lines = MIN(Y2 + 1 - Y1, Lines);
+
+ // Scroll
+ for (Y = Y1 + Lines; Y <= Y2; Y++) {
+ for (X = X1; X <= X2; X++) {
+ Ch = *(UINT8 *)((UINTN)0xB8000 + (Y * BdaPtr->TextColumns + X) * 2);
+ Attr = *(UINT8 *)((UINTN)0xB8000 + ((Y * BdaPtr->TextColumns + X) * 2) + 1);
+ *(UINT8 *)((UINTN)0xB8000 + ((Y - Lines) * BdaPtr->TextColumns + X) * 2) = Ch;
+ *(UINT8 *)((UINTN)0xB8000 + (((Y - Lines) * BdaPtr->TextColumns + X) * 2) + 1) = Attr;
+ }
+ }
+
+ // Fill
+ for (Y = Y2 + 1 - Lines; Y < Y2 + 1; Y++) {
+ for (X = X1; X <= X2; X++) {
+ *(UINT8 *)((UINTN)0xB8000 + (Y * BdaPtr->TextColumns + X) * 2) = ' ';
+ *(UINT8 *)((UINTN)0xB8000 + ((Y * BdaPtr->TextColumns + X) * 2) + 1) = FillAttr;
+ }
+ }
+}
+
+STATIC VOID
+VGAScrollDown(UINTN X1, UINTN Y1, UINTN X2, UINTN Y2, UINTN Lines, UINT8 FillAttr)
+{
+ BDA *BdaPtr = (BDA *)(UINTN)0x400;
+ UINTN X, Y;
+ UINT8 Ch, Attr;
+
+ DPRINTF(DBG_VERB, ("XXX VGAScrollDown() X1 %d Y1 %d X2 %d Y2 %d Lines %d Attr 0x%x\n", X1, Y1, X2, Y2, Lines, Attr));
+
+ if (Lines == 0)
+ Lines = (BdaPtr->TextRowsMinusOne + 1);
+
+ Lines = MIN(Y2 + 1 - Y1, Lines);
+
+ // Scroll
+ for (Y = Y1 + Lines; Y <= Y2; Y++) {
+ for (X = X1; X <= X2; X++) {
+ Ch = *(UINT8 *)((UINTN)0xB8000 + ((Y - Lines) * BdaPtr->TextColumns + X) * 2);
+ Attr = *(UINT8 *)((UINTN)0xB8000 + (((Y - Lines) * BdaPtr->TextColumns + X) * 2) + 1);
+ *(UINT8 *)((UINTN)0xB8000 + (Y * BdaPtr->TextColumns + X) * 2) = Ch;
+ *(UINT8 *)((UINTN)0xB8000 + ((Y * BdaPtr->TextColumns + X) * 2) + 1) = Attr;
+ }
+ }
+
+ // Fill
+ for (Y = Y2 + 1 - Lines; Y < Y2 + 1; Y++) {
+ for (X = X1; X <= X2; X++) {
+ *(UINT8 *)((UINTN)0xB8000 + (Y * BdaPtr->TextColumns + X) * 2) = ' ';
+ *(UINT8 *)((UINTN)0xB8000 + ((Y * BdaPtr->TextColumns + X) * 2) + 1) = FillAttr;
+ }
+ }
+}
+
+STATIC VOID
+InterruptVector0x10Palette(EFI_IA32_REGISTER_SET *Regs)
+{
+ UINTN Count;
+ UINT8 *Value;
+
+ switch (Regs->H.AL) {
+ case 0x00: /* Set Individual Palette Register */
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Set Individual Palette Register\n"));
+ IoRead8(VGA_INPUT_STATUS_1);
+ IoWrite8(VGA_WRITE_ATTR_INDEX, Regs->H.BL);
+ IoWrite8(VGA_WRITE_ATTR_DATA, Regs->H.BH);
+ break;
+ case 0x02: /* Set All Palette Registers and OverScan Register */
+ DPRINTF (DBG_INFO, ("XXX InterruptVector0x10() Set All Palette Registers\n"));
+ Value = (UINT8 *)(UINT64)((Regs->X.ES << 4) + (Regs->X.DX));
+ for (Count = 0; Count < 16; Count++) {
+ DPRINTF (DBG_VERB, ("XXX [%02d] = 0x%x\n", Count, *Value));
+ IoRead8(VGA_INPUT_STATUS_1);
+ IoWrite8(VGA_WRITE_ATTR_INDEX, Count);
+ IoWrite8(VGA_WRITE_ATTR_DATA, *Value);
+ Value++;
+ }
+ break;
+ case 0x10: /* Set Individual Color Register */
+ DPRINTF (DBG_INFO, ("XXX InterruptVector0x10() Set Individual Color Register\n"));
+ IoWrite8(VGA_PALETTE_WRITE, Regs->X.BX);
+ IoWrite8(VGA_PALETTE_DATA, Regs->H.DH);
+ IoWrite8(VGA_PALETTE_DATA, Regs->H.CH);
+ IoWrite8(VGA_PALETTE_DATA, Regs->H.CL);
+ break;
+ case 0x12: /* Set Block of Color Registers */
+ DPRINTF (DBG_INFO, ("XXX InterruptVector0x10() Set Block of Color Registers\n"));
+ Value = (UINT8 *)(UINT64)((Regs->X.ES << 4) + (Regs->X.DX));
+ IoWrite8(VGA_PALETTE_WRITE, Regs->X.BX);
+ for (Count = 0; Count < Regs->X.CX; Count++) {
+ DPRINTF (DBG_VERB, ("XXX [%02d] = 0x%x\n", Count, *Value));
+ IoWrite8(VGA_PALETTE_DATA, *Value);
+ Value++;
+ DPRINTF (DBG_VERB, ("XXX [%02d] = 0x%x\n", Count, *Value));
+ IoWrite8(VGA_PALETTE_DATA, *Value);
+ Value++;
+ DPRINTF (DBG_VERB, ("XXX [%02d] = 0x%x\n", Count, *Value));
+ IoWrite8(VGA_PALETTE_DATA, *Value);
+ Value++;
+ }
+ break;
+ default:
+ DPRINTF (DBG_WARN, ("XXX video (Palette) unhandled\n"));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10()\n"));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->H.AL=0%x\n", Regs->H.AL));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->H.AH=0%x\n", Regs->H.AH));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->X.AX=0%x\n", Regs->X.AX));
+ //for (;;) ;
+ break;
+ }
+}
+
+/*
+ * Video IO
+ */
+VOID
+InterruptVector0x10(EFI_IA32_REGISTER_SET *Regs)
+{
+ BDA *BdaPtr = (BDA *)(UINTN)0x400;
+
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10()\n"));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Regs->H.AL=0%x\n", Regs->H.AL));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Regs->H.AH=0%x\n", Regs->H.AH));
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Regs->X.AX=0%x\n", Regs->X.AX));
+
+ switch (Regs->H.AH) {
+ case 0x00: /* Set Video Mode */
+ DPRINTF (DBG_INFO, ("XXX InterruptVector0x10() Set Mode Mode=0x%x Retain=%s\n", Regs->H.AL & 0x7f, (Regs->H.AL & 0x80) ? L"TRUE" : L"FALSE"));
+ VGASetVideoMode(Regs->H.AL & 0x7f, (Regs->H.AL & 0x80) != 0);
+ break;
+ case 0x01: /* Set Cursor Type */
+ break;
+ case 0x02: /* Set Cursor Postion */
+ VGASetCursorPosition(Regs->H.BH, Regs->H.DL, Regs->H.DH);
+ break;
+ case 0x03: /* Get Cursor Postion */
+ VGAGetCursorPosition(Regs->H.BH, &Regs->H.DL, &Regs->H.DH);
+ break;
+ case 0x05: /* Select Active Display Page */
+ break;
+ case 0x06: /* Window Scroll Up */
+ VGAScrollUp(Regs->H.CL, Regs->H.CH, Regs->H.DL, Regs->H.DH, Regs->H.AL, Regs->H.BH);
+ break;
+ case 0x07: /* Window Scroll Down */
+ VGAScrollDown(Regs->H.CL, Regs->H.CH, Regs->H.DL, Regs->H.DH, Regs->H.AL, Regs->H.BH);
+ break;
+ case 0x08: /* Read Attribute / Character at Current Cursor Position */
+ VGAReadChar(&Regs->H.AL, &Regs->H.AH);
+ break;
+ case 0x09: /* Write Attribute / Character at Current Cursor Position */
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Write Count %d Attr 0x%x/Char '%c' at Current Position\n", Regs->X.CX, Regs->X.CX, Regs->H.AL));
+ switch (Regs->H.AL) {
+ case '\n':
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Write Attr 0x%x / Char '\\n' (0x%02x)\n", Regs->H.BL, Regs->H.AL));
+ break;
+ case '\r':
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Write Attr 0x%x / Char '\\r' (0x%02x)\n", Regs->H.BL, Regs->H.AL));
+ break;
+ default:
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Write Attr 0x%x / Ch '%c' (0x%02x)\n", Regs->H.BL, Regs->H.AL, Regs->H.AL));
+ break;
+ }
+ VGAWriteChars(Regs->H.BH, Regs->X.CX, Regs->H.AL, Regs->H.BL);
+ break;
+ case 0x0a: /* Write Character at Current Cursor Position */
+ switch (Regs->H.AL) {
+ case '\n':
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Write (Attr 0x%x) Char '\\n' (0x%02x)\n", Regs->H.AL));
+ break;
+ case '\r':
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Write (Attr 0x%x) Char '\\r' (0x%02x)\n", Regs->H.AL));
+ break;
+ default:
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Write (Attr 0x%x) Ch '%c'\n", Regs->H.AL, Regs->H.AL));
+ break;
+ }
+ //DEBUG (("XXX InterruptVector0x10() Write Count %d Char '%c' at Current Position\n", Regs->X.CX, Regs->H.AL));
+ if (CurrentState->MemoryModel == MemoryModelText) {
+ VGAWriteChars(Regs->H.BH, Regs->X.CX, Regs->H.AL, -1);
+ } else {
+ VGAWriteChars(Regs->H.BH, Regs->X.CX, Regs->H.AL, Regs->H.BL);
+ }
+ break;
+ case 0x0e: /* Write Teletype Character */
+ switch (Regs->H.AL) {
+ case '\n':
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Write Teletype Char '\\n' (0x%02x)\n", Regs->H.AL));
+ break;
+ case '\r':
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Write Teletype Char '\\r' (0x%02x)\n", Regs->H.AL));
+ break;
+ default:
+ DPRINTF (DBG_VERB, ("XXX InterruptVector0x10() Write Teletype Char '%c' (0x%02x)\n", Regs->H.AL, Regs->H.AL));
+ break;
+ }
+ VGAWriteTeletype(Regs->H.AL);
+ break;
+ case 0x0f: /* Get Video State */
+ Regs->H.AL = CurrentVideoMode;
+ Regs->H.AH = BdaPtr->TextColumns;
+ Regs->H.BH = CurrentActivePage;
+ break;
+ case 0x10: /* Palette */
+ InterruptVector0x10Palette(Regs);
+ break;
+ case 0x11: /* Character Generator */
+ switch (Regs->H.AL) {
+ case 0x30: /* Get Font Information */
+ switch (Regs->H.BH) {
+ case 0x6: /* Return BIOS 8x16 font pointer */
+ Regs->X.ES = (((UINTN)FONTDATA) & ~0xffff) >> 4;
+ Regs->X.BP = ((UINTN)FONTDATA) & 0xffff;
+
+ DPRINTF (DBG_INFO, ("XXX Get font information 0x%x Regs->X.ES=0%x Regs->X.BP=0x%x\n", FONTDATA, Regs->X.ES, Regs->X.BP));
+ break;
+ }
+ break;
+ default:
+ DPRINTF (DBG_WARN, ("XXX video (Character Generator) unhandled\n"));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10()\n"));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->H.AL=0%x\n", Regs->H.AL));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->H.AH=0%x\n", Regs->H.AH));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->X.AX=0%x\n", Regs->X.AX));
+ //for (;;) ;
+ break;
+ }
+ break;
+ case 0x12: /* Special Functions/Alternate Select */
+ switch (Regs->H.BL) {
+ case 0x10: /* Get Current Display Configuration */
+ Regs->H.BH = 0x0; /* color */
+ Regs->H.BL = 0x3; /* 256k */
+ Regs->H.CH = 0x0;
+ Regs->H.CL = 0x0;
+ break;
+ case 0x20: /* Select Alternate Print Screen Handler */
+ break;
+ case 0x34: /* Cursor Emulation */
+ mBdaPtr->VideoModeOptions &= 0x1;
+ mBdaPtr->VideoModeOptions |= (Regs->H.AL & 0x1);
+ break;
+ default:
+ DPRINTF (DBG_WARN, ("XXX video (Special functions/Alternate select) unhandled\n"));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10()\n"));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->H.AL=0%x\n", Regs->H.AL));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->H.AH=0%x\n", Regs->H.AH));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->X.AX=0%x\n", Regs->X.AX));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->H.BL=0%x\n", Regs->H.BL));
+ Regs->H.BH = 0;
+ Regs->H.BL = 0x03;
+ Regs->X.CX = 0;
+ //for (;;) ; // Windows
+ break;
+ }
+ break;
+ case 0x1a: /* Video Display Combination Code (DCC) */
+ switch (Regs->H.AL) {
+ case 0x0: /* Get Display Combination Code (DCC) */
+ Regs->H.AL = 0x1a;
+ Regs->H.BH = 0x0;
+ break;
+ case 0x1: /* Set Display Combination Code (DCC) */
+ break;
+ }
+ break;
+ default:
+ DPRINTF (DBG_WARN, ("XXX video unhandled\n"));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10()\n"));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->H.AL=0%x\n", Regs->H.AL));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->H.AH=0%x\n", Regs->H.AH));
+ DPRINTF (DBG_WARN, ("XXX InterruptVector0x10() Regs->X.AX=0%x\n", Regs->X.AX));
+ //for (;;) ; // Windows
+ break;
+ }
+}
+
+VOID
+VGAInitialize(VOID)
+{
+ DPRINTF (DBG_INFO, ("XXX VGAInitialize()\n"));
+
+ mBdaPtr->VideoModeOptions = 0x60; /* 256k, active, color */
+ mBdaPtr->VideoDisplayDataArea = 0x01; /* VGA is active */
+ mBdaPtr->VideoDCC = 0x08; /* VGA with analog color monitor */
+
+ VGASetVideoMode(0x3, FALSE);
+
+#if 0
+ {
+ UINT16 Val16;
+ UINT32 Val32;
+ UINT64 Val64;
+
+ *(UINT8 *)(0xB8000 + 0 * mBdaPtr->TextColumns + 0) = 'X';
+ *(UINT8 *)(0xB8000 + 0 * mBdaPtr->TextColumns + 0 + 1) = 0x7;
+
+ *(UINT8 *)(0xB8000 + 0 * mBdaPtr->TextColumns + 2) = 'Y';
+ *(UINT8 *)(0xB8000 + 0 * mBdaPtr->TextColumns + 2 + 1) = 0x7;
+
+ *(UINT8 *)(0xB8000 + 0 * mBdaPtr->TextColumns + 4) = 'Z';
+ *(UINT8 *)(0xB8000 + 0 * mBdaPtr->TextColumns + 4 + 1) = 0x7;
+
+ Val16 = *(UINT16 *)(0xB8000 + 0 * mBdaPtr->TextColumns + 0);
+ DEBUG(("XXX Val16 = 0x%x\n", Val16));
+ Val32 = *(UINT32 *)(0xB8000 + 0 * mBdaPtr->TextColumns + 0);
+ DEBUG(("XXX Val32 = 0x%x\n", Val32));
+ Val64 = *(UINT64 *)(0xB8000 + 0 * mBdaPtr->TextColumns + 0);
+ DEBUG(("XXX Val64 = 0x%lx\n", Val64));
+
+ DEBUG(("XXX spinning \n"));
+ for (;;) ;
+ }
+#endif
+}
diff --git BhyvePkg/Csm/BhyveCsm16/Video.h BhyvePkg/Csm/BhyveCsm16/Video.h
new file mode 100644
index 0000000..c865d5a
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/Video.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#ifndef _BHYVECSM16_VIDEO_H_
+#define _BHYVECSM16_VIDEO_H_
+
+VOID
+VGAInitialize(VOID);
+
+#endif
diff --git BhyvePkg/Csm/BhyveCsm16/bdf_to_c.awk BhyvePkg/Csm/BhyveCsm16/bdf_to_c.awk
new file mode 100644
index 0000000..9ee0952
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/bdf_to_c.awk
@@ -0,0 +1,262 @@
+#! /bin/awk -f
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 1998-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+
+BEGIN {
+ pats["0"]=" ";
+ pats["1"]=" X";
+ pats["2"]=" X ";
+ pats["3"]=" XX";
+ pats["4"]=" X ";
+ pats["5"]=" X X";
+ pats["6"]=" XX ";
+ pats["7"]=" XXX";
+ pats["8"]="X ";
+ pats["9"]="X X";
+ pats["a"]="X X "; pats["A"] = pats["a"];
+ pats["b"]="X XX"; pats["B"] = pats["b"];
+ pats["c"]="XX "; pats["C"] = pats["c"];
+ pats["d"]="XX X"; pats["D"] = pats["d"];
+ pats["e"]="XXX "; pats["E"] = pats["e"];
+ pats["f"]="XXXX"; pats["F"] = pats["f"];
+}
+
+$1=="ENDCHAR" {
+ in_bitmap = 0;
+ next;
+}
+
+in_bitmap != 0 {
+ if (ignoring) next;
+
+ for (c = 0; c < byteswide; c++)
+ printf "0x%s, ", substr($0,c*2+1,2);
+ s="";
+ for (c = 0; c < byteswide*2; c++)
+ s = s pats[substr($0,c+1,1)];
+ s = substr(s, 1, bitswide);
+ printf "/* %s */\n", s;
+
+ offset += length($0)/2;
+ next;
+}
+
+$1=="STARTFONT" {
+ if ($2 != "2.1") {
+ printf "Unknown BDF version number %s!\n", $2;
+ exit 1;
+ }
+ in_bitmap = 0;
+ ignoring = 1;
+ first = 1;
+ offset = 0;
+
+ for (i = 0; i < 256; i++)
+ encoding[i] = -1;
+
+ next;
+}
+
+$1=="COMMENT" {
+ if (NF > 1) {
+ printf "/*";
+ for (i = 2; i < NF; i++)
+ printf " %s",$i;
+ printf " */";
+ }
+ printf "\n";
+ next;
+}
+
+$1=="FONT" {
+ printf "/* %s */\n", $0;
+ next;
+}
+
+$1=="SIZE" {
+ next;
+}
+
+$1=="FONTBOUNDINGBOX" {
+ rows = $3;
+ byteswide = int(($2 + 7)/8);
+ bitswide = $2;
+ next;
+}
+
+$1=="STARTPROPERTIES" {
+ next;
+}
+
+$1=="FONTNAME_REGISTRY" {
+ next;
+}
+
+$1=="FOUNDRY" {
+ next;
+}
+
+$1=="FAMILY_NAME" {
+ next;
+}
+
+$1=="WEIGHT_NAME" {
+ next;
+}
+
+$1=="SLANT" {
+ next;
+}
+
+$1=="SETWIDTH_NAME" {
+ next;
+}
+
+$1=="ADD_STYLE_NAME" {
+ next;
+}
+
+$1=="PIXEL_SIZE" {
+ next;
+}
+
+$1=="POINT_SIZE" {
+ next;
+}
+
+$1=="RESOLUTION_X" {
+ next;
+}
+
+$1=="RESOLUTION_Y" {
+ next;
+}
+
+
+$1=="SPACING" {
+ if ($2 != "\"C\"") printf "Unsupported format %s!\n",$2;
+ next;
+}
+
+$1=="AVERAGE_WIDTH" {
+ next;
+}
+
+$1=="CHARSET_REGISTRY" {
+ next;
+}
+
+$1=="CHARSET_ENCODING" {
+ next;
+}
+
+
+$1=="DEFAULT_CHAR" {
+ default_char = $2;
+ next;
+}
+
+$1=="FONT_DESCENT" {
+ next;
+}
+
+$1=="FONT_ASCENT" {
+ next;
+}
+
+$1=="MIN_SPACE" {
+ next;
+}
+
+
+$1=="COPYRIGHT" {
+ printf "/* Copyright notice from .bdf file: */\n";
+ printf "/* %s */\n", $0;
+ next;
+}
+
+$1=="NOTICE" {
+ printf "/* Notice from .bdf file: */\n";
+ printf "/* %s */\n", $0;
+ next;
+}
+
+$1=="ENDPROPERTIES" {
+ next;
+}
+
+$1=="CHARS" {
+ next;
+}
+
+
+$1=="STARTCHAR" {
+ if (first) {
+ printf "unsigned char FONTDATA[] = {\n";
+ first = 0;
+ }
+ ignoring = 1;
+ row = 0;
+ next;
+}
+
+$1=="ENCODING" {
+ encoding[$2] = offset;
+ ignoring = 0;
+ got[$2] = 1;
+ printf "\n";
+ if ($2 >= 32 && $2 < 127) printf "/* '%c' */\n", $2;
+ else printf "/* 0x%2.2x */\n", $2;
+ next;
+}
+
+$1=="SWIDTH" {
+ next;
+}
+
+$1=="DWIDTH" {
+ next;
+}
+
+$1=="BBX" {
+ next;
+}
+
+$1=="BITMAP" {
+ in_bitmap = 1;
+ next;
+}
+
+$1=="ENDFONT" {
+ printf "};\n";
+ next;
+}
+
+{
+ printf "?!? %s\n", $0;
+}
diff --git BhyvePkg/Csm/BhyveCsm16/linker.lds BhyvePkg/Csm/BhyveCsm16/linker.lds
new file mode 100644
index 0000000..0662745
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/linker.lds
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+OUTPUT_FORMAT("elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+
+SECTIONS
+{
+ .raw 0xf0000 : {
+ *(.text)
+ *(.data)
+ *(.rodata)
+ *(.bss)
+ _end = .;
+ . = 0xfff5;
+ *(.tail)
+ } = 0x00
+
+ /DISCARD/ : {
+ *(.note*)
+ *(.comment*)
+ *(.iplt)
+ *(.igot.plt)
+ *(.rela*)
+ *(.eh_frame)
+ }
+}
diff --git BhyvePkg/Csm/BhyveCsm16/ter-u16n-IBM-CP437.bdf BhyvePkg/Csm/BhyveCsm16/ter-u16n-IBM-CP437.bdf
new file mode 100644
index 0000000..148f00d
--- /dev/null
+++ BhyvePkg/Csm/BhyveCsm16/ter-u16n-IBM-CP437.bdf
@@ -0,0 +1,5917 @@
+STARTFONT 2.1
+COMMENT ter-u16n
+FONT -xos4-Terminus-Medium-R-Normal--16-160-72-72-C-80-IBM-CP437
+SIZE 16 72 72
+FONTBOUNDINGBOX 8 16 0 -4
+STARTPROPERTIES 20
+FAMILY_NAME "Terminus"
+FOUNDRY "xos4"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+COPYRIGHT "Copyright (C) 2014 Dimitar Toshkov Zhekov"
+NOTICE "Licensed under the SIL Open Font License, Version 1.1"
+WEIGHT_NAME "Medium"
+SLANT "R"
+PIXEL_SIZE 16
+POINT_SIZE 160
+RESOLUTION_X 72
+RESOLUTION_Y 72
+SPACING "C"
+AVERAGE_WIDTH 80
+CHARSET_REGISTRY "IBM"
+CHARSET_ENCODING "CP437"
+MIN_SPACE 8
+FONT_ASCENT 12
+FONT_DESCENT 4
+DEFAULT_CHAR 65533
+ENDPROPERTIES
+CHARS 256
+STARTCHAR nbspace
+ENCODING 160
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR smileface
+ENCODING 9786
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+82
+AA
+82
+82
+BA
+92
+82
+82
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR invsmileface
+ENCODING 9787
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+FE
+D6
+FE
+FE
+C6
+EE
+FE
+FE
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR heart
+ENCODING 9829
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+6C
+FE
+FE
+FE
+FE
+7C
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR diamond
+ENCODING 9830
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+38
+7C
+FE
+7C
+38
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR club
+ENCODING 9827
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+38
+10
+54
+FE
+FE
+54
+10
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR spade
+ENCODING 9824
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+38
+7C
+FE
+FE
+7C
+10
+10
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR bullet
+ENCODING 8226
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+18
+3C
+3C
+18
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR invbullet
+ENCODING 9688
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FF
+FF
+FF
+FF
+FF
+FF
+E7
+C3
+C3
+E7
+FF
+FF
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR circle
+ENCODING 9675
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+18
+24
+24
+18
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR invcircle
+ENCODING 9689
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FF
+FF
+FF
+FF
+FF
+FF
+E7
+DB
+DB
+E7
+FF
+FF
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR male
+ENCODING 9794
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1E
+06
+0A
+12
+38
+44
+44
+44
+44
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR female
+ENCODING 9792
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+44
+44
+44
+44
+38
+10
+7C
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR musicalnote
+ENCODING 9834
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3E
+22
+3E
+20
+20
+20
+20
+20
+20
+C0
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR musicalnotedbl
+ENCODING 9835
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+42
+7E
+42
+42
+42
+42
+42
+42
+44
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR sun
+ENCODING 9788
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+92
+54
+38
+EE
+38
+54
+92
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25B6
+ENCODING 9654
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+C0
+F0
+FC
+FF
+FC
+F0
+C0
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni25C0
+ENCODING 9664
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+03
+0F
+3F
+FF
+3F
+0F
+03
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowupdn
+ENCODING 8597
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+54
+10
+10
+10
+10
+54
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclamdbl
+ENCODING 8252
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+24
+24
+24
+24
+24
+24
+00
+24
+24
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+92
+92
+92
+92
+72
+12
+12
+12
+12
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+44
+40
+30
+48
+44
+44
+24
+18
+04
+44
+38
+00
+00
+00
+ENDCHAR
+STARTCHAR filledrect
+ENCODING 9644
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+7E
+7E
+7E
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowupdnbse
+ENCODING 8616
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+54
+10
+10
+10
+54
+38
+10
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowup
+ENCODING 8593
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+38
+54
+10
+10
+10
+10
+10
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowdown
+ENCODING 8595
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+10
+10
+10
+10
+10
+54
+38
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowright
+ENCODING 8594
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+08
+04
+FE
+04
+08
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowleft
+ENCODING 8592
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+20
+40
+FE
+40
+20
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR orthogonal
+ENCODING 8735
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+40
+40
+40
+40
+40
+7E
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR arrowboth
+ENCODING 8596
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+24
+42
+FF
+42
+24
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR triagup
+ENCODING 9650
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+10
+38
+38
+7C
+7C
+FE
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR triagdn
+ENCODING 9660
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+FE
+FE
+7C
+7C
+38
+38
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR space
+ENCODING 32
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+10
+10
+10
+10
+10
+00
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+24
+24
+24
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+24
+24
+7E
+24
+24
+7E
+24
+24
+24
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+10
+7C
+92
+90
+90
+7C
+12
+12
+92
+7C
+10
+10
+00
+00
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+64
+94
+68
+08
+10
+10
+20
+2C
+52
+4C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+24
+24
+18
+30
+4A
+44
+44
+44
+3A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR quotesingle
+ENCODING 39
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+10
+10
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+10
+20
+20
+20
+20
+20
+20
+10
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+10
+08
+08
+08
+08
+08
+08
+10
+20
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+24
+18
+7E
+18
+24
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+10
+7C
+10
+10
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+10
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 45
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+7E
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+04
+08
+08
+10
+10
+20
+20
+40
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR zero
+ENCODING 48
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+46
+4A
+52
+62
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR one
+ENCODING 49
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+18
+28
+08
+08
+08
+08
+08
+08
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR two
+ENCODING 50
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+02
+04
+08
+10
+20
+40
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR three
+ENCODING 51
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+02
+1C
+02
+02
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR four
+ENCODING 52
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+02
+06
+0A
+12
+22
+42
+7E
+02
+02
+02
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR five
+ENCODING 53
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+40
+40
+40
+7C
+02
+02
+02
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR six
+ENCODING 54
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+1C
+20
+40
+40
+7C
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR seven
+ENCODING 55
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+02
+02
+04
+04
+08
+08
+10
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR eight
+ENCODING 56
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+42
+3C
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR nine
+ENCODING 57
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+42
+42
+3E
+02
+02
+04
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+10
+00
+00
+00
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+10
+00
+00
+00
+10
+10
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+04
+08
+10
+20
+40
+20
+10
+08
+04
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+00
+00
+7E
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+40
+20
+10
+08
+04
+08
+10
+20
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+42
+04
+08
+08
+00
+08
+08
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+82
+9E
+A2
+A2
+A2
+A6
+9A
+80
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+42
+42
+7E
+42
+42
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+42
+42
+42
+7C
+42
+42
+42
+42
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+40
+40
+40
+40
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+78
+44
+42
+42
+42
+42
+42
+42
+44
+78
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+40
+40
+40
+78
+40
+40
+40
+40
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+40
+40
+40
+78
+40
+40
+40
+40
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+40
+40
+4E
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+42
+42
+42
+42
+7E
+42
+42
+42
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+10
+10
+10
+10
+10
+10
+10
+10
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0E
+04
+04
+04
+04
+04
+04
+44
+44
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+42
+44
+48
+50
+60
+60
+50
+48
+44
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+82
+C6
+AA
+92
+92
+82
+82
+82
+82
+82
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+42
+42
+42
+62
+52
+4A
+46
+42
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+42
+42
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+42
+42
+42
+42
+7C
+40
+40
+40
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+42
+42
+42
+42
+42
+4A
+3C
+02
+00
+00
+00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7C
+42
+42
+42
+42
+7C
+50
+48
+44
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+40
+40
+3C
+02
+02
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+FE
+10
+10
+10
+10
+10
+10
+10
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+42
+42
+42
+42
+42
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+42
+42
+42
+42
+42
+24
+24
+24
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+82
+82
+82
+82
+82
+92
+92
+AA
+C6
+82
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+42
+42
+24
+24
+18
+18
+24
+24
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+82
+82
+44
+44
+28
+10
+10
+10
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+02
+02
+04
+08
+10
+20
+40
+40
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+20
+20
+20
+20
+20
+20
+20
+20
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+40
+40
+20
+20
+10
+10
+08
+08
+04
+04
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+08
+08
+08
+08
+08
+08
+08
+08
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+10
+28
+44
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+7E
+00
+00
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+08
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+02
+3E
+42
+42
+42
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+40
+40
+40
+7C
+42
+42
+42
+42
+42
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+42
+40
+40
+40
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+02
+02
+02
+3E
+42
+42
+42
+42
+42
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+42
+42
+7E
+40
+40
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0E
+10
+10
+7C
+10
+10
+10
+10
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3E
+42
+42
+42
+42
+42
+3E
+02
+02
+3C
+00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+40
+40
+40
+7C
+42
+42
+42
+42
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+00
+30
+10
+10
+10
+10
+10
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+04
+04
+00
+0C
+04
+04
+04
+04
+04
+04
+44
+44
+38
+00
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+40
+40
+40
+42
+44
+48
+70
+48
+44
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+10
+10
+10
+10
+10
+10
+10
+10
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FC
+92
+92
+92
+92
+92
+92
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+42
+42
+42
+42
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+42
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+42
+42
+42
+42
+42
+7C
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3E
+42
+42
+42
+42
+42
+3E
+02
+02
+02
+00
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+5E
+60
+40
+40
+40
+40
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3E
+40
+40
+3C
+02
+02
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+10
+7C
+10
+10
+10
+10
+10
+0E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+42
+42
+42
+42
+42
+42
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+42
+42
+42
+24
+24
+18
+18
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+82
+82
+92
+92
+92
+92
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+42
+42
+24
+18
+24
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+42
+42
+42
+42
+42
+42
+3E
+02
+02
+3C
+00
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+04
+08
+10
+20
+40
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+10
+10
+10
+20
+10
+10
+10
+10
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+08
+08
+08
+04
+08
+08
+08
+08
+30
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+62
+92
+8C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR house
+ENCODING 8962
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+28
+44
+82
+82
+82
+82
+FE
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+40
+40
+40
+40
+42
+42
+3C
+10
+10
+20
+00
+ENDCHAR
+STARTCHAR udieresis
+ENCODING 252
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+24
+00
+42
+42
+42
+42
+42
+42
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+10
+00
+3C
+42
+42
+7E
+40
+40
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+24
+00
+3C
+02
+3E
+42
+42
+42
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR adieresis
+ENCODING 228
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+24
+00
+3C
+02
+3E
+42
+42
+42
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+08
+00
+3C
+02
+3E
+42
+42
+42
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+24
+18
+3C
+02
+3E
+42
+42
+42
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+42
+40
+40
+40
+42
+3C
+10
+10
+20
+00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+24
+00
+3C
+42
+42
+7E
+40
+40
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR edieresis
+ENCODING 235
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+24
+00
+3C
+42
+42
+7E
+40
+40
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+08
+00
+3C
+42
+42
+7E
+40
+40
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR idieresis
+ENCODING 239
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+48
+48
+00
+30
+10
+10
+10
+10
+10
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+30
+48
+00
+30
+10
+10
+10
+10
+10
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+20
+10
+00
+30
+10
+10
+10
+10
+10
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Adieresis
+ENCODING 196
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+24
+24
+00
+3C
+42
+42
+42
+7E
+42
+42
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+18
+24
+18
+3C
+42
+42
+42
+7E
+42
+42
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+08
+10
+00
+7E
+40
+40
+40
+78
+40
+40
+40
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+6C
+12
+72
+9E
+90
+90
+6C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+90
+90
+90
+FC
+90
+90
+90
+90
+9E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+24
+00
+3C
+42
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR odieresis
+ENCODING 246
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+24
+00
+3C
+42
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+08
+00
+3C
+42
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+24
+00
+42
+42
+42
+42
+42
+42
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+08
+00
+42
+42
+42
+42
+42
+42
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ydieresis
+ENCODING 255
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+24
+24
+00
+42
+42
+42
+42
+42
+42
+3E
+02
+02
+3C
+00
+ENDCHAR
+STARTCHAR Odieresis
+ENCODING 214
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+24
+24
+00
+3C
+42
+42
+42
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Udieresis
+ENCODING 220
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+24
+24
+00
+42
+42
+42
+42
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+10
+10
+7C
+92
+90
+90
+90
+92
+7C
+10
+10
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+18
+24
+20
+20
+78
+20
+20
+20
+22
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+82
+82
+44
+28
+10
+7C
+10
+7C
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR peseta
+ENCODING 8359
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+F0
+88
+88
+88
+F4
+84
+8E
+84
+84
+82
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR florin
+ENCODING 402
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+12
+10
+10
+7C
+10
+10
+10
+10
+10
+10
+90
+60
+00
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+10
+00
+3C
+02
+3E
+42
+42
+42
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+10
+00
+30
+10
+10
+10
+10
+10
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+10
+00
+3C
+42
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+08
+10
+00
+42
+42
+42
+42
+42
+42
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+32
+4C
+00
+7C
+42
+42
+42
+42
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+32
+4C
+00
+42
+42
+62
+52
+4A
+46
+42
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+04
+3C
+44
+3C
+00
+7C
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ordmasculine
+ENCODING 186
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+44
+44
+44
+38
+00
+7C
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+00
+10
+10
+20
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR revlogicalnot
+ENCODING 8976
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+40
+40
+40
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR logicalnot
+ENCODING 172
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+02
+02
+02
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+20
+60
+20
+22
+24
+08
+10
+20
+4C
+92
+04
+08
+1E
+00
+00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+20
+60
+20
+22
+24
+08
+10
+22
+46
+8A
+1E
+02
+02
+00
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+10
+00
+10
+10
+10
+10
+10
+10
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+12
+24
+48
+90
+48
+24
+12
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+90
+48
+24
+12
+24
+48
+90
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ltshade
+ENCODING 9617
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+88
+22
+88
+22
+88
+22
+88
+22
+88
+22
+88
+22
+88
+22
+88
+22
+ENDCHAR
+STARTCHAR shade
+ENCODING 9618
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+AA
+55
+AA
+55
+AA
+55
+AA
+55
+AA
+55
+AA
+55
+AA
+55
+AA
+55
+ENDCHAR
+STARTCHAR dkshade
+ENCODING 9619
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+EE
+BB
+EE
+BB
+EE
+BB
+EE
+BB
+EE
+BB
+EE
+BB
+EE
+BB
+EE
+BB
+ENDCHAR
+STARTCHAR SF110000
+ENCODING 9474
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR SF090000
+ENCODING 9508
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+F0
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR SF190000
+ENCODING 9569
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+F0
+10
+F0
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR SF200000
+ENCODING 9570
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+28
+E8
+28
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF210000
+ENCODING 9558
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+F8
+28
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF220000
+ENCODING 9557
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+F0
+10
+F0
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR SF230000
+ENCODING 9571
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+E8
+08
+E8
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF240000
+ENCODING 9553
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+28
+28
+28
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF250000
+ENCODING 9559
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+F8
+08
+E8
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF260000
+ENCODING 9565
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+E8
+08
+F8
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF270000
+ENCODING 9564
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+28
+F8
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF280000
+ENCODING 9563
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+F0
+10
+F0
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF030000
+ENCODING 9488
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+F0
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR SF020000
+ENCODING 9492
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+1F
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF070000
+ENCODING 9524
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF060000
+ENCODING 9516
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR SF080000
+ENCODING 9500
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+1F
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR SF100000
+ENCODING 9472
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF050000
+ENCODING 9532
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+FF
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR SF360000
+ENCODING 9566
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+1F
+10
+1F
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR SF370000
+ENCODING 9567
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+28
+2F
+28
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF380000
+ENCODING 9562
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+2F
+20
+3F
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF390000
+ENCODING 9556
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+3F
+20
+2F
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF400000
+ENCODING 9577
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+EF
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF410000
+ENCODING 9574
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+FF
+00
+EF
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF420000
+ENCODING 9568
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+2F
+20
+2F
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF430000
+ENCODING 9552
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+FF
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF440000
+ENCODING 9580
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+EF
+00
+EF
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF450000
+ENCODING 9575
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+FF
+00
+FF
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF460000
+ENCODING 9576
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+28
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF470000
+ENCODING 9572
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+FF
+00
+FF
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR SF480000
+ENCODING 9573
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+FF
+28
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF490000
+ENCODING 9561
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+28
+3F
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF500000
+ENCODING 9560
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+1F
+10
+1F
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF510000
+ENCODING 9554
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+1F
+10
+1F
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR SF520000
+ENCODING 9555
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+3F
+28
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF530000
+ENCODING 9579
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+28
+28
+28
+28
+28
+28
+28
+FF
+28
+28
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR SF540000
+ENCODING 9578
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+FF
+10
+FF
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR SF040000
+ENCODING 9496
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+F0
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR SF010000
+ENCODING 9484
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+1F
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR block
+ENCODING 9608
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR dnblock
+ENCODING 9604
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+ENDCHAR
+STARTCHAR lfblock
+ENCODING 9612
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+F0
+ENDCHAR
+STARTCHAR rtblock
+ENCODING 9616
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+0F
+ENDCHAR
+STARTCHAR upblock
+ENCODING 9600
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+FF
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR alpha
+ENCODING 945
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3A
+46
+44
+44
+44
+46
+3A
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR beta
+ENCODING 946
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+38
+44
+44
+48
+7C
+42
+42
+42
+42
+7C
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR Gamma
+ENCODING 915
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+40
+40
+40
+40
+40
+40
+40
+40
+40
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR pi
+ENCODING 960
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7E
+42
+42
+42
+42
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Sigma
+ENCODING 931
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+7E
+40
+20
+10
+08
+08
+10
+20
+40
+7E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR sigma
+ENCODING 963
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3E
+44
+44
+44
+44
+44
+38
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+42
+42
+42
+42
+42
+46
+7A
+40
+40
+40
+00
+ENDCHAR
+STARTCHAR tau
+ENCODING 964
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+FE
+10
+10
+10
+10
+10
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Phi
+ENCODING 934
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+10
+7C
+92
+92
+92
+92
+92
+92
+7C
+10
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Theta
+ENCODING 920
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+42
+5A
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR Omega
+ENCODING 937
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3C
+42
+42
+42
+42
+42
+42
+24
+24
+66
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR delta
+ENCODING 948
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+3E
+10
+08
+3C
+42
+42
+42
+42
+42
+3C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR infinity
+ENCODING 8734
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+7C
+92
+92
+92
+7C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR emptyset
+ENCODING 8709
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+02
+04
+7C
+8A
+92
+92
+A2
+7C
+40
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR uni220A
+ENCODING 8714
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+1E
+20
+40
+7E
+40
+20
+1E
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR intersection
+ENCODING 8745
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+3C
+42
+42
+42
+42
+42
+42
+42
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR equivalence
+ENCODING 8801
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+7E
+00
+00
+7E
+00
+00
+7E
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+10
+10
+7C
+10
+10
+00
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR greaterequal
+ENCODING 8805
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+20
+10
+08
+04
+08
+10
+20
+00
+7C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR lessequal
+ENCODING 8804
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+04
+08
+10
+20
+10
+08
+04
+00
+3E
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR integraltp
+ENCODING 8992
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+0C
+12
+12
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR integralbt
+ENCODING 8993
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+10
+10
+90
+90
+60
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR divide
+ENCODING 247
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+10
+10
+00
+7C
+00
+10
+10
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR approxequal
+ENCODING 8776
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+32
+4C
+00
+32
+4C
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+24
+24
+18
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR bulletoperator
+ENCODING 8729
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+18
+18
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+10
+10
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR radical
+ENCODING 8730
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+06
+04
+04
+04
+04
+44
+44
+44
+24
+14
+0C
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR nsuperior
+ENCODING 8319
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+38
+24
+24
+24
+24
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+18
+24
+08
+10
+3C
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR filledbox
+ENCODING 9632
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+3C
+3C
+3C
+3C
+3C
+3C
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR nbspace
+ENCODING 160
+SWIDTH 500 0
+DWIDTH 8 0
+BBX 8 16 0 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+ENDFONT
diff --git BhyvePkg/Csm/CsmSupportLib/BhyveCsmSupportLib.c BhyvePkg/Csm/CsmSupportLib/BhyveCsmSupportLib.c
new file mode 100644
index 0000000..bd65340
--- /dev/null
+++ BhyvePkg/Csm/CsmSupportLib/BhyveCsmSupportLib.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * This program and the accompanying materials are licensed and made
+ * available under the terms and conditions of the BSD License which
+ * accompanies this distribution. The full text of the license may be
+ * found at http://opensource.org/licenses/bsd-license.php
+ *
+ * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
+ * BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED.
+ */
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#define EFI_SYSTEM_TABLE_MAX_ADDRESS 0xFFFFFFFF
+#define SYS_TABLE_PAD(ptr) (((~ptr) + 1) & 0x07)
+
+EFI_PHYSICAL_ADDRESS *mMpsTable;
+UINT32 mMpsTableLength;
+
+STATIC EFI_STATUS
+ShadowMpsTable (
+ IN OUT VOID **Table,
+ UINT32 *TableLength
+ )
+{
+ UINT32 Data32;
+ UINT32 FPLength;
+ EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerOri;
+ EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointerNew;
+ EFI_LEGACY_MP_TABLE_HEADER *MpsTableOri;
+ EFI_LEGACY_MP_TABLE_HEADER *MpsTableNew;
+ VOID *OemTableOri;
+ VOID *OemTableNew;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS BufferPtr;
+
+ //
+ // Get MP configuration Table
+ //
+ MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(*Table);
+
+ //
+ // Get Floating pointer structure length
+ //
+ FPLength = MpsFloatingPointerOri->Length * 16;
+ Data32 = FPLength + SYS_TABLE_PAD (FPLength);
+ MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress);
+ if (MpsTableOri != NULL) {
+ Data32 += MpsTableOri->BaseTableLength;
+ Data32 += MpsTableOri->ExtendedTableLength;
+ if (MpsTableOri->OemTablePointer != 0x00) {
+ Data32 += SYS_TABLE_PAD (Data32);
+ Data32 += MpsTableOri->OemTableSize;
+ }
+ *TableLength = Data32;
+ } else {
+ *TableLength = 0;
+ return EFI_SUCCESS;
+ }
+ //
+ // Relocate memory
+ //
+ BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiLoaderData,
+ EFI_SIZE_TO_PAGES(Data32),
+ &BufferPtr
+ );
+ if (EFI_ERROR (Status)) {
+ return (Status);
+ }
+
+ MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr;
+ CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength);
+
+ //
+ // If Mp Table exists
+ //
+ if (MpsTableOri != NULL) {
+ //
+ // Get Mps table length, including Ext table
+ //
+ BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength);
+ MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr;
+ CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength);
+
+ if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){
+ BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength;
+ BufferPtr += SYS_TABLE_PAD (BufferPtr);
+ OemTableNew = (VOID *)(UINTN)BufferPtr;
+ OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer;
+ CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize);
+ MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew;
+ }
+ MpsTableNew->Checksum = 0;
+ MpsTableNew->Checksum = CalculateCheckSum8 ((UINT8 *)MpsTableNew, MpsTableOri->BaseTableLength);
+ MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew;
+ MpsFloatingPointerNew->Checksum = 0;
+ MpsFloatingPointerNew->Checksum = CalculateCheckSum8 ((UINT8 *)MpsFloatingPointerNew, FPLength);
+ }
+
+ //
+ // Change the pointer
+ //
+ *Table = MpsFloatingPointerNew;
+
+ return EFI_SUCCESS;
+}
+
+VOID
+ShadowSystemTables (
+ VOID
+ )
+{
+ VOID *Table;
+ UINT32 TableLength;
+
+ Table = (VOID *)0xF0000;
+ TableLength = 0;
+
+ ShadowMpsTable(&Table, &TableLength);
+ mMpsTable = Table;
+ mMpsTableLength = TableLength;
+}
+
+VOID
+FixupMpsTable (
+ UINT32 TablePtr
+ )
+{
+ EFI_LEGACY_MP_TABLE_FLOATING_POINTER *MpsFloatingPointer;
+ UINT32 FPLength;
+
+ MpsFloatingPointer = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)mMpsTable;
+ FPLength = MpsFloatingPointer->Length * 16;
+
+ MpsFloatingPointer->PhysicalAddress = TablePtr + FPLength + SYS_TABLE_PAD (FPLength);
+ MpsFloatingPointer->Checksum = 0;
+ MpsFloatingPointer->Checksum = CalculateCheckSum8 ((UINT8 *)MpsFloatingPointer, FPLength);
+}
diff --git BhyvePkg/Csm/CsmSupportLib/CsmSupportLib.c BhyvePkg/Csm/CsmSupportLib/CsmSupportLib.c
new file mode 100644
index 0000000..08b3be3
--- /dev/null
+++ BhyvePkg/Csm/CsmSupportLib/CsmSupportLib.c
@@ -0,0 +1,49 @@
+/** @file
+ Platform CSM Support Library
+
+ Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "CsmSupportLib.h"
+
+#ifndef NOT_BHYVE
+VOID
+ShadowSystemTables (
+ VOID
+ );
+#endif
+
+/**
+ The constructor function for the platform CSM support library
+
+ @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
+
+**/
+RETURN_STATUS
+EFIAPI
+CsmSupportLibConstructor (
+ VOID
+ )
+{
+ LegacyRegionInit ();
+
+ LegacyInterruptInstall ();
+
+ LegacyBiosPlatformInstall ();
+
+#ifndef NOT_BHYVE
+ ShadowSystemTables ();
+#endif
+
+ return EFI_SUCCESS;
+}
+
diff --git BhyvePkg/Csm/CsmSupportLib/CsmSupportLib.h BhyvePkg/Csm/CsmSupportLib/CsmSupportLib.h
new file mode 100644
index 0000000..927d596
--- /dev/null
+++ BhyvePkg/Csm/CsmSupportLib/CsmSupportLib.h
@@ -0,0 +1,55 @@
+/** @file
+ Platform CSM Support Library
+
+ Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _CSM_SUPPORT_LIB_H_
+#define _CSM_SUPPORT_LIB_H_
+
+#include
+
+/**
+ Initialize Legacy Region support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyRegionInit (
+ VOID
+ );
+
+/**
+ Initialize Legacy Interrupt support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyInterruptInstall (
+ VOID
+ );
+
+/**
+ Initialize Legacy Platform support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyBiosPlatformInstall (
+ VOID
+ );
+
+#endif
+
diff --git BhyvePkg/Csm/CsmSupportLib/CsmSupportLib.inf BhyvePkg/Csm/CsmSupportLib/CsmSupportLib.inf
new file mode 100644
index 0000000..f54c6b9
--- /dev/null
+++ BhyvePkg/Csm/CsmSupportLib/CsmSupportLib.inf
@@ -0,0 +1,55 @@
+## @file
+# Platform CSM Support Library
+#
+# Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CsmSupportLib
+ FILE_GUID = 04e03541-4663-417d-93f6-976378247d61
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CsmSupportLib
+
+ CONSTRUCTOR = CsmSupportLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ CsmSupportLib.c
+ LegacyInterrupt.c
+ LegacyRegion.c
+ LegacyPlatform.c
+ BhyveCsmSupportLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ IntelFrameworkPkg/IntelFrameworkPkg.dec
+
+[Protocols]
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiDiskInfoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLegacyBiosPlatformProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLegacyBiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiLegacyInterruptProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiLegacyRegion2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiPciIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[LibraryClasses]
+ BaseLib
+ PciLib
+ IoLib
+
diff --git BhyvePkg/Csm/CsmSupportLib/LegacyInterrupt.c BhyvePkg/Csm/CsmSupportLib/LegacyInterrupt.c
new file mode 100644
index 0000000..0dceeda
--- /dev/null
+++ BhyvePkg/Csm/CsmSupportLib/LegacyInterrupt.c
@@ -0,0 +1,196 @@
+/** @file
+ Legacy Interrupt Support
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "LegacyInterrupt.h"
+
+//
+// Handle for the Legacy Interrupt Protocol instance produced by this driver
+//
+STATIC EFI_HANDLE mLegacyInterruptHandle = NULL;
+
+//
+// The Legacy Interrupt Protocol instance produced by this driver
+//
+STATIC EFI_LEGACY_INTERRUPT_PROTOCOL mLegacyInterrupt = {
+ GetNumberPirqs,
+ GetLocation,
+ ReadPirq,
+ WritePirq
+};
+
+STATIC UINT8 PirqReg[MAX_PIRQ_NUMBER] = { PIRQA, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH };
+
+
+/**
+ Return the number of PIRQs supported by this chipset.
+
+ @param[in] This Pointer to LegacyInterrupt Protocol
+ @param[out] NumberPirqs The pointer to return the max IRQ number supported
+
+ @retval EFI_SUCCESS Max PIRQs successfully returned
+
+**/
+EFI_STATUS
+EFIAPI
+GetNumberPirqs (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *NumberPirqs
+ )
+{
+ *NumberPirqs = MAX_PIRQ_NUMBER;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Return PCI location of this device.
+ $PIR table requires this info.
+
+ @param[in] This - Protocol instance pointer.
+ @param[out] Bus - PCI Bus
+ @param[out] Device - PCI Device
+ @param[out] Function - PCI Function
+
+ @retval EFI_SUCCESS Bus/Device/Function returned
+
+**/
+EFI_STATUS
+EFIAPI
+GetLocation (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *Bus,
+ OUT UINT8 *Device,
+ OUT UINT8 *Function
+ )
+{
+ *Bus = LEGACY_INT_BUS;
+ *Device = LEGACY_INT_DEV;
+ *Function = LEGACY_INT_FUNC;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Builds the PCI configuration address for the register specified by PirqNumber
+
+ @param[in] PirqNumber - The PIRQ number to build the PCI configuration address for
+
+ @return The PCI Configuration address for the PIRQ
+**/
+UINTN
+GetAddress (
+ UINT8 PirqNumber
+ )
+{
+ return PCI_LIB_ADDRESS(
+ LEGACY_INT_BUS,
+ LEGACY_INT_DEV,
+ LEGACY_INT_FUNC,
+ PirqReg[PirqNumber]
+ );
+}
+
+/**
+ Read the given PIRQ register
+
+ @param[in] This Protocol instance pointer
+ @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc
+ @param[out] PirqData Value read
+
+ @retval EFI_SUCCESS Decoding change affected.
+ @retval EFI_INVALID_PARAMETER Invalid PIRQ number
+
+**/
+EFI_STATUS
+EFIAPI
+ReadPirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ OUT UINT8 *PirqData
+ )
+{
+ if (PirqNumber >= MAX_PIRQ_NUMBER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *PirqData = PciRead8 (GetAddress (PirqNumber));
+ *PirqData = (UINT8) (*PirqData & 0x7f);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Write the given PIRQ register
+
+ @param[in] This Protocol instance pointer
+ @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc
+ @param[out] PirqData Value to write
+
+ @retval EFI_SUCCESS Decoding change affected.
+ @retval EFI_INVALID_PARAMETER Invalid PIRQ number
+
+**/
+EFI_STATUS
+EFIAPI
+WritePirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ IN UINT8 PirqData
+ )
+{
+ if (PirqNumber >= MAX_PIRQ_NUMBER) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PciWrite8 (GetAddress (PirqNumber), PirqData);
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize Legacy Interrupt support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyInterruptInstall (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Make sure the Legacy Interrupt Protocol is not already installed in the system
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED(NULL, &gEfiLegacyInterruptProtocolGuid);
+
+ //
+ // Make a new handle and install the protocol
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mLegacyInterruptHandle,
+ &gEfiLegacyInterruptProtocolGuid,
+ &mLegacyInterrupt,
+ NULL
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ return Status;
+}
+
diff --git BhyvePkg/Csm/CsmSupportLib/LegacyInterrupt.h BhyvePkg/Csm/CsmSupportLib/LegacyInterrupt.h
new file mode 100644
index 0000000..eddd6ab
--- /dev/null
+++ BhyvePkg/Csm/CsmSupportLib/LegacyInterrupt.h
@@ -0,0 +1,119 @@
+/** @file
+ Legacy Region Support
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LEGACY_INTERRUPT_H_
+#define _LEGACY_INTERRUPT_H_
+
+#include
+
+#include
+
+#include
+#include
+#include
+
+#define LEGACY_INT_BUS 0
+#define LEGACY_INT_DEV 1
+#define LEGACY_INT_FUNC 0
+
+#define PIRQN 0x00 // PIRQ Null
+#define PIRQA 0x60
+#define PIRQB 0x61
+#define PIRQC 0x62
+#define PIRQD 0x63
+#define PIRQE 0x68
+#define PIRQF 0x69
+#define PIRQG 0x6A
+#define PIRQH 0x6B
+
+#define MAX_PIRQ_NUMBER 8
+
+/**
+ Return the number of PIRQs supported by this chipset.
+
+ @param[in] This Pointer to LegacyInterrupt Protocol
+ @param[out] NumberPirqs The pointer to return the max IRQ number supported
+
+ @retval EFI_SUCCESS Max PIRQs successfully returned
+
+**/
+EFI_STATUS
+EFIAPI
+GetNumberPirqs (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *NumberPirqs
+ );
+
+/**
+ Return PCI location of this device.
+ $PIR table requires this info.
+
+ @param[in] This - Protocol instance pointer.
+ @param[out] Bus - PCI Bus
+ @param[out] Device - PCI Device
+ @param[out] Function - PCI Function
+
+ @retval EFI_SUCCESS Bus/Device/Function returned
+
+**/
+EFI_STATUS
+EFIAPI
+GetLocation (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ OUT UINT8 *Bus,
+ OUT UINT8 *Device,
+ OUT UINT8 *Function
+ );
+
+/**
+ Read the given PIRQ register
+
+ @param[in] This Protocol instance pointer
+ @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc
+ @param[out] PirqData Value read
+
+ @retval EFI_SUCCESS Decoding change affected.
+ @retval EFI_INVALID_PARAMETER Invalid PIRQ number
+
+**/
+EFI_STATUS
+EFIAPI
+ReadPirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ OUT UINT8 *PirqData
+ );
+
+/**
+ Write the given PIRQ register
+
+ @param[in] This Protocol instance pointer
+ @param[in] PirqNumber The Pirq register 0 = A, 1 = B etc
+ @param[out] PirqData Value to write
+
+ @retval EFI_SUCCESS Decoding change affected.
+ @retval EFI_INVALID_PARAMETER Invalid PIRQ number
+
+**/
+EFI_STATUS
+EFIAPI
+WritePirq (
+ IN EFI_LEGACY_INTERRUPT_PROTOCOL *This,
+ IN UINT8 PirqNumber,
+ IN UINT8 PirqData
+ );
+
+#endif
+
diff --git BhyvePkg/Csm/CsmSupportLib/LegacyPlatform.c BhyvePkg/Csm/CsmSupportLib/LegacyPlatform.c
new file mode 100644
index 0000000..641cbc5
--- /dev/null
+++ BhyvePkg/Csm/CsmSupportLib/LegacyPlatform.c
@@ -0,0 +1,1084 @@
+/** @file
+ Legacy BIOS Platform support
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "LegacyPlatform.h"
+
+EFI_SETUP_BBS_MAP mSetupBbsMap[] = {
+ { 1, 2, 1, 1 }, // ATA HardDrive
+ { 2, 3, 1, 1 }, // ATAPI CDROM
+ { 3, 0x80, 2, 0 }, // PXE
+ { 4, 1, 0, 6 }, // USB Floppy
+ { 4, 2, 0, 6 }, // USB HDD
+ { 4, 3, 0, 6 }, // USB CD
+ { 4, 1, 0, 0 }, // USB ZIP Bugbug since Class/SubClass code is uninitialized
+ { 4, 2, 0, 0 } // USB ZIP Bugbug since Class/SubClass code is uninitialized
+};
+
+//
+// Global variables for System ROMs
+//
+#define SYSTEM_ROM_FILE_GUID \
+{ 0x1547B4F3, 0x3E8A, 0x4FEF, { 0x81, 0xC8, 0x32, 0x8E, 0xD6, 0x47, 0xAB, 0x1A } }
+
+#define NULL_ROM_FILE_GUID \
+{ 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+
+SYSTEM_ROM_TABLE mSystemRomTable[] = {
+ { SYSTEM_ROM_FILE_GUID, 1 },
+ { NULL_ROM_FILE_GUID, 0 }
+};
+
+EFI_HANDLE mVgaHandles[0x20];
+EFI_HANDLE mDiskHandles[0x20];
+EFI_HANDLE mIsaHandles[0x20];
+
+EFI_LEGACY_IRQ_PRIORITY_TABLE_ENTRY IrqPriorityTable[MAX_IRQ_PRIORITY_ENTRIES] = {
+ {0x0B,0},
+ {0x09,0},
+ {0x0A,0},
+ {0x05,0},
+ {0x07,0},
+ {0x00,0},
+ {0x00,0}
+};
+
+//
+// PIRQ Table
+// - Slot numbering will be used to update the bus number and determine bridge
+// to check to get bus number. The Slot number - 1 is an index into a decode
+// table to get the bridge information.
+//
+EFI_LEGACY_PIRQ_TABLE PirqTableHead = {
+ {
+ EFI_LEGACY_PIRQ_TABLE_SIGNATURE, // UINT32 Signature
+ 0x00, // UINT8 MinorVersion
+ 0x01, // UINT8 MajorVersion
+ 0x0000, // UINT16 TableSize
+ 0x00, // UINT8 Bus
+ 0x08, // UINT8 DevFun
+ 0x0000, // UINT16 PciOnlyIrq
+ 0x8086, // UINT16 CompatibleVid
+ 0x122e, // UINT16 CompatibleDid
+ 0x00000000, // UINT32 Miniport
+ { // UINT8 Reserved[11]
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00
+ },
+ 0x00, // UINT8 Checksum
+ },
+ {
+ // -- Pin 1 -- -- Pin 2 -- -- Pin 3 -- -- Pin 4 --
+ // Bus Dev Reg Map Reg Map Reg Map Reg Map
+ //
+ {0x00,0x08,{{0x60,0xDEB8},{0x61,0xDEB8},{0x62,0xDEB8},{0x63,0xDEB8}},0x00,0x00},
+ {0x00,0x10,{{0x61,0xDEB8},{0x62,0xDEB8},{0x63,0xDEB8},{0x60,0xDEB8}},0x01,0x00},
+ {0x00,0x18,{{0x62,0xDEB8},{0x63,0xDEB8},{0x60,0xDEB8},{0x61,0xDEB8}},0x02,0x00},
+ {0x00,0x20,{{0x63,0xDEB8},{0x60,0xDEB8},{0x61,0xDEB8},{0x62,0xDEB8}},0x03,0x00},
+ {0x00,0x28,{{0x60,0xDEB8},{0x61,0xDEB8},{0x62,0xDEB8},{0x63,0xDEB8}},0x04,0x00},
+ {0x00,0x30,{{0x61,0xDEB8},{0x62,0xDEB8},{0x63,0xDEB8},{0x60,0xDEB8}},0x05,0x00},
+ }
+};
+
+LEGACY_BIOS_PLATFORM_INSTANCE mPrivateData;
+EFI_HANDLE mImageHandle = NULL;
+
+/**
+ Return the handles and assorted information for the specified PCI Class code
+
+ @param[in] PciClasses Array of PCI_CLASS_RECORD to find terminated with ClassCode 0xff
+ @param[in,out] DeviceTable Table to place handles etc in.
+ @param[in,out] DeviceIndex Number of devices found
+ @param[in] DeviceFlags FALSE if a valid legacy ROM is required, TRUE otherwise.
+
+ @retval EFI_SUCCESS One or more devices found
+ @retval EFI_NOT_FOUND No device found
+
+**/
+EFI_STATUS
+FindAllDeviceTypes (
+ IN PCI_CLASS_RECORD *PciClasses,
+ IN OUT DEVICE_STRUCTURE *DeviceTable,
+ IN OUT UINT16 *DeviceIndex,
+ IN BOOLEAN DeviceFlags
+ )
+{
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ UINTN StartIndex;
+ PCI_TYPE00 PciConfigHeader;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ UINTN Flags;
+ EFI_STATUS Status;
+ UINTN Index2;
+
+ //
+ // Get legacy BIOS protocol as it is required to deal with Option ROMs.
+ //
+ StartIndex = *DeviceIndex;
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID**)&LegacyBios
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Get all PCI handles and check them to generate a list of matching devices.
+ //
+ gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ for (Index = 0; Index < HandleCount; Index++) {
+ gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID**)&PciIo
+ );
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (PciConfigHeader) / sizeof (UINT32),
+ &PciConfigHeader
+ );
+ for (Index2 = 0; PciClasses[Index2].Class != 0xff; Index2++) {
+ if ((PciConfigHeader.Hdr.ClassCode[2] == PciClasses[Index2].Class) &&
+ (PciConfigHeader.Hdr.ClassCode[1] == PciClasses[Index2].SubClass)) {
+ LegacyBios->CheckPciRom (
+ LegacyBios,
+ HandleBuffer[Index],
+ NULL,
+ NULL,
+ &Flags
+ );
+
+ //
+ // Verify that results of OPROM check match request.
+ // The two valid requests are:
+ // DeviceFlags = 0 require a valid legacy ROM
+ // DeviceFlags = 1 require either no ROM or a valid legacy ROM
+ //
+ if (
+ ((DeviceFlags != 0) && (Flags == NO_ROM)) ||
+ ((Flags & (ROM_FOUND | VALID_LEGACY_ROM)) == (ROM_FOUND | VALID_LEGACY_ROM))
+ ) {
+ DeviceTable->Handle = HandleBuffer[Index];
+ DeviceTable->Vid = PciConfigHeader.Hdr.VendorId;
+ DeviceTable->Did = PciConfigHeader.Hdr.DeviceId;
+ DeviceTable->SvId = PciConfigHeader.Device.SubsystemVendorID;
+ DeviceTable->SysId = PciConfigHeader.Device.SubsystemID;
+ ++ *DeviceIndex;
+ DeviceTable++;
+ }
+ }
+ }
+ }
+
+ //
+ // Free any allocated buffers
+ //
+ gBS->FreePool (HandleBuffer);
+
+ if (*DeviceIndex != StartIndex) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+}
+
+/**
+ Load and initialize the Legacy BIOS SMM handler.
+
+ @param This The protocol instance pointer.
+ @param EfiToLegacy16BootTable A pointer to Legacy16 boot table.
+
+ @retval EFI_SUCCESS SMM code loaded.
+ @retval EFI_DEVICE_ERROR SMM code failed to load
+
+**/
+EFI_STATUS
+EFIAPI
+SmmInit (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ IN VOID *EfiToLegacy16BootTable
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Finds the device path that should be used as the primary display adapter.
+
+ @param VgaHandle - The handle of the video device
+
+**/
+VOID
+GetSelectedVgaDeviceInfo (
+ OUT EFI_HANDLE *VgaHandle
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+ UINT8 MinBus;
+ UINT8 MaxBus;
+ UINTN Segment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+ UINTN SelectedAddress;
+ UINTN CurrentAddress;
+
+ //
+ // Initialize return to 'not found' state
+ //
+ *VgaHandle = NULL;
+
+ //
+ // Initialize variable states. Ths is important for selecting the VGA device
+ // if multiple devices exist behind a single bridge.
+ //
+ HandleCount = 0;
+ HandleBuffer = NULL;
+ SelectedAddress = PCI_LIB_ADDRESS(0xff, 0x1f, 0x7, 0);
+
+ //
+ // The bus range to search for a VGA device in.
+ //
+ MinBus = MaxBus = 0;
+
+ //
+ // Start to check all the pci io to find all possible VGA device
+ //
+ HandleCount = 0;
+ HandleBuffer = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID**)&PciIo);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Detemine if this is in the correct bus range.
+ //
+ Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+ if (EFI_ERROR(Status) || (Bus < MinBus || Bus > MaxBus)) {
+ continue;
+ }
+
+ //
+ // Read device information.
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Make sure the device is a VGA device.
+ //
+ if (!IS_PCI_VGA (&Pci)) {
+ continue;
+ }
+ DEBUG ((EFI_D_INFO,
+ "PCI VGA: 0x%04x:0x%04x\n",
+ Pci.Hdr.VendorId,
+ Pci.Hdr.DeviceId
+ ));
+
+ //
+ // Currently we use the lowest numbered bus/device/function if multiple
+ // devices are found in the target bus range.
+ //
+ CurrentAddress = PCI_LIB_ADDRESS(Bus, Device, Function, 0);
+ if (CurrentAddress < SelectedAddress) {
+ SelectedAddress = CurrentAddress;
+ *VgaHandle = HandleBuffer[Index];
+ }
+ }
+ }
+
+ FreePool (HandleBuffer);
+}
+
+
+/**
+ Returns a buffer of handles for the requested subfunction.
+
+ @param This The protocol instance pointer.
+ @param Mode Specifies what handle to return. See EFI_GET_PLATFORM_HANDLE_MODE enum.
+ @param Type Mode specific. See EFI_GET_PLATFORM_HANDLE_MODE enum.
+ @param HandleBuffer Mode specific. See EFI_GET_PLATFORM_HANDLE_MODE enum.
+ @param HandleCount Mode specific. See EFI_GET_PLATFORM_HANDLE_MODE enum.
+ @param AdditionalData Mode specific. See EFI_GET_PLATFORM_HANDLE_MODE enum.
+
+ @retval EFI_SUCCESS Handle is valid.
+ @retval EFI_UNSUPPORTED Mode is not supported on the platform.
+ @retval EFI_NOT_FOUND Handle is not known.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformHandle (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ IN EFI_GET_PLATFORM_HANDLE_MODE Mode,
+ IN UINT16 Type,
+ OUT EFI_HANDLE **HandleBuffer,
+ OUT UINTN *HandleCount,
+ OUT VOID **AdditionalData OPTIONAL
+ )
+{
+ DEVICE_STRUCTURE LocalDevice[0x40];
+ UINT32 LocalIndex;
+ UINT32 Index;
+ DEVICE_STRUCTURE TempDevice;
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINTN Segment;
+ UINTN Bus;
+ UINTN Device;
+ UINTN Function;
+ HDD_INFO *HddInfo;
+ PCI_TYPE00 PciConfigHeader;
+ UINT32 HddIndex;
+ EFI_HANDLE IdeHandle;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ PCI_CLASS_RECORD ClassLists[10];
+ UINTN PriorityIndex;
+
+ static BOOLEAN bConnected = FALSE;
+
+ LocalIndex = 0x00;
+ HddInfo = NULL;
+ HddIndex = 0;
+
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID**)&LegacyBios
+ );
+
+ //
+ // Process mode specific operations
+ //
+ switch (Mode) {
+ case EfiGetPlatformVgaHandle:
+ //
+ // Get the handle for the currently selected VGA device.
+ //
+ GetSelectedVgaDeviceInfo (&mVgaHandles[0]);
+ *HandleBuffer = &mVgaHandles[0];
+ *HandleCount = (mVgaHandles[0] != NULL) ? 1 : 0;
+ return EFI_SUCCESS;
+ case EfiGetPlatformIdeHandle:
+ IdeHandle = NULL;
+ if (AdditionalData != NULL) {
+ HddInfo = (HDD_INFO *) *AdditionalData;
+ }
+
+ //
+ // Locate all found block io devices
+ //
+ ClassLists[0].Class = PCI_CLASS_MASS_STORAGE;
+ ClassLists[0].SubClass = PCI_CLASS_MASS_STORAGE_SCSI;
+ ClassLists[1].Class = PCI_CLASS_MASS_STORAGE;
+ ClassLists[1].SubClass = PCI_CLASS_MASS_STORAGE_IDE;
+ ClassLists[2].Class = PCI_CLASS_MASS_STORAGE;
+ ClassLists[2].SubClass = PCI_CLASS_MASS_STORAGE_RAID;
+ ClassLists[3].Class = PCI_CLASS_MASS_STORAGE;
+ ClassLists[3].SubClass = PCI_CLASS_MASS_STORAGE_SATADPA;
+ ClassLists[4].Class = 0xff;
+ FindAllDeviceTypes (ClassLists, LocalDevice, (UINT16 *) &LocalIndex, TRUE);
+ if (LocalIndex == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Make sure all IDE controllers are connected. This is necessary
+ // in NO_CONFIG_CHANGE boot path to ensure IDE controller is correctly
+ // initialized and all IDE drives are enumerated
+ //
+ if (!bConnected) {
+ for (Index = 0; Index < LocalIndex; Index++) {
+ gBS->ConnectController (LocalDevice[Index].Handle, NULL, NULL, TRUE);
+ }
+ }
+
+ //
+ // Locate onboard controllers.
+ //
+ for (Index = 0; Index < LocalIndex; Index++) {
+ if (LocalDevice[Index].Vid == V_INTEL_VENDOR_ID) {
+ if (LocalDevice[Index].Did == V_PIIX4_IDE_DEVICE_ID) {
+ IdeHandle = LocalDevice[Index].Handle;
+ }
+ }
+ }
+
+ //
+ // Set the IDE contorller as primary devices.
+ //
+ PriorityIndex = 0;
+ for (Index = 0; Index < LocalIndex; Index++) {
+ if (LocalDevice[Index].Handle == IdeHandle && PriorityIndex == 0) {
+ TempDevice = LocalDevice[PriorityIndex];
+ LocalDevice[PriorityIndex] = LocalDevice[Index];
+ LocalDevice[Index] = TempDevice;
+ PriorityIndex++;
+ break;
+ }
+ }
+
+ //
+ // Copy over handles and update return values.
+ //
+ for (Index = 0; Index < LocalIndex; Index++) {
+ mDiskHandles[Index] = LocalDevice[Index].Handle;
+ }
+ *HandleBuffer = &mDiskHandles[0];
+ *HandleCount = LocalIndex;
+
+ //
+ // We have connected all IDE controllers once. No more needed
+ //
+ bConnected = TRUE;
+
+ //
+ // Log all onboard controllers.
+ //
+ for (Index = 0; (Index < LocalIndex) && (AdditionalData != NULL); Index++) {
+ if ((LocalDevice[Index].Handle != NULL) &&
+ (LocalDevice[Index].Handle == IdeHandle)) {
+ Status = gBS->HandleProtocol (
+ LocalDevice[Index].Handle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo
+ );
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (PciConfigHeader) / sizeof (UINT32),
+ &PciConfigHeader
+ );
+ if (!EFI_ERROR (Status)) {
+ PciIo->GetLocation (
+ PciIo,
+ &Segment,
+ &Bus,
+ &Device,
+ &Function
+ );
+
+ //
+ // Be sure to only fill out correct information based on platform
+ // configureation.
+ //
+ HddInfo[HddIndex].Status |= HDD_PRIMARY;
+ HddInfo[HddIndex].Bus = (UINT32)Bus;
+ HddInfo[HddIndex].Device = (UINT32)Device;
+ HddInfo[HddIndex].Function = (UINT32)Function;
+ HddInfo[HddIndex + 1].Status |= HDD_SECONDARY;
+ HddInfo[HddIndex + 1].Bus = (UINT32)Bus;
+ HddInfo[HddIndex + 1].Device = (UINT32)Device;
+ HddInfo[HddIndex + 1].Function = (UINT32)Function;
+
+ //
+ // Primary controller data
+ //
+ if ((PciConfigHeader.Hdr.ClassCode[0] & 0x01) != 0) {
+ HddInfo[HddIndex].CommandBaseAddress =
+ (UINT16)(PciConfigHeader.Device.Bar[0] & 0xfffc);
+ HddInfo[HddIndex].ControlBaseAddress =
+ (UINT16)((PciConfigHeader.Device.Bar[1] & 0xfffc)+2);
+ HddInfo[HddIndex].BusMasterAddress =
+ (UINT16)(PciConfigHeader.Device.Bar[4] & 0xfffc);
+ HddInfo[HddIndex].HddIrq = PciConfigHeader.Device.InterruptLine;
+ } else {
+ HddInfo[HddIndex].HddIrq = 14;
+ HddInfo[HddIndex].CommandBaseAddress = 0x1f0;
+ HddInfo[HddIndex].ControlBaseAddress = 0x3f6;
+ HddInfo[HddIndex].BusMasterAddress = 0;
+ }
+ HddIndex++;
+
+ //
+ // Secondary controller data
+ //
+ if ((PciConfigHeader.Hdr.ClassCode[0] & 0x04) != 0) {
+ HddInfo[HddIndex].CommandBaseAddress =
+ (UINT16)(PciConfigHeader.Device.Bar[2] & 0xfffc);
+ HddInfo[HddIndex].ControlBaseAddress =
+ (UINT16)((PciConfigHeader.Device.Bar[3] & 0xfffc)+2);
+ HddInfo[HddIndex].BusMasterAddress =
+ (UINT16)(HddInfo[HddIndex].BusMasterAddress + 8);
+ HddInfo[HddIndex].HddIrq = PciConfigHeader.Device.InterruptLine;
+ } else {
+ HddInfo[HddIndex].HddIrq = 15;
+ HddInfo[HddIndex].CommandBaseAddress = 0x170;
+ HddInfo[HddIndex].ControlBaseAddress = 0x376;
+ HddInfo[HddIndex].BusMasterAddress = 0;
+ }
+ HddIndex++;
+ }
+ }
+ }
+ return EFI_SUCCESS;
+ case EfiGetPlatformIsaBusHandle:
+ ClassLists[0].Class = (UINT8) PCI_CLASS_BRIDGE;
+ ClassLists[0].SubClass = (UINT8) PCI_CLASS_BRIDGE_ISA_PDECODE;
+ ClassLists[1].Class = (UINT8) PCI_CLASS_BRIDGE;
+ ClassLists[1].SubClass = (UINT8) PCI_CLASS_BRIDGE_ISA;
+ ClassLists[2].Class = 0xff;
+
+ //
+ // Locate all found block io devices
+ //
+ FindAllDeviceTypes (ClassLists, LocalDevice, (UINT16 *) (&LocalIndex), TRUE);
+ if (LocalIndex == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Find our ISA bridge.
+ //
+ for (Index = 0; Index < LocalIndex; Index++) {
+ if (LocalDevice[Index].Vid == V_INTEL_VENDOR_ID) {
+ TempDevice = LocalDevice[0];
+ LocalDevice[0] = LocalDevice[Index];
+ LocalDevice[Index] = TempDevice;
+ }
+ }
+
+ //
+ // Perform copy and update return values.
+ //
+ for (Index = 0; Index < LocalIndex; Index++) {
+ mIsaHandles[Index] = LocalDevice[Index].Handle;
+ }
+ *HandleBuffer = &mIsaHandles[0];
+ *HandleCount = LocalIndex;
+ return EFI_SUCCESS;
+ case EfiGetPlatformUsbHandle:
+ default:
+ return EFI_UNSUPPORTED;
+ };
+}
+
+/**
+ Allows platform to perform any required action after a LegacyBios operation.
+ Invokes the specific sub function specified by Mode.
+
+ @param This The protocol instance pointer.
+ @param Mode Specifies what handle to return. See EFI_GET_PLATFORM_HOOK_MODE enum.
+ @param Type Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.
+ @param DeviceHandle Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.
+ @param ShadowAddress Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.
+ @param Compatibility16Table Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.
+ @param AdditionalData Mode specific. See EFI_GET_PLATFORM_HOOK_MODE enum.
+
+ @retval EFI_SUCCESS The operation performed successfully. Mode specific.
+ @retval EFI_UNSUPPORTED Mode is not supported on the platform.
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformHooks (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ IN EFI_GET_PLATFORM_HOOK_MODE Mode,
+ IN UINT16 Type,
+ OUT EFI_HANDLE DeviceHandle, OPTIONAL
+ IN OUT UINTN *Shadowaddress, OPTIONAL
+ IN EFI_COMPATIBILITY16_TABLE *Compatibility16Table, OPTIONAL
+ OUT VOID **AdditionalData OPTIONAL
+ )
+{
+ EFI_IA32_REGISTER_SET Regs;
+ EFI_LEGACY_BIOS_PROTOCOL *LegacyBios;
+ EFI_STATUS Status;
+
+ switch (Mode) {
+ case EfiPlatformHookPrepareToScanRom:
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyBiosProtocolGuid,
+ NULL,
+ (VOID**)&LegacyBios
+ );
+
+ //
+ // Set the 80x25 Text VGA Mode
+ //
+ Regs.H.AH = 0x00;
+ Regs.H.AL = 0x03;
+ Status = LegacyBios->Int86 (LegacyBios, 0x10, &Regs);
+ return Status;
+ case EfiPlatformHookShadowServiceRoms:
+ return EFI_SUCCESS;
+ case EfiPlatformHookAfterRomInit:
+ default:
+ return EFI_UNSUPPORTED;
+ };
+}
+
+/**
+ Returns information associated with PCI IRQ routing.
+ This function returns the following information associated with PCI IRQ routing:
+ * An IRQ routing table and number of entries in the table.
+ * The $PIR table and its size.
+ * A list of PCI IRQs and the priority order to assign them.
+
+ @param This The protocol instance pointer.
+ @param RoutingTable The pointer to PCI IRQ Routing table.
+ This location is the $PIR table minus the header.
+ @param RoutingTableEntries The number of entries in table.
+ @param LocalPirqTable $PIR table.
+ @param PirqTableSize $PIR table size.
+ @param LocalIrqPriorityTable A list of interrupts in priority order to assign.
+ @param IrqPriorityTableEntries The number of entries in the priority table.
+
+ @retval EFI_SUCCESS Data was successfully returned.
+
+**/
+EFI_STATUS
+EFIAPI
+GetRoutingTable (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ OUT VOID **RoutingTable,
+ OUT UINTN *RoutingTableEntries,
+ OUT VOID **LocalPirqTable, OPTIONAL
+ OUT UINTN *PirqTableSize, OPTIONAL
+ OUT VOID **LocalIrqPriorityTable, OPTIONAL
+ OUT UINTN *IrqPriorityTableEntries OPTIONAL
+ )
+{
+ UINT16 PTableSize;
+ UINT32 Index;
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ UINT8 Checksum;
+ UINT8 *Ptr;
+ EFI_STATUS Status;
+ EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt;
+
+ Checksum = 0;
+
+ if (LocalPirqTable != NULL) {
+ PTableSize = sizeof (EFI_LEGACY_PIRQ_TABLE_HEADER) +
+ sizeof (EFI_LEGACY_IRQ_ROUTING_ENTRY) * MAX_IRQ_ROUTING_ENTRIES;
+
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyInterruptProtocolGuid,
+ NULL,
+ (VOID**)&LegacyInterrupt
+ );
+ ASSERT_EFI_ERROR (Status);
+ LegacyInterrupt->GetLocation (
+ LegacyInterrupt,
+ &Bus,
+ &Device,
+ &Function
+ );
+
+ //
+ // Update fields in $PIR table header
+ //
+ PirqTableHead.PirqTable.TableSize = PTableSize;
+ PirqTableHead.PirqTable.Bus = Bus;
+ PirqTableHead.PirqTable.DevFun = (UINT8) ((Device << 3) + Function);
+ Ptr = (UINT8 *) (&PirqTableHead);
+
+ //
+ // Calculate checksum.
+ //
+ for (Index = 0; Index < PTableSize; Index++) {
+ Checksum = (UINT8) (Checksum + (UINT8) *Ptr);
+ Ptr += 1;
+ }
+ Checksum = (UINT8) (0x00 - Checksum);
+ PirqTableHead.PirqTable.Checksum = Checksum;
+
+ //
+ // Update return values.
+ //
+ *LocalPirqTable = (VOID *) (&PirqTableHead);
+ *PirqTableSize = PTableSize;
+ }
+
+ //
+ // More items to return.
+ //
+ *RoutingTable = PirqTableHead.IrqRoutingEntry;
+ *RoutingTableEntries = MAX_IRQ_ROUTING_ENTRIES;
+ if (LocalIrqPriorityTable != NULL) {
+ *LocalIrqPriorityTable = IrqPriorityTable;
+ *IrqPriorityTableEntries = MAX_IRQ_PRIORITY_ENTRIES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Finds the binary data or other platform information.
+
+ @param This The protocol instance pointer.
+ @param Mode Specifies what data to return. See See EFI_GET_PLATFORM_INFO_MODE enum.
+ @param Table Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.
+ @param TableSize Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.
+ @param Location Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.
+ @param Alignment Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.
+ @param LegacySegment Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.
+ @param LegacyOffset Mode specific. See EFI_GET_PLATFORM_INFO_MODE enum.
+
+ @retval EFI_SUCCESS Data returned successfully.
+ @retval EFI_UNSUPPORTED Mode is not supported on the platform.
+ @retval EFI_NOT_FOUND Binary image or table not found.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformInfo (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ IN EFI_GET_PLATFORM_INFO_MODE Mode,
+ OUT VOID **Table,
+ OUT UINTN *TableSize,
+ OUT UINTN *Location,
+ OUT UINTN *Alignment,
+ IN UINT16 LegacySegment,
+ IN UINT16 LegacyOffset
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+#ifndef NOT_BHYVE
+ extern EFI_PHYSICAL_ADDRESS *mMpsTable;
+ extern UINT32 mMpsTableLength;
+ extern VOID FixupMpsTable(UINT32 TablePtr);
+#endif
+
+ switch (Mode) {
+ case EfiGetPlatformBinarySystemRom:
+ //
+ // Loop through table of System rom descriptions
+ //
+ for (Index = 0; mSystemRomTable[Index].Valid != 0; Index++) {
+ Status = GetSectionFromFv (
+ &mSystemRomTable[Index].FileName,
+ EFI_SECTION_RAW,
+ 0,
+ Table,
+ (UINTN *) TableSize
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+#ifdef NOT_BHYVE
+ case EfiGetPlatformBinaryOem16Data:
+ case EfiGetPlatformBinaryMpTable:
+#else
+ case EfiGetPlatformBinaryOem16Data:
+ return EFI_UNSUPPORTED;
+ case EfiGetPlatformBinaryMpTable:
+ if (LegacySegment != 0 && LegacyOffset != 0) {
+ FixupMpsTable(LegacySegment * 16 + LegacyOffset);
+ } else {
+ *Table = mMpsTable;
+ *TableSize = mMpsTableLength;
+ }
+ return EFI_SUCCESS;
+#endif
+ case EfiGetPlatformBinaryOemIntData:
+ case EfiGetPlatformBinaryOem32Data:
+ case EfiGetPlatformBinaryTpmBinary:
+ case EfiGetPlatformPciExpressBase:
+ default:
+ return EFI_UNSUPPORTED;
+ };
+}
+
+/**
+ Translates the given PIRQ accounting for bridge.
+ This function translates the given PIRQ back through all buses, if required,
+ and returns the true PIRQ and associated IRQ.
+
+ @param This The protocol instance pointer.
+ @param PciBus The PCI bus number for this device.
+ @param PciDevice The PCI device number for this device.
+ @param PciFunction The PCI function number for this device.
+ @param Pirq Input is PIRQ reported by device, and output is true PIRQ.
+ @param PciIrq The IRQ already assigned to the PIRQ, or the IRQ to be
+ assigned to the PIRQ.
+
+ @retval EFI_SUCCESS The PIRQ was translated.
+
+**/
+EFI_STATUS
+EFIAPI
+TranslatePirq (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ IN UINTN PciBus,
+ IN UINTN PciDevice,
+ IN UINTN PciFunction,
+ IN OUT UINT8 *Pirq,
+ OUT UINT8 *PciIrq
+ )
+{
+ EFI_LEGACY_INTERRUPT_PROTOCOL *LegacyInterrupt;
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN Index1;
+ UINT8 LocalPirq;
+ UINT8 PirqData;
+ UINT8 MatchData;
+
+ Status = gBS->LocateProtocol (
+ &gEfiLegacyInterruptProtocolGuid,
+ NULL,
+ (VOID**)&LegacyInterrupt
+ );
+ ASSERT_EFI_ERROR (Status);
+ LocalPirq = (UINT8) (*Pirq);
+
+ for (Index = 0; Index < MAX_IRQ_ROUTING_ENTRIES; Index++) {
+ if ((PirqTableHead.IrqRoutingEntry[Index].Bus == PciBus) &&
+ (PirqTableHead.IrqRoutingEntry[Index].Device == PciDevice)) {
+ LocalPirq = (UINT8) (PirqTableHead.IrqRoutingEntry[Index].PirqEntry[LocalPirq].Pirq & 0x0f);
+ if (LocalPirq > 4) {
+ LocalPirq -= 4;
+ }
+
+ LegacyInterrupt->ReadPirq (LegacyInterrupt, LocalPirq, &PirqData);
+ MatchData = PCI_UNUSED;
+ while (PirqData == 0) {
+ for (Index1 = 0; Index1 < MAX_IRQ_PRIORITY_ENTRIES; Index1++) {
+ if ((IrqPriorityTable[Index1].Used == MatchData) &&
+ (IrqPriorityTable[Index1].Irq != 0)) {
+ PirqData = IrqPriorityTable[Index1].Irq;
+ IrqPriorityTable[Index1].Used = 0xff;
+ LegacyInterrupt->WritePirq (
+ LegacyInterrupt,
+ LocalPirq,
+ PirqData
+ );
+ break;
+ }
+ }
+
+ if (PirqData == 0) {
+
+ //
+ // No unused interrpts, so start reusing them.
+ //
+ MatchData = (UINT8) (~MatchData);
+ }
+ }
+
+ *PciIrq = PirqData;
+ *Pirq = LocalPirq;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Attempt to legacy boot the BootOption. If the EFI contexted has been
+ compromised this function will not return.
+
+ @param This The protocol instance pointer.
+ @param BbsDevicePath The EFI Device Path from BootXXXX variable.
+ @param BbsTable The Internal BBS table.
+ @param LoadOptionSize The size of LoadOption in size.
+ @param LoadOption The LoadOption from BootXXXX variable
+ @param EfiToLegacy16BootTable A pointer to BootTable structure
+
+ @retval EFI_SUCCESS Ready to boot.
+
+**/
+EFI_STATUS
+EFIAPI
+PrepareToBoot (
+ IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This,
+ IN BBS_BBS_DEVICE_PATH *BbsDevicePath,
+ IN VOID *BbsTable,
+ IN UINT32 LoadOptionsSize,
+ IN VOID *LoadOptions,
+ IN VOID *EfiToLegacy16BootTable
+ )
+{
+ BBS_TABLE *LocalBbsTable;
+ EFI_TO_COMPATIBILITY16_BOOT_TABLE *Legacy16BootTable;
+ DEVICE_PRODUCER_DATA_HEADER *SioPtr;
+ UINT16 DevicePathType;
+ UINT16 Index;
+ UINT16 Priority;
+
+ //
+ // Initialize values
+ //
+ Priority = 0;
+ Legacy16BootTable = (EFI_TO_COMPATIBILITY16_BOOT_TABLE*) EfiToLegacy16BootTable;
+
+ //
+ // Set how Gate A20 is gated by hardware
+ //
+ SioPtr = &Legacy16BootTable->SioData;
+ SioPtr->Flags.A20Kybd = 1;
+ SioPtr->Flags.A20Port90 = 1;
+ SioPtr->MousePresent = 1;
+
+ LocalBbsTable = BbsTable;
+
+ //
+ // There are 2 cases that must be covered.
+ // Case 1: Booting to a legacy OS - BbsDevicePath is non-NULL.
+ // Case 2: Booting to an EFI aware OS - BbsDevicePath is NULL.
+ // We need to perform the PrepareToBoot function to assign
+ // drive numbers to HDD devices to allow the shell or EFI
+ // to access them.
+ //
+ if (BbsDevicePath != NULL) {
+ DevicePathType = BbsDevicePath->DeviceType;
+ } else {
+ DevicePathType = BBS_HARDDISK;
+ }
+
+ //
+ // Skip the boot devices where priority is set by BDS and set the next one
+ //
+ for (Index = 0; Index < Legacy16BootTable->NumberBbsEntries; Index++) {
+ if ((LocalBbsTable[Index].BootPriority != BBS_UNPRIORITIZED_ENTRY) &&
+ (LocalBbsTable[Index].BootPriority != BBS_IGNORE_ENTRY) &&
+ (LocalBbsTable[Index].BootPriority != BBS_LOWEST_PRIORITY) &&
+ (Priority <= LocalBbsTable[Index].BootPriority)) {
+ Priority = (UINT16) (LocalBbsTable[Index].BootPriority + 1);
+ }
+ }
+
+ switch (DevicePathType) {
+ case BBS_FLOPPY:
+ case BBS_HARDDISK:
+ case BBS_CDROM:
+ case BBS_EMBED_NETWORK:
+ for (Index = 0; Index < Legacy16BootTable->NumberBbsEntries; Index++) {
+ if ((LocalBbsTable[Index].BootPriority == BBS_UNPRIORITIZED_ENTRY) &&
+ (LocalBbsTable[Index].DeviceType == DevicePathType)) {
+ LocalBbsTable[Index].BootPriority = Priority;
+ ++Priority;
+ }
+ }
+ break;
+ case BBS_BEV_DEVICE:
+ for (Index = 0; Index < Legacy16BootTable->NumberBbsEntries; Index++) {
+ if ((LocalBbsTable[Index].BootPriority == BBS_UNPRIORITIZED_ENTRY) &&
+ (LocalBbsTable[Index].Class == 01) &&
+ (LocalBbsTable[Index].SubClass == 01)) {
+ LocalBbsTable[Index].BootPriority = Priority;
+ ++Priority;
+ }
+ }
+ break;
+ case BBS_USB:
+ case BBS_PCMCIA:
+ case BBS_UNKNOWN:
+ default:
+ break;
+ };
+
+ //
+ // Set priority for rest of devices
+ //
+ for (Index = 0; Index < Legacy16BootTable->NumberBbsEntries; Index++) {
+ if (LocalBbsTable[Index].BootPriority == BBS_UNPRIORITIZED_ENTRY) {
+ LocalBbsTable[Index].BootPriority = Priority;
+ ++Priority;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initialize Legacy Platform support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyBiosPlatformInstall (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ LEGACY_BIOS_PLATFORM_INSTANCE *Private;
+
+ mImageHandle = gImageHandle;
+ Private = &mPrivateData;
+
+ //
+ // Grab a copy of all the protocols we depend on.
+ //
+ Private->Signature = LEGACY_BIOS_PLATFORM_INSTANCE_SIGNATURE;
+ Private->LegacyBiosPlatform.GetPlatformInfo = GetPlatformInfo;
+ Private->LegacyBiosPlatform.GetPlatformHandle = GetPlatformHandle;
+ Private->LegacyBiosPlatform.SmmInit = SmmInit;
+ Private->LegacyBiosPlatform.PlatformHooks = PlatformHooks;
+ Private->LegacyBiosPlatform.GetRoutingTable = GetRoutingTable;
+ Private->LegacyBiosPlatform.TranslatePirq = TranslatePirq;
+ Private->LegacyBiosPlatform.PrepareToBoot = PrepareToBoot;
+ Private->ImageHandle = gImageHandle;
+
+ //
+ // Make a new handle and install the protocol
+ //
+ Private->Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Private->Handle,
+ &gEfiLegacyBiosPlatformProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Private->LegacyBiosPlatform
+ );
+ return Status;
+}
+
diff --git BhyvePkg/Csm/CsmSupportLib/LegacyPlatform.h BhyvePkg/Csm/CsmSupportLib/LegacyPlatform.h
new file mode 100644
index 0000000..ad572e3
--- /dev/null
+++ BhyvePkg/Csm/CsmSupportLib/LegacyPlatform.h
@@ -0,0 +1,104 @@
+/** @file
+ Legacy BIOS Platform support
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef LEGACY_BIOS_PLATFORM_H_
+#define LEGACY_BIOS_PLATFORM_H_
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+//
+// PIRQ information constants.
+//
+#define MAX_IRQ_ROUTING_ENTRIES 6
+#define MAX_IRQ_PRIORITY_ENTRIES 7
+
+#define V_INTEL_VENDOR_ID 0x8086
+#define V_PIIX4_IDE_DEVICE_ID 0x7010
+
+//
+// Type declarations
+//
+typedef struct {
+ UINT8 SetupValue;
+ UINT16 DeviceType;
+ UINT8 Class;
+ UINT8 SubClass;
+} EFI_SETUP_BBS_MAP;
+
+typedef struct {
+ UINT8 Class;
+ UINT8 SubClass;
+} PCI_CLASS_RECORD;
+
+typedef struct {
+ EFI_LEGACY_PIRQ_TABLE_HEADER PirqTable;
+ EFI_LEGACY_IRQ_ROUTING_ENTRY IrqRoutingEntry[MAX_IRQ_ROUTING_ENTRIES];
+} EFI_LEGACY_PIRQ_TABLE;
+
+typedef struct {
+ EFI_HANDLE Handle;
+ UINT16 Vid;
+ UINT16 Did;
+ UINT16 SvId;
+ UINT16 SysId;
+} DEVICE_STRUCTURE;
+
+typedef struct {
+ EFI_GUID FileName;
+ UINTN Valid;
+} SYSTEM_ROM_TABLE;
+
+typedef struct {
+ UINT32 Signature;
+ EFI_HANDLE Handle;
+ EFI_LEGACY_BIOS_PLATFORM_PROTOCOL LegacyBiosPlatform;
+ EFI_HANDLE ImageHandle;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+} LEGACY_BIOS_PLATFORM_INSTANCE;
+
+#define LEGACY_BIOS_PLATFORM_INSTANCE_SIGNATURE SIGNATURE_32('P','B','I','O')
+
+#define LEGACY_BIOS_PLATFORM_INSTANCE_FROM_THIS(this) \
+ CR (this, \
+ LEGACY_BIOS_PLATFORM_INSTANCE, \
+ LegacyBiosPlatform, \
+ LEGACY_BIOS_PLATFORM_INSTANCE_SIGNATURE \
+ )
+
+#endif
+
diff --git BhyvePkg/Csm/CsmSupportLib/LegacyRegion.c BhyvePkg/Csm/CsmSupportLib/LegacyRegion.c
new file mode 100644
index 0000000..3e046ef
--- /dev/null
+++ BhyvePkg/Csm/CsmSupportLib/LegacyRegion.c
@@ -0,0 +1,466 @@
+/** @file
+ Legacy Region Support
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "LegacyRegion.h"
+
+//
+// 440 PAM map.
+//
+// PAM Range Offset Bits Operation
+// =============== ====== ==== ===============================================================
+// 0xC0000-0xC3FFF 0x5a 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xC4000-0xC7FFF 0x5a 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xC8000-0xCBFFF 0x5b 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xCC000-0xCFFFF 0x5b 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xD0000-0xD3FFF 0x5c 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xD4000-0xD7FFF 0x5c 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xD8000-0xDBFFF 0x5d 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xDC000-0xDFFFF 0x5d 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xE0000-0xE3FFF 0x5e 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xE4000-0xE7FFF 0x5e 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xE8000-0xEBFFF 0x5f 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xEC000-0xEFFFF 0x5f 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+// 0xF0000-0xFFFFF 0x59 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal
+//
+STATIC LEGACY_MEMORY_SECTION_INFO mSectionArray[] = {
+ {0xC0000, SIZE_16KB, FALSE, FALSE},
+ {0xC4000, SIZE_16KB, FALSE, FALSE},
+ {0xC8000, SIZE_16KB, FALSE, FALSE},
+ {0xCC000, SIZE_16KB, FALSE, FALSE},
+ {0xD0000, SIZE_16KB, FALSE, FALSE},
+ {0xD4000, SIZE_16KB, FALSE, FALSE},
+ {0xD8000, SIZE_16KB, FALSE, FALSE},
+ {0xDC000, SIZE_16KB, FALSE, FALSE},
+ {0xE0000, SIZE_16KB, FALSE, FALSE},
+ {0xE4000, SIZE_16KB, FALSE, FALSE},
+ {0xE8000, SIZE_16KB, FALSE, FALSE},
+ {0xEC000, SIZE_16KB, FALSE, FALSE},
+ {0xF0000, SIZE_64KB, FALSE, FALSE}
+};
+
+STATIC PAM_REGISTER_VALUE mRegisterValues[] = {
+ {REG_PAM1_OFFSET, 0x01, 0x02},
+ {REG_PAM1_OFFSET, 0x10, 0x20},
+ {REG_PAM2_OFFSET, 0x01, 0x02},
+ {REG_PAM2_OFFSET, 0x10, 0x20},
+ {REG_PAM3_OFFSET, 0x01, 0x02},
+ {REG_PAM3_OFFSET, 0x10, 0x20},
+ {REG_PAM4_OFFSET, 0x01, 0x02},
+ {REG_PAM4_OFFSET, 0x10, 0x20},
+ {REG_PAM5_OFFSET, 0x01, 0x02},
+ {REG_PAM5_OFFSET, 0x10, 0x20},
+ {REG_PAM6_OFFSET, 0x01, 0x02},
+ {REG_PAM6_OFFSET, 0x10, 0x20},
+ {REG_PAM0_OFFSET, 0x10, 0x20}
+};
+
+//
+// Handle used to install the Legacy Region Protocol
+//
+STATIC EFI_HANDLE mHandle = NULL;
+
+//
+// Instance of the Legacy Region Protocol to install into the handle database
+//
+STATIC EFI_LEGACY_REGION2_PROTOCOL mLegacyRegion2 = {
+ LegacyRegion2Decode,
+ LegacyRegion2Lock,
+ LegacyRegion2BootLock,
+ LegacyRegion2Unlock,
+ LegacyRegionGetInfo
+};
+
+STATIC
+EFI_STATUS
+LegacyRegionManipulationInternal (
+ IN UINT32 Start,
+ IN UINT32 Length,
+ IN BOOLEAN *ReadEnable,
+ IN BOOLEAN *WriteEnable,
+ OUT UINT32 *Granularity
+ )
+{
+ UINT32 EndAddress;
+ UINTN Index;
+ UINTN StartIndex;
+
+ //
+ // Validate input parameters.
+ //
+ if (Length == 0 || Granularity == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ EndAddress = Start + Length - 1;
+ if ((Start < PAM_BASE_ADDRESS) || EndAddress > PAM_LIMIT_ADDRESS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Loop to find the start PAM.
+ //
+ StartIndex = 0;
+ for (Index = 0; Index < (sizeof(mSectionArray) / sizeof (mSectionArray[0])); Index++) {
+ if ((Start >= mSectionArray[Index].Start) && (Start < (mSectionArray[Index].Start + mSectionArray[Index].Length))) {
+ StartIndex = Index;
+ break;
+ }
+ }
+ ASSERT (Index < (sizeof(mSectionArray) / sizeof (mSectionArray[0])));
+
+ //
+ // Program PAM until end PAM is encountered
+ //
+ for (Index = StartIndex; Index < (sizeof(mSectionArray) / sizeof (mSectionArray[0])); Index++) {
+ if (ReadEnable != NULL) {
+ if (*ReadEnable) {
+ PciOr8 (
+ PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset),
+ mRegisterValues[Index].ReadEnableData
+ );
+ } else {
+ PciAnd8 (
+ PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset),
+ (UINT8) (~mRegisterValues[Index].ReadEnableData)
+ );
+ }
+ }
+ if (WriteEnable != NULL) {
+ if (*WriteEnable) {
+ PciOr8 (
+ PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset),
+ mRegisterValues[Index].WriteEnableData
+ );
+ } else {
+ PciAnd8 (
+ PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset),
+ (UINT8) (~mRegisterValues[Index].WriteEnableData)
+ );
+ }
+ }
+
+ //
+ // If the end PAM is encountered, record its length as granularity and jump out.
+ //
+ if ((EndAddress >= mSectionArray[Index].Start) && (EndAddress < (mSectionArray[Index].Start + mSectionArray[Index].Length))) {
+ *Granularity = mSectionArray[Index].Length;
+ break;
+ }
+ }
+ ASSERT (Index < (sizeof(mSectionArray) / sizeof (mSectionArray[0])));
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+LegacyRegionGetInfoInternal (
+ OUT UINT32 *DescriptorCount,
+ OUT LEGACY_MEMORY_SECTION_INFO **Descriptor
+ )
+{
+ UINTN Index;
+ UINT8 PamValue;
+
+ //
+ // Check input parameters
+ //
+ if (DescriptorCount == NULL || Descriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Fill in current status of legacy region.
+ //
+ *DescriptorCount = sizeof(mSectionArray) / sizeof (mSectionArray[0]);
+ for (Index = 0; Index < *DescriptorCount; Index++) {
+ PamValue = PciRead8 (PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset));
+ mSectionArray[Index].ReadEnabled = FALSE;
+ if ((PamValue & mRegisterValues[Index].ReadEnableData) != 0) {
+ mSectionArray[Index].ReadEnabled = TRUE;
+ }
+ mSectionArray[Index].WriteEnabled = FALSE;
+ if ((PamValue & mRegisterValues[Index].WriteEnableData) != 0) {
+ mSectionArray[Index].WriteEnabled = TRUE;
+ }
+ }
+
+ *Descriptor = mSectionArray;
+ return EFI_SUCCESS;
+}
+
+/**
+ Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.
+
+ If the On parameter evaluates to TRUE, this function enables memory reads in the address range
+ Start to (Start + Length - 1).
+ If the On parameter evaluates to FALSE, this function disables memory reads in the address range
+ Start to (Start + Length - 1).
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose attributes
+ should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address
+ was not aligned to a region's starting address or if the length
+ was greater than the number of bytes in the first region.
+ @param On[in] Decode / Non-Decode flag.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Decode (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity,
+ IN BOOLEAN *On
+ )
+{
+ return LegacyRegionManipulationInternal (Start, Length, On, NULL, Granularity);
+}
+
+
+/**
+ Modify the hardware to disallow memory attribute changes in a region.
+
+ This function makes the attributes of a region read only. Once a region is boot-locked with this
+ function, the read and write attributes of that region cannot be changed until a power cycle has
+ reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+ @retval EFI_UNSUPPORTED The chipset does not support locking the configuration registers in
+ a way that will not affect memory regions outside the legacy memory
+ region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2BootLock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ )
+{
+ if ((Start < 0xC0000) || ((Start + Length - 1) > 0xFFFFF)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+
+/**
+ Modify the hardware to disallow memory writes in a region.
+
+ This function changes the attributes of a memory range to not allow writes.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Lock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ )
+{
+ BOOLEAN WriteEnable;
+
+ WriteEnable = FALSE;
+ return LegacyRegionManipulationInternal (Start, Length, NULL, &WriteEnable, Granularity);
+}
+
+
+/**
+ Modify the hardware to allow memory writes in a region.
+
+ This function changes the attributes of a memory range to allow writes.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Unlock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ )
+{
+ BOOLEAN WriteEnable;
+
+ WriteEnable = TRUE;
+ return LegacyRegionManipulationInternal (Start, Length, NULL, &WriteEnable, Granularity);
+}
+
+/**
+ Get region information for the attributes of the Legacy Region.
+
+ This function is used to discover the granularity of the attributes for the memory in the legacy
+ region. Each attribute may have a different granularity and the granularity may not be the same
+ for all memory ranges in the legacy region.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param DescriptorCount[out] The number of region descriptor entries returned in the Descriptor
+ buffer.
+ @param Descriptor[out] A pointer to a pointer used to return a buffer where the legacy
+ region information is deposited. This buffer will contain a list of
+ DescriptorCount number of region descriptors. This function will
+ provide the memory for the buffer.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegionGetInfo (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ OUT UINT32 *DescriptorCount,
+ OUT EFI_LEGACY_REGION_DESCRIPTOR **Descriptor
+ )
+{
+ LEGACY_MEMORY_SECTION_INFO *SectionInfo;
+ UINT32 SectionCount;
+ EFI_LEGACY_REGION_DESCRIPTOR *DescriptorArray;
+ UINTN Index;
+ UINTN DescriptorIndex;
+
+ //
+ // Get section numbers and information
+ //
+ LegacyRegionGetInfoInternal (&SectionCount, &SectionInfo);
+
+ //
+ // Each section has 3 descriptors, corresponding to readability, writeability, and lock status.
+ //
+ DescriptorArray = AllocatePool (sizeof (EFI_LEGACY_REGION_DESCRIPTOR) * SectionCount * 3);
+ if (DescriptorArray == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DescriptorIndex = 0;
+ for (Index = 0; Index < SectionCount; Index++) {
+ DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;
+ DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;
+ DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;
+ if (SectionInfo[Index].ReadEnabled) {
+ DescriptorArray[DescriptorIndex].Attribute = LegacyRegionDecoded;
+ } else {
+ DescriptorArray[DescriptorIndex].Attribute = LegacyRegionNotDecoded;
+ }
+ DescriptorIndex++;
+
+ //
+ // Create descriptor for writeability, according to lock status
+ //
+ DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;
+ DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;
+ DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;
+ if (SectionInfo[Index].WriteEnabled) {
+ DescriptorArray[DescriptorIndex].Attribute = LegacyRegionWriteEnabled;
+ } else {
+ DescriptorArray[DescriptorIndex].Attribute = LegacyRegionWriteDisabled;
+ }
+ DescriptorIndex++;
+
+ //
+ // Chipset does not support bootlock.
+ //
+ DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;
+ DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;
+ DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;
+ DescriptorArray[DescriptorIndex].Attribute = LegacyRegionNotLocked;
+ DescriptorIndex++;
+ }
+
+ *DescriptorCount = (UINT32) DescriptorIndex;
+ *Descriptor = DescriptorArray;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize Legacy Region support
+
+ @retval EFI_SUCCESS Successfully initialized
+
+**/
+EFI_STATUS
+LegacyRegionInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Install the Legacy Region Protocol on a new handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEfiLegacyRegion2ProtocolGuid, &mLegacyRegion2,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
diff --git BhyvePkg/Csm/CsmSupportLib/LegacyRegion.h BhyvePkg/Csm/CsmSupportLib/LegacyRegion.h
new file mode 100644
index 0000000..1be1dcd
--- /dev/null
+++ BhyvePkg/Csm/CsmSupportLib/LegacyRegion.h
@@ -0,0 +1,219 @@
+/** @file
+ Legacy Region Support
+
+ Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LEGACY_REGION_DXE_H_
+#define _LEGACY_REGION_DXE_H_
+
+#include
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#define PAM_PCI_BUS 0
+#define PAM_PCI_DEV 0
+#define PAM_PCI_FUNC 0
+
+#define REG_PAM0_OFFSET 0x59 // Programmable Attribute Map 0
+#define REG_PAM1_OFFSET 0x5a // Programmable Attribute Map 1
+#define REG_PAM2_OFFSET 0x5b // Programmable Attribute Map 2
+#define REG_PAM3_OFFSET 0x5c // Programmable Attribute Map 3
+#define REG_PAM4_OFFSET 0x5d // Programmable Attribute Map 4
+#define REG_PAM5_OFFSET 0x5e // Programmable Attribute Map 5
+#define REG_PAM6_OFFSET 0x5f // Programmable Attribute Map 6
+
+#define PAM_BASE_ADDRESS 0xc0000
+#define PAM_LIMIT_ADDRESS BASE_1MB
+
+//
+// Describes Legacy Region blocks and status.
+//
+typedef struct {
+ UINT32 Start;
+ UINT32 Length;
+ BOOLEAN ReadEnabled;
+ BOOLEAN WriteEnabled;
+} LEGACY_MEMORY_SECTION_INFO;
+
+//
+// Provides a map of the PAM registers and bits used to set Read/Write access.
+//
+typedef struct {
+ UINT8 PAMRegOffset;
+ UINT8 ReadEnableData;
+ UINT8 WriteEnableData;
+} PAM_REGISTER_VALUE;
+
+/**
+ Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.
+
+ If the On parameter evaluates to TRUE, this function enables memory reads in the address range
+ Start to (Start + Length - 1).
+ If the On parameter evaluates to FALSE, this function disables memory reads in the address range
+ Start to (Start + Length - 1).
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose attributes
+ should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address
+ was not aligned to a region's starting address or if the length
+ was greater than the number of bytes in the first region.
+ @param On[in] Decode / Non-Decode flag.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Decode (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity,
+ IN BOOLEAN *On
+ );
+
+/**
+ Modify the hardware to disallow memory writes in a region.
+
+ This function changes the attributes of a memory range to not allow writes.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Lock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ );
+
+/**
+ Modify the hardware to disallow memory attribute changes in a region.
+
+ This function makes the attributes of a region read only. Once a region is boot-locked with this
+ function, the read and write attributes of that region cannot be changed until a power cycle has
+ reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+ @retval EFI_UNSUPPORTED The chipset does not support locking the configuration registers in
+ a way that will not affect memory regions outside the legacy memory
+ region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2BootLock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ );
+
+/**
+ Modify the hardware to allow memory writes in a region.
+
+ This function changes the attributes of a memory range to allow writes.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param Start[in] The beginning of the physical address of the region whose
+ attributes should be modified.
+ @param Length[in] The number of bytes of memory whose attributes should be modified.
+ The actual number of bytes modified may be greater than the number
+ specified.
+ @param Granularity[out] The number of bytes in the last region affected. This may be less
+ than the total number of bytes affected if the starting address was
+ not aligned to a region's starting address or if the length was
+ greater than the number of bytes in the first region.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegion2Unlock (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ IN UINT32 Start,
+ IN UINT32 Length,
+ OUT UINT32 *Granularity
+ );
+
+/**
+ Get region information for the attributes of the Legacy Region.
+
+ This function is used to discover the granularity of the attributes for the memory in the legacy
+ region. Each attribute may have a different granularity and the granularity may not be the same
+ for all memory ranges in the legacy region.
+
+ @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.
+ @param DescriptorCount[out] The number of region descriptor entries returned in the Descriptor
+ buffer.
+ @param Descriptor[out] A pointer to a pointer used to return a buffer where the legacy
+ region information is deposited. This buffer will contain a list of
+ DescriptorCount number of region descriptors. This function will
+ provide the memory for the buffer.
+
+ @retval EFI_SUCCESS The region's attributes were successfully modified.
+ @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.
+
+**/
+EFI_STATUS
+EFIAPI
+LegacyRegionGetInfo (
+ IN EFI_LEGACY_REGION2_PROTOCOL *This,
+ OUT UINT32 *DescriptorCount,
+ OUT EFI_LEGACY_REGION_DESCRIPTOR **Descriptor
+ );
+
+#endif
+
diff --git BhyvePkg/EmuVariableFvbRuntimeDxe/Fvb.c BhyvePkg/EmuVariableFvbRuntimeDxe/Fvb.c
new file mode 100644
index 0000000..c927066
--- /dev/null
+++ BhyvePkg/EmuVariableFvbRuntimeDxe/Fvb.c
@@ -0,0 +1,917 @@
+/** @file
+ Firmware Block Services to support emulating non-volatile variables
+ by pretending that a memory buffer is storage for the NV variables.
+
+ Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PiDxe.h"
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "Fvb.h"
+
+#define EFI_AUTHENTICATED_VARIABLE_GUID \
+{ 0xaaf32c78, 0x947b, 0x439a, { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 } }
+
+//
+// Virtual Address Change Event
+//
+// This is needed for runtime variable access.
+//
+EFI_EVENT mEmuVarsFvbAddrChangeEvent = NULL;
+
+//
+// This is the single instance supported by this driver. It
+// supports the FVB and Device Path protocols.
+//
+EFI_FW_VOL_BLOCK_DEVICE mEmuVarsFvb = {
+ FVB_DEVICE_SIGNATURE,
+ { // DevicePath
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_MEMMAP_DP,
+ {
+ sizeof (MEMMAP_DEVICE_PATH),
+ 0
+ }
+ },
+ EfiMemoryMappedIO,
+ 0,
+ 0,
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ sizeof (EFI_DEVICE_PATH_PROTOCOL),
+ 0
+ }
+ }
+ },
+ NULL, // BufferPtr
+ FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize), // BlockSize
+ 2 * FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize), // Size
+ { // FwVolBlockInstance
+ FvbProtocolGetAttributes,
+ FvbProtocolSetAttributes,
+ FvbProtocolGetPhysicalAddress,
+ FvbProtocolGetBlockSize,
+ FvbProtocolRead,
+ FvbProtocolWrite,
+ FvbProtocolEraseBlocks,
+ NULL
+ },
+};
+
+
+/**
+ Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
+
+ This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
+ It converts pointer to new virtual address.
+
+ @param Event Event whose notification function is being invoked.
+ @param Context Pointer to the notification function's context.
+
+**/
+VOID
+EFIAPI
+FvbVirtualAddressChangeEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EfiConvertPointer (0x0, &mEmuVarsFvb.BufferPtr);
+}
+
+
+//
+// FVB protocol APIs
+//
+
+/**
+ The GetPhysicalAddress() function retrieves the base address of
+ a memory-mapped firmware volume. This function should be called
+ only for memory-mapped firmware volumes.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Address Pointer to a caller-allocated
+ EFI_PHYSICAL_ADDRESS that, on successful
+ return from GetPhysicalAddress(), contains the
+ base address of the firmware volume.
+
+ @retval EFI_SUCCESS The firmware volume base address is returned.
+
+ @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ *Address = (EFI_PHYSICAL_ADDRESS)(UINTN) FvbDevice->BufferPtr;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The GetBlockSize() function retrieves the size of the requested
+ block. It also returns the number of additional blocks with
+ the identical size. The GetBlockSize() function is used to
+ retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
+
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba Indicates the block for which to return the size.
+
+ @param BlockSize Pointer to a caller-allocated UINTN in which
+ the size of the block is returned.
+
+ @param NumberOfBlocks Pointer to a caller-allocated UINTN in
+ which the number of consecutive blocks,
+ starting with Lba, is returned. All
+ blocks in this range have a size of
+ BlockSize.
+
+
+ @retval EFI_SUCCESS The firmware volume base address is returned.
+
+ @retval EFI_INVALID_PARAMETER The requested LBA is out of range.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ )
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+
+ if (Lba > 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ *BlockSize = FvbDevice->BlockSize;
+ *NumberOfBlocks = (UINTN) (2 - (UINTN) Lba);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The GetAttributes() function retrieves the attributes and
+ current settings of the block. Status Codes Returned
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the
+ attributes and current settings are
+ returned. Type EFI_FVB_ATTRIBUTES_2 is defined
+ in EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were
+ returned.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolGetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ *Attributes =
+ (EFI_FVB_ATTRIBUTES_2) (
+ EFI_FVB2_READ_ENABLED_CAP |
+ EFI_FVB2_READ_STATUS |
+ EFI_FVB2_WRITE_ENABLED_CAP |
+ EFI_FVB2_WRITE_STATUS |
+ EFI_FVB2_ERASE_POLARITY
+ );
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ The SetAttributes() function sets configurable firmware volume
+ attributes and returns the new settings of the firmware volume.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Attributes On input, Attributes is a pointer to
+ EFI_FVB_ATTRIBUTES_2 that contains the
+ desired firmware volume settings. On
+ successful return, it contains the new
+ settings of the firmware volume. Type
+ EFI_FVB_ATTRIBUTES_2 is defined in
+ EFI_FIRMWARE_VOLUME_HEADER.
+
+ @retval EFI_SUCCESS The firmware volume attributes were returned.
+
+ @retval EFI_INVALID_PARAMETER The attributes requested are in
+ conflict with the capabilities
+ as declared in the firmware
+ volume header.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolSetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+{
+ return EFI_ACCESS_DENIED;
+}
+
+
+/**
+ Erases and initializes a firmware volume block.
+
+ The EraseBlocks() function erases one or more blocks as denoted
+ by the variable argument list. The entire parameter list of
+ blocks must be verified before erasing any blocks. If a block is
+ requested that does not exist within the associated firmware
+ volume (it has a larger index than the last block of the
+ firmware volume), the EraseBlocks() function must return the
+ status code EFI_INVALID_PARAMETER without modifying the contents
+ of the firmware volume. Implementations should be mindful that
+ the firmware volume might be in the WriteDisabled state. If it
+ is in this state, the EraseBlocks() function must return the
+ status code EFI_ACCESS_DENIED without modifying the contents of
+ the firmware volume. All calls to EraseBlocks() must be fully
+ flushed to the hardware before the EraseBlocks() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
+ instance.
+
+ @param ... The variable argument list is a list of tuples.
+ Each tuple describes a range of LBAs to erase
+ and consists of the following:
+ - An EFI_LBA that indicates the starting LBA
+ - A UINTN that indicates the number of blocks to
+ erase
+
+ The list is terminated with an
+ EFI_LBA_LIST_TERMINATOR. For example, the
+ following indicates that two ranges of blocks
+ (5-7 and 10-11) are to be erased: EraseBlocks
+ (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
+
+ @retval EFI_SUCCESS The erase request was successfully
+ completed.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the
+ WriteDisabled state.
+ @retval EFI_DEVICE_ERROR The block device is not functioning
+ correctly and could not be written.
+ The firmware device may have been
+ partially erased.
+ @retval EFI_INVALID_PARAMETER One or more of the LBAs listed
+ in the variable argument list do
+ not exist in the firmware volume.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ ...
+ )
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ VA_LIST args;
+ EFI_LBA StartingLba;
+ UINTN NumOfLba;
+ UINT8 Erase;
+ VOID *ErasePtr;
+ UINTN EraseSize;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+ Erase = 0;
+
+ VA_START (args, This);
+
+ do {
+ StartingLba = VA_ARG (args, EFI_LBA);
+ if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
+ break;
+ }
+
+ NumOfLba = VA_ARG (args, UINT32);
+
+ //
+ // Check input parameters
+ //
+ if ((NumOfLba == 0) || (StartingLba > 1) || ((StartingLba + NumOfLba) > 2)) {
+ VA_END (args);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (StartingLba == 0) {
+ Erase = (UINT8) (Erase | BIT0);
+ }
+ if ((StartingLba + NumOfLba) == 2) {
+ Erase = (UINT8) (Erase | BIT1);
+ }
+
+ } while (1);
+
+ VA_END (args);
+
+ ErasePtr = (UINT8*) FvbDevice->BufferPtr;
+ EraseSize = 0;
+
+ if ((Erase & BIT0) != 0) {
+ EraseSize = EraseSize + FvbDevice->BlockSize;
+ } else {
+ ErasePtr = (VOID*) ((UINT8*)ErasePtr + FvbDevice->BlockSize);
+ }
+
+ if ((Erase & BIT1) != 0) {
+ EraseSize = EraseSize + FvbDevice->BlockSize;
+ }
+
+ if (EraseSize != 0) {
+ SetMem (
+ (VOID*) ErasePtr,
+ EraseSize,
+ ERASED_UINT8
+ );
+ VA_START (args, This);
+ PlatformFvbBlocksErased (This, args);
+ VA_END (args);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Writes the specified number of bytes from the input buffer to the block.
+
+ The Write() function writes the specified number of bytes from
+ the provided buffer to the specified block and offset. If the
+ firmware volume is sticky write, the caller must ensure that
+ all the bits of the specified range to write are in the
+ EFI_FVB_ERASE_POLARITY state before calling the Write()
+ function, or else the result will be unpredictable. This
+ unpredictability arises because, for a sticky-write firmware
+ volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
+ state but cannot flip it back again. In general, before
+ calling the Write() function, the caller should call the
+ EraseBlocks() function first to erase the specified block to
+ write. A block erase cycle will transition bits from the
+ (NOT)EFI_FVB_ERASE_POLARITY state back to the
+ EFI_FVB_ERASE_POLARITY state. Implementations should be
+ mindful that the firmware volume might be in the WriteDisabled
+ state. If it is in this state, the Write() function must
+ return the status code EFI_ACCESS_DENIED without modifying the
+ contents of the firmware volume. The Write() function must
+ also prevent spanning block boundaries. If a write is
+ requested that spans a block boundary, the write must store up
+ to the boundary but not beyond. The output parameter NumBytes
+ must be set to correctly indicate the number of bytes actually
+ written. The caller must be aware that a write may be
+ partially completed. All writes, partial or otherwise, must be
+ fully flushed to the hardware before the Write() service
+ returns.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index to write to.
+
+ @param Offset Offset into the block at which to begin writing.
+
+ @param NumBytes Pointer to a UINTN. At entry, *NumBytes
+ contains the total size of the buffer. At
+ exit, *NumBytes contains the total number of
+ bytes actually written.
+
+ @param Buffer Pointer to a caller-allocated buffer that
+ contains the source for the write.
+
+ @retval EFI_SUCCESS The firmware volume was written successfully.
+
+ @retval EFI_BAD_BUFFER_SIZE The write was attempted across an
+ LBA boundary. On output, NumBytes
+ contains the total number of bytes
+ actually written.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the
+ WriteDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is malfunctioning
+ and could not be written.
+
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ UINT8 *FvbDataPtr;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ if ((Lba > 1) || (Offset > FvbDevice->BlockSize)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Offset + *NumBytes) > FvbDevice->BlockSize) {
+ *NumBytes = FvbDevice->BlockSize - Offset;
+ }
+
+ FvbDataPtr =
+ (UINT8*) FvbDevice->BufferPtr +
+ MultU64x32 (Lba, (UINT32) FvbDevice->BlockSize) +
+ Offset;
+
+ if (*NumBytes > 0) {
+ CopyMem (FvbDataPtr, Buffer, *NumBytes);
+ PlatformFvbDataWritten (This, Lba, Offset, *NumBytes, Buffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Reads the specified number of bytes into a buffer from the specified block.
+
+ The Read() function reads the requested number of bytes from the
+ requested block and stores them in the provided buffer.
+ Implementations should be mindful that the firmware volume
+ might be in the ReadDisabled state. If it is in this state,
+ the Read() function must return the status code
+ EFI_ACCESS_DENIED without modifying the contents of the
+ buffer. The Read() function must also prevent spanning block
+ boundaries. If a read is requested that would span a block
+ boundary, the read must read up to the boundary but not
+ beyond. The output parameter NumBytes must be set to correctly
+ indicate the number of bytes actually read. The caller must be
+ aware that a read may be partially completed.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+
+ @param Lba The starting logical block index
+ from which to read.
+
+ @param Offset Offset into the block at which to begin reading.
+
+ @param NumBytes Pointer to a UINTN. At entry, *NumBytes
+ contains the total size of the buffer. At
+ exit, *NumBytes contains the total number of
+ bytes read.
+
+ @param Buffer Pointer to a caller-allocated buffer that will
+ be used to hold the data that is read.
+
+ @retval EFI_SUCCESS The firmware volume was read successfully
+ and contents are in Buffer.
+
+ @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA
+ boundary. On output, NumBytes
+ contains the total number of bytes
+ returned in Buffer.
+
+ @retval EFI_ACCESS_DENIED The firmware volume is in the
+ ReadDisabled state.
+
+ @retval EFI_DEVICE_ERROR The block device is not
+ functioning correctly and could
+ not be read.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbProtocolRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN OUT UINT8 *Buffer
+ )
+{
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
+ UINT8 *FvbDataPtr;
+
+ FvbDevice = FVB_DEVICE_FROM_THIS (This);
+
+ if ((Lba > 1) || (Offset > FvbDevice->BlockSize)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Offset + *NumBytes) > FvbDevice->BlockSize) {
+ *NumBytes = FvbDevice->BlockSize - Offset;
+ }
+
+ FvbDataPtr =
+ (UINT8*) FvbDevice->BufferPtr +
+ MultU64x32 (Lba, (UINT32) FvbDevice->BlockSize) +
+ Offset;
+
+ if (*NumBytes > 0) {
+ CopyMem (Buffer, FvbDataPtr, *NumBytes);
+ PlatformFvbDataRead (This, Lba, Offset, *NumBytes, Buffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Check the integrity of firmware volume header.
+
+ @param[in] FwVolHeader - A pointer to a firmware volume header
+
+ @retval EFI_SUCCESS - The firmware volume is consistent
+ @retval EFI_NOT_FOUND - The firmware volume has been corrupted.
+
+**/
+EFI_STATUS
+ValidateFvHeader (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
+ )
+{
+ UINT16 Checksum;
+
+ //
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
+ (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
+ (FwVolHeader->FvLength != EMU_FVB_SIZE) ||
+ (FwVolHeader->HeaderLength != EMU_FV_HEADER_LENGTH)
+ ) {
+ DEBUG ((EFI_D_INFO, "EMU Variable FVB: Basic FV headers were invalid\n"));
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Verify the header checksum
+ //
+ Checksum = CalculateSum16((VOID*) FwVolHeader, FwVolHeader->HeaderLength);
+
+ if (Checksum != 0) {
+ DEBUG ((EFI_D_INFO, "EMU Variable FVB: FV checksum was invalid\n"));
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Initializes the FV Header and Variable Store Header
+ to support variable operations.
+
+ @param[in] Ptr - Location to initialize the headers
+
+**/
+VOID
+InitializeFvAndVariableStoreHeaders (
+ IN VOID *Ptr
+ )
+{
+ //
+ // Templates for standard (non-authenticated) variable FV header
+ //
+ STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndVarTemplate = {
+ { // EFI_FIRMWARE_VOLUME_HEADER FvHdr;
+ // UINT8 ZeroVector[16];
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+
+ // EFI_GUID FileSystemGuid;
+ EFI_SYSTEM_NV_DATA_FV_GUID,
+
+ // UINT64 FvLength;
+ EMU_FVB_SIZE,
+
+ // UINT32 Signature;
+ EFI_FVH_SIGNATURE,
+
+ // EFI_FVB_ATTRIBUTES_2 Attributes;
+ 0x4feff,
+
+ // UINT16 HeaderLength;
+ EMU_FV_HEADER_LENGTH,
+
+ // UINT16 Checksum;
+ 0,
+
+ // UINT16 ExtHeaderOffset;
+ 0,
+
+ // UINT8 Reserved[1];
+ {0},
+
+ // UINT8 Revision;
+ EFI_FVH_REVISION,
+
+ // EFI_FV_BLOCK_MAP_ENTRY BlockMap[1];
+ {
+ {
+ 2, // UINT32 NumBlocks;
+ EMU_FVB_BLOCK_SIZE // UINT32 Length;
+ }
+ }
+ },
+ // EFI_FV_BLOCK_MAP_ENTRY EndBlockMap;
+ { 0, 0 }, // End of block map
+ { // VARIABLE_STORE_HEADER VarHdr;
+ // EFI_GUID Signature;
+ EFI_VARIABLE_GUID,
+
+ // UINT32 Size;
+ (
+ FixedPcdGet32 (PcdVariableStoreSize) -
+ OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE, VarHdr)
+ ),
+
+ // UINT8 Format;
+ VARIABLE_STORE_FORMATTED,
+
+ // UINT8 State;
+ VARIABLE_STORE_HEALTHY,
+
+ // UINT16 Reserved;
+ 0,
+
+ // UINT32 Reserved1;
+ 0
+ }
+ };
+
+ //
+ // Templates for authenticated variable FV header
+ //
+ STATIC FVB_FV_HDR_AND_VARS_TEMPLATE FvAndAuthenticatedVarTemplate = {
+ { // EFI_FIRMWARE_VOLUME_HEADER FvHdr;
+ // UINT8 ZeroVector[16];
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+
+ // EFI_GUID FileSystemGuid;
+ EFI_SYSTEM_NV_DATA_FV_GUID,
+
+ // UINT64 FvLength;
+ EMU_FVB_SIZE,
+
+ // UINT32 Signature;
+ EFI_FVH_SIGNATURE,
+
+ // EFI_FVB_ATTRIBUTES_2 Attributes;
+ 0x4feff,
+
+ // UINT16 HeaderLength;
+ EMU_FV_HEADER_LENGTH,
+
+ // UINT16 Checksum;
+ 0,
+
+ // UINT16 ExtHeaderOffset;
+ 0,
+
+ // UINT8 Reserved[1];
+ {0},
+
+ // UINT8 Revision;
+ EFI_FVH_REVISION,
+
+ // EFI_FV_BLOCK_MAP_ENTRY BlockMap[1];
+ {
+ {
+ 2, // UINT32 NumBlocks;
+ EMU_FVB_BLOCK_SIZE // UINT32 Length;
+ }
+ }
+ },
+ // EFI_FV_BLOCK_MAP_ENTRY EndBlockMap;
+ { 0, 0 }, // End of block map
+ { // VARIABLE_STORE_HEADER VarHdr;
+ // EFI_GUID Signature; // need authenticated variables for secure boot
+ EFI_AUTHENTICATED_VARIABLE_GUID,
+
+ // UINT32 Size;
+ (
+ FixedPcdGet32 (PcdVariableStoreSize) -
+ OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE, VarHdr)
+ ),
+
+ // UINT8 Format;
+ VARIABLE_STORE_FORMATTED,
+
+ // UINT8 State;
+ VARIABLE_STORE_HEALTHY,
+
+ // UINT16 Reserved;
+ 0,
+
+ // UINT32 Reserved1;
+ 0
+ }
+ };
+
+ EFI_FIRMWARE_VOLUME_HEADER *Fv;
+
+ //
+ // Copy the template structure into the location
+ //
+ if (FeaturePcdGet (PcdSecureBootEnable) == FALSE) {
+ CopyMem (Ptr, (VOID*)&FvAndVarTemplate, sizeof (FvAndVarTemplate));
+ } else {
+ CopyMem (Ptr, (VOID*)&FvAndAuthenticatedVarTemplate, sizeof (FvAndAuthenticatedVarTemplate));
+ }
+
+ //
+ // Update the checksum for the FV header
+ //
+ Fv = (EFI_FIRMWARE_VOLUME_HEADER*) Ptr;
+ Fv->Checksum = CalculateCheckSum16 (Ptr, Fv->HeaderLength);
+}
+
+/**
+ Main entry point.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS Successfully initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+FvbInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ VOID *Ptr;
+ VOID *SubPtr;
+ BOOLEAN Initialize;
+ EFI_HANDLE Handle;
+ EFI_PHYSICAL_ADDRESS Address;
+
+ DEBUG ((EFI_D_INFO, "EMU Variable FVB Started\n"));
+
+ //
+ // Verify that the PCD's are set correctly.
+ //
+ if (
+ (PcdGet32 (PcdVariableStoreSize) +
+ PcdGet32 (PcdFlashNvStorageFtwWorkingSize)
+ ) >
+ EMU_FVB_BLOCK_SIZE
+ ) {
+ DEBUG ((EFI_D_ERROR, "EMU Variable invalid PCD sizes\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) {
+ DEBUG ((EFI_D_INFO, "Disabling EMU Variable FVB since "
+ "flash variables appear to be supported.\n"));
+ return EFI_ABORTED;
+ }
+
+ //
+ // By default we will initialize the FV contents. But, if
+ // PcdEmuVariableNvStoreReserved is non-zero, then we will
+ // use this location for our buffer.
+ //
+ // If this location does not have a proper FV header, then
+ // we will initialize it.
+ //
+ Initialize = TRUE;
+ if (PcdGet64 (PcdEmuVariableNvStoreReserved) != 0) {
+ Ptr = (VOID*)(UINTN) PcdGet64 (PcdEmuVariableNvStoreReserved);
+ DEBUG ((
+ EFI_D_INFO,
+ "EMU Variable FVB: Using pre-reserved block at %p\n",
+ Ptr
+ ));
+ Status = ValidateFvHeader (Ptr);
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "EMU Variable FVB: Found valid pre-existing FV\n"));
+ Initialize = FALSE;
+ }
+ } else {
+ Ptr = AllocateAlignedRuntimePages (
+ EFI_SIZE_TO_PAGES (EMU_FVB_SIZE),
+ SIZE_64KB
+ );
+ }
+
+ mEmuVarsFvb.BufferPtr = Ptr;
+
+ //
+ // Initialize the main FV header and variable store header
+ //
+ if (Initialize) {
+ SetMem (Ptr, EMU_FVB_SIZE, ERASED_UINT8);
+ InitializeFvAndVariableStoreHeaders (Ptr);
+ }
+ PcdSet64 (PcdFlashNvStorageVariableBase64, (UINT32)(UINTN) Ptr);
+
+ //
+ // Initialize the Fault Tolerant Write data area
+ //
+ SubPtr = (VOID*) ((UINT8*) Ptr + PcdGet32 (PcdVariableStoreSize));
+ PcdSet32 (PcdFlashNvStorageFtwWorkingBase, (UINT32)(UINTN) SubPtr);
+
+ //
+ // Initialize the Fault Tolerant Write spare block
+ //
+ SubPtr = (VOID*) ((UINT8*) Ptr + EMU_FVB_BLOCK_SIZE);
+ PcdSet32 (PcdFlashNvStorageFtwSpareBase, (UINT32)(UINTN) SubPtr);
+
+ //
+ // Setup FVB device path
+ //
+ Address = (EFI_PHYSICAL_ADDRESS)(UINTN) Ptr;
+ mEmuVarsFvb.DevicePath.MemMapDevPath.StartingAddress = Address;
+ mEmuVarsFvb.DevicePath.MemMapDevPath.EndingAddress = Address + EMU_FVB_SIZE - 1;
+
+ //
+ // Install the protocols
+ //
+ DEBUG ((EFI_D_INFO, "Installing FVB for EMU Variable support\n"));
+ Handle = 0;
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEfiFirmwareVolumeBlock2ProtocolGuid,
+ &mEmuVarsFvb.FwVolBlockInstance,
+ &gEfiDevicePathProtocolGuid,
+ &mEmuVarsFvb.DevicePath,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Register for the virtual address change event
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ FvbVirtualAddressChangeEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mEmuVarsFvbAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+
diff --git BhyvePkg/EmuVariableFvbRuntimeDxe/Fvb.h BhyvePkg/EmuVariableFvbRuntimeDxe/Fvb.h
new file mode 100644
index 0000000..45a4326
--- /dev/null
+++ BhyvePkg/EmuVariableFvbRuntimeDxe/Fvb.h
@@ -0,0 +1,140 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ FwBlockService.h
+
+Abstract:
+
+ Firmware volume block driver for Intel Firmware Hub (FWH) device
+
+--*/
+
+#ifndef _FW_BLOCK_SERVICE_H
+#define _FW_BLOCK_SERVICE_H
+
+//
+// Fvb Protocol instance data
+//
+#define FVB_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE)
+#define FVB_DEVICE_SIGNATURE SIGNATURE_32 ('F', 'V', 'B', 'N')
+
+#pragma pack (1)
+
+typedef struct {
+
+ EFI_FIRMWARE_VOLUME_HEADER FvHdr;
+ EFI_FV_BLOCK_MAP_ENTRY EndBlockMap;
+ VARIABLE_STORE_HEADER VarHdr;
+
+} FVB_FV_HDR_AND_VARS_TEMPLATE;
+
+typedef struct {
+ MEMMAP_DEVICE_PATH MemMapDevPath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevPath;
+} FV_DEVICE_PATH;
+
+#pragma pack ()
+
+typedef struct {
+ UINTN Signature;
+ FV_DEVICE_PATH DevicePath;
+ VOID *BufferPtr;
+ UINTN BlockSize;
+ UINTN Size;
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance;
+} EFI_FW_VOL_BLOCK_DEVICE;
+
+
+//
+// Constants
+//
+#define EMU_FVB_BLOCK_SIZE (FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize))
+#define EMU_FVB_SIZE (2 * FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize))
+#define FTW_WRITE_QUEUE_SIZE \
+ (FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) - \
+ sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER))
+#define EMU_FV_HEADER_LENGTH OFFSET_OF (FVB_FV_HDR_AND_VARS_TEMPLATE, VarHdr)
+
+#define NOT_ERASED_BIT 0
+#define ERASED_BIT 1
+#define ERASED_UINT8 0xff
+#define ERASED_UINT32 0xffffffff
+
+//
+// Protocol APIs
+//
+EFI_STATUS
+EFIAPI
+FvbProtocolGetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+;
+
+EFI_STATUS
+EFIAPI
+FvbProtocolSetAttributes (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
+ )
+;
+
+EFI_STATUS
+EFIAPI
+FvbProtocolGetPhysicalAddress (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+;
+
+EFI_STATUS
+EFIAPI
+FvbProtocolGetBlockSize (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ OUT UINTN *BlockSize,
+ OUT UINTN *NumberOfBlocks
+ )
+;
+
+EFI_STATUS
+EFIAPI
+FvbProtocolRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN OUT UINT8 *Buffer
+ )
+;
+
+EFI_STATUS
+EFIAPI
+FvbProtocolWrite (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN OUT UINTN *NumBytes,
+ IN UINT8 *Buffer
+ )
+;
+
+EFI_STATUS
+EFIAPI
+FvbProtocolEraseBlocks (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
+ ...
+ )
+;
+
+#endif
diff --git BhyvePkg/EmuVariableFvbRuntimeDxe/Fvb.inf BhyvePkg/EmuVariableFvbRuntimeDxe/Fvb.inf
new file mode 100644
index 0000000..bdc656f
--- /dev/null
+++ BhyvePkg/EmuVariableFvbRuntimeDxe/Fvb.inf
@@ -0,0 +1,76 @@
+## @file
+# Firmware Block Services to support emulating non-volatile variables
+# by pretending that a memory buffer is storage for the NV variables.
+#
+# Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = EmuVariableFvbRuntimeDxe
+ FILE_GUID = 22dc2b60-fe40-42ac-b01f-3ab1fad9aad8
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = FvbInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ Fvb.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ BhyvePkg/BhyvePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DxeServicesTableLib
+ HobLib
+ MemoryAllocationLib
+ PcdLib
+ PlatformFvbLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+ UefiRuntimeLib
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED Create Event: EVENT_GROUP_GUID
+
+[Protocols]
+ gEfiFirmwareVolumeBlock2ProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+ gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_PRODUCED
+
+[FixedPcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved
+
+[FeaturePcd]
+ gUefiBhyvePkgTokenSpaceGuid.PcdSecureBootEnable
+
+[Depex]
+ TRUE
+
diff --git BhyvePkg/Include/IndustryStandard/LegacyVgaBios.h BhyvePkg/Include/IndustryStandard/LegacyVgaBios.h
new file mode 100644
index 0000000..ef73775
--- /dev/null
+++ BhyvePkg/Include/IndustryStandard/LegacyVgaBios.h
@@ -0,0 +1,136 @@
+/** @file
+ Type definitions related to the VBE (VESA BIOS Extension, Int10h AH=4Fh)
+ services GET INFORMATION (AL=00h) and GET MODE INFORMATION (AL=01h).
+
+ For reference, see Ralf Brown's Interrupt List:
+
+
+
+ Copyright (C) 2014, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __LEGACY_VGA_BIOS_H__
+#define __LEGACY_VGA_BIOS_H__
+
+#include
+
+#pragma pack (1)
+typedef struct {
+ UINT8 Signature[4];
+ UINT16 VesaVersion;
+ UINT32 OemNameAddress;
+ UINT32 Capabilities;
+ UINT32 ModeListAddress;
+ UINT16 VideoMem64K;
+ UINT16 OemSoftwareVersion;
+ UINT32 VendorNameAddress;
+ UINT32 ProductNameAddress;
+ UINT32 ProductRevAddress;
+} VBE_INFO_BASE;
+
+typedef struct {
+ VBE_INFO_BASE Base;
+ UINT8 Buffer[256 - sizeof (VBE_INFO_BASE)];
+} VBE_INFO;
+
+typedef struct {
+ UINT16 ModeAttr;
+ UINT8 WindowAAttr;
+ UINT8 WindowBAttr;
+ UINT16 WindowGranularityKB;
+ UINT16 WindowSizeKB;
+ UINT16 WindowAStartSegment;
+ UINT16 WindowBStartSegment;
+ UINT32 WindowPositioningAddress;
+ UINT16 BytesPerScanLine;
+
+ UINT16 Width;
+ UINT16 Height;
+ UINT8 CharCellWidth;
+ UINT8 CharCellHeight;
+ UINT8 NumPlanes;
+ UINT8 BitsPerPixel;
+ UINT8 NumBanks;
+ UINT8 MemoryModel;
+ UINT8 BankSizeKB;
+ UINT8 NumImagePagesLessOne;
+ UINT8 Vbe3;
+
+ UINT8 RedMaskSize;
+ UINT8 RedMaskPos;
+ UINT8 GreenMaskSize;
+ UINT8 GreenMaskPos;
+ UINT8 BlueMaskSize;
+ UINT8 BlueMaskPos;
+ UINT8 ReservedMaskSize;
+ UINT8 ReservedMaskPos;
+ UINT8 DirectColorModeInfo;
+
+ UINT32 LfbAddress;
+ UINT32 OffScreenAddress;
+ UINT16 OffScreenSizeKB;
+
+ UINT16 BytesPerScanLineLinear;
+ UINT8 NumImagesLessOneBanked;
+ UINT8 NumImagesLessOneLinear;
+ UINT8 RedMaskSizeLinear;
+ UINT8 RedMaskPosLinear;
+ UINT8 GreenMaskSizeLinear;
+ UINT8 GreenMaskPosLinear;
+ UINT8 BlueMaskSizeLinear;
+ UINT8 BlueMaskPosLinear;
+ UINT8 ReservedMaskSizeLinear;
+ UINT8 ReservedMaskPosLinear;
+ UINT32 MaxPixelClockHz;
+ UINT8 Reserved[190];
+} VBE_MODE_INFO;
+
+typedef struct {
+ UINT16 ModeAttr;
+ UINT8 WindowAAttr;
+ UINT8 WindowBAttr;
+ UINT16 WindowGranularityKB;
+ UINT16 WindowSizeKB;
+ UINT16 WindowAStartSegment;
+ UINT16 WindowBStartSegment;
+ UINT32 WindowPositioningAddress;
+ UINT16 BytesPerScanLine;
+
+ UINT16 Width;
+ UINT16 Height;
+ UINT8 CharCellWidth;
+ UINT8 CharCellHeight;
+ UINT8 NumPlanes;
+ UINT8 BitsPerPixel;
+ UINT8 NumBanks;
+ UINT8 MemoryModel;
+ UINT8 BankSizeKB;
+ UINT8 NumImagePagesLessOne;
+ UINT8 Vbe3;
+
+ UINT8 RedMaskSize;
+ UINT8 RedMaskPos;
+ UINT8 GreenMaskSize;
+ UINT8 GreenMaskPos;
+ UINT8 BlueMaskSize;
+ UINT8 BlueMaskPos;
+ UINT8 ReservedMaskSize;
+ UINT8 ReservedMaskPos;
+ UINT8 DirectColorModeInfo;
+
+ UINT32 LfbAddress;
+ UINT32 OffScreenAddress;
+ UINT16 OffScreenSizeKB;
+} VBE2_MODE_INFO;
+
+#pragma pack ()
+
+#endif
diff --git BhyvePkg/Include/IndustryStandard/Virtio.h BhyvePkg/Include/IndustryStandard/Virtio.h
new file mode 100644
index 0000000..fc0c3da
--- /dev/null
+++ BhyvePkg/Include/IndustryStandard/Virtio.h
@@ -0,0 +1,193 @@
+/** @file
+
+ Generic type and macro definitions corresponding to the virtio-0.9.5
+ specification.
+
+ Copyright (C) 2012, Red Hat, Inc.
+ Portion of Copyright (C) 2013, ARM Ltd.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _VIRTIO_H_
+#define _VIRTIO_H_
+
+#include
+
+//
+// VirtIo Subsystem Device IDs
+//
+#define VIRTIO_SUBSYSTEM_NETWORK_CARD 1
+#define VIRTIO_SUBSYSTEM_BLOCK_DEVICE 2
+#define VIRTIO_SUBSYSTEM_CONSOLE 3
+#define VIRTIO_SUBSYSTEM_ENTROPY_SOURCE 4
+#define VIRTIO_SUBSYSTEM_MEMORY_BALLOONING 5
+#define VIRTIO_SUBSYSTEM_IO_MEMORY 6
+#define VIRTIO_SUBSYSTEM_RPMSG 7
+#define VIRTIO_SUBSYSTEM_SCSI_HOST 8
+#define VIRTIO_SUBSYSTEM_9P_TRANSPORT 9
+#define VIRTIO_SUBSYSTEM_MAC80211_WLAN 10
+
+//
+// Virtio IDs
+//
+#define VIRTIO_VENDOR_ID 0x1AF4
+#define VIRTIO_MMIO_MAGIC 0x74726976 // "virt"
+
+
+//
+// VirtIo Device Specific Configuration Offsets
+//
+#define VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI 20
+#define VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_PCI_WITH_MSI_X 24
+#define VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO 0x100
+
+//
+// PCI VirtIo Header Offsets
+//
+#define VIRTIO_PCI_OFFSET_DEVICE_FEATURES 0x00
+#define VIRTIO_PCI_OFFSET_GUEST_FEATURES 0x04
+#define VIRTIO_PCI_OFFSET_QUEUE_ADDRESS 0x08
+#define VIRTIO_PCI_OFFSET_QUEUE_SIZE 0x0C
+#define VIRTIO_PCI_OFFSET_QUEUE_SELECT 0x0E
+#define VIRTIO_PCI_OFFSET_QUEUE_NOTIFY 0x10
+#define VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS 0x12
+#define VIRTIO_PCI_OFFSET_QUEUE_DEVICE_ISR 0x13
+
+//
+// MMIO VirtIo Header Offsets
+//
+#define VIRTIO_MMIO_OFFSET_MAGIC 0x00
+#define VIRTIO_MMIO_OFFSET_VERSION 0x04
+#define VIRTIO_MMIO_OFFSET_DEVICE_ID 0x08
+#define VIRTIO_MMIO_OFFSET_VENDOR_ID 0x0C
+#define VIRTIO_MMIO_OFFSET_HOST_FEATURES 0x10
+#define VIRTIO_MMIO_OFFSET_HOST_FEATURES_SEL 0x14
+#define VIRTIO_MMIO_OFFSET_GUEST_FEATURES 0x20
+#define VIRTIO_MMIO_OFFSET_GUEST_FEATURES_SEL 0x24
+#define VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE 0x28
+#define VIRTIO_MMIO_OFFSET_QUEUE_SEL 0x30
+#define VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX 0x34
+#define VIRTIO_MMIO_OFFSET_QUEUE_NUM 0x38
+#define VIRTIO_MMIO_OFFSET_QUEUE_ALIGN 0x3C
+#define VIRTIO_MMIO_OFFSET_QUEUE_PFN 0x40
+#define VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY 0x50
+#define VIRTIO_MMIO_OFFSET_INTERRUPT_STATUS 0x60
+#define VIRTIO_MMIO_OFFSET_INTERRUPT_ACK 0x64
+#define VIRTIO_MMIO_OFFSET_STATUS 0x70
+
+//
+// Data in the communication area is defined as packed and accessed as
+// volatile.
+//
+// Some structures contain arrays with dynamically determined size. In such
+// cases the array and its sibling fields are replaced with pointers.
+//
+// All indices (variables and fields named *Idx) are free-running and wrap
+// around after 0xFFFF. The queue size reported by the host is always an
+// integral power of 2, not greater than 32768. Actual array indices are
+// consistently calculated by taking the remainder of a given Idx object modulo
+// QueueSize. Since 0x10000 is an integral multiple of the QueueSize, UINT16
+// wraparound is a correct wraparound modulo QueueSize too (it doesn't offset
+// the remainder class).
+//
+// virtio-0.9.5, 2.3.4 Available Ring
+//
+#define VRING_AVAIL_F_NO_INTERRUPT BIT0
+
+typedef struct {
+ volatile UINT16 *Flags;
+ volatile UINT16 *Idx;
+
+ volatile UINT16 *Ring; // QueueSize elements
+ volatile UINT16 *UsedEvent; // unused as per negotiation
+} VRING_AVAIL;
+
+
+//
+// virtio-0.9.5, 2.3.5 Used Ring
+//
+#define VRING_USED_F_NO_NOTIFY BIT0
+
+#pragma pack(1)
+typedef struct {
+ UINT32 Id;
+ UINT32 Len;
+} VRING_USED_ELEM;
+#pragma pack()
+
+typedef struct {
+ volatile UINT16 *Flags;
+ volatile UINT16 *Idx;
+ volatile VRING_USED_ELEM *UsedElem; // QueueSize elements
+ volatile UINT16 *AvailEvent; // unused as per negotiation
+} VRING_USED;
+
+
+//
+// virtio-0.9.5, 2.3.2 Descriptor Table
+//
+#define VRING_DESC_F_NEXT BIT0 // more descriptors in this request
+#define VRING_DESC_F_WRITE BIT1 // buffer to be written *by the host*
+#define VRING_DESC_F_INDIRECT BIT2 // unused
+
+#pragma pack(1)
+typedef struct {
+ UINT64 Addr;
+ UINT32 Len;
+ UINT16 Flags;
+ UINT16 Next;
+} VRING_DESC;
+#pragma pack()
+
+typedef struct {
+ UINTN NumPages;
+ VOID *Base; // deallocate only this field
+ volatile VRING_DESC *Desc; // QueueSize elements
+ VRING_AVAIL Avail;
+ VRING_USED Used;
+ UINT16 QueueSize;
+} VRING;
+
+
+//
+// virtio-0.9.5, 2.2.2 Virtio Header -- no MSI-X
+//
+#pragma pack(1)
+typedef struct {
+ UINT32 VhdrDeviceFeatureBits;
+ UINT32 VhdrGuestFeatureBits;
+ UINT32 VhdrQueueAddress;
+ UINT16 VhdrQueueSize;
+ UINT16 VhdrQueueSelect;
+ UINT16 VhdrQueueNotify;
+ UINT8 VhdrDeviceStatus;
+ UINT8 VhdrISR;
+} VIRTIO_HDR;
+#pragma pack()
+
+
+//
+// virtio-0.9.5, 2.2.2.1 Device Status
+//
+#define VSTAT_ACK BIT0
+#define VSTAT_DRIVER BIT1
+#define VSTAT_DRIVER_OK BIT2
+#define VSTAT_FAILED BIT7
+
+//
+// virtio-0.9.5, Appendix B: Reserved (Device-Independent) Feature Bits
+//
+#define VIRTIO_F_NOTIFY_ON_EMPTY BIT24
+#define VIRTIO_F_RING_INDIRECT_DESC BIT28
+#define VIRTIO_F_RING_EVENT_IDX BIT29
+
+
+#endif // _VIRTIO_H_
diff --git BhyvePkg/Include/IndustryStandard/VirtioBlk.h BhyvePkg/Include/IndustryStandard/VirtioBlk.h
new file mode 100644
index 0000000..0d3bcbb
--- /dev/null
+++ BhyvePkg/Include/IndustryStandard/VirtioBlk.h
@@ -0,0 +1,80 @@
+/** @file
+
+ Virtio Block Device specific type and macro definitions corresponding to the
+ virtio-0.9.5 specification.
+
+ Copyright (C) 2012, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _VIRTIO_BLK_H_
+#define _VIRTIO_BLK_H_
+
+#include
+
+
+//
+// virtio-0.9.5, Appendix D: Block Device
+//
+#pragma pack(1)
+typedef struct {
+ VIRTIO_HDR Generic;
+ UINT64 VhdrCapacity;
+ UINT32 VhdrSizeMax;
+ UINT32 VhdrSegMax;
+ UINT16 VhdrCylinders;
+ UINT8 VhdrHeads;
+ UINT8 VhdrSectors;
+ UINT32 VhdrBlkSize;
+} VBLK_HDR;
+#pragma pack()
+
+#define OFFSET_OF_VBLK(Field) OFFSET_OF (VBLK_HDR, Field)
+#define SIZE_OF_VBLK(Field) (sizeof ((VBLK_HDR *) 0)->Field)
+
+#define VIRTIO_BLK_F_BARRIER BIT0
+#define VIRTIO_BLK_F_SIZE_MAX BIT1
+#define VIRTIO_BLK_F_SEG_MAX BIT2
+#define VIRTIO_BLK_F_GEOMETRY BIT4
+#define VIRTIO_BLK_F_RO BIT5
+#define VIRTIO_BLK_F_BLK_SIZE BIT6 // treated as "logical block size" in
+ // practice; actual host side implementation
+ // negotiates "optimal" block size
+ // separately
+#define VIRTIO_BLK_F_SCSI BIT7
+#define VIRTIO_BLK_F_FLUSH BIT9 // identical to "write cache enabled"
+
+//
+// We keep the status byte separate from the rest of the virtio-blk request
+// header. See description of historical scattering at the end of Appendix D:
+// we're going to put the status byte in a separate VRING_DESC.
+//
+#pragma pack(1)
+typedef struct {
+ UINT32 Type;
+ UINT32 IoPrio;
+ UINT64 Sector;
+} VIRTIO_BLK_REQ;
+#pragma pack()
+
+#define VIRTIO_BLK_T_IN 0x00000000
+#define VIRTIO_BLK_T_OUT 0x00000001
+#define VIRTIO_BLK_T_SCSI_CMD 0x00000002
+#define VIRTIO_BLK_T_SCSI_CMD_OUT 0x00000003
+#define VIRTIO_BLK_T_FLUSH 0x00000004
+#define VIRTIO_BLK_T_FLUSH_OUT 0x00000005
+#define VIRTIO_BLK_T_BARRIER BIT31
+
+#define VIRTIO_BLK_S_OK 0x00
+#define VIRTIO_BLK_S_IOERR 0x01
+#define VIRTIO_BLK_S_UNSUPP 0x02
+
+#endif // _VIRTIO_BLK_H_
diff --git BhyvePkg/Include/IndustryStandard/VirtioNet.h BhyvePkg/Include/IndustryStandard/VirtioNet.h
new file mode 100644
index 0000000..6e79de1
--- /dev/null
+++ BhyvePkg/Include/IndustryStandard/VirtioNet.h
@@ -0,0 +1,97 @@
+/** @file
+ Virtio Network Device specific type and macro definitions corresponding to
+ the virtio-0.9.5 specification.
+
+ Copyright (C) 2013, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _VIRTIO_NET_H_
+#define _VIRTIO_NET_H_
+
+#include
+
+//
+// virtio-0.9.5, Appendix C: Network Device
+//
+#pragma pack(1)
+typedef struct {
+ UINT8 Mac[6];
+ UINT16 LinkStatus;
+} VIRTIO_NET_CONFIG;
+#pragma pack()
+
+#define OFFSET_OF_VNET(Field) OFFSET_OF (VIRTIO_NET_CONFIG, Field)
+#define SIZE_OF_VNET(Field) (sizeof ((VIRTIO_NET_CONFIG *) 0)->Field)
+
+//
+// Queue Identifiers
+//
+#define VIRTIO_NET_Q_RX 0
+#define VIRTIO_NET_Q_TX 1
+
+//
+// Feature Bits
+//
+#define VIRTIO_NET_F_CSUM BIT0 // host to checksum outgoing packets
+#define VIRTIO_NET_F_GUEST_CSUM BIT1 // guest to checksum incoming packets
+#define VIRTIO_NET_F_MAC BIT5 // MAC available to guest
+#define VIRTIO_NET_F_GSO BIT6 // deprecated
+#define VIRTIO_NET_F_GUEST_TSO4 BIT7 // guest can receive TSOv4
+#define VIRTIO_NET_F_GUEST_TSO6 BIT8 // guest can receive TSOv6
+#define VIRTIO_NET_F_GUEST_ECN BIT9 // guest can receive TSO with ECN
+#define VIRTIO_NET_F_GUEST_UFO BIT10 // guest can receive UFO
+#define VIRTIO_NET_F_HOST_TSO4 BIT11 // host can receive TSOv4
+#define VIRTIO_NET_F_HOST_TSO6 BIT12 // host can receive TSOv6
+#define VIRTIO_NET_F_HOST_ECN BIT13 // host can receive TSO with ECN
+#define VIRTIO_NET_F_HOST_UFO BIT14 // host can receive UFO
+#define VIRTIO_NET_F_MRG_RXBUF BIT15 // guest can merge receive buffers
+#define VIRTIO_NET_F_STATUS BIT16 // link status available to guest
+#define VIRTIO_NET_F_CTRL_VQ BIT17 // control channel available
+#define VIRTIO_NET_F_CTRL_RX BIT18 // control channel RX mode support
+#define VIRTIO_NET_F_CTRL_VLAN BIT19 // control channel VLAN filtering
+#define VIRTIO_NET_F_GUEST_ANNOUNCE BIT21 // guest can send gratuitous pkts
+
+//
+// Packet Header
+//
+#pragma pack(1)
+typedef struct {
+ UINT8 Flags;
+ UINT8 GsoType;
+ UINT16 HdrLen;
+ UINT16 GsoSize;
+ UINT16 CsumStart;
+ UINT16 CsumOffset;
+} VIRTIO_NET_REQ;
+#pragma pack()
+
+//
+// Bits in VIRTIO_NET_REQ.Flags
+//
+#define VIRTIO_NET_HDR_F_NEEDS_CSUM BIT0
+
+//
+// Types/Bits for VIRTIO_NET_REQ.GsoType
+//
+#define VIRTIO_NET_HDR_GSO_NONE 0x00
+#define VIRTIO_NET_HDR_GSO_TCPV4 0x01
+#define VIRTIO_NET_HDR_GSO_UDP 0x03
+#define VIRTIO_NET_HDR_GSO_TCPV6 0x04
+#define VIRTIO_NET_HDR_GSO_ECN BIT7
+
+//
+// Link Status Bits in VIRTIO_NET_CONFIG.LinkStatus
+//
+#define VIRTIO_NET_S_LINK_UP BIT0
+#define VIRTIO_NET_S_ANNOUNCE BIT1
+
+#endif // _VIRTIO_NET_H_
diff --git BhyvePkg/Include/IndustryStandard/VirtioScsi.h BhyvePkg/Include/IndustryStandard/VirtioScsi.h
new file mode 100644
index 0000000..626cfaf
--- /dev/null
+++ BhyvePkg/Include/IndustryStandard/VirtioScsi.h
@@ -0,0 +1,100 @@
+/** @file
+
+ Virtio SCSI Host Device specific type and macro definitions corresponding to
+ the virtio-0.9.5 specification.
+
+ Copyright (C) 2012, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _VIRTIO_SCSI_H_
+#define _VIRTIO_SCSI_H_
+
+#include
+
+
+//
+// virtio-0.9.5, Appendix I: SCSI Host Device
+//
+#pragma pack(1)
+typedef struct {
+ VIRTIO_HDR Generic;
+ UINT32 VhdrNumQueues;
+ UINT32 VhdrSegMax;
+ UINT32 VhdrMaxSectors;
+ UINT32 VhdrCmdPerLun;
+ UINT32 VhdrEventInfoSize;
+ UINT32 VhdrSenseSize;
+ UINT32 VhdrCdbSize;
+ UINT16 VhdrMaxChannel;
+ UINT16 VhdrMaxTarget;
+ UINT32 VhdrMaxLun;
+} VSCSI_HDR;
+#pragma pack()
+
+#define OFFSET_OF_VSCSI(Field) OFFSET_OF (VSCSI_HDR, Field)
+#define SIZE_OF_VSCSI(Field) (sizeof ((VSCSI_HDR *) 0)->Field)
+
+#define VIRTIO_SCSI_F_INOUT BIT0
+#define VIRTIO_SCSI_F_HOTPLUG BIT1
+
+//
+// We expect these maximum sizes from the host. Also we force the CdbLength and
+// SenseDataLength parameters of EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() not
+// to exceed these limits. See UEFI 2.3.1 errata C 14.7.
+//
+#define VIRTIO_SCSI_CDB_SIZE 32
+#define VIRTIO_SCSI_SENSE_SIZE 96
+
+//
+// We pass the dynamically sized buffers ("dataout", "datain") in separate ring
+// descriptors.
+//
+#pragma pack(1)
+typedef struct {
+ UINT8 Lun[8];
+ UINT64 Id;
+ UINT8 TaskAttr;
+ UINT8 Prio;
+ UINT8 Crn;
+ UINT8 Cdb[VIRTIO_SCSI_CDB_SIZE];
+} VIRTIO_SCSI_REQ;
+
+typedef struct {
+ UINT32 SenseLen;
+ UINT32 Residual;
+ UINT16 StatusQualifier;
+ UINT8 Status;
+ UINT8 Response;
+ UINT8 Sense[VIRTIO_SCSI_SENSE_SIZE];
+} VIRTIO_SCSI_RESP;
+#pragma pack()
+
+//
+// selector of first virtio queue usable for request transfer
+//
+#define VIRTIO_SCSI_REQUEST_QUEUE 2
+
+//
+// host response codes
+//
+#define VIRTIO_SCSI_S_OK 0
+#define VIRTIO_SCSI_S_OVERRUN 1
+#define VIRTIO_SCSI_S_ABORTED 2
+#define VIRTIO_SCSI_S_BAD_TARGET 3
+#define VIRTIO_SCSI_S_RESET 4
+#define VIRTIO_SCSI_S_BUSY 5
+#define VIRTIO_SCSI_S_TRANSPORT_FAILURE 6
+#define VIRTIO_SCSI_S_TARGET_FAILURE 7
+#define VIRTIO_SCSI_S_NEXUS_FAILURE 8
+#define VIRTIO_SCSI_S_FAILURE 9
+
+#endif // _VIRTIO_SCSI_H_
diff --git BhyvePkg/Include/Library/BhyveFwCtlLib.h BhyvePkg/Include/Library/BhyveFwCtlLib.h
new file mode 100644
index 0000000..2e04863
--- /dev/null
+++ BhyvePkg/Include/Library/BhyveFwCtlLib.h
@@ -0,0 +1,52 @@
+/** @file
+ bhyve firmware configuration access
+
+ Copyright (c) 2015 Nahanni Systems
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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 BhyvePkg/Include/Library/NvVarsFileLib.h BhyvePkg/Include/Library/NvVarsFileLib.h
new file mode 100644
index 0000000..8525f3a
--- /dev/null
+++ BhyvePkg/Include/Library/NvVarsFileLib.h
@@ -0,0 +1,51 @@
+/** @file
+ Provides functions to save and restore NV variables in a file.
+
+ Copyright (c) 2009, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __NV_VARS_FILE_LIB__
+#define __NV_VARS_FILE_LIB__
+
+/**
+ Attempts to connect the NvVarsFileLib to the specified file system.
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return The EFI_STATUS while attempting to connect the NvVarsFileLib
+ to the file system instance.
+ @retval EFI_SUCCESS - The given file system was connected successfully
+
+**/
+EFI_STATUS
+EFIAPI
+ConnectNvVarsToFileSystem (
+ IN EFI_HANDLE FsHandle
+ );
+
+
+/**
+ Update non-volatile variables stored on the file system.
+
+ @return The EFI_STATUS while attempting to update the variable on
+ the connected file system.
+ @retval EFI_SUCCESS - The non-volatile variables were saved to the disk
+ @retval EFI_NOT_STARTED - A file system has not been connected
+
+**/
+EFI_STATUS
+EFIAPI
+UpdateNvVarsOnFileSystem (
+ );
+
+
+#endif
+
diff --git BhyvePkg/Include/Library/PlatformFvbLib.h BhyvePkg/Include/Library/PlatformFvbLib.h
new file mode 100644
index 0000000..b49cb87
--- /dev/null
+++ BhyvePkg/Include/Library/PlatformFvbLib.h
@@ -0,0 +1,87 @@
+/** @file
+ Library to define platform customization functions for a
+ Firmare Volume Block driver.
+
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PLATFORM_FVB_LIB__
+#define __PLATFORM_FVB_LIB__
+
+#include
+
+/**
+ This function will be called following a call to the
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL Read function.
+
+ @param[in] This The EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+ @param[in] Lba The starting logical block index
+ from which to read.
+ @param[in] Offset Offset into the block at which to begin reading.
+ @param[in] NumBytes The number of bytes read.
+ @param[in] Buffer Pointer to the buffer that was read, and will be
+ returned to the caller.
+
+**/
+VOID
+EFIAPI
+PlatformFvbDataRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN NumBytes,
+ IN UINT8 *Buffer
+ );
+
+
+/**
+ This function will be called following a call to the
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL Write function.
+
+ @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+ @param[in] Lba The starting logical block index to written to.
+ @param[in] Offset Offset into the block at which to begin writing.
+ @param[in] NumBytes The number of bytes written.
+ @param[in] Buffer Pointer to the buffer that was written.
+
+**/
+VOID
+EFIAPI
+PlatformFvbDataWritten (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN NumBytes,
+ IN UINT8 *Buffer
+ );
+
+
+/**
+ This function will be called following a call to the
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL Erase function.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
+ instance.
+ @param List The variable argument list as documented for
+ the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL Erase
+ function.
+
+**/
+VOID
+EFIAPI
+PlatformFvbBlocksErased (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN VA_LIST List
+ );
+
+
+#endif
+
diff --git BhyvePkg/Include/Library/SerializeVariablesLib.h BhyvePkg/Include/Library/SerializeVariablesLib.h
new file mode 100644
index 0000000..b3f7b86
--- /dev/null
+++ BhyvePkg/Include/Library/SerializeVariablesLib.h
@@ -0,0 +1,229 @@
+/** @file
+ Serialize & Deserialize UEFI Variables
+
+ Copyright (c) 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __SERIALIZE_VARIABLES_LIB__
+#define __SERIALIZE_VARIABLES_LIB__
+
+
+/**
+ Callback function for each variable
+
+ @param[in] Context - Context as sent to the iteration function
+ @param[in] VariableName - Refer to RuntimeServices GetNextVariableName
+ @param[in] VendorGuid - Refer to RuntimeServices GetNextVariableName
+ @param[in] Attributes - Refer to RuntimeServices GetVariable
+ @param[in] DataSize - Refer to RuntimeServices GetVariable
+ @param[in] Data - Refer to RuntimeServices GetVariable
+
+ @retval RETURN_SUCCESS Continue iterating through the variables
+ @return Any RETURN_ERROR Stop iterating through the variables
+
+**/
+typedef
+RETURN_STATUS
+(EFIAPI *VARIABLE_SERIALIZATION_ITERATION_CALLBACK)(
+ IN VOID *Context,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ );
+
+
+/**
+ Creates a new variable serialization instance
+
+ @param[out] Handle - Handle for a variable serialization instance
+
+ @retval RETURN_SUCCESS - The variable serialization instance was
+ successfully created.
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ create the variable serialization instance.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesNewInstance (
+ OUT EFI_HANDLE *Handle
+ );
+
+
+/**
+ Free memory associated with a variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+
+ @retval RETURN_SUCCESS - The variable serialization instance was
+ successfully freed.
+ @retval RETURN_INVALID_PARAMETER - Handle was not a valid
+ variable serialization instance.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesFreeInstance (
+ IN EFI_HANDLE Handle
+ );
+
+
+/**
+ Creates a new variable serialization instance using the given
+ binary representation of the variables to fill the new instance
+
+ @param[out] Handle - Handle for a variable serialization instance
+ @param[in] Buffer - A buffer with the serialized representation
+ of the variables. Must be the same format as produced
+ by SerializeVariablesToBuffer.
+ @param[in] Size - This is the size of the binary representation
+ of the variables.
+
+ @retval RETURN_SUCCESS - The binary representation was successfully
+ imported into a new variable serialization instance
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ create the new variable serialization instance
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesNewInstanceFromBuffer (
+ OUT EFI_HANDLE *Handle,
+ IN VOID *Buffer,
+ IN UINTN Size
+ );
+
+
+/**
+ Iterates all variables found with RuntimeServices GetNextVariableName
+
+ @param[in] CallbackFunction - Function called for each variable instance
+ @param[in] Context - Passed to each call of CallbackFunction
+
+ @retval RETURN_SUCCESS - All variables were iterated without the
+ CallbackFunction returning an error
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ iterate through the variables
+ @return Any of RETURN_ERROR indicates an error reading the variable
+ or an error was returned from CallbackFunction
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesIterateSystemVariables (
+ IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+ IN VOID *Context
+ );
+
+
+/**
+ Iterates all variables found in the variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+ @param[in] CallbackFunction - Function called for each variable instance
+ @param[in] Context - Passed to each call of CallbackFunction
+
+ @retval RETURN_SUCCESS - All variables were iterated without the
+ CallbackFunction returning an error
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ iterate through the variables
+ @return Any of RETURN_ERROR indicates an error reading the variable
+ or an error was returned from CallbackFunction
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesIterateInstanceVariables (
+ IN EFI_HANDLE Handle,
+ IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+ IN VOID *Context
+ );
+
+
+/**
+ Sets all variables found in the variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+
+ @retval RETURN_SUCCESS - All variables were set successfully
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ set all the variables
+ @return Any of RETURN_ERROR indicates an error reading the variables
+ or in attempting to set a variable
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesSetSerializedVariables (
+ IN EFI_HANDLE Handle
+ );
+
+
+/**
+ Adds a variable to the variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+ @param[in] VariableName - Refer to RuntimeServices GetVariable
+ @param[in] VendorGuid - Refer to RuntimeServices GetVariable
+ @param[in] Attributes - Refer to RuntimeServices GetVariable
+ @param[in] DataSize - Refer to RuntimeServices GetVariable
+ @param[in] Data - Refer to RuntimeServices GetVariable
+
+ @retval RETURN_SUCCESS - All variables were set successfully
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ add the variable
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesAddVariable (
+ IN EFI_HANDLE Handle,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ );
+
+
+/**
+ Serializes the variables known to this instance into the
+ provided buffer.
+
+ @param[in] Handle - Handle for a variable serialization instance
+ @param[out] Buffer - A buffer to store the binary representation
+ of the variables.
+ @param[in,out] Size - On input this is the size of the buffer.
+ On output this is the size of the binary representation
+ of the variables.
+
+ @retval RETURN_SUCCESS - The binary representation was successfully
+ completed and returned in the buffer.
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ save the variables to the buffer.
+ @retval RETURN_INVALID_PARAMETER - Handle was not a valid
+ variable serialization instance or
+ Size or Buffer were NULL.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesToBuffer (
+ IN EFI_HANDLE Handle,
+ OUT VOID *Buffer,
+ IN OUT UINTN *Size
+ );
+
+
+#endif
+
diff --git BhyvePkg/Include/Library/VirtioLib.h BhyvePkg/Include/Library/VirtioLib.h
new file mode 100644
index 0000000..141d680
--- /dev/null
+++ BhyvePkg/Include/Library/VirtioLib.h
@@ -0,0 +1,246 @@
+/** @file
+
+ Declarations of utility functions used by virtio device drivers.
+
+ Copyright (C) 2012, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _VIRTIO_LIB_H_
+#define _VIRTIO_LIB_H_
+
+#include
+#include
+
+/**
+
+ Write a word into Region 0 of the device specified by PciIo.
+
+ Region 0 must be an iomem region. This is an internal function for the
+ driver-specific VIRTIO_CFG_WRITE() macros.
+
+ @param[in] PciIo Target PCI device.
+
+ @param[in] FieldOffset Destination offset.
+
+ @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
+
+ @param[in] Value Little endian value to write, converted to UINT64.
+ The least significant FieldSize bytes will be used.
+
+
+ @return Status code returned by PciIo->Io.Write().
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioWrite (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINT64 Value
+ );
+
+
+/**
+
+ Read a word from Region 0 of the device specified by PciIo.
+
+ Region 0 must be an iomem region. This is an internal function for the
+ driver-specific VIRTIO_CFG_READ() macros.
+
+ @param[in] PciIo Source PCI device.
+
+ @param[in] FieldOffset Source offset.
+
+ @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.
+
+ @param[in] BufferSize Number of bytes available in the target buffer. Must
+ equal FieldSize.
+
+ @param[out] Buffer Target buffer.
+
+
+ @return Status code returned by PciIo->Io.Read().
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioRead (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ );
+
+
+/**
+
+ Configure a virtio ring.
+
+ This function sets up internal storage (the guest-host communication area)
+ and lays out several "navigation" (ie. no-ownership) pointers to parts of
+ that storage.
+
+ Relevant sections from the virtio-0.9.5 spec:
+ - 1.1 Virtqueues,
+ - 2.3 Virtqueue Configuration.
+
+ @param[in] The number of descriptors to allocate for the
+ virtio ring, as requested by the host.
+
+ @param[out] Ring The virtio ring to set up.
+
+ @retval EFI_OUT_OF_RESOURCES AllocatePages() failed to allocate contiguous
+ pages for the requested QueueSize. Fields of
+ Ring have indeterminate value.
+
+ @retval EFI_SUCCESS Allocation and setup successful. Ring->Base
+ (and nothing else) is responsible for
+ deallocation.
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioRingInit (
+ IN UINT16 QueueSize,
+ OUT VRING *Ring
+ );
+
+
+/**
+
+ Tear down the internal resources of a configured virtio ring.
+
+ The caller is responsible to stop the host from using this ring before
+ invoking this function: the VSTAT_DRIVER_OK bit must be clear in
+ VhdrDeviceStatus.
+
+ @param[out] Ring The virtio ring to clean up.
+
+**/
+VOID
+EFIAPI
+VirtioRingUninit (
+ IN OUT VRING *Ring
+ );
+
+
+//
+// Internal use structure for tracking the submission of a multi-descriptor
+// request.
+//
+typedef struct {
+ UINT16 HeadDescIdx;
+ UINT16 NextDescIdx;
+} DESC_INDICES;
+
+
+/**
+
+ Turn off interrupt notifications from the host, and prepare for appending
+ multiple descriptors to the virtio ring.
+
+ The calling driver must be in VSTAT_DRIVER_OK state.
+
+ @param[in,out] Ring The virtio ring we intend to append descriptors to.
+
+ @param[out] Indices The DESC_INDICES structure to initialize.
+
+**/
+VOID
+EFIAPI
+VirtioPrepare (
+ IN OUT VRING *Ring,
+ OUT DESC_INDICES *Indices
+ );
+
+
+/**
+
+ Append a contiguous buffer for transmission / reception via the virtio ring.
+
+ This function implements the following section from virtio-0.9.5:
+ - 2.4.1.1 Placing Buffers into the Descriptor Table
+
+ Free space is taken as granted, since the individual drivers support only
+ synchronous requests and host side status is processed in lock-step with
+ request submission. It is the calling driver's responsibility to verify the
+ ring size in advance.
+
+ The caller is responsible for initializing *Indices with VirtioPrepare()
+ first.
+
+ @param[in,out] Ring The virtio ring to append the buffer to, as a
+ descriptor.
+
+ @param[in] BufferPhysAddr (Guest pseudo-physical) start address of the
+ transmit / receive buffer.
+
+ @param[in] BufferSize Number of bytes to transmit or receive.
+
+ @param[in] Flags A bitmask of VRING_DESC_F_* flags. The caller
+ computes this mask dependent on further buffers to
+ append and transfer direction.
+ VRING_DESC_F_INDIRECT is unsupported. The
+ VRING_DESC.Next field is always set, but the host
+ only interprets it dependent on VRING_DESC_F_NEXT.
+
+ @param[in,out] Indices Indices->HeadDescIdx is not accessed.
+ On input, Indices->NextDescIdx identifies the next
+ descriptor to carry the buffer. On output,
+ Indices->NextDescIdx is incremented by one, modulo
+ 2^16.
+
+**/
+VOID
+EFIAPI
+VirtioAppendDesc (
+ IN OUT VRING *Ring,
+ IN UINTN BufferPhysAddr,
+ IN UINT32 BufferSize,
+ IN UINT16 Flags,
+ IN OUT DESC_INDICES *Indices
+ );
+
+
+/**
+
+ Notify the host about the descriptor chain just built, and wait until the
+ host processes it.
+
+ @param[in] PciIo The target virtio PCI device to notify.
+
+ @param[in] VirtQueueId Identifies the queue for the target device.
+
+ @param[in,out] Ring The virtio ring with descriptors to submit.
+
+ @param[in] Indices Indices->NextDescIdx is not accessed.
+ Indices->HeadDescIdx identifies the head descriptor
+ of the descriptor chain.
+
+
+ @return Error code from VirtioWrite() if it fails.
+
+ @retval EFI_SUCCESS Otherwise, the host processed all descriptors.
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioFlush (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 VirtQueueId,
+ IN OUT VRING *Ring,
+ IN DESC_INDICES *Indices
+ );
+
+#endif // _VIRTIO_LIB_H_
diff --git BhyvePkg/Include/Protocol/BlockMmio.h BhyvePkg/Include/Protocol/BlockMmio.h
new file mode 100644
index 0000000..b8a657b
--- /dev/null
+++ BhyvePkg/Include/Protocol/BlockMmio.h
@@ -0,0 +1,50 @@
+/** @file
+ Block IO (memory mapped)
+
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __BLOCK_MMIO_H__
+#define __BLOCK_MMIO_H__
+
+#include
+
+#define BLOCK_MMIO_PROTOCOL_GUID \
+ { \
+ 0x6b558ce3, 0x69e5, 0x4c67, {0xa6, 0x34, 0xf7, 0xfe, 0x72, 0xad, 0xbe, 0x84 } \
+ }
+
+typedef struct _BLOCK_MMIO_PROTOCOL BLOCK_MMIO_PROTOCOL;
+
+
+///
+/// This protocol provides control over block devices.
+///
+struct _BLOCK_MMIO_PROTOCOL {
+ ///
+ /// The revision to which the block IO interface adheres. All future
+ /// revisions must be backwards compatible. If a future version is not
+ /// back wards compatible, it is not the same GUID.
+ ///
+ UINT64 Revision;
+ ///
+ /// Pointer to the EFI_BLOCK_IO_MEDIA data for this device.
+ ///
+ EFI_BLOCK_IO_MEDIA *Media;
+
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+
+};
+
+extern EFI_GUID gBlockMmioProtocolGuid;
+
+#endif
+
diff --git BhyvePkg/Library/AcpiTimerLib/AcpiTimerLib.c BhyvePkg/Library/AcpiTimerLib/AcpiTimerLib.c
new file mode 100644
index 0000000..f9ddd95
--- /dev/null
+++ BhyvePkg/Library/AcpiTimerLib/AcpiTimerLib.c
@@ -0,0 +1,308 @@
+/** @file
+ ACPI Timer implements one instance of Timer Library.
+
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2011, Andrei Warkentin
+
+ This program and the accompanying materials are
+ licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//
+// PCI Location of PIIX4 Power Management PCI Configuration Registers
+//
+#define PIIX4_POWER_MANAGEMENT_BUS 0x00
+#define PIIX4_POWER_MANAGEMENT_DEVICE 0x01
+#define PIIX4_POWER_MANAGEMENT_FUNCTION 0x03
+
+//
+// Macro to access PIIX4 Power Management PCI Configuration Registers
+//
+#define PIIX4_PCI_POWER_MANAGEMENT_REGISTER(Register) \
+ PCI_LIB_ADDRESS ( \
+ PIIX4_POWER_MANAGEMENT_BUS, \
+ PIIX4_POWER_MANAGEMENT_DEVICE, \
+ PIIX4_POWER_MANAGEMENT_FUNCTION, \
+ Register \
+ )
+
+//
+// PIIX4 Power Management PCI Configuration Registers
+//
+#define PMBA PIIX4_PCI_POWER_MANAGEMENT_REGISTER (0x40)
+#define PMBA_RTE BIT0
+#define PMREGMISC PIIX4_PCI_POWER_MANAGEMENT_REGISTER (0x80)
+#define PMIOSE BIT0
+
+//
+// The ACPI Time in the PIIX4 is a 24-bit counter
+//
+#define ACPI_TIMER_COUNT_SIZE BIT24
+
+//
+// Offset in the PIIX4 Power Management Base Address to the ACPI Timer
+//
+#define ACPI_TIMER_OFFSET 0x8
+
+/**
+ The constructor function enables ACPI IO space.
+
+ If ACPI I/O space not enabled, this function will enable it.
+ It will always return RETURN_SUCCESS.
+
+ @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
+
+**/
+RETURN_STATUS
+EFIAPI
+AcpiTimerLibConstructor (
+ VOID
+ )
+{
+ //
+ // Check to see if the PIIX4 Power Management Base Address is already enabled
+ //
+ if ((PciRead8 (PMREGMISC) & PMIOSE) == 0) {
+ //
+ // If the PIIX4 Power Management Base Address is not programmed,
+ // then program the PIIX4 Power Management Base Address from a PCD.
+ //
+ PciAndThenOr32 (PMBA, (UINT32)(~0x0000FFC0), PcdGet16 (PcdAcpiPmBaseAddress));
+
+ //
+ // Enable PMBA I/O port decodes in PMREGMISC
+ //
+ PciOr8 (PMREGMISC, PMIOSE);
+ }
+
+ return RETURN_SUCCESS;
+}
+
+/**
+ Internal function to read the current tick counter of ACPI.
+
+ Internal function to read the current tick counter of ACPI.
+
+ @return The tick counter read.
+
+**/
+UINT32
+InternalAcpiGetTimerTick (
+ VOID
+ )
+{
+#ifdef NOT_BHYVE
+ //
+ // Read PMBA to read and return the current ACPI timer value.
+ //
+ return IoRead32 ((PciRead32 (PMBA) & ~PMBA_RTE) + ACPI_TIMER_OFFSET);
+#else
+ return IoRead32 (0x408);
+#endif
+}
+
+/**
+ Stalls the CPU for at least the given number of ticks.
+
+ Stalls the CPU for at least the given number of ticks. It's invoked by
+ MicroSecondDelay() and NanoSecondDelay().
+
+ @param Delay A period of time to delay in ticks.
+
+**/
+VOID
+InternalAcpiDelay (
+ IN UINT32 Delay
+ )
+{
+ UINT32 Ticks;
+ UINT32 Times;
+
+ Times = Delay >> 22;
+ Delay &= BIT22 - 1;
+ do {
+ //
+ // The target timer count is calculated here
+ //
+ Ticks = InternalAcpiGetTimerTick () + Delay;
+ Delay = BIT22;
+ //
+ // Wait until time out
+ // Delay >= 2^23 could not be handled by this function
+ // Timer wrap-arounds are handled correctly by this function
+ //
+ while (((Ticks - InternalAcpiGetTimerTick ()) & BIT23) == 0) {
+ CpuPause ();
+ }
+ } while (Times-- > 0);
+}
+
+/**
+ Stalls the CPU for at least the given number of microseconds.
+
+ Stalls the CPU for the number of microseconds specified by MicroSeconds.
+
+ @param MicroSeconds The minimum number of microseconds to delay.
+
+ @return MicroSeconds
+
+**/
+UINTN
+EFIAPI
+MicroSecondDelay (
+ IN UINTN MicroSeconds
+ )
+{
+ InternalAcpiDelay (
+ (UINT32)DivU64x32 (
+ MultU64x32 (
+ MicroSeconds,
+ ACPI_TIMER_FREQUENCY
+ ),
+ 1000000u
+ )
+ );
+ return MicroSeconds;
+}
+
+/**
+ Stalls the CPU for at least the given number of nanoseconds.
+
+ Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
+
+ @param NanoSeconds The minimum number of nanoseconds to delay.
+
+ @return NanoSeconds
+
+**/
+UINTN
+EFIAPI
+NanoSecondDelay (
+ IN UINTN NanoSeconds
+ )
+{
+ InternalAcpiDelay (
+ (UINT32)DivU64x32 (
+ MultU64x32 (
+ NanoSeconds,
+ ACPI_TIMER_FREQUENCY
+ ),
+ 1000000000u
+ )
+ );
+ return NanoSeconds;
+}
+
+/**
+ Retrieves the current value of a 64-bit free running performance counter.
+
+ Retrieves the current value of a 64-bit free running performance counter. The
+ counter can either count up by 1 or count down by 1. If the physical
+ performance counter counts by a larger increment, then the counter values
+ must be translated. The properties of the counter can be retrieved from
+ GetPerformanceCounterProperties().
+
+ @return The current value of the free running performance counter.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounter (
+ VOID
+ )
+{
+ return (UINT64)InternalAcpiGetTimerTick ();
+}
+
+/**
+ Retrieves the 64-bit frequency in Hz and the range of performance counter
+ values.
+
+ If StartValue is not NULL, then the value that the performance counter starts
+ with immediately after is it rolls over is returned in StartValue. If
+ EndValue is not NULL, then the value that the performance counter end with
+ immediately before it rolls over is returned in EndValue. The 64-bit
+ frequency of the performance counter in Hz is always returned. If StartValue
+ is less than EndValue, then the performance counter counts up. If StartValue
+ is greater than EndValue, then the performance counter counts down. For
+ example, a 64-bit free running counter that counts up would have a StartValue
+ of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
+ that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
+
+ @param StartValue The value the performance counter starts with when it
+ rolls over.
+ @param EndValue The value that the performance counter ends with before
+ it rolls over.
+
+ @return The frequency in Hz.
+
+**/
+UINT64
+EFIAPI
+GetPerformanceCounterProperties (
+ OUT UINT64 *StartValue, OPTIONAL
+ OUT UINT64 *EndValue OPTIONAL
+ )
+{
+ if (StartValue != NULL) {
+ *StartValue = 0;
+ }
+
+ if (EndValue != NULL) {
+ *EndValue = ACPI_TIMER_COUNT_SIZE - 1;
+ }
+
+ return ACPI_TIMER_FREQUENCY;
+}
+
+/**
+ Converts elapsed ticks of performance counter to time in nanoseconds.
+
+ This function converts the elapsed ticks of running performance counter to
+ time value in unit of nanoseconds.
+
+ @param Ticks The number of elapsed ticks of running performance counter.
+
+ @return The elapsed time in nanoseconds.
+
+**/
+UINT64
+EFIAPI
+GetTimeInNanoSecond (
+ IN UINT64 Ticks
+ )
+{
+ UINT64 NanoSeconds;
+ UINT32 Remainder;
+
+ //
+ // Ticks
+ // Time = --------- x 1,000,000,000
+ // Frequency
+ //
+ NanoSeconds = MultU64x32 (DivU64x32Remainder (Ticks, ACPI_TIMER_FREQUENCY, &Remainder), 1000000000u);
+
+ //
+ // Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000)
+ // will not overflow 64-bit.
+ //
+ NanoSeconds += DivU64x32 (MultU64x32 ((UINT64) Remainder, 1000000000u), ACPI_TIMER_FREQUENCY);
+
+ return NanoSeconds;
+}
diff --git BhyvePkg/Library/AcpiTimerLib/AcpiTimerLib.inf BhyvePkg/Library/AcpiTimerLib/AcpiTimerLib.inf
new file mode 100644
index 0000000..58ca7c6
--- /dev/null
+++ BhyvePkg/Library/AcpiTimerLib/AcpiTimerLib.inf
@@ -0,0 +1,44 @@
+## @file
+# ACPI Timer Library Instance.
+#
+# Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = AcpiTimerLib
+ FILE_GUID = CDD9D74F-213E-4c28-98F7-8B4A167DB936
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = TimerLib
+
+ CONSTRUCTOR = AcpiTimerLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ AcpiTimerLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BhyvePkg/BhyvePkg.dec
+
+[Pcd]
+ gUefiBhyvePkgTokenSpaceGuid.PcdAcpiPmBaseAddress
+
+[LibraryClasses]
+ BaseLib
+ PciLib
+ IoLib
diff --git BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c
new file mode 100644
index 0000000..5cc87af
--- /dev/null
+++ BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c
@@ -0,0 +1,430 @@
+/** @file
+
+ Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.
+ Copyright (C) 2013, Red Hat, Inc.
+ Copyright (c) 2015, Nahanni Systems.
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Uefi.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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;
+ INTN 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;
+ INTN oLen, remLen, 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 ((EFI_D_INFO, "FwCtlInitialize\n"));
+
+ IoWrite16 (FW_PORT, 0x0000);
+ for (i = 0; i < 4; i++) {
+ ch = IoRead8 (FW_IPORT);
+ if (ch != mBhyveSig[i]) {
+ DEBUG ((EFI_D_INFO, "Host f/w sig mismatch %c/%c\n", ch, mBhyveSig[i]));
+ return RETURN_SUCCESS;
+ }
+ }
+
+ mBhyveFwCtlSupported = TRUE;
+
+ return RETURN_SUCCESS;
+}
diff --git BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
new file mode 100644
index 0000000..7eccfd0
--- /dev/null
+++ BhyvePkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
@@ -0,0 +1,45 @@
+## @file
+#
+# Copyright (C) 2015 Nahanni Systems
+# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BhyveFwCtlLib
+ FILE_GUID = fd982666-67f9-11e5-a42a-0025908602f6
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BhyveFwCtlLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER
+
+ CONSTRUCTOR = BhyveFwCtlInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources]
+ BhyveFwCtlLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BhyvePkg/BhyvePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ IoLib
+ MemoryAllocationLib
+
diff --git BhyvePkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.c BhyvePkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.c
new file mode 100644
index 0000000..6efb723
--- /dev/null
+++ BhyvePkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.c
@@ -0,0 +1,103 @@
+/** @file
+ OVMF platform customization for EMU Variable FVB driver
+
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PiDxe.h"
+#include
+#include
+#include
+#include
+#include
+
+
+/**
+ This function will be called following a call to the
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL Read function.
+
+ @param[in] This The EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+ @param[in] Lba The starting logical block index
+ from which to read.
+ @param[in] Offset Offset into the block at which to begin reading.
+ @param[in] NumBytes The number of bytes read.
+ @param[in] Buffer Pointer to the buffer that was read, and will be
+ returned to the caller.
+
+**/
+VOID
+EFIAPI
+PlatformFvbDataRead (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+}
+
+
+/**
+ This function will be called following a call to the
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL Write function.
+
+ @param[in] This EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
+ @param[in] Lba The starting logical block index to written to.
+ @param[in] Offset Offset into the block at which to begin writing.
+ @param[in] NumBytes The number of bytes written.
+ @param[in] Buffer Pointer to the buffer that was written.
+
+**/
+VOID
+EFIAPI
+PlatformFvbDataWritten (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN EFI_LBA Lba,
+ IN UINTN Offset,
+ IN UINTN NumBytes,
+ IN UINT8 *Buffer
+ )
+{
+ STATIC EFI_EVENT EventToSignal = NULL;
+
+ if (!EfiAtRuntime ()) {
+ if (EventToSignal == NULL) {
+ EventToSignal = (EFI_EVENT)(UINTN) PcdGet64 (PcdEmuVariableEvent);
+ }
+ if (EventToSignal != NULL) {
+ gBS->SignalEvent (EventToSignal);
+ }
+ }
+}
+
+
+/**
+ This function will be called following a call to the
+ EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL Erase function.
+
+ @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
+ instance.
+ @param List The variable argument list as documented for
+ the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL Erase
+ function.
+
+**/
+VOID
+EFIAPI
+PlatformFvbBlocksErased (
+ IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This,
+ IN VA_LIST List
+ )
+{
+}
+
+
diff --git BhyvePkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf BhyvePkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf
new file mode 100644
index 0000000..a77cf88
--- /dev/null
+++ BhyvePkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf
@@ -0,0 +1,48 @@
+## @file
+# OVMF platform customization for EMU Variable FVB driver
+#
+# This library handles hooks for the EMU Variable FVB driver.
+#
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = EmuVariableFvbLib
+ FILE_GUID = 8a6062ed-7140-4a74-b4ea-fe900e79e24b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformFvbLib|DXE_RUNTIME_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ EmuVariableFvbLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ BhyvePkg/BhyvePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+
+[Pcd]
+ gUefiBhyvePkgTokenSpaceGuid.PcdEmuVariableEvent
+
diff --git BhyvePkg/Library/NvVarsFileLib/FsAccess.c BhyvePkg/Library/NvVarsFileLib/FsAccess.c
new file mode 100644
index 0000000..937e4ab
--- /dev/null
+++ BhyvePkg/Library/NvVarsFileLib/FsAccess.c
@@ -0,0 +1,515 @@
+/** @file
+ File System Access for NvVarsFileLib
+
+ Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "NvVarsFileLib.h"
+
+#include
+#include
+#include
+
+
+/**
+ Open the NvVars file for reading or writing
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+ @param[in] ReadingFile - TRUE: open the file for reading. FALSE: writing
+ @param[out] NvVarsFile - If EFI_SUCCESS is returned, then this is updated
+ with the opened NvVars file.
+
+ @return EFI_SUCCESS if the file was opened
+
+**/
+EFI_STATUS
+GetNvVarsFile (
+ IN EFI_HANDLE FsHandle,
+ IN BOOLEAN ReadingFile,
+ OUT EFI_FILE_HANDLE *NvVarsFile
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs;
+ EFI_FILE_HANDLE Root;
+
+ //
+ // Get the FileSystem protocol on that handle
+ //
+ Status = gBS->HandleProtocol (
+ FsHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID **)&Fs
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get the volume (the root directory)
+ //
+ Status = Fs->OpenVolume (Fs, &Root);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Attempt to open the NvVars file in the root directory
+ //
+ Status = Root->Open (
+ Root,
+ NvVarsFile,
+ L"NvVars",
+ ReadingFile ?
+ EFI_FILE_MODE_READ :
+ (
+ EFI_FILE_MODE_CREATE |
+ EFI_FILE_MODE_READ |
+ EFI_FILE_MODE_WRITE
+ ),
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return Status;
+}
+
+
+/**
+ Open the NvVars file for reading or writing
+
+ @param[in] File - The file to inspect
+ @param[out] Exists - Returns whether the file exists
+ @param[out] Size - Returns the size of the file
+ (0 if the file does not exist)
+
+**/
+VOID
+NvVarsFileReadCheckup (
+ IN EFI_FILE_HANDLE File,
+ OUT BOOLEAN *Exists,
+ OUT UINTN *Size
+ )
+{
+ EFI_FILE_INFO *FileInfo;
+
+ *Exists = FALSE;
+ *Size = 0;
+
+ FileInfo = FileHandleGetInfo (File);
+ if (FileInfo == NULL) {
+ return;
+ }
+
+ if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) != 0) {
+ FreePool (FileInfo);
+ return;
+ }
+
+ *Exists = TRUE;
+ *Size = (UINTN) FileInfo->FileSize;
+
+ FreePool (FileInfo);
+}
+
+
+/**
+ Open the NvVars file for reading or writing
+
+ @param[in] File - The file to inspect
+ @param[out] Exists - Returns whether the file exists
+ @param[out] Size - Returns the size of the file
+ (0 if the file does not exist)
+
+**/
+EFI_STATUS
+FileHandleEmpty (
+ IN EFI_FILE_HANDLE File
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_INFO *FileInfo;
+
+ //
+ // Retrieve the FileInfo structure
+ //
+ FileInfo = FileHandleGetInfo (File);
+ if (FileInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If the path is a directory, then return an error
+ //
+ if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) != 0) {
+ FreePool (FileInfo);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If the file size is already 0, then it is empty, so
+ // we can return success.
+ //
+ if (FileInfo->FileSize == 0) {
+ FreePool (FileInfo);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Set the file size to 0.
+ //
+ FileInfo->FileSize = 0;
+ Status = FileHandleSetInfo (File, FileInfo);
+
+ FreePool (FileInfo);
+
+ return Status;
+}
+
+
+/**
+ Reads a file to a newly allocated buffer
+
+ @param[in] File - The file to read
+ @param[in] ReadSize - The size of data to read from the file
+
+ @return Pointer to buffer allocated to hold the file
+ contents. NULL if an error occured.
+
+**/
+VOID*
+FileHandleReadToNewBuffer (
+ IN EFI_FILE_HANDLE FileHandle,
+ IN UINTN ReadSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN ActualReadSize;
+ VOID *FileContents;
+
+ ActualReadSize = ReadSize;
+ FileContents = AllocatePool (ReadSize);
+ if (FileContents != NULL) {
+ Status = FileHandleRead (
+ FileHandle,
+ &ReadSize,
+ FileContents
+ );
+ if (EFI_ERROR (Status) || (ActualReadSize != ReadSize)) {
+ FreePool (FileContents);
+ return NULL;
+ }
+ }
+
+ return FileContents;
+}
+
+
+/**
+ Reads the contents of the NvVars file on the file system
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return EFI_STATUS based on the success or failure of the file read
+
+**/
+EFI_STATUS
+ReadNvVarsFile (
+ IN EFI_HANDLE FsHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_HANDLE File;
+ UINTN FileSize;
+ BOOLEAN FileExists;
+ VOID *FileContents;
+ EFI_HANDLE SerializedVariables;
+
+ Status = GetNvVarsFile (FsHandle, TRUE, &File);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "FsAccess.c: Could not open NV Variables file on this file system\n"));
+ return Status;
+ }
+
+ NvVarsFileReadCheckup (File, &FileExists, &FileSize);
+ if (FileSize == 0) {
+ FileHandleClose (File);
+ return EFI_UNSUPPORTED;
+ }
+
+ FileContents = FileHandleReadToNewBuffer (File, FileSize);
+ if (FileContents == NULL) {
+ FileHandleClose (File);
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((
+ EFI_D_INFO,
+ "FsAccess.c: Read %d bytes from NV Variables file\n",
+ FileSize
+ ));
+
+ Status = SerializeVariablesNewInstanceFromBuffer (
+ &SerializedVariables,
+ FileContents,
+ FileSize
+ );
+ if (!RETURN_ERROR (Status)) {
+ Status = SerializeVariablesSetSerializedVariables (SerializedVariables);
+ }
+
+ FreePool (FileContents);
+ FileHandleClose (File);
+
+ return Status;
+}
+
+
+/**
+ Writes a variable to indicate that the NV variables
+ have been loaded from the file system.
+
+**/
+STATIC
+VOID
+SetNvVarsVariable (
+ VOID
+ )
+{
+ BOOLEAN VarData;
+ UINTN Size;
+
+ //
+ // Write a variable to indicate we've already loaded the
+ // variable data. If it is found, we skip the loading on
+ // subsequent attempts.
+ //
+ Size = sizeof (VarData);
+ VarData = TRUE;
+ gRT->SetVariable (
+ L"NvVars",
+ &gEfiSimpleFileSystemProtocolGuid,
+ EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ Size,
+ (VOID*) &VarData
+ );
+}
+
+
+/**
+ Loads the non-volatile variables from the NvVars file on the
+ given file system.
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return EFI_STATUS based on the success or failure of load operation
+
+**/
+EFI_STATUS
+LoadNvVarsFromFs (
+ EFI_HANDLE FsHandle
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN VarData;
+ UINTN Size;
+
+ DEBUG ((EFI_D_INFO, "FsAccess.c: LoadNvVarsFromFs\n"));
+
+ //
+ // We write a variable to indicate we've already loaded the
+ // variable data. If it is found, we skip the loading.
+ //
+ // This is relevent if the non-volatile variable have been
+ // able to survive a reboot operation. In that case, we don't
+ // want to re-load the file as it would overwrite newer changes
+ // made to the variables.
+ //
+ Size = sizeof (VarData);
+ VarData = TRUE;
+ Status = gRT->GetVariable (
+ L"NvVars",
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &Size,
+ (VOID*) &VarData
+ );
+ if (Status == EFI_SUCCESS) {
+ DEBUG ((EFI_D_INFO, "NV Variables were already loaded\n"));
+ return EFI_ALREADY_STARTED;
+ }
+
+ //
+ // Attempt to restore the variables from the NvVars file.
+ //
+ Status = ReadNvVarsFile (FsHandle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Error while restoring NV variable data\n"));
+ return Status;
+ }
+
+ //
+ // Write a variable to indicate we've already loaded the
+ // variable data. If it is found, we skip the loading on
+ // subsequent attempts.
+ //
+ SetNvVarsVariable();
+
+ DEBUG ((
+ EFI_D_INFO,
+ "FsAccess.c: Read NV Variables file (size=%d)\n",
+ Size
+ ));
+
+ return Status;
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackAddAllNvVariables (
+ IN VOID *Context,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ EFI_HANDLE Instance;
+
+ Instance = (EFI_HANDLE) Context;
+
+ //
+ // Only save non-volatile variables
+ //
+ if ((Attributes & EFI_VARIABLE_NON_VOLATILE) == 0) {
+ return RETURN_SUCCESS;
+ }
+
+ return SerializeVariablesAddVariable (
+ Instance,
+ VariableName,
+ VendorGuid,
+ Attributes,
+ DataSize,
+ Data
+ );
+}
+
+
+/**
+ Saves the non-volatile variables into the NvVars file on the
+ given file system.
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return EFI_STATUS based on the success or failure of load operation
+
+**/
+EFI_STATUS
+SaveNvVarsToFs (
+ EFI_HANDLE FsHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_HANDLE File;
+ UINTN WriteSize;
+ UINTN VariableDataSize;
+ VOID *VariableData;
+ EFI_HANDLE SerializedVariables;
+
+ Status = SerializeVariablesNewInstance (&SerializedVariables);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SerializeVariablesIterateSystemVariables (
+ IterateVariablesCallbackAddAllNvVariables,
+ (VOID*) SerializedVariables
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ VariableData = NULL;
+ VariableDataSize = 0;
+ Status = SerializeVariablesToBuffer (
+ SerializedVariables,
+ NULL,
+ &VariableDataSize
+ );
+ if (Status == RETURN_BUFFER_TOO_SMALL) {
+ VariableData = AllocatePool (VariableDataSize);
+ if (VariableData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ Status = SerializeVariablesToBuffer (
+ SerializedVariables,
+ VariableData,
+ &VariableDataSize
+ );
+ }
+ }
+
+ SerializeVariablesFreeInstance (SerializedVariables);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Open the NvVars file for writing.
+ //
+ Status = GetNvVarsFile (FsHandle, FALSE, &File);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "FsAccess.c: Unable to open file to saved NV Variables\n"));
+ return Status;
+ }
+
+ //
+ // Empty the starting file contents.
+ //
+ Status = FileHandleEmpty (File);
+ if (EFI_ERROR (Status)) {
+ FileHandleClose (File);
+ return Status;
+ }
+
+ WriteSize = VariableDataSize;
+ Status = FileHandleWrite (File, &WriteSize, VariableData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ FileHandleClose (File);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Write a variable to indicate we've already loaded the
+ // variable data. If it is found, we skip the loading on
+ // subsequent attempts.
+ //
+ SetNvVarsVariable();
+
+ DEBUG ((EFI_D_INFO, "Saved NV Variables to NvVars file\n"));
+ }
+
+ return Status;
+
+}
+
+
diff --git BhyvePkg/Library/NvVarsFileLib/NvVarsFileLib.c BhyvePkg/Library/NvVarsFileLib/NvVarsFileLib.c
new file mode 100644
index 0000000..c89bb4a
--- /dev/null
+++ BhyvePkg/Library/NvVarsFileLib/NvVarsFileLib.c
@@ -0,0 +1,83 @@
+/** @file
+ Save Non-Volatile Variables to a file system.
+
+ Copyright (c) 2009, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "NvVarsFileLib.h"
+#include
+#include
+
+EFI_HANDLE mNvVarsFileLibFsHandle = NULL;
+
+
+/**
+ Attempts to connect the NvVarsFileLib to the specified file system.
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return The EFI_STATUS while attempting to connect the NvVarsFileLib
+ to the file system instance.
+ @retval EFI_SUCCESS - The given file system was connected successfully
+
+**/
+EFI_STATUS
+EFIAPI
+ConnectNvVarsToFileSystem (
+ IN EFI_HANDLE FsHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // We might fail to load the variable, since the file system initially
+ // will not have the NvVars file.
+ //
+ LoadNvVarsFromFs (FsHandle);
+
+ //
+ // We must be able to save the variables successfully to the file system
+ // to have connected successfully.
+ //
+ Status = SaveNvVarsToFs (FsHandle);
+ if (!EFI_ERROR (Status)) {
+ mNvVarsFileLibFsHandle = FsHandle;
+ }
+
+ return Status;
+}
+
+
+/**
+ Update non-volatile variables stored on the file system.
+
+ @return The EFI_STATUS while attempting to update the variable on
+ the connected file system.
+ @retval EFI_SUCCESS - The non-volatile variables were saved to the disk
+ @retval EFI_NOT_STARTED - A file system has not been connected
+
+**/
+EFI_STATUS
+EFIAPI
+UpdateNvVarsOnFileSystem (
+ )
+{
+ if (mNvVarsFileLibFsHandle == NULL) {
+ //
+ // A file system had not been connected to the library.
+ //
+ return EFI_NOT_STARTED;
+ } else {
+ return SaveNvVarsToFs (mNvVarsFileLibFsHandle);
+ }
+}
+
+
diff --git BhyvePkg/Library/NvVarsFileLib/NvVarsFileLib.h BhyvePkg/Library/NvVarsFileLib/NvVarsFileLib.h
new file mode 100644
index 0000000..ac3a3d6
--- /dev/null
+++ BhyvePkg/Library/NvVarsFileLib/NvVarsFileLib.h
@@ -0,0 +1,61 @@
+/** @file
+ Save Non-Volatile Variables to a file system.
+
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __NV_VARS_FILE_LIB_INSTANCE__
+#define __NV_VARS_FILE_LIB_INSTANCE__
+
+#include
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+/**
+ Loads the non-volatile variables from the NvVars file on the
+ given file system.
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return EFI_STATUS based on the success or failure of load operation
+
+**/
+EFI_STATUS
+LoadNvVarsFromFs (
+ EFI_HANDLE FsHandle
+ );
+
+
+/**
+ Saves the non-volatile variables into the NvVars file on the
+ given file system.
+
+ @param[in] FsHandle - Handle for a gEfiSimpleFileSystemProtocolGuid instance
+
+ @return EFI_STATUS based on the success or failure of load operation
+
+**/
+EFI_STATUS
+SaveNvVarsToFs (
+ EFI_HANDLE FsHandle
+ );
+
+#endif
+
diff --git BhyvePkg/Library/NvVarsFileLib/NvVarsFileLib.inf BhyvePkg/Library/NvVarsFileLib/NvVarsFileLib.inf
new file mode 100644
index 0000000..488f134
--- /dev/null
+++ BhyvePkg/Library/NvVarsFileLib/NvVarsFileLib.inf
@@ -0,0 +1,60 @@
+## @file
+# NvVarsFileLib
+#
+# This library saves and restores non-volatile variables in a
+# file within a file system.
+#
+# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = NvVarsFileLib
+ FILE_GUID = 9172fe8b-9a36-40f8-bba5-5e57a44390bd
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NvVarsFileLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ FsAccess.c
+ NvVarsFileLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ BhyvePkg/BhyvePkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ FileHandleLib
+ MemoryAllocationLib
+ SerializeVariablesLib
+
+[Protocols]
+ gEfiSimpleFileSystemProtocolGuid ## CONSUMES
+
+
+[Guids]
+ gEfiFileInfoGuid
+
+[Depex]
+ gEfiVariableWriteArchProtocolGuid
+
diff --git BhyvePkg/Library/PlatformBdsLib/BdsPlatform.c BhyvePkg/Library/PlatformBdsLib/BdsPlatform.c
new file mode 100644
index 0000000..c0c41c6
--- /dev/null
+++ BhyvePkg/Library/PlatformBdsLib/BdsPlatform.c
@@ -0,0 +1,1503 @@
+/** @file
+ Platform BDS customizations.
+
+ Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BdsPlatform.h"
+
+#include
+
+//
+// Global data
+//
+
+VOID *mEfiDevPathNotifyReg;
+EFI_EVENT mEfiDevPathEvent;
+VOID *mEmuVariableEventReg;
+EFI_EVENT mEmuVariableEvent;
+BOOLEAN mDetectVgaOnly;
+
+
+// Maintain a reference to the original HandleProtocol function
+STATIC EFI_HANDLE_PROTOCOL gBS_HandleProtocol;
+
+
+//
+// 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
+ );
+
+//
+// BDS Platform Functions
+//
+VOID
+EFIAPI
+PlatformBdsInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Platform Bds init. Incude the platform firmware vendor, revision
+ and so crc check.
+
+Arguments:
+
+Returns:
+
+ None.
+
+--*/
+{
+ DEBUG ((EFI_D_INFO, "PlatformBdsInit\n"));
+ InstallDevicePathCallback ();
+}
+
+
+EFI_STATUS
+ConnectRootBridge (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Connect RootBridge
+
+Arguments:
+
+ None.
+
+Returns:
+
+ EFI_SUCCESS - Connect RootBridge successfully.
+ EFI_STATUS - Connect RootBridge fail.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_HANDLE RootHandle;
+
+ //
+ // Make all the PCI_IO protocols on PCI Seg 0 show up
+ //
+ BdsLibConnectDevicePath (gPlatformRootBridges[0]);
+
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &gPlatformRootBridges[0],
+ &RootHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+PrepareLpcBridgeDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+/*++
+
+Routine Description:
+
+ Add IsaKeyboard to ConIn,
+ add IsaSerial to ConOut, ConIn, ErrOut.
+ LPC Bridge: 06 01 00
+
+Arguments:
+
+ DeviceHandle - Handle of PCIIO protocol.
+
+Returns:
+
+ EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
+ EFI_STATUS - No LPC bridge is added.
+
+--*/
+{
+ 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);
+
+ BdsLibUpdateConsoleVariable (VarConsoleInp, 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 = DevicePathToStr(DevicePath);
+ if (DevPathStr != NULL) {
+ DEBUG((
+ EFI_D_INFO,
+ "BdsPlatform.c+%d: COM%d DevPath: %s\n",
+ __LINE__,
+ gPnp16550ComPortDeviceNode.UID + 1,
+ DevPathStr
+ ));
+ FreePool(DevPathStr);
+ }
+
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarErrorOut, 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 dirver 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 futhure, 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.
+ //
+ BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);
+ BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);
+ }
+ }
+ gBS->FreePool (GopHandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PreparePciVgaDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+/*++
+
+Routine Description:
+
+ Add PCI VGA to ConOut.
+ PCI VGA: 03 00 00
+
+Arguments:
+
+ DeviceHandle - Handle of PCIIO protocol.
+
+Returns:
+
+ EFI_SUCCESS - PCI VGA is added to ConOut.
+ EFI_STATUS - No PCI VGA device is added.
+
+--*/
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ GetGopDevicePath (DevicePath, &GopDevicePath);
+ DevicePath = GopDevicePath;
+
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+PreparePciSerialDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+/*++
+
+Routine Description:
+
+ Add PCI Serial to ConOut, ConIn, ErrOut.
+ PCI Serial: 07 00 02
+
+Arguments:
+
+ DeviceHandle - Handle of PCIIO protocol.
+
+Returns:
+
+ EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
+ EFI_STATUS - No PCI Serial device is added.
+
+--*/
+{
+ 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);
+
+ BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
+ BdsLibUpdateConsoleVariable (VarErrorOut, 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);
+
+ if (!mDetectVgaOnly) {
+ //
+ // 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 ((EFI_D_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 ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));
+ PreparePciSerialDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Here we decide which VGA device to enable in PCI bus
+ //
+ if (IS_PCI_VGA (Pci)) {
+ //
+ // Add them to ConOut.
+ //
+ DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));
+ PreparePciVgaDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+
+/**
+ Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
+
+ @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
+
+ @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
+ @retval EFI_STATUS - PCI Device check or Console variable update fail.
+
+**/
+EFI_STATUS
+DetectAndPreparePlatformPciDevicePaths (
+ BOOLEAN DetectVgaOnly
+ )
+{
+ mDetectVgaOnly = DetectVgaOnly;
+ return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
+}
+
+
+EFI_STATUS
+PlatformBdsConnectConsole (
+ IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ )
+/*++
+
+Routine Description:
+
+ Connect the predefined platform default console device. Always try to find
+ and enable the vga device if have.
+
+Arguments:
+
+ PlatformConsole - Predfined platform default console device array.
+
+Returns:
+
+ EFI_SUCCESS - Success connect at least one ConIn and ConOut
+ device, there must have one ConOut device is
+ active vga device.
+
+ EFI_STATUS - Return the status of
+ BdsLibConnectAllDefaultConsoles ()
+
+--*/
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *VarConout;
+ EFI_DEVICE_PATH_PROTOCOL *VarConin;
+ UINTN DevicePathSize;
+
+ //
+ // Connect RootBridge
+ //
+ VarConout = BdsLibGetVariableAndSize (
+ VarConsoleOut,
+ &gEfiGlobalVariableGuid,
+ &DevicePathSize
+ );
+ VarConin = BdsLibGetVariableAndSize (
+ VarConsoleInp,
+ &gEfiGlobalVariableGuid,
+ &DevicePathSize
+ );
+
+ if (VarConout == NULL || VarConin == NULL) {
+ //
+ // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
+ //
+ DetectAndPreparePlatformPciDevicePaths (FALSE);
+
+ //
+ // Have chance to connect the platform default console,
+ // the platform default console is the minimue 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) {
+ BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
+ BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
+ BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
+ }
+ }
+ } else {
+ //
+ // Only detect VGA device and add them to ConOut
+ //
+ DetectAndPreparePlatformPciDevicePaths (TRUE);
+ }
+
+ //
+ // Connect the all the default console with current cosole variable
+ //
+ Status = BdsLibConnectAllDefaultConsoles ();
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+PciInitialization (
+ )
+{
+#ifdef NOT_BHYVE
+ //
+ // Bus 0, Device 0, Function 0 - Host to PCI Bridge
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0, 0, 0x3c), 0x00);
+
+ //
+ // Bus 0, Device 1, Function 0 - PCI to ISA Bridge
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00);
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // LNKA routing target
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // LNKB routing target
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // LNKC routing target
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // LNKD routing target
+
+ //
+ // Bus 0, Device 1, Function 1 - IDE Controller
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x3c), 0x00);
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x0d), 0x40);
+
+ //
+ // Bus 0, Device 1, Function 3 - Power Managment Controller
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x09);
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01); // INTA
+
+ //
+ // Bus 0, Device 2, Function 0 - Video Controller
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x00);
+
+ //
+ // Bus 0, Device 3, Function 0 - Network Controller
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0a);
+ PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01); // INTA (-> LNKC)
+
+ //
+ // Bus 0, Device 5, Function 0 - RAM Memory
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3c), 0x0b);
+ PciWrite8 (PCI_LIB_ADDRESS (0, 5, 0, 0x3d), 0x01); // INTA (-> LNKA)
+#endif
+}
+
+
+VOID
+AcpiInitialization (
+ VOID
+ )
+{
+ //
+ // Set ACPI SCI_EN bit in PMCNTRL
+ //
+ IoOr16 ((PciRead32 (PCI_LIB_ADDRESS (0, 1, 3, 0x40)) & ~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;
+
+ 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 = DevicePathToStr (DevicePath);
+ if (DevPathStr != NULL) {
+ DEBUG((
+ EFI_D_INFO,
+ "Found Mass Storage device: %s\n",
+ 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 occured
+ @param Context For EFI compatiblity. Not used.
+
+**/
+VOID
+EFIAPI
+EmuVariablesUpdatedCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ DEBUG ((EFI_D_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;
+
+ 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
+ );
+ PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+PlatformBdsRestoreNvVarsFromHardDisk (
+ )
+{
+ VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
+ VisitAllInstancesOfProtocol (
+ &gEfiSimpleFileSystemProtocolGuid,
+ VisitingFileSystemInstance,
+ NULL
+ );
+
+}
+
+
+VOID
+PlatformBdsConnectSequence (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Connect with predeined platform connect sequence,
+ the OEM/IBV can customize with their own connect sequence.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ None.
+
+--*/
+{
+ UINTN Index;
+
+ DEBUG ((EFI_D_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
+ //
+ BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
+ Index++;
+ }
+
+ //
+ // Just use the simple policy to connect all devices
+ //
+ BdsLibConnectAll ();
+
+ PciInitialization ();
+ AcpiInitialization ();
+
+ //
+ // Clear the logo after all devices are connected.
+ //
+ gST->ConOut->ClearScreen (gST->ConOut);
+}
+
+VOID
+PlatformBdsGetDriverOption (
+ IN OUT LIST_ENTRY *BdsDriverLists
+ )
+/*++
+
+Routine Description:
+
+ Load the predefined driver option, OEM/IBV can customize this
+ to load their own drivers
+
+Arguments:
+
+ BdsDriverLists - The header of the driver option link list.
+
+Returns:
+
+ None.
+
+--*/
+{
+ DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));
+ return;
+}
+
+VOID
+PlatformBdsDiagnostics (
+ IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
+ IN BOOLEAN QuietBoot,
+ IN BASEM_MEMORY_TEST BaseMemoryTest
+ )
+/*++
+
+Routine Description:
+
+ Perform the platform diagnostic, such like test memory. OEM/IBV also
+ can customize this fuction to support specific platform diagnostic.
+
+Arguments:
+
+ MemoryTestLevel - The memory test intensive level
+
+ QuietBoot - Indicate if need to enable the quiet boot
+
+ BaseMemoryTest - A pointer to BaseMemoryTest()
+
+Returns:
+
+ None.
+
+--*/
+{
+ EFI_STATUS Status;
+
+ DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
+
+ //
+ // Here we can decide if we need to show
+ // the diagnostics screen
+ // Notes: this quiet boot code should be remove
+ // from the graphic lib
+ //
+ if (QuietBoot) {
+ EnableQuietBoot (PcdGetPtr(PcdLogoFile));
+ //
+ // Perform system diagnostic
+ //
+ Status = BaseMemoryTest (MemoryTestLevel);
+ if (EFI_ERROR (Status)) {
+ DisableQuietBoot ();
+ }
+
+ return ;
+ }
+ //
+ // Perform system diagnostic
+ //
+ Status = BaseMemoryTest (MemoryTestLevel);
+}
+
+/**
+ Override HandleProtocol() to generate a shadowed version of the
+ Interface if it is a device path protocol. This is a workaround
+ for guests that damage the device path structure.
+**/
+EFI_STATUS
+EFIAPI
+BhyveHandleProtocol (
+ IN EFI_HANDLE UserHandle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface
+ )
+{
+ EFI_STATUS Status;
+ STATIC EFI_DEVICE_PATH_PROTOCOL *TempFilePath;
+ EFI_DEVICE_PATH_PROTOCOL *HandleFilePath;
+ UINTN HandleFilePathSize;
+ UINTN NumHandles;
+ EFI_DEVICE_PATH_PROTOCOL *DPtr;
+ CHAR16 *DevPathStr;
+
+ Status = gBS_HandleProtocol(UserHandle, Protocol, Interface);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (CompareGuid (&gEfiDevicePathProtocolGuid, Protocol)) {
+ if (TempFilePath == NULL) {
+ TempFilePath = AllocateZeroPool(512); // XXX this should be resizable
+ }
+
+ HandleFilePath = (EFI_DEVICE_PATH_PROTOCOL *)*Interface;
+
+ NumHandles = 0;
+ DPtr = HandleFilePath;
+ while (!IsDevicePathEnd(DPtr)) {
+ DPtr = NextDevicePathNode(DPtr);
+ NumHandles++;
+ }
+
+ // Return immediately if there aren't many handlers because the guest is
+ // unlikely to damage it.
+ if (NumHandles < 2)
+ return Status;
+
+ HandleFilePathSize = GetDevicePathSize (HandleFilePath);
+
+ DevPathStr = DevicePathToStr(HandleFilePath);
+ if (DevPathStr != NULL) {
+ DEBUG((EFI_D_INFO, "Bhyve-HandleProtocol: Copying DevPath: %s [%d]\n",
+ DevPathStr, HandleFilePathSize));
+ FreePool(DevPathStr);
+ }
+ CopyMem(TempFilePath, HandleFilePath, HandleFilePathSize);
+
+ *Interface = TempFilePath;
+ }
+ return Status;
+}
+
+VOID
+EFIAPI
+PlatformBdsPolicyBehavior (
+ IN OUT LIST_ENTRY *DriverOptionList,
+ IN OUT LIST_ENTRY *BootOptionList,
+ IN PROCESS_CAPSULES ProcessCapsules,
+ IN BASEM_MEMORY_TEST BaseMemoryTest
+ )
+/*++
+
+Routine Description:
+
+ The function will excute with as the platform policy, current policy
+ is driven by boot mode. IBV/OEM can customize this code for their specific
+ policy action.
+
+Arguments:
+
+ DriverOptionList - The header of the driver option link list
+
+ BootOptionList - The header of the boot option link list
+
+ ProcessCapsules - A pointer to ProcessCapsules()
+
+ BaseMemoryTest - A pointer to BaseMemoryTest()
+
+Returns:
+
+ None.
+
+--*/
+{
+ EFI_STATUS Status;
+ UINT16 Timeout;
+ EFI_EVENT UserInputDurationTime;
+ LIST_ENTRY *Link;
+ BDS_COMMON_OPTION *BootOption;
+ UINTN Index;
+ EFI_INPUT_KEY Key;
+ EFI_TPL OldTpl;
+ EFI_BOOT_MODE BootMode;
+
+ DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));
+
+ ConnectRootBridge ();
+
+ if (PcdGetBool (PcdBhyveFlashVariablesEnable)) {
+ DEBUG ((EFI_D_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 ();*/
+ }
+
+ //
+ // Init the time out value
+ //
+ Timeout = PcdGet16 (PcdPlatformBootTimeOut);
+
+ //
+ // Load the driver option as the driver option list
+ //
+ PlatformBdsGetDriverOption (DriverOptionList);
+
+ //
+ // Get current Boot Mode
+ //
+ Status = BdsLibGetBootMode (&BootMode);
+ DEBUG ((EFI_D_ERROR, "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);
+ //
+ // Connect platform console
+ //
+ Status = PlatformBdsConnectConsole (gPlatformConsole);
+ if (EFI_ERROR (Status)) {
+ //
+ // Here OEM/IBV can customize with defined action
+ //
+ PlatformBdsNoConsoleAction ();
+ }
+ //
+ // Create a 300ms duration event to ensure user has enough input time to enter Setup
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ 0,
+ NULL,
+ NULL,
+ &UserInputDurationTime
+ );
+ ASSERT (Status == EFI_SUCCESS);
+ Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
+ ASSERT (Status == EFI_SUCCESS);
+ //
+ // Memory test and Logo show
+ //
+ PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
+
+ //
+ // Perform some platform specific connect sequence
+ //
+ PlatformBdsConnectSequence ();
+
+ //
+ // Give one chance to enter the setup if we
+ // have the time out
+ //
+ if (Timeout != 0) {
+ //PlatformBdsEnterFrontPage (Timeout, FALSE);
+ }
+
+ DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));
+ BdsLibConnectAll ();
+ BdsLibEnumerateAllBootOption (BootOptionList);
+
+ //
+ // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
+ // checking code in real production tip.
+ //
+ // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
+ // and do enumerate all the default boot options. But in development system board, the boot mode
+ // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
+ // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
+ //
+ Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
+ if (EFI_ERROR(Status)) {
+ //
+ // If cannot find "BootOrder" variable, it may be first boot.
+ // Try to connect all devices and enumerate all boot options here.
+ //
+ BdsLibConnectAll ();
+ BdsLibEnumerateAllBootOption (BootOptionList);
+ }
+
+ //
+ // To give the User a chance to enter Setup here, if user set TimeOut is 0.
+ // BDS should still give user a chance to enter Setup
+ //
+ // Connect first boot option, and then check user input before exit
+ //
+ for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
+ BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
+ if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
+ //
+ // skip the header of the link list, becuase it has no boot option
+ //
+ continue;
+ } else {
+ //
+ // Make sure the boot option device path connected, but ignore the BBS device path
+ //
+ if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
+ BdsLibConnectDevicePath (BootOption->DevicePath);
+ }
+ break;
+ }
+ }
+
+
+ DEBUG((EFI_D_INFO, "Overriding HandleProtocol for bhyve guests\n"));
+ gBS_HandleProtocol = gBS->HandleProtocol;
+ gBS->HandleProtocol = BhyveHandleProtocol;
+
+ //
+ // Check whether the user input after the duration time has expired
+ //
+ OldTpl = EfiGetCurrentTpl();
+ gBS->RestoreTPL (TPL_APPLICATION);
+ gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
+ gBS->CloseEvent (UserInputDurationTime);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ gBS->RaiseTPL (OldTpl);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Enter Setup if user input
+ //
+ Timeout = 0xffff;
+ PlatformBdsEnterFrontPage (Timeout, FALSE);
+ }
+
+ return ;
+}
+
+VOID
+EFIAPI
+PlatformBdsBootSuccess (
+ IN BDS_COMMON_OPTION *Option
+ )
+/*++
+
+Routine Description:
+
+ Hook point after a boot attempt succeeds. We don't expect a boot option to
+ return, so the EFI 1.0 specification defines that you will default to an
+ interactive mode and stop processing the BootOrder list in this case. This
+ is alos a platform implementation and can be customized by IBV/OEM.
+
+Arguments:
+
+ Option - Pointer to Boot Option that succeeded to boot.
+
+Returns:
+
+ None.
+
+--*/
+{
+ CHAR16 *TmpStr;
+
+ DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
+ //
+ // If Boot returned with EFI_SUCCESS and there is not in the boot device
+ // select loop then we need to pop up a UI and wait for user input.
+ //
+ TmpStr = Option->StatusString;
+ if (TmpStr != NULL) {
+ BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
+ FreePool (TmpStr);
+ }
+}
+
+VOID
+EFIAPI
+PlatformBdsBootFail (
+ IN BDS_COMMON_OPTION *Option,
+ IN EFI_STATUS Status,
+ IN CHAR16 *ExitData,
+ IN UINTN ExitDataSize
+ )
+/*++
+
+Routine Description:
+
+ Hook point after a boot attempt fails.
+
+Arguments:
+
+ Option - Pointer to Boot Option that failed to boot.
+
+ Status - Status returned from failed boot.
+
+ ExitData - Exit data returned from failed boot.
+
+ ExitDataSize - Exit data size returned from failed boot.
+
+Returns:
+
+ None.
+
+--*/
+{
+ CHAR16 *TmpStr;
+
+ DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
+
+ //
+ // If Boot returned with failed status then we need to pop up a UI and wait
+ // for user input.
+ //
+ TmpStr = Option->StatusString;
+ if (TmpStr != NULL) {
+ BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
+ FreePool (TmpStr);
+ }
+}
+
+EFI_STATUS
+PlatformBdsNoConsoleAction (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function is remained for IBV/OEM to do some platform action,
+ if there no console device can be connected.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ EFI_SUCCESS - Direct return success now.
+
+--*/
+{
+ DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));
+ return EFI_SUCCESS;
+}
+
+VOID
+EFIAPI
+PlatformBdsLockNonUpdatableFlash (
+ VOID
+ )
+{
+ DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
+ return;
+}
+
+
+/**
+ This notification function is invoked when an instance of the
+ EFI_DEVICE_PATH_PROTOCOL is produced.
+
+ @param Event The event that occured
+ @param Context For EFI compatiblity. 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 ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
+ mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
+ &gEfiDevicePathProtocolGuid,
+ TPL_CALLBACK,
+ NotifyDevPath,
+ NULL,
+ &mEfiDevPathNotifyReg
+ );
+}
+
+/**
+ Lock the ConsoleIn device in system table. All key
+ presses will be ignored until the Password is typed in. The only way to
+ disable the password is to type it in to a ConIn device.
+
+ @param Password Password used to lock ConIn device.
+
+ @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
+ @retval EFI_UNSUPPORTED Password not found
+
+**/
+EFI_STATUS
+EFIAPI
+LockKeyboards (
+ IN CHAR16 *Password
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
diff --git BhyvePkg/Library/PlatformBdsLib/BdsPlatform.h BhyvePkg/Library/PlatformBdsLib/BdsPlatform.h
new file mode 100644
index 0000000..220c8cd
--- /dev/null
+++ BhyvePkg/Library/PlatformBdsLib/BdsPlatform.h
@@ -0,0 +1,312 @@
+/** @file
+ Platform BDS customizations include file.
+
+ Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ BdsPlatform.h
+
+Abstract:
+
+ Head file for BDS Platform specific code
+
+**/
+
+#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[];
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[];
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[];
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[];
+extern ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode;
+extern ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode;
+extern UART_DEVICE_PATH gUartDeviceNode;
+extern VENDOR_DEVICE_PATH gTerminalTypeDeviceNode;
+//
+//
+//
+#define VarConsoleInpDev L"ConInDev"
+#define VarConsoleInp L"ConIn"
+#define VarConsoleOutDev L"ConOutDev"
+#define VarConsoleOut L"ConOut"
+#define VarErrorOutDev L"ErrOutDev"
+#define VarErrorOut L"ErrOut"
+
+#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 gPciRootBridge \
+ PNPID_DEVICE_PATH_NODE(0x0A03)
+
+#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 gVt100pTerminal \
+ { \
+ { \
+ MESSAGING_DEVICE_PATH, \
+ MSG_VENDOR_DP, \
+ { \
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \
+ } \
+ }, \
+ DEVICE_PATH_MESSAGING_VT_100_PLUS \
+ }
+
+
+#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 EFI_SYSTEM_TABLE_MAX_ADDRESS 0xFFFFFFFF
+#define SYS_TABLE_PAD(ptr) (((~ptr) +1) & 0x07 )
+
+#define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
+
+//
+// Platform Root Bridge
+//
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_ROOT_BRIDGE_DEVICE_PATH;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH IsaBridge;
+ ACPI_HID_DEVICE_PATH Keyboard;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_ISA_KEYBOARD_DEVICE_PATH;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH IsaBridge;
+ ACPI_HID_DEVICE_PATH IsaSerial;
+ UART_DEVICE_PATH Uart;
+ VENDOR_DEVICE_PATH TerminalType;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_ISA_SERIAL_DEVICE_PATH;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH VgaDevice;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_DUMMY_PCI_VGA_DEVICE_PATH;
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH PciRootBridge;
+ PCI_DEVICE_PATH PciBridge;
+ PCI_DEVICE_PATH SerialDevice;
+ UART_DEVICE_PATH Uart;
+ VENDOR_DEVICE_PATH TerminalType;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} PLATFORM_DUMMY_PCI_SERIAL_DEVICE_PATH;
+
+//
+// the short form device path for Usb keyboard
+//
+#define CLASS_HID 3
+#define SUBCLASS_BOOT 1
+#define PROTOCOL_KEYBOARD 1
+
+typedef struct {
+ USB_CLASS_DEVICE_PATH UsbClass;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} USB_CLASS_FORMAT_DEVICE_PATH;
+
+extern PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0;
+
+//
+// Platform BDS Functions
+//
+
+VOID
+PlatformBdsGetDriverOption (
+ IN LIST_ENTRY *BdsDriverLists
+ );
+
+EFI_STATUS
+BdsMemoryTest (
+ EXTENDMEM_COVERAGE_LEVEL Level
+ );
+
+EFI_STATUS
+PlatformBdsShowProgress (
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,
+ CHAR16 *Title,
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,
+ UINTN Progress,
+ UINTN PreviousValue
+ );
+
+VOID
+PlatformBdsConnectSequence (
+ VOID
+ );
+
+EFI_STATUS
+ProcessCapsules (
+ EFI_BOOT_MODE BootMode
+ );
+
+EFI_STATUS
+PlatformBdsConnectConsole (
+ IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ );
+
+EFI_STATUS
+PlatformBdsNoConsoleAction (
+ VOID
+ );
+
+EFI_STATUS
+ConvertMpsTable (
+ IN OUT VOID **Table
+ );
+
+EFI_STATUS
+ConvertSmbiosTable (
+ IN OUT VOID **Table
+ );
+
+EFI_STATUS
+ConvertAcpiTable (
+ IN UINTN TableLen,
+ IN OUT VOID **Table
+ );
+
+EFI_STATUS
+ConvertSystemTable (
+ IN EFI_GUID *TableGuid,
+ IN OUT VOID **Table
+ );
+
+VOID
+PlatformBdsEnterFrontPage (
+ IN UINT16 TimeoutDefault,
+ IN BOOLEAN ConnectAllHappened
+ );
+
+#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
diff --git BhyvePkg/Library/PlatformBdsLib/PlatformBdsLib.inf BhyvePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
new file mode 100644
index 0000000..17b024f
--- /dev/null
+++ BhyvePkg/Library/PlatformBdsLib/PlatformBdsLib.inf
@@ -0,0 +1,62 @@
+## @file
+# Platform BDS customizations library.
+#
+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformBdsLib
+ FILE_GUID = F844172E-9985-44f2-BADE-0DD783462E95
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformBdsLib|DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ BdsPlatform.c
+ PlatformData.c
+ BdsPlatform.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
+ BhyvePkg/BhyvePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ GenericBdsLib
+ PciLib
+ NvVarsFileLib
+
+[Pcd]
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdLogoFile
+ gUefiBhyvePkgTokenSpaceGuid.PcdEmuVariableEvent
+ gUefiBhyvePkgTokenSpaceGuid.PcdBhyveFlashVariablesEnable
+
+[Pcd.IA32, Pcd.X64]
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock
+
+[Protocols]
+ gEfiDecompressProtocolGuid
+
diff --git BhyvePkg/Library/PlatformBdsLib/PlatformData.c BhyvePkg/Library/PlatformBdsLib/PlatformData.c
new file mode 100644
index 0000000..11d1f88
--- /dev/null
+++ BhyvePkg/Library/PlatformBdsLib/PlatformData.c
@@ -0,0 +1,83 @@
+/** @file
+ Defined the platform specific device path which will be used by
+ platform Bbd to perform the platform policy connect.
+
+ Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "BdsPlatform.h"
+
+//
+// Predefined platform default time out value
+//
+UINT16 gPlatformBootTimeOutDefault = 5;
+
+ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard;
+ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort;
+UART_DEVICE_PATH gUartDeviceNode = gUart;
+VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gVt100pTerminal;
+
+//
+// Predefined platform root bridge
+//
+PLATFORM_ROOT_BRIDGE_DEVICE_PATH gPlatformRootBridge0 = {
+ gPciRootBridge,
+ gEndEntire
+};
+
+EFI_DEVICE_PATH_PROTOCOL *gPlatformRootBridges[] = {
+ (EFI_DEVICE_PATH_PROTOCOL *) &gPlatformRootBridge0,
+ NULL
+};
+
+//
+// Platform specific ISA serial device path
+//
+PLATFORM_ISA_SERIAL_DEVICE_PATH gIsaSerialDevicePath = {
+ gPciRootBridge,
+ gPciIsaBridge,
+ gPnp16550ComPort,
+ gUart,
+ gVt100pTerminal,
+ gEndEntire
+};
+
+//
+// Platform specific ISA keyboard device path
+//
+PLATFORM_ISA_KEYBOARD_DEVICE_PATH gIsaKeyboardDevicePath = {
+ gPciRootBridge,
+ gPciIsaBridge,
+ gPnpPs2Keyboard,
+ gEndEntire
+};
+
+//
+// Predefined platform default console device path
+//
+BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = {
+ {(EFI_DEVICE_PATH_PROTOCOL*)&gIsaKeyboardDevicePath, CONSOLE_IN},
+ {(EFI_DEVICE_PATH_PROTOCOL*)&gIsaSerialDevicePath, CONSOLE_ALL},
+ {NULL, 0}
+};
+
+//
+// Predefined platform specific driver option
+//
+EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[] = { NULL };
+
+//
+// Predefined platform connect sequence
+//
+EFI_DEVICE_PATH_PROTOCOL* gPlatformConnectSequence [] = {
+ (EFI_DEVICE_PATH_PROTOCOL *)&gPlatformRootBridge0, // Force PCI enumer before Legacy OpROM shadow
+ NULL
+};
diff --git BhyvePkg/Library/PlatformDebugLibIoPort/DebugLib.c BhyvePkg/Library/PlatformDebugLibIoPort/DebugLib.c
new file mode 100644
index 0000000..4e2b47f
--- /dev/null
+++ BhyvePkg/Library/PlatformDebugLibIoPort/DebugLib.c
@@ -0,0 +1,286 @@
+/** @file
+ Base Debug library instance for QEMU debug port.
+ It uses PrintLib to send debug messages to a fixed I/O port.
+
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ Copyright (c) 2012, Red Hat, Inc.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//
+// Define the maximum debug and assert message length that this library supports
+//
+#define MAX_DEBUG_MESSAGE_LENGTH 0x100
+
+/**
+ This constructor function does not have to do anything.
+
+ @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
+
+**/
+RETURN_STATUS
+EFIAPI
+PlatformDebugLibIoPortConstructor (
+ VOID
+ )
+{
+ return EFI_SUCCESS;
+}
+
+/**
+ Prints a debug message to the debug output device if the specified error level is enabled.
+
+ If any bit in ErrorLevel is also set in DebugPrintErrorLevelLib function
+ GetDebugPrintErrorLevel (), then print the message specified by Format and the
+ associated variable argument list to the debug output device.
+
+ If Format is NULL, then ASSERT().
+
+ @param ErrorLevel The error level of the debug message.
+ @param Format Format string for the debug message to print.
+ @param ... Variable argument list whose contents are accessed
+ based on the format string specified by Format.
+
+**/
+VOID
+EFIAPI
+DebugPrint (
+ IN UINTN ErrorLevel,
+ IN CONST CHAR8 *Format,
+ ...
+ )
+{
+ CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
+ VA_LIST Marker;
+ UINT8 *Ptr;
+
+ //
+ // If Format is NULL, then ASSERT().
+ //
+ ASSERT (Format != NULL);
+
+ //
+ // Check driver debug mask value and global mask
+ //
+ if ((ErrorLevel & GetDebugPrintErrorLevel ()) == 0) {
+ return;
+ }
+
+ //
+ // Convert the DEBUG() message to an ASCII String
+ //
+ VA_START (Marker, Format);
+ AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker);
+ VA_END (Marker);
+
+ //
+ // Send the print string to the debug I/O port
+ //
+ for (Ptr = (UINT8 *) Buffer; *Ptr; Ptr++) {
+ IoWrite8 (PcdGet16(PcdDebugIoPort), *Ptr);
+ }
+}
+
+
+/**
+ Prints an assert message containing a filename, line number, and description.
+ This may be followed by a breakpoint or a dead loop.
+
+ Print a message of the form "ASSERT (): \n"
+ to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of
+ PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if
+ DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then
+ CpuDeadLoop() is called. If neither of these bits are set, then this function
+ returns immediately after the message is printed to the debug output device.
+ DebugAssert() must actively prevent recursion. If DebugAssert() is called while
+ processing another DebugAssert(), then DebugAssert() must return immediately.
+
+ If FileName is NULL, then a string of "(NULL) Filename" is printed.
+ If Description is NULL, then a string of "(NULL) Description" is printed.
+
+ @param FileName The pointer to the name of the source file that generated the assert condition.
+ @param LineNumber The line number in the source file that generated the assert condition
+ @param Description The pointer to the description of the assert condition.
+
+**/
+VOID
+EFIAPI
+DebugAssert (
+ IN CONST CHAR8 *FileName,
+ IN UINTN LineNumber,
+ IN CONST CHAR8 *Description
+ )
+{
+ CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH];
+ UINT8 *Ptr;
+
+ //
+ // Generate the ASSERT() message in Ascii format
+ //
+ AsciiSPrint (Buffer, sizeof (Buffer), "ASSERT %a(%d): %a\n", FileName, LineNumber, Description);
+
+ //
+ // Send the print string to the Console Output device
+ //
+ for (Ptr = (UINT8 *) Buffer; *Ptr; Ptr++) {
+ IoWrite8 (PcdGet16(PcdDebugIoPort), *Ptr);
+ }
+
+ //
+ // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings
+ //
+ if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) {
+ CpuBreakpoint ();
+ } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) {
+ CpuDeadLoop ();
+ }
+}
+
+
+/**
+ Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer.
+
+ This function fills Length bytes of Buffer with the value specified by
+ PcdDebugClearMemoryValue, and returns Buffer.
+
+ If Buffer is NULL, then ASSERT().
+ If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT().
+
+ @param Buffer The pointer to the target buffer to be filled with PcdDebugClearMemoryValue.
+ @param Length The number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue.
+
+ @return Buffer The pointer to the target buffer filled with PcdDebugClearMemoryValue.
+
+**/
+VOID *
+EFIAPI
+DebugClearMemory (
+ OUT VOID *Buffer,
+ IN UINTN Length
+ )
+{
+ //
+ // If Buffer is NULL, then ASSERT().
+ //
+ ASSERT (Buffer != NULL);
+
+ //
+ // SetMem() checks for the the ASSERT() condition on Length and returns Buffer
+ //
+ return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue));
+}
+
+
+/**
+ Returns TRUE if ASSERT() macros are enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of
+ PcdDebugProperyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugAssertEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0);
+}
+
+
+/**
+ Returns TRUE if DEBUG() macros are enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of
+ PcdDebugProperyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugPrintEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0);
+}
+
+
+/**
+ Returns TRUE if DEBUG_CODE() macros are enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of
+ PcdDebugProperyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugCodeEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0);
+}
+
+
+/**
+ Returns TRUE if DEBUG_CLEAR_MEMORY() macro is enabled.
+
+ This function returns TRUE if the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of
+ PcdDebugProperyMask is set. Otherwise FALSE is returned.
+
+ @retval TRUE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set.
+ @retval FALSE The DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear.
+
+**/
+BOOLEAN
+EFIAPI
+DebugClearMemoryEnabled (
+ VOID
+ )
+{
+ return (BOOLEAN) ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0);
+}
+
+/**
+ Returns TRUE if any one of the bit is set both in ErrorLevel and PcdFixedDebugPrintErrorLevel.
+
+ This function compares the bit mask of ErrorLevel and PcdFixedDebugPrintErrorLevel.
+
+ @retval TRUE Current ErrorLevel is supported.
+ @retval FALSE Current ErrorLevel is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+DebugPrintLevelEnabled (
+ IN CONST UINTN ErrorLevel
+ )
+{
+ return (BOOLEAN) ((ErrorLevel & PcdGet32(PcdFixedDebugPrintErrorLevel)) != 0);
+}
diff --git BhyvePkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf BhyvePkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
new file mode 100644
index 0000000..34784c4
--- /dev/null
+++ BhyvePkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
@@ -0,0 +1,50 @@
+## @file
+# Instance of Debug Library for the QEMU debug console port.
+# It uses Print Library to produce formatted output strings.
+#
+# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+# Copyright (c) 2012, Red Hat, Inc.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php.
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformDebugLibIoPort
+ FILE_GUID = DF934DA3-CD31-49FE-AF50-B3C87C79325F
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DebugLib
+ CONSTRUCTOR = PlatformDebugLibIoPortConstructor
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ DebugLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BhyvePkg/BhyvePkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ IoLib
+ PcdLib
+ PrintLib
+ BaseLib
+ DebugPrintErrorLevelLib
+
+[Pcd]
+ gUefiBhyvePkgTokenSpaceGuid.PcdDebugIoPort ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdDebugClearMemoryValue ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel ## CONSUMES
diff --git BhyvePkg/Library/PlatformSecureLib/PlatformSecureLib.c BhyvePkg/Library/PlatformSecureLib/PlatformSecureLib.c
new file mode 100644
index 0000000..7ff8733
--- /dev/null
+++ BhyvePkg/Library/PlatformSecureLib/PlatformSecureLib.c
@@ -0,0 +1,40 @@
+/** @file
+ Provides a platform-specific method to enable Secure Boot Custom Mode setup.
+
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include
+
+/**
+
+ This function provides a platform-specific method to detect whether the platform
+ is operating by a physically present user.
+
+ Programmatic changing of platform security policy (such as disable Secure Boot,
+ or switch between Standard/Custom Secure Boot mode) MUST NOT be possible during
+ Boot Services or after exiting EFI Boot Services. Only a physically present user
+ is allowed to perform these operations.
+
+ NOTE THAT: This function cannot depend on any EFI Variable Service since they are
+ not available when this function is called in AuthenticateVariable driver.
+
+ @retval TRUE The platform is operated by a physically present user.
+ @retval FALSE The platform is NOT operated by a physically present user.
+
+**/
+BOOLEAN
+EFIAPI
+UserPhysicalPresent (
+ VOID
+ )
+{
+ return TRUE;
+}
diff --git BhyvePkg/Library/PlatformSecureLib/PlatformSecureLib.inf BhyvePkg/Library/PlatformSecureLib/PlatformSecureLib.inf
new file mode 100644
index 0000000..c5f6921
--- /dev/null
+++ BhyvePkg/Library/PlatformSecureLib/PlatformSecureLib.inf
@@ -0,0 +1,33 @@
+## @file
+# Provides a platform-specific method to enable Secure Boot Custom Mode setup.
+#
+# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformSecureLib
+ FILE_GUID = 4204D78D-EDBF-4cee-BE80-3881457CF344
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformSecureLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ PlatformSecureLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
diff --git BhyvePkg/Library/ResetSystemLib/ResetSystemLib.c BhyvePkg/Library/ResetSystemLib/ResetSystemLib.c
new file mode 100644
index 0000000..1319e5d
--- /dev/null
+++ BhyvePkg/Library/ResetSystemLib/ResetSystemLib.c
@@ -0,0 +1,108 @@
+/** @file
+ Reset System Library functions for OVMF
+
+ Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+VOID
+AcpiPmControl (
+ UINTN SuspendType
+ )
+{
+ ASSERT (SuspendType < 6);
+
+ IoBitFieldWrite16 (PcdGet16 (PcdAcpiPmBaseAddress) + 4, 10, 13, (UINT16) SuspendType);
+ IoOr16 (PcdGet16 (PcdAcpiPmBaseAddress) + 4, BIT13);
+ CpuDeadLoop ();
+}
+
+/**
+ Calling this function causes a system-wide reset. This sets
+ all circuitry within the system to its initial state. This type of reset
+ is asynchronous to system operation and operates without regard to
+ cycle boundaries.
+
+ System reset should not return, if it returns, it means the system does
+ not support cold reset.
+**/
+VOID
+EFIAPI
+ResetCold (
+ VOID
+ )
+{
+ IoWrite8 (0xCF9, BIT2 | BIT1); // 1st choice: PIIX3 RCR, RCPU|SRST
+ MicroSecondDelay (50);
+
+ IoWrite8 (0x64, 0xfe); // 2nd choice: keyboard controller
+ CpuDeadLoop ();
+}
+
+/**
+ Calling this function causes a system-wide initialization. The processors
+ are set to their initial state, and pending cycles are not corrupted.
+
+ System reset should not return, if it returns, it means the system does
+ not support warm reset.
+**/
+VOID
+EFIAPI
+ResetWarm (
+ VOID
+ )
+{
+ IoWrite8 (0x64, 0xfe);
+ CpuDeadLoop ();
+}
+
+/**
+ Calling this function causes the system to enter a power state equivalent
+ to the ACPI G2/S5 or G3 states.
+
+ System shutdown should not return, if it returns, it means the system does
+ not support shut down reset.
+**/
+VOID
+EFIAPI
+ResetShutdown (
+ VOID
+ )
+{
+ AcpiPmControl (0);
+ ASSERT (FALSE);
+}
+
+
+/**
+ Calling this function causes the system to enter a power state for capsule
+ update.
+
+ Reset update should not return, if it returns, it means the system does
+ not support capsule update.
+
+**/
+VOID
+EFIAPI
+EnterS3WithImmediateWake (
+ VOID
+ )
+{
+ AcpiPmControl (1);
+ ASSERT (FALSE);
+}
diff --git BhyvePkg/Library/ResetSystemLib/ResetSystemLib.inf BhyvePkg/Library/ResetSystemLib/ResetSystemLib.inf
new file mode 100644
index 0000000..3b45529
--- /dev/null
+++ BhyvePkg/Library/ResetSystemLib/ResetSystemLib.inf
@@ -0,0 +1,42 @@
+## @file
+# Library instance for ResetSystem library class for OVMF
+#
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ResetSystemLib
+ FILE_GUID = 66564872-21d4-4d2a-a68b-1e844f980820
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ResetSystemLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF
+#
+
+[Sources]
+ ResetSystemLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BhyvePkg/BhyvePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ IoLib
+ TimerLib
+
+[Pcd]
+ gUefiBhyvePkgTokenSpaceGuid.PcdAcpiPmBaseAddress
diff --git BhyvePkg/Library/SerializeVariablesLib/SerializeVariablesLib.c BhyvePkg/Library/SerializeVariablesLib/SerializeVariablesLib.c
new file mode 100644
index 0000000..11bd3c8
--- /dev/null
+++ BhyvePkg/Library/SerializeVariablesLib/SerializeVariablesLib.c
@@ -0,0 +1,870 @@
+/** @file
+ Serialize Variables Library implementation
+
+ Copyright (c) 2004 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "SerializeVariablesLib.h"
+
+/**
+ Serialization format:
+
+ The SerializeVariablesLib interface does not specify a format
+ for the serialization of the variable data. This library uses
+ a packed array of a non-uniformly sized data structure elements.
+
+ Each variable is stored (packed) as:
+ UINT32 VendorNameSize; // Name size in bytes
+ CHAR16 VendorName[?]; // The variable unicode name including the
+ // null terminating character.
+ EFI_GUID VendorGuid; // The variable GUID
+ UINT32 DataSize; // The size of variable data in bytes
+ UINT8 Data[?]; // The variable data
+
+**/
+
+
+/**
+ Unpacks the next variable from the buffer
+
+ @param[in] Buffer - Buffer pointing to the next variable instance
+ On subsequent calls, the pointer should be incremented
+ by the returned SizeUsed value.
+ @param[in] MaxSize - Max allowable size for the variable data
+ On subsequent calls, this should be decremented
+ by the returned SizeUsed value.
+ @param[out] Name - Variable name string (address in Buffer)
+ @param[out] NameSize - Size of Name in bytes
+ @param[out] Guid - GUID of variable (address in Buffer)
+ @param[out] Attributes - Attributes of variable
+ @param[out] Data - Buffer containing Data for variable (address in Buffer)
+ @param[out] DataSize - Size of Data in bytes
+ @param[out] SizeUsed - Total size used for this variable instance in Buffer
+
+ @return EFI_STATUS based on the success or failure of the operation
+
+**/
+STATIC
+EFI_STATUS
+UnpackVariableFromBuffer (
+ IN VOID *Buffer,
+ IN UINTN MaxSize,
+ OUT CHAR16 **Name,
+ OUT UINT32 *NameSize,
+ OUT EFI_GUID **Guid,
+ OUT UINT32 *Attributes,
+ OUT UINT32 *DataSize,
+ OUT VOID **Data,
+ OUT UINTN *SizeUsed
+ )
+{
+ UINT8 *BytePtr;
+ UINTN Offset;
+
+ BytePtr = (UINT8*)Buffer;
+ Offset = 0;
+
+ *NameSize = *(UINT32*) (BytePtr + Offset);
+ Offset = Offset + sizeof (UINT32);
+
+ if (Offset > MaxSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Name = (CHAR16*) (BytePtr + Offset);
+ Offset = Offset + *(UINT32*)BytePtr;
+ if (Offset > MaxSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Guid = (EFI_GUID*) (BytePtr + Offset);
+ Offset = Offset + sizeof (EFI_GUID);
+ if (Offset > MaxSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Attributes = *(UINT32*) (BytePtr + Offset);
+ Offset = Offset + sizeof (UINT32);
+ if (Offset > MaxSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *DataSize = *(UINT32*) (BytePtr + Offset);
+ Offset = Offset + sizeof (UINT32);
+ if (Offset > MaxSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Data = (VOID*) (BytePtr + Offset);
+ Offset = Offset + *DataSize;
+ if (Offset > MaxSize) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *SizeUsed = Offset;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Iterates through the variables in the buffer, and calls a callback
+ function for each variable found.
+
+ @param[in] CallbackFunction - Function called for each variable instance
+ @param[in] Context - Passed to each call of CallbackFunction
+ @param[in] Buffer - Buffer containing serialized variables
+ @param[in] MaxSize - Size of Buffer in bytes
+
+ @return EFI_STATUS based on the success or failure of the operation
+
+**/
+STATIC
+EFI_STATUS
+IterateVariablesInBuffer (
+ IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+ IN VOID *CallbackContext,
+ IN VOID *Buffer,
+ IN UINTN MaxSize
+ )
+{
+ RETURN_STATUS Status;
+ UINTN TotalSizeUsed;
+ UINTN SizeUsed;
+
+ CHAR16 *Name;
+ UINT32 NameSize;
+ CHAR16 *AlignedName;
+ UINT32 AlignedNameMaxSize;
+ EFI_GUID *Guid;
+ UINT32 Attributes;
+ UINT32 DataSize;
+ VOID *Data;
+
+ SizeUsed = 0;
+ AlignedName = NULL;
+ AlignedNameMaxSize = 0;
+ Name = NULL;
+ Guid = NULL;
+ Attributes = 0;
+ DataSize = 0;
+ Data = NULL;
+
+ for (
+ Status = EFI_SUCCESS, TotalSizeUsed = 0;
+ !EFI_ERROR (Status) && (TotalSizeUsed < MaxSize);
+ ) {
+ Status = UnpackVariableFromBuffer (
+ (VOID*) ((UINT8*) Buffer + TotalSizeUsed),
+ (MaxSize - TotalSizeUsed),
+ &Name,
+ &NameSize,
+ &Guid,
+ &Attributes,
+ &DataSize,
+ &Data,
+ &SizeUsed
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // We copy the name to a separately allocated buffer,
+ // to be sure it is 16-bit aligned.
+ //
+ if (NameSize > AlignedNameMaxSize) {
+ if (AlignedName != NULL) {
+ FreePool (AlignedName);
+ }
+ AlignedName = AllocatePool (NameSize);
+ }
+ if (AlignedName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (AlignedName, Name, NameSize);
+
+ TotalSizeUsed = TotalSizeUsed + SizeUsed;
+
+ //
+ // Run the callback function
+ //
+ Status = (*CallbackFunction) (
+ CallbackContext,
+ AlignedName,
+ Guid,
+ Attributes,
+ DataSize,
+ Data
+ );
+
+ }
+
+ if (AlignedName != NULL) {
+ FreePool (AlignedName);
+ }
+
+ //
+ // Make sure the entire buffer was used, or else return an error
+ //
+ if (TotalSizeUsed != MaxSize) {
+ DEBUG ((
+ EFI_D_ERROR,
+ "Deserialize variables error: TotalSizeUsed(%d) != MaxSize(%d)\n",
+ TotalSizeUsed,
+ MaxSize
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackNop (
+ IN VOID *Context,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ return RETURN_SUCCESS;
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackSetInInstance (
+ IN VOID *Context,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ EFI_HANDLE Instance;
+
+ Instance = (EFI_HANDLE) Context;
+
+ return SerializeVariablesAddVariable (
+ Instance,
+ VariableName,
+ VendorGuid,
+ Attributes,
+ DataSize,
+ Data
+ );
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+IterateVariablesCallbackSetSystemVariable (
+ IN VOID *Context,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ EFI_STATUS Status;
+ STATIC CONST UINT32 AuthMask =
+ EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+
+ Status = gRT->SetVariable (
+ VariableName,
+ VendorGuid,
+ Attributes,
+ DataSize,
+ Data
+ );
+
+ if (Status == EFI_SECURITY_VIOLATION && (Attributes & AuthMask) != 0) {
+ DEBUG ((DEBUG_WARN, "%a: setting authenticated variable \"%s\" "
+ "failed with EFI_SECURITY_VIOLATION, ignoring\n", __FUNCTION__,
+ VariableName));
+ Status = EFI_SUCCESS;
+ }
+ return Status;
+}
+
+
+STATIC
+RETURN_STATUS
+EnsureExtraBufferSpace (
+ IN SV_INSTANCE *Instance,
+ IN UINTN Size
+ )
+{
+ VOID *NewBuffer;
+ UINTN NewSize;
+
+ NewSize = Instance->DataSize + Size;
+ if (NewSize <= Instance->BufferSize) {
+ return RETURN_SUCCESS;
+ }
+
+ //
+ // Double the required size to lessen the need to re-allocate in the future
+ //
+ NewSize = 2 * NewSize;
+
+ NewBuffer = AllocatePool (NewSize);
+ if (NewBuffer == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ if (Instance->BufferPtr != NULL) {
+ CopyMem (NewBuffer, Instance->BufferPtr, Instance->DataSize);
+ FreePool (Instance->BufferPtr);
+ }
+
+ Instance->BufferPtr = NewBuffer;
+ Instance->BufferSize = NewSize;
+
+ return RETURN_SUCCESS;
+}
+
+
+STATIC
+VOID
+AppendToBuffer (
+ IN SV_INSTANCE *Instance,
+ IN VOID *Data,
+ IN UINTN Size
+ )
+{
+ UINTN NewSize;
+
+ ASSERT (Instance != NULL);
+ ASSERT (Data != NULL);
+
+ NewSize = Instance->DataSize + Size;
+ ASSERT ((Instance->DataSize + Size) <= Instance->BufferSize);
+
+ CopyMem (
+ (VOID*) (((UINT8*) (Instance->BufferPtr)) + Instance->DataSize),
+ Data,
+ Size
+ );
+
+ Instance->DataSize = NewSize;
+}
+
+
+/**
+ Creates a new variable serialization instance
+
+ @param[out] Handle - Handle for a variable serialization instance
+
+ @retval RETURN_SUCCESS - The variable serialization instance was
+ successfully created.
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ create the variable serialization instance.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesNewInstance (
+ OUT EFI_HANDLE *Handle
+ )
+{
+ SV_INSTANCE *New;
+
+ New = AllocateZeroPool (sizeof (*New));
+ if (New == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ New->Signature = SV_SIGNATURE;
+
+ *Handle = (EFI_HANDLE) New;
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Free memory associated with a variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+
+ @retval RETURN_SUCCESS - The variable serialization instance was
+ successfully freed.
+ @retval RETURN_INVALID_PARAMETER - Handle was not a valid
+ variable serialization instance.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesFreeInstance (
+ IN EFI_HANDLE Handle
+ )
+{
+ SV_INSTANCE *Instance;
+
+ Instance = SV_FROM_HANDLE (Handle);
+
+ if (Instance->Signature != SV_SIGNATURE) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ Instance->Signature = 0;
+
+ if (Instance->BufferPtr != NULL) {
+ FreePool (Instance->BufferPtr);
+ }
+
+ FreePool (Instance);
+
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Creates a new variable serialization instance using the given
+ binary representation of the variables to fill the new instance
+
+ @param[out] Handle - Handle for a variable serialization instance
+ @param[in] Buffer - A buffer with the serialized representation
+ of the variables. Must be the same format as produced
+ by SerializeVariablesToBuffer.
+ @param[in] Size - This is the size of the binary representation
+ of the variables.
+
+ @retval RETURN_SUCCESS - The binary representation was successfully
+ imported into a new variable serialization instance
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ create the new variable serialization instance
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesNewInstanceFromBuffer (
+ OUT EFI_HANDLE *Handle,
+ IN VOID *Buffer,
+ IN UINTN Size
+ )
+{
+ RETURN_STATUS Status;
+
+ Status = SerializeVariablesNewInstance (Handle);
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = IterateVariablesInBuffer (
+ IterateVariablesCallbackNop,
+ NULL,
+ Buffer,
+ Size
+ );
+ if (RETURN_ERROR (Status)) {
+ SerializeVariablesFreeInstance (*Handle);
+ return Status;
+ }
+
+ Status = IterateVariablesInBuffer (
+ IterateVariablesCallbackSetInInstance,
+ (VOID*) *Handle,
+ Buffer,
+ Size
+ );
+ if (RETURN_ERROR (Status)) {
+ SerializeVariablesFreeInstance (*Handle);
+ return Status;
+ }
+
+ return Status;
+}
+
+
+/**
+ Iterates all variables found with RuntimeServices GetNextVariableName
+
+ @param[in] CallbackFunction - Function called for each variable instance
+ @param[in] Context - Passed to each call of CallbackFunction
+
+ @retval RETURN_SUCCESS - All variables were iterated without the
+ CallbackFunction returning an error
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ iterate through the variables
+ @return Any of RETURN_ERROR indicates an error reading the variable
+ or an error was returned from CallbackFunction
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesIterateSystemVariables (
+ IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+ IN VOID *Context
+ )
+{
+ RETURN_STATUS Status;
+ UINTN VariableNameBufferSize;
+ UINTN VariableNameSize;
+ CHAR16 *VariableName;
+ EFI_GUID VendorGuid;
+ UINTN VariableDataBufferSize;
+ UINTN VariableDataSize;
+ VOID *VariableData;
+ UINT32 VariableAttributes;
+ VOID *NewBuffer;
+
+ //
+ // Initialize the variable name and data buffer variables.
+ //
+ VariableNameBufferSize = sizeof (CHAR16);
+ VariableName = AllocateZeroPool (VariableNameBufferSize);
+
+ VariableDataBufferSize = 0;
+ VariableData = NULL;
+
+ for (;;) {
+ //
+ // Get the next variable name and guid
+ //
+ VariableNameSize = VariableNameBufferSize;
+ Status = gRT->GetNextVariableName (
+ &VariableNameSize,
+ VariableName,
+ &VendorGuid
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // The currently allocated VariableName buffer is too small,
+ // so we allocate a larger buffer, and copy the old buffer
+ // to it.
+ //
+ NewBuffer = AllocatePool (VariableNameSize);
+ if (NewBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ CopyMem (NewBuffer, VariableName, VariableNameBufferSize);
+ if (VariableName != NULL) {
+ FreePool (VariableName);
+ }
+ VariableName = NewBuffer;
+ VariableNameBufferSize = VariableNameSize;
+
+ //
+ // Try to get the next variable name again with the larger buffer.
+ //
+ Status = gRT->GetNextVariableName (
+ &VariableNameSize,
+ VariableName,
+ &VendorGuid
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ Status = EFI_SUCCESS;
+ }
+ break;
+ }
+
+ //
+ // Get the variable data and attributes
+ //
+ VariableDataSize = VariableDataBufferSize;
+ Status = gRT->GetVariable (
+ VariableName,
+ &VendorGuid,
+ &VariableAttributes,
+ &VariableDataSize,
+ VariableData
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // The currently allocated VariableData buffer is too small,
+ // so we allocate a larger buffer.
+ //
+ if (VariableDataBufferSize != 0) {
+ FreePool (VariableData);
+ VariableData = NULL;
+ VariableDataBufferSize = 0;
+ }
+ VariableData = AllocatePool (VariableDataSize);
+ if (VariableData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ VariableDataBufferSize = VariableDataSize;
+
+ //
+ // Try to read the variable again with the larger buffer.
+ //
+ Status = gRT->GetVariable (
+ VariableName,
+ &VendorGuid,
+ &VariableAttributes,
+ &VariableDataSize,
+ VariableData
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ //
+ // Run the callback function
+ //
+ Status = (*CallbackFunction) (
+ Context,
+ VariableName,
+ &VendorGuid,
+ VariableAttributes,
+ VariableDataSize,
+ VariableData
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ }
+
+ if (VariableName != NULL) {
+ FreePool (VariableName);
+ }
+
+ if (VariableData != NULL) {
+ FreePool (VariableData);
+ }
+
+ return Status;
+}
+
+
+/**
+ Iterates all variables found in the variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+ @param[in] CallbackFunction - Function called for each variable instance
+ @param[in] Context - Passed to each call of CallbackFunction
+
+ @retval RETURN_SUCCESS - All variables were iterated without the
+ CallbackFunction returning an error
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ iterate through the variables
+ @return Any of RETURN_ERROR indicates an error reading the variable
+ or an error was returned from CallbackFunction
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesIterateInstanceVariables (
+ IN EFI_HANDLE Handle,
+ IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,
+ IN VOID *Context
+ )
+{
+ SV_INSTANCE *Instance;
+
+ Instance = SV_FROM_HANDLE (Handle);
+
+ if ((Instance->BufferPtr != NULL) && (Instance->DataSize != 0)) {
+ return IterateVariablesInBuffer (
+ CallbackFunction,
+ Context,
+ Instance->BufferPtr,
+ Instance->DataSize
+ );
+ } else {
+ return RETURN_SUCCESS;
+ }
+}
+
+
+/**
+ Sets all variables found in the variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+
+ @retval RETURN_SUCCESS - All variables were set successfully
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ set all the variables
+ @return Any of RETURN_ERROR indicates an error reading the variables
+ or in attempting to set a variable
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesSetSerializedVariables (
+ IN EFI_HANDLE Handle
+ )
+{
+ return SerializeVariablesIterateInstanceVariables (
+ Handle,
+ IterateVariablesCallbackSetSystemVariable,
+ NULL
+ );
+}
+
+
+/**
+ Adds a variable to the variable serialization instance
+
+ @param[in] Handle - Handle for a variable serialization instance
+ @param[in] VariableName - Refer to RuntimeServices GetVariable
+ @param[in] VendorGuid - Refer to RuntimeServices GetVariable
+ @param[in] Attributes - Refer to RuntimeServices GetVariable
+ @param[in] DataSize - Refer to RuntimeServices GetVariable
+ @param[in] Data - Refer to RuntimeServices GetVariable
+
+ @retval RETURN_SUCCESS - All variables were set successfully
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ add the variable
+ @retval RETURN_INVALID_PARAMETER - Handle was not a valid
+ variable serialization instance or
+ VariableName, VariableGuid or Data are NULL.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesAddVariable (
+ IN EFI_HANDLE Handle,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ RETURN_STATUS Status;
+ SV_INSTANCE *Instance;
+ UINT32 SerializedNameSize;
+ UINT32 SerializedDataSize;
+ UINTN SerializedSize;
+
+ Instance = SV_FROM_HANDLE (Handle);
+
+ if ((Instance->Signature != SV_SIGNATURE) ||
+ (VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL)) {
+ }
+
+ SerializedNameSize = (UINT32) StrSize (VariableName);
+
+ SerializedSize =
+ sizeof (SerializedNameSize) +
+ SerializedNameSize +
+ sizeof (*VendorGuid) +
+ sizeof (Attributes) +
+ sizeof (SerializedDataSize) +
+ DataSize;
+
+ Status = EnsureExtraBufferSpace (
+ Instance,
+ SerializedSize
+ );
+ if (RETURN_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Add name size (UINT32)
+ //
+ AppendToBuffer (Instance, (VOID*) &SerializedNameSize, sizeof (SerializedNameSize));
+
+ //
+ // Add variable unicode name string
+ //
+ AppendToBuffer (Instance, (VOID*) VariableName, SerializedNameSize);
+
+ //
+ // Add variable GUID
+ //
+ AppendToBuffer (Instance, (VOID*) VendorGuid, sizeof (*VendorGuid));
+
+ //
+ // Add variable attributes
+ //
+ AppendToBuffer (Instance, (VOID*) &Attributes, sizeof (Attributes));
+
+ //
+ // Add variable data size (UINT32)
+ //
+ SerializedDataSize = (UINT32) DataSize;
+ AppendToBuffer (Instance, (VOID*) &SerializedDataSize, sizeof (SerializedDataSize));
+
+ //
+ // Add variable data
+ //
+ AppendToBuffer (Instance, Data, DataSize);
+
+ return RETURN_SUCCESS;
+}
+
+
+/**
+ Serializes the variables known to this instance into the
+ provided buffer.
+
+ @param[in] Handle - Handle for a variable serialization instance
+ @param[out] Buffer - A buffer to store the binary representation
+ of the variables.
+ @param[in,out] Size - On input this is the size of the buffer.
+ On output this is the size of the binary representation
+ of the variables.
+
+ @retval RETURN_SUCCESS - The binary representation was successfully
+ completed and returned in the buffer.
+ @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to
+ save the variables to the buffer.
+ @retval RETURN_INVALID_PARAMETER - Handle was not a valid
+ variable serialization instance or
+ Size or Buffer were NULL.
+ @retval RETURN_BUFFER_TOO_SMALL - The Buffer size as indicated by
+ the Size parameter was too small for the serialized
+ variable data. Size is returned with the required size.
+
+**/
+RETURN_STATUS
+EFIAPI
+SerializeVariablesToBuffer (
+ IN EFI_HANDLE Handle,
+ OUT VOID *Buffer,
+ IN OUT UINTN *Size
+ )
+{
+ SV_INSTANCE *Instance;
+
+ Instance = SV_FROM_HANDLE (Handle);
+
+ if (Size == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ if (*Size < Instance->DataSize) {
+ *Size = Instance->DataSize;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+
+ if (Buffer == NULL) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ *Size = Instance->DataSize;
+ CopyMem (Buffer, Instance->BufferPtr, Instance->DataSize);
+
+ return RETURN_SUCCESS;
+}
+
diff --git BhyvePkg/Library/SerializeVariablesLib/SerializeVariablesLib.h BhyvePkg/Library/SerializeVariablesLib/SerializeVariablesLib.h
new file mode 100644
index 0000000..4d01fd6
--- /dev/null
+++ BhyvePkg/Library/SerializeVariablesLib/SerializeVariablesLib.h
@@ -0,0 +1,39 @@
+/** @file
+ Serialize Variables Library implementation
+
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __SERIALIZE_VARIABLES_LIB_INSTANCE__
+#define __SERIALIZE_VARIABLES_LIB_INSTANCE__
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define SV_FROM_HANDLE(a) CR (a, SV_INSTANCE, Signature, SV_SIGNATURE)
+#define SV_SIGNATURE SIGNATURE_32 ('S', 'V', 'A', 'R')
+
+typedef struct {
+ UINT32 Signature;
+ VOID *BufferPtr;
+ UINTN BufferSize;
+ UINTN DataSize;
+} SV_INSTANCE;
+
+#endif
+
diff --git BhyvePkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf BhyvePkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
new file mode 100644
index 0000000..5e66723
--- /dev/null
+++ BhyvePkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
@@ -0,0 +1,41 @@
+## @file
+# Serialize Variables Library implementation
+#
+# This library serializes and deserializes UEFI variables
+#
+# Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeSerializeVariablesLib
+ FILE_GUID = 9515f92a-83ae-45fd-9d2e-e3dc15df52d0
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerializeVariablesLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER UEFI_DRIVER
+
+[Sources]
+ SerializeVariablesLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ BhyvePkg/BhyvePkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+
diff --git BhyvePkg/Library/VirtioLib/VirtioLib.c BhyvePkg/Library/VirtioLib/VirtioLib.c
new file mode 100644
index 0000000..6eeeff0
--- /dev/null
+++ BhyvePkg/Library/VirtioLib/VirtioLib.c
@@ -0,0 +1,461 @@
+/** @file
+
+ Utility functions used by virtio device drivers.
+
+ Copyright (C) 2012, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License which accompanies this
+ distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+
+/**
+
+ Write a word into Region 0 of the device specified by PciIo.
+
+ Region 0 must be an iomem region. This is an internal function for the
+ driver-specific VIRTIO_CFG_WRITE() macros.
+
+ @param[in] PciIo Target PCI device.
+
+ @param[in] FieldOffset Destination offset.
+
+ @param[in] FieldSize Destination field size, must be in { 1, 2, 4, 8 }.
+
+ @param[in] Value Little endian value to write, converted to UINT64.
+ The least significant FieldSize bytes will be used.
+
+
+ @return Status code returned by PciIo->Io.Write().
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioWrite (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINT64 Value
+ )
+{
+ UINTN Count;
+ EFI_PCI_IO_PROTOCOL_WIDTH Width;
+
+ Count = 1;
+ switch (FieldSize) {
+ case 1:
+ Width = EfiPciIoWidthUint8;
+ break;
+
+ case 2:
+ Width = EfiPciIoWidthUint16;
+ break;
+
+ case 8:
+ Count = 2;
+ // fall through
+
+ case 4:
+ Width = EfiPciIoWidthUint32;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciIo->Io.Write (
+ PciIo,
+ Width,
+ PCI_BAR_IDX0,
+ FieldOffset,
+ Count,
+ &Value
+ );
+}
+
+
+/**
+
+ Read a word from Region 0 of the device specified by PciIo.
+
+ Region 0 must be an iomem region. This is an internal function for the
+ driver-specific VIRTIO_CFG_READ() macros.
+
+ @param[in] PciIo Source PCI device.
+
+ @param[in] FieldOffset Source offset.
+
+ @param[in] FieldSize Source field size, must be in { 1, 2, 4, 8 }.
+
+ @param[in] BufferSize Number of bytes available in the target buffer. Must
+ equal FieldSize.
+
+ @param[out] Buffer Target buffer.
+
+
+ @return Status code returned by PciIo->Io.Read().
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioRead (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINTN FieldOffset,
+ IN UINTN FieldSize,
+ IN UINTN BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ UINTN Count;
+ EFI_PCI_IO_PROTOCOL_WIDTH Width;
+
+ ASSERT (FieldSize == BufferSize);
+
+ Count = 1;
+ switch (FieldSize) {
+ case 1:
+ Width = EfiPciIoWidthUint8;
+ break;
+
+ case 2:
+ Width = EfiPciIoWidthUint16;
+ break;
+
+ case 8:
+ Count = 2;
+ // fall through
+
+ case 4:
+ Width = EfiPciIoWidthUint32;
+ break;
+
+ default:
+ ASSERT (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return PciIo->Io.Read (
+ PciIo,
+ Width,
+ PCI_BAR_IDX0,
+ FieldOffset,
+ Count,
+ Buffer
+ );
+}
+
+
+/**
+
+ Configure a virtio ring.
+
+ This function sets up internal storage (the guest-host communication area)
+ and lays out several "navigation" (ie. no-ownership) pointers to parts of
+ that storage.
+
+ Relevant sections from the virtio-0.9.5 spec:
+ - 1.1 Virtqueues,
+ - 2.3 Virtqueue Configuration.
+
+ @param[in] The number of descriptors to allocate for the
+ virtio ring, as requested by the host.
+
+ @param[out] Ring The virtio ring to set up.
+
+ @retval EFI_OUT_OF_RESOURCES AllocatePages() failed to allocate contiguous
+ pages for the requested QueueSize. Fields of
+ Ring have indeterminate value.
+
+ @retval EFI_SUCCESS Allocation and setup successful. Ring->Base
+ (and nothing else) is responsible for
+ deallocation.
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioRingInit (
+ IN UINT16 QueueSize,
+ OUT VRING *Ring
+ )
+{
+ UINTN RingSize;
+ volatile UINT8 *RingPagesPtr;
+
+ RingSize = ALIGN_VALUE (
+ sizeof *Ring->Desc * QueueSize +
+ sizeof *Ring->Avail.Flags +
+ sizeof *Ring->Avail.Idx +
+ sizeof *Ring->Avail.Ring * QueueSize +
+ sizeof *Ring->Avail.UsedEvent,
+ EFI_PAGE_SIZE);
+
+ RingSize += ALIGN_VALUE (
+ sizeof *Ring->Used.Flags +
+ sizeof *Ring->Used.Idx +
+ sizeof *Ring->Used.UsedElem * QueueSize +
+ sizeof *Ring->Used.AvailEvent,
+ EFI_PAGE_SIZE);
+
+ Ring->NumPages = EFI_SIZE_TO_PAGES (RingSize);
+ Ring->Base = AllocatePages (Ring->NumPages);
+ if (Ring->Base == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ SetMem (Ring->Base, RingSize, 0x00);
+ RingPagesPtr = Ring->Base;
+
+ Ring->Desc = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Desc * QueueSize;
+
+ Ring->Avail.Flags = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Avail.Flags;
+
+ Ring->Avail.Idx = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Avail.Idx;
+
+ Ring->Avail.Ring = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Avail.Ring * QueueSize;
+
+ Ring->Avail.UsedEvent = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Avail.UsedEvent;
+
+ RingPagesPtr = (volatile UINT8 *) Ring->Base +
+ ALIGN_VALUE (RingPagesPtr - (volatile UINT8 *) Ring->Base,
+ EFI_PAGE_SIZE);
+
+ Ring->Used.Flags = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Used.Flags;
+
+ Ring->Used.Idx = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Used.Idx;
+
+ Ring->Used.UsedElem = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Used.UsedElem * QueueSize;
+
+ Ring->Used.AvailEvent = (volatile VOID *) RingPagesPtr;
+ RingPagesPtr += sizeof *Ring->Used.AvailEvent;
+
+ Ring->QueueSize = QueueSize;
+ return EFI_SUCCESS;
+}
+
+
+/**
+
+ Tear down the internal resources of a configured virtio ring.
+
+ The caller is responsible to stop the host from using this ring before
+ invoking this function: the VSTAT_DRIVER_OK bit must be clear in
+ VhdrDeviceStatus.
+
+ @param[out] Ring The virtio ring to clean up.
+
+**/
+VOID
+EFIAPI
+VirtioRingUninit (
+ IN OUT VRING *Ring
+ )
+{
+ FreePages (Ring->Base, Ring->NumPages);
+ SetMem (Ring, sizeof *Ring, 0x00);
+}
+
+
+/**
+
+ Turn off interrupt notifications from the host, and prepare for appending
+ multiple descriptors to the virtio ring.
+
+ The calling driver must be in VSTAT_DRIVER_OK state.
+
+ @param[in,out] Ring The virtio ring we intend to append descriptors to.
+
+ @param[out] Indices The DESC_INDICES structure to initialize.
+
+**/
+VOID
+EFIAPI
+VirtioPrepare (
+ IN OUT VRING *Ring,
+ OUT DESC_INDICES *Indices
+ )
+{
+ //
+ // Prepare for virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device.
+ // We're going to poll the answer, the host should not send an interrupt.
+ //
+ *Ring->Avail.Flags = (UINT16) VRING_AVAIL_F_NO_INTERRUPT;
+
+ //
+ // Prepare for virtio-0.9.5, 2.4.1 Supplying Buffers to the Device.
+ //
+ // Since we support only one in-flight descriptor chain, we can always build
+ // that chain starting at entry #0 of the descriptor table.
+ //
+ Indices->HeadDescIdx = 0;
+ Indices->NextDescIdx = Indices->HeadDescIdx;
+}
+
+
+/**
+
+ Append a contiguous buffer for transmission / reception via the virtio ring.
+
+ This function implements the following section from virtio-0.9.5:
+ - 2.4.1.1 Placing Buffers into the Descriptor Table
+
+ Free space is taken as granted, since the individual drivers support only
+ synchronous requests and host side status is processed in lock-step with
+ request submission. It is the calling driver's responsibility to verify the
+ ring size in advance.
+
+ The caller is responsible for initializing *Indices with VirtioPrepare()
+ first.
+
+ @param[in,out] Ring The virtio ring to append the buffer to, as a
+ descriptor.
+
+ @param[in] BufferPhysAddr (Guest pseudo-physical) start address of the
+ transmit / receive buffer.
+
+ @param[in] BufferSize Number of bytes to transmit or receive.
+
+ @param[in] Flags A bitmask of VRING_DESC_F_* flags. The caller
+ computes this mask dependent on further buffers to
+ append and transfer direction.
+ VRING_DESC_F_INDIRECT is unsupported. The
+ VRING_DESC.Next field is always set, but the host
+ only interprets it dependent on VRING_DESC_F_NEXT.
+
+ @param[in,out] Indices Indices->HeadDescIdx is not accessed.
+ On input, Indices->NextDescIdx identifies the next
+ descriptor to carry the buffer. On output,
+ Indices->NextDescIdx is incremented by one, modulo
+ 2^16.
+
+**/
+VOID
+EFIAPI
+VirtioAppendDesc (
+ IN OUT VRING *Ring,
+ IN UINTN BufferPhysAddr,
+ IN UINT32 BufferSize,
+ IN UINT16 Flags,
+ IN OUT DESC_INDICES *Indices
+ )
+{
+ volatile VRING_DESC *Desc;
+
+ Desc = &Ring->Desc[Indices->NextDescIdx++ % Ring->QueueSize];
+ Desc->Addr = BufferPhysAddr;
+ Desc->Len = BufferSize;
+ Desc->Flags = Flags;
+ Desc->Next = Indices->NextDescIdx % Ring->QueueSize;
+}
+
+
+/**
+
+ Notify the host about the descriptor chain just built, and wait until the
+ host processes it.
+
+ @param[in] PciIo The target virtio PCI device to notify.
+
+ @param[in] VirtQueueId Identifies the queue for the target device.
+
+ @param[in,out] Ring The virtio ring with descriptors to submit.
+
+ @param[in] Indices Indices->NextDescIdx is not accessed.
+ Indices->HeadDescIdx identifies the head descriptor
+ of the descriptor chain.
+
+
+ @return Error code from VirtioWrite() if it fails.
+
+ @retval EFI_SUCCESS Otherwise, the host processed all descriptors.
+
+**/
+EFI_STATUS
+EFIAPI
+VirtioFlush (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 VirtQueueId,
+ IN OUT VRING *Ring,
+ IN DESC_INDICES *Indices
+ )
+{
+ UINT16 NextAvailIdx;
+ EFI_STATUS Status;
+ UINTN PollPeriodUsecs;
+
+ //
+ // virtio-0.9.5, 2.4.1.2 Updating the Available Ring
+ //
+ // It is not exactly clear from the wording of the virtio-0.9.5
+ // specification, but each entry in the Available Ring references only the
+ // head descriptor of any given descriptor chain.
+ //
+ NextAvailIdx = *Ring->Avail.Idx;
+ Ring->Avail.Ring[NextAvailIdx++ % Ring->QueueSize] =
+ Indices->HeadDescIdx % Ring->QueueSize;
+
+ //
+ // virtio-0.9.5, 2.4.1.3 Updating the Index Field
+ //
+ MemoryFence();
+ *Ring->Avail.Idx = NextAvailIdx;
+
+ //
+ // virtio-0.9.5, 2.4.1.4 Notifying the Device -- gratuitous notifications are
+ // OK.
+ //
+ MemoryFence();
+ Status = VirtioWrite (
+ PciIo,
+ OFFSET_OF (VIRTIO_HDR, VhdrQueueNotify),
+ sizeof (UINT16),
+ VirtQueueId
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device
+ // Wait until the host processes and acknowledges our descriptor chain. The
+ // condition we use for polling is greatly simplified and relies on the
+ // synchronous, lock-step progress.
+ //
+ // Keep slowing down until we reach a poll period of slightly above 1 ms.
+ //
+ PollPeriodUsecs = 1;
+ MemoryFence();
+ while (*Ring->Used.Idx != NextAvailIdx) {
+ gBS->Stall (PollPeriodUsecs); // calls AcpiTimerLib::MicroSecondDelay
+
+ if (PollPeriodUsecs < 1024) {
+ PollPeriodUsecs *= 2;
+ }
+ MemoryFence();
+ }
+
+ MemoryFence();
+ return EFI_SUCCESS;
+}
diff --git BhyvePkg/Library/VirtioLib/VirtioLib.inf BhyvePkg/Library/VirtioLib/VirtioLib.inf
new file mode 100644
index 0000000..92895d7
--- /dev/null
+++ BhyvePkg/Library/VirtioLib/VirtioLib.inf
@@ -0,0 +1,36 @@
+## @file
+# Library of virtio utility functions.
+#
+# Copyright (C) 2012, Red Hat, Inc.
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License which accompanies this
+# distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = VirtioLib
+ FILE_GUID = 90CED1D9-18F2-47CC-BF24-41EC29406637
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = VirtioLib
+
+[Sources]
+ VirtioLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ BhyvePkg/BhyvePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
diff --git BhyvePkg/PlatformPei/Cmos.c BhyvePkg/PlatformPei/Cmos.c
new file mode 100644
index 0000000..c1ef83d
--- /dev/null
+++ BhyvePkg/PlatformPei/Cmos.c
@@ -0,0 +1,64 @@
+/** @file
+ PC/AT CMOS access routines
+
+ Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "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 BhyvePkg/PlatformPei/Cmos.h BhyvePkg/PlatformPei/Cmos.h
new file mode 100644
index 0000000..eba9791
--- /dev/null
+++ BhyvePkg/PlatformPei/Cmos.h
@@ -0,0 +1,56 @@
+/** @file
+ PC/AT CMOS access routines
+
+ Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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 BhyvePkg/PlatformPei/Fv.c BhyvePkg/PlatformPei/Fv.c
new file mode 100644
index 0000000..9169229
--- /dev/null
+++ BhyvePkg/PlatformPei/Fv.c
@@ -0,0 +1,58 @@
+/** @file
+ Build FV related hobs for platform.
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PiPei.h"
+#include
+#include
+#include
+#include
+
+
+/**
+ Perform a call-back into the SEC simulator to get address of the Firmware Hub
+
+ @param FfsHeader Ffs Header availible to every PEIM
+ @param PeiServices General purpose services available to every PEIM.
+
+ @retval EFI_SUCCESS Platform PEI FVs were initialized successfully.
+
+**/
+EFI_STATUS
+PeiFvInitialization (
+ VOID
+ )
+{
+ DEBUG ((EFI_D_ERROR, "Platform PEI Firmware Volume Initialization\n"));
+
+ DEBUG (
+ (EFI_D_ERROR, "Firmware Volume HOB: 0x%x 0x%x\n",
+ PcdGet32 (PcdBhyveMemFvBase),
+ PcdGet32 (PcdBhyveMemFvSize)
+ )
+ );
+
+ BuildFvHob (PcdGet32 (PcdBhyveMemFvBase), PcdGet32 (PcdBhyveMemFvSize));
+
+ //
+ // Create a memory allocation HOB.
+ //
+ BuildMemoryAllocationHob (
+ PcdGet32 (PcdBhyveMemFvBase),
+ PcdGet32 (PcdBhyveMemFvSize),
+ EfiBootServicesData
+ );
+
+ return EFI_SUCCESS;
+}
+
diff --git BhyvePkg/PlatformPei/MemDetect.c BhyvePkg/PlatformPei/MemDetect.c
new file mode 100644
index 0000000..9bd0862
--- /dev/null
+++ BhyvePkg/PlatformPei/MemDetect.c
@@ -0,0 +1,146 @@
+/**@file
+ Memory Detection for Virtual Machines.
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ MemDetect.c
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include
+
+//
+// The Library classes this module consumes
+//
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "Platform.h"
+#include "Cmos.h"
+
+STATIC
+UINTN
+GetSystemMemorySizeBelow4gb (
+ )
+{
+ 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 (((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);
+}
+
+
+/**
+ Peform Memory Detection
+
+ @return EFI_SUCCESS The PEIM initialized successfully.
+
+**/
+EFI_PHYSICAL_ADDRESS
+MemDetect (
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS MemoryBase;
+ UINT64 MemorySize;
+ UINT64 LowerMemorySize;
+ UINT64 UpperMemorySize;
+
+ DEBUG ((EFI_D_ERROR, "MemDetect called\n"));
+
+ //
+ // Determine total memory size available
+ //
+ LowerMemorySize = GetSystemMemorySizeBelow4gb ();
+ UpperMemorySize = GetSystemMemorySizeAbove4gb ();
+
+ //
+ // Determine the range of memory to use during PEI
+ //
+ MemoryBase = PcdGet32 (PcdBhyveMemFvBase) + PcdGet32 (PcdBhyveMemFvSize);
+ MemorySize = LowerMemorySize - MemoryBase;
+ if (MemorySize > SIZE_64MB) {
+ MemoryBase = LowerMemorySize - SIZE_64MB;
+ MemorySize = SIZE_64MB;
+ }
+
+ //
+ // Publish this memory to the PEI Core
+ //
+ Status = PublishSystemMemory(MemoryBase, MemorySize);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Create memory HOBs
+ //
+ AddMemoryBaseSizeHob (MemoryBase, MemorySize);
+ AddMemoryRangeHob (BASE_1MB, MemoryBase);
+ AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
+
+ MtrrSetMemoryAttribute (BASE_1MB, MemoryBase + MemorySize - BASE_1MB, CacheWriteBack);
+
+ MtrrSetMemoryAttribute (0, BASE_512KB + BASE_128KB, CacheWriteBack);
+
+ if (UpperMemorySize != 0) {
+ AddUntestedMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);
+
+ MtrrSetMemoryAttribute (BASE_4GB, UpperMemorySize, CacheWriteBack);
+ }
+
+ return MemoryBase + MemorySize;
+}
+
diff --git BhyvePkg/PlatformPei/Platform.c BhyvePkg/PlatformPei/Platform.c
new file mode 100644
index 0000000..00cc7fc
--- /dev/null
+++ BhyvePkg/PlatformPei/Platform.c
@@ -0,0 +1,359 @@
+/**@file
+ Platform PEI driver
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.
+ Copyright (c) 2011, Andrei Warkentin
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include
+
+//
+// The Library classes this module consumes
+//
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include