PageRenderTime 68ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/src/VBox/Main/src-client/ConsoleImpl2.cpp

https://bitbucket.org/diagiman/vbox-trunk
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

  1. /* $Id$ */
  2. /** @file
  3. * VBox Console COM Class implementation - VM Configuration Bits.
  4. *
  5. * @remark We've split out the code that the 64-bit VC++ v8 compiler finds
  6. * problematic to optimize so we can disable optimizations and later,
  7. * perhaps, find a real solution for it (like rewriting the code and
  8. * to stop resemble a tonne of spaghetti).
  9. */
  10. /*
  11. * Copyright (C) 2006-2012 Oracle Corporation
  12. *
  13. * This file is part of VirtualBox Open Source Edition (OSE), as
  14. * available from http://www.virtualbox.org. This file is free software;
  15. * you can redistribute it and/or modify it under the terms of the GNU
  16. * General Public License (GPL) as published by the Free Software
  17. * Foundation, in version 2 as it comes in the "COPYING" file of the
  18. * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
  19. * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
  20. */
  21. /*******************************************************************************
  22. * Header Files *
  23. *******************************************************************************/
  24. // for some reason Windows burns in sdk\...\winsock.h if this isn't included first
  25. #include "VBox/com/ptr.h"
  26. #include "ConsoleImpl.h"
  27. #include "DisplayImpl.h"
  28. #ifdef VBOX_WITH_GUEST_CONTROL
  29. # include "GuestImpl.h"
  30. #endif
  31. #ifdef VBOX_WITH_DRAG_AND_DROP
  32. # include "GuestDnDImpl.h"
  33. #endif
  34. #include "VMMDev.h"
  35. #include "Global.h"
  36. #ifdef VBOX_WITH_PCI_PASSTHROUGH
  37. # include "PCIRawDevImpl.h"
  38. #endif
  39. // generated header
  40. #include "SchemaDefs.h"
  41. #include "AutoCaller.h"
  42. #include "Logging.h"
  43. #include <iprt/buildconfig.h>
  44. #include <iprt/ctype.h>
  45. #include <iprt/dir.h>
  46. #include <iprt/file.h>
  47. #include <iprt/param.h>
  48. #include <iprt/path.h>
  49. #include <iprt/string.h>
  50. #include <iprt/system.h>
  51. #include <iprt/cpp/exception.h>
  52. #if 0 /* enable to play with lots of memory. */
  53. # include <iprt/env.h>
  54. #endif
  55. #include <iprt/stream.h>
  56. #include <VBox/vmm/vmapi.h>
  57. #include <VBox/err.h>
  58. #include <VBox/param.h>
  59. #include <VBox/vmm/pdmapi.h> /* For PDMR3DriverAttach/PDMR3DriverDetach */
  60. #include <VBox/version.h>
  61. #include <VBox/HostServices/VBoxClipboardSvc.h>
  62. #ifdef VBOX_WITH_CROGL
  63. # include <VBox/HostServices/VBoxCrOpenGLSvc.h>
  64. #include <VBox/VBoxOGLTest.h>
  65. #endif
  66. #ifdef VBOX_WITH_GUEST_PROPS
  67. # include <VBox/HostServices/GuestPropertySvc.h>
  68. # include <VBox/com/defs.h>
  69. # include <VBox/com/array.h>
  70. # include "HGCM.h" /** @todo it should be possible to register a service
  71. * extension using a VMMDev callback. */
  72. # include <vector>
  73. #endif /* VBOX_WITH_GUEST_PROPS */
  74. #include <VBox/intnet.h>
  75. #include <VBox/com/com.h>
  76. #include <VBox/com/string.h>
  77. #include <VBox/com/array.h>
  78. #ifdef VBOX_WITH_NETFLT
  79. # if defined(RT_OS_SOLARIS)
  80. # include <zone.h>
  81. # elif defined(RT_OS_LINUX)
  82. # include <unistd.h>
  83. # include <sys/ioctl.h>
  84. # include <sys/socket.h>
  85. # include <linux/types.h>
  86. # include <linux/if.h>
  87. # include <linux/wireless.h>
  88. # elif defined(RT_OS_FREEBSD)
  89. # include <unistd.h>
  90. # include <sys/types.h>
  91. # include <sys/ioctl.h>
  92. # include <sys/socket.h>
  93. # include <net/if.h>
  94. # include <net80211/ieee80211_ioctl.h>
  95. # endif
  96. # if defined(RT_OS_WINDOWS)
  97. # include <VBox/VBoxNetCfg-win.h>
  98. # include <Ntddndis.h>
  99. # include <devguid.h>
  100. # else
  101. # include <HostNetworkInterfaceImpl.h>
  102. # include <netif.h>
  103. # include <stdlib.h>
  104. # endif
  105. #endif /* VBOX_WITH_NETFLT */
  106. #include "DHCPServerRunner.h"
  107. #include "BusAssignmentManager.h"
  108. #ifdef VBOX_WITH_EXTPACK
  109. # include "ExtPackManagerImpl.h"
  110. #endif
  111. #if defined(RT_OS_DARWIN)
  112. # include "IOKit/IOKitLib.h"
  113. static int DarwinSmcKey(char *pabKey, uint32_t cbKey)
  114. {
  115. /*
  116. * Method as described in Amit Singh's article:
  117. * http://osxbook.com/book/bonus/chapter7/tpmdrmmyth/
  118. */
  119. typedef struct
  120. {
  121. uint32_t key;
  122. uint8_t pad0[22];
  123. uint32_t datasize;
  124. uint8_t pad1[10];
  125. uint8_t cmd;
  126. uint32_t pad2;
  127. uint8_t data[32];
  128. } AppleSMCBuffer;
  129. AssertReturn(cbKey >= 65, VERR_INTERNAL_ERROR);
  130. io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault,
  131. IOServiceMatching("AppleSMC"));
  132. if (!service)
  133. return VERR_NOT_FOUND;
  134. io_connect_t port = (io_connect_t)0;
  135. kern_return_t kr = IOServiceOpen(service, mach_task_self(), 0, &port);
  136. IOObjectRelease(service);
  137. if (kr != kIOReturnSuccess)
  138. return RTErrConvertFromDarwin(kr);
  139. AppleSMCBuffer inputStruct = { 0, {0}, 32, {0}, 5, };
  140. AppleSMCBuffer outputStruct;
  141. size_t cbOutputStruct = sizeof(outputStruct);
  142. for (int i = 0; i < 2; i++)
  143. {
  144. inputStruct.key = (uint32_t)((i == 0) ? 'OSK0' : 'OSK1');
  145. kr = IOConnectCallStructMethod((mach_port_t)port,
  146. (uint32_t)2,
  147. (const void *)&inputStruct,
  148. sizeof(inputStruct),
  149. (void *)&outputStruct,
  150. &cbOutputStruct);
  151. if (kr != kIOReturnSuccess)
  152. {
  153. IOServiceClose(port);
  154. return RTErrConvertFromDarwin(kr);
  155. }
  156. for (int j = 0; j < 32; j++)
  157. pabKey[j + i*32] = outputStruct.data[j];
  158. }
  159. IOServiceClose(port);
  160. pabKey[64] = 0;
  161. return VINF_SUCCESS;
  162. }
  163. #endif /* RT_OS_DARWIN */
  164. /* Darwin compile kludge */
  165. #undef PVM
  166. /* Comment out the following line to remove VMWare compatibility hack. */
  167. #define VMWARE_NET_IN_SLOT_11
  168. /**
  169. * Translate IDE StorageControllerType_T to string representation.
  170. */
  171. const char* controllerString(StorageControllerType_T enmType)
  172. {
  173. switch (enmType)
  174. {
  175. case StorageControllerType_PIIX3:
  176. return "PIIX3";
  177. case StorageControllerType_PIIX4:
  178. return "PIIX4";
  179. case StorageControllerType_ICH6:
  180. return "ICH6";
  181. default:
  182. return "Unknown";
  183. }
  184. }
  185. /**
  186. * Simple class for storing network boot information.
  187. */
  188. struct BootNic
  189. {
  190. ULONG mInstance;
  191. PCIBusAddress mPCIAddress;
  192. ULONG mBootPrio;
  193. bool operator < (const BootNic &rhs) const
  194. {
  195. ULONG lval = mBootPrio - 1; /* 0 will wrap around and get the lowest priority. */
  196. ULONG rval = rhs.mBootPrio - 1;
  197. return lval < rval; /* Zero compares as highest number (lowest prio). */
  198. }
  199. };
  200. static int findEfiRom(IVirtualBox* vbox, FirmwareType_T aFirmwareType, Utf8Str *pEfiRomFile)
  201. {
  202. Bstr aFilePath, empty;
  203. BOOL fPresent = FALSE;
  204. HRESULT hrc = vbox->CheckFirmwarePresent(aFirmwareType, empty.raw(),
  205. empty.asOutParam(), aFilePath.asOutParam(), &fPresent);
  206. AssertComRCReturn(hrc, Global::vboxStatusCodeFromCOM(hrc));
  207. if (!fPresent)
  208. {
  209. LogRel(("Failed to find an EFI ROM file.\n"));
  210. return VERR_FILE_NOT_FOUND;
  211. }
  212. *pEfiRomFile = Utf8Str(aFilePath);
  213. return VINF_SUCCESS;
  214. }
  215. static int getSmcDeviceKey(IMachine *pMachine, BSTR *aKey, bool *pfGetKeyFromRealSMC)
  216. {
  217. *pfGetKeyFromRealSMC = false;
  218. /*
  219. * The extra data takes precedence (if non-zero).
  220. */
  221. HRESULT hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/SmcDeviceKey").raw(),
  222. aKey);
  223. if (FAILED(hrc))
  224. return Global::vboxStatusCodeFromCOM(hrc);
  225. if ( SUCCEEDED(hrc)
  226. && *aKey
  227. && **aKey)
  228. return VINF_SUCCESS;
  229. #ifdef RT_OS_DARWIN
  230. /*
  231. * Query it here and now.
  232. */
  233. char abKeyBuf[65];
  234. int rc = DarwinSmcKey(abKeyBuf, sizeof(abKeyBuf));
  235. if (SUCCEEDED(rc))
  236. {
  237. Bstr(abKeyBuf).detachTo(aKey);
  238. return rc;
  239. }
  240. LogRel(("Warning: DarwinSmcKey failed with rc=%Rrc!\n", rc));
  241. #else
  242. /*
  243. * Is it apple hardware in bootcamp?
  244. */
  245. /** @todo implement + test RTSYSDMISTR_MANUFACTURER on all hosts.
  246. * Currently falling back on the product name. */
  247. char szManufacturer[256];
  248. szManufacturer[0] = '\0';
  249. RTSystemQueryDmiString(RTSYSDMISTR_MANUFACTURER, szManufacturer, sizeof(szManufacturer));
  250. if (szManufacturer[0] != '\0')
  251. {
  252. if ( !strcmp(szManufacturer, "Apple Computer, Inc.")
  253. || !strcmp(szManufacturer, "Apple Inc.")
  254. )
  255. *pfGetKeyFromRealSMC = true;
  256. }
  257. else
  258. {
  259. char szProdName[256];
  260. szProdName[0] = '\0';
  261. RTSystemQueryDmiString(RTSYSDMISTR_PRODUCT_NAME, szProdName, sizeof(szProdName));
  262. if ( ( !strncmp(szProdName, "Mac", 3)
  263. || !strncmp(szProdName, "iMac", 4)
  264. || !strncmp(szProdName, "iMac", 4)
  265. || !strncmp(szProdName, "Xserve", 6)
  266. )
  267. && !strchr(szProdName, ' ') /* no spaces */
  268. && RT_C_IS_DIGIT(szProdName[strlen(szProdName) - 1]) /* version number */
  269. )
  270. *pfGetKeyFromRealSMC = true;
  271. }
  272. int rc = VINF_SUCCESS;
  273. #endif
  274. return rc;
  275. }
  276. /*
  277. * VC++ 8 / amd64 has some serious trouble with the next functions.
  278. * As a temporary measure, we'll drop global optimizations.
  279. */
  280. #if defined(_MSC_VER) && defined(RT_ARCH_AMD64)
  281. # pragma optimize("g", off)
  282. #endif
  283. static const char *const g_apszIDEDrives[4] =
  284. { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" };
  285. class ConfigError : public RTCError
  286. {
  287. public:
  288. ConfigError(const char *pcszFunction,
  289. int vrc,
  290. const char *pcszName)
  291. : RTCError(Utf8StrFmt("%s failed: rc=%Rrc, pcszName=%s", pcszFunction, vrc, pcszName)),
  292. m_vrc(vrc)
  293. {
  294. AssertMsgFailed(("%s\n", what())); // in strict mode, hit a breakpoint here
  295. }
  296. int m_vrc;
  297. };
  298. /**
  299. * Helper that calls CFGMR3InsertString and throws an RTCError if that
  300. * fails (C-string variant).
  301. * @param pParent See CFGMR3InsertStringN.
  302. * @param pcszNodeName See CFGMR3InsertStringN.
  303. * @param pcszValue The string value.
  304. */
  305. static void InsertConfigString(PCFGMNODE pNode,
  306. const char *pcszName,
  307. const char *pcszValue)
  308. {
  309. int vrc = CFGMR3InsertString(pNode,
  310. pcszName,
  311. pcszValue);
  312. if (RT_FAILURE(vrc))
  313. throw ConfigError("CFGMR3InsertString", vrc, pcszName);
  314. }
  315. /**
  316. * Helper that calls CFGMR3InsertString and throws an RTCError if that
  317. * fails (Utf8Str variant).
  318. * @param pParent See CFGMR3InsertStringN.
  319. * @param pcszNodeName See CFGMR3InsertStringN.
  320. * @param rStrValue The string value.
  321. */
  322. static void InsertConfigString(PCFGMNODE pNode,
  323. const char *pcszName,
  324. const Utf8Str &rStrValue)
  325. {
  326. int vrc = CFGMR3InsertStringN(pNode,
  327. pcszName,
  328. rStrValue.c_str(),
  329. rStrValue.length());
  330. if (RT_FAILURE(vrc))
  331. throw ConfigError("CFGMR3InsertStringLengthKnown", vrc, pcszName);
  332. }
  333. /**
  334. * Helper that calls CFGMR3InsertString and throws an RTCError if that
  335. * fails (Bstr variant).
  336. *
  337. * @param pParent See CFGMR3InsertStringN.
  338. * @param pcszNodeName See CFGMR3InsertStringN.
  339. * @param rBstrValue The string value.
  340. */
  341. static void InsertConfigString(PCFGMNODE pNode,
  342. const char *pcszName,
  343. const Bstr &rBstrValue)
  344. {
  345. InsertConfigString(pNode, pcszName, Utf8Str(rBstrValue));
  346. }
  347. /**
  348. * Helper that calls CFGMR3InsertBytes and throws an RTCError if that fails.
  349. *
  350. * @param pNode See CFGMR3InsertBytes.
  351. * @param pcszName See CFGMR3InsertBytes.
  352. * @param pvBytes See CFGMR3InsertBytes.
  353. * @param cbBytes See CFGMR3InsertBytes.
  354. */
  355. static void InsertConfigBytes(PCFGMNODE pNode,
  356. const char *pcszName,
  357. const void *pvBytes,
  358. size_t cbBytes)
  359. {
  360. int vrc = CFGMR3InsertBytes(pNode,
  361. pcszName,
  362. pvBytes,
  363. cbBytes);
  364. if (RT_FAILURE(vrc))
  365. throw ConfigError("CFGMR3InsertBytes", vrc, pcszName);
  366. }
  367. /**
  368. * Helper that calls CFGMR3InsertInteger and throws an RTCError if that
  369. * fails.
  370. *
  371. * @param pNode See CFGMR3InsertInteger.
  372. * @param pcszName See CFGMR3InsertInteger.
  373. * @param u64Integer See CFGMR3InsertInteger.
  374. */
  375. static void InsertConfigInteger(PCFGMNODE pNode,
  376. const char *pcszName,
  377. uint64_t u64Integer)
  378. {
  379. int vrc = CFGMR3InsertInteger(pNode,
  380. pcszName,
  381. u64Integer);
  382. if (RT_FAILURE(vrc))
  383. throw ConfigError("CFGMR3InsertInteger", vrc, pcszName);
  384. }
  385. /**
  386. * Helper that calls CFGMR3InsertNode and throws an RTCError if that fails.
  387. *
  388. * @param pNode See CFGMR3InsertNode.
  389. * @param pcszName See CFGMR3InsertNode.
  390. * @param ppChild See CFGMR3InsertNode.
  391. */
  392. static void InsertConfigNode(PCFGMNODE pNode,
  393. const char *pcszName,
  394. PCFGMNODE *ppChild)
  395. {
  396. int vrc = CFGMR3InsertNode(pNode, pcszName, ppChild);
  397. if (RT_FAILURE(vrc))
  398. throw ConfigError("CFGMR3InsertNode", vrc, pcszName);
  399. }
  400. /**
  401. * Helper that calls CFGMR3RemoveValue and throws an RTCError if that fails.
  402. *
  403. * @param pNode See CFGMR3RemoveValue.
  404. * @param pcszName See CFGMR3RemoveValue.
  405. */
  406. static void RemoveConfigValue(PCFGMNODE pNode,
  407. const char *pcszName)
  408. {
  409. int vrc = CFGMR3RemoveValue(pNode, pcszName);
  410. if (RT_FAILURE(vrc))
  411. throw ConfigError("CFGMR3RemoveValue", vrc, pcszName);
  412. }
  413. /** Helper that finds out the next SATA port used
  414. */
  415. static LONG GetNextUsedSataPort(LONG aSataPortUsed[30], LONG lBaseVal, uint32_t u32Size)
  416. {
  417. LONG lNextPortUsed = 30;
  418. for (size_t j = 0; j < u32Size; ++j)
  419. {
  420. if(aSataPortUsed[j] > lBaseVal &&
  421. aSataPortUsed[j] <= lNextPortUsed)
  422. lNextPortUsed = aSataPortUsed[j];
  423. }
  424. return lNextPortUsed;
  425. }
  426. #ifdef VBOX_WITH_PCI_PASSTHROUGH
  427. HRESULT Console::attachRawPCIDevices(PVM pVM,
  428. BusAssignmentManager *BusMgr,
  429. PCFGMNODE pDevices)
  430. {
  431. HRESULT hrc = S_OK;
  432. PCFGMNODE pInst, pCfg, pLunL0, pLunL1;
  433. SafeIfaceArray<IPCIDeviceAttachment> assignments;
  434. ComPtr<IMachine> aMachine = machine();
  435. hrc = aMachine->COMGETTER(PCIDeviceAssignments)(ComSafeArrayAsOutParam(assignments));
  436. if ( hrc != S_OK
  437. || assignments.size() < 1)
  438. return hrc;
  439. /*
  440. * PCI passthrough is only available if the proper ExtPack is installed.
  441. *
  442. * Note. Configuring PCI passthrough here and providing messages about
  443. * the missing extpack isn't exactly clean, but it is a necessary evil
  444. * to patch over legacy compatability issues introduced by the new
  445. * distribution model.
  446. */
  447. # ifdef VBOX_WITH_EXTPACK
  448. static const char *s_pszPCIRawExtPackName = "Oracle VM VirtualBox Extension Pack";
  449. if (!mptrExtPackManager->isExtPackUsable(s_pszPCIRawExtPackName))
  450. {
  451. /* Always fatal! */
  452. return VMSetError(pVM, VERR_NOT_FOUND, RT_SRC_POS,
  453. N_("Implementation of the PCI passthrough framework not found!\n"
  454. "The VM cannot be started. To fix this problem, either "
  455. "install the '%s' or disable PCI passthrough via VBoxManage"),
  456. s_pszPCIRawExtPackName);
  457. }
  458. # endif
  459. PCFGMNODE pBridges = CFGMR3GetChild(pDevices, "ich9pcibridge");
  460. Assert(pBridges);
  461. /* Find required bridges, and add missing ones */
  462. for (size_t iDev = 0; iDev < assignments.size(); iDev++)
  463. {
  464. ComPtr<IPCIDeviceAttachment> assignment = assignments[iDev];
  465. LONG guest = 0;
  466. PCIBusAddress GuestPCIAddress;
  467. assignment->COMGETTER(GuestAddress)(&guest);
  468. GuestPCIAddress.fromLong(guest);
  469. Assert(GuestPCIAddress.valid());
  470. if (GuestPCIAddress.miBus > 0)
  471. {
  472. int iBridgesMissed = 0;
  473. int iBase = GuestPCIAddress.miBus - 1;
  474. while (!BusMgr->hasPCIDevice("ich9pcibridge", iBase) && iBase > 0)
  475. {
  476. iBridgesMissed++; iBase--;
  477. }
  478. iBase++;
  479. for (int iBridge = 0; iBridge < iBridgesMissed; iBridge++)
  480. {
  481. InsertConfigNode(pBridges, Utf8StrFmt("%d", iBase + iBridge).c_str(), &pInst);
  482. InsertConfigInteger(pInst, "Trusted", 1);
  483. hrc = BusMgr->assignPCIDevice("ich9pcibridge", pInst);
  484. }
  485. }
  486. }
  487. /* Now actually add devices */
  488. PCFGMNODE pPCIDevs = NULL;
  489. if (assignments.size() > 0)
  490. {
  491. InsertConfigNode(pDevices, "pciraw", &pPCIDevs);
  492. PCFGMNODE pRoot = CFGMR3GetParent(pDevices); Assert(pRoot);
  493. /* Tell PGM to tell GPCIRaw about guest mappings. */
  494. CFGMR3InsertNode(pRoot, "PGM", NULL);
  495. InsertConfigInteger(CFGMR3GetChild(pRoot, "PGM"), "PciPassThrough", 1);
  496. /*
  497. * Currently, using IOMMU needed for PCI passthrough
  498. * requires RAM preallocation.
  499. */
  500. /** @todo: check if we can lift this requirement */
  501. CFGMR3RemoveValue(pRoot, "RamPreAlloc");
  502. InsertConfigInteger(pRoot, "RamPreAlloc", 1);
  503. }
  504. for (size_t iDev = 0; iDev < assignments.size(); iDev++)
  505. {
  506. PCIBusAddress HostPCIAddress, GuestPCIAddress;
  507. ComPtr<IPCIDeviceAttachment> assignment = assignments[iDev];
  508. LONG host, guest;
  509. Bstr aDevName;
  510. assignment->COMGETTER(HostAddress)(&host);
  511. assignment->COMGETTER(GuestAddress)(&guest);
  512. assignment->COMGETTER(Name)(aDevName.asOutParam());
  513. InsertConfigNode(pPCIDevs, Utf8StrFmt("%d", iDev).c_str(), &pInst);
  514. InsertConfigInteger(pInst, "Trusted", 1);
  515. HostPCIAddress.fromLong(host);
  516. Assert(HostPCIAddress.valid());
  517. InsertConfigNode(pInst, "Config", &pCfg);
  518. InsertConfigString(pCfg, "DeviceName", aDevName);
  519. InsertConfigInteger(pCfg, "DetachHostDriver", 1);
  520. InsertConfigInteger(pCfg, "HostPCIBusNo", HostPCIAddress.miBus);
  521. InsertConfigInteger(pCfg, "HostPCIDeviceNo", HostPCIAddress.miDevice);
  522. InsertConfigInteger(pCfg, "HostPCIFunctionNo", HostPCIAddress.miFn);
  523. GuestPCIAddress.fromLong(guest);
  524. Assert(GuestPCIAddress.valid());
  525. hrc = BusMgr->assignHostPCIDevice("pciraw", pInst, HostPCIAddress, GuestPCIAddress, true);
  526. if (hrc != S_OK)
  527. return hrc;
  528. InsertConfigInteger(pCfg, "GuestPCIBusNo", GuestPCIAddress.miBus);
  529. InsertConfigInteger(pCfg, "GuestPCIDeviceNo", GuestPCIAddress.miDevice);
  530. InsertConfigInteger(pCfg, "GuestPCIFunctionNo", GuestPCIAddress.miFn);
  531. /* the driver */
  532. InsertConfigNode(pInst, "LUN#0", &pLunL0);
  533. InsertConfigString(pLunL0, "Driver", "pciraw");
  534. InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
  535. /* the Main driver */
  536. InsertConfigString(pLunL1, "Driver", "MainPciRaw");
  537. InsertConfigNode(pLunL1, "Config", &pCfg);
  538. PCIRawDev* pMainDev = new PCIRawDev(this);
  539. InsertConfigInteger(pCfg, "Object", (uintptr_t)pMainDev);
  540. }
  541. return hrc;
  542. }
  543. #endif
  544. void Console::attachStatusDriver(PCFGMNODE pCtlInst, PPDMLED *papLeds,
  545. uint64_t uFirst, uint64_t uLast,
  546. Console::MediumAttachmentMap *pmapMediumAttachments,
  547. const char *pcszDevice, unsigned uInstance)
  548. {
  549. PCFGMNODE pLunL0, pCfg;
  550. InsertConfigNode(pCtlInst, "LUN#999", &pLunL0);
  551. InsertConfigString(pLunL0, "Driver", "MainStatus");
  552. InsertConfigNode(pLunL0, "Config", &pCfg);
  553. InsertConfigInteger(pCfg, "papLeds", (uintptr_t)papLeds);
  554. if (pmapMediumAttachments)
  555. {
  556. InsertConfigInteger(pCfg, "pmapMediumAttachments", (uintptr_t)pmapMediumAttachments);
  557. InsertConfigInteger(pCfg, "pConsole", (uintptr_t)this);
  558. AssertPtr(pcszDevice);
  559. Utf8Str deviceInstance = Utf8StrFmt("%s/%u", pcszDevice, uInstance);
  560. InsertConfigString(pCfg, "DeviceInstance", deviceInstance.c_str());
  561. }
  562. InsertConfigInteger(pCfg, "First", uFirst);
  563. InsertConfigInteger(pCfg, "Last", uLast);
  564. }
  565. /**
  566. * Construct the VM configuration tree (CFGM).
  567. *
  568. * This is a callback for VMR3Create() call. It is called from CFGMR3Init()
  569. * in the emulation thread (EMT). Any per thread COM/XPCOM initialization
  570. * is done here.
  571. *
  572. * @param pVM VM handle.
  573. * @param pvConsole Pointer to the VMPowerUpTask object.
  574. * @return VBox status code.
  575. *
  576. * @note Locks the Console object for writing.
  577. */
  578. DECLCALLBACK(int) Console::configConstructor(PVM pVM, void *pvConsole)
  579. {
  580. LogFlowFuncEnter();
  581. AssertReturn(pvConsole, VERR_GENERAL_FAILURE);
  582. ComObjPtr<Console> pConsole = static_cast<Console *>(pvConsole);
  583. AutoCaller autoCaller(pConsole);
  584. AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED);
  585. /* lock the console because we widely use internal fields and methods */
  586. AutoWriteLock alock(pConsole COMMA_LOCKVAL_SRC_POS);
  587. /*
  588. * Set the VM handle and do the rest of the job in an worker method so we
  589. * can easily reset the VM handle on failure.
  590. */
  591. PUVM pUVM = pConsole->mpUVM = VMR3GetUVM(pVM);
  592. VMR3RetainUVM(pUVM);
  593. int vrc;
  594. try
  595. {
  596. vrc = pConsole->configConstructorInner(pVM, &alock);
  597. }
  598. catch (...)
  599. {
  600. vrc = VERR_UNEXPECTED_EXCEPTION;
  601. }
  602. if (RT_FAILURE(vrc))
  603. {
  604. pConsole->mpUVM = NULL;
  605. VMR3ReleaseUVM(pUVM);
  606. }
  607. return vrc;
  608. }
  609. /**
  610. * Worker for configConstructor.
  611. *
  612. * @return VBox status code.
  613. * @param pVM The VM handle.
  614. * @param pAlock The automatic lock instance. This is for when we have
  615. * to leave it in order to avoid deadlocks (ext packs and
  616. * more).
  617. */
  618. int Console::configConstructorInner(PVM pVM, AutoWriteLock *pAlock)
  619. {
  620. VMMDev *pVMMDev = m_pVMMDev;
  621. Assert(pVMMDev);
  622. ComPtr<IMachine> pMachine = machine();
  623. int rc;
  624. HRESULT hrc;
  625. Bstr bstr;
  626. #define H() AssertMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_GENERAL_FAILURE)
  627. /*
  628. * Get necessary objects and frequently used parameters.
  629. */
  630. ComPtr<IVirtualBox> virtualBox;
  631. hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H();
  632. ComPtr<IHost> host;
  633. hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H();
  634. ComPtr<ISystemProperties> systemProperties;
  635. hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); H();
  636. ComPtr<IBIOSSettings> biosSettings;
  637. hrc = pMachine->COMGETTER(BIOSSettings)(biosSettings.asOutParam()); H();
  638. hrc = pMachine->COMGETTER(HardwareUUID)(bstr.asOutParam()); H();
  639. RTUUID HardwareUuid;
  640. rc = RTUuidFromUtf16(&HardwareUuid, bstr.raw());
  641. AssertRCReturn(rc, rc);
  642. ULONG cRamMBs;
  643. hrc = pMachine->COMGETTER(MemorySize)(&cRamMBs); H();
  644. #if 0 /* enable to play with lots of memory. */
  645. if (RTEnvExist("VBOX_RAM_SIZE"))
  646. cRamMBs = RTStrToUInt64(RTEnvGet("VBOX_RAM_SIZE"));
  647. #endif
  648. uint64_t const cbRam = cRamMBs * (uint64_t)_1M;
  649. uint32_t cbRamHole = MM_RAM_HOLE_SIZE_DEFAULT;
  650. uint64_t uMcfgBase = 0;
  651. uint32_t cbMcfgLength = 0;
  652. ChipsetType_T chipsetType;
  653. hrc = pMachine->COMGETTER(ChipsetType)(&chipsetType); H();
  654. if (chipsetType == ChipsetType_ICH9)
  655. {
  656. /* We'd better have 0x10000000 region, to cover 256 buses
  657. but this put too much load on hypervisor heap */
  658. cbMcfgLength = 0x4000000; //0x10000000;
  659. cbRamHole += cbMcfgLength;
  660. uMcfgBase = _4G - cbRamHole;
  661. }
  662. BusAssignmentManager* BusMgr = mBusMgr = BusAssignmentManager::createInstance(chipsetType);
  663. ULONG cCpus = 1;
  664. hrc = pMachine->COMGETTER(CPUCount)(&cCpus); H();
  665. ULONG ulCpuExecutionCap = 100;
  666. hrc = pMachine->COMGETTER(CPUExecutionCap)(&ulCpuExecutionCap); H();
  667. Bstr osTypeId;
  668. hrc = pMachine->COMGETTER(OSTypeId)(osTypeId.asOutParam()); H();
  669. LogRel(("OS type: '%s'\n", Utf8Str(osTypeId).c_str()));
  670. BOOL fIOAPIC;
  671. hrc = biosSettings->COMGETTER(IOAPICEnabled)(&fIOAPIC); H();
  672. ComPtr<IGuestOSType> guestOSType;
  673. hrc = virtualBox->GetGuestOSType(osTypeId.raw(), guestOSType.asOutParam()); H();
  674. Bstr guestTypeFamilyId;
  675. hrc = guestOSType->COMGETTER(FamilyId)(guestTypeFamilyId.asOutParam()); H();
  676. BOOL fOsXGuest = guestTypeFamilyId == Bstr("MacOS");
  677. ULONG maxNetworkAdapters;
  678. hrc = systemProperties->GetMaxNetworkAdapters(chipsetType, &maxNetworkAdapters); H();
  679. /*
  680. * Get root node first.
  681. * This is the only node in the tree.
  682. */
  683. PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
  684. Assert(pRoot);
  685. // InsertConfigString throws
  686. try
  687. {
  688. /*
  689. * Set the root (and VMM) level values.
  690. */
  691. hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H();
  692. InsertConfigString(pRoot, "Name", bstr);
  693. InsertConfigBytes(pRoot, "UUID", &HardwareUuid, sizeof(HardwareUuid));
  694. InsertConfigInteger(pRoot, "RamSize", cbRam);
  695. InsertConfigInteger(pRoot, "RamHoleSize", cbRamHole);
  696. InsertConfigInteger(pRoot, "NumCPUs", cCpus);
  697. InsertConfigInteger(pRoot, "CpuExecutionCap", ulCpuExecutionCap);
  698. InsertConfigInteger(pRoot, "TimerMillies", 10);
  699. #ifdef VBOX_WITH_RAW_MODE
  700. InsertConfigInteger(pRoot, "RawR3Enabled", 1); /* boolean */
  701. InsertConfigInteger(pRoot, "RawR0Enabled", 1); /* boolean */
  702. /** @todo Config: RawR0, PATMEnabled and CSAMEnabled needs attention later. */
  703. InsertConfigInteger(pRoot, "PATMEnabled", 1); /* boolean */
  704. InsertConfigInteger(pRoot, "CSAMEnabled", 1); /* boolean */
  705. #endif
  706. /* Not necessary, but to make sure these two settings end up in the release log. */
  707. BOOL fPageFusion = FALSE;
  708. hrc = pMachine->COMGETTER(PageFusionEnabled)(&fPageFusion); H();
  709. InsertConfigInteger(pRoot, "PageFusion", fPageFusion); /* boolean */
  710. ULONG ulBalloonSize = 0;
  711. hrc = pMachine->COMGETTER(MemoryBalloonSize)(&ulBalloonSize); H();
  712. InsertConfigInteger(pRoot, "MemBalloonSize", ulBalloonSize);
  713. /*
  714. * CPUM values.
  715. */
  716. PCFGMNODE pCPUM;
  717. InsertConfigNode(pRoot, "CPUM", &pCPUM);
  718. /* cpuid leaf overrides. */
  719. static uint32_t const s_auCpuIdRanges[] =
  720. {
  721. UINT32_C(0x00000000), UINT32_C(0x0000000a),
  722. UINT32_C(0x80000000), UINT32_C(0x8000000a)
  723. };
  724. for (unsigned i = 0; i < RT_ELEMENTS(s_auCpuIdRanges); i += 2)
  725. for (uint32_t uLeaf = s_auCpuIdRanges[i]; uLeaf < s_auCpuIdRanges[i + 1]; uLeaf++)
  726. {
  727. ULONG ulEax, ulEbx, ulEcx, ulEdx;
  728. hrc = pMachine->GetCPUIDLeaf(uLeaf, &ulEax, &ulEbx, &ulEcx, &ulEdx);
  729. if (SUCCEEDED(hrc))
  730. {
  731. PCFGMNODE pLeaf;
  732. InsertConfigNode(pCPUM, Utf8StrFmt("HostCPUID/%RX32", uLeaf).c_str(), &pLeaf);
  733. InsertConfigInteger(pLeaf, "eax", ulEax);
  734. InsertConfigInteger(pLeaf, "ebx", ulEbx);
  735. InsertConfigInteger(pLeaf, "ecx", ulEcx);
  736. InsertConfigInteger(pLeaf, "edx", ulEdx);
  737. }
  738. else if (hrc != E_INVALIDARG) H();
  739. }
  740. /* We must limit CPUID count for Windows NT 4, as otherwise it stops
  741. with error 0x3e (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED). */
  742. if (osTypeId == "WindowsNT4")
  743. {
  744. LogRel(("Limiting CPUID leaf count for NT4 guests\n"));
  745. InsertConfigInteger(pCPUM, "NT4LeafLimit", true);
  746. }
  747. /* Expose extended MWAIT features to Mac OS X guests. */
  748. if (fOsXGuest)
  749. {
  750. LogRel(("Using MWAIT extensions\n"));
  751. InsertConfigInteger(pCPUM, "MWaitExtensions", true);
  752. }
  753. /*
  754. * Hardware virtualization extensions.
  755. */
  756. BOOL fHWVirtExEnabled;
  757. BOOL fHwVirtExtForced = false;
  758. #ifdef VBOX_WITH_RAW_MODE
  759. hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Enabled, &fHWVirtExEnabled); H();
  760. if (cCpus > 1) /** @todo SMP: This isn't nice, but things won't work on mac otherwise. */
  761. fHWVirtExEnabled = TRUE;
  762. # ifdef RT_OS_DARWIN
  763. fHwVirtExtForced = fHWVirtExEnabled;
  764. # else
  765. /* - With more than 4GB PGM will use different RAMRANGE sizes for raw
  766. mode and hv mode to optimize lookup times.
  767. - With more than one virtual CPU, raw-mode isn't a fallback option. */
  768. fHwVirtExtForced = fHWVirtExEnabled
  769. && ( cbRam + cbRamHole > _4G
  770. || cCpus > 1);
  771. # endif
  772. #else /* !VBOX_WITH_RAW_MODE */
  773. fHWVirtExEnabled = fHwVirtExtForced = true;
  774. #endif /* !VBOX_WITH_RAW_MODE */
  775. /* only honor the property value if there was no other reason to enable it */
  776. if (!fHwVirtExtForced)
  777. {
  778. hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Force, &fHwVirtExtForced); H();
  779. }
  780. InsertConfigInteger(pRoot, "HwVirtExtForced", fHwVirtExtForced);
  781. /*
  782. * MM values.
  783. */
  784. PCFGMNODE pMM;
  785. InsertConfigNode(pRoot, "MM", &pMM);
  786. InsertConfigInteger(pMM, "CanUseLargerHeap", chipsetType == ChipsetType_ICH9);
  787. /*
  788. * Hardware virtualization settings.
  789. */
  790. BOOL fIsGuest64Bit = false;
  791. PCFGMNODE pHWVirtExt;
  792. InsertConfigNode(pRoot, "HWVirtExt", &pHWVirtExt);
  793. if (fHWVirtExEnabled)
  794. {
  795. InsertConfigInteger(pHWVirtExt, "Enabled", 1);
  796. /* Indicate whether 64-bit guests are supported or not. */
  797. /** @todo This is currently only forced off on 32-bit hosts only because it
  798. * makes a lof of difference there (REM and Solaris performance).
  799. */
  800. BOOL fSupportsLongMode = false;
  801. hrc = host->GetProcessorFeature(ProcessorFeature_LongMode,
  802. &fSupportsLongMode); H();
  803. hrc = guestOSType->COMGETTER(Is64Bit)(&fIsGuest64Bit); H();
  804. if (fSupportsLongMode && fIsGuest64Bit)
  805. {
  806. InsertConfigInteger(pHWVirtExt, "64bitEnabled", 1);
  807. #if ARCH_BITS == 32 /* The recompiler must use VBoxREM64 (32-bit host only). */
  808. PCFGMNODE pREM;
  809. InsertConfigNode(pRoot, "REM", &pREM);
  810. InsertConfigInteger(pREM, "64bitEnabled", 1);
  811. #endif
  812. }
  813. #if ARCH_BITS == 32 /* 32-bit guests only. */
  814. else
  815. {
  816. InsertConfigInteger(pHWVirtExt, "64bitEnabled", 0);
  817. }
  818. #endif
  819. /** @todo Not exactly pretty to check strings; VBOXOSTYPE would be better, but that requires quite a bit of API change in Main. */
  820. if ( !fIsGuest64Bit
  821. && fIOAPIC
  822. && ( osTypeId == "WindowsNT4"
  823. || osTypeId == "Windows2000"
  824. || osTypeId == "WindowsXP"
  825. || osTypeId == "Windows2003"))
  826. {
  827. /* Only allow TPR patching for NT, Win2k, XP and Windows Server 2003. (32 bits mode)
  828. * We may want to consider adding more guest OSes (Solaris) later on.
  829. */
  830. InsertConfigInteger(pHWVirtExt, "TPRPatchingEnabled", 1);
  831. }
  832. }
  833. /* HWVirtEx exclusive mode */
  834. BOOL fHWVirtExExclusive = true;
  835. hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Exclusive, &fHWVirtExExclusive); H();
  836. InsertConfigInteger(pHWVirtExt, "Exclusive", fHWVirtExExclusive);
  837. /* Nested paging (VT-x/AMD-V) */
  838. BOOL fEnableNestedPaging = false;
  839. hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_NestedPaging, &fEnableNestedPaging); H();
  840. InsertConfigInteger(pHWVirtExt, "EnableNestedPaging", fEnableNestedPaging);
  841. /* Large pages; requires nested paging */
  842. BOOL fEnableLargePages = false;
  843. hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_LargePages, &fEnableLargePages); H();
  844. InsertConfigInteger(pHWVirtExt, "EnableLargePages", fEnableLargePages);
  845. /* VPID (VT-x) */
  846. BOOL fEnableVPID = false;
  847. hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_VPID, &fEnableVPID); H();
  848. InsertConfigInteger(pHWVirtExt, "EnableVPID", fEnableVPID);
  849. /* Physical Address Extension (PAE) */
  850. BOOL fEnablePAE = false;
  851. hrc = pMachine->GetCPUProperty(CPUPropertyType_PAE, &fEnablePAE); H();
  852. InsertConfigInteger(pRoot, "EnablePAE", fEnablePAE);
  853. /* Synthetic CPU */
  854. BOOL fSyntheticCpu = false;
  855. hrc = pMachine->GetCPUProperty(CPUPropertyType_Synthetic, &fSyntheticCpu); H();
  856. InsertConfigInteger(pCPUM, "SyntheticCpu", fSyntheticCpu);
  857. if (fOsXGuest)
  858. InsertConfigInteger(pCPUM, "EnableHVP", 1);
  859. BOOL fPXEDebug;
  860. hrc = biosSettings->COMGETTER(PXEDebugEnabled)(&fPXEDebug); H();
  861. /*
  862. * PDM config.
  863. * Load drivers in VBoxC.[so|dll]
  864. */
  865. PCFGMNODE pPDM;
  866. PCFGMNODE pNode;
  867. PCFGMNODE pMod;
  868. InsertConfigNode(pRoot, "PDM", &pPDM);
  869. InsertConfigNode(pPDM, "Devices", &pNode);
  870. InsertConfigNode(pPDM, "Drivers", &pNode);
  871. InsertConfigNode(pNode, "VBoxC", &pMod);
  872. #ifdef VBOX_WITH_XPCOM
  873. // VBoxC is located in the components subdirectory
  874. char szPathVBoxC[RTPATH_MAX];
  875. rc = RTPathAppPrivateArch(szPathVBoxC, RTPATH_MAX - sizeof("/components/VBoxC")); AssertRC(rc);
  876. strcat(szPathVBoxC, "/components/VBoxC");
  877. InsertConfigString(pMod, "Path", szPathVBoxC);
  878. #else
  879. InsertConfigString(pMod, "Path", "VBoxC");
  880. #endif
  881. /*
  882. * Block cache settings.
  883. */
  884. PCFGMNODE pPDMBlkCache;
  885. InsertConfigNode(pPDM, "BlkCache", &pPDMBlkCache);
  886. /* I/O cache size */
  887. ULONG ioCacheSize = 5;
  888. hrc = pMachine->COMGETTER(IOCacheSize)(&ioCacheSize); H();
  889. InsertConfigInteger(pPDMBlkCache, "CacheSize", ioCacheSize * _1M);
  890. /*
  891. * Bandwidth groups.
  892. */
  893. PCFGMNODE pAc;
  894. PCFGMNODE pAcFile;
  895. PCFGMNODE pAcFileBwGroups;
  896. ComPtr<IBandwidthControl> bwCtrl;
  897. com::SafeIfaceArray<IBandwidthGroup> bwGroups;
  898. hrc = pMachine->COMGETTER(BandwidthControl)(bwCtrl.asOutParam()); H();
  899. hrc = bwCtrl->GetAllBandwidthGroups(ComSafeArrayAsOutParam(bwGroups)); H();
  900. InsertConfigNode(pPDM, "AsyncCompletion", &pAc);
  901. InsertConfigNode(pAc, "File", &pAcFile);
  902. InsertConfigNode(pAcFile, "BwGroups", &pAcFileBwGroups);
  903. #ifdef VBOX_WITH_NETSHAPER
  904. PCFGMNODE pNetworkShaper;
  905. PCFGMNODE pNetworkBwGroups;
  906. InsertConfigNode(pPDM, "NetworkShaper", &pNetworkShaper);
  907. InsertConfigNode(pNetworkShaper, "BwGroups", &pNetworkBwGroups);
  908. #endif /* VBOX_WITH_NETSHAPER */
  909. for (size_t i = 0; i < bwGroups.size(); i++)
  910. {
  911. Bstr strName;
  912. LONG64 cMaxBytesPerSec;
  913. BandwidthGroupType_T enmType;
  914. hrc = bwGroups[i]->COMGETTER(Name)(strName.asOutParam()); H();
  915. hrc = bwGroups[i]->COMGETTER(Type)(&enmType); H();
  916. hrc = bwGroups[i]->COMGETTER(MaxBytesPerSec)(&cMaxBytesPerSec); H();
  917. if (enmType == BandwidthGroupType_Disk)
  918. {
  919. PCFGMNODE pBwGroup;
  920. InsertConfigNode(pAcFileBwGroups, Utf8Str(strName).c_str(), &pBwGroup);
  921. InsertConfigInteger(pBwGroup, "Max", cMaxBytesPerSec);
  922. InsertConfigInteger(pBwGroup, "Start", cMaxBytesPerSec);
  923. InsertConfigInteger(pBwGroup, "Step", 0);
  924. }
  925. #ifdef VBOX_WITH_NETSHAPER
  926. else if (enmType == BandwidthGroupType_Network)
  927. {
  928. /* Network bandwidth groups. */
  929. PCFGMNODE pBwGroup;
  930. InsertConfigNode(pNetworkBwGroups, Utf8Str(strName).c_str(), &pBwGroup);
  931. InsertConfigInteger(pBwGroup, "Max", cMaxBytesPerSec);
  932. }
  933. #endif /* VBOX_WITH_NETSHAPER */
  934. }
  935. /*
  936. * Devices
  937. */
  938. PCFGMNODE pDevices = NULL; /* /Devices */
  939. PCFGMNODE pDev = NULL; /* /Devices/Dev/ */
  940. PCFGMNODE pInst = NULL; /* /Devices/Dev/0/ */
  941. PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */
  942. PCFGMNODE pLunL0 = NULL; /* /Devices/Dev/0/LUN#0/ */
  943. PCFGMNODE pLunL1 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/ */
  944. PCFGMNODE pLunL2 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/Config/ */
  945. PCFGMNODE pBiosCfg = NULL; /* /Devices/pcbios/0/Config/ */
  946. PCFGMNODE pNetBootCfg = NULL; /* /Devices/pcbios/0/Config/NetBoot/ */
  947. InsertConfigNode(pRoot, "Devices", &pDevices);
  948. /*
  949. * PC Arch.
  950. */
  951. InsertConfigNode(pDevices, "pcarch", &pDev);
  952. InsertConfigNode(pDev, "0", &pInst);
  953. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  954. InsertConfigNode(pInst, "Config", &pCfg);
  955. /*
  956. * The time offset
  957. */
  958. LONG64 timeOffset;
  959. hrc = biosSettings->COMGETTER(TimeOffset)(&timeOffset); H();
  960. PCFGMNODE pTMNode;
  961. InsertConfigNode(pRoot, "TM", &pTMNode);
  962. InsertConfigInteger(pTMNode, "UTCOffset", timeOffset * 1000000);
  963. /*
  964. * DMA
  965. */
  966. InsertConfigNode(pDevices, "8237A", &pDev);
  967. InsertConfigNode(pDev, "0", &pInst);
  968. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  969. /*
  970. * PCI buses.
  971. */
  972. uint32_t uIocPCIAddress, uHbcPCIAddress;
  973. switch (chipsetType)
  974. {
  975. default:
  976. Assert(false);
  977. case ChipsetType_PIIX3:
  978. InsertConfigNode(pDevices, "pci", &pDev);
  979. uHbcPCIAddress = (0x0 << 16) | 0;
  980. uIocPCIAddress = (0x1 << 16) | 0; // ISA controller
  981. break;
  982. case ChipsetType_ICH9:
  983. InsertConfigNode(pDevices, "ich9pci", &pDev);
  984. uHbcPCIAddress = (0x1e << 16) | 0;
  985. uIocPCIAddress = (0x1f << 16) | 0; // LPC controller
  986. break;
  987. }
  988. InsertConfigNode(pDev, "0", &pInst);
  989. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  990. InsertConfigNode(pInst, "Config", &pCfg);
  991. InsertConfigInteger(pCfg, "IOAPIC", fIOAPIC);
  992. if (chipsetType == ChipsetType_ICH9)
  993. {
  994. /* Provide MCFG info */
  995. InsertConfigInteger(pCfg, "McfgBase", uMcfgBase);
  996. InsertConfigInteger(pCfg, "McfgLength", cbMcfgLength);
  997. /* And register 2 bridges */
  998. InsertConfigNode(pDevices, "ich9pcibridge", &pDev);
  999. InsertConfigNode(pDev, "0", &pInst);
  1000. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  1001. hrc = BusMgr->assignPCIDevice("ich9pcibridge", pInst); H();
  1002. InsertConfigNode(pDev, "1", &pInst);
  1003. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  1004. hrc = BusMgr->assignPCIDevice("ich9pcibridge", pInst); H();
  1005. #ifdef VBOX_WITH_PCI_PASSTHROUGH
  1006. /* Add PCI passthrough devices */
  1007. hrc = attachRawPCIDevices(pVM, BusMgr, pDevices); H();
  1008. #endif
  1009. }
  1010. /*
  1011. * Enable the following devices: HPET, SMC and LPC on MacOS X guests or on ICH9 chipset
  1012. */
  1013. /*
  1014. * High Precision Event Timer (HPET)
  1015. */
  1016. BOOL fHPETEnabled;
  1017. /* Other guests may wish to use HPET too, but MacOS X not functional without it */
  1018. hrc = pMachine->COMGETTER(HPETEnabled)(&fHPETEnabled); H();
  1019. /* so always enable HPET in extended profile */
  1020. fHPETEnabled |= fOsXGuest;
  1021. /* HPET is always present on ICH9 */
  1022. fHPETEnabled |= (chipsetType == ChipsetType_ICH9);
  1023. if (fHPETEnabled)
  1024. {
  1025. InsertConfigNode(pDevices, "hpet", &pDev);
  1026. InsertConfigNode(pDev, "0", &pInst);
  1027. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  1028. InsertConfigNode(pInst, "Config", &pCfg);
  1029. InsertConfigInteger(pCfg, "ICH9", (chipsetType == ChipsetType_ICH9) ? 1 : 0); /* boolean */
  1030. }
  1031. /*
  1032. * System Management Controller (SMC)
  1033. */
  1034. BOOL fSmcEnabled;
  1035. fSmcEnabled = fOsXGuest;
  1036. if (fSmcEnabled)
  1037. {
  1038. InsertConfigNode(pDevices, "smc", &pDev);
  1039. InsertConfigNode(pDev, "0", &pInst);
  1040. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  1041. InsertConfigNode(pInst, "Config", &pCfg);
  1042. bool fGetKeyFromRealSMC;
  1043. Bstr bstrKey;
  1044. rc = getSmcDeviceKey(pMachine, bstrKey.asOutParam(), &fGetKeyFromRealSMC);
  1045. AssertRCReturn(rc, rc);
  1046. InsertConfigString(pCfg, "DeviceKey", bstrKey);
  1047. InsertConfigInteger(pCfg, "GetKeyFromRealSMC", fGetKeyFromRealSMC);
  1048. }
  1049. /*
  1050. * Low Pin Count (LPC) bus
  1051. */
  1052. BOOL fLpcEnabled;
  1053. /** @todo: implement appropriate getter */
  1054. fLpcEnabled = fOsXGuest || (chipsetType == ChipsetType_ICH9);
  1055. if (fLpcEnabled)
  1056. {
  1057. InsertConfigNode(pDevices, "lpc", &pDev);
  1058. InsertConfigNode(pDev, "0", &pInst);
  1059. hrc = BusMgr->assignPCIDevice("lpc", pInst); H();
  1060. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  1061. }
  1062. BOOL fShowRtc;
  1063. fShowRtc = fOsXGuest || (chipsetType == ChipsetType_ICH9);
  1064. /*
  1065. * PS/2 keyboard & mouse.
  1066. */
  1067. InsertConfigNode(pDevices, "pckbd", &pDev);
  1068. InsertConfigNode(pDev, "0", &pInst);
  1069. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  1070. InsertConfigNode(pInst, "Config", &pCfg);
  1071. InsertConfigNode(pInst, "LUN#0", &pLunL0);
  1072. InsertConfigString(pLunL0, "Driver", "KeyboardQueue");
  1073. InsertConfigNode(pLunL0, "Config", &pCfg);
  1074. InsertConfigInteger(pCfg, "QueueSize", 64);
  1075. InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
  1076. InsertConfigString(pLunL1, "Driver", "MainKeyboard");
  1077. InsertConfigNode(pLunL1, "Config", &pCfg);
  1078. Keyboard *pKeyboard = mKeyboard;
  1079. InsertConfigInteger(pCfg, "Object", (uintptr_t)pKeyboard);
  1080. InsertConfigNode(pInst, "LUN#1", &pLunL0);
  1081. InsertConfigString(pLunL0, "Driver", "MouseQueue");
  1082. InsertConfigNode(pLunL0, "Config", &pCfg);
  1083. InsertConfigInteger(pCfg, "QueueSize", 128);
  1084. InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1);
  1085. InsertConfigString(pLunL1, "Driver", "MainMouse");
  1086. InsertConfigNode(pLunL1, "Config", &pCfg);
  1087. Mouse *pMouse = mMouse;
  1088. InsertConfigInteger(pCfg, "Object", (uintptr_t)pMouse);
  1089. /*
  1090. * i8254 Programmable Interval Timer And Dummy Speaker
  1091. */
  1092. InsertConfigNode(pDevices, "i8254", &pDev);
  1093. InsertConfigNode(pDev, "0", &pInst);
  1094. InsertConfigNode(pInst, "Config", &pCfg);
  1095. #ifdef DEBUG
  1096. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  1097. #endif
  1098. /*
  1099. * i8259 Programmable Interrupt Controller.
  1100. */
  1101. InsertConfigNode(pDevices, "i8259", &pDev);
  1102. InsertConfigNode(pDev, "0", &pInst);
  1103. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  1104. InsertConfigNode(pInst, "Config", &pCfg);
  1105. /*
  1106. * Advanced Programmable Interrupt Controller.
  1107. * SMP: Each CPU has a LAPIC, but we have a single device representing all LAPICs states,
  1108. * thus only single insert
  1109. */
  1110. InsertConfigNode(pDevices, "apic", &pDev);
  1111. InsertConfigNode(pDev, "0", &pInst);
  1112. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  1113. InsertConfigNode(pInst, "Config", &pCfg);
  1114. InsertConfigInteger(pCfg, "IOAPIC", fIOAPIC);
  1115. InsertConfigInteger(pCfg, "NumCPUs", cCpus);
  1116. if (fIOAPIC)
  1117. {
  1118. /*
  1119. * I/O Advanced Programmable Interrupt Controller.
  1120. */
  1121. InsertConfigNode(pDevices, "ioapic", &pDev);
  1122. InsertConfigNode(pDev, "0", &pInst);
  1123. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  1124. InsertConfigNode(pInst, "Config", &pCfg);
  1125. InsertConfigInteger(pCfg, "NumCPUs", cCpus);
  1126. }
  1127. /*
  1128. * RTC MC146818.
  1129. */
  1130. InsertConfigNode(pDevices, "mc146818", &pDev);
  1131. InsertConfigNode(pDev, "0", &pInst);
  1132. InsertConfigNode(pInst, "Config", &pCfg);
  1133. BOOL fRTCUseUTC;
  1134. hrc = pMachine->COMGETTER(RTCUseUTC)(&fRTCUseUTC); H();
  1135. InsertConfigInteger(pCfg, "UseUTC", fRTCUseUTC ? 1 : 0);
  1136. /*
  1137. * VGA.
  1138. */
  1139. InsertConfigNode(pDevices, "vga", &pDev);
  1140. InsertConfigNode(pDev, "0", &pInst);
  1141. InsertConfigInteger(pInst, "Trusted", 1); /* boolean */
  1142. hrc = BusMgr->assignPCIDevice("vga", pInst); H();
  1143. InsertConfigNode(pInst, "Config", &pCfg);
  1144. ULONG cVRamMBs;
  1145. hrc = pMachine->COMGETTER(VRAMSize)(&cVRamMBs); H();
  1146. InsertConfigInteger(pCfg, "VRamSize", cVRamMBs * _1M);
  1147. ULONG cMonitorCount;
  1148. hrc = pMachine->COMGETTER(MonitorCount)(&cMonitorCount); H();
  1149. InsertConfigInteger(pCfg, "MonitorCount", cMonitorCount);
  1150. #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
  1151. InsertConfigInteger(pCfg, "R0Enabled", fHWVirtExEnabled);
  1152. #endif
  1153. /*
  1154. * BIOS logo
  1155. */
  1156. BOOL fFadeIn;
  1157. hrc = biosSettings->COMGETTER(LogoFadeIn)(&fFadeIn); H();
  1158. InsertConfigInteger(pCfg, "FadeIn", fFadeIn ? 1 : 0);
  1159. BOOL fFadeOut;
  1160. hrc = biosSettings->COMGETTER(LogoFadeOut)(&fFadeOut); H();
  1161. InsertConfigInteger(pCfg, "FadeOut", fFadeOut ? 1: 0);
  1162. ULONG logoDisplayTime;
  1163. hrc = biosSettings->COMGETTER(LogoDisplayTime)(&logoDisplayTime); H();
  1164. InsertConfigInteger(pCfg, "LogoTime", logoDisplayTime);
  1165. Bstr logoImagePath;
  1166. hrc = biosSettings->COMGETTER(LogoImagePath)(logoImagePath.asOutParam()); H();
  1167. InsertConfigString(pCfg, "LogoFile", Utf8Str(!logoImagePath.isEmpty() ? logoImagePath : "") );
  1168. /*
  1169. * Boot menu
  1170. */
  1171. BIOSBootMenuMode_T eBootMenuMode;
  1172. int iShowBootMenu;
  1173. biosSettings->COMGETTER(BootMenuMode)(&eBootMenuMode);
  1174. switch (eBootMenuMode)
  1175. {
  1176. case BIOSBootMenuMode_Disabled: iShowBootMenu = 0; break;
  1177. case BIOSBootMenuMode_MenuOnly: iShowBootMenu = 1; break;
  1178. default: iShowBootMenu = 2; break;
  1179. }
  1180. InsertConfigInteger(pCfg, "ShowBootMenu", iShowBootMenu);
  1181. /* Custom VESA mode list */
  1182. unsigned cModes = 0;
  1183. for (unsigned iMode = 1; iMode <= 16; ++iMode)
  1184. {
  1185. char szExtraDataKey[sizeof("CustomVideoModeXX")];
  1186. RTStrPrintf(szExtraDataKey, sizeof(szExtraDataKey), "CustomVideoMode%u", iMode);
  1187. hrc = pMachine->GetExtraData(Bstr(szExtraDataKey).raw(), bstr.asOutParam()); H();
  1188. if (bstr.isEmpty())
  1189. break;
  1190. InsertConfigString(pCfg, szExtraDataKey, bstr);
  1191. ++cModes;
  1192. }
  1193. InsertConfigInteger(pCfg, "CustomVideoModes", cModes);
  1194. /* VESA height reduction */
  1195. ULONG ulHeightR

Large files files are truncated, but you can click here to view the full file