DevPcBios.cpp revision c0561435d07a058f4256e68c08621200ef7d7390
/* $Id$ */
/** @file
* PC BIOS Device.
*/
/*
* Copyright (C) 2006-2008 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_DEV_PC_BIOS
#include <iprt/buildconfig.h>
#include "../Builtins.h"
#include "../Builtins2.h"
#include "DevPcBios.h"
/** @page pg_devbios_cmos_assign CMOS Assignments (BIOS)
*
* The BIOS uses a CMOS to store configuration data.
* It is currently used as follows:
*
* @verbatim
Base memory:
0x15
0x16
Extended memory:
0x17
0x18
0x30
0x31
Amount of memory above 16M and below 4GB in 64KB units:
0x34
0x35
Boot device (BOCHS bios specific):
0x3d
0x38
0x3c
PXE debug:
0x3f
Floppy drive type:
0x10
Equipment byte:
0x14
First HDD:
0x19
0x1e - 0x25
Second HDD:
0x1a
0x26 - 0x2d
Third HDD:
0x67 - 0x6e
Fourth HDD:
0x70 - 0x77
Extended:
0x12
First Sata HDD:
0x40 - 0x47
Second Sata HDD:
0x48 - 0x4f
Third Sata HDD:
0x50 - 0x57
Fourth Sata HDD:
0x58 - 0x5f
Number of CPUs:
0x60
RAM above 4G in 64KB units:
0x61 - 0x65
@endverbatim
*
* @todo Mark which bits are compatible with which BIOSes and
* which are our own definitions.
*
* @todo r=bird: Is the 0x61 - 0x63 range defined by AMI,
* PHOENIX or AWARD? If not I'd say 64MB units is a bit
* too big, besides it forces unnecessary math stuff onto
* the BIOS.
* although for them position in CMOS is different:
* 0x5b - 0x5c: RAM above 4G
* 0x5f: number of CPUs
* Unfortunately for us those positions in our CMOS are already taken
* by 4th SATA drive configuration.
*
*/
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* The boot device.
*/
typedef enum DEVPCBIOSBOOT
{
/**
* PC Bios instance data structure.
*/
typedef struct DEVPCBIOS
{
/** Pointer back to the device instance. */
/** Boot devices (ordered). */
/** RAM size (in bytes). */
/** RAM hole size (in bytes). */
/** Bochs shutdown index. */
/** Floppy device. */
char *pszFDDevice;
/** Harddisk device. */
char *pszHDDevice;
/** Sata harddisk device. */
char *pszSataDevice;
/** LUN of the four harddisks which are emulated as IDE. */
/** Bios message buffer. */
char szMsg[256];
/** Bios message buffer index. */
/** The system BIOS ROM data. */
/** The size of the system BIOS ROM. */
/** The name of the BIOS ROM file. */
char *pszPcBiosFile;
/** The LAN boot ROM data. */
/** The name of the LAN boot ROM file. */
char *pszLanBootFile;
/** The size of the LAN boot ROM. */
/** The DMI tables. */
/** The boot countdown (in seconds). */
/** PXE debug logging enabled? */
/** Number of logical CPUs in guest */
} DEVPCBIOS, *PDEVPCBIOS;
#pragma pack(1)
/** DMI header */
typedef struct DMIHDR
{
} *PDMIHDR;
/** DMI BIOS information (Type 0) */
typedef struct DMIBIOSINF
{
} *PDMIBIOSINF;
/** DMI system information (Type 1) */
typedef struct DMISYSTEMINF
{
} *PDMISYSTEMINF;
/** DMI system enclosure or chassis type (Type 3) */
typedef struct DMICHASSIS
{
/* v2.3+, currently not supported */
} *PDMICHASSIS;
/** DMI processor information (Type 4) */
typedef struct DMIPROCESSORINF
{
} *PDMIPROCESSORINF;
/** DMI OEM strings (Type 11) */
typedef struct DMIOEMSTRINGS
{
} *PDMIOEMSTRINGS;
/** MPS floating pointer structure */
typedef struct MPSFLOATPTR
{
} *PMPSFLOATPTR;
/** MPS config table header */
typedef struct MPSCFGTBLHEADER
{
} *PMPSCFGTBLHEADER;
/** MPS processor entry */
typedef struct MPSPROCENTRY
{
} *PMPSPROCENTRY;
/** MPS bus entry */
typedef struct MPSBUSENTRY
{
} *PMPSBUSENTRY;
typedef struct MPSIOAPICENTRY
{
} *PMPSIOAPICENTRY;
/** MPS I/O-Interrupt entry */
typedef struct MPSIOINTERRUPTENTRY
{
} *PMPSIOIRQENTRY;
#pragma pack()
/* Attempt to guess the LCHS disk geometry from the MS-DOS master boot
* record (partition table). */
{
int rc;
if (!pBlock)
return VERR_INVALID_PARAMETER;
if (RT_FAILURE(rc))
return rc;
/* Test MBR magic number. */
return VERR_INVALID_PARAMETER;
for (uint32_t i = 0; i < 4; i++)
{
/* Figure out the start of a partition table entry. */
iEndHead = p[5];
{
/* Assumption: partition terminates on a cylinder boundary. */
if (cLCHSCylinders >= 1)
{
return VINF_SUCCESS;
}
}
}
return VERR_INVALID_PARAMETER;
}
/**
* Write to CMOS memory.
* This is used by the init complete code.
*/
{
#if 1
#else
#endif
}
/* -=-=-=-=-=-=- based on code from pc.c -=-=-=-=-=-=- */
/**
* Initializes the CMOS data for one harddisk.
*/
static void pcbiosCmosInitHardDisk(PPDMDEVINS pDevIns, int offType, int offInfo, PCPDMMEDIAGEOMETRY pLCHSGeometry)
{
Log2(("%s: offInfo=%#x: LCHS=%d/%d/%d\n", __FUNCTION__, offInfo, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
if (offType)
/* Cylinders low */
/* Cylinders high */
/* Heads */
/* Landing zone low */
/* Landing zone high */
/* Write precomp low */
/* Write precomp high */
/* Sectors */
}
/**
* Set logical CHS geometry for a hard disk
*
* @returns VBox status code.
* @param pBase Base interface for the device.
* @param pHardDisk The hard disk.
* @param pLCHSGeometry Where to store the geometry settings.
*/
static int setLogicalDiskGeometry(PPDMIBASE pBase, PPDMIBLOCKBIOS pHardDisk, PPDMMEDIAGEOMETRY pLCHSGeometry)
{
int rc = VINF_SUCCESS;
if ( rc == VERR_PDM_GEOMETRY_NOT_SET
|| LCHSGeometry.cCylinders == 0
|| LCHSGeometry.cHeads == 0
|| LCHSGeometry.cSectors == 0
{
/* No LCHS geometry, autodetect and set. */
if (RT_FAILURE(rc))
{
/* Try if PCHS geometry works, otherwise fall back. */
}
if ( RT_FAILURE(rc)
|| LCHSGeometry.cCylinders == 0
|| LCHSGeometry.cHeads == 0
|| LCHSGeometry.cSectors == 0
{
{
}
{
}
{
}
{
}
else
{
}
}
if (rc == VERR_VD_IMAGE_READ_ONLY)
{
LogRel(("DevPcBios: ATA failed to update LCHS geometry, read only\n"));
rc = VINF_SUCCESS;
}
else if (rc == VERR_PDM_GEOMETRY_NOT_SET)
{
LogRel(("DevPcBios: ATA failed to update LCHS geometry, backend refused\n"));
rc = VINF_SUCCESS;
}
}
return rc;
}
/**
* Get BIOS boot code from enmBootDevice in order
*
* @todo r=bird: This is a rather silly function since the conversion is 1:1.
*/
{
{
case DEVPCBIOSBOOT_NONE:
return 0;
case DEVPCBIOSBOOT_FLOPPY:
return 1;
case DEVPCBIOSBOOT_HD:
return 2;
case DEVPCBIOSBOOT_DVD:
return 3;
case DEVPCBIOSBOOT_LAN:
return 4;
default:
return 0;
}
}
/**
* Init complete notification.
* This routine will write information needed by the bios to the CMOS.
*
* @returns VBOX status code.
* @param pDevIns The device instance.
* a description of standard and non-standard CMOS registers.
*/
{
unsigned i;
LogFlow(("pcbiosInitComplete:\n"));
/*
* Memory sizes.
*/
/* base memory. */
u32 = pThis->cbRam > 640 ? 640 : (uint32_t)pThis->cbRam / _1K; /* <-- this test is wrong, but it doesn't matter since we never assign less than 1MB */
/* Extended memory, up to 65MB */
/* Bochs BIOS specific? Anyway, it's the amount of memory above 16MB
and below 4GB (as it can only hold 4GB+16M). We have to chop off the
top 2MB or it conflict with what the ACPI tables return. (Should these
be adjusted, we still have to chop it at 0xfffc0000 or it'll conflict
with the high BIOS mapping.) */
u32 = (uint32_t)( (RT_MIN(RT_MIN(pThis->cbRam, offRamHole), UINT32_C(0xffe00000)) - 16U * _1M) / _64K );
else
u32 = 0;
Bochs got these in a different location which we've already used for SATA,
it also lacks the last two. */
c64KBAbove4GB = 0;
else
{
/* Make sure it doesn't hit the limits of the current BIOS code. */
AssertLogRelMsgReturn((c64KBAbove4GB >> (3 * 8)) < 255, ("%#RX64\n", c64KBAbove4GB), VERR_OUT_OF_RANGE);
}
/*
* Number of CPUs.
*/
/*
* Bochs BIOS specifics - boot device.
* We do both new and old (ami-style) settings.
* See rombios.c line ~7215 (int19_function).
*/
/* This is an extension. Bochs BIOS normally supports only 3 boot devices. */
/*
* PXE debug option.
*/
/*
* Floppy drive type.
*/
for (i = 0; i < RT_ELEMENTS(apFDs); i++)
{
if (RT_SUCCESS(rc))
}
u32 = 0;
if (apFDs[0])
{
default: AssertFailed(); break;
}
if (apFDs[1])
{
default: AssertFailed(); break;
}
/*
* Equipment byte.
*/
switch (u32)
{
default:u32 = 0; break; /* floppy not installed. */
}
/*
* Harddisks.
*/
for (i = 0; i < RT_ELEMENTS(apHDs); i++)
{
if (RT_SUCCESS(rc))
if ( apHDs[i]
if (apHDs[i])
{
if (i < 4)
{
/* Award BIOS extended drive types for first to fourth disk.
* Used by the BIOS for setting the logical geometry. */
switch (i)
{
case 0:
offType = 0x19;
offInfo = 0x1e;
break;
case 1:
offType = 0x1a;
offInfo = 0x26;
break;
case 2:
offType = 0x00;
offInfo = 0x67;
break;
case 3:
default:
offType = 0x00;
offInfo = 0x70;
break;
}
&LCHSGeometry);
}
LogRel(("DevPcBios: ATA LUN#%d LCHS=%u/%u/%u\n", i, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors));
}
}
/* 0Fh means extended and points to 19h, 1Ah */
/*
* Sata Harddisks.
*/
if (pThis->pszSataDevice)
{
/* Clear pointers to IDE controller. */
for (i = 0; i < RT_ELEMENTS(apHDs); i++)
for (i = 0; i < RT_ELEMENTS(apHDs); i++)
{
if (RT_SUCCESS(rc))
if ( apHDs[i]
if (apHDs[i])
{
if (i < 4)
{
/* Award BIOS extended drive types for first to fourth disk.
* Used by the BIOS for setting the logical geometry. */
int offInfo;
switch (i)
{
case 0:
offInfo = 0x40;
break;
case 1:
offInfo = 0x48;
break;
case 2:
offInfo = 0x50;
break;
case 3:
default:
offInfo = 0x58;
break;
}
&LCHSGeometry);
}
LogRel(("DevPcBios: SATA LUN#%d LCHS=%u/%u/%u\n", i, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors));
}
}
}
return VINF_SUCCESS;
}
/**
* Port I/O Handler for IN operations.
*
* @returns VBox status code.
*
* @param pDevIns The device instance.
* @param pvUser User argument - ignored.
* @param Port Port number used for the IN operation.
* @param pu32 Where to store the result.
* @param cb Number of bytes read.
*/
static DECLCALLBACK(int) pcbiosIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
{
return VERR_IOM_IOPORT_UNUSED;
}
/**
* Port I/O Handler for OUT operations.
*
* @returns VBox status code.
*
* @param pDevIns The device instance.
* @param pvUser User argument - ignored.
* @param Port Port number used for the IN operation.
* @param u32 The value to output.
* @param cb The value size in bytes.
*/
static DECLCALLBACK(int) pcbiosIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
{
/*
* Bochs BIOS Panic
*/
if ( cb == 2
&& ( Port == 0x400
|| Port == 0x401))
{
return VERR_INTERNAL_ERROR;
}
/*
* Bochs BIOS char printing.
*/
if ( cb == 1
&& ( Port == 0x402
|| Port == 0x403))
{
/* The raw version. */
switch (u32)
{
}
/* The readable, buffered version. */
{
}
else
{
{
}
}
return VINF_SUCCESS;
}
/*
* Bochs BIOS shutdown request.
*/
{
static const unsigned char szShutdown[] = "Shutdown";
{
{
LogRel(("8900h shutdown request.\n"));
return PDMDevHlpVMPowerOff(pDevIns);
}
}
else
return VINF_SUCCESS;
}
/* not in use. */
return VINF_SUCCESS;
}
/**
* Construct the DMI table.
*
* @returns VBox status code.
* @param pDevIns The device instance.
* @param pTable Where to create the DMI table.
* @param cbMax The max size of the DMI table.
* @param pUuid Pointer to the UUID to use if the DmiUuid
* configuration string isn't present.
* @param pCfgHandle The handle to our config node.
*/
static int pcbiosPlantDMITable(PPDMDEVINS pDevIns, uint8_t *pTable, unsigned cbMax, PRTUUID pUuid, PCFGMNODE pCfgHandle)
{
int iStrNr;
int rc;
char *pszDmiSystemVendor, *pszDmiSystemProduct, *pszDmiSystemVersion, *pszDmiSystemSerial, *pszDmiSystemUuid, *pszDmiSystemFamily;
char *pszDmiOEMVBoxVer, *pszDmiOEMVBoxRev;
do { \
size_t _max = (size_t)(pszStr + want - (char *)pTable) + 5; /* +1 for strtab terminator +4 for end-of-table entry */ \
{ \
N_("One of the DMI strings is too long. Check all bios/Dmi* configuration entries. At least %zu bytes are needed but there is no space for more than %d bytes"), _max, cbMax); \
} \
} while (0)
do { \
if (!str[0]) \
memb = 0; /* empty string */ \
else \
{ \
} \
} while (0)
do { \
if (rc == VERR_CFGM_VALUE_NOT_FOUND) \
else if (RT_FAILURE(rc)) \
variable[0] = '\0'; \
} while (0)
do { \
if (rc == VERR_CFGM_VALUE_NOT_FOUND) \
variable = default_value; \
else if (RT_FAILURE(rc)) \
} while (0)
/*
* Don't change this information otherwise Windows guests will demand re-activation!
*/
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
else if (RT_FAILURE(rc))
N_("Configuration error: Querying \"DmiUuid\" as a string failed"));
/* DMI BIOS information (Type 0) */
/* don't set these fields by default for legacy compatibility */
if (iDmiBIOSReleaseMajor != 0 || iDmiBIOSReleaseMinor != 0)
{
if (iDmiBIOSFirmwareMajor != 0 || iDmiBIOSFirmwareMinor != 0)
{
}
}
iStrNr = 1;
/* any more?? */
;
/* any more?? */
;
/* any more?? */
;
*pszStr++ = '\0';
/* DMI system information (Type 1) */
CHECKSIZE(sizeof(*pSystemInf));
iStrNr = 1;
if (pszDmiSystemUuid)
{
if (RT_FAILURE(rc))
N_("Invalid UUID for DMI tables specified"));
}
pSystemInf->u8SKUNumber = 0;
*pszStr++ = '\0';
/* DMI System Enclosure or Chassis (Type 3) */
iStrNr = 1;
#ifdef VBOX_WITH_DMI_CHASSIS
#else
#endif
# if 0
/* v2.3+, currently not supported */
pChassis->u32OEMdefined = 0;
# endif
*pszStr++ = '\0';
/* DMI OEM strings */
CHECKSIZE(sizeof(*pOEMStrings));
iStrNr = 1;
#ifdef VBOX_WITH_DMI_OEMSTRINGS
#else
#endif
char* pszVBoxVer, *pszVBoxRev;
*pszStr++ = '\0';
/* End-of-table marker - includes padding to account for fixed table size. */
/* If more fields are added here, fix the size check in SETSTRING */
return VINF_SUCCESS;
}
/**
* Calculate a simple checksum for the MPS table.
*
* @param data data
* @param len size of data
*/
{
return -u8Sum;
}
/**
* Construct the MPS table. Only applicable if IOAPIC is active!
*
* See ``MultiProcessor Specificatiton Version 1.4 (May 1997)'':
* ``1.3 Scope
* ...
* The hardware required to implement the MP specification is kept to a
* minimum, as follows:
* * One or more processors that are Intel architecture instruction set
* compatible, such as the CPUs in the Intel486 or Pentium processor
* family.
* * One or more APICs, such as the Intel 82489DX Advanced Programmable
* Interrupt Controller or the integrated APIC, such as that on the
* Intel Pentium 735\90 and 815\100 processors, together with a discrete
* I/O APIC unit.''
* and later:
* ``4.3.3 I/O APIC Entries
* The configuration table contains one or more entries for I/O APICs.
* ...
* I/O APIC FLAGS: EN 3:0 1 If zero, this I/O APIC is unusable, and the
* operating system should not attempt to access
* this I/O APIC.
* At least one I/O APIC must be enabled.''
*
* @param pDevIns The device instance data.
* @param addr physical address in guest memory.
*/
{
/* configuration table */
pCfgTab->u32OemTablePtr = 0;
pCfgTab->u16OemTableSize = 0;
+ 1 /* ISA Bus */
+ 16 /* Interrupts */;
pCfgTab->u16ExtTableLength = 0;
pCfgTab->u8ExtTableChecksxum = 0;
pCfgTab->u8Reserved = 0;
if (u32Eax >= 1)
{
/* Local APIC will be enabled later so override it here. Since we provide
* an MP table we have an IOAPIC and therefore a Local APIC. */
}
/* Construct MPS table for each VCPU. */
for (int i = 0; i<numCpus; i++)
{
pProcEntry->u8LocalApicId = i;
pProcEntry->u8CPUFlags = (i == 0 ? 2 /* bootstrap processor */ : 0 /* application processor */) | 1 /* enabled */;
pProcEntry->u32Reserved[0] =
pProcEntry++;
}
/* ISA bus */
/* PCI bus? */
* MP spec: "The configuration table contains one or more entries for I/O APICs.
* ... At least one I/O APIC must be enabled." */
for (int i = 0; i < 16; i++, pIrqEntry++)
{
trigger mode = conforms to bus */
pIrqEntry->u8SrcBusIrq = i;
pIrqEntry->u8DstIOAPICInt = i;
}
("VBOX_MPS_TABLE_SIZE=%d, maximum allowed size is %d",
floatPtr.u8Checksum = 0;
floatPtr.au8Feature[0] = 0;
}
/**
* Reset notification.
*
* @returns VBox status.
* @param pDevIns The device instance data.
*/
{
LogFlow(("pcbiosReset:\n"));
/*
*
* This is normally done by the BIOS code, but since we're currently lacking
* the chipset support for this we do it here (and in the constructor).
*/
while (cPages > 0)
{
int rc;
/* Read the (original) ROM page and write it back to the RAM page. */
if (RT_FAILURE(rc))
/* Advance */
cPages--;
}
}
/**
* Destruct a device instance.
*
* Most VM resources are freed by the VM. This callback is provided so that any non-VM
* resources can be freed correctly.
*
* @param pDevIns The device instance data.
*/
{
LogFlow(("pcbiosDestruct:\n"));
/*
* Free MM heap pointers.
*/
{
}
if (pThis->pszPcBiosFile)
{
}
if (pThis->pu8LanBoot)
{
}
if (pThis->pszLanBootFile)
{
}
return VINF_SUCCESS;
}
/**
* Convert config value to DEVPCBIOSBOOT.
*
* @returns VBox status code.
* @param pCfgHandle Configuration handle.
* @param pszParam The name of the value to read.
* @param penmBoot Where to store the boot method.
*/
static int pcbiosBootFromCfg(PPDMDEVINS pDevIns, PCFGMNODE pCfgHandle, const char *pszParam, DEVPCBIOSBOOT *penmBoot)
{
char *psz;
if (RT_FAILURE(rc))
N_("Configuration error: Querying \"%s\" as a string failed"),
pszParam);
else
{
N_("Configuration error: The \"%s\" value \"%s\" is unknown"),
}
return rc;
}
/**
* Construct a device instance for a VM.
*
* @returns VBox status.
* @param pDevIns The device instance data.
* If the registration structure is needed, pDevIns->pDevReg points to it.
* @param iInstance Instance number. Use this to figure out which registers and such to use.
* The device number is also found in pDevIns->iInstance, but since it's
* likely to be freqently used PDM passes it as parameter.
* @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
* of the device instance. It's also found in pDevIns->pCfgHandle, but like
* iInstance it's expected to be used a bit in this function.
*/
{
unsigned i;
int rc;
int cb;
/*
* Validate configuration.
*/
"BootDevice0\0"
"BootDevice1\0"
"BootDevice2\0"
"BootDevice3\0"
"RamSize\0"
"RamHoleSize\0"
"HardDiskDevice\0"
"SataHardDiskDevice\0"
"SataPrimaryMasterLUN\0"
"SataPrimarySlaveLUN\0"
"SataSecondaryMasterLUN\0"
"SataSecondarySlaveLUN\0"
"FloppyDevice\0"
"DelayBoot\0"
"BiosRom\0"
"LanBootRom\0"
"PXEDebug\0"
"UUID\0"
"IOAPIC\0"
"NumCPUs\0"
"DmiBIOSVendor\0"
"DmiBIOSVersion\0"
"DmiBIOSReleaseDate\0"
"DmiBIOSReleaseMajor\0"
"DmiBIOSReleaseMinor\0"
"DmiBIOSFirmwareMajor\0"
"DmiBIOSFirmwareMinor\0"
"DmiSystemFamily\0"
"DmiSystemProduct\0"
"DmiSystemSerial\0"
"DmiSystemUuid\0"
"DmiSystemVendor\0"
"DmiSystemVersion\0"
"DmiChassisVendor\0"
"DmiChassisVersion\0"
"DmiChassisSerial\0"
"DmiChassisAssetTag\0"
#ifdef VBOX_WITH_DMI_OEMSTRINGS
"DmiOEMVBoxVer\0"
"DmiOEMVBoxRev\0"
#endif
))
N_("Invalid configuraton for device pcbios device"));
/*
* Init the data.
*/
if (RT_FAILURE(rc))
N_("Configuration error: Querying \"RamSize\" as integer failed"));
if (RT_FAILURE(rc))
N_("Configuration error: Querying \"RamHoleSize\" as integer failed"));
if (RT_FAILURE(rc))
N_("Configuration error: Querying \"NumCPUs\" as integer failed"));
if (RT_FAILURE (rc))
N_("Configuration error: Failed to read \"IOAPIC\""));
static const char * const s_apszBootDevices[] = { "BootDevice0", "BootDevice1", "BootDevice2", "BootDevice3" };
{
if (RT_FAILURE(rc))
return rc;
}
if (RT_FAILURE(rc))
N_("Configuration error: Querying \"HardDiskDevice\" as a string failed"));
if (RT_FAILURE(rc))
N_("Configuration error: Querying \"FloppyDevice\" as a string failed"));
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
else if (RT_FAILURE(rc))
N_("Configuration error: Querying \"SataHardDiskDevice\" as a string failed"));
if (pThis->pszSataDevice)
{
static const char * const s_apszSataDisks[] =
{ "SataPrimaryMasterLUN", "SataPrimarySlaveLUN", "SataSecondaryMasterLUN", "SataSecondarySlaveLUN" };
{
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
pThis->iSataHDLUN[i] = i;
else if (RT_FAILURE(rc))
}
}
/*
* Register I/O Ports and PC BIOS.
*/
if (RT_FAILURE(rc))
return rc;
if (RT_FAILURE(rc))
return rc;
/*
*/
if (RT_FAILURE(rc))
N_("Configuration error: Querying \"UUID\" failed"));
/* Convert the UUID to network byte order. Not entirely straightforward as parts are MSB already... */
if (RT_FAILURE(rc))
return rc;
PGMPHYS_ROM_FLAGS_PERMANENT_BINARY, "DMI tables");
if (RT_FAILURE(rc))
return rc;
/*
* Read the PXE debug logging option.
*/
if (RT_FAILURE(rc))
N_("Configuration error: Querying \"PXEDebug\" as integer failed"));
/*
* Get the system BIOS ROM file name.
*/
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
{
rc = VINF_SUCCESS;
}
else if (RT_FAILURE(rc))
N_("Configuration error: Querying \"BiosRom\" as a string failed"));
else if (!*pThis->pszPcBiosFile)
{
}
/*
* Determine the system BIOS ROM size, open specified ROM file in the process.
*/
if (pThis->pszPcBiosFile)
{
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
/* The following checks should be in sync the AssertReleaseMsg's below. */
}
}
if (RT_FAILURE(rc))
{
/*
* In case of failure simply fall back to the built-in BIOS ROM.
*/
Log(("pcbiosConstruct: Failed to open system BIOS ROM file '%s', rc=%Rrc!\n", pThis->pszPcBiosFile, rc));
}
}
/*
* Attempt to get the system BIOS ROM data from file.
*/
if (pThis->pszPcBiosFile)
{
/*
* Allocate buffer for the system BIOS ROM data.
*/
{
if (RT_FAILURE(rc))
{
}
rc = VINF_SUCCESS;
}
else
rc = VERR_NO_MEMORY;
}
else
/* cleanup */
if (FilePcBios != NIL_RTFILE)
/* If we were unable to get the data from file for whatever reason, fall
back to the built-in ROM image. */
{
}
else
{
}
/*
* Map the BIOS into memory.
* There are two mappings:
* 1. 0x000e0000 to 0x000fffff contains the last 128 kb of the bios.
* The bios code might be 64 kb in size, and will then start at 0xf0000.
* 2. 0xfffxxxxx to 0xffffffff contains the entire bios.
*/
("cbPcBiosBinary=%#x\n", cbPcBiosBinary));
fFlags, "PC BIOS - 0xfffff");
if (RT_FAILURE(rc))
return rc;
rc = PDMDevHlpROMRegister(pDevIns, (uint32_t)-(int32_t)cbPcBiosBinary, cbPcBiosBinary, pu8PcBiosBinary,
fFlags, "PC BIOS - 0xffffffff");
if (RT_FAILURE(rc))
return rc;
#ifdef VBOX_WITH_VMI
/*
* Map the VMI BIOS into memory.
*/
PGMPHYS_ROM_FLAGS_PERMANENT_BINARY, "VMI BIOS");
if (RT_FAILURE(rc))
return rc;
#endif /* VBOX_WITH_VMI */
/*
* Call reset to set values and stuff.
*/
/*
* Get the LAN boot ROM file name.
*/
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
{
rc = VINF_SUCCESS;
}
else if (RT_FAILURE(rc))
N_("Configuration error: Querying \"LanBootRom\" as a string failed"));
else if (!*pThis->pszLanBootFile)
{
}
/*
* Determine the LAN boot ROM size, open specified ROM file in the process.
*/
if (pThis->pszLanBootFile)
{
if (RT_SUCCESS(rc))
{
if (RT_SUCCESS(rc))
{
|| cbFileLanBoot > _64K)
}
}
if (RT_FAILURE(rc))
{
/*
* Ignore failure and fall back to the built-in LAN boot ROM.
*/
Log(("pcbiosConstruct: Failed to open LAN boot ROM file '%s', rc=%Rrc!\n", pThis->pszLanBootFile, rc));
}
}
/*
* Get the LAN boot ROM data.
*/
if (pThis->pszLanBootFile)
{
/*
* Allocate buffer for the LAN boot ROM data.
*/
if (pThis->pu8LanBoot)
{
if (RT_FAILURE(rc))
{
}
rc = VINF_SUCCESS;
}
else
rc = VERR_NO_MEMORY;
}
else
/* cleanup */
if (FileLanBoot != NIL_RTFILE)
/* If we were unable to get the data from file for whatever reason, fall
* back to the built-in LAN boot ROM image.
*/
{
}
else
{
}
/*
* Map the Network Boot ROM into memory.
* Currently there is a fixed mapping: 0x000c8000 to 0x000cffff contains
* the (up to) 32 kb ROM image.
*/
if (pu8LanBootBinary)
{
PGMPHYS_ROM_FLAGS_SHADOWED, "Net Boot ROM");
if (RT_SUCCESS(rc))
{
rc = PDMDevHlpROMProtectShadow(pDevIns, VBOX_LANBOOT_SEG << 4, cbLanBootBinary, PGMROMPROT_READ_RAM_WRITE_RAM);
}
}
if (RT_FAILURE(rc))
N_("Configuration error: Querying \"DelayBoot\" as integer failed"));
return rc;
}
/**
* The device registration structure.
*/
const PDMDEVREG g_DevicePcBios =
{
/* u32Version */
/* szDeviceName */
"pcbios",
/* szRCMod */
"",
/* szR0Mod */
"",
/* pszDescription */
"PC BIOS Device",
/* fFlags */
/* fClass */
/* cMaxInstances */
1,
/* cbInstance */
sizeof(DEVPCBIOS),
/* pfnConstruct */
/* pfnDestruct */
/* pfnRelocate */
NULL,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
NULL,
/* pfnReset */
/* pfnSuspend */
NULL,
/* pfnResume */
NULL,
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnQueryInterface. */
NULL,
/* pfnInitComplete. */
/* pfnPowerOff */
NULL,
/* pfnSoftReset */
NULL,
/* u32VersionEnd */
};