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 +#include + +#include "Platform.h" +#include "Cmos.h" + +EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = { + { EfiACPIMemoryNVS, 0x004 }, + { EfiACPIReclaimMemory, 0x008 }, + { EfiReservedMemoryType, 0x004 }, + { EfiRuntimeServicesData, 0x024 }, + { EfiRuntimeServicesCode, 0x030 }, + { EfiBootServicesCode, 0x180 }, + { EfiBootServicesData, 0xF00 }, + { EfiMaxMemoryType, 0x000 } +}; + + +EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiMasterBootModePpiGuid, + NULL + } +}; + + +VOID +AddIoMemoryBaseSizeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + UINT64 MemorySize + ) +{ + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_MAPPED_IO, + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED, + MemoryBase, + MemorySize + ); +} + +VOID +AddReservedMemoryBaseSizeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + UINT64 MemorySize + ) +{ + BuildResourceDescriptorHob ( + EFI_RESOURCE_MEMORY_RESERVED, + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED, + MemoryBase, + MemorySize + ); +} + +VOID +AddIoMemoryRangeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + EFI_PHYSICAL_ADDRESS MemoryLimit + ) +{ + AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase)); +} + + +VOID +AddMemoryBaseSizeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + UINT64 MemorySize + ) +{ + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_TESTED, + MemoryBase, + MemorySize + ); +} + + +VOID +AddMemoryRangeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + EFI_PHYSICAL_ADDRESS MemoryLimit + ) +{ + AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase)); +} + + +VOID +AddUntestedMemoryBaseSizeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + UINT64 MemorySize + ) +{ + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE, + MemoryBase, + MemorySize + ); +} + + +VOID +AddUntestedMemoryRangeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + EFI_PHYSICAL_ADDRESS MemoryLimit + ) +{ + AddUntestedMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase)); +} + + +VOID +MemMapInitialization ( + EFI_PHYSICAL_ADDRESS TopOfMemory + ) +{ + // + // Create Memory Type Information HOB + // + BuildGuidDataHob ( + &gEfiMemoryTypeInformationGuid, + mDefaultMemoryTypeInformation, + sizeof(mDefaultMemoryTypeInformation) + ); + + // + // Add PCI IO Port space available for PCI resource allocations. + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_IO, + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED, + 0xC000, + 0x4000 + ); + + // + // Video memory + Legacy BIOS region + // + AddIoMemoryRangeHob (0x0A0000, BASE_1MB); + + // + // address purpose size + // ------------ -------- ------------------------- + // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g) + // 0xFC000000 gap 44 MB + // 0xFEC00000 IO-APIC 4 KB + // 0xFEC01000 gap 1020 KB + // 0xFED00000 HPET 1 KB + // 0xFED00400 gap 1023 KB + // 0xFEE00000 LAPIC 1 MB + // + AddIoMemoryRangeHob (TopOfMemory < BASE_2GB ? BASE_2GB : TopOfMemory, 0xFC000000); + AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB); + AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB); + AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB); +} + + +VOID +MiscInitialization ( + VOID + ) +{ + // + // Disable A20 Mask + // + IoOr8 (0x92, BIT1); + + // + // Build the CPU hob with 36-bit addressing and 16-bits of IO space. + // + BuildCpuHob (36, 16); + + // + // If PMREGMISC/PMIOSE is set, assume the ACPI PMBA has been configured (for + // example by Xen) and skip the setup here. This matches the logic in + // AcpiTimerLibConstructor (). + // + if ((PciRead8 (PCI_LIB_ADDRESS (0, 1, 3, 0x80)) & 0x01) == 0) { + // + // The PEI phase should be exited with fully accessibe PIIX4 IO space: + // 1. set PMBA + // + PciAndThenOr32 ( + PCI_LIB_ADDRESS (0, 1, 3, 0x40), + (UINT32) ~0xFFC0, + PcdGet16 (PcdAcpiPmBaseAddress) + ); + + // + // 2. set PCICMD/IOSE + // + PciOr8 ( + PCI_LIB_ADDRESS (0, 1, 3, PCI_COMMAND_OFFSET), + EFI_PCI_COMMAND_IO_SPACE + ); + + // + // 3. set PMREGMISC/PMIOSE + // + PciOr8 (PCI_LIB_ADDRESS (0, 1, 3, 0x80), 0x01); + } +} + + +VOID +BootModeInitialization ( + ) +{ + EFI_STATUS Status; + + Status = PeiServicesSetBootMode (BOOT_WITH_FULL_CONFIGURATION); + ASSERT_EFI_ERROR (Status); + + Status = PeiServicesInstallPpi (mPpiBootMode); + ASSERT_EFI_ERROR (Status); +} + + +VOID +ReserveEmuVariableNvStore ( + ) +{ + EFI_PHYSICAL_ADDRESS VariableStore; + + // + // Allocate storage for NV variables early on so it will be + // at a consistent address. Since VM memory is preserved + // across reboots, this allows the NV variable storage to survive + // a VM reboot. + // + VariableStore = + (EFI_PHYSICAL_ADDRESS)(UINTN) + AllocateAlignedRuntimePages ( + EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)), + PcdGet32 (PcdFlashNvStorageFtwSpareSize) + ); + DEBUG ((EFI_D_INFO, + "Reserved variable store memory: 0x%lX; size: %dkb\n", + VariableStore, + (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024 + )); + PcdSet64 (PcdEmuVariableNvStoreReserved, VariableStore); +} + + +VOID +DebugDumpCmos ( + VOID + ) +{ + UINTN Loop; + + DEBUG ((EFI_D_INFO, "CMOS:\n")); + + for (Loop = 0; Loop < 0x80; Loop++) { + if ((Loop % 0x10) == 0) { + DEBUG ((EFI_D_INFO, "%02x:", Loop)); + } + DEBUG ((EFI_D_INFO, " %02x", CmosRead8 (Loop))); + if ((Loop % 0x10) == 0xf) { + DEBUG ((EFI_D_INFO, "\n")); + } + } +} + + +/** + Perform Platform PEI initialization. + + @param FileHandle Handle of the file being invoked. + @param PeiServices Describes the list of possible PEI Services. + + @return EFI_SUCCESS The PEIM initialized successfully. + +**/ +EFI_STATUS +EFIAPI +InitializePlatform ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_PHYSICAL_ADDRESS TopOfMemory; + + DEBUG ((EFI_D_ERROR, "Platform PEIM Loaded\n")); + + DebugDumpCmos (); + + TopOfMemory = MemDetect (); + + ReserveEmuVariableNvStore (); + + PeiFvInitialization (); + + MemMapInitialization (TopOfMemory); + + MiscInitialization (); + + BootModeInitialization (); + + return EFI_SUCCESS; +} diff --git BhyvePkg/PlatformPei/Platform.h BhyvePkg/PlatformPei/Platform.h new file mode 100644 index 0000000..feac8d5 --- /dev/null +++ BhyvePkg/PlatformPei/Platform.h @@ -0,0 +1,70 @@ +/** @file + Platform PEI module include file. + + 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 _PLATFORM_PEI_H_INCLUDED_ +#define _PLATFORM_PEI_H_INCLUDED_ + +VOID +AddIoMemoryBaseSizeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + UINT64 MemorySize + ); + +VOID +AddIoMemoryRangeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + EFI_PHYSICAL_ADDRESS MemoryLimit + ); + +VOID +AddMemoryBaseSizeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + UINT64 MemorySize + ); + +VOID +AddMemoryRangeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + EFI_PHYSICAL_ADDRESS MemoryLimit + ); + +VOID +AddUntestedMemoryBaseSizeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + UINT64 MemorySize + ); + +VOID +AddReservedMemoryBaseSizeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + UINT64 MemorySize + ); + +VOID +AddUntestedMemoryRangeHob ( + EFI_PHYSICAL_ADDRESS MemoryBase, + EFI_PHYSICAL_ADDRESS MemoryLimit + ); + +EFI_PHYSICAL_ADDRESS +MemDetect ( + VOID + ); + +EFI_STATUS +PeiFvInitialization ( + VOID + ); + +#endif // _PLATFORM_PEI_H_INCLUDED_ diff --git BhyvePkg/PlatformPei/PlatformPei.inf BhyvePkg/PlatformPei/PlatformPei.inf new file mode 100644 index 0000000..318a6c2 --- /dev/null +++ BhyvePkg/PlatformPei/PlatformPei.inf @@ -0,0 +1,73 @@ +## @file +# Platform PEI driver +# +# This module provides platform specific function to detect boot mode. +# 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 = PlatformPei + FILE_GUID = 222c386d-5abc-4fb4-b124-fbb82488acf4 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + ENTRY_POINT = InitializePlatform + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + Cmos.c + Fv.c + MemDetect.c + Platform.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + BhyvePkg/BhyvePkg.dec + +[Guids] + gEfiMemoryTypeInformationGuid + +[LibraryClasses] + DebugLib + HobLib + IoLib + PciLib + PeiResourcePublicationLib + PeiServicesLib + PeiServicesTablePointerLib + PeimEntryPoint + MtrrLib + PcdLib + +[Pcd] + gUefiBhyvePkgTokenSpaceGuid.PcdBhyveMemFvBase + gUefiBhyvePkgTokenSpaceGuid.PcdBhyveMemFvSize + gUefiBhyvePkgTokenSpaceGuid.PcdAcpiPmBaseAddress + gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize + gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved + gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress + +[Ppis] + gEfiPeiMasterBootModePpiGuid + +[Depex] + TRUE + diff --git BhyvePkg/ResetVector/Ia32/PageTables64.asm BhyvePkg/ResetVector/Ia32/PageTables64.asm new file mode 100644 index 0000000..cb0e871 --- /dev/null +++ BhyvePkg/ResetVector/Ia32/PageTables64.asm @@ -0,0 +1,91 @@ +;------------------------------------------------------------------------------ +; @file +; Sets the CR3 register for 64-bit paging +; +; Copyright (c) 2008 - 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. +; +;------------------------------------------------------------------------------ + +BITS 32 + +%define PAGE_PRESENT 0x01 +%define PAGE_READ_WRITE 0x02 +%define PAGE_USER_SUPERVISOR 0x04 +%define PAGE_WRITE_THROUGH 0x08 +%define PAGE_CACHE_DISABLE 0x010 +%define PAGE_ACCESSED 0x020 +%define PAGE_DIRTY 0x040 +%define PAGE_PAT 0x080 +%define PAGE_GLOBAL 0x0100 +%define PAGE_2M_MBO 0x080 +%define PAGE_2M_PAT 0x01000 + +%define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \ + PAGE_ACCESSED + \ + PAGE_DIRTY + \ + PAGE_READ_WRITE + \ + PAGE_PRESENT) + +%define PAGE_PDP_ATTR (PAGE_ACCESSED + \ + PAGE_READ_WRITE + \ + PAGE_PRESENT) + + +; +; Modified: EAX, ECX +; +SetCr3ForPageTables64: + + ; + ; For OVMF, build some initial page tables at 0x80000. This is just + ; after the early stack/temp RAM. + ; + ; At the end of PEI, the pages tables will be rebuilt into a + ; more permanent location by DxeIpl. + ; + + mov ecx, 6 * 0x1000 / 4 + xor eax, eax +clearPageTablesMemoryLoop: + mov dword[ecx * 4 + 0x80000 - 4], eax + loop clearPageTablesMemoryLoop + + ; + ; Top level Page Directory Pointers (1 * 512GB entry) + ; + mov dword[0x80000], 0x81000 + PAGE_PDP_ATTR + + ; + ; Next level Page Directory Pointers (4 * 1GB entries => 4GB) + ; + mov dword[0x81000], 0x82000 + PAGE_PDP_ATTR + mov dword[0x81008], 0x83000 + PAGE_PDP_ATTR + mov dword[0x81010], 0x84000 + PAGE_PDP_ATTR + mov dword[0x81018], 0x85000 + PAGE_PDP_ATTR + + ; + ; Page Table Entries (2048 * 2MB entries => 4GB) + ; + mov ecx, 0x800 +pageTableEntriesLoop: + mov eax, ecx + dec eax + shl eax, 21 + add eax, PAGE_2M_PDE_ATTR + mov [ecx * 8 + 0x82000 - 8], eax + loop pageTableEntriesLoop + + ; + ; Set CR3 now that the paging structures are available + ; + mov eax, 0x80000 + mov cr3, eax + + OneTimeCallRet SetCr3ForPageTables64 diff --git BhyvePkg/ResetVector/ResetVector.inf BhyvePkg/ResetVector/ResetVector.inf new file mode 100644 index 0000000..0dc67fa --- /dev/null +++ BhyvePkg/ResetVector/ResetVector.inf @@ -0,0 +1,37 @@ +## @file +# Reset Vector +# +# Copyright (c) 2006 - 2014, 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 = ResetVector + FILE_GUID = 1BA0062E-C779-4582-8566-336AE8F78F09 + MODULE_TYPE = SEC + VERSION_STRING = 1.1 + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + ResetVector.nasmb + +[Packages] + MdePkg/MdePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[BuildOptions] + *_*_IA32_NASMB_FLAGS = -I$(WORKSPACE)/UefiCpuPkg/ResetVector/Vtf0/ + *_*_X64_NASMB_FLAGS = -I$(WORKSPACE)/UefiCpuPkg/ResetVector/Vtf0/ diff --git BhyvePkg/ResetVector/ResetVector.nasmb BhyvePkg/ResetVector/ResetVector.nasmb new file mode 100644 index 0000000..e8ad5fb --- /dev/null +++ BhyvePkg/ResetVector/ResetVector.nasmb @@ -0,0 +1,66 @@ +;------------------------------------------------------------------------------ +; @file +; This file includes all other code files to assemble the reset vector code +; +; Copyright (c) 2008 - 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. +; +;------------------------------------------------------------------------------ + +; +; If neither ARCH_IA32 nor ARCH_X64 are defined, then try to include +; Base.h to use the C pre-processor to determine the architecture. +; +%ifndef ARCH_IA32 + %ifndef ARCH_X64 + #include + #if defined (MDE_CPU_IA32) + %define ARCH_IA32 + #elif defined (MDE_CPU_X64) + %define ARCH_X64 + #endif + %endif +%endif + +%ifdef ARCH_IA32 + %ifdef ARCH_X64 + %error "Only one of ARCH_IA32 or ARCH_X64 can be defined." + %endif +%elifdef ARCH_X64 +%else + %error "Either ARCH_IA32 or ARCH_X64 must be defined." +%endif + +%include "CommonMacros.inc" + +%include "PostCodes.inc" + +%ifdef DEBUG_PORT80 + %include "Port80Debug.asm" +%elifdef DEBUG_SERIAL + %include "SerialDebug.asm" +%else + %include "DebugDisabled.asm" +%endif + +%include "Ia32/SearchForBfvBase.asm" +%include "Ia32/SearchForSecEntry.asm" + +%ifdef ARCH_X64 +%include "Ia32/Flat32ToFlat64.asm" +%include "Ia32/PageTables64.asm" +%endif + +%include "Ia16/Real16ToFlat32.asm" +%include "Ia16/Init16.asm" + +%include "Main.asm" + +%include "Ia16/ResetVectorVtf0.asm" + diff --git BhyvePkg/ResetVector/ResetVectorCode.asm BhyvePkg/ResetVector/ResetVectorCode.asm new file mode 100644 index 0000000..a5fe6e3 --- /dev/null +++ BhyvePkg/ResetVector/ResetVectorCode.asm @@ -0,0 +1,53 @@ +;------------------------------------------------------------------------------ +; @file +; This file includes all other code files to assemble the reset vector code +; +; Copyright (c) 2008 - 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. +; +;------------------------------------------------------------------------------ + +%ifdef ARCH_IA32 + %ifdef ARCH_X64 + %error "Only one of ARCH_IA32 or ARCH_X64 can be defined." + %endif +%elifdef ARCH_X64 +%else + %error "Either ARCH_IA32 or ARCH_X64 must be defined." +%endif + +%include "CommonMacros.inc" + +%include "PostCodes.inc" + +%ifdef DEBUG_NONE + %include "DebugDisabled.asm" +%elifdef DEBUG_PORT80 + %include "Port80Debug.asm" +%elifdef DEBUG_SERIAL + %include "SerialDebug.asm" +%else + %error "No debug type was specified." +%endif + +%include "Ia32/SearchForBfvBase.asm" +%include "Ia32/SearchForSecEntry.asm" + +%ifdef ARCH_X64 +%include "Ia32/Flat32ToFlat64.asm" +%include "Ia32/PageTables64.asm" +%endif + +%include "Ia16/Real16ToFlat32.asm" +%include "Ia16/Init16.asm" + +%include "Main.asm" + +%include "Ia16/ResetVectorVtf0.asm" + diff --git BhyvePkg/Sec/Ia32/SecEntry.S BhyvePkg/Sec/Ia32/SecEntry.S new file mode 100644 index 0000000..a1b0c0d --- /dev/null +++ BhyvePkg/Sec/Ia32/SecEntry.S @@ -0,0 +1,55 @@ +# TITLE SecEntry.asm +#------------------------------------------------------------------------------ +#* +#* 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. +#* +#* CpuAsm.asm +#* +#* Abstract: +#* +#------------------------------------------------------------------------------ + + +#include + +#EXTERN ASM_PFX(SecCoreStartupWithStack) + +# +# SecCore Entry Point +# +# Processor is in flat protected mode +# +# @param[in] EAX Initial value of the EAX register (BIST: Built-in Self Test) +# @param[in] DI 'BP': boot-strap processor, or 'AP': application processor +# @param[in] EBP Pointer to the start of the Boot Firmware Volume +# +# @return None This routine does not return +# +ASM_GLOBAL ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + + # + # Load temporary stack top at very low memory. The C code + # can reload to a better address. + # + movl $BASE_512KB, %eax + movl %eax, %esp + nop + + # + # Call into C code + # + pushl %eax + pushl %ebp + call ASM_PFX(SecCoreStartupWithStack) + + +#END + diff --git BhyvePkg/Sec/Ia32/SecEntry.asm BhyvePkg/Sec/Ia32/SecEntry.asm new file mode 100644 index 0000000..eb617b3 --- /dev/null +++ BhyvePkg/Sec/Ia32/SecEntry.asm @@ -0,0 +1,57 @@ + TITLE SecEntry.asm +;------------------------------------------------------------------------------ +;* +;* 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. +;* +;* CpuAsm.asm +;* +;* Abstract: +;* +;------------------------------------------------------------------------------ + +#include + + .686 + .model flat,C + .code + +EXTERN SecCoreStartupWithStack:PROC + +; +; SecCore Entry Point +; +; Processor is in flat protected mode +; +; @param[in] EAX Initial value of the EAX register (BIST: Built-in Self Test) +; @param[in] DI 'BP': boot-strap processor, or 'AP': application processor +; @param[in] EBP Pointer to the start of the Boot Firmware Volume +; +; @return None This routine does not return +; +_ModuleEntryPoint PROC PUBLIC + + ; + ; Load temporary stack top at very low memory. The C code + ; can reload to a better address. + ; + mov eax, BASE_512KB + mov esp, eax + nop + + ; + ; Call into C code + ; + push eax + push ebp + call SecCoreStartupWithStack + +_ModuleEntryPoint ENDP + +END diff --git BhyvePkg/Sec/SecMain.c BhyvePkg/Sec/SecMain.c new file mode 100644 index 0000000..95cc1df --- /dev/null +++ BhyvePkg/Sec/SecMain.c @@ -0,0 +1,765 @@ +/** @file + Main SEC phase code. Transitions to PEI. + + 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SEC_IDT_ENTRY_COUNT 34 + +typedef struct _SEC_IDT_TABLE { + EFI_PEI_SERVICES *PeiService; + IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT]; +} SEC_IDT_TABLE; + +VOID +EFIAPI +SecStartupPhase2 ( + IN VOID *Context + ); + +EFI_STATUS +EFIAPI +TemporaryRamMigration ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ); + +// +// +// +EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = { + TemporaryRamMigration +}; + +EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = { + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiTemporaryRamSupportPpiGuid, + &mTemporaryRamSupportPpi + }, +}; + +// +// Template of an IDT entry pointing to 10:FFFFFFE4h. +// +IA32_IDT_GATE_DESCRIPTOR mIdtEntryTemplate = { + { // Bits + 0xffe4, // OffsetLow + 0x10, // Selector + 0x0, // Reserved_0 + IA32_IDT_GATE_TYPE_INTERRUPT_32, // GateType + 0xffff // OffsetHigh + } +}; + +/** + Locates the main boot firmware volume. + + @param[in,out] BootFv On input, the base of the BootFv + On output, the decompressed main firmware volume + + @retval EFI_SUCCESS The main firmware volume was located and decompressed + @retval EFI_NOT_FOUND The main firmware volume was not found + +**/ +EFI_STATUS +FindMainFv ( + IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *Fv; + UINTN Distance; + + ASSERT (((UINTN) *BootFv & EFI_PAGE_MASK) == 0); + + Fv = *BootFv; + Distance = (UINTN) (*BootFv)->FvLength; + do { + Fv = (EFI_FIRMWARE_VOLUME_HEADER*) ((UINT8*) Fv - EFI_PAGE_SIZE); + Distance += EFI_PAGE_SIZE; + if (Distance > SIZE_32MB) { + return EFI_NOT_FOUND; + } + + if (Fv->Signature != EFI_FVH_SIGNATURE) { + continue; + } + + if ((UINTN) Fv->FvLength > Distance) { + continue; + } + + *BootFv = Fv; + return EFI_SUCCESS; + + } while (TRUE); +} + +/** + Locates a section within a series of sections + with the specified section type. + + @param[in] Sections The sections to search + @param[in] SizeOfSections Total size of all sections + @param[in] SectionType The section type to locate + @param[out] FoundSection The FFS section if found + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +FindFfsSectionInSections ( + IN VOID *Sections, + IN UINTN SizeOfSections, + IN EFI_SECTION_TYPE SectionType, + OUT EFI_COMMON_SECTION_HEADER **FoundSection + ) +{ + EFI_PHYSICAL_ADDRESS CurrentAddress; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfSections; + EFI_COMMON_SECTION_HEADER *Section; + EFI_PHYSICAL_ADDRESS EndOfSection; + + // + // Loop through the FFS file sections within the PEI Core FFS file + // + EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) Sections; + EndOfSections = EndOfSection + SizeOfSections; + for (;;) { + if (EndOfSection == EndOfSections) { + break; + } + CurrentAddress = (EndOfSection + 3) & ~(3ULL); + if (CurrentAddress >= EndOfSections) { + return EFI_VOLUME_CORRUPTED; + } + + Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; + DEBUG ((EFI_D_INFO, "Section->Type: 0x%x\n", Section->Type)); + + Size = SECTION_SIZE (Section); + if (Size < sizeof (*Section)) { + return EFI_VOLUME_CORRUPTED; + } + + EndOfSection = CurrentAddress + Size; + if (EndOfSection > EndOfSections) { + return EFI_VOLUME_CORRUPTED; + } + + // + // Look for the requested section type + // + if (Section->Type == SectionType) { + *FoundSection = Section; + return EFI_SUCCESS; + } + DEBUG ((EFI_D_INFO, "Section->Type (0x%x) != SectionType (0x%x)\n", Section->Type, SectionType)); + } + + return EFI_NOT_FOUND; +} + +/** + Locates a FFS file with the specified file type and a section + within that file with the specified section type. + + @param[in] Fv The firmware volume to search + @param[in] FileType The file type to locate + @param[in] SectionType The section type to locate + @param[out] FoundSection The FFS section if found + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +EFIAPI +FindFfsFileAndSection ( + IN EFI_FIRMWARE_VOLUME_HEADER *Fv, + IN EFI_FV_FILETYPE FileType, + IN EFI_SECTION_TYPE SectionType, + OUT EFI_COMMON_SECTION_HEADER **FoundSection + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS CurrentAddress; + EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; + EFI_FFS_FILE_HEADER *File; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfFile; + + if (Fv->Signature != EFI_FVH_SIGNATURE) { + DEBUG ((EFI_D_INFO, "FV at %p does not have FV header signature\n", Fv)); + return EFI_VOLUME_CORRUPTED; + } + + CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Fv; + EndOfFirmwareVolume = CurrentAddress + Fv->FvLength; + + // + // Loop through the FFS files in the Boot Firmware Volume + // + for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) { + + CurrentAddress = (EndOfFile + 7) & ~(7ULL); + if (CurrentAddress > EndOfFirmwareVolume) { + return EFI_VOLUME_CORRUPTED; + } + + File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress; + Size = *(UINT32*) File->Size & 0xffffff; + if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) { + return EFI_VOLUME_CORRUPTED; + } + DEBUG ((EFI_D_INFO, "File->Type: 0x%x\n", File->Type)); + + EndOfFile = CurrentAddress + Size; + if (EndOfFile > EndOfFirmwareVolume) { + return EFI_VOLUME_CORRUPTED; + } + + // + // Look for the request file type + // + if (File->Type != FileType) { + DEBUG ((EFI_D_INFO, "File->Type (0x%x) != FileType (0x%x)\n", File->Type, FileType)); + continue; + } + + Status = FindFfsSectionInSections ( + (VOID*) (File + 1), + (UINTN) EndOfFile - (UINTN) (File + 1), + SectionType, + FoundSection + ); + if (!EFI_ERROR (Status) || (Status == EFI_VOLUME_CORRUPTED)) { + return Status; + } + } +} + +/** + Locates the compressed main firmware volume and decompresses it. + + @param[in,out] Fv On input, the firmware volume to search + On output, the decompressed main FV + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +EFIAPI +DecompressGuidedFv ( + IN OUT EFI_FIRMWARE_VOLUME_HEADER **Fv + ) +{ + EFI_STATUS Status; + EFI_GUID_DEFINED_SECTION *Section; + UINT32 OutputBufferSize; + UINT32 ScratchBufferSize; + UINT16 SectionAttribute; + UINT32 AuthenticationStatus; + VOID *OutputBuffer; + VOID *ScratchBuffer; + EFI_FIRMWARE_VOLUME_IMAGE_SECTION *NewFvSection; + EFI_FIRMWARE_VOLUME_HEADER *NewFv; + + NewFvSection = (EFI_FIRMWARE_VOLUME_IMAGE_SECTION*) NULL; + + Status = FindFfsFileAndSection ( + *Fv, + EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, + EFI_SECTION_GUID_DEFINED, + (EFI_COMMON_SECTION_HEADER**) &Section + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Unable to find GUID defined section\n")); + return Status; + } + + Status = ExtractGuidedSectionGetInfo ( + Section, + &OutputBufferSize, + &ScratchBufferSize, + &SectionAttribute + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Unable to GetInfo for GUIDed section\n")); + return Status; + } + + //PcdGet32 (PcdBhyveMemFvBase), PcdGet32 (PcdBhyveMemFvSize) + OutputBuffer = (VOID*) ((UINT8*)(UINTN) PcdGet32 (PcdBhyveMemFvBase) + SIZE_1MB); + ScratchBuffer = ALIGN_POINTER ((UINT8*) OutputBuffer + OutputBufferSize, SIZE_1MB); + Status = ExtractGuidedSectionDecode ( + Section, + &OutputBuffer, + ScratchBuffer, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Error during GUID section decode\n")); + return Status; + } + + Status = FindFfsSectionInSections ( + OutputBuffer, + OutputBufferSize, + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, + (EFI_COMMON_SECTION_HEADER**) &NewFvSection + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Unable to find FV image in extracted data\n")); + return Status; + } + + NewFv = (EFI_FIRMWARE_VOLUME_HEADER*)(UINTN) PcdGet32 (PcdBhyveMemFvBase); + CopyMem (NewFv, (VOID*) (NewFvSection + 1), PcdGet32 (PcdBhyveMemFvSize)); + + if (NewFv->Signature != EFI_FVH_SIGNATURE) { + DEBUG ((EFI_D_ERROR, "Extracted FV at %p does not have FV header signature\n", NewFv)); + CpuDeadLoop (); + return EFI_VOLUME_CORRUPTED; + } + + *Fv = NewFv; + return EFI_SUCCESS; +} + +/** + Locates the PEI Core entry point address + + @param[in] Fv The firmware volume to search + @param[out] PeiCoreEntryPoint The entry point of the PEI Core image + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +EFI_STATUS +EFIAPI +FindPeiCoreImageBaseInFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *Fv, + OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase + ) +{ + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER *Section; + + Status = FindFfsFileAndSection ( + Fv, + EFI_FV_FILETYPE_PEI_CORE, + EFI_SECTION_PE32, + &Section + ); + if (EFI_ERROR (Status)) { + Status = FindFfsFileAndSection ( + Fv, + EFI_FV_FILETYPE_PEI_CORE, + EFI_SECTION_TE, + &Section + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Unable to find PEI Core image\n")); + return Status; + } + } + + *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1); + return EFI_SUCCESS; +} + +/** + Locates the PEI Core entry point address + + @param[in,out] Fv The firmware volume to search + @param[out] PeiCoreEntryPoint The entry point of the PEI Core image + + @retval EFI_SUCCESS The file and section was found + @retval EFI_NOT_FOUND The file and section was not found + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted + +**/ +VOID +EFIAPI +FindPeiCoreImageBase ( + IN OUT EFI_FIRMWARE_VOLUME_HEADER **BootFv, + OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase + ) +{ + *PeiCoreImageBase = 0; + + FindMainFv (BootFv); + + DecompressGuidedFv (BootFv); + + FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase); +} + +/** + Find core image base. + +**/ +EFI_STATUS +EFIAPI +FindImageBase ( + IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr, + OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase + ) +{ + EFI_PHYSICAL_ADDRESS CurrentAddress; + EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; + EFI_FFS_FILE_HEADER *File; + UINT32 Size; + EFI_PHYSICAL_ADDRESS EndOfFile; + EFI_COMMON_SECTION_HEADER *Section; + EFI_PHYSICAL_ADDRESS EndOfSection; + + *SecCoreImageBase = 0; + + CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr; + EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength; + + // + // Loop through the FFS files in the Boot Firmware Volume + // + for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) { + + CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL; + if (CurrentAddress > EndOfFirmwareVolume) { + return EFI_NOT_FOUND; + } + + File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress; + Size = *(UINT32*) File->Size & 0xffffff; + if (Size < sizeof (*File)) { + return EFI_NOT_FOUND; + } + + EndOfFile = CurrentAddress + Size; + if (EndOfFile > EndOfFirmwareVolume) { + return EFI_NOT_FOUND; + } + + // + // Look for SEC Core + // + if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) { + continue; + } + + // + // Loop through the FFS file sections within the FFS file + // + EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN) (File + 1); + for (;;) { + CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL; + Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress; + + Size = *(UINT32*) Section->Size & 0xffffff; + if (Size < sizeof (*Section)) { + return EFI_NOT_FOUND; + } + + EndOfSection = CurrentAddress + Size; + if (EndOfSection > EndOfFile) { + return EFI_NOT_FOUND; + } + + // + // Look for executable sections + // + if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) { + if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) { + *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) (Section + 1); + } + break; + } + } + + // + // SEC Core image found + // + if (*SecCoreImageBase != 0) { + return EFI_SUCCESS; + } + } +} + +/* + Find and return Pei Core entry point. + + It also find SEC and PEI Core file debug inforamtion. It will report them if + remote debug is enabled. + +**/ +VOID +EFIAPI +FindAndReportEntryPoints ( + IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr, + OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS SecCoreImageBase; + EFI_PHYSICAL_ADDRESS PeiCoreImageBase; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + // + // Find SEC Core and PEI Core image base + // + Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase); + ASSERT_EFI_ERROR (Status); + + FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase); + + ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + // + // Report SEC Core debug information when remote debug is enabled + // + ImageContext.ImageAddress = SecCoreImageBase; + ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress); + PeCoffLoaderRelocateImageExtraAction (&ImageContext); + + // + // Report PEI Core debug information when remote debug is enabled + // + ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase; + ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress); + PeCoffLoaderRelocateImageExtraAction (&ImageContext); + + // + // Find PEI Core entry point + // + Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint); + if (EFI_ERROR (Status)) { + *PeiCoreEntryPoint = 0; + } + + return; +} + +VOID +EFIAPI +SecCoreStartupWithStack ( + IN EFI_FIRMWARE_VOLUME_HEADER *BootFv, + IN VOID *TopOfCurrentStack + ) +{ + EFI_SEC_PEI_HAND_OFF SecCoreData; + SEC_IDT_TABLE IdtTableInStack; + IA32_DESCRIPTOR IdtDescriptor; + UINT32 Index; + + ProcessLibraryConstructorList (NULL, NULL); + + DEBUG ((EFI_D_ERROR, + "SecCoreStartupWithStack(0x%x, 0x%x)\n", + (UINT32)(UINTN)BootFv, + (UINT32)(UINTN)TopOfCurrentStack + )); + + // + // Initialize floating point operating environment + // to be compliant with UEFI spec. + // + InitializeFloatingPointUnits (); + + // + // Initialize IDT + // + IdtTableInStack.PeiService = NULL; + for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) { + CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate)); + } + + IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable; + IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1); + + AsmWriteIdtr (&IdtDescriptor); + + // + // |-------------| <-- TopOfCurrentStack + // | Stack | 32k + // |-------------| + // | Heap | 32k + // |-------------| <-- SecCoreData.TemporaryRamBase + // + + // + // Initialize SEC hand-off state + // + SecCoreData.DataSize = sizeof(EFI_SEC_PEI_HAND_OFF); + + SecCoreData.TemporaryRamSize = SIZE_64KB; + SecCoreData.TemporaryRamBase = (VOID*)((UINT8 *)TopOfCurrentStack - SecCoreData.TemporaryRamSize); + + SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; + SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1; + + SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize; + SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1; + + SecCoreData.BootFirmwareVolumeBase = BootFv; + SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength; + + // + // Make sure the 8259 is masked before initializing the Debug Agent and the debug timer is enabled + // + IoWrite8 (0x21, 0xff); + IoWrite8 (0xA1, 0xff); + + // + // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready. + // + InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2); +} + +/** + Caller provided function to be invoked at the end of InitializeDebugAgent(). + + Entry point to the C language phase of SEC. After the SEC assembly + code has initialized some temporary memory and set up the stack, + the control is transferred to this function. + + @param[in] Context The first input parameter of InitializeDebugAgent(). + +**/ +VOID +EFIAPI +SecStartupPhase2( + IN VOID *Context + ) +{ + EFI_SEC_PEI_HAND_OFF *SecCoreData; + EFI_FIRMWARE_VOLUME_HEADER *BootFv; + EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint; + + SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context; + + // + // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug + // is enabled. + // + BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase; + FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint); + SecCoreData->BootFirmwareVolumeBase = BootFv; + SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength; + + // + // Transfer the control to the PEI core + // + (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable); + + // + // If we get here then the PEI Core returned, which is not recoverable. + // + ASSERT (FALSE); + CpuDeadLoop (); +} + +EFI_STATUS +EFIAPI +TemporaryRamMigration ( + IN CONST EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, + IN UINTN CopySize + ) +{ + IA32_DESCRIPTOR IdtDescriptor; + VOID *OldHeap; + VOID *NewHeap; + VOID *OldStack; + VOID *NewStack; + DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext; + BOOLEAN OldStatus; + BASE_LIBRARY_JUMP_BUFFER JumpBuffer; + + DEBUG ((EFI_D_ERROR, "TemporaryRamMigration(0x%x, 0x%x, 0x%x)\n", (UINTN)TemporaryMemoryBase, (UINTN)PermanentMemoryBase, CopySize)); + + OldHeap = (VOID*)(UINTN)TemporaryMemoryBase; + NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1)); + + OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1)); + NewStack = (VOID*)(UINTN)PermanentMemoryBase; + + DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap; + DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack; + + OldStatus = SaveAndSetDebugTimerInterrupt (FALSE); + InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL); + + // + // Migrate Heap + // + CopyMem (NewHeap, OldHeap, CopySize >> 1); + + // + // Migrate Stack + // + CopyMem (NewStack, OldStack, CopySize >> 1); + + // + // Rebase IDT table in permanent memory + // + AsmReadIdtr (&IdtDescriptor); + IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack; + + AsmWriteIdtr (&IdtDescriptor); + + // + // Use SetJump()/LongJump() to switch to a new stack. + // + if (SetJump (&JumpBuffer) == 0) { +#if defined (MDE_CPU_IA32) + JumpBuffer.Esp = JumpBuffer.Esp + DebugAgentContext.StackMigrateOffset; +#endif +#if defined (MDE_CPU_X64) + JumpBuffer.Rsp = JumpBuffer.Rsp + DebugAgentContext.StackMigrateOffset; +#endif + LongJump (&JumpBuffer, (UINTN)-1); + } + + SaveAndSetDebugTimerInterrupt (OldStatus); + + return EFI_SUCCESS; +} + diff --git BhyvePkg/Sec/SecMain.inf BhyvePkg/Sec/SecMain.inf new file mode 100644 index 0000000..3c7b02d --- /dev/null +++ BhyvePkg/Sec/SecMain.inf @@ -0,0 +1,68 @@ +## @file +# SEC Driver +# +# 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 = SecMain + FILE_GUID = df1ccef6-f301-4a63-9661-fc6030dcc880 + MODULE_TYPE = SEC + VERSION_STRING = 1.0 + ENTRY_POINT = SecMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + SecMain.c + +[Sources.IA32] + Ia32/SecEntry.asm | MSFT + Ia32/SecEntry.asm | INTEL + Ia32/SecEntry.S | GCC + +[Sources.X64] + X64/SecEntry.asm | MSFT + X64/SecEntry.asm | INTEL + X64/SecEntry.S | GCC + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + BhyvePkg/BhyvePkg.dec + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + PeiServicesLib + PcdLib + UefiCpuLib + DebugAgentLib + IoLib + PeCoffLib + PeCoffGetEntryPointLib + PeCoffExtraActionLib + ExtractGuidedSectionLib + +[Ppis] + gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED + +[Pcd] + gUefiBhyvePkgTokenSpaceGuid.PcdBhyveMemFvBase + gUefiBhyvePkgTokenSpaceGuid.PcdBhyveMemFvSize diff --git BhyvePkg/Sec/X64/SecEntry.S BhyvePkg/Sec/X64/SecEntry.S new file mode 100644 index 0000000..de0859b --- /dev/null +++ BhyvePkg/Sec/X64/SecEntry.S @@ -0,0 +1,54 @@ +# TITLE SecEntry.asm +#------------------------------------------------------------------------------ +#* +#* 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. +#* +#* CpuAsm.asm +#* +#* Abstract: +#* +#------------------------------------------------------------------------------ + + +#include + +#EXTERN ASM_PFX(SecCoreStartupWithStack) + +# +# SecCore Entry Point +# +# Processor is in flat protected mode +# +# @param[in] RAX Initial value of the EAX register (BIST: Built-in Self Test) +# @param[in] DI 'BP': boot-strap processor, or 'AP': application processor +# @param[in] RBP Pointer to the start of the Boot Firmware Volume +# +# @return None This routine does not return +# +ASM_GLOBAL ASM_PFX(_ModuleEntryPoint) +ASM_PFX(_ModuleEntryPoint): + + # + # Load temporary stack top at very low memory. The C code + # can reload to a better address. + # + movq $BASE_512KB, %rsp + nop + + # + # Setup parameters and call SecCoreStartupWithStack + # rcx: BootFirmwareVolumePtr + # rdx: TopOfCurrentStack + # + movq %rbp, %rcx + movq %rsp, %rdx + subq $0x20, %rsp + call ASM_PFX(SecCoreStartupWithStack) + diff --git BhyvePkg/Sec/X64/SecEntry.asm BhyvePkg/Sec/X64/SecEntry.asm new file mode 100644 index 0000000..2e63540 --- /dev/null +++ BhyvePkg/Sec/X64/SecEntry.asm @@ -0,0 +1,57 @@ + TITLE SecEntry.asm +;------------------------------------------------------------------------------ +;* +;* 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. +;* +;* CpuAsm.asm +;* +;* Abstract: +;* +;------------------------------------------------------------------------------ + +#include + +.code + +EXTERN SecCoreStartupWithStack:PROC + +; +; SecCore Entry Point +; +; Processor is in flat protected mode +; +; @param[in] RAX Initial value of the EAX register (BIST: Built-in Self Test) +; @param[in] DI 'BP': boot-strap processor, or 'AP': application processor +; @param[in] RBP Pointer to the start of the Boot Firmware Volume +; +; @return None This routine does not return +; +_ModuleEntryPoint PROC PUBLIC + + ; + ; Load temporary stack top at very low memory. The C code + ; can reload to a better address. + ; + mov rsp, BASE_512KB + nop + + ; + ; Setup parameters and call SecCoreStartupWithStack + ; rcx: BootFirmwareVolumePtr + ; rdx: TopOfCurrentStack + ; + mov rcx, rbp + mov rdx, rsp + sub rsp, 20h + call SecCoreStartupWithStack + +_ModuleEntryPoint ENDP + +END diff --git BhyvePkg/SmbiosPlatformDxe/Bhyve.c BhyvePkg/SmbiosPlatformDxe/Bhyve.c new file mode 100644 index 0000000..166b538 --- /dev/null +++ BhyvePkg/SmbiosPlatformDxe/Bhyve.c @@ -0,0 +1,49 @@ +/* + * 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 "SmbiosPlatformDxe.h" + +#define BHYVE_SMBIOS_PHYSICAL_ADDRESS 0x000F0000 +#define BHYVE_SMBIOS_PHYSICAL_END 0x000FFFFF + +/** + Locates the bhyve SMBIOS data if it exists + + @return SMBIOS_TABLE_ENTRY_POINT Address of bhyve SMBIOS data + +**/ +SMBIOS_TABLE_ENTRY_POINT * +GetBhyveSmbiosTables ( + VOID + ) +{ + UINT8 *BhyveSmbiosPtr; + SMBIOS_TABLE_ENTRY_POINT *BhyveSmbiosEntryPointStructure; + + for (BhyveSmbiosPtr = (UINT8*)(UINTN) BHYVE_SMBIOS_PHYSICAL_ADDRESS; + BhyveSmbiosPtr < (UINT8*)(UINTN) BHYVE_SMBIOS_PHYSICAL_END; + BhyveSmbiosPtr += 0x10) { + + BhyveSmbiosEntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) BhyveSmbiosPtr; + + if (!AsciiStrnCmp ((CHAR8 *) BhyveSmbiosEntryPointStructure->AnchorString, "_SM_", 4) && + !AsciiStrnCmp ((CHAR8 *) BhyveSmbiosEntryPointStructure->IntermediateAnchorString, "_DMI_", 5) && + IsEntryPointStructureValid (BhyveSmbiosEntryPointStructure)) { + + return BhyveSmbiosEntryPointStructure; + + } + } + + return NULL; +} diff --git BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c new file mode 100644 index 0000000..4811a5d --- /dev/null +++ BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.c @@ -0,0 +1,172 @@ +/** @file + This driver installs SMBIOS information for OVMF + + Copyright (c) 2011, Bei Guan + 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. + +**/ + +#include "SmbiosPlatformDxe.h" + + +/** + Validates the SMBIOS entry point structure + + @param EntryPointStructure SMBIOS entry point structure + + @retval TRUE The entry point structure is valid + @retval FALSE The entry point structure is not valid + +**/ +BOOLEAN +IsEntryPointStructureValid ( + IN SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure + ) +{ + UINTN Index; + UINT8 Length; + UINT8 Checksum; + UINT8 *BytePtr; + + BytePtr = (UINT8*) EntryPointStructure; + Length = EntryPointStructure->EntryPointLength; + Checksum = 0; + + for (Index = 0; Index < Length; Index++) { + Checksum = Checksum + (UINT8) BytePtr[Index]; + } + + if (Checksum != 0) { + return FALSE; + } else { + return TRUE; + } +} + + +/** + Get SMBIOS record length. + + @param SmbiosTable SMBIOS pointer. + +**/ +UINTN +SmbiosTableLength ( + IN SMBIOS_STRUCTURE_POINTER SmbiosTable + ) +{ + CHAR8 *AChar; + UINTN Length; + + AChar = (CHAR8 *)(SmbiosTable.Raw + SmbiosTable.Hdr->Length); + + // + // Each structure shall be terminated by a double-null (SMBIOS spec.7.1) + // + while ((*AChar != 0) || (*(AChar + 1) != 0)) { + AChar ++; + } + Length = ((UINTN)AChar - (UINTN)SmbiosTable.Raw + 2); + + return Length; +} + + +/** + Install all structures from the given SMBIOS structures block + + @param Smbios SMBIOS protocol + @param EntryPointStructure SMBIOS entry point structures block + +**/ +EFI_STATUS +InstallAllStructures ( + IN EFI_SMBIOS_PROTOCOL *Smbios, + IN SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure + ) +{ + EFI_STATUS Status; + SMBIOS_STRUCTURE_POINTER SmbiosTable; + EFI_SMBIOS_HANDLE SmbiosHandle; + + SmbiosTable.Raw = (UINT8*)(UINTN) EntryPointStructure->TableAddress; + if (SmbiosTable.Raw == NULL) { + return EFI_INVALID_PARAMETER; + } + + while (SmbiosTable.Hdr->Type != 127) { + // + // Log the SMBIOS data for this structure + // + SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED; + Status = Smbios->Add ( + Smbios, + NULL, + &SmbiosHandle, + (EFI_SMBIOS_TABLE_HEADER*) SmbiosTable.Raw + ); + ASSERT_EFI_ERROR (Status); + + // + // Get the next structure address + // + SmbiosTable.Raw = (UINT8 *)(SmbiosTable.Raw + SmbiosTableLength (SmbiosTable)); + } + + return EFI_SUCCESS; +} + + +/** + Installs SMBIOS information for OVMF + + @param ImageHandle Module's image handle + @param SystemTable Pointer of EFI_SYSTEM_TABLE + + @retval EFI_SUCCESS Smbios data successfully installed + @retval Other Smbios data was not installed + +**/ +EFI_STATUS +EFIAPI +SmbiosTablePublishEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_SMBIOS_PROTOCOL *Smbios; + SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure; + + // + // Find the SMBIOS protocol + // + Status = gBS->LocateProtocol ( + &gEfiSmbiosProtocolGuid, + NULL, + (VOID**)&Smbios + ); + if (EFI_ERROR (Status)) { + return Status; + } + +#ifndef NOT_BHYVE + // + // Add bhyve SMBIOS data + // + EntryPointStructure = GetBhyveSmbiosTables (); + if (EntryPointStructure != NULL) { + Status = InstallAllStructures (Smbios, EntryPointStructure); + } +#endif + + return Status; +} diff --git BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h new file mode 100644 index 0000000..30e127b --- /dev/null +++ BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.h @@ -0,0 +1,58 @@ +/** @file + This driver installs SMBIOS information for OVMF + + Copyright (c) 2011, Bei Guan + 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 _SMBIOS_PLATFORM_DXE_H_ +#define _SMBIOS_PLATFORM_DXE_H_ + +#include + +#include +#include +#include +#include +#include +#include + + +#ifndef NOT_BHYVE +/** + Locates the bhyve SMBIOS data if it exists + + @return SMBIOS_TABLE_ENTRY_POINT Address of bhyve SMBIOS data + +**/ +SMBIOS_TABLE_ENTRY_POINT * +GetBhyveSmbiosTables ( + VOID + ); +#endif + + +/** + Validates the SMBIOS entry point structure + + @param EntryPointStructure SMBIOS entry point structure + + @retval TRUE The entry point structure is valid + @retval FALSE The entry point structure is not valid + +**/ +BOOLEAN +IsEntryPointStructureValid ( + IN SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure + ); + +#endif diff --git BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf new file mode 100644 index 0000000..a40080d --- /dev/null +++ BhyvePkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf @@ -0,0 +1,54 @@ +## @file +# This driver installs SMBIOS information for OVMF +# +# Copyright (c) 2011, Bei Guan +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmbiosPlatformDxe + FILE_GUID = 4110465d-5ff3-4f4b-b580-24ed0d06747a + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + + ENTRY_POINT = SmbiosTablePublishEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + SmbiosPlatformDxe.h + SmbiosPlatformDxe.c + Bhyve.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + BhyvePkg/BhyvePkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + BaseMemoryLib + BaseLib + UefiDriverEntryPoint + DebugLib + HobLib + +[Protocols] + gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED + +[Depex] + gEfiSmbiosProtocolGuid + diff --git IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c index 6ee43ad..e03b055 100644 --- IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c +++ IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBbs.c @@ -259,6 +259,39 @@ LegacyBiosBuildBbs ( } } +#ifndef NOT_BHYVE + /* + */ + BbsTable[5].BootPriority = BBS_UNPRIORITIZED_ENTRY; + BbsTable[5].Bus = 0xff; + BbsTable[5].Device = 0xff; + BbsTable[5].Function = 0xff; + BbsTable[5].DeviceType = BBS_CDROM; + BbsTable[5].Class = 01; /* Mass storage controller */ + BbsTable[5].SubClass = 0x80; /* Other mass storage controller*/ + BbsTable[5].StatusFlags.OldPosition = 0; + BbsTable[5].StatusFlags.Reserved1 = 0; + BbsTable[5].StatusFlags.Enabled = 0; + BbsTable[5].StatusFlags.Failed = 0; + BbsTable[5].StatusFlags.MediaPresent = 0; + BbsTable[5].StatusFlags.Reserved2 = 0; + + /* + */ + BbsTable[6].BootPriority = BBS_UNPRIORITIZED_ENTRY; + BbsTable[6].Bus = 0xff; + BbsTable[6].Device = 0xff; + BbsTable[6].Function = 0xff; + BbsTable[6].DeviceType = BBS_HARDDISK; + BbsTable[6].Class = 01; /* Mass storage controller */ + BbsTable[6].SubClass = 0x80; /* Other mass storage controller*/ + BbsTable[6].StatusFlags.OldPosition = 0; + BbsTable[6].StatusFlags.Reserved1 = 0; + BbsTable[6].StatusFlags.Enabled = 0; + BbsTable[6].StatusFlags.Failed = 0; + BbsTable[6].StatusFlags.MediaPresent = 0; + BbsTable[6].StatusFlags.Reserved2 = 0; +#endif return EFI_SUCCESS; } diff --git IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c index dd2e2b9..7e2033d 100644 --- IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c +++ IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBios.c @@ -1060,6 +1060,7 @@ LegacyBiosInstall ( // // Allocate high PMM Memory under 16 MB // +#ifdef NOT_BHYVE Status = AllocateLegacyMemory ( AllocateMaxAddress, 0x1000000, @@ -1077,6 +1078,17 @@ LegacyBiosInstall ( &MemoryAddress ); } +#else + // + // Allocate high PMM Memory under 4GB + // + Status = AllocateLegacyMemory ( + AllocateMaxAddress, + 0xFFFFFFFF, + EFI_SIZE_TO_PAGES (MemorySize), + &MemoryAddress + ); +#endif if (!EFI_ERROR (Status)) { EfiToLegacy16InitTable->HiPmmMemory = (UINT32) (EFI_PHYSICAL_ADDRESS) (UINTN) MemoryAddress; EfiToLegacy16InitTable->HiPmmMemorySizeInBytes = MemorySize; diff --git IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c index 6ed0210..7d8134d 100644 --- IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c +++ IntelFrameworkModulePkg/Csm/LegacyBiosDxe/LegacyBootSupport.c @@ -1048,7 +1048,9 @@ GenericLegacyBoot ( // We must build IDE data, if it hasn't been done, before PciShadowRoms // to insure EFI drivers are connected. // +#ifdef NOT_BHYVE LegacyBiosBuildIdeData (Private, &HddInfo, 1); +#endif UpdateAllIdentifyDriveData (Private); // @@ -1082,7 +1084,9 @@ GenericLegacyBoot ( // // WARNING: PciIo is gone after this call. // +#ifdef NOT_BHYVE PciShadowRoms (Private); +#endif // // Shadow PXE base code, BIS etc. @@ -1118,6 +1122,46 @@ GenericLegacyBoot ( &LocalBbsTable ); +#ifndef NOT_BHYVE + DEBUG ((EFI_D_INFO, "GenericLegacyBoot: bbs count %d\n", BbsCount)); + { + BDA_STRUC *Bda; + UINTN Index, Count; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + // Update Bda disk count based on number of non-cdrom block devices + Bda = (BDA_STRUC *) ((UINTN) 0x400); + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR(Status)) { + return Status; + } + + for (Count = 0, Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (!BlockIo->Media->RemovableMedia) + Count++; + } + + DEBUG ((EFI_D_INFO, "GenericLegacyBoot: Bda drive count %d\n", Count)); + Bda->NumberOfDrives = (UINT8) Count; + } +#endif + DEBUG_CODE ( PrintPciInterruptRegister (); PrintBbsTable (LocalBbsTable); @@ -1587,6 +1631,7 @@ EfiMemoryTypeToE820Type ( IN UINT32 Type ) { +#ifdef NOT_BHYVE switch (Type) { case EfiLoaderCode: case EfiLoaderData: @@ -1619,6 +1664,37 @@ EfiMemoryTypeToE820Type ( default: return EfiAcpiAddressRangeReserved; } +#else + switch (Type) { + case EfiConventionalMemory: + return EfiAcpiAddressRangeMemory; + + case EfiLoaderCode: + case EfiLoaderData: + case EfiBootServicesCode: + case EfiBootServicesData: + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + case EfiACPIReclaimMemory: + return EfiAcpiAddressRangeACPI; + + case EfiACPIMemoryNVS: + return EfiAcpiAddressRangeNVS; + + // + // All other types map to reserved. + // Adding the code just waists FLASH space. + // + // case EfiReservedMemoryType: + // case EfiUnusableMemory: + // case EfiMemoryMappedIO: + // case EfiMemoryMappedIOPortSpace: + // case EfiPalCode: + // + default: + return EfiAcpiAddressRangeReserved; + } +#endif } /** @@ -1780,6 +1856,12 @@ LegacyBiosBuildE820 ( // Convert memory type to E820 type // TempType = EfiMemoryTypeToE820Type (EfiEntry->Type); +#ifndef NOT_BHYVE + if (EfiEntry->PhysicalStart == 0x00000800000) { + // Throw this one on the heap of usable memory. + TempType = EfiAcpiAddressRangeMemory; + } +#endif if ((E820Table[Index].Type == TempType) && (EfiEntry->PhysicalStart == (E820Table[Index].BaseAddr + E820Table[Index].Length))) { // diff --git MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c index 6ccf0a3..5c0f5b5 100644 --- MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c +++ MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.c @@ -43,7 +43,11 @@ ATA_ATAPI_PASS_THRU_INSTANCE gAtaAtapiPassThruInstanceTemplate = { // // IoAlign // +#ifdef NOT_BHYVE sizeof (UINTN) +#else + 0 +#endif }, { // AtaPassThru NULL, @@ -70,7 +74,11 @@ ATA_ATAPI_PASS_THRU_INSTANCE gAtaAtapiPassThruInstanceTemplate = { // // IoAlign // +#ifdef NOT_BHYVE sizeof (UINTN) +#else + 0 +#endif }, { // ExtScsiPassThru NULL, diff --git MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c index d99bc71..a3cd925 100644 --- MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c +++ MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c @@ -1579,7 +1579,6 @@ CheckTargetStatus ( case EFI_EXT_SCSI_STATUS_TARGET_RESERVATION_CONFLICT: return EFI_DEVICE_ERROR; - break; default: return EFI_SUCCESS; @@ -1762,6 +1761,13 @@ ParseInquiryData ( { ScsiDiskDevice->FixedDevice = (BOOLEAN) ((ScsiDiskDevice->InquiryData.Rmb == 1) ? 0 : 1); ScsiDiskDevice->BlkIoMedia.RemovableMedia = (BOOLEAN) (!ScsiDiskDevice->FixedDevice); +#ifndef NOT_BHYVE + switch (ScsiDiskDevice->InquiryData.Peripheral_Type) { + case EFI_SCSI_TYPE_CDROM: + ScsiDiskDevice->BlkIoMedia.ReadOnly = TRUE; + break; + } +#endif } /** diff --git MdeModulePkg/Core/Dxe/Event/Event.c MdeModulePkg/Core/Dxe/Event/Event.c index a8c4c34..0812fc7 100644 --- MdeModulePkg/Core/Dxe/Event/Event.c +++ MdeModulePkg/Core/Dxe/Event/Event.c @@ -85,6 +85,13 @@ UINT32 mEventTable[] = { /// waited on with CheckEvent() or WaitForEvent() /// EVT_TIMER | EVT_NOTIFY_WAIT, +#ifndef NOT_BHYVE + /// + /// 0x40000200 Runtime event with a notification function that + /// is queued when the event is signaled with SignalEvent() + /// + EVT_RUNTIME | EVT_NOTIFY_SIGNAL, +#endif }; /// diff --git MdeModulePkg/MdeModulePkg.dec MdeModulePkg/MdeModulePkg.dec index 93241d9..aeda2aa 100644 --- MdeModulePkg/MdeModulePkg.dec +++ MdeModulePkg/MdeModulePkg.dec @@ -1067,7 +1067,9 @@ # 0x0F (EFI_WHITE)
# @Prompt Foreground color for highlighted browser field. # @ValidRange 0x80000004 | 0x00 - 0x0F - gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextHighlightColor|0x07|UINT8|0x00010059 +### NOT_BHYVE : for bhyve use 0x0A for highlighting. + #gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextHighlightColor|0x07|UINT8|0x00010059 + gEfiMdeModulePkgTokenSpaceGuid.PcdBrowserFieldTextHighlightColor|0x0A|UINT8|0x00010059 ## Specify the background color for highlighted prompt and Question value text in HII Form Browser. # The default value is EFI_BACKGROUND_BLACK. Only following values defined in UEFI specification are valid:

diff --git MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c index affb3ae..993a551 100644 --- MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c +++ MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c @@ -21,6 +21,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // // UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = { +#ifdef NOT_BHYVE { BOXDRAW_HORIZONTAL, 0xc4, L'-' }, { BOXDRAW_VERTICAL, 0xb3, L'|' }, { BOXDRAW_DOWN_RIGHT, 0xda, L'/' }, @@ -74,6 +75,61 @@ UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = { { ARROW_UP, 0x18, L'^' }, { ARROW_RIGHT, 0x3e, L'>' }, { ARROW_DOWN, 0x19, L'v' }, +#else + { BOXDRAW_HORIZONTAL, 'q', L'-' }, + { BOXDRAW_VERTICAL, 'x', L'|' }, + { BOXDRAW_DOWN_RIGHT, 'l', L'/' }, + { BOXDRAW_DOWN_LEFT, 'k', L'\\' }, + { BOXDRAW_UP_RIGHT, 'm', L'\\' }, + { BOXDRAW_UP_LEFT, 'j', L'/' }, + { BOXDRAW_VERTICAL_RIGHT, 'x', L'|' }, + { BOXDRAW_VERTICAL_LEFT, 'x', L'|' }, + { BOXDRAW_DOWN_HORIZONTAL, 'w', L'+' }, + { BOXDRAW_UP_HORIZONTAL, 'v', L'+' }, + { BOXDRAW_VERTICAL_HORIZONTAL, 'n', L'+' }, + { BOXDRAW_DOUBLE_HORIZONTAL, 'q', L'-' }, + { BOXDRAW_DOUBLE_VERTICAL, 'x', L'|' }, + { BOXDRAW_DOWN_RIGHT_DOUBLE, 'l', L'/' }, + { BOXDRAW_DOWN_DOUBLE_RIGHT, 'l', L'/' }, + { BOXDRAW_DOUBLE_DOWN_RIGHT, 'l', L'/' }, + { BOXDRAW_DOWN_LEFT_DOUBLE, 'k', L'\\' }, + { BOXDRAW_DOWN_DOUBLE_LEFT, 'k', L'\\' }, + { BOXDRAW_DOUBLE_DOWN_LEFT, 'k', L'\\' }, + { BOXDRAW_UP_RIGHT_DOUBLE, 'm', L'\\' }, + { BOXDRAW_UP_DOUBLE_RIGHT, 'm', L'\\' }, + { BOXDRAW_DOUBLE_UP_RIGHT, 'm', L'\\' }, + { BOXDRAW_UP_LEFT_DOUBLE, 'j', L'/' }, + { BOXDRAW_UP_DOUBLE_LEFT, 'j', L'/' }, + { BOXDRAW_DOUBLE_UP_LEFT, 'j', L'/' }, + { BOXDRAW_VERTICAL_RIGHT_DOUBLE, 't', L'|' }, + { BOXDRAW_VERTICAL_DOUBLE_RIGHT, 't', L'|' }, + { BOXDRAW_DOUBLE_VERTICAL_RIGHT, 't', L'|' }, + { BOXDRAW_VERTICAL_LEFT_DOUBLE, 'u', L'|' }, + { BOXDRAW_VERTICAL_DOUBLE_LEFT, 'u', L'|' }, + { BOXDRAW_DOUBLE_VERTICAL_LEFT, 'u', L'|' }, + { BOXDRAW_DOWN_HORIZONTAL_DOUBLE, 'w', L'+' }, + { BOXDRAW_DOWN_DOUBLE_HORIZONTAL, 'w', L'+' }, + { BOXDRAW_DOUBLE_DOWN_HORIZONTAL, 'w', L'+' }, + { BOXDRAW_UP_HORIZONTAL_DOUBLE, 'v', L'+' }, + { BOXDRAW_UP_DOUBLE_HORIZONTAL, 'v', L'+' }, + { BOXDRAW_DOUBLE_UP_HORIZONTAL, 'v', L'+' }, + { BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, 'n', L'+' }, + { BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, 'n', L'+' }, + { BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, 'n', L'+' }, + + { BLOCKELEMENT_FULL_BLOCK, '_', L'*' }, + { BLOCKELEMENT_LIGHT_SHADE, 'a', L'+' }, + + { GEOMETRICSHAPE_UP_TRIANGLE, 0x00, L'^' }, + { GEOMETRICSHAPE_RIGHT_TRIANGLE, 0x00, L'>' }, + { GEOMETRICSHAPE_DOWN_TRIANGLE, 0x00, L'v' }, + { GEOMETRICSHAPE_LEFT_TRIANGLE, 0x00, L'<' }, + + { ARROW_LEFT, 0x00, L'<' }, + { ARROW_UP, 0x00, L'^' }, + { ARROW_RIGHT, 0x00, L'>' }, + { ARROW_DOWN, 0x00, L'v' }, +#endif { 0x0000, 0x00, L'\0' } }; @@ -143,7 +199,9 @@ TerminalConOutReset ( } } +#ifdef NOT_BHYVE This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BLACK)); +#endif Status = This->SetMode (This, 0); @@ -183,6 +241,9 @@ TerminalConOutOutputString ( UTF8_CHAR Utf8Char; CHAR8 GraphicChar; CHAR8 AsciiChar; +#ifndef NOT_BHYVE + CHAR8 GraphicSeq[8]; +#endif EFI_STATUS Status; UINT8 ValidBytes; // @@ -246,8 +307,12 @@ TerminalConOutOutputString ( AsciiChar = GraphicChar; +#ifndef NOT_BHYVE + GraphicChar = 0; +#endif } +#ifdef NOT_BHYVE if (TerminalDevice->TerminalType != PCANSITYPE) { GraphicChar = AsciiChar; } @@ -259,6 +324,34 @@ TerminalConOutOutputString ( &Length, &GraphicChar ); +#else + if (TerminalDevice->TerminalType == PCANSITYPE) { + GraphicSeq[0] = AsciiChar; + Length = 1; + } else { + if (GraphicChar == 0) { + GraphicSeq[0] = AsciiChar; + Length = 1; + } else { + // For graphical characters, change to DEC G0 set and write + // character, followed by reset to ASCII character set + GraphicSeq[0] = 0x1b; + GraphicSeq[1] = '('; + GraphicSeq[2] = '0'; + GraphicSeq[3] = GraphicChar; + GraphicSeq[4] = 0x1b; + GraphicSeq[5] = '('; + GraphicSeq[6] = 'B'; + Length = 7; + } + } + + Status = TerminalDevice->SerialIo->Write ( + TerminalDevice->SerialIo, + &Length, + GraphicSeq + ); +#endif if (EFI_ERROR (Status)) { goto OutputError; @@ -543,6 +636,7 @@ TerminalConOutSetAttribute ( // convert Attribute value to terminal emulator // understandable foreground color // +#ifdef NOT_BHYVE switch (Attribute & 0x07) { case EFI_BLACK: @@ -580,12 +674,14 @@ TerminalConOutSetAttribute ( break; } +#endif // // bit4 of the Attribute indicates bright control // of terminal emulator. // BrightControl = (UINT8) ((Attribute >> 3) & 1); +#ifdef NOT_BHYVE // // convert Attribute value to terminal emulator // understandable background color. @@ -626,6 +722,19 @@ TerminalConOutSetAttribute ( BackgroundControl = 47; break; } +#endif + +#ifndef NOT_BHYVE + if (Attribute == 0x0A) + ForegroundControl = 31; /* Highlighted item */ + else if (BrightControl) + ForegroundControl = 32; /* Bright item */ + else + ForegroundControl = 39; /* Remove color attr for everything else */ + BackgroundControl = 49; +#endif + + // // terminal emulator's control sequence to set attributes // diff --git PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.c PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.c index 7b1ab1c..40f268f 100644 --- PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.c +++ PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.c @@ -130,6 +130,7 @@ InitializePcatIsaAcpiDeviceList ( CopyMem (&gPcatIsaAcpiDeviceList[Index], &mPcatIsaAcpiPs2MouseDevice, sizeof(mPcatIsaAcpiPs2MouseDevice)); Index++; } +#ifdef NOT_BHYVE if (PcdGetBool (PcdIsaAcpiFloppyAEnable)) { CopyMem (&gPcatIsaAcpiDeviceList[Index], &mPcatIsaAcpiFloppyADevice, sizeof(mPcatIsaAcpiFloppyADevice)); Index++; @@ -138,6 +139,7 @@ InitializePcatIsaAcpiDeviceList ( CopyMem (&gPcatIsaAcpiDeviceList[Index], &mPcatIsaAcpiFloppyBDevice, sizeof(mPcatIsaAcpiFloppyBDevice)); Index++; } +#endif } //