/src/VBox/Main/src-client/ConsoleImpl2.cpp
C++ | 5037 lines | 3869 code | 485 blank | 683 comment | 501 complexity | aed98d69c4fa415824c0f53b6ffabd8b MD5 | raw file
Possible License(s): BSD-3-Clause, MIT, GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- /* $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-2012 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * 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 "VBox/com/ptr.h"
- #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>
- #include <iprt/ctype.h>
- #include <iprt/dir.h>
- #include <iprt/file.h>
- #include <iprt/param.h>
- #include <iprt/path.h>
- #include <iprt/string.h>
- #include <iprt/system.h>
- #include <iprt/cpp/exception.h>
- #if 0 /* enable to play with lots of memory. */
- # include <iprt/env.h>
- #endif
- #include <iprt/stream.h>
- #include <VBox/vmm/vmapi.h>
- #include <VBox/err.h>
- #include <VBox/param.h>
- #include <VBox/vmm/pdmapi.h> /* For PDMR3DriverAttach/PDMR3DriverDetach */
- #include <VBox/version.h>
- #include <VBox/HostServices/VBoxClipboardSvc.h>
- #ifdef VBOX_WITH_CROGL
- # include <VBox/HostServices/VBoxCrOpenGLSvc.h>
- #include <VBox/VBoxOGLTest.h>
- #endif
- #ifdef VBOX_WITH_GUEST_PROPS
- # include <VBox/HostServices/GuestPropertySvc.h>
- # include <VBox/com/defs.h>
- # include <VBox/com/array.h>
- # include "HGCM.h" /** @todo it should be possible to register a service
- * extension using a VMMDev callback. */
- # include <vector>
- #endif /* VBOX_WITH_GUEST_PROPS */
- #include <VBox/intnet.h>
- #include <VBox/com/com.h>
- #include <VBox/com/string.h>
- #include <VBox/com/array.h>
- #ifdef VBOX_WITH_NETFLT
- # if defined(RT_OS_SOLARIS)
- # include <zone.h>
- # elif defined(RT_OS_LINUX)
- # include <unistd.h>
- # include <sys/ioctl.h>
- # include <sys/socket.h>
- # include <linux/types.h>
- # include <linux/if.h>
- # include <linux/wireless.h>
- # elif defined(RT_OS_FREEBSD)
- # include <unistd.h>
- # include <sys/types.h>
- # include <sys/ioctl.h>
- # include <sys/socket.h>
- # include <net/if.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 "DHCPServerRunner.h"
- #include "BusAssignmentManager.h"
- #ifdef VBOX_WITH_EXTPACK
- # include "ExtPackManagerImpl.h"
- #endif
- #if defined(RT_OS_DARWIN)
- # include "IOKit/IOKitLib.h"
- static int DarwinSmcKey(char *pabKey, uint32_t cbKey)
- {
- /*
- * Method as described in Amit Singh's article:
- * http://osxbook.com/book/bonus/chapter7/tpmdrmmyth/
- */
- typedef struct
- {
- uint32_t key;
- uint8_t pad0[22];
- uint32_t datasize;
- uint8_t pad1[10];
- uint8_t cmd;
- uint32_t pad2;
- uint8_t data[32];
- } AppleSMCBuffer;
- AssertReturn(cbKey >= 65, VERR_INTERNAL_ERROR);
- io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault,
- IOServiceMatching("AppleSMC"));
- if (!service)
- return VERR_NOT_FOUND;
- io_connect_t port = (io_connect_t)0;
- kern_return_t kr = IOServiceOpen(service, mach_task_self(), 0, &port);
- IOObjectRelease(service);
- if (kr != kIOReturnSuccess)
- return RTErrConvertFromDarwin(kr);
- AppleSMCBuffer inputStruct = { 0, {0}, 32, {0}, 5, };
- AppleSMCBuffer outputStruct;
- size_t cbOutputStruct = sizeof(outputStruct);
- for (int i = 0; i < 2; i++)
- {
- inputStruct.key = (uint32_t)((i == 0) ? 'OSK0' : 'OSK1');
- kr = IOConnectCallStructMethod((mach_port_t)port,
- (uint32_t)2,
- (const void *)&inputStruct,
- sizeof(inputStruct),
- (void *)&outputStruct,
- &cbOutputStruct);
- if (kr != kIOReturnSuccess)
- {
- IOServiceClose(port);
- return RTErrConvertFromDarwin(kr);
- }
- for (int j = 0; j < 32; j++)
- pabKey[j + i*32] = outputStruct.data[j];
- }
- IOServiceClose(port);
- pabKey[64] = 0;
- return VINF_SUCCESS;
- }
- #endif /* RT_OS_DARWIN */
- /* Darwin compile kludge */
- #undef PVM
- /* Comment out the following line to remove VMWare compatibility hack. */
- #define VMWARE_NET_IN_SLOT_11
- /**
- * Translate IDE StorageControllerType_T to string representation.
- */
- const char* controllerString(StorageControllerType_T enmType)
- {
- switch (enmType)
- {
- case StorageControllerType_PIIX3:
- return "PIIX3";
- case StorageControllerType_PIIX4:
- return "PIIX4";
- case StorageControllerType_ICH6:
- return "ICH6";
- default:
- return "Unknown";
- }
- }
- /**
- * Simple class for storing network boot information.
- */
- struct BootNic
- {
- ULONG mInstance;
- PCIBusAddress mPCIAddress;
- ULONG mBootPrio;
- bool operator < (const BootNic &rhs) const
- {
- ULONG lval = mBootPrio - 1; /* 0 will wrap around and get the lowest priority. */
- ULONG rval = rhs.mBootPrio - 1;
- return lval < rval; /* Zero compares as highest number (lowest prio). */
- }
- };
- static int findEfiRom(IVirtualBox* vbox, FirmwareType_T aFirmwareType, Utf8Str *pEfiRomFile)
- {
- Bstr aFilePath, empty;
- BOOL fPresent = FALSE;
- HRESULT hrc = vbox->CheckFirmwarePresent(aFirmwareType, empty.raw(),
- empty.asOutParam(), aFilePath.asOutParam(), &fPresent);
- AssertComRCReturn(hrc, Global::vboxStatusCodeFromCOM(hrc));
- if (!fPresent)
- {
- LogRel(("Failed to find an EFI ROM file.\n"));
- return VERR_FILE_NOT_FOUND;
- }
- *pEfiRomFile = Utf8Str(aFilePath);
- return VINF_SUCCESS;
- }
- static int getSmcDeviceKey(IMachine *pMachine, BSTR *aKey, bool *pfGetKeyFromRealSMC)
- {
- *pfGetKeyFromRealSMC = false;
- /*
- * The extra data takes precedence (if non-zero).
- */
- HRESULT hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/SmcDeviceKey").raw(),
- aKey);
- if (FAILED(hrc))
- return Global::vboxStatusCodeFromCOM(hrc);
- if ( SUCCEEDED(hrc)
- && *aKey
- && **aKey)
- return VINF_SUCCESS;
- #ifdef RT_OS_DARWIN
- /*
- * Query it here and now.
- */
- char abKeyBuf[65];
- int rc = DarwinSmcKey(abKeyBuf, sizeof(abKeyBuf));
- if (SUCCEEDED(rc))
- {
- Bstr(abKeyBuf).detachTo(aKey);
- return rc;
- }
- LogRel(("Warning: DarwinSmcKey failed with rc=%Rrc!\n", 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';
- RTSystemQueryDmiString(RTSYSDMISTR_MANUFACTURER, szManufacturer, sizeof(szManufacturer));
- if (szManufacturer[0] != '\0')
- {
- if ( !strcmp(szManufacturer, "Apple Computer, Inc.")
- || !strcmp(szManufacturer, "Apple Inc.")
- )
- *pfGetKeyFromRealSMC = true;
- }
- else
- {
- char szProdName[256];
- szProdName[0] = '\0';
- RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_NAME, szProdName, sizeof(szProdName));
- if ( ( !strncmp(szProdName, "Mac", 3)
- || !strncmp(szProdName, "iMac", 4)
- || !strncmp(szProdName, "iMac", 4)
- || !strncmp(szProdName, "Xserve", 6)
- )
- && !strchr(szProdName, ' ') /* no spaces */
- && RT_C_IS_DIGIT(szProdName[strlen(szProdName) - 1]) /* version number */
- )
- *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)
- # pragma optimize("g", off)
- #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)
- : 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
- }
- 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.
- */
- static void InsertConfigString(PCFGMNODE pNode,
- const char *pcszName,
- const char *pcszValue)
- {
- int vrc = CFGMR3InsertString(pNode,
- pcszName,
- pcszValue);
- if (RT_FAILURE(vrc))
- throw ConfigError("CFGMR3InsertString", vrc, pcszName);
- }
- /**
- * 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.
- */
- static void InsertConfigString(PCFGMNODE pNode,
- const char *pcszName,
- const Utf8Str &rStrValue)
- {
- int vrc = CFGMR3InsertStringN(pNode,
- pcszName,
- rStrValue.c_str(),
- rStrValue.length());
- if (RT_FAILURE(vrc))
- throw ConfigError("CFGMR3InsertStringLengthKnown", vrc, pcszName);
- }
- /**
- * 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.
- */
- static void InsertConfigString(PCFGMNODE pNode,
- const char *pcszName,
- const Bstr &rBstrValue)
- {
- InsertConfigString(pNode, pcszName, Utf8Str(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.
- */
- static void InsertConfigBytes(PCFGMNODE pNode,
- const char *pcszName,
- const void *pvBytes,
- size_t cbBytes)
- {
- int vrc = CFGMR3InsertBytes(pNode,
- pcszName,
- pvBytes,
- cbBytes);
- if (RT_FAILURE(vrc))
- throw ConfigError("CFGMR3InsertBytes", vrc, pcszName);
- }
- /**
- * Helper that calls CFGMR3InsertInteger and throws an RTCError if that
- * fails.
- *
- * @param pNode See CFGMR3InsertInteger.
- * @param pcszName See CFGMR3InsertInteger.
- * @param u64Integer See CFGMR3InsertInteger.
- */
- static void InsertConfigInteger(PCFGMNODE pNode,
- const char *pcszName,
- uint64_t u64Integer)
- {
- int vrc = CFGMR3InsertInteger(pNode,
- pcszName,
- u64Integer);
- if (RT_FAILURE(vrc))
- throw ConfigError("CFGMR3InsertInteger", vrc, pcszName);
- }
- /**
- * Helper that calls CFGMR3InsertNode and throws an RTCError if that fails.
- *
- * @param pNode See CFGMR3InsertNode.
- * @param pcszName See CFGMR3InsertNode.
- * @param ppChild See CFGMR3InsertNode.
- */
- static void InsertConfigNode(PCFGMNODE pNode,
- const char *pcszName,
- PCFGMNODE *ppChild)
- {
- int vrc = CFGMR3InsertNode(pNode, pcszName, ppChild);
- if (RT_FAILURE(vrc))
- throw ConfigError("CFGMR3InsertNode", vrc, pcszName);
- }
- /**
- * Helper that calls CFGMR3RemoveValue and throws an RTCError if that fails.
- *
- * @param pNode See CFGMR3RemoveValue.
- * @param pcszName See CFGMR3RemoveValue.
- */
- static void RemoveConfigValue(PCFGMNODE pNode,
- const char *pcszName)
- {
- int vrc = CFGMR3RemoveValue(pNode, pcszName);
- if (RT_FAILURE(vrc))
- throw ConfigError("CFGMR3RemoveValue", vrc, pcszName);
- }
- /** Helper that finds out the next SATA port used
- */
- static LONG GetNextUsedSataPort(LONG aSataPortUsed[30], LONG lBaseVal, uint32_t u32Size)
- {
- LONG lNextPortUsed = 30;
- for (size_t j = 0; j < u32Size; ++j)
- {
- if(aSataPortUsed[j] > lBaseVal &&
- aSataPortUsed[j] <= lNextPortUsed)
- lNextPortUsed = aSataPortUsed[j];
- }
- return lNextPortUsed;
- }
- #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).
- *
- * This is a callback for VMR3Create() call. It is called from CFGMR3Init()
- * in the emulation thread (EMT). Any per thread COM/XPCOM initialization
- * is done here.
- *
- * @param pVM VM handle.
- * @param pvConsole Pointer to the VMPowerUpTask object.
- * @return VBox status code.
- *
- * @note Locks the Console object for writing.
- */
- DECLCALLBACK(int) Console::configConstructor(PVM pVM, void *pvConsole)
- {
- LogFlowFuncEnter();
- AssertReturn(pvConsole, VERR_GENERAL_FAILURE);
- ComObjPtr<Console> pConsole = static_cast<Console *>(pvConsole);
- AutoCaller autoCaller(pConsole);
- AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED);
- /* lock the console because we widely use internal fields and methods */
- AutoWriteLock alock(pConsole COMMA_LOCKVAL_SRC_POS);
- /*
- * 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.
- */
- PUVM pUVM = pConsole->mpUVM = VMR3GetUVM(pVM);
- VMR3RetainUVM(pUVM);
- int vrc;
- try
- {
- vrc = pConsole->configConstructorInner(pVM, &alock);
- }
- catch (...)
- {
- vrc = VERR_UNEXPECTED_EXCEPTION;
- }
- if (RT_FAILURE(vrc))
- {
- pConsole->mpUVM = NULL;
- VMR3ReleaseUVM(pUVM);
- }
- return vrc;
- }
- /**
- * Worker for configConstructor.
- *
- * @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)
- {
- VMMDev *pVMMDev = m_pVMMDev;
- Assert(pVMMDev);
- ComPtr<IMachine> pMachine = machine();
- int rc;
- HRESULT hrc;
- Bstr bstr;
- #define H() AssertMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_GENERAL_FAILURE)
- /*
- * Get necessary objects and frequently used parameters.
- */
- ComPtr<IVirtualBox> virtualBox;
- hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H();
- ComPtr<IHost> host;
- hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H();
- ComPtr<ISystemProperties> systemProperties;
- hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); H();
- ComPtr<IBIOSSettings> biosSettings;
- hrc = pMachine->COMGETTER(BIOSSettings)(biosSettings.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();
- #if 0 /* enable to play with lots of memory. */
- if (RTEnvExist("VBOX_RAM_SIZE"))
- cRamMBs = RTStrToUInt64(RTEnvGet("VBOX_RAM_SIZE"));
- #endif
- uint64_t const cbRam = cRamMBs * (uint64_t)_1M;
- uint32_t cbRamHole = MM_RAM_HOLE_SIZE_DEFAULT;
- uint64_t uMcfgBase = 0;
- uint32_t cbMcfgLength = 0;
- ChipsetType_T chipsetType;
- hrc = pMachine->COMGETTER(ChipsetType)(&chipsetType); H();
- if (chipsetType == ChipsetType_ICH9)
- {
- /* We'd better have 0x10000000 region, to cover 256 buses
- but this put too much load on hypervisor heap */
- cbMcfgLength = 0x4000000; //0x10000000;
- cbRamHole += cbMcfgLength;
- uMcfgBase = _4G - cbRamHole;
- }
- BusAssignmentManager* BusMgr = mBusMgr = BusAssignmentManager::createInstance(chipsetType);
- ULONG cCpus = 1;
- hrc = pMachine->COMGETTER(CPUCount)(&cCpus); H();
- ULONG ulCpuExecutionCap = 100;
- hrc = pMachine->COMGETTER(CPUExecutionCap)(&ulCpuExecutionCap); H();
- Bstr osTypeId;
- hrc = pMachine->COMGETTER(OSTypeId)(osTypeId.asOutParam()); H();
- LogRel(("OS type: '%s'\n", Utf8Str(osTypeId).c_str()));
- BOOL fIOAPIC;
- hrc = biosSettings->COMGETTER(IOAPICEnabled)(&fIOAPIC); H();
- ComPtr<IGuestOSType> guestOSType;
- hrc = virtualBox->GetGuestOSType(osTypeId.raw(), guestOSType.asOutParam()); H();
- Bstr guestTypeFamilyId;
- hrc = guestOSType->COMGETTER(FamilyId)(guestTypeFamilyId.asOutParam()); H();
- BOOL fOsXGuest = guestTypeFamilyId == Bstr("MacOS");
- ULONG maxNetworkAdapters;
- hrc = systemProperties->GetMaxNetworkAdapters(chipsetType, &maxNetworkAdapters); H();
- /*
- * Get root node first.
- * This is the only node in the tree.
- */
- PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
- Assert(pRoot);
- // InsertConfigString throws
- try
- {
- /*
- * Set the root (and VMM) level values.
- */
- hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H();
- InsertConfigString(pRoot, "Name", bstr);
- InsertConfigBytes(pRoot, "UUID", &HardwareUuid, sizeof(HardwareUuid));
- InsertConfigInteger(pRoot, "RamSize", cbRam);
- InsertConfigInteger(pRoot, "RamHoleSize", cbRamHole);
- InsertConfigInteger(pRoot, "NumCPUs", cCpus);
- InsertConfigInteger(pRoot, "CpuExecutionCap", ulCpuExecutionCap);
- InsertConfigInteger(pRoot, "TimerMillies", 10);
- #ifdef VBOX_WITH_RAW_MODE
- InsertConfigInteger(pRoot, "RawR3Enabled", 1); /* boolean */
- InsertConfigInteger(pRoot, "RawR0Enabled", 1); /* boolean */
- /** @todo Config: RawR0, PATMEnabled and CSAMEnabled needs attention later. */
- InsertConfigInteger(pRoot, "PATMEnabled", 1); /* boolean */
- InsertConfigInteger(pRoot, "CSAMEnabled", 1); /* boolean */
- #endif
- /* Not necessary, but to make sure these two settings end up in the release log. */
- BOOL fPageFusion = FALSE;
- hrc = pMachine->COMGETTER(PageFusionEnabled)(&fPageFusion); H();
- InsertConfigInteger(pRoot, "PageFusion", fPageFusion); /* boolean */
- ULONG ulBalloonSize = 0;
- hrc = pMachine->COMGETTER(MemoryBalloonSize)(&ulBalloonSize); H();
- InsertConfigInteger(pRoot, "MemBalloonSize", ulBalloonSize);
- /*
- * CPUM values.
- */
- PCFGMNODE pCPUM;
- InsertConfigNode(pRoot, "CPUM", &pCPUM);
- /* cpuid leaf overrides. */
- static uint32_t const s_auCpuIdRanges[] =
- {
- UINT32_C(0x00000000), UINT32_C(0x0000000a),
- UINT32_C(0x80000000), UINT32_C(0x8000000a)
- };
- for (unsigned i = 0; i < RT_ELEMENTS(s_auCpuIdRanges); i += 2)
- for (uint32_t uLeaf = s_auCpuIdRanges[i]; uLeaf < s_auCpuIdRanges[i + 1]; uLeaf++)
- {
- ULONG ulEax, ulEbx, ulEcx, ulEdx;
- hrc = pMachine->GetCPUIDLeaf(uLeaf, &ulEax, &ulEbx, &ulEcx, &ulEdx);
- if (SUCCEEDED(hrc))
- {
- PCFGMNODE pLeaf;
- InsertConfigNode(pCPUM, Utf8StrFmt("HostCPUID/%RX32", uLeaf).c_str(), &pLeaf);
- InsertConfigInteger(pLeaf, "eax", ulEax);
- InsertConfigInteger(pLeaf, "ebx", ulEbx);
- InsertConfigInteger(pLeaf, "ecx", ulEcx);
- InsertConfigInteger(pLeaf, "edx", ulEdx);
- }
- 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"));
- InsertConfigInteger(pCPUM, "NT4LeafLimit", true);
- }
- /* Expose extended MWAIT features to Mac OS X guests. */
- if (fOsXGuest)
- {
- LogRel(("Using MWAIT extensions\n"));
- InsertConfigInteger(pCPUM, "MWaitExtensions", true);
- }
- /*
- * Hardware virtualization extensions.
- */
- BOOL fHWVirtExEnabled;
- BOOL fHwVirtExtForced = false;
- #ifdef VBOX_WITH_RAW_MODE
- hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Enabled, &fHWVirtExEnabled); H();
- if (cCpus > 1) /** @todo SMP: This isn't nice, but things won't work on mac otherwise. */
- fHWVirtExEnabled = TRUE;
- # ifdef RT_OS_DARWIN
- fHwVirtExtForced = fHWVirtExEnabled;
- # else
- /* - 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. */
- fHwVirtExtForced = fHWVirtExEnabled
- && ( cbRam + cbRamHole > _4G
- || cCpus > 1);
- # endif
- #else /* !VBOX_WITH_RAW_MODE */
- fHWVirtExEnabled = fHwVirtExtForced = true;
- #endif /* !VBOX_WITH_RAW_MODE */
- /* only honor the property value if there was no other reason to enable it */
- if (!fHwVirtExtForced)
- {
- hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Force, &fHwVirtExtForced); H();
- }
- InsertConfigInteger(pRoot, "HwVirtExtForced", fHwVirtExtForced);
- /*
- * MM values.
- */
- PCFGMNODE pMM;
- InsertConfigNode(pRoot, "MM", &pMM);
- InsertConfigInteger(pMM, "CanUseLargerHeap", chipsetType == ChipsetType_ICH9);
- /*
- * Hardware virtualization settings.
- */
- BOOL fIsGuest64Bit = false;
- PCFGMNODE pHWVirtExt;
- InsertConfigNode(pRoot, "HWVirtExt", &pHWVirtExt);
- if (fHWVirtExEnabled)
- {
- InsertConfigInteger(pHWVirtExt, "Enabled", 1);
- /* Indicate whether 64-bit guests are supported or not. */
- /** @todo This is currently only forced off on 32-bit hosts only because it
- * makes a lof of difference there (REM and Solaris performance).
- */
- BOOL fSupportsLongMode = false;
- hrc = host->GetProcessorFeature(ProcessorFeature_LongMode,
- &fSupportsLongMode); H();
- hrc = guestOSType->COMGETTER(Is64Bit)(&fIsGuest64Bit); H();
- if (fSupportsLongMode && fIsGuest64Bit)
- {
- InsertConfigInteger(pHWVirtExt, "64bitEnabled", 1);
- #if ARCH_BITS == 32 /* The recompiler must use VBoxREM64 (32-bit host only). */
- PCFGMNODE pREM;
- InsertConfigNode(pRoot, "REM", &pREM);
- InsertConfigInteger(pREM, "64bitEnabled", 1);
- #endif
- }
- #if ARCH_BITS == 32 /* 32-bit guests only. */
- else
- {
- InsertConfigInteger(pHWVirtExt, "64bitEnabled", 0);
- }
- #endif
- /** @todo Not exactly pretty to check strings; VBOXOSTYPE would be better, but that requires quite a bit of API change in Main. */
- if ( !fIsGuest64Bit
- && 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.
- */
- InsertConfigInteger(pHWVirtExt, "TPRPatchingEnabled", 1);
- }
- }
- /* HWVirtEx exclusive mode */
- BOOL fHWVirtExExclusive = true;
- hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Exclusive, &fHWVirtExExclusive); H();
- InsertConfigInteger(pHWVirtExt, "Exclusive", fHWVirtExExclusive);
- /* Nested paging (VT-x/AMD-V) */
- BOOL fEnableNestedPaging = false;
- hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_NestedPaging, &fEnableNestedPaging); H();
- InsertConfigInteger(pHWVirtExt, "EnableNestedPaging", fEnableNestedPaging);
- /* Large pages; requires nested paging */
- BOOL fEnableLargePages = false;
- hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_LargePages, &fEnableLargePages); H();
- InsertConfigInteger(pHWVirtExt, "EnableLargePages", fEnableLargePages);
- /* VPID (VT-x) */
- BOOL fEnableVPID = false;
- hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_VPID, &fEnableVPID); H();
- InsertConfigInteger(pHWVirtExt, "EnableVPID", fEnableVPID);
- /* Physical Address Extension (PAE) */
- BOOL fEnablePAE = false;
- hrc = pMachine->GetCPUProperty(CPUPropertyType_PAE, &fEnablePAE); H();
- InsertConfigInteger(pRoot, "EnablePAE", fEnablePAE);
- /* Synthetic CPU */
- BOOL fSyntheticCpu = false;
- hrc = pMachine->GetCPUProperty(CPUPropertyType_Synthetic, &fSyntheticCpu); H();
- InsertConfigInteger(pCPUM, "SyntheticCpu", fSyntheticCpu);
- if (fOsXGuest)
- InsertConfigInteger(pCPUM, "EnableHVP", 1);
- BOOL fPXEDebug;
- hrc = biosSettings->COMGETTER(PXEDebugEnabled)(&fPXEDebug); H();
- /*
- * PDM config.
- * Load drivers in VBoxC.[so|dll]
- */
- PCFGMNODE pPDM;
- PCFGMNODE pNode;
- PCFGMNODE pMod;
- InsertConfigNode(pRoot, "PDM", &pPDM);
- InsertConfigNode(pPDM, "Devices", &pNode);
- InsertConfigNode(pPDM, "Drivers", &pNode);
- InsertConfigNode(pNode, "VBoxC", &pMod);
- #ifdef VBOX_WITH_XPCOM
- // VBoxC is located in the components subdirectory
- char szPathVBoxC[RTPATH_MAX];
- rc = RTPathAppPrivateArch(szPathVBoxC, RTPATH_MAX - sizeof("/components/VBoxC")); AssertRC(rc);
- strcat(szPathVBoxC, "/components/VBoxC");
- InsertConfigString(pMod, "Path", szPathVBoxC);
- #else
- InsertConfigString(pMod, "Path", "VBoxC");
- #endif
- /*
- * Block cache settings.
- */
- PCFGMNODE pPDMBlkCache;
- InsertConfigNode(pPDM, "BlkCache", &pPDMBlkCache);
- /* I/O cache size */
- ULONG ioCacheSize = 5;
- hrc = pMachine->COMGETTER(IOCacheSize)(&ioCacheSize); H();
- InsertConfigInteger(pPDMBlkCache, "CacheSize", ioCacheSize * _1M);
- /*
- * Bandwidth groups.
- */
- PCFGMNODE pAc;
- PCFGMNODE pAcFile;
- PCFGMNODE pAcFileBwGroups;
- ComPtr<IBandwidthControl> bwCtrl;
- com::SafeIfaceArray<IBandwidthGroup> bwGroups;
- hrc = pMachine->COMGETTER(BandwidthControl)(bwCtrl.asOutParam()); H();
- hrc = bwCtrl->GetAllBandwidthGroups(ComSafeArrayAsOutParam(bwGroups)); H();
- InsertConfigNode(pPDM, "AsyncCompletion", &pAc);
- InsertConfigNode(pAc, "File", &pAcFile);
- InsertConfigNode(pAcFile, "BwGroups", &pAcFileBwGroups);
- #ifdef VBOX_WITH_NETSHAPER
- PCFGMNODE pNetworkShaper;
- PCFGMNODE pNetworkBwGroups;
- InsertConfigNode(pPDM, "NetworkShaper", &pNetworkShaper);
- InsertConfigNode(pNetworkShaper, "BwGroups", &pNetworkBwGroups);
- #endif /* VBOX_WITH_NETSHAPER */
- for (size_t i = 0; i < bwGroups.size(); i++)
- {
- Bstr strName;
- LONG64 cMaxBytesPerSec;
- BandwidthGroupType_T enmType;
- hrc = bwGroups[i]->COMGETTER(Name)(strName.asOutParam()); H();
- hrc = bwGroups[i]->COMGETTER(Type)(&enmType); H();
- hrc = bwGroups[i]->COMGETTER(MaxBytesPerSec)(&cMaxBytesPerSec); H();
- if (enmType == BandwidthGroupType_Disk)
- {
- PCFGMNODE pBwGroup;
- InsertConfigNode(pAcFileBwGroups, Utf8Str(strName).c_str(), &pBwGroup);
- InsertConfigInteger(pBwGroup, "Max", cMaxBytesPerSec);
- InsertConfigInteger(pBwGroup, "Start", cMaxBytesPerSec);
- InsertConfigInteger(pBwGroup, "Step", 0);
- }
- #ifdef VBOX_WITH_NETSHAPER
- else if (enmType == BandwidthGroupType_Network)
- {
- /* Network bandwidth groups. */
- PCFGMNODE pBwGroup;
- InsertConfigNode(pNetworkBwGroups, Utf8Str(strName).c_str(), &pBwGroup);
- InsertConfigInteger(pBwGroup, "Max", cMaxBytesPerSec);
- }
- #endif /* VBOX_WITH_NETSHAPER */
- }
- /*
- * Devices
- */
- PCFGMNODE pDevices = NULL; /* /Devices */
- PCFGMNODE pDev = NULL; /* /Devices/Dev/ */
- PCFGMNODE pInst = NULL; /* /Devices/Dev/0/ */
- PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */
- PCFGMNODE pLunL0 = NULL; /* /Devices/Dev/0/LUN#0/ */
- PCFGMNODE pLunL1 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/ */
- PCFGMNODE pLunL2 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/Config/ */
- PCFGMNODE pBiosCfg = NULL; /* /Devices/pcbios/0/Config/ */
- PCFGMNODE pNetBootCfg = NULL; /* /Devices/pcbios/0/Config/NetBoot/ */
- InsertConfigNode(pRoot, "Devices", &pDevices);
- /*
- * PC Arch.
- */
- InsertConfigNode(pDevices, "pcarch", &pDev);
- InsertConfigNode(pDev, "0", &pInst);
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- InsertConfigNode(pInst, "Config", &pCfg);
- /*
- * The time offset
- */
- LONG64 timeOffset;
- hrc = biosSettings->COMGETTER(TimeOffset)(&timeOffset); H();
- PCFGMNODE pTMNode;
- InsertConfigNode(pRoot, "TM", &pTMNode);
- InsertConfigInteger(pTMNode, "UTCOffset", timeOffset * 1000000);
- /*
- * DMA
- */
- InsertConfigNode(pDevices, "8237A", &pDev);
- InsertConfigNode(pDev, "0", &pInst);
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- /*
- * PCI buses.
- */
- uint32_t uIocPCIAddress, uHbcPCIAddress;
- switch (chipsetType)
- {
- default:
- Assert(false);
- case ChipsetType_PIIX3:
- InsertConfigNode(pDevices, "pci", &pDev);
- uHbcPCIAddress = (0x0 << 16) | 0;
- uIocPCIAddress = (0x1 << 16) | 0; // ISA controller
- break;
- case ChipsetType_ICH9:
- InsertConfigNode(pDevices, "ich9pci", &pDev);
- uHbcPCIAddress = (0x1e << 16) | 0;
- uIocPCIAddress = (0x1f << 16) | 0; // LPC controller
- break;
- }
- InsertConfigNode(pDev, "0", &pInst);
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- InsertConfigNode(pInst, "Config", &pCfg);
- InsertConfigInteger(pCfg, "IOAPIC", fIOAPIC);
- if (chipsetType == ChipsetType_ICH9)
- {
- /* Provide MCFG info */
- InsertConfigInteger(pCfg, "McfgBase", uMcfgBase);
- InsertConfigInteger(pCfg, "McfgLength", cbMcfgLength);
- /* And register 2 bridges */
- InsertConfigNode(pDevices, "ich9pcibridge", &pDev);
- InsertConfigNode(pDev, "0", &pInst);
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- hrc = BusMgr->assignPCIDevice("ich9pcibridge", pInst); H();
- InsertConfigNode(pDev, "1", &pInst);
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- hrc = BusMgr->assignPCIDevice("ich9pcibridge", pInst); H();
- #ifdef VBOX_WITH_PCI_PASSTHROUGH
- /* Add PCI passthrough devices */
- hrc = attachRawPCIDevices(pVM, BusMgr, pDevices); H();
- #endif
- }
- /*
- * Enable the following devices: HPET, SMC and LPC on MacOS X guests or on ICH9 chipset
- */
- /*
- * High Precision Event Timer (HPET)
- */
- BOOL fHPETEnabled;
- /* Other guests may wish to use HPET too, but MacOS X not functional without it */
- hrc = pMachine->COMGETTER(HPETEnabled)(&fHPETEnabled); H();
- /* so always enable HPET in extended profile */
- fHPETEnabled |= fOsXGuest;
- /* HPET is always present on ICH9 */
- fHPETEnabled |= (chipsetType == ChipsetType_ICH9);
- if (fHPETEnabled)
- {
- 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 */
- }
- /*
- * System Management Controller (SMC)
- */
- BOOL fSmcEnabled;
- fSmcEnabled = fOsXGuest;
- if (fSmcEnabled)
- {
- InsertConfigNode(pDevices, "smc", &pDev);
- InsertConfigNode(pDev, "0", &pInst);
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- InsertConfigNode(pInst, "Config", &pCfg);
- bool fGetKeyFromRealSMC;
- Bstr bstrKey;
- rc = getSmcDeviceKey(pMachine, bstrKey.asOutParam(), &fGetKeyFromRealSMC);
- AssertRCReturn(rc, rc);
- InsertConfigString(pCfg, "DeviceKey", bstrKey);
- InsertConfigInteger(pCfg, "GetKeyFromRealSMC", fGetKeyFromRealSMC);
- }
- /*
- * Low Pin Count (LPC) bus
- */
- BOOL fLpcEnabled;
- /** @todo: implement appropriate getter */
- fLpcEnabled = fOsXGuest || (chipsetType == ChipsetType_ICH9);
- if (fLpcEnabled)
- {
- InsertConfigNode(pDevices, "lpc", &pDev);
- InsertConfigNode(pDev, "0", &pInst);
- hrc = BusMgr->assignPCIDevice("lpc", pInst); H();
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- }
- BOOL fShowRtc;
- fShowRtc = fOsXGuest || (chipsetType == ChipsetType_ICH9);
- /*
- * PS/2 keyboard & mouse.
- */
- InsertConfigNode(pDevices, "pckbd", &pDev);
- InsertConfigNode(pDev, "0", &pInst);
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- InsertConfigNode(pInst, "Config", &pCfg);
- InsertConfigNode(pInst, "LUN#0", &pLunL0);
- InsertConfigString(pLunL0, "Driver", "KeyboardQueue");
- InsertConfigNode(pLunL0, "Config", &pCfg);
- InsertConfigInteger(pCfg, "QueueSize", 64);
- InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
- InsertConfigString(pLunL1, "Driver", "MainKeyboard");
- InsertConfigNode(pLunL1, "Config", &pCfg);
- Keyboard *pKeyboard = mKeyboard;
- InsertConfigInteger(pCfg, "Object", (uintptr_t)pKeyboard);
- InsertConfigNode(pInst, "LUN#1", &pLunL0);
- InsertConfigString(pLunL0, "Driver", "MouseQueue");
- InsertConfigNode(pLunL0, "Config", &pCfg);
- InsertConfigInteger(pCfg, "QueueSize", 128);
- InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
- InsertConfigString(pLunL1, "Driver", "MainMouse");
- InsertConfigNode(pLunL1, "Config", &pCfg);
- Mouse *pMouse = mMouse;
- InsertConfigInteger(pCfg, "Object", (uintptr_t)pMouse);
- /*
- * i8254 Programmable Interval Timer And Dummy Speaker
- */
- InsertConfigNode(pDevices, "i8254", &pDev);
- InsertConfigNode(pDev, "0", &pInst);
- InsertConfigNode(pInst, "Config", &pCfg);
- #ifdef DEBUG
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- #endif
- /*
- * i8259 Programmable Interrupt Controller.
- */
- InsertConfigNode(pDevices, "i8259", &pDev);
- InsertConfigNode(pDev, "0", &pInst);
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- InsertConfigNode(pInst, "Config", &pCfg);
- /*
- * Advanced Programmable Interrupt Controller.
- * SMP: Each CPU has a LAPIC, but we have a single device representing all LAPICs states,
- * thus only single insert
- */
- InsertConfigNode(pDevices, "apic", &pDev);
- InsertConfigNode(pDev, "0", &pInst);
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- InsertConfigNode(pInst, "Config", &pCfg);
- InsertConfigInteger(pCfg, "IOAPIC", fIOAPIC);
- InsertConfigInteger(pCfg, "NumCPUs", cCpus);
- if (fIOAPIC)
- {
- /*
- * I/O Advanced Programmable Interrupt Controller.
- */
- InsertConfigNode(pDevices, "ioapic", &pDev);
- InsertConfigNode(pDev, "0", &pInst);
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- InsertConfigNode(pInst, "Config", &pCfg);
- InsertConfigInteger(pCfg, "NumCPUs", cCpus);
- }
- /*
- * RTC MC146818.
- */
- InsertConfigNode(pDevices, "mc146818", &pDev);
- InsertConfigNode(pDev, "0", &pInst);
- InsertConfigNode(pInst, "Config", &pCfg);
- BOOL fRTCUseUTC;
- hrc = pMachine->COMGETTER(RTCUseUTC)(&fRTCUseUTC); H();
- InsertConfigInteger(pCfg, "UseUTC", fRTCUseUTC ? 1 : 0);
- /*
- * VGA.
- */
- InsertConfigNode(pDevices, "vga", &pDev);
- InsertConfigNode(pDev, "0", &pInst);
- InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
- hrc = BusMgr->assignPCIDevice("vga", pInst); H();
- InsertConfigNode(pInst, "Config", &pCfg);
- ULONG cVRamMBs;
- hrc = pMachine->COMGETTER(VRAMSize)(&cVRamMBs); H();
- InsertConfigInteger(pCfg, "VRamSize", cVRamMBs * _1M);
- ULONG cMonitorCount;
- hrc = pMachine->COMGETTER(MonitorCount)(&cMonitorCount); H();
- InsertConfigInteger(pCfg, "MonitorCount", cMonitorCount);
- #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
- InsertConfigInteger(pCfg, "R0Enabled", fHWVirtExEnabled);
- #endif
- /*
- * BIOS logo
- */
- BOOL fFadeIn;
- hrc = biosSettings->COMGETTER(LogoFadeIn)(&fFadeIn); H();
- InsertConfigInteger(pCfg, "FadeIn", fFadeIn ? 1 : 0);
- BOOL fFadeOut;
- hrc = biosSettings->COMGETTER(LogoFadeOut)(&fFadeOut); H();
- InsertConfigInteger(pCfg, "FadeOut", fFadeOut ? 1: 0);
- ULONG logoDisplayTime;
- hrc = biosSettings->COMGETTER(LogoDisplayTime)(&logoDisplayTime); H();
- InsertConfigInteger(pCfg, "LogoTime", logoDisplayTime);
- Bstr logoImagePath;
- hrc = biosSettings->COMGETTER(LogoImagePath)(logoImagePath.asOutParam()); H();
- InsertConfigString(pCfg, "LogoFile", Utf8Str(!logoImagePath.isEmpty() ? logoImagePath : "") );
- /*
- * Boot menu
- */
- BIOSBootMenuMode_T eBootMenuMode;
- int iShowBootMenu;
- biosSettings->COMGETTER(BootMenuMode)(&eBootMenuMode);
- switch (eBootMenuMode)
- {
- case BIOSBootMenuMode_Disabled: iShowBootMenu = 0; break;
- case BIOSBootMenuMode_MenuOnly: iShowBootMenu = 1; break;
- default: iShowBootMenu = 2; break;
- }
- InsertConfigInteger(pCfg, "ShowBootMenu", iShowBootMenu);
- /* Custom VESA mode list */
- unsigned cModes = 0;
- for (unsigned iMode = 1; iMode <= 16; ++iMode)
- {
- char szExtraDataKey[sizeof("CustomVideoModeXX")];
- RTStrPrintf(szExtraDataKey, sizeof(szExtraDataKey), "CustomVideoMode%u", iMode);
- hrc = pMachine->GetExtraData(Bstr(szExtraDataKey).raw(), bstr.asOutParam()); H();
- if (bstr.isEmpty())
- break;
- InsertConfigString(pCfg, szExtraDataKey, bstr);
- ++cModes;
- }
- InsertConfigInteger(pCfg, "CustomVideoModes", cModes);
- /* VESA height reduction */
- ULONG ulHeightR…
Large files files are truncated, but you can click here to view the full file