diff options
Diffstat (limited to 'src/VBox/Devices/PC/DevPcBios.cpp')
-rw-r--r-- | src/VBox/Devices/PC/DevPcBios.cpp | 466 |
1 files changed, 288 insertions, 178 deletions
diff --git a/src/VBox/Devices/PC/DevPcBios.cpp b/src/VBox/Devices/PC/DevPcBios.cpp index 5e0e866f..d34dce5b 100644 --- a/src/VBox/Devices/PC/DevPcBios.cpp +++ b/src/VBox/Devices/PC/DevPcBios.cpp @@ -1,10 +1,10 @@ /* $Id: DevPcBios.cpp $ */ /** @file - * PC BIOS Device. + * DevPcBios - PC BIOS Device. */ /* - * Copyright (C) 2006-2008 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -31,6 +31,7 @@ #include <iprt/mem.h> #include <iprt/string.h> #include <iprt/uuid.h> +#include <iprt/cdefs.h> #include <VBox/err.h> #include <VBox/param.h> @@ -105,6 +106,15 @@ 0x82 - 0x83 Second to third net boot devices: 0x84 - 0x89 + First SCSI HDD: + 0x90 - 0x97 + Second SCSI HDD: + 0x98 - 0x9f + Third SCSI HDD: + 0xa0 - 0xa7 + Fourth SCSI HDD: + 0xa8 - 0xaf + @endverbatim * * @todo Mark which bits are compatible with which BIOSes and @@ -150,8 +160,12 @@ typedef struct DEVPCBIOS char *pszHDDevice; /** Sata harddisk device. */ char *pszSataDevice; - /** LUN of the four harddisks which are emulated as IDE. */ + /** LUNs of the four BIOS-accessible SATA disks. */ uint32_t iSataHDLUN[4]; + /** SCSI harddisk device. */ + char *pszScsiDevice; + /** LUNs of the four BIOS-accessible SCSI disks. */ + uint32_t iScsiHDLUN[4]; /** Bios message buffer. */ char szMsg[256]; /** Bios message buffer index. */ @@ -182,11 +196,99 @@ typedef struct DEVPCBIOS uint16_t cCpus; uint32_t u32McfgBase; uint32_t cbMcfgLength; -} DEVPCBIOS, *PDEVPCBIOS; +} DEVPCBIOS; +/** Pointer to the BIOS device state. */ +typedef DEVPCBIOS *PDEVPCBIOS; + + +/** + * @callback_method_impl{FNIOMIOPORTIN, Boch Debug and Shutdown ports.} + */ +static DECLCALLBACK(int) pcbiosIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) +{ + return VERR_IOM_IOPORT_UNUSED; +} -/* Attempt to guess the LCHS disk geometry from the MS-DOS master boot - * record (partition table). */ +/** + * @callback_method_impl{FNIOMIOPORTOUT, Boch Debug and Shutdown ports.} + */ +static DECLCALLBACK(int) pcbiosIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) +{ + /* + * Bochs BIOS char printing. + */ + if ( cb == 1 + && ( Port == 0x402 + || Port == 0x403)) + { + PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS); + /* The raw version. */ + switch (u32) + { + case '\r': Log2(("pcbios: <return>\n")); break; + case '\n': Log2(("pcbios: <newline>\n")); break; + case '\t': Log2(("pcbios: <tab>\n")); break; + default: Log2(("pcbios: %c (%02x)\n", u32, u32)); break; + } + + /* The readable, buffered version. */ + if (u32 == '\n' || u32 == '\r') + { + pThis->szMsg[pThis->iMsg] = '\0'; + if (pThis->iMsg) + Log(("pcbios: %s\n", pThis->szMsg)); + pThis->iMsg = 0; + } + else + { + if (pThis->iMsg >= sizeof(pThis->szMsg)-1) + { + pThis->szMsg[pThis->iMsg] = '\0'; + Log(("pcbios: %s\n", pThis->szMsg)); + pThis->iMsg = 0; + } + pThis->szMsg[pThis->iMsg] = (char )u32; + pThis->szMsg[++pThis->iMsg] = '\0'; + } + return VINF_SUCCESS; + } + + /* + * Bochs BIOS shutdown request. + */ + if (cb == 1 && Port == 0x8900) + { + static const unsigned char szShutdown[] = "Shutdown"; + PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS); + if (u32 == szShutdown[pThis->iShutdown]) + { + pThis->iShutdown++; + if (pThis->iShutdown == 8) + { + pThis->iShutdown = 0; + LogRel(("DevPcBios: 8900h shutdown request.\n")); + return PDMDevHlpVMPowerOff(pDevIns); + } + } + else + pThis->iShutdown = 0; + return VINF_SUCCESS; + } + + /* not in use. */ + return VINF_SUCCESS; +} + + +/** + * Attempt to guess the LCHS disk geometry from the MS-DOS master boot record + * (partition table). + * + * @returns VBox status code. + * @param pBlock The block device interface of the disk. + * @param pLCHSGeometry Where to return the disk geometry on success + */ static int biosGuessDiskLCHS(PPDMIBLOCK pBlock, PPDMMEDIAGEOMETRY pLCHSGeometry) { uint8_t aMBR[512], *p; @@ -240,6 +342,7 @@ static void pcbiosCmosWrite(PPDMDEVINS pDevIns, int off, uint32_t u32Val) AssertRC(rc); } + /** * Read from CMOS memory. * This is used by the init complete code. @@ -256,7 +359,6 @@ static uint8_t pcbiosCmosRead(PPDMDEVINS pDevIns, int off) return u8val; } -/* -=-=-=-=-=-=- based on code from pc.c -=-=-=-=-=-=- */ /** * Initializes the CMOS data for one harddisk. @@ -284,6 +386,7 @@ static void pcbiosCmosInitHardDisk(PPDMDEVINS pDevIns, int offType, int offInfo, pcbiosCmosWrite(pDevIns, offInfo + 7, pLCHSGeometry->cSectors); } + /** * Set logical CHS geometry for a hard disk * @@ -369,6 +472,41 @@ static int setLogicalDiskGeometry(PPDMIBASE pBase, PPDMIBLOCKBIOS pHardDisk, PPD return rc; } + +/** + * Get logical CHS geometry for a hard disk, intended for SCSI/SAS drives + * with no physical geometry. + * + * @returns VBox status code. + * @param pHardDisk The hard disk. + * @param pLCHSGeometry Where to store the geometry settings. + */ +static int getLogicalDiskGeometry(PPDMIBLOCKBIOS pHardDisk, PPDMMEDIAGEOMETRY pLCHSGeometry) +{ + PDMMEDIAGEOMETRY LCHSGeometry; + int rc = VINF_SUCCESS; + + rc = pHardDisk->pfnGetLCHSGeometry(pHardDisk, &LCHSGeometry); + if ( rc == VERR_PDM_GEOMETRY_NOT_SET + || LCHSGeometry.cCylinders == 0 + || LCHSGeometry.cHeads == 0 + || LCHSGeometry.cHeads > 255 + || LCHSGeometry.cSectors == 0 + || LCHSGeometry.cSectors > 63) + { + /* Unlike the ATA case, if the image does not provide valid logical + * geometry, we leave things alone and let the BIOS decide what the + * logical geometry should be. + */ + rc = VERR_PDM_GEOMETRY_NOT_SET; + } + else + *pLCHSGeometry = LCHSGeometry; + + return rc; +} + + /** * Get BIOS boot code from enmBootDevice in order * @@ -396,11 +534,10 @@ static uint8_t getBiosBootCode(PDEVPCBIOS pThis, unsigned iOrder) /** - * Init complete notification. + * @interface_method_impl{PDMDEVREG,pfnInitComplete} + * * This routine will write information needed by the bios to the CMOS. * - * @returns VBOX status code. - * @param pDevIns The device instance. * @see http://www.brl.ntt.co.jp/people/takehiko/interrupt/CMOS.LST.txt for * a description of standard and non-standard CMOS registers. */ @@ -409,10 +546,8 @@ static DECLCALLBACK(int) pcbiosInitComplete(PPDMDEVINS pDevIns) PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS); uint32_t u32; unsigned i; - PVM pVM = PDMDevHlpGetVM(pDevIns); + PUVM pUVM = PDMDevHlpGetUVM(pDevIns); AssertRelease(pUVM); PPDMIBLOCKBIOS apHDs[4] = {0}; - PPDMIBLOCKBIOS apFDs[2] = {0}; - AssertRelease(pVM); LogFlow(("pcbiosInitComplete:\n")); /* @@ -497,57 +632,54 @@ static DECLCALLBACK(int) pcbiosInitComplete(PPDMDEVINS pDevIns) /* * Floppy drive type. */ - for (i = 0; i < RT_ELEMENTS(apFDs); i++) + uint32_t cFDs = 0; + u32 = 0; + for (i = 0; i < 2; i++) { PPDMIBASE pBase; - int rc = PDMR3QueryLun(pVM, pThis->pszFDDevice, 0, i, &pBase); + int rc = PDMR3QueryLun(pUVM, pThis->pszFDDevice, 0, i, &pBase); if (RT_SUCCESS(rc)) - apFDs[i] = PDMIBASE_QUERY_INTERFACE(pBase, PDMIBLOCKBIOS); - } - u32 = 0; - if (apFDs[0]) - switch (apFDs[0]->pfnGetType(apFDs[0])) { - case PDMBLOCKTYPE_FLOPPY_360: u32 |= 1 << 4; break; - case PDMBLOCKTYPE_FLOPPY_1_20: u32 |= 2 << 4; break; - case PDMBLOCKTYPE_FLOPPY_720: u32 |= 3 << 4; break; - case PDMBLOCKTYPE_FLOPPY_1_44: u32 |= 4 << 4; break; - case PDMBLOCKTYPE_FLOPPY_2_88: u32 |= 5 << 4; break; - default: AssertFailed(); break; - } - if (apFDs[1]) - switch (apFDs[1]->pfnGetType(apFDs[1])) - { - case PDMBLOCKTYPE_FLOPPY_360: u32 |= 1; break; - case PDMBLOCKTYPE_FLOPPY_1_20: u32 |= 2; break; - case PDMBLOCKTYPE_FLOPPY_720: u32 |= 3; break; - case PDMBLOCKTYPE_FLOPPY_1_44: u32 |= 4; break; - case PDMBLOCKTYPE_FLOPPY_2_88: u32 |= 5; break; - default: AssertFailed(); break; + PPDMIBLOCKBIOS pFD = PDMIBASE_QUERY_INTERFACE(pBase, PDMIBLOCKBIOS); + if (pFD) + { + cFDs++; + unsigned cShift = i == 0 ? 4 : 0; + switch (pFD->pfnGetType(pFD)) + { + case PDMBLOCKTYPE_FLOPPY_360: u32 |= 1 << cShift; break; + case PDMBLOCKTYPE_FLOPPY_1_20: u32 |= 2 << cShift; break; + case PDMBLOCKTYPE_FLOPPY_720: u32 |= 3 << cShift; break; + case PDMBLOCKTYPE_FLOPPY_1_44: u32 |= 4 << cShift; break; + case PDMBLOCKTYPE_FLOPPY_2_88: u32 |= 5 << cShift; break; + case PDMBLOCKTYPE_FLOPPY_FAKE_15_6: u32 |= 14 << cShift; break; + case PDMBLOCKTYPE_FLOPPY_FAKE_63_5: u32 |= 15 << cShift; break; + default: AssertFailed(); break; + } + } } + } pcbiosCmosWrite(pDevIns, 0x10, u32); /* 10h - Floppy Drive Type */ /* * Equipment byte. */ - u32 = !!apFDs[0] + !!apFDs[1]; - switch (u32) - { - case 1: u32 = 0x01; break; /* floppy installed, 2 drives. */ - default:u32 = 0; break; /* floppy not installed. */ - } + if (cFDs > 0) + u32 = 0x01; /* floppy installed, 2 drives. */ + else + u32 = 0x00; /* floppy not installed. */ u32 |= RT_BIT(1); /* math coprocessor installed */ u32 |= RT_BIT(2); /* keyboard enabled (or mouse?) */ u32 |= RT_BIT(3); /* display enabled (monitory type is 0, i.e. vga) */ pcbiosCmosWrite(pDevIns, 0x14, u32); /* 14h - Equipment Byte */ /* - * Harddisks. + * IDE harddisks. */ for (i = 0; i < RT_ELEMENTS(apHDs); i++) { PPDMIBASE pBase; - int rc = PDMR3QueryLun(pVM, pThis->pszHDDevice, 0, i, &pBase); + int rc = PDMR3QueryLun(pUVM, pThis->pszHDDevice, 0, i, &pBase); if (RT_SUCCESS(rc)) apHDs[i] = PDMIBASE_QUERY_INTERFACE(pBase, PDMIBLOCKBIOS); if ( apHDs[i] @@ -597,18 +729,18 @@ static DECLCALLBACK(int) pcbiosInitComplete(PPDMDEVINS pDevIns) pcbiosCmosWrite(pDevIns, 0x12, u32); /* - * Sata Harddisks. + * SATA harddisks. */ if (pThis->pszSataDevice) { - /* Clear pointers to IDE controller. */ + /* Clear pointers to the block devices. */ for (i = 0; i < RT_ELEMENTS(apHDs); i++) apHDs[i] = NULL; for (i = 0; i < RT_ELEMENTS(apHDs); i++) { PPDMIBASE pBase; - int rc = PDMR3QueryLun(pVM, pThis->pszSataDevice, 0, pThis->iSataHDLUN[i], &pBase); + int rc = PDMR3QueryLun(pUVM, pThis->pszSataDevice, 0, pThis->iSataHDLUN[i], &pBase); if (RT_SUCCESS(rc)) apHDs[i] = PDMIBASE_QUERY_INTERFACE(pBase, PDMIBLOCKBIOS); if ( apHDs[i] @@ -650,134 +782,81 @@ static DECLCALLBACK(int) pcbiosInitComplete(PPDMDEVINS pDevIns) } } - /* Calculate and store AT-style CMOS checksum. */ - uint16_t cksum = 0; - for (i = 0x10; i < 0x2e; ++i) - cksum += pcbiosCmosRead(pDevIns, i); - pcbiosCmosWrite(pDevIns, 0x2e, cksum >> 8); - pcbiosCmosWrite(pDevIns, 0x2f, cksum & 0xff); - - LogFlow(("%s: returns VINF_SUCCESS\n", __FUNCTION__)); - 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)) - { - Log(("pcbios: PC BIOS panic at rombios.c(%d)\n", u32)); - AssertReleaseMsgFailed(("PC BIOS panic at rombios.c(%d)\n", u32)); - return VERR_INTERNAL_ERROR; - } - /* - * Bochs BIOS char printing. + * SCSI harddisks. Not handled quite the same as SATA. */ - if ( cb == 1 - && ( Port == 0x402 - || Port == 0x403)) + if (pThis->pszScsiDevice) { - PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS); - /* The raw version. */ - switch (u32) - { - case '\r': Log2(("pcbios: <return>\n")); break; - case '\n': Log2(("pcbios: <newline>\n")); break; - case '\t': Log2(("pcbios: <tab>\n")); break; - default: Log2(("pcbios: %c (%02x)\n", u32, u32)); break; - } + /* Clear pointers to the block devices. */ + for (i = 0; i < RT_ELEMENTS(apHDs); i++) + apHDs[i] = NULL; - /* The readable, buffered version. */ - if (u32 == '\n' || u32 == '\r') - { - pThis->szMsg[pThis->iMsg] = '\0'; - if (pThis->iMsg) - Log(("pcbios: %s\n", pThis->szMsg)); - pThis->iMsg = 0; - } - else + for (i = 0; i < RT_ELEMENTS(apHDs); i++) { - if (pThis->iMsg >= sizeof(pThis->szMsg)-1) + PPDMIBASE pBase; + int rc = PDMR3QueryLun(pUVM, pThis->pszScsiDevice, 0, pThis->iScsiHDLUN[i], &pBase); + if (RT_SUCCESS(rc)) + apHDs[i] = PDMIBASE_QUERY_INTERFACE(pBase, PDMIBLOCKBIOS); + if ( apHDs[i] + && ( apHDs[i]->pfnGetType(apHDs[i]) != PDMBLOCKTYPE_HARD_DISK + || !apHDs[i]->pfnIsVisible(apHDs[i]))) + apHDs[i] = NULL; + if (apHDs[i]) { - pThis->szMsg[pThis->iMsg] = '\0'; - Log(("pcbios: %s\n", pThis->szMsg)); - pThis->iMsg = 0; - } - pThis->szMsg[pThis->iMsg] = (char )u32; - pThis->szMsg[++pThis->iMsg] = '\0'; - } - return VINF_SUCCESS; - } + PDMMEDIAGEOMETRY LCHSGeometry; + rc = getLogicalDiskGeometry(apHDs[i], &LCHSGeometry); - /* - * Bochs BIOS shutdown request. - */ - if (cb == 1 && Port == 0x8900) - { - static const unsigned char szShutdown[] = "Shutdown"; - PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS); - if (u32 == szShutdown[pThis->iShutdown]) - { - pThis->iShutdown++; - if (pThis->iShutdown == 8) - { - pThis->iShutdown = 0; - LogRel(("DevPcBios: 8900h shutdown request.\n")); - return PDMDevHlpVMPowerOff(pDevIns); + if (i < 4 && RT_SUCCESS(rc)) + { + /* Extended drive information (for SCSI disks). + * Used by the BIOS for setting the logical geometry, but + * only if the image provided valid data. + */ + int offInfo; + switch (i) + { + case 0: + offInfo = 0x90; + break; + case 1: + offInfo = 0x98; + break; + case 2: + offInfo = 0xa0; + break; + case 3: + default: + offInfo = 0xa8; + break; + } + pcbiosCmosInitHardDisk(pDevIns, 0x00, offInfo, &LCHSGeometry); + LogRel(("DevPcBios: SCSI LUN#%d LCHS=%u/%u/%u\n", i, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors)); + } + else + LogRel(("DevPcBios: SCSI LUN#%d LCHS not provided\n", i)); } } - else - pThis->iShutdown = 0; - return VINF_SUCCESS; } - /* not in use. */ + /* Calculate and store AT-style CMOS checksum. */ + uint16_t cksum = 0; + for (i = 0x10; i < 0x2e; ++i) + cksum += pcbiosCmosRead(pDevIns, i); + pcbiosCmosWrite(pDevIns, 0x2e, cksum >> 8); + pcbiosCmosWrite(pDevIns, 0x2f, cksum & 0xff); + + LogFlow(("%s: returns VINF_SUCCESS\n", __FUNCTION__)); return VINF_SUCCESS; } + /** - * Reset notification. - * - * @returns VBox status. - * @param pDevIns The device instance data. + * @interface_method_impl{PDMDEVREG,pfnMemSetup} */ -static DECLCALLBACK(void) pcbiosReset(PPDMDEVINS pDevIns) +static DECLCALLBACK(void) pcbiosMemSetup(PPDMDEVINS pDevIns, PDMDEVMEMSETUPCTX enmCtx) { PDEVPCBIOS pThis = PDMINS_2_DATA(pDevIns, PDEVPCBIOS); - LogFlow(("pcbiosReset:\n")); + LogFlow(("pcbiosMemSetup:\n")); if (pThis->u8IOAPIC) FwCommonPlantMpsFloatPtr(pDevIns); @@ -819,12 +898,7 @@ static DECLCALLBACK(void) pcbiosReset(PPDMDEVINS pDevIns) /** - * 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. + * @interface_method_impl{PDMDEVREG,pfnDestruct} */ static DECLCALLBACK(int) pcbiosDestruct(PPDMDEVINS pDevIns) { @@ -877,6 +951,12 @@ static DECLCALLBACK(int) pcbiosDestruct(PPDMDEVINS pDevIns) pThis->pszSataDevice = NULL; } + if (pThis->pszScsiDevice) + { + MMR3HeapFree(pThis->pszScsiDevice); + pThis->pszScsiDevice = NULL; + } + return VINF_SUCCESS; } @@ -942,10 +1022,15 @@ static DECLCALLBACK(int) pcbiosConstruct(PPDMDEVINS pDevIns, int iInstance, PCF "RamHoleSize\0" "HardDiskDevice\0" "SataHardDiskDevice\0" - "SataPrimaryMasterLUN\0" - "SataPrimarySlaveLUN\0" - "SataSecondaryMasterLUN\0" - "SataSecondarySlaveLUN\0" + "SataLUN1\0" + "SataLUN2\0" + "SataLUN3\0" + "SataLUN4\0" + "ScsiHardDiskDevice\0" + "ScsiLUN1\0" + "ScsiLUN2\0" + "ScsiLUN3\0" + "ScsiLUN4\0" "FloppyDevice\0" "DelayBoot\0" "BiosRom\0" @@ -979,6 +1064,7 @@ static DECLCALLBACK(int) pcbiosConstruct(PPDMDEVINS pDevIns, int iInstance, PCF "DmiBoardVersion\0" "DmiChassisAssetTag\0" "DmiChassisSerial\0" + "DmiChassisType\0" "DmiChassisVendor\0" "DmiChassisVersion\0" "DmiProcManufacturer\0" @@ -1056,7 +1142,7 @@ static DECLCALLBACK(int) pcbiosConstruct(PPDMDEVINS pDevIns, int iInstance, PCF if (pThis->pszSataDevice) { static const char * const s_apszSataDisks[] = - { "SataPrimaryMasterLUN", "SataPrimarySlaveLUN", "SataSecondaryMasterLUN", "SataSecondarySlaveLUN" }; + { "SataLUN1", "SataLUN2", "SataLUN3", "SataLUN4" }; Assert(RT_ELEMENTS(s_apszSataDisks) == RT_ELEMENTS(pThis->iSataHDLUN)); for (unsigned i = 0; i < RT_ELEMENTS(pThis->iSataHDLUN); i++) { @@ -1068,6 +1154,32 @@ static DECLCALLBACK(int) pcbiosConstruct(PPDMDEVINS pDevIns, int iInstance, PCF N_("Configuration error: Querying \"%s\" as a string failed"), s_apszSataDisks); } } + + /* Repeat the exercise for SCSI drives. */ + rc = CFGMR3QueryStringAlloc(pCfg, "ScsiHardDiskDevice", &pThis->pszScsiDevice); + if (rc == VERR_CFGM_VALUE_NOT_FOUND) + pThis->pszScsiDevice = NULL; + else if (RT_FAILURE(rc)) + return PDMDEV_SET_ERROR(pDevIns, rc, + N_("Configuration error: Querying \"ScsiHardDiskDevice\" as a string failed")); + + if (pThis->pszScsiDevice) + { + static const char * const s_apszScsiDisks[] = + { "ScsiLUN1", "ScsiLUN2", "ScsiLUN3", "ScsiLUN4" }; + Assert(RT_ELEMENTS(s_apszScsiDisks) == RT_ELEMENTS(pThis->iScsiHDLUN)); + for (unsigned i = 0; i < RT_ELEMENTS(pThis->iScsiHDLUN); i++) + { + rc = CFGMR3QueryU32(pCfg, s_apszScsiDisks[i], &pThis->iScsiHDLUN[i]); + if (rc == VERR_CFGM_VALUE_NOT_FOUND) + pThis->iScsiHDLUN[i] = i; + else if (RT_FAILURE(rc)) + return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, + N_("Configuration error: Querying \"%s\" as a string failed"), s_apszScsiDisks); + } + } + + /* * Register I/O Ports and PC BIOS. */ @@ -1256,8 +1368,9 @@ static DECLCALLBACK(int) pcbiosConstruct(PPDMDEVINS pDevIns, int iInstance, PCF uuid.Gen.u16TimeMid = RT_H2BE_U16(uuid.Gen.u16TimeMid); uuid.Gen.u16TimeHiAndVersion = RT_H2BE_U16(uuid.Gen.u16TimeHiAndVersion); uint16_t cbDmiTables = 0; + uint16_t cNumDmiTables = 0; rc = FwCommonPlantDMITable(pDevIns, pThis->au8DMIPage, VBOX_DMI_TABLE_SIZE, - &uuid, pCfg, pThis->cCpus, &cbDmiTables); + &uuid, pCfg, pThis->cCpus, &cbDmiTables, &cNumDmiTables); if (RT_FAILURE(rc)) return rc; @@ -1271,7 +1384,8 @@ static DECLCALLBACK(int) pcbiosConstruct(PPDMDEVINS pDevIns, int iInstance, PCF && pThis->pu8PcBios[i + 0x04] == '_' && *(uint16_t*)&pThis->pu8PcBios[i + 0x06] == 0) { - *(uint16_t*)&pThis->pu8PcBios[i + 0x06] = cbDmiTables; + *(uint16_t*)&pThis->pu8PcBios[i + 0x06] = RT_H2LE_U16(cbDmiTables); + *(uint16_t*)&pThis->pu8PcBios[i + 0x0C] = RT_H2LE_U16(cNumDmiTables); uint8_t u8Sum = 0; for (unsigned j = 0; j < pThis->cbPcBios; j++) if (j != i + 0x05) @@ -1433,11 +1547,6 @@ static DECLCALLBACK(int) pcbiosConstruct(PPDMDEVINS pDevIns, int iInstance, PCF if (pThis->uBootDelay > 15) pThis->uBootDelay = 15; - /* - * Call reset plant tables and shadow the PXE ROM. - */ - pcbiosReset(pDevIns); - return VINF_SUCCESS; } @@ -1471,12 +1580,12 @@ const PDMDEVREG g_DevicePcBios = pcbiosDestruct, /* pfnRelocate */ NULL, - /* pfnIOCtl */ - NULL, + /* pfnMemSetup */ + pcbiosMemSetup, /* pfnPowerOn */ NULL, /* pfnReset */ - pcbiosReset, + NULL, /* pfnSuspend */ NULL, /* pfnResume */ @@ -1496,3 +1605,4 @@ const PDMDEVREG g_DevicePcBios = /* u32VersionEnd */ PDM_DEVREG_VERSION }; + |