diff options
Diffstat (limited to 'src/VBox/Main/src-client/ConsoleImpl2.cpp')
-rw-r--r-- | src/VBox/Main/src-client/ConsoleImpl2.cpp | 676 |
1 files changed, 451 insertions, 225 deletions
diff --git a/src/VBox/Main/src-client/ConsoleImpl2.cpp b/src/VBox/Main/src-client/ConsoleImpl2.cpp index b81c39423..aae3a5e30 100644 --- a/src/VBox/Main/src-client/ConsoleImpl2.cpp +++ b/src/VBox/Main/src-client/ConsoleImpl2.cpp @@ -1,4 +1,4 @@ -/* $Id: ConsoleImpl2.cpp $ */ +/* $Id: ConsoleImpl2.cpp 37902 2011-07-12 13:49:32Z vboxsync $ */ /** @file * VBox Console COM Class implementation * @@ -33,6 +33,9 @@ #endif #include "VMMDev.h" #include "Global.h" +#ifdef VBOX_WITH_PCI_PASSTHROUGH +# include "PciRawDevImpl.h" +#endif // generated header #include "SchemaDefs.h" @@ -96,7 +99,7 @@ # include <net80211/ieee80211_ioctl.h> # endif # if defined(RT_OS_WINDOWS) -# include <VBox/WinNetConfig.h> +# include <VBox/VBoxNetCfg-win.h> # include <Ntddndis.h> # include <devguid.h> # else @@ -312,15 +315,17 @@ static int getSmcDeviceKey(IMachine *pMachine, BSTR *aKey, bool *pfGetKeyFromRea # pragma optimize("g", off) #endif +static const char *const g_apszIDEDrives[4] = + { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" }; -class ConfigError : public iprt::Error +class ConfigError : public RTCError { public: ConfigError(const char *pcszFunction, int vrc, const char *pcszName) - : iprt::Error(Utf8StrFmt("%s failed: rc=%Rrc, pcszName=%s", pcszFunction, vrc, pcszName)), + : RTCError(Utf8StrFmt("%s failed: rc=%Rrc, pcszName=%s", pcszFunction, vrc, pcszName)), m_vrc(vrc) { AssertMsgFailed(("%s\n", what())); // in strict mode, hit a breakpoint here @@ -331,7 +336,7 @@ public: /** - * Helper that calls CFGMR3InsertString and throws an iprt::Error if that + * Helper that calls CFGMR3InsertString and throws an RTCError if that * fails (C-string variant). * @param pParent See CFGMR3InsertStringN. * @param pcszNodeName See CFGMR3InsertStringN. @@ -349,7 +354,7 @@ static void InsertConfigString(PCFGMNODE pNode, } /** - * Helper that calls CFGMR3InsertString and throws an iprt::Error if that + * Helper that calls CFGMR3InsertString and throws an RTCError if that * fails (Utf8Str variant). * @param pParent See CFGMR3InsertStringN. * @param pcszNodeName See CFGMR3InsertStringN. @@ -368,7 +373,7 @@ static void InsertConfigString(PCFGMNODE pNode, } /** - * Helper that calls CFGMR3InsertString and throws an iprt::Error if that + * Helper that calls CFGMR3InsertString and throws an RTCError if that * fails (Bstr variant). * * @param pParent See CFGMR3InsertStringN. @@ -383,7 +388,7 @@ static void InsertConfigString(PCFGMNODE pNode, } /** - * Helper that calls CFGMR3InsertBytes and throws an iprt::Error if that fails. + * Helper that calls CFGMR3InsertBytes and throws an RTCError if that fails. * * @param pNode See CFGMR3InsertBytes. * @param pcszName See CFGMR3InsertBytes. @@ -404,7 +409,7 @@ static void InsertConfigBytes(PCFGMNODE pNode, } /** - * Helper that calls CFGMR3InsertInteger and throws an iprt::Error if that + * Helper that calls CFGMR3InsertInteger and throws an RTCError if that * fails. * * @param pNode See CFGMR3InsertInteger. @@ -423,7 +428,7 @@ static void InsertConfigInteger(PCFGMNODE pNode, } /** - * Helper that calls CFGMR3InsertNode and throws an iprt::Error if that fails. + * Helper that calls CFGMR3InsertNode and throws an RTCError if that fails. * * @param pNode See CFGMR3InsertNode. * @param pcszName See CFGMR3InsertNode. @@ -439,7 +444,7 @@ static void InsertConfigNode(PCFGMNODE pNode, } /** - * Helper that calls CFGMR3RemoveValue and throws an iprt::Error if that fails. + * Helper that calls CFGMR3RemoveValue and throws an RTCError if that fails. * * @param pNode See CFGMR3RemoveValue. * @param pcszName See CFGMR3RemoveValue. @@ -452,6 +457,172 @@ static void RemoveConfigValue(PCFGMNODE pNode, throw ConfigError("CFGMR3RemoveValue", vrc, pcszName); } +#ifdef VBOX_WITH_PCI_PASSTHROUGH +HRESULT Console::attachRawPciDevices(PVM pVM, + BusAssignmentManager *BusMgr, + PCFGMNODE pDevices) +{ + HRESULT hrc = S_OK; + PCFGMNODE pInst, pCfg, pLunL0, pLunL1; + + SafeIfaceArray<IPciDeviceAttachment> assignments; + ComPtr<IMachine> aMachine = machine(); + + hrc = aMachine->COMGETTER(PciDeviceAssignments)(ComSafeArrayAsOutParam(assignments)); + if ( hrc != S_OK + || assignments.size() < 1) + return hrc; + + /* + * PCI passthrough is only available if the proper ExtPack is installed. + * + * Note. Configuring PCI passthrough here and providing messages about + * the missing extpack isn't exactly clean, but it is a necessary evil + * to patch over legacy compatability issues introduced by the new + * distribution model. + */ +# ifdef VBOX_WITH_EXTPACK + static const char *s_pszPciRawExtPackName = "Oracle VM VirtualBox Extension Pack"; + if (!mptrExtPackManager->isExtPackUsable(s_pszPciRawExtPackName)) + { + /* Always fatal! */ + return VMSetError(pVM, VERR_NOT_FOUND, RT_SRC_POS, + N_("Implementation of the PCI passthrough framework not found!\n" + "The VM cannot be started. To fix this problem, either " + "install the '%s' or disable PCI passthrough via VBoxManage"), + s_pszPciRawExtPackName); + } +# endif + + PCFGMNODE pBridges = CFGMR3GetChild(pDevices, "ich9pcibridge"); + Assert(pBridges); + + /* Find required bridges, and add missing ones */ + for (size_t iDev = 0; iDev < assignments.size(); iDev++) + { + ComPtr<IPciDeviceAttachment> assignment = assignments[iDev]; + LONG guest = 0; + PciBusAddress GuestPciAddress; + + assignment->COMGETTER(GuestAddress)(&guest); + GuestPciAddress.fromLong(guest); + Assert(GuestPciAddress.valid()); + + if (GuestPciAddress.miBus > 0) + { + int iBridgesMissed = 0; + int iBase = GuestPciAddress.miBus - 1; + + while (!BusMgr->hasPciDevice("ich9pcibridge", iBase) && iBase > 0) + { + iBridgesMissed++; iBase--; + } + iBase++; + + for (int iBridge = 0; iBridge < iBridgesMissed; iBridge++) + { + InsertConfigNode(pBridges, Utf8StrFmt("%d", iBase + iBridge).c_str(), &pInst); + InsertConfigInteger(pInst, "Trusted", 1); + hrc = BusMgr->assignPciDevice("ich9pcibridge", pInst); + } + } + } + + /* Now actually add devices */ + PCFGMNODE pPciDevs = NULL; + + if (assignments.size() > 0) + { + InsertConfigNode(pDevices, "pciraw", &pPciDevs); + + PCFGMNODE pRoot = CFGMR3GetParent(pDevices); Assert(pRoot); + + /* Tell PGM to tell GPciRaw about guest mappings. */ + CFGMR3InsertNode(pRoot, "PGM", NULL); + InsertConfigInteger(CFGMR3GetChild(pRoot, "PGM"), "PciPassThrough", 1); + + /* + * Currently, using IOMMU needed for PCI passthrough + * requires RAM preallocation. + */ + /** @todo: check if we can lift this requirement */ + CFGMR3RemoveValue(pRoot, "RamPreAlloc"); + InsertConfigInteger(pRoot, "RamPreAlloc", 1); + } + + for (size_t iDev = 0; iDev < assignments.size(); iDev++) + { + PciBusAddress HostPciAddress, GuestPciAddress; + ComPtr<IPciDeviceAttachment> assignment = assignments[iDev]; + LONG host, guest; + Bstr aDevName; + + assignment->COMGETTER(HostAddress)(&host); + assignment->COMGETTER(GuestAddress)(&guest); + assignment->COMGETTER(Name)(aDevName.asOutParam()); + + InsertConfigNode(pPciDevs, Utf8StrFmt("%d", iDev).c_str(), &pInst); + InsertConfigInteger(pInst, "Trusted", 1); + + HostPciAddress.fromLong(host); + Assert(HostPciAddress.valid()); + InsertConfigNode(pInst, "Config", &pCfg); + InsertConfigString(pCfg, "DeviceName", aDevName); + + InsertConfigInteger(pCfg, "DetachHostDriver", 1); + InsertConfigInteger(pCfg, "HostPCIBusNo", HostPciAddress.miBus); + InsertConfigInteger(pCfg, "HostPCIDeviceNo", HostPciAddress.miDevice); + InsertConfigInteger(pCfg, "HostPCIFunctionNo", HostPciAddress.miFn); + + GuestPciAddress.fromLong(guest); + Assert(GuestPciAddress.valid()); + hrc = BusMgr->assignHostPciDevice("pciraw", pInst, HostPciAddress, GuestPciAddress, true); + if (hrc != S_OK) + return hrc; + + InsertConfigInteger(pCfg, "GuestPCIBusNo", GuestPciAddress.miBus); + InsertConfigInteger(pCfg, "GuestPCIDeviceNo", GuestPciAddress.miDevice); + InsertConfigInteger(pCfg, "GuestPCIFunctionNo", GuestPciAddress.miFn); + + /* the driver */ + InsertConfigNode(pInst, "LUN#0", &pLunL0); + InsertConfigString(pLunL0, "Driver", "pciraw"); + InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1); + + /* the Main driver */ + InsertConfigString(pLunL1, "Driver", "MainPciRaw"); + InsertConfigNode(pLunL1, "Config", &pCfg); + PciRawDev* pMainDev = new PciRawDev(this); + InsertConfigInteger(pCfg, "Object", (uintptr_t)pMainDev); + } + + return hrc; +} +#endif + + +void Console::attachStatusDriver(PCFGMNODE pCtlInst, PPDMLED *papLeds, + uint64_t uFirst, uint64_t uLast, + Console::MediumAttachmentMap *pmapMediumAttachments, + const char *pcszDevice, unsigned uInstance) +{ + PCFGMNODE pLunL0, pCfg; + InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); + InsertConfigString(pLunL0, "Driver", "MainStatus"); + InsertConfigNode(pLunL0, "Config", &pCfg); + InsertConfigInteger(pCfg, "papLeds", (uintptr_t)papLeds); + if (pmapMediumAttachments) + { + InsertConfigInteger(pCfg, "pmapMediumAttachments", (uintptr_t)pmapMediumAttachments); + InsertConfigInteger(pCfg, "pConsole", (uintptr_t)this); + AssertPtr(pcszDevice); + Utf8Str deviceInstance = Utf8StrFmt("%s/%u", pcszDevice, uInstance); + InsertConfigString(pCfg, "DeviceInstance", deviceInstance.c_str()); + } + InsertConfigInteger(pCfg, "First", uFirst); + InsertConfigInteger(pCfg, "Last", uLast); +} + /** * Construct the VM configuration tree (CFGM). @@ -483,10 +654,14 @@ DECLCALLBACK(int) Console::configConstructor(PVM pVM, void *pvConsole) * Set the VM handle and do the rest of the job in an worker method so we * can easily reset the VM handle on failure. */ - pConsole->mpVM = pVM; + PUVM pUVM = pConsole->mpUVM = VMR3GetUVM(pVM); + VMR3RetainUVM(pUVM); int vrc = pConsole->configConstructorInner(pVM, &alock); if (RT_FAILURE(vrc)) - pConsole->mpVM = NULL; + { + pConsole->mpUVM = NULL; + VMR3ReleaseUVM(pUVM); + } return vrc; } @@ -497,6 +672,9 @@ DECLCALLBACK(int) Console::configConstructor(PVM pVM, void *pvConsole) * * @return VBox status code. * @param pVM The VM handle. + * @param pAlock The automatic lock instance. This is for when we have + * to leave it in order to avoid deadlocks (ext packs and + * more). */ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) { @@ -515,24 +693,24 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) * Get necessary objects and frequently used parameters. */ ComPtr<IVirtualBox> virtualBox; - hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H(); + hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H(); ComPtr<IHost> host; - hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H(); + hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H(); ComPtr<ISystemProperties> systemProperties; - hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); H(); + hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); H(); ComPtr<IBIOSSettings> biosSettings; - hrc = pMachine->COMGETTER(BIOSSettings)(biosSettings.asOutParam()); H(); + hrc = pMachine->COMGETTER(BIOSSettings)(biosSettings.asOutParam()); H(); - hrc = pMachine->COMGETTER(HardwareUUID)(bstr.asOutParam()); H(); + hrc = pMachine->COMGETTER(HardwareUUID)(bstr.asOutParam()); H(); RTUUID HardwareUuid; rc = RTUuidFromUtf16(&HardwareUuid, bstr.raw()); AssertRCReturn(rc, rc); ULONG cRamMBs; - hrc = pMachine->COMGETTER(MemorySize)(&cRamMBs); H(); + hrc = pMachine->COMGETTER(MemorySize)(&cRamMBs); H(); #if 0 /* enable to play with lots of memory. */ if (RTEnvExist("VBOX_RAM_SIZE")) cRamMBs = RTStrToUInt64(RTEnvGet("VBOX_RAM_SIZE")); @@ -543,7 +721,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) uint32_t cbMcfgLength = 0; ChipsetType_T chipsetType; - hrc = pMachine->COMGETTER(ChipsetType)(&chipsetType); H(); + hrc = pMachine->COMGETTER(ChipsetType)(&chipsetType); H(); if (chipsetType == ChipsetType_ICH9) { /* We'd better have 0x10000000 region, to cover 256 buses @@ -556,22 +734,22 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) BusAssignmentManager* BusMgr = mBusMgr = BusAssignmentManager::createInstance(chipsetType); ULONG cCpus = 1; - hrc = pMachine->COMGETTER(CPUCount)(&cCpus); H(); + hrc = pMachine->COMGETTER(CPUCount)(&cCpus); H(); ULONG ulCpuExecutionCap = 100; - hrc = pMachine->COMGETTER(CPUExecutionCap)(&ulCpuExecutionCap); H(); + hrc = pMachine->COMGETTER(CPUExecutionCap)(&ulCpuExecutionCap); H(); Bstr osTypeId; - hrc = pMachine->COMGETTER(OSTypeId)(osTypeId.asOutParam()); H(); + hrc = pMachine->COMGETTER(OSTypeId)(osTypeId.asOutParam()); H(); BOOL fIOAPIC; - hrc = biosSettings->COMGETTER(IOAPICEnabled)(&fIOAPIC); H(); + hrc = biosSettings->COMGETTER(IOAPICEnabled)(&fIOAPIC); H(); ComPtr<IGuestOSType> guestOSType; - hrc = virtualBox->GetGuestOSType(osTypeId.raw(), guestOSType.asOutParam()); H(); + hrc = virtualBox->GetGuestOSType(osTypeId.raw(), guestOSType.asOutParam()); H(); Bstr guestTypeFamilyId; - hrc = guestOSType->COMGETTER(FamilyId)(guestTypeFamilyId.asOutParam()); H(); + hrc = guestOSType->COMGETTER(FamilyId)(guestTypeFamilyId.asOutParam()); H(); BOOL fOsXGuest = guestTypeFamilyId == Bstr("MacOS"); /* @@ -919,15 +1097,19 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) InsertConfigNode(pDevices, "ich9pcibridge", &pDev); InsertConfigNode(pDev, "0", &pInst); InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ - hrc = BusMgr->assignPciDevice("ich9pcibridge", pInst); H(); + hrc = BusMgr->assignPciDevice("ich9pcibridge", pInst); H(); InsertConfigNode(pDev, "1", &pInst); InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ - hrc = BusMgr->assignPciDevice("ich9pcibridge", pInst); H(); - } + hrc = BusMgr->assignPciDevice("ich9pcibridge", pInst); H(); +#ifdef VBOX_WITH_PCI_PASSTHROUGH + /* Add PCI passthrough devices */ + hrc = attachRawPciDevices(pVM, BusMgr, pDevices); H(); +#endif + } /* - * Enable 3 following devices: HPET, SMC, LPC on MacOS X guests + * Enable 3 following devices: HPET, SMC, LPC on MacOS X guests or on ICH9 chipset */ /* * High Precision Event Timer (HPET) @@ -944,6 +1126,8 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) InsertConfigNode(pDevices, "hpet", &pDev); InsertConfigNode(pDev, "0", &pInst); InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ + InsertConfigNode(pInst, "Config", &pCfg); + InsertConfigInteger(pCfg, "ICH9", (chipsetType == ChipsetType_ICH9) ? 1 : 0); /* boolean */ } /* @@ -977,7 +1161,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) { InsertConfigNode(pDevices, "lpc", &pDev); InsertConfigNode(pDev, "0", &pInst); - hrc = BusMgr->assignPciDevice("lpc", pInst); H(); + hrc = BusMgr->assignPciDevice("lpc", pInst); H(); InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ } @@ -1053,6 +1237,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) InsertConfigNode(pDev, "0", &pInst); InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ InsertConfigNode(pInst, "Config", &pCfg); + InsertConfigInteger(pCfg, "NumCPUs", cCpus); } /* @@ -1072,7 +1257,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) InsertConfigNode(pDev, "0", &pInst); InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ - hrc = BusMgr->assignPciDevice("vga", pInst); H(); + hrc = BusMgr->assignPciDevice("vga", pInst); H(); InsertConfigNode(pInst, "Config", &pCfg); ULONG cVRamMBs; hrc = pMachine->COMGETTER(VRAMSize)(&cVRamMBs); H(); @@ -1343,43 +1528,35 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) { case StorageControllerType_LsiLogic: { - hrc = BusMgr->assignPciDevice("lsilogic", pCtlInst); H(); + hrc = BusMgr->assignPciDevice("lsilogic", pCtlInst); H(); InsertConfigInteger(pCfg, "Bootable", fBootable); /* Attach the status driver */ - InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); - InsertConfigString(pLunL0, "Driver", "MainStatus"); - InsertConfigNode(pLunL0, "Config", &pCfg); - InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&mapStorageLeds[iLedScsi]); - InsertConfigInteger(pCfg, "First", 0); Assert(cLedScsi >= 16); - InsertConfigInteger(pCfg, "Last", 15); + attachStatusDriver(pCtlInst, &mapStorageLeds[iLedScsi], 0, 15, + &mapMediumAttachments, pszCtrlDev, ulInstance); paLedDevType = &maStorageDevType[iLedScsi]; break; } case StorageControllerType_BusLogic: { - hrc = BusMgr->assignPciDevice("buslogic", pCtlInst); H(); + hrc = BusMgr->assignPciDevice("buslogic", pCtlInst); H(); InsertConfigInteger(pCfg, "Bootable", fBootable); /* Attach the status driver */ - InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); - InsertConfigString(pLunL0, "Driver", "MainStatus"); - InsertConfigNode(pLunL0, "Config", &pCfg); - InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&mapStorageLeds[iLedScsi]); - InsertConfigInteger(pCfg, "First", 0); Assert(cLedScsi >= 16); - InsertConfigInteger(pCfg, "Last", 15); + attachStatusDriver(pCtlInst, &mapStorageLeds[iLedScsi], 0, 15, + &mapMediumAttachments, pszCtrlDev, ulInstance); paLedDevType = &maStorageDevType[iLedScsi]; break; } case StorageControllerType_IntelAhci: { - hrc = BusMgr->assignPciDevice("ahci", pCtlInst); H(); + hrc = BusMgr->assignPciDevice("ahci", pCtlInst); H(); ULONG cPorts = 0; hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts); H(); @@ -1396,27 +1573,21 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) for (uint32_t j = 0; j < 4; ++j) { - static const char * const s_apszConfig[4] = - { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" }; static const char * const s_apszBiosConfig[4] = { "SataPrimaryMasterLUN", "SataPrimarySlaveLUN", "SataSecondaryMasterLUN", "SataSecondarySlaveLUN" }; LONG lPortNumber = -1; - hrc = ctrls[i]->GetIDEEmulationPort(j, &lPortNumber); H(); - InsertConfigInteger(pCfg, s_apszConfig[j], lPortNumber); + hrc = ctrls[i]->GetIDEEmulationPort(j, &lPortNumber); H(); + InsertConfigInteger(pCfg, g_apszIDEDrives[j], lPortNumber); if (pBiosCfg) InsertConfigInteger(pBiosCfg, s_apszBiosConfig[j], lPortNumber); } } /* Attach the status driver */ - InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); - InsertConfigString(pLunL0, "Driver", "MainStatus"); - InsertConfigNode(pLunL0, "Config", &pCfg); AssertRelease(cPorts <= cLedSata); - InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&mapStorageLeds[iLedSata]); - InsertConfigInteger(pCfg, "First", 0); - InsertConfigInteger(pCfg, "Last", cPorts - 1); + attachStatusDriver(pCtlInst, &mapStorageLeds[iLedSata], 0, cPorts - 1, + &mapMediumAttachments, pszCtrlDev, ulInstance); paLedDevType = &maStorageDevType[iLedSata]; break; } @@ -1428,17 +1599,12 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) /* * IDE (update this when the main interface changes) */ - hrc = BusMgr->assignPciDevice("piix3ide", pCtlInst); H(); + hrc = BusMgr->assignPciDevice("piix3ide", pCtlInst); H(); InsertConfigString(pCfg, "Type", controllerString(enmCtrlType)); - /* Attach the status driver */ - InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); - InsertConfigString(pLunL0, "Driver", "MainStatus"); - InsertConfigNode(pLunL0, "Config", &pCfg); - InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&mapStorageLeds[iLedIde]); - InsertConfigInteger(pCfg, "First", 0); Assert(cLedIde >= 4); - InsertConfigInteger(pCfg, "Last", 3); + attachStatusDriver(pCtlInst, &mapStorageLeds[iLedIde], 0, 3, + &mapMediumAttachments, pszCtrlDev, ulInstance); paLedDevType = &maStorageDevType[iLedIde]; /* IDE flavors */ @@ -1460,32 +1626,24 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) InsertConfigInteger(pCfg, "IOBase", 0x3f0); /* Attach the status driver */ - InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); - InsertConfigString(pLunL0, "Driver", "MainStatus"); - InsertConfigNode(pLunL0, "Config", &pCfg); - InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&mapStorageLeds[iLedFloppy]); - InsertConfigInteger(pCfg, "First", 0); - Assert(cLedFloppy >= 1); - InsertConfigInteger(pCfg, "Last", 0); + Assert(cLedFloppy >= 2); + attachStatusDriver(pCtlInst, &mapStorageLeds[iLedFloppy], 0, 1, + &mapMediumAttachments, pszCtrlDev, ulInstance); paLedDevType = &maStorageDevType[iLedFloppy]; break; } case StorageControllerType_LsiLogicSas: { - hrc = BusMgr->assignPciDevice("lsilogicsas", pCtlInst); H(); + hrc = BusMgr->assignPciDevice("lsilogicsas", pCtlInst); H(); InsertConfigString(pCfg, "ControllerType", "SAS1068"); InsertConfigInteger(pCfg, "Bootable", fBootable); /* Attach the status driver */ - InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); - InsertConfigString(pLunL0, "Driver", "MainStatus"); - InsertConfigNode(pLunL0, "Config", &pCfg); - InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&mapStorageLeds[iLedSas]); - InsertConfigInteger(pCfg, "First", 0); Assert(cLedSas >= 8); - InsertConfigInteger(pCfg, "Last", 7); + attachStatusDriver(pCtlInst, &mapStorageLeds[iLedSas], 0, 7, + &mapMediumAttachments, pszCtrlDev, ulInstance); paLedDevType = &maStorageDevType[iLedSas]; break; } @@ -1497,15 +1655,16 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) /* Attach the media to the storage controllers. */ com::SafeIfaceArray<IMediumAttachment> atts; hrc = pMachine->GetMediumAttachmentsOfController(controllerName.raw(), - ComSafeArrayAsOutParam(atts)); H(); + ComSafeArrayAsOutParam(atts)); H(); /* Builtin I/O cache - per device setting. */ BOOL fBuiltinIoCache = true; - hrc = pMachine->COMGETTER(IoCacheEnabled)(&fBuiltinIoCache); H(); + hrc = pMachine->COMGETTER(IoCacheEnabled)(&fBuiltinIoCache); H(); for (size_t j = 0; j < atts.size(); ++j) { + IMediumAttachment *pMediumAtt = atts[j]; rc = configMediumAttachment(pCtlInst, pszCtrlDev, ulInstance, @@ -1515,11 +1674,12 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) false /* fSetupMerge */, 0 /* uMergeSource */, 0 /* uMergeTarget */, - atts[j], + pMediumAtt, mMachineState, NULL /* phrc */, false /* fAttachDetach */, false /* fForceUnmount */, + false /* fHotplug */, pVM, paLedDevType); if (RT_FAILURE(rc)) @@ -1624,7 +1784,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) iPciDeviceNo = 3; #endif PciBusAddress PciAddr = PciBusAddress(0, iPciDeviceNo, 0); - hrc = BusMgr->assignPciDevice(pszAdapterName, pInst, PciAddr); H(); + hrc = BusMgr->assignPciDevice(pszAdapterName, pInst, PciAddr); H(); InsertConfigNode(pInst, "Config", &pCfg); #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE /* not safe here yet. */ @@ -1709,10 +1869,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) /* * Attach the status driver. */ - InsertConfigNode(pInst, "LUN#999", &pLunL0); - InsertConfigString(pLunL0, "Driver", "MainStatus"); - InsertConfigNode(pLunL0, "Config", &pCfg); - InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&mapNetworkLeds[ulInstance]); + attachStatusDriver(pInst, &mapNetworkLeds[ulInstance], 0, 0, NULL, NULL, 0); /* * Configure the network card now @@ -1751,15 +1908,18 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) achBootIdx[0] = '0' + uBootIdx++; /* Boot device order. */ InsertConfigNode(pNetBootCfg, achBootIdx, &pNetBtDevCfg); InsertConfigInteger(pNetBtDevCfg, "NIC", it->mInstance); - InsertConfigInteger(pNetBtDevCfg, "PCIBusNo", it->mPciAddress.iBus); - InsertConfigInteger(pNetBtDevCfg, "PCIDeviceNo", it->mPciAddress.iDevice); - InsertConfigInteger(pNetBtDevCfg, "PCIFunctionNo", it->mPciAddress.iFn); + InsertConfigInteger(pNetBtDevCfg, "PCIBusNo", it->mPciAddress.miBus); + InsertConfigInteger(pNetBtDevCfg, "PCIDeviceNo", it->mPciAddress.miDevice); + InsertConfigInteger(pNetBtDevCfg, "PCIFunctionNo", it->mPciAddress.miFn); } } /* * Serial (UART) Ports */ + /* serial enabled mask to be passed to dev ACPI */ + uint16_t auSerialIoPortBase[SchemaDefs::SerialPortCount] = {0}; + uint8_t auSerialIrq[SchemaDefs::SerialPortCount] = {0}; InsertConfigNode(pDevices, "serial", &pDev); for (ULONG ulInstance = 0; ulInstance < SchemaDefs::SerialPortCount; ++ulInstance) { @@ -1777,9 +1937,13 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) ULONG ulIRQ; hrc = serialPort->COMGETTER(IRQ)(&ulIRQ); H(); InsertConfigInteger(pCfg, "IRQ", ulIRQ); + auSerialIrq[ulInstance] = (uint8_t)ulIRQ; + ULONG ulIOBase; hrc = serialPort->COMGETTER(IOBase)(&ulIOBase); H(); InsertConfigInteger(pCfg, "IOBase", ulIOBase); + auSerialIoPortBase[ulInstance] = (uint16_t)ulIOBase; + BOOL fServer; hrc = serialPort->COMGETTER(Server)(&fServer); H(); hrc = serialPort->COMGETTER(Path)(bstr.asOutParam()); H(); @@ -1853,7 +2017,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) InsertConfigNode(pDev, "0", &pInst); InsertConfigNode(pInst, "Config", &pCfg); InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ - hrc = BusMgr->assignPciDevice("VMMDev", pInst); H(); + hrc = BusMgr->assignPciDevice("VMMDev", pInst); H(); Bstr hwVersion; hrc = pMachine->COMGETTER(HardwareVersion)(hwVersion.asOutParam()); H(); @@ -1861,7 +2025,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) if (hwVersion.compare(Bstr("1").raw()) == 0) /* <= 2.0.x */ InsertConfigInteger(pCfg, "HeapEnabled", 0); Bstr snapshotFolder; - hrc = pMachine->COMGETTER(SnapshotFolder)(snapshotFolder.asOutParam()); H(); + hrc = pMachine->COMGETTER(SnapshotFolder)(snapshotFolder.asOutParam()); H(); InsertConfigString(pCfg, "GuestCoreDumpDir", snapshotFolder); /* the VMM device's Main driver */ @@ -1873,12 +2037,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) /* * Attach the status driver. */ - InsertConfigNode(pInst, "LUN#999", &pLunL0); - InsertConfigString(pLunL0, "Driver", "MainStatus"); - InsertConfigNode(pLunL0, "Config", &pCfg); - InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&mapSharedFolderLed); - InsertConfigInteger(pCfg, "First", 0); - InsertConfigInteger(pCfg, "Last", 0); + attachStatusDriver(pInst, &mapSharedFolderLed, 0, 0, NULL, NULL, 0); /* * Audio Sniffer Device @@ -1897,7 +2056,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) /* * AC'97 ICH / SoundBlaster16 audio / Intel HD Audio */ - BOOL fAudioEnabled; + BOOL fAudioEnabled = FALSE; ComPtr<IAudioAdapter> audioAdapter; hrc = pMachine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam()); H(); if (audioAdapter) @@ -1915,7 +2074,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) InsertConfigNode(pDevices, "ichac97", &pDev); InsertConfigNode(pDev, "0", &pInst); InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ - hrc = BusMgr->assignPciDevice("ichac97", pInst); H(); + hrc = BusMgr->assignPciDevice("ichac97", pInst); H(); InsertConfigNode(pInst, "Config", &pCfg); break; } @@ -1939,7 +2098,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) InsertConfigNode(pDevices, "hda", &pDev); InsertConfigNode(pDev, "0", &pInst); InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ - hrc = BusMgr->assignPciDevice("hda", pInst); H(); + hrc = BusMgr->assignPciDevice("hda", pInst); H(); InsertConfigNode(pInst, "Config", &pCfg); } } @@ -2046,12 +2205,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) /* * Attach the status driver. */ - InsertConfigNode(pInst, "LUN#999", &pLunL0); - InsertConfigString(pLunL0, "Driver", "MainStatus"); - InsertConfigNode(pLunL0, "Config", &pCfg); - InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&mapUSBLed[0]); - InsertConfigInteger(pCfg, "First", 0); - InsertConfigInteger(pCfg, "Last", 0); + attachStatusDriver(pInst, &mapUSBLed[0], 0, 0, NULL, NULL, 0); #ifdef VBOX_WITH_EHCI BOOL fEhciEnabled; @@ -2084,12 +2238,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) /* * Attach the status driver. */ - InsertConfigNode(pInst, "LUN#999", &pLunL0); - InsertConfigString(pLunL0, "Driver", "MainStatus"); - InsertConfigNode(pLunL0, "Config", &pCfg); - InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&mapUSBLed[1]); - InsertConfigInteger(pCfg, "First", 0); - InsertConfigInteger(pCfg, "Last", 0); + attachStatusDriver(pInst, &mapUSBLed[1], 0, 0, NULL, NULL, 0); } # ifdef VBOX_WITH_EXTPACK else @@ -2131,6 +2280,25 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) } #endif +#ifdef VBOX_WITH_USB_VIDEO + + InsertConfigNode(pUsbDevices, "Webcam", &pDev); + InsertConfigNode(pDev, "0", &pInst); + InsertConfigNode(pInst, "Config", &pCfg); +# if 0 /* Experiments with attaching */ + InsertConfigInteger(pCfg, "USBVER", RT_BIT(2)); +# endif + InsertConfigNode(pInst, "LUN#0", &pLunL0); +# ifdef VBOX_WITH_USB_VIDEO_TEST + InsertConfigString(pLunL0, "Driver", "WebcamFileFeeder"); + InsertConfigNode(pLunL0, "Config", &pCfg); + InsertConfigString(pCfg, "DirToFeed", "out"); +# else + InsertConfigString(pLunL0, "Driver", "UsbWebcamInterface"); + InsertConfigNode(pLunL0, "Config", &pCfg); + InsertConfigInteger(pCfg, "Object", mUsbWebcamInterface); +# endif +#endif # if 0 /* Virtual MSD*/ InsertConfigNode(pUsbDevices, "Msd", &pDev); @@ -2262,6 +2430,10 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm); + parm.setUInt32(!useHostClipboard()); + + pVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_HEADLESS, 1, &parm); + Log(("Set VBoxSharedClipboard mode\n")); } } @@ -2363,7 +2535,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) if (fOsXGuest && !llBootNics.empty()) { BootNic aNic = llBootNics.front(); - uint32_t u32NicPciAddr = (aNic.mPciAddress.iDevice << 16) | aNic.mPciAddress.iFn; + uint32_t u32NicPciAddr = (aNic.mPciAddress.miDevice << 16) | aNic.mPciAddress.miFn; InsertConfigInteger(pCfg, "NicPciAddress", u32NicPciAddr); } if (fOsXGuest && fAudioEnabled) @@ -2371,7 +2543,7 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) PciBusAddress Address; if (BusMgr->findPciAddress("hda", 0, Address)) { - uint32_t u32AudioPciAddr = (Address.iDevice << 16) | Address.iFn; + uint32_t u32AudioPciAddr = (Address.miDevice << 16) | Address.miFn; InsertConfigInteger(pCfg, "AudioPciAddress", u32AudioPciAddr); } } @@ -2385,6 +2557,12 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) InsertConfigInteger(pCfg, "ShowCpu", fShowCpu); InsertConfigInteger(pCfg, "CpuHotPlug", fCpuHotPlug); + InsertConfigInteger(pCfg, "Serial0IoPortBase", auSerialIoPortBase[0]); + InsertConfigInteger(pCfg, "Serial0Irq", auSerialIrq[0]); + + InsertConfigInteger(pCfg, "Serial1IoPortBase", auSerialIoPortBase[1]); + InsertConfigInteger(pCfg, "Serial1Irq", auSerialIrq[1]); + InsertConfigNode(pInst, "LUN#0", &pLunL0); InsertConfigString(pLunL0, "Driver", "ACPIHost"); InsertConfigNode(pLunL0, "Config", &pCfg); @@ -2434,6 +2612,8 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) #undef H + pAlock->release(); /* Avoid triggering the lock order inversion check. */ + /* * Register VM state change handler. */ @@ -2450,6 +2630,8 @@ int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock) if (RT_SUCCESS(rc)) rc = rc2; + pAlock->acquire(); + LogFlowFunc(("vrc = %Rrc\n", rc)); LogFlowFuncLeave(); @@ -2659,6 +2841,7 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst, HRESULT *phrc, bool fAttachDetach, bool fForceUnmount, + bool fHotplug, PVM pVM, DeviceType_T *paLedDevType) { @@ -2678,10 +2861,11 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst, hrc = pMediumAtt->COMGETTER(Port)(&lPort); H(); DeviceType_T lType; hrc = pMediumAtt->COMGETTER(Type)(&lType); H(); + BOOL fNonRotational; + hrc = pMediumAtt->COMGETTER(NonRotational)(&fNonRotational); H(); unsigned uLUN; PCFGMNODE pLunL0 = NULL; - PCFGMNODE pCfg = NULL; hrc = Console::convertBusPortDeviceToLun(enmBus, lPort, lDev, uLUN); H(); /* First check if the LUN already exists. */ @@ -2716,7 +2900,7 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst, } } - rc = PDMR3DeviceDetach(pVM, pcszDevice, 0, uLUN, PDM_TACH_FLAGS_NOT_HOT_PLUG); + rc = PDMR3DeviceDetach(pVM, pcszDevice, uInstance, uLUN, fHotplug ? 0 : PDM_TACH_FLAGS_NOT_HOT_PLUG); if (rc == VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN) rc = VINF_SUCCESS; AssertRCReturn(rc, rc); @@ -2729,11 +2913,42 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst, InsertConfigNode(pCtlInst, Utf8StrFmt("LUN#%u", uLUN).c_str(), &pLunL0); + PCFGMNODE pCfg = CFGMR3GetChild(pCtlInst, "Config"); + if (pCfg) + { + if (!strcmp(pcszDevice, "piix3ide")) + { + PCFGMNODE pDrive = CFGMR3GetChild(pCfg, g_apszIDEDrives[uLUN]); + if (!pDrive) + InsertConfigNode(pCfg, g_apszIDEDrives[uLUN], &pDrive); + /* Don't use the RemoveConfigValue wrapper above, as we don't + * know if the leaf is present or not. */ + CFGMR3RemoveValue(pDrive, "NonRotationalMedium"); + InsertConfigInteger(pDrive, "NonRotationalMedium", !!fNonRotational); + } + else if (!strcmp(pcszDevice, "ahci")) + { + Utf8Str strPort = Utf8StrFmt("Port%u", uLUN); + PCFGMNODE pDrive = CFGMR3GetChild(pCfg, strPort.c_str()); + if (!pDrive) + InsertConfigNode(pCfg, strPort.c_str(), &pDrive); + /* Don't use the RemoveConfigValue wrapper above, as we don't + * know if the leaf is present or not. */ + CFGMR3RemoveValue(pDrive, "NonRotationalMedium"); + InsertConfigInteger(pDrive, "NonRotationalMedium", !!fNonRotational); + } + } + /** @todo add SCSI/SAS support once the SSD support is there */ + + Utf8Str devicePath = Utf8StrFmt("%s/%u/LUN#%u", pcszDevice, uInstance, uLUN); + mapMediumAttachments[devicePath] = pMediumAtt; + /* SCSI has a another driver between device and block. */ if (enmBus == StorageBus_SCSI || enmBus == StorageBus_SAS) { InsertConfigString(pLunL0, "Driver", "SCSI"); - InsertConfigNode(pLunL0, "Config", &pCfg); + PCFGMNODE pL1Cfg = NULL; + InsertConfigNode(pLunL0, "Config", &pL1Cfg); InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0); } @@ -2937,25 +3152,25 @@ int Console::configMediumAttachment(PCFGMNODE pCtlInst, } rc = configMedium(pLunL0, - !!fPassthrough, - lType, - fUseHostIOCache, - fBuiltinIoCache, - fSetupMerge, - uMergeSource, - uMergeTarget, - strBwGroup.isEmpty() ? NULL : Utf8Str(strBwGroup).c_str(), - pMedium, - aMachineState, - phrc); + !!fPassthrough, + lType, + fUseHostIOCache, + fBuiltinIoCache, + fSetupMerge, + uMergeSource, + uMergeTarget, + strBwGroup.isEmpty() ? NULL : Utf8Str(strBwGroup).c_str(), + pMedium, + aMachineState, + phrc); if (RT_FAILURE(rc)) return rc; if (fAttachDetach) { /* Attach the new driver. */ - rc = PDMR3DeviceAttach(pVM, pcszDevice, 0, uLUN, - PDM_TACH_FLAGS_NOT_HOT_PLUG, NULL /*ppBase*/); + rc = PDMR3DeviceAttach(pVM, pcszDevice, uInstance, uLUN, + fHotplug ? 0 : PDM_TACH_FLAGS_NOT_HOT_PLUG, NULL /*ppBase*/); AssertRCReturn(rc, rc); /* There is no need to handle removable medium mounting, as we @@ -3065,18 +3280,18 @@ int Console::configMedium(PCFGMNODE pLunL0, // we failed on startup, but that's not good because the only way out then // would be to discard the VM state... MediumState_T mediumState; - hrc = pMedium->RefreshState(&mediumState); H(); + hrc = pMedium->RefreshState(&mediumState); H(); if (mediumState == MediumState_Inaccessible) { Bstr loc; - hrc = pMedium->COMGETTER(Location)(loc.asOutParam()); H(); - setVMRuntimeErrorCallbackF(mpVM, - this, - 0, - "DvdOrFloppyImageInaccessible", - "The image file '%ls' is inaccessible and is being ignored. Please select a different image file for the virtual %s drive.", - loc.raw(), - (enmType == DeviceType_DVD) ? "DVD" : "floppy"); + hrc = pMedium->COMGETTER(Location)(loc.asOutParam()); H(); + setVMRuntimeErrorCallbackF(VMR3GetVM(mpUVM), + this, + 0, + "DvdOrFloppyImageInaccessible", + "The image file '%ls' is inaccessible and is being ignored. Please select a different image file for the virtual %s drive.", + loc.raw(), + enmType == DeviceType_DVD ? "DVD" : "floppy"); pMedium = NULL; } } @@ -3179,9 +3394,9 @@ int Console::configMedium(PCFGMNODE pLunL0, bool fHostIP = true; SafeArray<BSTR> names; SafeArray<BSTR> values; - hrc = pMedium->GetProperties(NULL, - ComSafeArrayAsOutParam(names), - ComSafeArrayAsOutParam(values)); H(); + hrc = pMedium->GetProperties(Bstr().raw(), + ComSafeArrayAsOutParam(names), + ComSafeArrayAsOutParam(values)); H(); if (names.size() != 0) { @@ -3231,7 +3446,7 @@ int Console::configMedium(PCFGMNODE pLunL0, SafeArray<BSTR> aValues; hrc = pMedium->GetProperties(NULL, ComSafeArrayAsOutParam(aNames), - ComSafeArrayAsOutParam(aValues)); H(); + ComSafeArrayAsOutParam(aValues)); H(); if (aNames.size() != 0) { @@ -3292,7 +3507,8 @@ int Console::configMedium(PCFGMNODE pLunL0, * True if connection failures should be ignored * (makes only sense for bridged/host-only networks). * - * @note Locks this object for writing. + * @note Locks this object for writing. + * @thread EMT */ int Console::configNetwork(const char *pszDevice, unsigned uInstance, @@ -3323,28 +3539,31 @@ int Console::configNetwork(const char *pszDevice, */ AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); - PVM pVM = mpVM; + PVM pVM = VMR3GetVM(mpUVM); /* We're on an EMT, so this is safe. */ ComPtr<IMachine> pMachine = machine(); ComPtr<IVirtualBox> virtualBox; - hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); - H(); + hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H(); ComPtr<IHost> host; - hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); - H(); + hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H(); BOOL fSniffer; - hrc = aNetworkAdapter->COMGETTER(TraceEnabled)(&fSniffer); - H(); + hrc = aNetworkAdapter->COMGETTER(TraceEnabled)(&fSniffer); H(); - hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/AllowPromiscousGuests").raw(), bstr.asOutParam()); - if (SUCCEEDED(hrc) && bstr.isEmpty()) - hrc = virtualBox->GetExtraData(Bstr("VBoxInternal2/AllowPromiscousGuests").raw(), bstr.asOutParam()); - H(); - const char * const pszPromiscuousGuestPolicy = bstr.isNotEmpty() ? "allow-all" : "deny"; + NetworkAdapterPromiscModePolicy_T enmPromiscModePolicy; + hrc = aNetworkAdapter->COMGETTER(PromiscModePolicy)(&enmPromiscModePolicy); H(); + const char *pszPromiscuousGuestPolicy; + switch (enmPromiscModePolicy) + { + case NetworkAdapterPromiscModePolicy_Deny: pszPromiscuousGuestPolicy = "deny"; break; + case NetworkAdapterPromiscModePolicy_AllowNetwork: pszPromiscuousGuestPolicy = "allow-network"; break; + case NetworkAdapterPromiscModePolicy_AllowAll: pszPromiscuousGuestPolicy = "allow-all"; break; + default: AssertFailedReturn(VERR_INTERNAL_ERROR_4); + } + Utf8Str strNetDriver; if (fAttachDetach && fSniffer) { const char *pszNetDriver = "IntNet"; @@ -3354,6 +3573,12 @@ int Console::configNetwork(const char *pszDevice, if (meAttachmentType[uInstance] == NetworkAttachmentType_Bridged) pszNetDriver = "HostInterface"; #endif + if (meAttachmentType[uInstance] == NetworkAttachmentType_Generic) + { + hrc = aNetworkAdapter->COMGETTER(GenericDriver)(bstr.asOutParam()); H(); + strNetDriver = bstr; + pszNetDriver = strNetDriver.c_str(); + } rc = PDMR3DriverDetach(pVM, pszDevice, uInstance, uLun, pszNetDriver, 0, 0 /*fFlags*/); if (rc == VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN) @@ -3604,21 +3829,21 @@ int Console::configNetwork(const char *pszDevice, InsertConfigNode(pInst, "LUN#0", &pLunL0); } - Bstr HifName; - hrc = aNetworkAdapter->COMGETTER(HostInterface)(HifName.asOutParam()); + Bstr BridgedIfName; + hrc = aNetworkAdapter->COMGETTER(BridgedInterface)(BridgedIfName.asOutParam()); if (FAILED(hrc)) { - LogRel(("NetworkAttachmentType_Bridged: COMGETTER(HostInterface) failed, hrc (0x%x)", hrc)); + LogRel(("NetworkAttachmentType_Bridged: COMGETTER(BridgedInterface) failed, hrc (0x%x)", hrc)); H(); } - Utf8Str HifNameUtf8(HifName); - const char *pszHifName = HifNameUtf8.c_str(); + Utf8Str BridgedIfNameUtf8(BridgedIfName); + const char *pszBridgedIfName = BridgedIfNameUtf8.c_str(); # if defined(RT_OS_DARWIN) /* The name is on the form 'ifX: long name', chop it off at the colon. */ char szTrunk[8]; - strncpy(szTrunk, pszHifName, sizeof(szTrunk)); + RTStrCopy(szTrunk, sizeof(szTrunk), pszBridgedIfName); char *pszColon = (char *)memchr(szTrunk, ':', sizeof(szTrunk)); // Quick fix for #5633 // if (!pszColon) @@ -3628,11 +3853,11 @@ int Console::configNetwork(const char *pszDevice, // * network with invalid host adapter (as it is must be changed before // * the attachment), calling Detach here will cause a deadlock. // * See #4750. -// * hrc = aNetworkAdapter->Detach(); H(); +// * hrc = aNetworkAdapter->Detach(); H(); // */ // return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS, // N_("Malformed host interface networking name '%ls'"), -// HifName.raw()); +// BridgedIfName.raw()); // } if (pszColon) *pszColon = '\0'; @@ -3641,7 +3866,7 @@ int Console::configNetwork(const char *pszDevice, # elif defined(RT_OS_SOLARIS) /* The name is on the form format 'ifX[:1] - long name, chop it off at space. */ char szTrunk[256]; - strlcpy(szTrunk, pszHifName, sizeof(szTrunk)); + strlcpy(szTrunk, pszBridgedIfName, sizeof(szTrunk)); char *pszSpace = (char *)memchr(szTrunk, ' ', sizeof(szTrunk)); /* @@ -3661,14 +3886,14 @@ int Console::configNetwork(const char *pszDevice, # elif defined(RT_OS_WINDOWS) ComPtr<IHostNetworkInterface> hostInterface; - hrc = host->FindHostNetworkInterfaceByName(HifName.raw(), + hrc = host->FindHostNetworkInterfaceByName(BridgedIfName.raw(), hostInterface.asOutParam()); if (!SUCCEEDED(hrc)) { AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: FindByName failed, rc=%Rhrc (0x%x)", hrc, hrc)); return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS, N_("Nonexistent host networking interface, name '%ls'"), - HifName.raw()); + BridgedIfName.raw()); } HostNetworkInterfaceType_T eIfType; @@ -3683,7 +3908,7 @@ int Console::configNetwork(const char *pszDevice, { return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS, N_("Interface ('%ls') is not a Bridged Adapter interface"), - HifName.raw()); + BridgedIfName.raw()); } hrc = hostInterface->COMGETTER(Id)(bstr.asOutParam()); @@ -3694,14 +3919,11 @@ int Console::configNetwork(const char *pszDevice, } Guid hostIFGuid(bstr); - INetCfg *pNc; + INetCfg *pNc; ComPtr<INetCfgComponent> pAdaptorComponent; - LPWSTR pszApp; + LPWSTR pszApp; - hrc = VBoxNetCfgWinQueryINetCfg(FALSE /*fGetWriteLock*/, - L"VirtualBox", - &pNc, - &pszApp); + hrc = VBoxNetCfgWinQueryINetCfg(&pNc, FALSE, L"VirtualBox", 10, &pszApp); Assert(hrc == S_OK); if (hrc != S_OK) { @@ -3774,7 +3996,7 @@ int Console::configNetwork(const char *pszDevice, * This works and performs better than bridging a physical * interface via the current FreeBSD vboxnetflt implementation. */ - if (!strncmp(pszHifName, "tap", sizeof "tap" - 1)) { + if (!strncmp(pszBridgedIfName, "tap", sizeof "tap" - 1)) { hrc = attachToTapInterface(aNetworkAdapter); if (FAILED(hrc)) { @@ -3786,7 +4008,7 @@ int Console::configNetwork(const char *pszDevice, "permissions of that node, and that the net.link.tap.user_open " "sysctl is set. Either run 'chmod 0666 /dev/%s' or " "change the group of that node to vboxusers and make yourself " - "a member of that group. Make sure that these changes are permanent."), pszHifName, pszHifName); + "a member of that group. Make sure that these changes are permanent."), pszBridgedIfName, pszBridgedIfName); default: AssertMsgFailed(("Could not attach to tap interface! Bad!\n")); return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_( @@ -3805,7 +4027,7 @@ int Console::configNetwork(const char *pszDevice, } # endif /** @todo Check for malformed names. */ - const char *pszTrunk = pszHifName; + const char *pszTrunk = pszBridgedIfName; /* Issue a warning if the interface is down */ { @@ -3813,14 +4035,13 @@ int Console::configNetwork(const char *pszDevice, if (iSock >= 0) { struct ifreq Req; - - memset(&Req, 0, sizeof(Req)); - strncpy(Req.ifr_name, pszHifName, sizeof(Req.ifr_name) - 1); + RT_ZERO(Req); + strncpy(Req.ifr_name, pszBridgedIfName, sizeof(Req.ifr_name) - 1); if (ioctl(iSock, SIOCGIFFLAGS, &Req) >= 0) if ((Req.ifr_flags & IFF_UP) == 0) - { - setVMRuntimeErrorCallbackF(pVM, this, 0, "BridgedInterfaceDown", "Bridged interface %s is down. Guest will not be able to use this interface", pszHifName); - } + setVMRuntimeErrorCallbackF(pVM, this, 0, "BridgedInterfaceDown", + "Bridged interface %s is down. Guest will not be able to use this interface", + pszBridgedIfName); close(iSock); } @@ -3837,7 +4058,7 @@ int Console::configNetwork(const char *pszDevice, InsertConfigInteger(pCfg, "IgnoreConnectFailure", (uint64_t)fIgnoreConnectFailure); InsertConfigString(pCfg, "IfPolicyPromisc", pszPromiscuousGuestPolicy); char szNetwork[INTNET_MAX_NETWORK_NAME]; - RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszHifName); + RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszBridgedIfName); InsertConfigString(pCfg, "Network", szNetwork); networkName = Bstr(szNetwork); trunkName = Bstr(pszTrunk); @@ -3845,8 +4066,8 @@ int Console::configNetwork(const char *pszDevice, # if defined(RT_OS_DARWIN) /** @todo Come up with a better deal here. Problem is that IHostNetworkInterface is completely useless here. */ - if ( strstr(pszHifName, "Wireless") - || strstr(pszHifName, "AirPort" )) + if ( strstr(pszBridgedIfName, "Wireless") + || strstr(pszBridgedIfName, "AirPort" )) InsertConfigInteger(pCfg, "SharedMacOnWire", true); # elif defined(RT_OS_LINUX) int iSock = socket(AF_INET, SOCK_DGRAM, 0); @@ -3855,7 +4076,7 @@ int Console::configNetwork(const char *pszDevice, struct iwreq WRq; memset(&WRq, 0, sizeof(WRq)); - strncpy(WRq.ifr_name, pszHifName, IFNAMSIZ); + strncpy(WRq.ifr_name, pszBridgedIfName, IFNAMSIZ); bool fSharedMacOnWire = ioctl(iSock, SIOCGIWNAME, &WRq) >= 0; close(iSock); if (fSharedMacOnWire) @@ -3876,7 +4097,7 @@ int Console::configNetwork(const char *pszDevice, uint8_t abData[32]; memset(&WReq, 0, sizeof(WReq)); - strncpy(WReq.i_name, pszHifName, sizeof(WReq.i_name)); + strncpy(WReq.i_name, pszBridgedIfName, sizeof(WReq.i_name)); WReq.i_type = IEEE80211_IOC_SSID; WReq.i_val = -1; WReq.i_data = abData; @@ -4024,29 +4245,29 @@ int Console::configNetwork(const char *pszDevice, InsertConfigString(pLunL0, "Driver", "IntNet"); InsertConfigNode(pLunL0, "Config", &pCfg); - Bstr HifName; - hrc = aNetworkAdapter->COMGETTER(HostInterface)(HifName.asOutParam()); + Bstr HostOnlyName; + hrc = aNetworkAdapter->COMGETTER(HostOnlyInterface)(HostOnlyName.asOutParam()); if (FAILED(hrc)) { - LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(HostInterface) failed, hrc (0x%x)\n", hrc)); + LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(HostOnlyInterface) failed, hrc (0x%x)\n", hrc)); H(); } - Utf8Str HifNameUtf8(HifName); - const char *pszHifName = HifNameUtf8.c_str(); + Utf8Str HostOnlyNameUtf8(HostOnlyName); + const char *pszHostOnlyName = HostOnlyNameUtf8.c_str(); ComPtr<IHostNetworkInterface> hostInterface; - rc = host->FindHostNetworkInterfaceByName(HifName.raw(), + rc = host->FindHostNetworkInterfaceByName(HostOnlyName.raw(), hostInterface.asOutParam()); if (!SUCCEEDED(rc)) { LogRel(("NetworkAttachmentType_HostOnly: FindByName failed, rc (0x%x)\n", rc)); return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS, N_("Nonexistent host networking interface, name '%ls'"), - HifName.raw()); + HostOnlyName.raw()); } char szNetwork[INTNET_MAX_NETWORK_NAME]; - RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszHifName); + RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszHostOnlyName); #if defined(RT_OS_WINDOWS) # ifndef VBOX_WITH_NETFLT @@ -4067,7 +4288,7 @@ int Console::configNetwork(const char *pszDevice, if (eIfType != HostNetworkInterfaceType_HostOnly) return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS, N_("Interface ('%ls') is not a Host-Only Adapter interface"), - HifName.raw()); + HostOnlyName.raw()); hrc = hostInterface->COMGETTER(Id)(bstr.asOutParam()); if (FAILED(hrc)) @@ -4080,11 +4301,7 @@ int Console::configNetwork(const char *pszDevice, INetCfg *pNc; ComPtr<INetCfgComponent> pAdaptorComponent; LPWSTR pszApp; - - hrc = VBoxNetCfgWinQueryINetCfg(FALSE, - L"VirtualBox", - &pNc, - &pszApp); + hrc = VBoxNetCfgWinQueryINetCfg(&pNc, FALSE, L"VirtualBox", 10, &pszApp); Assert(hrc == S_OK); if (hrc != S_OK) { @@ -4162,18 +4379,18 @@ int Console::configNetwork(const char *pszDevice, trunkType = TRUNKTYPE_NETADP; # endif /* defined VBOX_WITH_NETFLT*/ #elif defined(RT_OS_DARWIN) - InsertConfigString(pCfg, "Trunk", pszHifName); + InsertConfigString(pCfg, "Trunk", pszHostOnlyName); InsertConfigString(pCfg, "Network", szNetwork); InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_NetAdp); networkName = Bstr(szNetwork); - trunkName = Bstr(pszHifName); + trunkName = Bstr(pszHostOnlyName); trunkType = TRUNKTYPE_NETADP; #else - InsertConfigString(pCfg, "Trunk", pszHifName); + InsertConfigString(pCfg, "Trunk", pszHostOnlyName); InsertConfigString(pCfg, "Network", szNetwork); InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_NetFlt); networkName = Bstr(szNetwork); - trunkName = Bstr(pszHifName); + trunkName = Bstr(pszHostOnlyName); trunkType = TRUNKTYPE_NETFLT; #endif InsertConfigString(pCfg, "IfPolicyPromisc", pszPromiscuousGuestPolicy); @@ -4183,12 +4400,12 @@ int Console::configNetwork(const char *pszDevice, Bstr tmpAddr, tmpMask; hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPAddress", - pszHifName).raw(), + pszHostOnlyName).raw(), tmpAddr.asOutParam()); if (SUCCEEDED(hrc) && !tmpAddr.isEmpty()) { hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPNetMask", - pszHifName).raw(), + pszHostOnlyName).raw(), tmpMask.asOutParam()); if (SUCCEEDED(hrc) && !tmpMask.isEmpty()) hrc = hostInterface->EnableStaticIpConfig(tmpAddr.raw(), @@ -4200,17 +4417,17 @@ int Console::configNetwork(const char *pszDevice, else { /* Grab the IP number from the 'vboxnetX' instance number (see netif.h) */ - hrc = hostInterface->EnableStaticIpConfig(getDefaultIPv4Address(Bstr(pszHifName)).raw(), + hrc = hostInterface->EnableStaticIpConfig(getDefaultIPv4Address(Bstr(pszHostOnlyName)).raw(), Bstr(VBOXNET_IPV4MASK_DEFAULT).raw()); } ComAssertComRC(hrc); /** @todo r=bird: Why this isn't fatal? (H()) */ hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6Address", - pszHifName).raw(), + pszHostOnlyName).raw(), tmpAddr.asOutParam()); if (SUCCEEDED(hrc)) - hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6NetMask", pszHifName).raw(), + hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6NetMask", pszHostOnlyName).raw(), tmpMask.asOutParam()); if (SUCCEEDED(hrc) && !tmpAddr.isEmpty() && !tmpMask.isEmpty()) { @@ -4222,21 +4439,32 @@ int Console::configNetwork(const char *pszDevice, break; } -#if defined(VBOX_WITH_VDE) - case NetworkAttachmentType_VDE: + case NetworkAttachmentType_Generic: { - hrc = aNetworkAdapter->COMGETTER(VDENetwork)(bstr.asOutParam()); H(); - InsertConfigNode(pInst, "LUN#0", &pLunL0); - InsertConfigString(pLunL0, "Driver", "VDE"); + hrc = aNetworkAdapter->COMGETTER(GenericDriver)(bstr.asOutParam()); H(); + SafeArray<BSTR> names; + SafeArray<BSTR> values; + hrc = aNetworkAdapter->GetProperties(Bstr().raw(), + ComSafeArrayAsOutParam(names), + ComSafeArrayAsOutParam(values)); H(); + + if (fSniffer) + InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0); + else + InsertConfigNode(pInst, "LUN#0", &pLunL0); + InsertConfigString(pLunL0, "Driver", bstr); InsertConfigNode(pLunL0, "Config", &pCfg); - if (!bstr.isEmpty()) + for (size_t ii = 0; ii < names.size(); ++ii) { - InsertConfigString(pCfg, "Network", bstr); - networkName = bstr; + if (values[ii] && *values[ii]) + { + Utf8Str name = names[ii]; + Utf8Str value = values[ii]; + InsertConfigString(pCfg, name.c_str(), value); + } } break; } -#endif default: AssertMsgFailed(("should not get here!\n")); @@ -4255,9 +4483,7 @@ int Console::configNetwork(const char *pszDevice, case NetworkAttachmentType_Internal: case NetworkAttachmentType_HostOnly: case NetworkAttachmentType_NAT: -#if defined(VBOX_WITH_VDE) - case NetworkAttachmentType_VDE: -#endif + case NetworkAttachmentType_Generic: { if (SUCCEEDED(hrc) && SUCCEEDED(rc)) { @@ -4580,7 +4806,7 @@ int configSetGlobalPropertyFlags(VMMDev * const pVMMDev, { HGCMSVCEXTHANDLE hDummy; rc = HGCMHostRegisterServiceExtension(&hDummy, "VBoxGuestControlSvc", - &Guest::doGuestCtrlNotification, + &Guest::notifyCtrlDispatcher, pConsole->getGuest()); if (RT_FAILURE(rc)) Log(("Cannot register VBoxGuestControlSvc extension!\n")); |