ConsoleImpl2.cpp revision 5f80794f0fac6c6ae43bf4d2baaef60babb2a7c7
/* $Id$ */
/** @file
* VBox Console COM Class implementation - VM Configuration Bits.
*
* @remark We've split out the code that the 64-bit VC++ v8 compiler finds
* problematic to optimize so we can disable optimizations and later,
* perhaps, find a real solution for it (like rewriting the code and
* to stop resemble a tonne of spaghetti).
*/
/*
* Copyright (C) 2006-2014 Oracle Corporation
*
* 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.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
// for some reason Windows burns in sdk\...\winsock.h if this isn't included first
#include "ConsoleImpl.h"
#include "DisplayImpl.h"
#ifdef VBOX_WITH_GUEST_CONTROL
# include "GuestImpl.h"
#endif
#ifdef VBOX_WITH_DRAG_AND_DROP
# include "GuestDnDImpl.h"
#endif
#include "VMMDev.h"
#include "Global.h"
#ifdef VBOX_WITH_PCI_PASSTHROUGH
# include "PCIRawDevImpl.h"
#endif
// generated header
#include "SchemaDefs.h"
#include "AutoCaller.h"
#include "Logging.h"
#include <iprt/buildconfig.h>
#if 0 /* enable to play with lots of memory. */
#endif
#ifdef VBOX_WITH_CROGL
#include <VBox/VBoxOGLTest.h>
#endif
#ifdef VBOX_WITH_GUEST_PROPS
# include "HGCM.h" /** @todo it should be possible to register a service
* extension using a VMMDev callback. */
# include <vector>
#endif /* VBOX_WITH_GUEST_PROPS */
#ifdef VBOX_WITH_NETFLT
# if defined(RT_OS_SOLARIS)
# include <zone.h>
# elif defined(RT_OS_LINUX)
# include <unistd.h>
# include <linux/wireless.h>
# elif defined(RT_OS_FREEBSD)
# include <unistd.h>
# include <net80211/ieee80211_ioctl.h>
# endif
# if defined(RT_OS_WINDOWS)
# include <VBox/VBoxNetCfg-win.h>
# include <Ntddndis.h>
# include <devguid.h>
# else
# include <HostNetworkInterfaceImpl.h>
# include <netif.h>
# include <stdlib.h>
# endif
#endif /* VBOX_WITH_NETFLT */
#include "NetworkServiceRunner.h"
#include "BusAssignmentManager.h"
#ifdef VBOX_WITH_EXTPACK
# include "ExtPackManagerImpl.h"
#endif
#if defined(RT_OS_DARWIN)
# include "IOKit/IOKitLib.h"
#endif
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
static Utf8Str *GetExtraDataBoth(IVirtualBox *pVirtualBox, IMachine *pMachine, const char *pszName, Utf8Str *pStrValue);
#if defined(RT_OS_DARWIN)
{
/*
* Method as described in Amit Singh's article:
*/
typedef struct
{
IOServiceMatching("AppleSMC"));
if (!service)
return VERR_NOT_FOUND;
if (kr != kIOReturnSuccess)
return RTErrConvertFromDarwin(kr);
for (int i = 0; i < 2; i++)
{
(uint32_t)2,
(const void *)&inputStruct,
sizeof(inputStruct),
(void *)&outputStruct,
if (kr != kIOReturnSuccess)
{
return RTErrConvertFromDarwin(kr);
}
for (int j = 0; j < 32; j++)
}
pabKey[64] = 0;
return VINF_SUCCESS;
}
#endif /* RT_OS_DARWIN */
/* Darwin compile kludge */
/* Comment out the following line to remove VMWare compatibility hack. */
#define VMWARE_NET_IN_SLOT_11
/**
* Translate IDE StorageControllerType_T to string representation.
*/
{
switch (enmType)
{
return "PIIX3";
return "PIIX4";
return "ICH6";
default:
return "Unknown";
}
}
/**
* Simple class for storing network boot information.
*/
struct BootNic
{
{
}
};
{
if (!fPresent)
{
LogRel(("Failed to find an EFI ROM file.\n"));
return VERR_FILE_NOT_FOUND;
}
return VINF_SUCCESS;
}
/**
* @throws HRESULT on extra data retrival error.
*/
static int getSmcDeviceKey(IVirtualBox *pVirtualBox, IMachine *pMachine, Utf8Str *pStrKey, bool *pfGetKeyFromRealSMC)
{
*pfGetKeyFromRealSMC = false;
/*
* The extra data takes precedence (if non-zero).
*/
if (pStrKey->isNotEmpty())
return VINF_SUCCESS;
#ifdef RT_OS_DARWIN
/*
* Query it here and now.
*/
char abKeyBuf[65];
{
*pfGetKeyFromRealSMC = true;
return rc;
}
#else
/*
* Is it apple hardware in bootcamp?
*/
/** @todo implement + test RTSYSDMISTR_MANUFACTURER on all hosts.
* Currently falling back on the product name. */
char szManufacturer[256];
szManufacturer[0] = '\0';
if (szManufacturer[0] != '\0')
{
)
*pfGetKeyFromRealSMC = true;
}
else
{
char szProdName[256];
szProdName[0] = '\0';
)
)
*pfGetKeyFromRealSMC = true;
}
int rc = VINF_SUCCESS;
#endif
return rc;
}
/*
* VC++ 8 / amd64 has some serious trouble with the next functions.
* As a temporary measure, we'll drop global optimizations.
*/
#if defined(_MSC_VER) && defined(RT_ARCH_AMD64)
#endif
static const char *const g_apszIDEDrives[4] =
{ "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" };
class ConfigError : public RTCError
{
public:
ConfigError(const char *pcszFunction,
int vrc,
const char *pcszName)
{
}
int m_vrc;
};
/**
* Helper that calls CFGMR3InsertString and throws an RTCError if that
* fails (C-string variant).
* @param pParent See CFGMR3InsertStringN.
* @param pcszNodeName See CFGMR3InsertStringN.
* @param pcszValue The string value.
*/
const char *pcszName,
const char *pcszValue)
{
if (RT_FAILURE(vrc))
}
/**
* Helper that calls CFGMR3InsertString and throws an RTCError if that
* fails (Utf8Str variant).
* @param pParent See CFGMR3InsertStringN.
* @param pcszNodeName See CFGMR3InsertStringN.
* @param rStrValue The string value.
*/
const char *pcszName,
{
if (RT_FAILURE(vrc))
}
/**
* Helper that calls CFGMR3InsertString and throws an RTCError if that
* fails (Bstr variant).
*
* @param pParent See CFGMR3InsertStringN.
* @param pcszNodeName See CFGMR3InsertStringN.
* @param rBstrValue The string value.
*/
const char *pcszName,
const Bstr &rBstrValue)
{
}
/**
* Helper that calls CFGMR3InsertBytes and throws an RTCError if that fails.
*
* @param pNode See CFGMR3InsertBytes.
* @param pcszName See CFGMR3InsertBytes.
* @param pvBytes See CFGMR3InsertBytes.
* @param cbBytes See CFGMR3InsertBytes.
*/
const char *pcszName,
const void *pvBytes,
{
cbBytes);
if (RT_FAILURE(vrc))
}
/**
* Helper that calls CFGMR3InsertInteger and throws an RTCError if that
* fails.
*
* @param pNode See CFGMR3InsertInteger.
* @param pcszName See CFGMR3InsertInteger.
* @param u64Integer See CFGMR3InsertInteger.
*/
const char *pcszName,
{
if (RT_FAILURE(vrc))
}
/**
* Helper that calls CFGMR3InsertNode and throws an RTCError if that fails.
*
* @param pNode See CFGMR3InsertNode.
* @param pcszName See CFGMR3InsertNode.
* @param ppChild See CFGMR3InsertNode.
*/
const char *pcszName,
{
if (RT_FAILURE(vrc))
}
/**
* Helper that calls CFGMR3RemoveValue and throws an RTCError if that fails.
*
* @param pNode See CFGMR3RemoveValue.
* @param pcszName See CFGMR3RemoveValue.
*/
const char *pcszName)
{
if (RT_FAILURE(vrc))
}
/**
* Gets an extra data value, consulting both machine and global extra data.
*
* @throws HRESULT on failure
* @returns pStrValue for the callers convenience.
* @param pVirtualBox Pointer to the IVirtualBox interface.
* @param pMachine Pointer to the IMachine interface.
* @param pszName The value to get.
* @param pStrValue Where to return it's value (empty string if not
* found).
*/
static Utf8Str *GetExtraDataBoth(IVirtualBox *pVirtualBox, IMachine *pMachine, const char *pszName, Utf8Str *pStrValue)
{
throw hrc;
{
throw hrc;
}
if (bstrValue.isNotEmpty())
return pStrValue;
}
/** Helper that finds out the next HBA port used
*/
{
{
&& aPortUsed[j] <= lNextPortUsed)
lNextPortUsed = aPortUsed[j];
}
return lNextPortUsed;
}
#define MAX_BIOS_LUN_COUNT 4
{
#define MAX_DEVICES 30
uint32_t u32HDCount = 0;
/* init to max value */
lPortLUN[0] = MAX_DEVICES;
ComSafeArrayAsOutParam(atts)); H();
if (uNumAttachments > MAX_DEVICES)
{
}
for (size_t j = 0; j < uNumAttachments; ++j)
{
{
{
/* find min port number used for HD */
}
/* Configure the hotpluggable flag for the port. */
{
char szName[24];
}
}
}
/* Pick only the top 4 used HD Ports as CMOS doesn't have space
* to save details for all 30 ports
*/
if (u32HDCount < MAX_BIOS_LUN_COUNT)
lPortLUN[j-1],
if (pBiosCfg)
{
for (size_t j = 0; j < u32MaxPortCount; j++)
{
}
}
return VINF_SUCCESS;
}
#ifdef VBOX_WITH_PCI_PASSTHROUGH
{
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";
/* Always fatal! */
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"),
# endif
/* Find required bridges, and add missing ones */
{
if (GuestPCIAddress.miBus > 0)
{
int iBridgesMissed = 0;
{
iBridgesMissed++; iBase--;
}
iBase++;
{
}
}
}
/* Now actually add devices */
if (assignments.size() > 0)
{
/* Tell PGM to tell GPCIRaw about guest mappings. */
/*
* Currently, using IOMMU needed for PCI passthrough
* requires RAM preallocation.
*/
/** @todo: check if we can lift this requirement */
}
{
return hrc;
/* the driver */
/* the Main driver */
}
return hrc;
}
#endif
const char *pcszDevice, unsigned uInstance)
{
{
}
}
/**
* Construct the VM configuration tree (CFGM).
*
* This is a callback for VMR3Create() call. It is called from CFGMR3Init()
* is done here.
*
* @param pUVM The user mode VM handle.
* @param pVM The cross context VM handle.
* @param pvConsole Pointer to the VMPowerUpTask object.
* @return VBox status code.
*
* @note Locks the Console object for writing.
*/
{
/* lock the console because we widely use internal fields and methods */
/*
* 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.
*/
int vrc;
try
{
}
catch (...)
{
}
if (RT_FAILURE(vrc))
{
}
return vrc;
}
/**
* Worker for configConstructor.
*
* @return VBox status code.
* @param pUVM The user mode VM handle.
* @param pVM The cross context 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 rc;
/*
* Get necessary objects and frequently used parameters.
*/
#if 0 /* enable to play with lots of memory. */
if (RTEnvExist("VBOX_RAM_SIZE"))
#endif
uint32_t cbMcfgLength = 0;
if (chipsetType == ChipsetType_ICH9)
{
/* We'd better have 0x10000000 region, to cover 256 buses
but this put too much load on hypervisor heap */
}
/*
* Get root node first.
* This is the only node in the tree.
*/
// InsertConfigString throws
try
{
/*
* Set the root (and VMM) level values.
*/
#ifdef VBOX_WITH_RAW_MODE
/** @todo Config: RawR0, PATMEnabled and CSAMEnabled needs attention later. */
#endif
#ifdef VBOX_WITH_RAW_RING1
if (osTypeId == "QNX")
{
/* QNX needs special treatment in raw mode due to its use of ring-1. */
}
#endif
/* Not necessary, but to make sure these two settings end up in the release log. */
ULONG ulBalloonSize = 0;
/*
* CPUM values.
*/
/* cpuid leaf overrides. */
static uint32_t const s_auCpuIdRanges[] =
{
};
{
{
}
else if (hrc != E_INVALIDARG) H();
}
/* We must limit CPUID count for Windows NT 4, as otherwise it stops
with error 0x3e (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED). */
if (osTypeId == "WindowsNT4")
{
LogRel(("Limiting CPUID leaf count for NT4 guests\n"));
}
/* Expose CMPXCHG16B. Currently a hack. */
if ( osTypeId == "Windows81_64"
|| osTypeId == "Windows2012_64")
{
LogRel(("Enabling CMPXCHG16B for Windows 8.1 / 2k12 guests\n"));
}
/* Expose extended MWAIT features to Mac OS X guests. */
if (fOsXGuest)
{
LogRel(("Using MWAIT extensions\n"));
}
if (fOsXGuest)
{
because older mac releases really doesn't work on newer cpus,
and partly because mac os x expects more from systems with newer
cpus (MSRs, power features, whatever). */
if ( osTypeId == "MacOS"
|| osTypeId == "MacOS_64")
else if ( osTypeId == "MacOS106"
|| osTypeId == "MacOS106_64")
else if ( osTypeId == "MacOS107"
|| osTypeId == "MacOS107_64")
uMaxIntelFamilyModelStep = RT_MAKE_U32_FROM_U8(1, 23, 6, 7); /* Penryn / X5482 */ /** @todo figure out what is required here. */
else if ( osTypeId == "MacOS108"
|| osTypeId == "MacOS108_64")
uMaxIntelFamilyModelStep = RT_MAKE_U32_FROM_U8(1, 23, 6, 7); /* Penryn / X5482 */ /** @todo figure out what is required here. */
else if ( osTypeId == "MacOS109"
|| osTypeId == "MacOS109_64")
uMaxIntelFamilyModelStep = RT_MAKE_U32_FROM_U8(1, 23, 6, 7); /* Penryn / X5482 */ /** @todo figure out what is required here. */
if (uMaxIntelFamilyModelStep != UINT32_MAX)
}
/* Synthetic CPU */
BOOL fSyntheticCpu = false;
/* Physical Address Extension (PAE) */
BOOL fEnablePAE = false;
/*
* Hardware virtualization extensions.
*/
if (fIsGuest64Bit)
{
if (!fSupportsLongMode)
{
LogRel(("WARNING! 64-bit guest type selected but the host CPU does NOT support 64-bit.\n"));
}
if (!fSupportsHwVirtEx)
{
LogRel(("WARNING! 64-bit guest type selected but the host CPU does NOT support HW virtualization.\n"));
}
}
{
LogRel(("Forced fHMEnabled to TRUE by SMP guest.\n"));
fHMEnabled = TRUE;
}
#ifdef VBOX_WITH_RAW_MODE
/* - With more than 4GB PGM will use different RAMRANGE sizes for raw
mode and hv mode to optimize lookup times.
- With more than one virtual CPU, raw-mode isn't a fallback option.
- With a 64-bit guest, raw-mode isn't a fallback option either. */
|| cCpus > 1
|| fIsGuest64Bit);
# ifdef RT_OS_DARWIN
# endif
if (fHMForced)
{
LogRel(("fHMForced=true - Lots of RAM\n"));
if (cCpus > 1)
LogRel(("fHMForced=true - SMP\n"));
if (fIsGuest64Bit)
LogRel(("fHMForced=true - 64-bit guest\n"));
# ifdef RT_OS_DARWIN
LogRel(("fHMForced=true - Darwin host\n"));
# endif
}
#else /* !VBOX_WITH_RAW_MODE */
LogRel(("fHMForced=true - No raw-mode support in this build!\n"));
#endif /* !VBOX_WITH_RAW_MODE */
if (!fHMForced) /* No need to query if already forced above. */
{
if (fHMForced)
LogRel(("fHMForced=true - HWVirtExPropertyType_Force\n"));
}
/* Triple fault behavior. */
BOOL fTripleFaultReset = false;
if (fHMEnabled)
{
/* Indicate whether 64-bit guests are supported or not. */
#endif
/** @todo Not exactly pretty to check strings; VBOXOSTYPE would be better, but that requires quite a bit of API change in Main. */
if ( fIOAPIC
&& ( osTypeId == "WindowsNT4"
|| osTypeId == "Windows2000"
|| osTypeId == "WindowsXP"
|| osTypeId == "Windows2003"))
{
/* Only allow TPR patching for NT, Win2k, XP and Windows Server 2003. (32 bits mode)
* We may want to consider adding more guest OSes (Solaris) later on.
*/
}
}
/* HWVirtEx exclusive mode */
BOOL fHMExclusive = true;
BOOL fEnableNestedPaging = false;
/* Large pages; requires nested paging */
BOOL fEnableLargePages = false;
/* VPID (VT-x) */
BOOL fEnableVPID = false;
/* Unrestricted execution aka UX (VT-x) */
/* Reset overwrite. */
if (isResetTurnedIntoPowerOff())
/*
* MM values.
*/
/*
* PDM config.
* Load drivers in VBoxC.[so|dll]
*/
#ifdef VBOX_WITH_XPCOM
// VBoxC is located in the components subdirectory
char szPathVBoxC[RTPATH_MAX];
#else
#endif
/*
* Block cache settings.
*/
/* I/O cache size */
/*
* Bandwidth groups.
*/
#ifdef VBOX_WITH_NETSHAPER
#endif /* VBOX_WITH_NETSHAPER */
{
N_("No bandwidth group name specified"));
if (enmType == BandwidthGroupType_Disk)
{
}
#ifdef VBOX_WITH_NETSHAPER
else if (enmType == BandwidthGroupType_Network)
{
/* Network bandwidth groups. */
}
#endif /* VBOX_WITH_NETSHAPER */
}
/*
* Devices
*/
/*
* PC Arch.
*/
/*
* The time offset
*/
/*
* DMA
*/
/*
* PCI buses.
*/
switch (chipsetType)
{
default:
Assert(false);
case ChipsetType_PIIX3:
break;
case ChipsetType_ICH9:
break;
}
if (chipsetType == ChipsetType_ICH9)
{
/* Provide MCFG info */
/* And register 2 bridges */
#ifdef VBOX_WITH_PCI_PASSTHROUGH
/* Add PCI passthrough devices */
#endif
}
/*
* Enable the following devices: HPET, SMC and LPC on MacOS X guests or on ICH9 chipset
*/
/*
* High Precision Event Timer (HPET)
*/
/* Other guests may wish to use HPET too, but MacOS X not functional without it */
/* so always enable HPET in extended profile */
/* HPET is always present on ICH9 */
if (fHPETEnabled)
{
}
/*
* System Management Controller (SMC)
*/
if (fSmcEnabled)
{
bool fGetKeyFromRealSMC;
}
/*
* Low Pin Count (LPC) bus
*/
/** @todo: implement appropriate getter */
if (fLpcEnabled)
{
}
/*
* PS/2 keyboard & mouse.
*/
/*
* i8254 Programmable Interval Timer And Dummy Speaker
*/
#ifdef DEBUG
#endif
/*
* i8259 Programmable Interrupt Controller.
*/
/*
* Advanced Programmable Interrupt Controller.
* SMP: Each CPU has a LAPIC, but we have a single device representing all LAPICs states,
* thus only single insert
*/
if (fIOAPIC)
{
/*
* I/O Advanced Programmable Interrupt Controller.
*/
}
/*
* RTC MC146818.
*/
/*
* VGA.
*/
switch (graphicsController)
{
break;
#ifdef VBOX_WITH_VMSVGA
#endif
return rc;
break;
default:
}
/*
* Firmware.
*/
#ifdef VBOX_WITH_EFI
#else
BOOL fEfiEnabled = false;
#endif
if (!fEfiEnabled)
{
/*
* PC Bios.
*/
AssertMsgReturn(SchemaDefs::MaxBootPosition <= 9, ("Too many boot devices %d\n", SchemaDefs::MaxBootPosition),
{
char szParamName[] = "BootDeviceX";
const char *pszBootDevice;
switch (bootDevice)
{
case DeviceType_Null:
pszBootDevice = "NONE";
break;
case DeviceType_HardDisk:
pszBootDevice = "IDE";
break;
case DeviceType_DVD:
pszBootDevice = "DVD";
break;
case DeviceType_Floppy:
pszBootDevice = "FLOPPY";
break;
case DeviceType_Network:
pszBootDevice = "LAN";
break;
default:
}
}
/** @todo @bugref{7145}: We might want to enable this by default for new VMs. For now,
* this is required for Windows 2012 guests. */
if (osTypeId == "Windows2012_64")
}
else
{
/* Autodetect firmware type, basing on guest type */
if (eFwType == FirmwareType_EFI)
{
}
/* Get boot args */
/* Get device props */
/* Get GOP mode settings */
/* UGA mode settings */
uint32_t u32UgaHorisontal = 0;
uint32_t u32UgaVertical = 0;
/*
* EFI subtree.
*/
/* For OS X guests we'll force passing host's DMI info to the guest */
if (fOsXGuest)
{
}
#ifdef DEBUG_vvl
#endif
}
/*
* The USB Controllers.
*/
bool fOhciPresent = false; /**< Flag whether at least one OHCI controller is present. */
{
if (enmCtrlType == USBControllerType_OHCI)
{
fOhciPresent = true;
break;
}
}
/*
* Currently EHCI is only enabled when a OHCI controller is present too.
* This might change when XHCI is supported.
*/
if (fOhciPresent)
mfVMHasUsbController = true;
if (mfVMHasUsbController)
{
{
if (enmCtrlType == USBControllerType_OHCI)
{
/*
* Attach the status driver.
*/
}
#ifdef VBOX_WITH_EHCI
else if (enmCtrlType == USBControllerType_EHCI)
{
/*
* USB 2.0 is only available if the proper ExtPack is installed.
*
* Note. Configuring EHCI 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.
*/
static const char *s_pszUsbExtPackName = "Oracle VM VirtualBox Extension Pack";
# ifdef VBOX_WITH_EXTPACK
# endif
{
/*
* Attach the status driver.
*/
}
# ifdef VBOX_WITH_EXTPACK
else
{
/* Always fatal! Up to VBox 4.0.4 we allowed to start the VM anyway
* but this induced problems when the user saved + restored the VM! */
N_("Implementation of the USB 2.0 controller not found!\n"
"Because the USB 2.0 controller state is part of the saved "
"VM state, the VM cannot be started. To fix "
"this problem, either install the '%s' or disable USB 2.0 "
"support in the VM settings"),
}
# endif
}
#endif
} /* for every USB controller. */
/*
* Virtual USB Devices.
*/
#ifdef VBOX_WITH_USB
{
/*
* Global USB options, currently unused as we'll apply the 2.0 -> 1.1 morphing
* on a per device level now.
*/
// This globally enables the 2.0 -> 1.1 device morphing of proxied devices to keep windows quiet.
//InsertConfigInteger(pCfg, "Force11Device", true);
// The following breaks stuff, but it makes MSDs work in vista. (I include it here so
// that it's documented somewhere.) Users needing it can use:
// VBoxManage setextradata "myvm" "VBoxInternal/USB/USBProxy/GlobalConfig/Force11PacketSize" 1
//InsertConfigInteger(pCfg, "Force11PacketSize", true);
}
#endif
#ifdef VBOX_WITH_USB_CARDREADER
{
# ifdef VBOX_WITH_USB_CARDREADER_TEST
# else
# endif
}
#endif
if ( aPointingHID == PointingHIDType_USBMouse
{
if (aPointingHID == PointingHIDType_USBMouse)
else
}
{
}
/* Virtual USB Keyboard */
if (aKbdHID == KeyboardHIDType_USBKeyboard)
{
}
}
/*
* Storage controllers.
*/
bool fFdcEnabled = false;
{
|| enmCtrlType == StorageControllerType_USB);
if (enmCtrlType != StorageControllerType_USB)
{
/* /Devices/<ctrldev>/ */
if (!pDev)
{
}
/* /Devices/<ctrldev>/<instance>/ */
}
static const char * const apszBiosConfigScsi[MAX_BIOS_LUN_COUNT] =
{ "ScsiLUN1", "ScsiLUN2", "ScsiLUN3", "ScsiLUN4" };
static const char * const apszBiosConfigSata[MAX_BIOS_LUN_COUNT] =
{ "SataLUN1", "SataLUN2", "SataLUN3", "SataLUN4" };
switch (enmCtrlType)
{
{
/* BIOS configuration values, first SCSI controller only. */
&& pBiosCfg)
{
}
/* Attach the status driver */
break;
}
{
/* BIOS configuration values, first SCSI controller only. */
&& pBiosCfg)
{
}
/* Attach the status driver */
break;
}
{
/* BIOS configuration values, first AHCI controller only. */
&& pBiosCfg)
{
}
/* Attach the status driver */
break;
}
{
/*
* IDE (update this when the main interface changes)
*/
/* Attach the status driver */
/* IDE flavors */
break;
}
{
/*
* i82078 Floppy drive controller
*/
fFdcEnabled = true;
/* Attach the status driver */
break;
}
{
/* BIOS configuration values, first SCSI controller only. */
&& pBiosCfg)
{
}
/* Attach the status driver */
break;
}
{
if (pUsbDevices)
{
/*
* USB MSDs are handled a bit different as the device instance
* doesn't match the storage controller instance but the port.
*/
}
else
N_("There is no USB controller enabled but there\n"
"is at least one USB storage device configured for this VM.\n"
"To fix this problem either enable the USB controller or remove\n"
"the storage device from the VM"));
break;
}
default:
AssertMsgFailedReturn(("invalid storage controller type: %d\n", enmCtrlType), VERR_GENERAL_FAILURE);
}
/* Attach the media to the storage controllers. */
ComSafeArrayAsOutParam(atts)); H();
/* Builtin I/O cache - per device setting. */
BOOL fBuiltinIOCache = true;
{
false /* fSetupMerge */,
0 /* uMergeSource */,
0 /* uMergeTarget */,
NULL /* phrc */,
false /* fAttachDetach */,
false /* fForceUnmount */,
false /* fHotplug */,
pUVM,
if (RT_FAILURE(rc))
return rc;
}
H();
}
H();
/*
* Network adapters
*/
#ifdef VMWARE_NET_IN_SLOT_11
bool fSwapSlots3and11 = false;
#endif
#ifdef VBOX_WITH_E1000
#endif
#ifdef VBOX_WITH_VIRTIO
#endif /* VBOX_WITH_VIRTIO */
{
if (!fEnabledNetAdapter)
continue;
/*
* The virtual hardware type. Create appropriate device first.
*/
const char *pszAdapterName = "pcnet";
switch (adapterType)
{
break;
#ifdef VBOX_WITH_E1000
pszAdapterName = "e1000";
break;
#endif
#ifdef VBOX_WITH_VIRTIO
pszAdapterName = "virtio-net";
break;
#endif /* VBOX_WITH_VIRTIO */
default:
AssertMsgFailed(("Invalid network adapter type '%d' for slot '%d'",
N_("Invalid network adapter type '%d' for slot '%d'"),
}
/* the first network card gets the PCI ID 3, the next 3 gets 8..10,
* next 4 get 16..19. */
int iPCIDeviceNo;
switch (ulInstance)
{
case 0:
iPCIDeviceNo = 3;
break;
case 1: case 2: case 3:
break;
case 4: case 5: case 6: case 7:
break;
default:
/* auto assignment */
iPCIDeviceNo = -1;
break;
}
#ifdef VMWARE_NET_IN_SLOT_11
/*
* Dirty hack for PCI slot compatibility with VMWare,
* it assigns slot 0x11 to the first network controller.
*/
{
iPCIDeviceNo = 0x11;
fSwapSlots3and11 = true;
}
iPCIDeviceNo = 3;
#endif
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE /* not safe here yet. */ /** @todo Make PCNet ring-0 safe on 32-bit mac kernels! */
{
}
#endif
/*
* Collect information needed for network booting and add it to the list.
*/
/* Could be updated by reference, if auto assigned */
/*
* The virtual hardware type. PCNet supports two types.
*/
switch (adapterType)
{
break;
break;
break;
break;
break;
}
/*
* Get the MAC address and convert it to binary representation
*/
for (uint32_t i = 0; i < 6; ++i)
{
if (c1 > 9)
c1 -= 7;
if (c2 > 9)
c2 -= 7;
}
/*
* Check if the cable is supposed to be unplugged
*/
/*
* Line speed to report from custom drivers
*/
/*
* Attach the status driver.
*/
/*
* Configure the network card now
*/
0,
pCfg,
false /*fAttachDetach*/,
if (RT_FAILURE(rc))
return rc;
}
/*
* Build network boot information and transfer it to the BIOS.
*/
{
char achBootIdx[] = "0";
unsigned uBootIdx = 0;
{
/* A NIC with priority 0 is only used if it's first in the list. */
break;
}
}
/*
* Serial (UART) Ports
*/
/* serial enabled mask to be passed to dev ACPI */
{
if (serialPort)
if (!fEnabledSerPort)
continue;
if (eHostMode != PortMode_Disconnected)
{
if (eHostMode == PortMode_HostPipe)
{
}
else if (eHostMode == PortMode_HostDevice)
{
}
else if (eHostMode == PortMode_RawFile)
{
}
}
}
/*
* Parallel (LPT) Ports
*/
{
if (parallelPort)
{
}
if (!fEnabledParPort)
continue;
}
/*
* VMM Device
*/
/* the VMM device's Main driver */
/*
* Attach the status driver.
*/
#ifndef VBOX_WITH_PDM_AUDIO_DRIVER
/*
* Audio Sniffer Device
*/
/* the Audio Sniffer device's Main driver */
#endif
/*
* AC'97 ICH / SoundBlaster16 audio / Intel HD Audio
*/
if (audioAdapter)
if (fAudioEnabled)
{
switch (audioController)
{
case AudioControllerType_AC97:
{
/* default: ICH AC97 */
break;
}
case AudioControllerType_SB16:
{
/* legacy SoundBlaster16 */
break;
}
case AudioControllerType_HDA:
{
/* Intel HD Audio */
}
}
/* the Audio driver */
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#endif
switch (audioDriver)
{
case AudioDriverType_Null:
{
break;
}
#ifdef RT_OS_WINDOWS
#ifdef VBOX_WITH_WINMM
case AudioDriverType_WinMM:
{
break;
}
#endif
{
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
break;
}
#endif /* RT_OS_WINDOWS */
#ifdef RT_OS_SOLARIS
case AudioDriverType_SolAudio:
{
break;
}
#endif
#ifdef RT_OS_LINUX
# ifdef VBOX_WITH_ALSA
case AudioDriverType_ALSA:
{
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
break;
}
# endif
# ifdef VBOX_WITH_PULSE
case AudioDriverType_Pulse:
{
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
break;
}
# endif
#endif /* RT_OS_LINUX */
case AudioDriverType_OSS:
{
break;
}
#endif
#ifdef RT_OS_FREEBSD
# ifdef VBOX_WITH_PULSE
case AudioDriverType_Pulse:
{
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
#else
#endif
break;
}
# endif
#endif
#ifdef RT_OS_DARWIN
{
break;
}
#endif
}
#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
/* the Audio driver */
#endif
}
/*
* Clipboard
*/
{
if (/* mode != ClipboardMode_Disabled */ true)
{
/* Load the service */
if (RT_FAILURE(rc))
{
/* That is not a fatal failure. */
rc = VINF_SUCCESS;
}
else
{
/* Setup the service. */
Log(("Set VBoxSharedClipboard mode\n"));
}
}
}
/*
* HGCM HostChannel
*/
{
value.asOutParam());
&& value == "1")
{
if (RT_FAILURE(rc))
{
/* That is not a fatal failure. */
rc = VINF_SUCCESS;
}
}
}
#ifdef VBOX_WITH_DRAG_AND_DROP
/*
* Drag & Drop
*/
{
/* Load the service */
if (RT_FAILURE(rc))
{
/* That is not a fatal failure. */
rc = VINF_SUCCESS;
}
else
{
getGuest());
if (RT_FAILURE(rc))
Log(("Cannot register VBoxDragAndDropSvc extension!\n"));
else
{
Log(("VBoxDragAndDropSvc loaded\n"));
}
}
}
#endif /* VBOX_WITH_DRAG_AND_DROP */
#ifdef VBOX_WITH_CROGL
/*
* crOpenGL
*/
{
BOOL fEnabled3D = false;
if (fEnabled3D)
{
if (!fSupports3D)
N_("This VM was configured to use 3D acceleration. However, the "
"3D support of the host is not working properly and the "
"VM cannot be started. To fix this problem, either "
"fix the host 3D support (update the host graphics driver?) "
"or disable 3D acceleration in the VM settings"));
/* Load the service */
if (RT_FAILURE(rc))
{
/* That is not a fatal failure. */
rc = VINF_SUCCESS;
}
else
{
LogRel(("Shared crOpenGL service loaded.\n"));
/* Setup the service. */
rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_CONSOLE, SHCRGL_CPARMS_SET_CONSOLE, &parm);
if (!RT_SUCCESS(rc))
rc = pVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_VM, SHCRGL_CPARMS_SET_VM, &parm);
if (!RT_SUCCESS(rc))
}
}
}
#endif
#ifdef VBOX_WITH_GUEST_PROPS
/*
* Guest property service
*/
#endif /* VBOX_WITH_GUEST_PROPS defined */
#ifdef VBOX_WITH_GUEST_CONTROL
/*
* Guest control service
*/
rc = configGuestControl(this);
#endif /* VBOX_WITH_GUEST_CONTROL defined */
/*
* ACPI
*/
if (fACPI)
{
/* Always show the CPU leafs when we have multiple VCPUs or when the IO-APIC is enabled.
* The Windows SMP kernel needs a CPU leaf or else its idle loop will burn cpu cycles; the
* intelppm driver refuses to register an idle state handler.
* Always show CPU leafs for OS X guests. */
fShowCpu = true;
{
}
if (fOsXGuest && fAudioEnabled)
{
{
}
}
if (chipsetType == ChipsetType_ICH9)
{
}
/* Attach the dummy CPU drivers */
{
BOOL fCpuAttached = true;
if (fCpuHotPlug)
{
}
if (fCpuAttached)
{
}
}
}
/*
* Configure DBGF (Debug(ger) Facility).
*/
{
/* Paths to search for debug info and such things. */
char szHomeDir[RTPATH_MAX];
if (RT_FAILURE(rc))
szHomeDir[0] = '\0';
/* Tracing configuration. */
if (fTracingEnabled)
if (fTracingEnabled)
}
}
catch (ConfigError &x)
{
// InsertConfig threw something:
return x.m_vrc;
}
{
}
#ifdef VBOX_WITH_EXTPACK
/*
* Call the extension pack hooks if everything went well thus far.
*/
if (RT_SUCCESS(rc))
{
}
#endif
/*
* Apply the CFGM overlay.
*/
if (RT_SUCCESS(rc))
/*
* Dump all extradata API settings tweaks, both global and per VM.
*/
if (RT_SUCCESS(rc))
#undef H
/*
* Register VM state change handler.
*/
if (RT_SUCCESS(rc))
/*
* Register VM runtime error handler.
*/
if (RT_SUCCESS(rc))
return rc;
}
/**
* Applies the CFGM overlay as specified by VBoxInternal/XXX extra data
* values.
*
* @returns VBox status code.
* @param pRoot The root of the configuration tree.
* @param pVirtualBox Pointer to the IVirtualBox interface.
* @param pMachine Pointer to the IMachine interface.
*/
/* static */
{
/*
* CFGM overlay handling.
*
* Here we check the extra data entries for CFGM values
* and create the nodes and insert the values on the fly. Existing
* values will be removed and reinserted. CFGM is typed, so by default
* we will guess whether it's a string or an integer (byte arrays are
* not currently supported). It's possible to override this autodetection
* by adding "string:", "integer:" or "bytes:" (future).
*
* We first perform a run on global extra data, then on the machine
* extra data to support global settings with local overrides.
*/
int rc = VINF_SUCCESS;
try
{
/** @todo add support for removing nodes and byte blobs. */
/*
* Get the next key
*/
// remember the no. of global values so we can call the correct method below
// build a combined list from global keys...
// ... and machine keys
{
/*
* We only care about keys starting with "VBoxInternal/" (skip "G:" or "M:")
*/
continue;
// get the value
if (i2 < cGlobalValues)
// this is still one of the global values:
else
/*
* Split the two and get the node, delete the value and create the node
* if necessary.
*/
if (pszCFGMValueName)
{
/* terminate the node and advance to the value (Utf8Str might not
offically like this but wtf) */
*(char*)pszCFGMValueName = '\0';
/* does the node already exist? */
if (pNode)
else
{
/* create the node */
if (RT_FAILURE(rc))
{
continue;
}
}
}
else
{
/* root value (no node path). */
}
/*
* Now let's have a look at the value.
* Empty strings means that we should remove the value, which we've
* already done above.
*/
if (!strCFGMValueUtf8.isEmpty())
{
/* check for type prefix first. */
{
if (RT_SUCCESS(rc))
}
{
if (cbValue > 0)
{
if (pvBytes)
{
if (RT_SUCCESS(rc))
}
else
}
else if (cbValue == 0)
else
}
/* auto detect type. */
else
AssertLogRelMsgRCBreak(rc, ("failed to insert CFGM value '%s' to key '%s'\n", strCFGMValueUtf8.c_str(), pszExtraDataKey));
}
}
}
catch (ConfigError &x)
{
// InsertConfig threw something:
return x.m_vrc;
}
return rc;
}
/**
* Dumps the API settings tweaks as specified by VBoxInternal2/XXX extra data
* values.
*
* @returns VBox status code.
* @param pVirtualBox Pointer to the IVirtualBox interface.
* @param pMachine Pointer to the IMachine interface.
*/
/* static */
{
{
bool hasKey = false;
{
continue;
bstrValue.asOutParam());
continue;
if (!hasKey)
LogRel(("Global extradata API settings:\n"));
hasKey = true;
}
}
{
bool hasKey = false;
{
continue;
bstrValue.asOutParam());
continue;
if (!hasKey)
LogRel(("Per-VM extradata API settings:\n"));
hasKey = true;
}
}
return VINF_SUCCESS;
}
bool fHMEnabled)
{
// InsertConfig* throws
try
{
const char *pcszDevice = "vga";
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
#else
#endif
#ifdef VBOX_WITH_VMSVGA
{
#ifdef VBOX_WITH_VMSVGA3D
if (pFramebuffer)
{
/* @todo deal with multimonitor setup */
}
#endif
}
#endif
/* Custom VESA mode list */
unsigned cModes = 0;
{
char szExtraDataKey[sizeof("CustomVideoModeXX")];
break;
++cModes;
}
/* VESA height reduction */
if (pFramebuffer)
{
}
else
{
/* If framebuffer is not available, there is no height reduction. */
ulHeightReduction = 0;
}
/*
* BIOS logo
*/
/*
* Boot menu
*/
int iShowBootMenu;
switch (eBootMenuMode)
{
case BIOSBootMenuMode_Disabled: iShowBootMenu = 0; break;
default: iShowBootMenu = 2; break;
}
/* Attach the display. */
}
catch (ConfigError &x)
{
// InsertConfig threw something:
return x.m_vrc;
}
#undef H
return VINF_SUCCESS;
}
/**
* Ellipsis to va_list wrapper for calling setVMRuntimeErrorCallback.
*/
void Console::setVMRuntimeErrorCallbackF(uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
{
}
/* XXX introduce RT format specifier */
{
{
*pszUnit = "TB";
}
{
*pszUnit = "GB";
}
else
{
*pszUnit = "MB";
}
}
const char *pcszDevice,
unsigned uInstance,
bool fUseHostIOCache,
bool fBuiltinIOCache,
bool fSetupMerge,
unsigned uMergeSource,
unsigned uMergeTarget,
bool fAttachDetach,
bool fForceUnmount,
bool fHotplug,
{
// InsertConfig* throws
try
{
int rc = VINF_SUCCESS;
// #define RC_CHECK() AssertMsgReturn(RT_SUCCESS(rc), ("rc=%Rrc\n", rc), rc)
unsigned uLUN;
if (enmBus == StorageBus_USB)
{
/* Create correct instance. */
if (!fHotplug && !fAttachDetach)
else if (fAttachDetach)
if (!fAttachDetach)
if (!fHotplug && !fAttachDetach)
{
/** @todo: No LED after hotplugging. */
/* Attach the status driver */
&mapMediumAttachments, pcszDevice, 0);
}
}
/* First check if the LUN already exists. */
if (pLunL0)
{
if (fAttachDetach)
{
if (lType != DeviceType_HardDisk)
{
/* Unmount existing media only for floppy and DVD drives. */
if (RT_FAILURE(rc))
{
rc = VINF_SUCCESS;
}
else
{
/* Unmount the media (but do not eject the medium!) */
if (rc == VERR_PDM_MEDIA_NOT_MOUNTED)
rc = VINF_SUCCESS;
/* for example if the medium is locked */
else if (RT_FAILURE(rc))
return rc;
}
}
if (enmBus == StorageBus_USB)
rc = PDMR3UsbDriverDetach(pUVM, pcszDevice, uInstance, uLUN, NULL, 0, fHotplug ? 0 : PDM_TACH_FLAGS_NOT_HOT_PLUG);
else
rc = PDMR3DeviceDetach(pUVM, pcszDevice, uInstance, uLUN, fHotplug ? 0 : PDM_TACH_FLAGS_NOT_HOT_PLUG);
if (rc == VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN)
rc = VINF_SUCCESS;
}
else
}
if (pCfg)
{
{
if (!pDrive)
/* Don't use the RemoveConfigValue wrapper above, as we don't
* know if the leaf is present or not. */
}
{
if (!pDrive)
/* Don't use the RemoveConfigValue wrapper above, as we don't
* know if the leaf is present or not. */
}
}
/* SCSI has a another driver between device and block. */
{
}
/*
* 1. Only check this for hard disk images.
* 2. Only check during VM creation and not later, especially not during
* taking an online snapshot!
*/
if ( lType == DeviceType_HardDisk
&& ( aMachineState == MachineState_Starting
|| aMachineState == MachineState_Restoring))
{
/*
* Some sanity checks.
*/
uCaps |= mediumFormatCap[j];
{
/* Ignore the error code. On error, the file system type is still 'unknown' so
* none of the following paths are taken. This can happen for new VMs which
* still don't have a snapshot folder. */
{
LogRel(("File system of '%s' (snapshots) is %s\n",
mfSnapshotFolderDiskTypeShown = true;
}
#ifdef RT_OS_WINDOWS
if ( enmFsTypeFile == RTFSTYPE_FAT
{
const char *pszUnit;
setVMRuntimeErrorCallbackF(0, "FatPartitionDetected",
N_("The medium '%ls' has a logical size of %RU64%s "
"but the file system the medium is located on seems "
"to be FAT(32) which cannot handle files bigger than 4GB.\n"
"We strongly recommend to put all your virtual disk images and "
"the snapshot folder onto an NTFS partition"),
}
#else /* !RT_OS_WINDOWS */
if ( enmFsTypeFile == RTFSTYPE_FAT
|| enmFsTypeFile == RTFSTYPE_EXT
|| enmFsTypeFile == RTFSTYPE_EXT2
|| enmFsTypeFile == RTFSTYPE_EXT3
|| enmFsTypeFile == RTFSTYPE_EXT4)
{
if (RT_SUCCESS(rc))
{
/* Careful: This function will work only on selected local file systems! */
if ( RT_SUCCESS(rc)
&& maxSize > 0
{
const char *pszUnitSiz;
const char *pszUnitMax;
N_("The medium '%ls' has a logical size of %RU64%s "
"but the file system the medium is located on can "
"only handle files up to %RU64%s in theory.\n"
"We strongly recommend to put all your virtual disk "
"images and the snapshot folder onto a proper "
"file system (e.g. ext3) with a sufficient size"),
}
}
}
#endif /* !RT_OS_WINDOWS */
/*
* Snapshot folder:
* Here we test only for a FAT partition as we had to create a dummy file otherwise
*/
if ( enmFsTypeSnap == RTFSTYPE_FAT
{
const char *pszUnit;
setVMRuntimeErrorCallbackF(0, "FatPartitionDetected",
#ifdef RT_OS_WINDOWS
N_("The snapshot folder of this VM '%ls' seems to be located on "
"a FAT(32) file system. The logical size of the medium '%ls' "
"(%RU64%s) is bigger than the maximum file size this file "
"system can handle (4GB).\n"
"We strongly recommend to put all your virtual disk images and "
"the snapshot folder onto an NTFS partition"),
#else
N_("The snapshot folder of this VM '%ls' seems to be located on "
"a FAT(32) file system. The logical size of the medium '%ls' "
"(%RU64%s) is bigger than the maximum file size this file "
"system can handle (4GB).\n"
"We strongly recommend to put all your virtual disk images and "
"the snapshot folder onto a proper file system (e.g. ext3)"),
#endif
/* Show this particular warning only once */
mfSnapshotFolderSizeWarningShown = true;
}
#ifdef RT_OS_LINUX
/*
* Ext4 bug: Check if the host I/O cache is disabled and the disk image is located
* on an ext4 partition. Later we have to check the Linux kernel version!
* This bug apparently applies to the XFS file system as well.
* Linux 2.6.36 is known to be fixed (tested with 2.6.36-rc4).
*/
char szOsRelease[128];
&& !fUseHostIOCache
{
if ( enmFsTypeFile == RTFSTYPE_EXT4
|| enmFsTypeFile == RTFSTYPE_XFS)
{
setVMRuntimeErrorCallbackF(0, "Ext4PartitionDetected",
N_("The host I/O cache for at least one controller is disabled "
"and the medium '%ls' for this VM "
"is located on an %s partition. There is a known Linux "
"kernel bug which can lead to the corruption of the virtual "
"disk image under these conditions.\n"
"Either enable the host I/O cache permanently in the VM "
"settings or put the disk image and the snapshot folder "
"onto a different file system.\n"
"The host I/O cache will now be enabled for this medium"),
fUseHostIOCache = true;
}
else if ( ( enmFsTypeSnap == RTFSTYPE_EXT4
|| enmFsTypeSnap == RTFSTYPE_XFS)
{
setVMRuntimeErrorCallbackF(0, "Ext4PartitionDetected",
N_("The host I/O cache for at least one controller is disabled "
"and the snapshot folder for this VM "
"is located on an %s partition. There is a known Linux "
"kernel bug which can lead to the corruption of the virtual "
"disk image under these conditions.\n"
"Either enable the host I/O cache permanently in the VM "
"settings or put the disk image and the snapshot folder "
"onto a different file system.\n"
"The host I/O cache will now be enabled for this medium"),
fUseHostIOCache = true;
mfSnapshotFolderExt4WarningShown = true;
}
}
#endif
}
}
if (pMedium)
{
if ( ( lType == DeviceType_DVD
|| lType == DeviceType_Floppy)
&& !fHostDrive)
{
/*
* Informative logging.
*/
LogRel(("File system of '%s' (%s) is %s\n",
}
}
{
}
!!fPassthrough,
!!fDiscard,
phrc);
if (RT_FAILURE(rc))
return rc;
if (fAttachDetach)
{
/* Attach the new driver. */
if (enmBus == StorageBus_USB)
{
if (fHotplug)
{
if (RT_SUCCESS(rc))
}
else
}
else
/* There is no need to handle removable medium mounting, as we
* unconditionally replace everthing including the block driver level.
* This means the new medium will be picked up automatically. */
}
if (paLedDevType)
}
catch (ConfigError &x)
{
// InsertConfig threw something:
return x.m_vrc;
}
#undef H
return VINF_SUCCESS;
}
bool fPassthrough,
bool fUseHostIOCache,
bool fBuiltinIOCache,
bool fSetupMerge,
unsigned uMergeSource,
unsigned uMergeTarget,
const char *pcszBwGroup,
bool fDiscard,
{
// InsertConfig* throws
try
{
int rc = VINF_SUCCESS;
#define H() \
AssertMsgReturnStmt(SUCCEEDED(hrc), ("hrc=%Rhrc\n", hrc), if (phrc) *phrc = hrc, Global::vboxStatusCodeFromCOM(hrc))
if (pMedium)
{
}
if (fHostDrive)
{
if (enmType == DeviceType_DVD)
{
}
else if (enmType == DeviceType_Floppy)
{
}
}
else
{
switch (enmType)
{
case DeviceType_DVD:
break;
case DeviceType_Floppy:
break;
case DeviceType_HardDisk:
default:
}
if ( pMedium
&& ( enmType == DeviceType_DVD
|| enmType == DeviceType_Floppy)
)
{
// if this medium represents an ISO image and this image is inaccessible,
// the ignore it instead of causing a failure; this can happen when we
// restore a VM state and the ISO has disappeared, e.g. because the Guest
// Additions were mounted and the user upgraded VirtualBox. Previously
// we failed on startup, but that's not good because the only way out then
// would be to discard the VM state...
if (mediumState == MediumState_Inaccessible)
{
setVMRuntimeErrorCallbackF(0, "DvdOrFloppyImageInaccessible",
"The image file '%ls' is inaccessible and is being ignored. Please select a different image file for the virtual %s drive.",
}
}
if (pMedium)
{
/* Start with length of parent chain, as the list is reversed */
unsigned uImage = 0;
while (pTmp)
{
uImage++;
}
/* Index of last image */
uImage--;
#if 0 /* Enable for I/O debugging */
#endif
if (mediumType == MediumType_Readonly)
else if (enmType == DeviceType_Floppy)
/* Start without exclusive write access to the images. */
/** @todo Live Migration: I don't quite like this, we risk screwing up when
* we're resuming the VM if some 3rd dude have any of the VDIs open
* with write sharing denied. However, if the two VMs are sharing a
* image it really is necessary....
*
* So, on the "lock-media" command, the target teleporter should also
* make DrvVD undo TempReadOnly. It gets interesting if we fail after
* that. Grumble. */
if ( enmType == DeviceType_HardDisk
/* Flag for opening the medium for sharing between VMs. This
* is done at the moment only for the first (and only) medium
* in the chain, as shared media can have no diffs. */
if (mediumType == MediumType_Shareable)
if (!fUseHostIOCache)
{
/*
* Activate the builtin I/O cache for harddisks only.
* It caches writes only which doesn't make sense for DVD drives
* and just increases the overhead.
*/
if ( fBuiltinIOCache
&& (enmType == DeviceType_HardDisk))
}
if (fSetupMerge)
{
if (uImage == uMergeSource)
else if (uImage == uMergeTarget)
}
switch (enmType)
{
case DeviceType_DVD:
break;
case DeviceType_Floppy:
break;
case DeviceType_HardDisk:
default:
}
if (pcszBwGroup)
if (fDiscard)
/* Pass all custom parameters. */
bool fHostIP = true;
ComSafeArrayAsOutParam(values)); H();
{
{
{
fHostIP = false;
}
}
}
/* Create an inverted list of parents. */
uImage--;
{
if (!pMedium)
break;
if (fSetupMerge)
{
if (uImage == uMergeSource)
else if (uImage == uMergeTarget)
}
/* Pass all custom parameters. */
ComSafeArrayAsOutParam(aValues)); H();
{
{
{
fHostIP = false;
}
}
}
/* next */
}
/* Custom code: put marker to not use host IP stack to driver
* configuration node. Simplifies life of DrvVD a bit. */
if (!fHostIP)
}
}
#undef H
}
catch (ConfigError &x)
{
// InsertConfig threw something:
return x.m_vrc;
}
return VINF_SUCCESS;
}
/**
* Construct the Network configuration tree
*
* @returns VBox status code.
*
* @param pszDevice The PDM device name.
* @param uInstance The PDM device instance.
* @param uLun The PDM LUN number of the drive.
* @param aNetworkAdapter The network adapter whose attachment needs to be changed
* @param pCfg Configuration node for the device
* @param pLunL0 To store the pointer to the LUN#0.
* @param pInst The instance CFGM node
* @param fAttachDetach To determine if the network attachment should
* configuration.
* @param fIgnoreConnectFailure
* True if connection failures should be ignored
*
* @note Locks this object for writing.
* @thread EMT
*/
unsigned uInstance,
unsigned uLun,
bool fAttachDetach,
bool fIgnoreConnectFailure)
{
AutoCaller autoCaller(this);
// InsertConfig* throws
try
{
int rc = VINF_SUCCESS;
/*
* Locking the object before doing VMR3* calls is quite safe here, since
* we're on EMT. Write lock is necessary because we indirectly modify the
* meAttachmentType member.
*/
const char *pszPromiscuousGuestPolicy;
switch (enmPromiscModePolicy)
{
case NetworkAdapterPromiscModePolicy_AllowNetwork: pszPromiscuousGuestPolicy = "allow-network"; break;
default: AssertFailedReturn(VERR_INTERNAL_ERROR_4);
}
if (fAttachDetach)
{
if (rc == VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN)
rc = VINF_SUCCESS;
/* nuke anything which might have been left behind. */
}
#ifdef VBOX_WITH_NETSHAPER
{
}
#endif /* VBOX_WITH_NETSHAPER */
#ifdef VBOX_WITH_NETSHAPER
if (!strBwGroup.isEmpty())
{
}
#endif /* VBOX_WITH_NETSHAPER */
if (fSniffer)
{
}
switch (eAttachmentType)
{
break;
{
/* Configure TFTP prefix and boot filename. */
InsertConfigString(pCfg, "TFTPPrefix", Utf8StrFmt("%ls%c%s", bstr.raw(), RTPATH_DELIMITER, "TFTP"));
else
{
}
if (mtu)
if (sockRcv)
if (sockSnd)
if (tcpRcv)
if (tcpSnd)
{
}
{
}
/* port-forwarding */
{
do { \
{ \
continue; \
} \
} while (0)
bool fValid = true;
switch (proto)
{
case NATProtocol_UDP:
strProto = "UDP";
break;
case NATProtocol_TCP:
strProto = "TCP";
break;
default:
fValid = false;
}
/* continue with next rule if no valid proto was passed */
if (!fValid)
continue;
N_("NAT redirection rule without a name"));
if (!strGuestIP.isEmpty())
if (port)
if (port)
}
break;
}
{
{
switch (hrc)
{
case VERR_ACCESS_DENIED:
"change the group of that node and make yourself a member of that group. Make "
"sure that these changes are permanent, especially if you are "
"using udev"));
default:
AssertMsgFailed(("Could not attach to host interface! Bad!\n"));
"Failed to initialize Host Interface Networking"));
}
}
{
}
#elif defined(VBOX_WITH_NETFLT)
/*
* This is the new VBoxNetFlt+IntNet stuff.
*/
{
H();
}
# if defined(RT_OS_DARWIN)
/* The name is on the form 'ifX: long name', chop it off at the colon. */
char szTrunk[8];
// Quick fix for @bugref{5633}
// if (!pszColon)
// {
// /*
// * Dynamic changing of attachment causes an attempt to configure
// * network with invalid host adapter (as it is must be changed before
// * the attachment), calling Detach here will cause a deadlock.
// * See @bugref{4750}.
// * hrc = aNetworkAdapter->Detach(); H();
// */
// return VMSetError(VMR3GetVM(mpUVM), VERR_INTERNAL_ERROR, RT_SRC_POS,
// N_("Malformed host interface networking name '%ls'"),
// BridgedIfName.raw());
// }
if (pszColon)
*pszColon = '\0';
# elif defined(RT_OS_SOLARIS)
/* The name is on the form format 'ifX[:1] - long name, chop it off at space. */
char szTrunk[256];
/*
* Currently don't bother about malformed names here for the sake of people using
* VBoxManage and setting only the NIC name from there. If there is a space we
* chop it off and proceed, otherwise just use whatever we've got.
*/
if (pszSpace)
*pszSpace = '\0';
/* Chop it off at the colon (zone naming eg: e1000g:1 we need only the e1000g) */
if (pszColon)
*pszColon = '\0';
# elif defined(RT_OS_WINDOWS)
{
AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: FindByName failed, rc=%Rhrc (0x%x)", hrc, hrc));
N_("Nonexistent host networking interface, name '%ls'"),
BridgedIfName.raw());
}
{
H();
}
{
N_("Interface ('%ls') is not a Bridged Adapter interface"),
BridgedIfName.raw());
}
{
H();
}
{
H();
}
/* get the adapter's INetCfgComponent*/
hrc = VBoxNetCfgWinGetComponentByGuid(pNc, &GUID_DEVCLASS_NET, (GUID*)hostIFGuid.raw(), pAdaptorComponent.asOutParam());
{
LogRel(("NetworkAttachmentType_Bridged: VBoxNetCfgWinGetComponentByGuid failed, hrc (0x%x)\n", hrc));
H();
}
#define VBOX_WIN_BINDNAME_PREFIX "\\DEVICE\\"
char szTrunkName[INTNET_MAX_TRUNK_NAME];
char *pszTrunkName = szTrunkName;
wchar_t * pswzBindName;
{
int cbFullBindNamePrefix = sizeof(VBOX_WIN_BINDNAME_PREFIX);
{
{
AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: WideCharToMultiByte failed, hr=%Rhrc (0x%x) err=%u\n", hrc, hrc, err));
}
}
else
{
AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: insufficient szTrunkName buffer space\n"));
/** @todo set appropriate error code */
}
{
AssertFailed();
H();
}
/* we're not freeing the bind name since we'll use it later for detecting wireless*/
}
else
{
AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: VBoxNetCfgWinGetComponentByGuid failed, hrc (0x%x)", hrc));
H();
}
const char *pszTrunk = szTrunkName;
/* we're not releasing the INetCfg stuff here since we use it later to figure out whether it is wireless */
# if defined(RT_OS_FREEBSD)
/*
* If we bridge to a tap interface open it the `old' direct way.
* This works and performs better than bridging a physical
* interface via the current FreeBSD vboxnetflt implementation.
*/
{
switch (hrc)
{
case VERR_ACCESS_DENIED:
"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."), pszBridgedIfName, pszBridgedIfName);
default:
AssertMsgFailed(("Could not attach to tap interface! Bad!\n"));
"Failed to initialize Host Interface Networking"));
}
}
{
}
break;
}
# endif
/** @todo Check for malformed names. */
const char *pszTrunk = pszBridgedIfName;
/* Issue a warning if the interface is down */
{
if (iSock >= 0)
{
setVMRuntimeErrorCallbackF(0, "BridgedInterfaceDown",
N_("Bridged interface %s is down. Guest will not be able to use this interface"),
}
}
# else
# error "PORTME (VBOX_WITH_NETFLT)"
# endif
char szNetwork[INTNET_MAX_NETWORK_NAME];
#if defined(RT_OS_SOLARIS) || defined(RT_OS_DARWIN)
/*
* 'pszTrunk' contains just the interface name required in ring-0, while 'pszBridgedIfName' contains
* interface name + optional description. We must not pass any description to the VM as it can differ
* for the same interface name, eg: "nge0 - ethernet" (GUI) vs "nge0" (VBoxManage).
*/
#else
#endif
# if defined(RT_OS_DARWIN)
/** @todo Come up with a better deal here. Problem is that IHostNetworkInterface is completely useless here. */
# elif defined(RT_OS_LINUX)
if (iSock >= 0)
{
if (fSharedMacOnWire)
{
Log(("Set SharedMacOnWire\n"));
}
else
Log(("Failed to get wireless name\n"));
}
else
Log(("Failed to open wireless socket\n"));
# elif defined(RT_OS_FREEBSD)
if (iSock >= 0)
{
struct ieee80211req WReq;
if (fSharedMacOnWire)
{
Log(("Set SharedMacOnWire\n"));
}
else
Log(("Failed to get wireless name\n"));
}
else
Log(("Failed to open wireless socket\n"));
# elif defined(RT_OS_WINDOWS)
# define DEVNAME_PREFIX L"\\\\.\\"
/* we are getting the medium type via IOCTL_NDIS_QUERY_GLOBAL_STATS Io Control
* there is a pretty long way till there though since we need to obtain the symbolic link name
* for the adapter device we are going to query given the device Guid */
/* prepend the "\\\\.\\" to the bind name to obtain the link name */
/* open the device */
NULL,
NULL);
if (hDevice != INVALID_HANDLE_VALUE)
{
bool fSharedMacOnWire = false;
/* now issue the OID_GEN_PHYSICAL_MEDIUM query */
if (DeviceIoControl(hDevice,
&Oid,
sizeof(Oid),
&PhMedium,
sizeof(PhMedium),
&cbResult,
NULL))
{
/* that was simple, now examine PhMedium */
fSharedMacOnWire = true;
}
else
{
int winEr = GetLastError();
Assert(winEr == ERROR_INVALID_PARAMETER || winEr == ERROR_NOT_SUPPORTED || winEr == ERROR_BAD_COMMAND);
}
if (fSharedMacOnWire)
{
Log(("this is a wireless adapter"));
Log(("Set SharedMacOnWire\n"));
}
else
Log(("this is NOT a wireless adapter"));
}
else
{
int winEr = GetLastError();
AssertLogRelMsgFailed(("Console::configNetwork: CreateFile failed, err (0x%x), ignoring\n", winEr));
}
/* release the pNc finally */
# else
/** @todo PORTME: wireless detection */
# endif
# if defined(RT_OS_SOLARIS)
# if 0 /* bird: this is a bit questionable and might cause more trouble than its worth. */
/* Zone access restriction, don't allow snooping the global zone. */
if (ZoneId != GLOBAL_ZONEID)
{
}
# endif
# endif
/* NOTHING TO DO HERE */
#elif defined(RT_OS_LINUX)
/// @todo aleksey: is there anything to be done here?
#elif defined(RT_OS_FREEBSD)
/** @todo FreeBSD: Check out this later (HIF networking). */
#else
# error "Port me"
#endif
break;
}
{
{
networkName = bstr;
}
break;
}
{
{
H();
}
{
N_("Nonexistent host networking interface, name '%ls'"),
HostOnlyName.raw());
}
char szNetwork[INTNET_MAX_NETWORK_NAME];
#if defined(RT_OS_WINDOWS)
# ifndef VBOX_WITH_NETFLT
LogRel(("NetworkAttachmentType_HostOnly: Not Implemented\n"));
H();
# else /* defined VBOX_WITH_NETFLT*/
/** @todo r=bird: Put this in a function. */
{
H();
}
N_("Interface ('%ls') is not a Host-Only Adapter interface"),
HostOnlyName.raw());
{
H();
}
{
H();
}
/* get the adapter's INetCfgComponent*/
hrc = VBoxNetCfgWinGetComponentByGuid(pNc, &GUID_DEVCLASS_NET, (GUID*)hostIFGuid.raw(), pAdaptorComponent.asOutParam());
{
LogRel(("NetworkAttachmentType_HostOnly: VBoxNetCfgWinGetComponentByGuid failed, hrc=%Rhrc (0x%x)\n", hrc, hrc));
H();
}
# define VBOX_WIN_BINDNAME_PREFIX "\\DEVICE\\"
char szTrunkName[INTNET_MAX_TRUNK_NAME];
char *pszTrunkName = szTrunkName;
wchar_t * pswzBindName;
{
int cbFullBindNamePrefix = sizeof(VBOX_WIN_BINDNAME_PREFIX);
{
{
AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: WideCharToMultiByte failed, hr=%Rhrc (0x%x) err=%u\n", hrc, hrc, err));
}
}
else
{
AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: insufficient szTrunkName buffer space\n"));
/** @todo set appropriate error code */
}
{
AssertFailed();
H();
}
}
else
{
AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: VBoxNetCfgWinGetComponentByGuid failed, hrc=%Rhrc (0x%x)\n", hrc, hrc));
H();
}
/* release the pNc finally */
const char *pszTrunk = szTrunkName;
InsertConfigInteger(pCfg, "IgnoreConnectFailure", (uint64_t)fIgnoreConnectFailure); /** @todo why is this windows only?? */
# endif /* defined VBOX_WITH_NETFLT*/
#elif defined(RT_OS_DARWIN)
#else
#endif
#if !defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT)
pszHostOnlyName).raw(),
tmpAddr.asOutParam());
{
pszHostOnlyName).raw(),
tmpMask.asOutParam());
else
}
else
{
/* Grab the IP number from the 'vboxnetX' instance number (see netif.h) */
}
pszHostOnlyName).raw(),
tmpAddr.asOutParam());
tmpMask.asOutParam());
{
}
#endif
break;
}
{
ComSafeArrayAsOutParam(values)); H();
{
{
}
}
break;
}
{
{
/** @todo add intnet prefix to separate namespaces, and add trunk if dealing with vboxnatX */
networkName = bstr;
}
break;
}
default:
AssertMsgFailed(("should not get here!\n"));
break;
}
/*
* Attempt to attach the driver.
*/
switch (eAttachmentType)
{
break;
{
{
if (fAttachDetach)
{
//AssertRC(rc);
}
{
/** @todo pritesh: get the dhcp server name from the
* previous network configuration and then stop the server
* else it may conflict with the dhcp server running with
* the current attachment type
*/
/* Stop the hostonly DHCP Server */
}
/*
* NAT networks start their DHCP server theirself, see NATNetwork::Start()
*/
if ( !networkName.isEmpty()
{
/*
* Until we implement service reference counters DHCP Server will be stopped
* by DHCPServerRunner destructor.
*/
dhcpServer.asOutParam());
{
/* there is a DHCP server available for this network */
{
H();
}
if (fEnabledDhcp)
}
else
}
}
break;
}
default:
AssertMsgFailed(("should not get here!\n"));
break;
}
}
catch (ConfigError &x)
{
// InsertConfig threw something:
return x.m_vrc;
}
#undef H
return VINF_SUCCESS;
}
#ifdef VBOX_WITH_GUEST_PROPS
/**
* Set an array of guest properties
*/
void *names,
void *values,
void *timestamps,
void *flags)
{
4,
&parms[0]);
}
/**
* Set a single guest property
*/
const char *pszName,
const char *pszValue,
const char *pszFlags)
{
&parms[0]);
}
/**
* Set the global flags value by calling the service
* @returns the status returned by the call to the service
*
* @param pTable the service instance handle
* @param eFlags the flags to set
*/
{
&paParm);
if (RT_FAILURE(rc))
{
Log(("Failed to set the global flags.\n"));
else
}
return rc;
}
#endif /* VBOX_WITH_GUEST_PROPS */
/**
* Set up the Guest Property service, populate it with properties read from
* the machine XML and set a couple of initial properties.
*/
{
#ifdef VBOX_WITH_GUEST_PROPS
/* Load the service */
if (RT_FAILURE(rc))
{
/* That is not a fatal failure. */
rc = VINF_SUCCESS;
}
else
{
/*
* Initialize built-in properties that can be changed and saved.
*
* These are typically transient properties that the guest cannot
* change.
*/
{
int rc2 = pConsole->m_pVMMDev->hgcmHostCall("VBoxGuestPropSvc", guestProp::GET_DBGF_INFO_FN, 2, &Params[0]);
if (RT_SUCCESS(rc2))
{
DBGFR3InfoRegisterExternal(pUVM, "guestprops", "Display the guest properties", pfnHandler, pService);
}
}
/* Sysprep execution by VBoxService. */
"/VirtualBox/HostGuest/SysprepExec", "",
"TRANSIENT, RDONLYGUEST");
"/VirtualBox/HostGuest/SysprepArgs", "",
"TRANSIENT, RDONLYGUEST");
/*
* Pull over the properties from the server.
*/
)
char szEmpty[] = "";
{
{
if (RT_FAILURE(rc))
break;
if (valuesOut[i])
else
papszValues[i] = szEmpty;
if (RT_FAILURE(rc))
break;
pai64Timestamps[i] = timestampsOut[i];
if (flagsOut[i])
else
papszFlags[i] = szEmpty;
}
if (RT_SUCCESS(rc))
(void *)papszNames,
(void *)papszValues,
(void *)pai64Timestamps,
(void *)papszFlags);
for (unsigned i = 0; i < cProps; ++i)
{
RTStrFree(papszNames[i]);
if (valuesOut[i])
RTStrFree(papszValues[i]);
if (flagsOut[i])
RTStrFree(papszFlags[i]);
}
}
else
rc = VERR_NO_MEMORY;
/*
* These properties have to be set before pulling over the properties
* from the machine XML, to ensure that properties saved in the XML
* will override them.
*/
* version comparison. */
VBOX_VERSION_STRING_RAW, "TRANSIENT, RDONLYGUEST");
/* Set the full VBox version string as a guest property. Can contain vendor-specific
* information/branding and/or pre-release tags. */
VBOX_VERSION_STRING, "TRANSIENT, RDONLYGUEST");
/* Set the VBox SVN revision as a guest property */
RTBldCfgRevisionStr(), "TRANSIENT, RDONLYGUEST");
/*
* Register the host notification callback
*/
#endif
Log(("Set VBoxGuestPropSvc property store\n"));
}
return VINF_SUCCESS;
#else /* !VBOX_WITH_GUEST_PROPS */
return VERR_NOT_SUPPORTED;
#endif /* !VBOX_WITH_GUEST_PROPS */
}
/**
* Set up the Guest Control service.
*/
{
#ifdef VBOX_WITH_GUEST_CONTROL
/* Load the service */
if (RT_FAILURE(rc))
{
/* That is not a fatal failure. */
rc = VINF_SUCCESS;
}
else
{
if (RT_FAILURE(rc))
Log(("Cannot register VBoxGuestControlSvc extension!\n"));
else
Log(("VBoxGuestControlSvc loaded\n"));
}
return rc;
#else /* !VBOX_WITH_GUEST_CONTROL */
return VERR_NOT_SUPPORTED;
#endif /* !VBOX_WITH_GUEST_CONTROL */
}