VirtualBox

source: vbox/trunk/src/VBox/Main/ConsoleImpl2.cpp@ 10372

Last change on this file since 10372 was 10372, checked in by vboxsync, 16 years ago

disable the floppy controller in the ACPI tables if necessary

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 86.0 KB
Line 
1/** $Id: ConsoleImpl2.cpp 10372 2008-07-08 14:14:29Z vboxsync $ */
2/** @file
3 * VBox Console COM Class implementation
4 *
5 * @remark We've split out the code that the 64-bit VC++ v8 compiler
6 * finds problematic to optimize so we can disable optimizations
7 * and later, perhaps, find a real solution for it.
8 */
9
10/*
11 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
22 * Clara, CA 95054 USA or visit http://www.sun.com if you need
23 * additional information or have any questions.
24 */
25
26/*******************************************************************************
27* Header Files *
28*******************************************************************************/
29#include "ConsoleImpl.h"
30#include "DisplayImpl.h"
31#include "VMMDev.h"
32
33// generated header
34#include "SchemaDefs.h"
35
36#include "Logging.h"
37
38#include <iprt/string.h>
39#include <iprt/path.h>
40#include <iprt/dir.h>
41#include <iprt/param.h>
42
43#include <VBox/vmapi.h>
44#include <VBox/err.h>
45#include <VBox/version.h>
46#include <VBox/HostServices/VBoxClipboardSvc.h>
47#ifdef VBOX_WITH_INFO_SVC
48#include <VBox/HostServices/VBoxInfoSvc.h>
49#endif /* VBOX_WITH_INFO_SVC */
50
51
52/*
53 * VC++ 8 / amd64 has some serious trouble with this function.
54 * As a temporary measure, we'll drop global optimizations.
55 */
56#if defined(_MSC_VER) && defined(RT_ARCH_AMD64)
57# pragma optimize("g", off)
58#endif
59
60/**
61 * Construct the VM configuration tree (CFGM).
62 *
63 * This is a callback for VMR3Create() call. It is called from CFGMR3Init()
64 * in the emulation thread (EMT). Any per thread COM/XPCOM initialization
65 * is done here.
66 *
67 * @param pVM VM handle.
68 * @param pvConsole Pointer to the VMPowerUpTask object.
69 * @return VBox status code.
70 *
71 * @note Locks the Console object for writing.
72 */
73DECLCALLBACK(int) Console::configConstructor(PVM pVM, void *pvConsole)
74{
75 LogFlowFuncEnter();
76 /* Note: hardcoded assumption about number of slots; see rom bios */
77 bool afPciDeviceNo[15] = {false};
78
79#if !defined (VBOX_WITH_XPCOM)
80 {
81 /* initialize COM */
82 HRESULT hrc = CoInitializeEx(NULL,
83 COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE |
84 COINIT_SPEED_OVER_MEMORY);
85 LogFlow (("Console::configConstructor(): CoInitializeEx()=%08X\n", hrc));
86 AssertComRCReturn (hrc, VERR_GENERAL_FAILURE);
87 }
88#endif
89
90 AssertReturn (pvConsole, VERR_GENERAL_FAILURE);
91 ComObjPtr <Console> pConsole = static_cast <Console *> (pvConsole);
92
93 AutoCaller autoCaller (pConsole);
94 AssertComRCReturn (autoCaller.rc(), VERR_ACCESS_DENIED);
95
96 /* lock the console because we widely use internal fields and methods */
97 AutoWriteLock alock (pConsole);
98
99 ComPtr <IMachine> pMachine = pConsole->machine();
100
101 int rc;
102 HRESULT hrc;
103 char *psz = NULL;
104 BSTR str = NULL;
105
106#define STR_CONV() do { rc = RTUtf16ToUtf8(str, &psz); RC_CHECK(); } while (0)
107#define STR_FREE() do { if (str) { SysFreeString(str); str = NULL; } if (psz) { RTStrFree(psz); psz = NULL; } } while (0)
108#define RC_CHECK() do { if (VBOX_FAILURE(rc)) { AssertMsgFailed(("rc=%Vrc\n", rc)); STR_FREE(); return rc; } } while (0)
109#define H() do { if (FAILED(hrc)) { AssertMsgFailed(("hrc=%#x\n", hrc)); STR_FREE(); return VERR_GENERAL_FAILURE; } } while (0)
110
111 /*
112 * Get necessary objects and frequently used parameters.
113 */
114 ComPtr<IVirtualBox> virtualBox;
115 hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); H();
116
117 ComPtr<IHost> host;
118 hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); H();
119
120 ComPtr <ISystemProperties> systemProperties;
121 hrc = virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam()); H();
122
123 ComPtr<IBIOSSettings> biosSettings;
124 hrc = pMachine->COMGETTER(BIOSSettings)(biosSettings.asOutParam()); H();
125
126 Guid uuid;
127 hrc = pMachine->COMGETTER(Id)(uuid.asOutParam()); H();
128 PCRTUUID pUuid = uuid.raw();
129
130 ULONG cRamMBs;
131 hrc = pMachine->COMGETTER(MemorySize)(&cRamMBs); H();
132
133
134 /*
135 * Get root node first.
136 * This is the only node in the tree.
137 */
138 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
139 Assert(pRoot);
140
141 /*
142 * Set the root level values.
143 */
144 hrc = pMachine->COMGETTER(Name)(&str); H();
145 STR_CONV();
146 rc = CFGMR3InsertString(pRoot, "Name", psz); RC_CHECK();
147 STR_FREE();
148 rc = CFGMR3InsertBytes(pRoot, "UUID", pUuid, sizeof(*pUuid)); RC_CHECK();
149 rc = CFGMR3InsertInteger(pRoot, "RamSize", cRamMBs * _1M); RC_CHECK();
150 rc = CFGMR3InsertInteger(pRoot, "TimerMillies", 10); RC_CHECK();
151 rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled", 1); /* boolean */ RC_CHECK();
152 rc = CFGMR3InsertInteger(pRoot, "RawR0Enabled", 1); /* boolean */ RC_CHECK();
153 /** @todo Config: RawR0, PATMEnabled and CASMEnabled needs attention later. */
154 rc = CFGMR3InsertInteger(pRoot, "PATMEnabled", 1); /* boolean */ RC_CHECK();
155 rc = CFGMR3InsertInteger(pRoot, "CSAMEnabled", 1); /* boolean */ RC_CHECK();
156
157 /* hardware virtualization extensions */
158 TSBool_T hwVirtExEnabled;
159 BOOL fHWVirtExEnabled;
160 hrc = pMachine->COMGETTER(HWVirtExEnabled)(&hwVirtExEnabled); H();
161 if (hwVirtExEnabled == TSBool_Default)
162 {
163 /* check the default value */
164 hrc = systemProperties->COMGETTER(HWVirtExEnabled)(&fHWVirtExEnabled); H();
165 }
166 else
167 fHWVirtExEnabled = (hwVirtExEnabled == TSBool_True);
168#ifndef RT_OS_DARWIN /** @todo Implement HWVirtExt on darwin. See #1865. */
169 if (fHWVirtExEnabled)
170 {
171 PCFGMNODE pHWVirtExt;
172 rc = CFGMR3InsertNode(pRoot, "HWVirtExt", &pHWVirtExt); RC_CHECK();
173 rc = CFGMR3InsertInteger(pHWVirtExt, "Enabled", 1); RC_CHECK();
174 }
175#endif
176
177 /* Physical Address Extension (PAE) */
178 BOOL fEnablePAE = false;
179 hrc = pMachine->COMGETTER(PAEEnabled)(&fEnablePAE); H();
180 rc = CFGMR3InsertInteger(pRoot, "EnablePAE", fEnablePAE); RC_CHECK();
181
182 BOOL fIOAPIC;
183 hrc = biosSettings->COMGETTER(IOAPICEnabled)(&fIOAPIC); H();
184
185 BOOL fPXEDebug;
186 hrc = biosSettings->COMGETTER(PXEDebugEnabled)(&fPXEDebug); H();
187
188 /*
189 * Virtual IDE controller type.
190 */
191 IDEControllerType_T controllerType;
192 BOOL fPIIX4;
193 hrc = biosSettings->COMGETTER(IDEControllerType)(&controllerType); H();
194 switch (controllerType)
195 {
196 case IDEControllerType_PIIX3:
197 fPIIX4 = FALSE;
198 break;
199 case IDEControllerType_PIIX4:
200 fPIIX4 = TRUE;
201 break;
202 default:
203 AssertMsgFailed(("Invalid IDE controller type '%d'", controllerType));
204 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
205 N_("Invalid IDE controller type '%d'"), controllerType);
206 }
207
208 /*
209 * PDM config.
210 * Load drivers in VBoxC.[so|dll]
211 */
212 PCFGMNODE pPDM;
213 PCFGMNODE pDrivers;
214 PCFGMNODE pMod;
215 rc = CFGMR3InsertNode(pRoot, "PDM", &pPDM); RC_CHECK();
216 rc = CFGMR3InsertNode(pPDM, "Drivers", &pDrivers); RC_CHECK();
217 rc = CFGMR3InsertNode(pDrivers, "VBoxC", &pMod); RC_CHECK();
218#ifdef VBOX_WITH_XPCOM
219 // VBoxC is located in the components subdirectory
220 char szPathVBoxC[RTPATH_MAX];
221 rc = RTPathAppPrivateArch(szPathVBoxC, RTPATH_MAX - sizeof("/components/VBoxC")); AssertRC(rc);
222 strcat(szPathVBoxC, "/components/VBoxC");
223 rc = CFGMR3InsertString(pMod, "Path", szPathVBoxC); RC_CHECK();
224#else
225 rc = CFGMR3InsertString(pMod, "Path", "VBoxC"); RC_CHECK();
226#endif
227
228 /*
229 * Devices
230 */
231 PCFGMNODE pDevices = NULL; /* /Devices */
232 PCFGMNODE pDev = NULL; /* /Devices/Dev/ */
233 PCFGMNODE pInst = NULL; /* /Devices/Dev/0/ */
234 PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */
235 PCFGMNODE pLunL0 = NULL; /* /Devices/Dev/0/LUN#0/ */
236 PCFGMNODE pLunL1 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/ */
237 PCFGMNODE pLunL2 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/Config/ */
238 PCFGMNODE pIdeInst = NULL; /* /Devices/piix3ide/0/ */
239 PCFGMNODE pSataInst = NULL; /* /Devices/ahci/0/ */
240 PCFGMNODE pBiosCfg = NULL; /* /Devices/pcbios/0/Config/ */
241#ifdef VBOX_WITH_INFO_SVC
242 PCFGMNODE pGuest = NULL; /* /Guest */
243 PCFGMNODE pRegistry = NULL; /* /Guest/Registry */
244#endif /* VBOX_WITH_INFO_SVC defined */
245
246 rc = CFGMR3InsertNode(pRoot, "Devices", &pDevices); RC_CHECK();
247
248 /*
249 * PC Arch.
250 */
251 rc = CFGMR3InsertNode(pDevices, "pcarch", &pDev); RC_CHECK();
252 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
253 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
254 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
255
256 /*
257 * PC Bios.
258 */
259 rc = CFGMR3InsertNode(pDevices, "pcbios", &pDev); RC_CHECK();
260 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
261 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
262 rc = CFGMR3InsertNode(pInst, "Config", &pBiosCfg); RC_CHECK();
263 rc = CFGMR3InsertInteger(pBiosCfg, "RamSize", cRamMBs * _1M); RC_CHECK();
264 rc = CFGMR3InsertString(pBiosCfg, "HardDiskDevice", "piix3ide"); RC_CHECK();
265 rc = CFGMR3InsertString(pBiosCfg, "FloppyDevice", "i82078"); RC_CHECK();
266 rc = CFGMR3InsertInteger(pBiosCfg, "IOAPIC", fIOAPIC); RC_CHECK();
267 rc = CFGMR3InsertInteger(pBiosCfg, "PXEDebug", fPXEDebug); RC_CHECK();
268 rc = CFGMR3InsertBytes(pBiosCfg, "UUID", pUuid, sizeof(*pUuid)); RC_CHECK();
269
270 DeviceType_T bootDevice;
271 if (SchemaDefs::MaxBootPosition > 9)
272 {
273 AssertMsgFailed (("Too many boot devices %d\n",
274 SchemaDefs::MaxBootPosition));
275 return VERR_INVALID_PARAMETER;
276 }
277
278 for (ULONG pos = 1; pos <= SchemaDefs::MaxBootPosition; pos ++)
279 {
280 hrc = pMachine->GetBootOrder(pos, &bootDevice); H();
281
282 char szParamName[] = "BootDeviceX";
283 szParamName[sizeof (szParamName) - 2] = ((char (pos - 1)) + '0');
284
285 const char *pszBootDevice;
286 switch (bootDevice)
287 {
288 case DeviceType_Null:
289 pszBootDevice = "NONE";
290 break;
291 case DeviceType_HardDisk:
292 pszBootDevice = "IDE";
293 break;
294 case DeviceType_DVD:
295 pszBootDevice = "DVD";
296 break;
297 case DeviceType_Floppy:
298 pszBootDevice = "FLOPPY";
299 break;
300 case DeviceType_Network:
301 pszBootDevice = "LAN";
302 break;
303 default:
304 AssertMsgFailed(("Invalid bootDevice=%d\n", bootDevice));
305 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
306 N_("Invalid boot device '%d'"), bootDevice);
307 }
308 rc = CFGMR3InsertString(pBiosCfg, szParamName, pszBootDevice); RC_CHECK();
309 }
310
311 /*
312 * The time offset
313 */
314 LONG64 timeOffset;
315 hrc = biosSettings->COMGETTER(TimeOffset)(&timeOffset); H();
316 PCFGMNODE pTMNode;
317 rc = CFGMR3InsertNode(pRoot, "TM", &pTMNode); RC_CHECK();
318 rc = CFGMR3InsertInteger(pTMNode, "UTCOffset", timeOffset * 1000000); RC_CHECK();
319
320 /*
321 * DMA
322 */
323 rc = CFGMR3InsertNode(pDevices, "8237A", &pDev); RC_CHECK();
324 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
325 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
326
327 /*
328 * PCI bus.
329 */
330 rc = CFGMR3InsertNode(pDevices, "pci", &pDev); /* piix3 */ RC_CHECK();
331 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
332 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
333 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
334 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
335
336 /*
337 * PS/2 keyboard & mouse.
338 */
339 rc = CFGMR3InsertNode(pDevices, "pckbd", &pDev); RC_CHECK();
340 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
341 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
342 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
343
344 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
345 rc = CFGMR3InsertString(pLunL0, "Driver", "KeyboardQueue"); RC_CHECK();
346 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
347 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 64); RC_CHECK();
348
349 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
350 rc = CFGMR3InsertString(pLunL1, "Driver", "MainKeyboard"); RC_CHECK();
351 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
352 Keyboard *pKeyboard = pConsole->mKeyboard;
353 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pKeyboard); RC_CHECK();
354
355 rc = CFGMR3InsertNode(pInst, "LUN#1", &pLunL0); RC_CHECK();
356 rc = CFGMR3InsertString(pLunL0, "Driver", "MouseQueue"); RC_CHECK();
357 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
358 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 128); RC_CHECK();
359
360 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
361 rc = CFGMR3InsertString(pLunL1, "Driver", "MainMouse"); RC_CHECK();
362 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
363 Mouse *pMouse = pConsole->mMouse;
364 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pMouse); RC_CHECK();
365
366 /*
367 * i82078 Floppy drive controller
368 */
369 ComPtr<IFloppyDrive> floppyDrive;
370 hrc = pMachine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam()); H();
371 BOOL fFdcEnabled;
372 hrc = floppyDrive->COMGETTER(Enabled)(&fFdcEnabled); H();
373 if (fFdcEnabled)
374 {
375 rc = CFGMR3InsertNode(pDevices, "i82078", &pDev); RC_CHECK();
376 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
377 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); RC_CHECK();
378 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
379 rc = CFGMR3InsertInteger(pCfg, "IRQ", 6); RC_CHECK();
380 rc = CFGMR3InsertInteger(pCfg, "DMA", 2); RC_CHECK();
381 rc = CFGMR3InsertInteger(pCfg, "MemMapped", 0 ); RC_CHECK();
382 rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x3f0); RC_CHECK();
383
384 /* Attach the status driver */
385 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
386 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
387 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
388 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapFDLeds[0]); RC_CHECK();
389 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
390 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
391
392 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
393
394 ComPtr<IFloppyImage> floppyImage;
395 hrc = floppyDrive->GetImage(floppyImage.asOutParam()); H();
396 if (floppyImage)
397 {
398 pConsole->meFloppyState = DriveState_ImageMounted;
399 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK();
400 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
401 rc = CFGMR3InsertString(pCfg, "Type", "Floppy 1.44"); RC_CHECK();
402 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK();
403
404 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
405 rc = CFGMR3InsertString(pLunL1, "Driver", "RawImage"); RC_CHECK();
406 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
407 hrc = floppyImage->COMGETTER(FilePath)(&str); H();
408 STR_CONV();
409 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
410 STR_FREE();
411 }
412 else
413 {
414 ComPtr<IHostFloppyDrive> hostFloppyDrive;
415 hrc = floppyDrive->GetHostDrive(hostFloppyDrive.asOutParam()); H();
416 if (hostFloppyDrive)
417 {
418 pConsole->meFloppyState = DriveState_HostDriveCaptured;
419 rc = CFGMR3InsertString(pLunL0, "Driver", "HostFloppy"); RC_CHECK();
420 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
421 hrc = hostFloppyDrive->COMGETTER(Name)(&str); H();
422 STR_CONV();
423 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
424 STR_FREE();
425 }
426 else
427 {
428 pConsole->meFloppyState = DriveState_NotMounted;
429 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK();
430 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
431 rc = CFGMR3InsertString(pCfg, "Type", "Floppy 1.44"); RC_CHECK();
432 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK();
433 }
434 }
435 }
436
437 /*
438 * ACPI
439 */
440 BOOL fACPI;
441 hrc = biosSettings->COMGETTER(ACPIEnabled)(&fACPI); H();
442 if (fACPI)
443 {
444 rc = CFGMR3InsertNode(pDevices, "acpi", &pDev); RC_CHECK();
445 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
446 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
447 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
448 rc = CFGMR3InsertInteger(pCfg, "RamSize", cRamMBs * _1M); RC_CHECK();
449 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
450 rc = CFGMR3InsertInteger(pCfg, "FdcEnabled", fFdcEnabled); RC_CHECK();
451 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 7); RC_CHECK();
452 Assert(!afPciDeviceNo[7]);
453 afPciDeviceNo[7] = true;
454 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
455
456 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
457 rc = CFGMR3InsertString(pLunL0, "Driver", "ACPIHost"); RC_CHECK();
458 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
459 }
460
461 /*
462 * i8254 Programmable Interval Timer And Dummy Speaker
463 */
464 rc = CFGMR3InsertNode(pDevices, "i8254", &pDev); RC_CHECK();
465 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
466 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
467#ifdef DEBUG
468 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
469#endif
470
471 /*
472 * i8259 Programmable Interrupt Controller.
473 */
474 rc = CFGMR3InsertNode(pDevices, "i8259", &pDev); RC_CHECK();
475 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
476 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
477 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
478
479 /*
480 * Advanced Programmable Interrupt Controller.
481 */
482 rc = CFGMR3InsertNode(pDevices, "apic", &pDev); RC_CHECK();
483 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
484 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
485 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
486 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();
487
488 if (fIOAPIC)
489 {
490 /*
491 * I/O Advanced Programmable Interrupt Controller.
492 */
493 rc = CFGMR3InsertNode(pDevices, "ioapic", &pDev); RC_CHECK();
494 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
495 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
496 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
497 }
498
499 /*
500 * RTC MC146818.
501 */
502 rc = CFGMR3InsertNode(pDevices, "mc146818", &pDev); RC_CHECK();
503 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
504 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
505
506 /*
507 * VGA.
508 */
509 rc = CFGMR3InsertNode(pDevices, "vga", &pDev); RC_CHECK();
510 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
511 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
512 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 2); RC_CHECK();
513 Assert(!afPciDeviceNo[2]);
514 afPciDeviceNo[2] = true;
515 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
516 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
517 hrc = pMachine->COMGETTER(VRAMSize)(&cRamMBs); H();
518 rc = CFGMR3InsertInteger(pCfg, "VRamSize", cRamMBs * _1M); RC_CHECK();
519
520 /*
521 * BIOS logo
522 */
523 BOOL fFadeIn;
524 hrc = biosSettings->COMGETTER(LogoFadeIn)(&fFadeIn); H();
525 rc = CFGMR3InsertInteger(pCfg, "FadeIn", fFadeIn ? 1 : 0); RC_CHECK();
526 BOOL fFadeOut;
527 hrc = biosSettings->COMGETTER(LogoFadeOut)(&fFadeOut); H();
528 rc = CFGMR3InsertInteger(pCfg, "FadeOut", fFadeOut ? 1: 0); RC_CHECK();
529 ULONG logoDisplayTime;
530 hrc = biosSettings->COMGETTER(LogoDisplayTime)(&logoDisplayTime); H();
531 rc = CFGMR3InsertInteger(pCfg, "LogoTime", logoDisplayTime); RC_CHECK();
532 Bstr logoImagePath;
533 hrc = biosSettings->COMGETTER(LogoImagePath)(logoImagePath.asOutParam()); H();
534 rc = CFGMR3InsertString(pCfg, "LogoFile", logoImagePath ? Utf8Str(logoImagePath) : ""); RC_CHECK();
535
536 /*
537 * Boot menu
538 */
539 BIOSBootMenuMode_T bootMenuMode;
540 int value;
541 biosSettings->COMGETTER(BootMenuMode)(&bootMenuMode);
542 switch (bootMenuMode)
543 {
544 case BIOSBootMenuMode_Disabled:
545 value = 0;
546 break;
547 case BIOSBootMenuMode_MenuOnly:
548 value = 1;
549 break;
550 default:
551 value = 2;
552 }
553 rc = CFGMR3InsertInteger(pCfg, "ShowBootMenu", value); RC_CHECK();
554
555 /* Custom VESA mode list */
556 unsigned cModes = 0;
557 for (unsigned iMode = 1; iMode <= 16; iMode++)
558 {
559 char szExtraDataKey[sizeof("CustomVideoModeXX")];
560 RTStrPrintf(szExtraDataKey, sizeof(szExtraDataKey), "CustomVideoMode%d", iMode);
561 hrc = pMachine->GetExtraData(Bstr(szExtraDataKey), &str); H();
562 if (!str || !*str)
563 break;
564 STR_CONV();
565 rc = CFGMR3InsertString(pCfg, szExtraDataKey, psz);
566 STR_FREE();
567 cModes++;
568 }
569 rc = CFGMR3InsertInteger(pCfg, "CustomVideoModes", cModes);
570
571 /* VESA height reduction */
572 ULONG ulHeightReduction;
573 IFramebuffer *pFramebuffer = pConsole->getDisplay()->getFramebuffer();
574 if (pFramebuffer)
575 {
576 hrc = pFramebuffer->COMGETTER(HeightReduction)(&ulHeightReduction); H();
577 }
578 else
579 {
580 /* If framebuffer is not available, there is no height reduction. */
581 ulHeightReduction = 0;
582 }
583 rc = CFGMR3InsertInteger(pCfg, "HeightReduction", ulHeightReduction); RC_CHECK();
584
585 /* Attach the display. */
586 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
587 rc = CFGMR3InsertString(pLunL0, "Driver", "MainDisplay"); RC_CHECK();
588 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
589 Display *pDisplay = pConsole->mDisplay;
590 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pDisplay); RC_CHECK();
591
592 /*
593 * IDE (update this when the main interface changes)
594 */
595 rc = CFGMR3InsertNode(pDevices, "piix3ide", &pDev); /* piix3 */ RC_CHECK();
596 rc = CFGMR3InsertNode(pDev, "0", &pIdeInst); RC_CHECK();
597 rc = CFGMR3InsertInteger(pIdeInst, "Trusted", 1); /* boolean */ RC_CHECK();
598 rc = CFGMR3InsertInteger(pIdeInst, "PCIDeviceNo", 1); RC_CHECK();
599 Assert(!afPciDeviceNo[1]);
600 afPciDeviceNo[1] = true;
601 rc = CFGMR3InsertInteger(pIdeInst, "PCIFunctionNo", 1); RC_CHECK();
602 rc = CFGMR3InsertNode(pIdeInst, "Config", &pCfg); RC_CHECK();
603 rc = CFGMR3InsertInteger(pCfg, "PIIX4", fPIIX4); /* boolean */ RC_CHECK();
604
605 /* Attach the status driver */
606 rc = CFGMR3InsertNode(pIdeInst, "LUN#999", &pLunL0); RC_CHECK();
607 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
608 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
609 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapIDELeds[0]);RC_CHECK();
610 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
611 rc = CFGMR3InsertInteger(pCfg, "Last", 3); RC_CHECK();
612
613 /*
614 * SATA controller
615 */
616 ComPtr<ISATAController> sataController;
617 hrc = pMachine->COMGETTER(SATAController)(sataController.asOutParam());
618 BOOL enabled = FALSE;
619
620 if (sataController)
621 {
622 hrc = sataController->COMGETTER(Enabled)(&enabled); H();
623
624 if (enabled)
625 {
626 rc = CFGMR3InsertNode(pDevices, "ahci", &pDev); RC_CHECK();
627 rc = CFGMR3InsertNode(pDev, "0", &pSataInst); RC_CHECK();
628 rc = CFGMR3InsertInteger(pSataInst, "Trusted", 1); RC_CHECK();
629 rc = CFGMR3InsertInteger(pSataInst, "PCIDeviceNo", 13); RC_CHECK();
630 Assert(!afPciDeviceNo[13]);
631 afPciDeviceNo[13] = true;
632 rc = CFGMR3InsertInteger(pSataInst, "PCIFunctionNo", 0); RC_CHECK();
633 rc = CFGMR3InsertNode(pSataInst, "Config", &pCfg); RC_CHECK();
634
635 ULONG cPorts = 0;
636 hrc = sataController->COMGETTER(PortCount)(&cPorts); H();
637 rc = CFGMR3InsertInteger(pCfg, "PortCount", cPorts); RC_CHECK();
638
639 /* Needed configuration values for the bios. */
640 rc = CFGMR3InsertString(pBiosCfg, "SataHardDiskDevice", "ahci"); RC_CHECK();
641
642 for (uint32_t i = 0; i < 4; i++)
643 {
644 static const char *s_apszConfig[4] =
645 { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" };
646 static const char *s_apszBiosConfig[4] =
647 { "SataPrimaryMasterLUN", "SataPrimarySlaveLUN", "SataSecondaryMasterLUN", "SataSecondarySlaveLUN" };
648
649 LONG lPortNumber = -1;
650 hrc = sataController->GetIDEEmulationPort(i, &lPortNumber); H();
651 rc = CFGMR3InsertInteger(pCfg, s_apszConfig[i], lPortNumber); RC_CHECK();
652 rc = CFGMR3InsertInteger(pBiosCfg, s_apszBiosConfig[i], lPortNumber); RC_CHECK();
653 }
654
655 /* Attach the status driver */
656 rc = CFGMR3InsertNode(pSataInst,"LUN#999", &pLunL0); RC_CHECK();
657 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
658 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
659 AssertRelease(cPorts <= RT_ELEMENTS(pConsole->mapSATALeds));
660 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapSATALeds[0]); RC_CHECK();
661 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
662 rc = CFGMR3InsertInteger(pCfg, "Last", cPorts - 1); RC_CHECK();
663 }
664 }
665
666 /* Attach the harddisks */
667 ComPtr<IHardDiskAttachmentCollection> hdaColl;
668 hrc = pMachine->COMGETTER(HardDiskAttachments)(hdaColl.asOutParam()); H();
669 ComPtr<IHardDiskAttachmentEnumerator> hdaEnum;
670 hrc = hdaColl->Enumerate(hdaEnum.asOutParam()); H();
671
672 BOOL fMore = FALSE;
673 while ( SUCCEEDED(hrc = hdaEnum->HasMore(&fMore))
674 && fMore)
675 {
676 PCFGMNODE pHardDiskCtl;
677 ComPtr<IHardDiskAttachment> hda;
678 hrc = hdaEnum->GetNext(hda.asOutParam()); H();
679 ComPtr<IHardDisk> hardDisk;
680 hrc = hda->COMGETTER(HardDisk)(hardDisk.asOutParam()); H();
681 StorageBus_T enmBus;
682 hrc = hda->COMGETTER(Bus)(&enmBus); H();
683 LONG lDev;
684 hrc = hda->COMGETTER(Device)(&lDev); H();
685 LONG lChannel;
686 hrc = hda->COMGETTER(Channel)(&lChannel); H();
687
688 int iLUN;
689 switch (enmBus)
690 {
691 case StorageBus_IDE:
692 {
693 if (lChannel >= 2 || lChannel < 0)
694 {
695 AssertMsgFailed(("invalid controller channel number: %d\n", lChannel));
696 return VERR_GENERAL_FAILURE;
697 }
698
699 if (lDev >= 2 || lDev < 0)
700 {
701 AssertMsgFailed(("invalid controller device number: %d\n", lDev));
702 return VERR_GENERAL_FAILURE;
703 }
704 iLUN = 2*lChannel + lDev;
705 pHardDiskCtl = pIdeInst;
706 }
707 break;
708 case StorageBus_SATA:
709 iLUN = lChannel;
710 pHardDiskCtl = enabled ? pSataInst : NULL;
711 break;
712 default:
713 AssertMsgFailed(("invalid disk controller type: %d\n", enmBus));
714 return VERR_GENERAL_FAILURE;
715 }
716
717 /* Can be NULL if SATA controller is not enabled and current hard disk is attached to SATA controller. */
718 if (pHardDiskCtl)
719 {
720 char szLUN[16];
721 RTStrPrintf(szLUN, sizeof(szLUN), "LUN#%d", iLUN);
722 rc = CFGMR3InsertNode(pHardDiskCtl, szLUN, &pLunL0); RC_CHECK();
723 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK();
724 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
725 rc = CFGMR3InsertString(pCfg, "Type", "HardDisk"); RC_CHECK();
726 rc = CFGMR3InsertInteger(pCfg, "Mountable", 0); RC_CHECK();
727
728 HardDiskStorageType_T hddType;
729 hardDisk->COMGETTER(StorageType)(&hddType);
730 if (hddType == HardDiskStorageType_VirtualDiskImage)
731 {
732 ComPtr<IVirtualDiskImage> vdiDisk = hardDisk;
733 AssertBreakStmt (!vdiDisk.isNull(), hrc = E_FAIL);
734
735 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
736 rc = CFGMR3InsertString(pLunL1, "Driver", "VBoxHDD"); RC_CHECK();
737 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
738 hrc = vdiDisk->COMGETTER(FilePath)(&str); H();
739 STR_CONV();
740 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
741 STR_FREE();
742
743 /* Create an inversed tree of parents. */
744 ComPtr<IHardDisk> parentHardDisk = hardDisk;
745 for (PCFGMNODE pParent = pCfg;;)
746 {
747 ComPtr<IHardDisk> curHardDisk;
748 hrc = parentHardDisk->COMGETTER(Parent)(curHardDisk.asOutParam()); H();
749 if (!curHardDisk)
750 break;
751
752 vdiDisk = curHardDisk;
753 AssertBreakStmt (!vdiDisk.isNull(), hrc = E_FAIL);
754
755 PCFGMNODE pCur;
756 rc = CFGMR3InsertNode(pParent, "Parent", &pCur); RC_CHECK();
757 hrc = vdiDisk->COMGETTER(FilePath)(&str); H();
758 STR_CONV();
759 rc = CFGMR3InsertString(pCur, "Path", psz); RC_CHECK();
760 STR_FREE();
761 rc = CFGMR3InsertInteger(pCur, "ReadOnly", 1); RC_CHECK();
762
763 /* next */
764 pParent = pCur;
765 parentHardDisk = curHardDisk;
766 }
767 }
768 else if (hddType == HardDiskStorageType_ISCSIHardDisk)
769 {
770 ComPtr<IISCSIHardDisk> iSCSIDisk = hardDisk;
771 AssertBreakStmt (!iSCSIDisk.isNull(), hrc = E_FAIL);
772
773 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
774 rc = CFGMR3InsertString(pLunL1, "Driver", "iSCSI"); RC_CHECK();
775 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
776
777 /* Set up the iSCSI initiator driver configuration. */
778 hrc = iSCSIDisk->COMGETTER(Target)(&str); H();
779 STR_CONV();
780 rc = CFGMR3InsertString(pCfg, "TargetName", psz); RC_CHECK();
781 STR_FREE();
782
783 // @todo currently there is no Initiator name config.
784 rc = CFGMR3InsertString(pCfg, "InitiatorName", "iqn.2008-04.com.sun.virtualbox.initiator"); RC_CHECK();
785
786 ULONG64 lun;
787 hrc = iSCSIDisk->COMGETTER(Lun)(&lun); H();
788 rc = CFGMR3InsertInteger(pCfg, "LUN", lun); RC_CHECK();
789
790 hrc = iSCSIDisk->COMGETTER(Server)(&str); H();
791 STR_CONV();
792 USHORT port;
793 hrc = iSCSIDisk->COMGETTER(Port)(&port); H();
794 if (port != 0)
795 {
796 char *pszTN;
797 RTStrAPrintf(&pszTN, "%s:%u", psz, port);
798 rc = CFGMR3InsertString(pCfg, "TargetAddress", pszTN); RC_CHECK();
799 RTStrFree(pszTN);
800 }
801 else
802 {
803 rc = CFGMR3InsertString(pCfg, "TargetAddress", psz); RC_CHECK();
804 }
805 STR_FREE();
806
807 hrc = iSCSIDisk->COMGETTER(UserName)(&str); H();
808 if (str)
809 {
810 STR_CONV();
811 rc = CFGMR3InsertString(pCfg, "InitiatorUsername", psz); RC_CHECK();
812 STR_FREE();
813 }
814
815 hrc = iSCSIDisk->COMGETTER(Password)(&str); H();
816 if (str)
817 {
818 STR_CONV();
819 rc = CFGMR3InsertString(pCfg, "InitiatorSecret", psz); RC_CHECK();
820 STR_FREE();
821 }
822
823 // @todo currently there is no target username config.
824 //rc = CFGMR3InsertString(pCfg, "TargetUsername", ""); RC_CHECK();
825
826 // @todo currently there is no target password config.
827 //rc = CFGMR3InsertString(pCfg, "TargetSecret", ""); RC_CHECK();
828
829 /* The iSCSI initiator needs an attached iSCSI transport driver. */
830 rc = CFGMR3InsertNode(pLunL1, "AttachedDriver", &pLunL2); RC_CHECK();
831 rc = CFGMR3InsertString(pLunL2, "Driver", "iSCSITCP"); RC_CHECK();
832 /* Currently the transport driver has no config options. */
833 }
834 else if (hddType == HardDiskStorageType_VMDKImage)
835 {
836 ComPtr<IVMDKImage> vmdkDisk = hardDisk;
837 AssertBreakStmt (!vmdkDisk.isNull(), hrc = E_FAIL);
838
839 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
840#if 1 /* Enable new VD container code (and new VMDK), as the bugs are fixed. */
841 rc = CFGMR3InsertString(pLunL1, "Driver", "VD"); RC_CHECK();
842#else
843 rc = CFGMR3InsertString(pLunL1, "Driver", "VmdkHDD"); RC_CHECK();
844#endif
845 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
846 hrc = vmdkDisk->COMGETTER(FilePath)(&str); H();
847 STR_CONV();
848 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
849 STR_FREE();
850 rc = CFGMR3InsertString(pCfg, "Format", "VMDK"); RC_CHECK();
851 }
852 else if (hddType == HardDiskStorageType_CustomHardDisk)
853 {
854 ComPtr<ICustomHardDisk> customHardDisk = hardDisk;
855 AssertBreakStmt (!customHardDisk.isNull(), hrc = E_FAIL);
856
857 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
858 rc = CFGMR3InsertString(pLunL1, "Driver", "VD"); RC_CHECK();
859 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
860 hrc = customHardDisk->COMGETTER(Location)(&str); H();
861 STR_CONV();
862 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
863 STR_FREE();
864 hrc = customHardDisk->COMGETTER(Format)(&str); H();
865 STR_CONV();
866 rc = CFGMR3InsertString(pCfg, "Format", psz); RC_CHECK();
867 STR_FREE();
868 }
869 else if (hddType == HardDiskStorageType_VHDImage)
870 {
871 ComPtr<IVHDImage> vhdDisk = hardDisk;
872 AssertBreakStmt (!vhdDisk.isNull(), hrc = E_FAIL);
873
874 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
875 rc = CFGMR3InsertString(pLunL1, "Driver", "VD"); RC_CHECK();
876 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
877 hrc = vhdDisk->COMGETTER(FilePath)(&str); H();
878 STR_CONV();
879 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
880 rc = CFGMR3InsertString(pCfg, "Format", "VHD"); RC_CHECK();
881 STR_FREE();
882 }
883 else
884 AssertFailed();
885 }
886 }
887 H();
888
889 ComPtr<IDVDDrive> dvdDrive;
890 hrc = pMachine->COMGETTER(DVDDrive)(dvdDrive.asOutParam()); H();
891 if (dvdDrive)
892 {
893 // ASSUME: DVD drive is always attached to LUN#2 (i.e. secondary IDE master)
894 rc = CFGMR3InsertNode(pIdeInst, "LUN#2", &pLunL0); RC_CHECK();
895 ComPtr<IHostDVDDrive> hostDvdDrive;
896 hrc = dvdDrive->GetHostDrive(hostDvdDrive.asOutParam()); H();
897 if (hostDvdDrive)
898 {
899 pConsole->meDVDState = DriveState_HostDriveCaptured;
900 rc = CFGMR3InsertString(pLunL0, "Driver", "HostDVD"); RC_CHECK();
901 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
902 hrc = hostDvdDrive->COMGETTER(Name)(&str); H();
903 STR_CONV();
904 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
905 STR_FREE();
906 BOOL fPassthrough;
907 hrc = dvdDrive->COMGETTER(Passthrough)(&fPassthrough); H();
908 rc = CFGMR3InsertInteger(pCfg, "Passthrough", !!fPassthrough); RC_CHECK();
909 }
910 else
911 {
912 pConsole->meDVDState = DriveState_NotMounted;
913 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK();
914 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
915 rc = CFGMR3InsertString(pCfg, "Type", "DVD"); RC_CHECK();
916 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK();
917
918 ComPtr<IDVDImage> dvdImage;
919 hrc = dvdDrive->GetImage(dvdImage.asOutParam()); H();
920 if (dvdImage)
921 {
922 pConsole->meDVDState = DriveState_ImageMounted;
923 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
924 rc = CFGMR3InsertString(pLunL1, "Driver", "MediaISO"); RC_CHECK();
925 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK();
926 hrc = dvdImage->COMGETTER(FilePath)(&str); H();
927 STR_CONV();
928 rc = CFGMR3InsertString(pCfg, "Path", psz); RC_CHECK();
929 STR_FREE();
930 }
931 }
932 }
933
934 /*
935 * Network adapters
936 */
937 PCFGMNODE pDevPCNet = NULL; /* PCNet-type devices */
938 rc = CFGMR3InsertNode(pDevices, "pcnet", &pDevPCNet); RC_CHECK();
939#ifdef VBOX_WITH_E1000
940 PCFGMNODE pDevE1000 = NULL; /* E1000-type devices */
941 rc = CFGMR3InsertNode(pDevices, "e1000", &pDevE1000); RC_CHECK();
942#endif
943 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::NetworkAdapterCount; ulInstance++)
944 {
945 ComPtr<INetworkAdapter> networkAdapter;
946 hrc = pMachine->GetNetworkAdapter(ulInstance, networkAdapter.asOutParam()); H();
947 BOOL fEnabled = FALSE;
948 hrc = networkAdapter->COMGETTER(Enabled)(&fEnabled); H();
949 if (!fEnabled)
950 continue;
951
952 /*
953 * The virtual hardware type. Create appropriate device first.
954 */
955 NetworkAdapterType_T adapterType;
956 hrc = networkAdapter->COMGETTER(AdapterType)(&adapterType); H();
957 switch (adapterType)
958 {
959 case NetworkAdapterType_Am79C970A:
960 case NetworkAdapterType_Am79C973:
961 pDev = pDevPCNet;
962 break;
963#ifdef VBOX_WITH_E1000
964 case NetworkAdapterType_I82540EM:
965 case NetworkAdapterType_I82543GC:
966 pDev = pDevE1000;
967 break;
968#endif
969 default:
970 AssertMsgFailed(("Invalid network adapter type '%d' for slot '%d'",
971 adapterType, ulInstance));
972 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS,
973 N_("Invalid network adapter type '%d' for slot '%d'"),
974 adapterType, ulInstance);
975 }
976
977 char szInstance[4]; Assert(ulInstance <= 999);
978 RTStrPrintf(szInstance, sizeof(szInstance), "%lu", ulInstance);
979 rc = CFGMR3InsertNode(pDev, szInstance, &pInst); RC_CHECK();
980 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
981 /* the first network card gets the PCI ID 3, the next 3 gets 8..10. */
982 const unsigned iPciDeviceNo = !ulInstance ? 3 : ulInstance - 1 + 8;
983 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", iPciDeviceNo); RC_CHECK();
984 Assert(!afPciDeviceNo[iPciDeviceNo]);
985 afPciDeviceNo[iPciDeviceNo] = true;
986 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
987 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
988
989 /*
990 * The virtual hardware type. PCNet supports two types.
991 */
992 switch (adapterType)
993 {
994 case NetworkAdapterType_Am79C970A:
995 rc = CFGMR3InsertInteger(pCfg, "Am79C973", 0); RC_CHECK();
996 break;
997 case NetworkAdapterType_Am79C973:
998 rc = CFGMR3InsertInteger(pCfg, "Am79C973", 1); RC_CHECK();
999 break;
1000 case NetworkAdapterType_I82540EM:
1001 rc = CFGMR3InsertInteger(pCfg, "AdapterType", 0); RC_CHECK();
1002 break;
1003 case NetworkAdapterType_I82543GC:
1004 rc = CFGMR3InsertInteger(pCfg, "AdapterType", 1); RC_CHECK();
1005 break;
1006 }
1007
1008 /*
1009 * Get the MAC address and convert it to binary representation
1010 */
1011 Bstr macAddr;
1012 hrc = networkAdapter->COMGETTER(MACAddress)(macAddr.asOutParam()); H();
1013 Assert(macAddr);
1014 Utf8Str macAddrUtf8 = macAddr;
1015 char *macStr = (char*)macAddrUtf8.raw();
1016 Assert(strlen(macStr) == 12);
1017 PDMMAC Mac;
1018 memset(&Mac, 0, sizeof(Mac));
1019 char *pMac = (char*)&Mac;
1020 for (uint32_t i = 0; i < 6; i++)
1021 {
1022 char c1 = *macStr++ - '0';
1023 if (c1 > 9)
1024 c1 -= 7;
1025 char c2 = *macStr++ - '0';
1026 if (c2 > 9)
1027 c2 -= 7;
1028 *pMac++ = ((c1 & 0x0f) << 4) | (c2 & 0x0f);
1029 }
1030 rc = CFGMR3InsertBytes(pCfg, "MAC", &Mac, sizeof(Mac)); RC_CHECK();
1031
1032 /*
1033 * Check if the cable is supposed to be unplugged
1034 */
1035 BOOL fCableConnected;
1036 hrc = networkAdapter->COMGETTER(CableConnected)(&fCableConnected); H();
1037 rc = CFGMR3InsertInteger(pCfg, "CableConnected", fCableConnected ? 1 : 0); RC_CHECK();
1038
1039 /*
1040 * Line speed to report from custom drivers
1041 */
1042 ULONG ulLineSpeed;
1043 hrc = networkAdapter->COMGETTER(LineSpeed)(&ulLineSpeed); H();
1044 rc = CFGMR3InsertInteger(pCfg, "LineSpeed", ulLineSpeed); RC_CHECK();
1045
1046 /*
1047 * Attach the status driver.
1048 */
1049 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1050 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1051 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1052 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapNetworkLeds[ulInstance]); RC_CHECK();
1053
1054 /*
1055 * Enable the packet sniffer if requested.
1056 */
1057 BOOL fSniffer;
1058 hrc = networkAdapter->COMGETTER(TraceEnabled)(&fSniffer); H();
1059 if (fSniffer)
1060 {
1061 /* insert the sniffer filter driver. */
1062 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1063 rc = CFGMR3InsertString(pLunL0, "Driver", "NetSniffer"); RC_CHECK();
1064 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1065 hrc = networkAdapter->COMGETTER(TraceFile)(&str); H();
1066 if (str) /* check convention for indicating default file. */
1067 {
1068 STR_CONV();
1069 rc = CFGMR3InsertString(pCfg, "File", psz); RC_CHECK();
1070 STR_FREE();
1071 }
1072 }
1073
1074 NetworkAttachmentType_T networkAttachment;
1075 hrc = networkAdapter->COMGETTER(AttachmentType)(&networkAttachment); H();
1076 switch (networkAttachment)
1077 {
1078 case NetworkAttachmentType_Null:
1079 break;
1080
1081 case NetworkAttachmentType_NAT:
1082 {
1083 if (fSniffer)
1084 {
1085 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
1086 }
1087 else
1088 {
1089 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1090 }
1091 rc = CFGMR3InsertString(pLunL0, "Driver", "NAT"); RC_CHECK();
1092 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1093 /* (Port forwarding goes here.) */
1094
1095 /* Configure TFTP prefix and boot filename. */
1096 hrc = virtualBox->COMGETTER(HomeFolder)(&str); H();
1097 STR_CONV();
1098 if (psz && *psz)
1099 {
1100 char *pszTFTPPrefix = NULL;
1101 RTStrAPrintf(&pszTFTPPrefix, "%s%c%s", psz, RTPATH_DELIMITER, "TFTP");
1102 rc = CFGMR3InsertString(pCfg, "TFTPPrefix", pszTFTPPrefix); RC_CHECK();
1103 RTStrFree(pszTFTPPrefix);
1104 }
1105 STR_FREE();
1106 hrc = pMachine->COMGETTER(Name)(&str); H();
1107 STR_CONV();
1108 char *pszBootFile = NULL;
1109 RTStrAPrintf(&pszBootFile, "%s.pxe", psz);
1110 STR_FREE();
1111 rc = CFGMR3InsertString(pCfg, "BootFile", pszBootFile); RC_CHECK();
1112 RTStrFree(pszBootFile);
1113
1114 hrc = networkAdapter->COMGETTER(NATNetwork)(&str); H();
1115 if (str)
1116 {
1117 STR_CONV();
1118 if (psz && *psz)
1119 rc = CFGMR3InsertString(pCfg, "Network", psz); RC_CHECK();
1120 STR_FREE();
1121 }
1122 break;
1123 }
1124
1125 case NetworkAttachmentType_HostInterface:
1126 {
1127 /*
1128 * Perform the attachment if required (don't return on error!)
1129 */
1130 hrc = pConsole->attachToHostInterface(networkAdapter);
1131 if (SUCCEEDED(hrc))
1132 {
1133#ifdef VBOX_WITH_UNIXY_TAP_NETWORKING
1134 Assert (pConsole->maTapFD[ulInstance] >= 0);
1135 if (pConsole->maTapFD[ulInstance] >= 0)
1136 {
1137 if (fSniffer)
1138 {
1139 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
1140 }
1141 else
1142 {
1143 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1144 }
1145 rc = CFGMR3InsertString(pLunL0, "Driver", "HostInterface"); RC_CHECK();
1146 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1147# if defined(RT_OS_SOLARIS)
1148 /* Device name/number is required for Solaris as we need it for TAP PPA. */
1149 Bstr tapDeviceName;
1150 networkAdapter->COMGETTER(HostInterface)(tapDeviceName.asOutParam());
1151 if (!tapDeviceName.isEmpty())
1152 rc = CFGMR3InsertString(pCfg, "Device", Utf8Str(tapDeviceName)); RC_CHECK();
1153
1154 /* TAP setup application/script */
1155 Bstr tapSetupApp;
1156 networkAdapter->COMGETTER(TAPSetupApplication)(tapSetupApp.asOutParam());
1157 if (!tapSetupApp.isEmpty())
1158 rc = CFGMR3InsertString(pCfg, "TAPSetupApplication", Utf8Str(tapSetupApp)); RC_CHECK();
1159
1160 /* TAP terminate application/script */
1161 Bstr tapTerminateApp;
1162 networkAdapter->COMGETTER(TAPTerminateApplication)(tapTerminateApp.asOutParam());
1163 if (!tapTerminateApp.isEmpty())
1164 rc = CFGMR3InsertString(pCfg, "TAPTerminateApplication", Utf8Str(tapTerminateApp)); RC_CHECK();
1165
1166 /* "FileHandle" must NOT be inserted here, it is done in DrvTAP.cpp */
1167
1168# ifdef VBOX_WITH_CROSSBOW
1169 /* Crossbow: needs the MAC address for setting up TAP. */
1170 rc = CFGMR3InsertBytes(pCfg, "MAC", &Mac, sizeof(Mac)); RC_CHECK();
1171# endif
1172# else
1173 rc = CFGMR3InsertInteger(pCfg, "FileHandle", pConsole->maTapFD[ulInstance]); RC_CHECK();
1174# endif
1175 }
1176#elif defined(RT_OS_WINDOWS)
1177 if (fSniffer)
1178 {
1179 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
1180 }
1181 else
1182 {
1183 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1184 }
1185 Bstr hostInterfaceName;
1186 hrc = networkAdapter->COMGETTER(HostInterface)(hostInterfaceName.asOutParam()); H();
1187 ComPtr<IHostNetworkInterfaceCollection> coll;
1188 hrc = host->COMGETTER(NetworkInterfaces)(coll.asOutParam()); H();
1189 ComPtr<IHostNetworkInterface> hostInterface;
1190 rc = coll->FindByName(hostInterfaceName, hostInterface.asOutParam());
1191 if (!SUCCEEDED(rc))
1192 {
1193 AssertMsgFailed(("Cannot get GUID for host interface '%ls'\n", hostInterfaceName));
1194 hrc = networkAdapter->Detach(); H();
1195 }
1196 else
1197 {
1198 rc = CFGMR3InsertString(pLunL0, "Driver", "HostInterface"); RC_CHECK();
1199 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1200 rc = CFGMR3InsertString(pCfg, "HostInterfaceName", Utf8Str(hostInterfaceName)); RC_CHECK();
1201 Guid hostIFGuid;
1202 hrc = hostInterface->COMGETTER(Id)(hostIFGuid.asOutParam()); H();
1203 char szDriverGUID[256] = {0};
1204 /* add curly brackets */
1205 szDriverGUID[0] = '{';
1206 strcpy(szDriverGUID + 1, hostIFGuid.toString().raw());
1207 strcat(szDriverGUID, "}");
1208 rc = CFGMR3InsertBytes(pCfg, "GUID", szDriverGUID, sizeof(szDriverGUID)); RC_CHECK();
1209 }
1210#else
1211# error "Port me"
1212#endif
1213 }
1214 else
1215 {
1216 switch (hrc)
1217 {
1218#ifdef RT_OS_LINUX
1219 case VERR_ACCESS_DENIED:
1220 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_(
1221 "Failed to open '/dev/net/tun' for read/write access. Please check the "
1222 "permissions of that node. Either run 'chmod 0666 /dev/net/tun' or "
1223 "change the group of that node and make yourself a member of that group. Make "
1224 "sure that these changes are permanent, especially if you are "
1225 "using udev"));
1226#endif /* RT_OS_LINUX */
1227 default:
1228 AssertMsgFailed(("Could not attach to host interface! Bad!\n"));
1229 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_(
1230 "Failed to initialize Host Interface Networking"));
1231 }
1232 }
1233 break;
1234 }
1235
1236 case NetworkAttachmentType_Internal:
1237 {
1238 hrc = networkAdapter->COMGETTER(InternalNetwork)(&str); H();
1239 if (str)
1240 {
1241 STR_CONV();
1242 if (psz && *psz)
1243 {
1244 if (fSniffer)
1245 {
1246 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();
1247 }
1248 else
1249 {
1250 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1251 }
1252 rc = CFGMR3InsertString(pLunL0, "Driver", "IntNet"); RC_CHECK();
1253 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1254 rc = CFGMR3InsertString(pCfg, "Network", psz); RC_CHECK();
1255 }
1256 STR_FREE();
1257 }
1258 break;
1259 }
1260
1261 default:
1262 AssertMsgFailed(("should not get here!\n"));
1263 break;
1264 }
1265 }
1266
1267 /*
1268 * Serial (UART) Ports
1269 */
1270 rc = CFGMR3InsertNode(pDevices, "serial", &pDev); RC_CHECK();
1271 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::SerialPortCount; ulInstance++)
1272 {
1273 ComPtr<ISerialPort> serialPort;
1274 hrc = pMachine->GetSerialPort (ulInstance, serialPort.asOutParam()); H();
1275 BOOL fEnabled = FALSE;
1276 if (serialPort)
1277 hrc = serialPort->COMGETTER(Enabled)(&fEnabled); H();
1278 if (!fEnabled)
1279 continue;
1280
1281 char szInstance[4]; Assert(ulInstance <= 999);
1282 RTStrPrintf(szInstance, sizeof(szInstance), "%lu", ulInstance);
1283
1284 rc = CFGMR3InsertNode(pDev, szInstance, &pInst); RC_CHECK();
1285 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1286
1287 ULONG ulIRQ, ulIOBase;
1288 PortMode_T HostMode;
1289 Bstr path;
1290 BOOL fServer;
1291 hrc = serialPort->COMGETTER(HostMode)(&HostMode); H();
1292 hrc = serialPort->COMGETTER(IRQ)(&ulIRQ); H();
1293 hrc = serialPort->COMGETTER(IOBase)(&ulIOBase); H();
1294 hrc = serialPort->COMGETTER(Path)(path.asOutParam()); H();
1295 hrc = serialPort->COMGETTER(Server)(&fServer); H();
1296 rc = CFGMR3InsertInteger(pCfg, "IRQ", ulIRQ); RC_CHECK();
1297 rc = CFGMR3InsertInteger(pCfg, "IOBase", ulIOBase); RC_CHECK();
1298 if (HostMode != PortMode_Disconnected)
1299 {
1300 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1301 if (HostMode == PortMode_HostPipe)
1302 {
1303 rc = CFGMR3InsertString(pLunL0, "Driver", "Char"); RC_CHECK();
1304 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
1305 rc = CFGMR3InsertString(pLunL1, "Driver", "NamedPipe"); RC_CHECK();
1306 rc = CFGMR3InsertNode(pLunL1, "Config", &pLunL2); RC_CHECK();
1307 rc = CFGMR3InsertString(pLunL2, "Location", Utf8Str(path)); RC_CHECK();
1308 rc = CFGMR3InsertInteger(pLunL2, "IsServer", fServer); RC_CHECK();
1309 }
1310 else if (HostMode == PortMode_HostDevice)
1311 {
1312 rc = CFGMR3InsertString(pLunL0, "Driver", "Host Serial"); RC_CHECK();
1313 rc = CFGMR3InsertNode(pLunL0, "Config", &pLunL1); RC_CHECK();
1314 rc = CFGMR3InsertString(pLunL1, "DevicePath", Utf8Str(path)); RC_CHECK();
1315 }
1316 }
1317 }
1318
1319 /*
1320 * Parallel (LPT) Ports
1321 */
1322 rc = CFGMR3InsertNode(pDevices, "parallel", &pDev); RC_CHECK();
1323 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::ParallelPortCount; ulInstance++)
1324 {
1325 ComPtr<IParallelPort> parallelPort;
1326 hrc = pMachine->GetParallelPort (ulInstance, parallelPort.asOutParam()); H();
1327 BOOL fEnabled = FALSE;
1328 if (parallelPort)
1329 hrc = parallelPort->COMGETTER(Enabled)(&fEnabled); H();
1330 if (!fEnabled)
1331 continue;
1332
1333 char szInstance[4]; Assert(ulInstance <= 999);
1334 RTStrPrintf(szInstance, sizeof(szInstance), "%lu", ulInstance);
1335
1336 rc = CFGMR3InsertNode(pDev, szInstance, &pInst); RC_CHECK();
1337 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1338
1339 ULONG ulIRQ, ulIOBase;
1340 Bstr DevicePath;
1341 hrc = parallelPort->COMGETTER(IRQ)(&ulIRQ); H();
1342 hrc = parallelPort->COMGETTER(IOBase)(&ulIOBase); H();
1343 hrc = parallelPort->COMGETTER(Path)(DevicePath.asOutParam()); H();
1344 rc = CFGMR3InsertInteger(pCfg, "IRQ", ulIRQ); RC_CHECK();
1345 rc = CFGMR3InsertInteger(pCfg, "IOBase", ulIOBase); RC_CHECK();
1346 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1347 rc = CFGMR3InsertString(pLunL0, "Driver", "HostParallel"); RC_CHECK();
1348 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK();
1349 rc = CFGMR3InsertString(pLunL1, "DevicePath", Utf8Str(DevicePath)); RC_CHECK();
1350 }
1351
1352 /*
1353 * VMM Device
1354 */
1355 rc = CFGMR3InsertNode(pDevices, "VMMDev", &pDev); RC_CHECK();
1356 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1357 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1358 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1359 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 4); RC_CHECK();
1360 Assert(!afPciDeviceNo[4]);
1361 afPciDeviceNo[4] = true;
1362 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1363
1364 /* the VMM device's Main driver */
1365 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1366 rc = CFGMR3InsertString(pLunL0, "Driver", "MainVMMDev"); RC_CHECK();
1367 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1368 VMMDev *pVMMDev = pConsole->mVMMDev;
1369 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pVMMDev); RC_CHECK();
1370
1371 /*
1372 * Attach the status driver.
1373 */
1374 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1375 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1376 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1377 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapSharedFolderLed); RC_CHECK();
1378 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
1379 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
1380
1381 /*
1382 * Audio Sniffer Device
1383 */
1384 rc = CFGMR3InsertNode(pDevices, "AudioSniffer", &pDev); RC_CHECK();
1385 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1386 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1387
1388 /* the Audio Sniffer device's Main driver */
1389 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1390 rc = CFGMR3InsertString(pLunL0, "Driver", "MainAudioSniffer"); RC_CHECK();
1391 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1392 AudioSniffer *pAudioSniffer = pConsole->mAudioSniffer;
1393 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pAudioSniffer); RC_CHECK();
1394
1395 /*
1396 * AC'97 ICH / SoundBlaster16 audio
1397 */
1398 ComPtr<IAudioAdapter> audioAdapter;
1399 hrc = pMachine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam()); H();
1400 if (audioAdapter)
1401 hrc = audioAdapter->COMGETTER(Enabled)(&enabled); H();
1402
1403 if (enabled)
1404 {
1405 AudioControllerType_T audioController;
1406 hrc = audioAdapter->COMGETTER(AudioController)(&audioController); H();
1407 switch (audioController)
1408 {
1409 case AudioControllerType_AC97:
1410 {
1411 /* default: ICH AC97 */
1412 rc = CFGMR3InsertNode(pDevices, "ichac97", &pDev); RC_CHECK();
1413 rc = CFGMR3InsertNode(pDev, "0", &pInst);
1414 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1415 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 5); RC_CHECK();
1416 Assert(!afPciDeviceNo[5]);
1417 afPciDeviceNo[5] = true;
1418 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1419 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1420 break;
1421 }
1422 case AudioControllerType_SB16:
1423 {
1424 /* legacy SoundBlaster16 */
1425 rc = CFGMR3InsertNode(pDevices, "sb16", &pDev); RC_CHECK();
1426 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1427 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1428 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1429 rc = CFGMR3InsertInteger(pCfg, "IRQ", 5); RC_CHECK();
1430 rc = CFGMR3InsertInteger(pCfg, "DMA", 1); RC_CHECK();
1431 rc = CFGMR3InsertInteger(pCfg, "DMA16", 5); RC_CHECK();
1432 rc = CFGMR3InsertInteger(pCfg, "Port", 0x220); RC_CHECK();
1433 rc = CFGMR3InsertInteger(pCfg, "Version", 0x0405); RC_CHECK();
1434 break;
1435 }
1436 }
1437
1438 /* the Audio driver */
1439 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1440 rc = CFGMR3InsertString(pLunL0, "Driver", "AUDIO"); RC_CHECK();
1441 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1442
1443 AudioDriverType_T audioDriver;
1444 hrc = audioAdapter->COMGETTER(AudioDriver)(&audioDriver); H();
1445 switch (audioDriver)
1446 {
1447 case AudioDriverType_Null:
1448 {
1449 rc = CFGMR3InsertString(pCfg, "AudioDriver", "null"); RC_CHECK();
1450 break;
1451 }
1452#ifdef RT_OS_WINDOWS
1453#ifdef VBOX_WITH_WINMM
1454 case AudioDriverType_WinMM:
1455 {
1456 rc = CFGMR3InsertString(pCfg, "AudioDriver", "winmm"); RC_CHECK();
1457 break;
1458 }
1459#endif
1460 case AudioDriverType_DirectSound:
1461 {
1462 rc = CFGMR3InsertString(pCfg, "AudioDriver", "dsound"); RC_CHECK();
1463 break;
1464 }
1465#endif /* RT_OS_WINDOWS */
1466#ifdef RT_OS_SOLARIS
1467 case AudioDriverType_SolAudio:
1468 {
1469 rc = CFGMR3InsertString(pCfg, "AudioDriver", "solaudio"); RC_CHECK();
1470 break;
1471 }
1472#endif
1473#ifdef RT_OS_LINUX
1474 case AudioDriverType_OSS:
1475 {
1476 rc = CFGMR3InsertString(pCfg, "AudioDriver", "oss"); RC_CHECK();
1477 break;
1478 }
1479# ifdef VBOX_WITH_ALSA
1480 case AudioDriverType_ALSA:
1481 {
1482 rc = CFGMR3InsertString(pCfg, "AudioDriver", "alsa"); RC_CHECK();
1483 break;
1484 }
1485# endif
1486# ifdef VBOX_WITH_PULSE
1487 case AudioDriverType_Pulse:
1488 {
1489 rc = CFGMR3InsertString(pCfg, "AudioDriver", "pulse"); RC_CHECK();
1490 break;
1491 }
1492# endif
1493#endif /* RT_OS_LINUX */
1494#ifdef RT_OS_DARWIN
1495 case AudioDriverType_CoreAudio:
1496 {
1497 rc = CFGMR3InsertString(pCfg, "AudioDriver", "coreaudio"); RC_CHECK();
1498 break;
1499 }
1500#endif
1501 }
1502 hrc = pMachine->COMGETTER(Name)(&str); H();
1503 STR_CONV();
1504 rc = CFGMR3InsertString(pCfg, "StreamName", psz); RC_CHECK();
1505 STR_FREE();
1506 }
1507
1508 /*
1509 * The USB Controller.
1510 */
1511 ComPtr<IUSBController> USBCtlPtr;
1512 hrc = pMachine->COMGETTER(USBController)(USBCtlPtr.asOutParam());
1513 if (USBCtlPtr)
1514 {
1515 BOOL fEnabled;
1516 hrc = USBCtlPtr->COMGETTER(Enabled)(&fEnabled); H();
1517 if (fEnabled)
1518 {
1519 rc = CFGMR3InsertNode(pDevices, "usb-ohci", &pDev); RC_CHECK();
1520 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1521 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1522 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1523 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 6); RC_CHECK();
1524 Assert(!afPciDeviceNo[6]);
1525 afPciDeviceNo[6] = true;
1526 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1527
1528 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1529 rc = CFGMR3InsertString(pLunL0, "Driver", "VUSBRootHub"); RC_CHECK();
1530 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1531
1532 /*
1533 * Attach the status driver.
1534 */
1535 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1536 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1537 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1538 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapUSBLed[0]);RC_CHECK();
1539 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
1540 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
1541
1542#ifdef VBOX_WITH_EHCI
1543 hrc = USBCtlPtr->COMGETTER(EnabledEhci)(&fEnabled); H();
1544 if (fEnabled)
1545 {
1546 rc = CFGMR3InsertNode(pDevices, "usb-ehci", &pDev); RC_CHECK();
1547 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();
1548 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();
1549 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();
1550 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 11); RC_CHECK();
1551 Assert(!afPciDeviceNo[11]);
1552 afPciDeviceNo[11] = true;
1553 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();
1554
1555 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
1556 rc = CFGMR3InsertString(pLunL0, "Driver", "VUSBRootHub"); RC_CHECK();
1557 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1558
1559 /*
1560 * Attach the status driver.
1561 */
1562 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK();
1563 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK();
1564 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();
1565 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapUSBLed[1]);RC_CHECK();
1566 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK();
1567 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK();
1568 }
1569 else
1570#endif
1571 {
1572 /*
1573 * Global USB options, currently unused as we'll apply the 2.0 -> 1.1 morphing
1574 * on a per device level now.
1575 */
1576 rc = CFGMR3InsertNode(pRoot, "USB", &pCfg); RC_CHECK();
1577 rc = CFGMR3InsertNode(pCfg, "USBProxy", &pCfg); RC_CHECK();
1578 rc = CFGMR3InsertNode(pCfg, "GlobalConfig", &pCfg); RC_CHECK();
1579 // This globally enables the 2.0 -> 1.1 device morphing of proxied devies to keep windows quiet.
1580 //rc = CFGMR3InsertInteger(pCfg, "Force11Device", true); RC_CHECK();
1581 // The following breaks stuff, but it makes MSDs work in vista. (I include it here so
1582 // that it's documented somewhere.) Users needing it can use:
1583 // VBoxManage setextradata "myvm" "VBoxInternal/USB/USBProxy/GlobalConfig/Force11PacketSize" 1
1584 //rc = CFGMR3InsertInteger(pCfg, "Force11PacketSize", true); RC_CHECK();
1585 }
1586 }
1587 }
1588
1589 /*
1590 * Clipboard
1591 */
1592 {
1593 ClipboardMode_T mode = ClipboardMode_Disabled;
1594 hrc = pMachine->COMGETTER(ClipboardMode) (&mode); H();
1595
1596 if (mode != ClipboardMode_Disabled)
1597 {
1598 /* Load the service */
1599 rc = pConsole->mVMMDev->hgcmLoadService ("VBoxSharedClipboard", "VBoxSharedClipboard");
1600
1601 if (VBOX_FAILURE (rc))
1602 {
1603 LogRel(("VBoxSharedClipboard is not available. rc = %Vrc\n", rc));
1604 /* That is not a fatal failure. */
1605 rc = VINF_SUCCESS;
1606 }
1607 else
1608 {
1609 /* Setup the service. */
1610 VBOXHGCMSVCPARM parm;
1611
1612 parm.type = VBOX_HGCM_SVC_PARM_32BIT;
1613
1614 switch (mode)
1615 {
1616 default:
1617 case ClipboardMode_Disabled:
1618 {
1619 LogRel(("VBoxSharedClipboard mode: Off\n"));
1620 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_OFF;
1621 break;
1622 }
1623 case ClipboardMode_GuestToHost:
1624 {
1625 LogRel(("VBoxSharedClipboard mode: Guest to Host\n"));
1626 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST;
1627 break;
1628 }
1629 case ClipboardMode_HostToGuest:
1630 {
1631 LogRel(("VBoxSharedClipboard mode: Host to Guest\n"));
1632 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST;
1633 break;
1634 }
1635 case ClipboardMode_Bidirectional:
1636 {
1637 LogRel(("VBoxSharedClipboard mode: Bidirectional\n"));
1638 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL;
1639 break;
1640 }
1641 }
1642
1643 pConsole->mVMMDev->hgcmHostCall ("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm);
1644
1645 Log(("Set VBoxSharedClipboard mode\n"));
1646 }
1647 }
1648 }
1649#ifdef VBOX_WITH_INFO_SVC
1650 /*
1651 * Shared information services
1652 */
1653 {
1654 /* Load the service */
1655 rc = pConsole->mVMMDev->hgcmLoadService ("VBoxSharedInfoSvc", "VBoxSharedInfoSvc");
1656
1657 if (VBOX_FAILURE (rc))
1658 {
1659 LogRel(("VBoxSharedInfoSvc is not available. rc = %Vrc\n", rc));
1660 /* That is not a fatal failure. */
1661 rc = VINF_SUCCESS;
1662 }
1663 else
1664 {
1665 rc = CFGMR3InsertNode(pRoot, "Guest", &pGuest); RC_CHECK();
1666 rc = CFGMR3InsertNode(pGuest, "Registry", &pRegistry); RC_CHECK();
1667 /* Load the saved machine registry. This is stored as extra data
1668 * keys in the machine XML file, starting with the prefix
1669 * VBOX_SHARED_INFO_KEY_PREFIX. */
1670 Bstr strExtraDataKey;
1671 for (;;)
1672 {
1673 Bstr strNextExtraDataKey;
1674 Bstr strExtraDataValue;
1675
1676 /* get the next key */
1677 hrc = pMachine->GetNextExtraDataKey(strExtraDataKey, strNextExtraDataKey.asOutParam(),
1678 strExtraDataValue.asOutParam());
1679
1680 /* stop if for some reason there's nothing more to request */
1681 if (FAILED(hrc) || !strNextExtraDataKey)
1682 break;
1683
1684 strExtraDataKey = strNextExtraDataKey;
1685 Utf8Str strExtraDataKeyUtf8 = Utf8Str(strExtraDataKey);
1686
1687 /* we only care about keys starting with VBOX_SHARED_INFO_KEY_PREFIX */
1688 if (strncmp(strExtraDataKeyUtf8.raw(), VBOX_SHARED_INFO_KEY_PREFIX, VBOX_SHARED_INFO_PREFIX_LEN) != 0)
1689 continue;
1690 char *pszCFGMValueName = (char*)strExtraDataKeyUtf8.raw() + VBOX_SHARED_INFO_PREFIX_LEN;
1691
1692 /* now let's have a look at the value */
1693 Utf8Str strCFGMValueUtf8 = Utf8Str(strExtraDataValue);
1694 const char *pszCFGMValue = strCFGMValueUtf8.raw();
1695 /* empty value means remove value which we've already done */
1696 if (pszCFGMValue && *pszCFGMValue)
1697 {
1698 rc = CFGMR3InsertString(pRegistry, pszCFGMValueName, pszCFGMValue);
1699 AssertMsgRC(rc, ("failed to insert CFGM value '%s' to key '%s'\n", pszCFGMValue, pszCFGMValueName));
1700 }
1701 }
1702
1703 /* Setup the service. */
1704 VBOXHGCMSVCPARM parm;
1705
1706 parm.type = VBOX_HGCM_SVC_PARM_PTR;
1707 parm.u.pointer.addr = pRegistry;
1708 parm.u.pointer.size = sizeof(pRegistry); /* We don't actually care. */
1709
1710 pConsole->mVMMDev->hgcmHostCall ("VBoxSharedInfoSvc", svcInfo::SET_CFGM_NODE, 1, &parm);
1711
1712 Log(("Set VBoxSharedInfoSvc guest registry\n"));
1713 }
1714 }
1715#endif /* VBOX_WITH_INFO_SVC defined */
1716
1717 /*
1718 * CFGM overlay handling.
1719 *
1720 * Here we check the extra data entries for CFGM values
1721 * and create the nodes and insert the values on the fly. Existing
1722 * values will be removed and reinserted. If a value is a valid number,
1723 * it will be inserted as a number, otherwise as a string.
1724 *
1725 * We first perform a run on global extra data, then on the machine
1726 * extra data to support global settings with local overrides.
1727 *
1728 */
1729 Bstr strExtraDataKey;
1730 bool fGlobalExtraData = true;
1731 for (;;)
1732 {
1733 Bstr strNextExtraDataKey;
1734 Bstr strExtraDataValue;
1735
1736 /* get the next key */
1737 if (fGlobalExtraData)
1738 hrc = virtualBox->GetNextExtraDataKey(strExtraDataKey, strNextExtraDataKey.asOutParam(),
1739 strExtraDataValue.asOutParam());
1740 else
1741 hrc = pMachine->GetNextExtraDataKey(strExtraDataKey, strNextExtraDataKey.asOutParam(),
1742 strExtraDataValue.asOutParam());
1743
1744 /* stop if for some reason there's nothing more to request */
1745 if (FAILED(hrc) || !strNextExtraDataKey)
1746 {
1747 /* if we're out of global keys, continue with machine, otherwise we're done */
1748 if (fGlobalExtraData)
1749 {
1750 fGlobalExtraData = false;
1751 strExtraDataKey.setNull();
1752 continue;
1753 }
1754 break;
1755 }
1756
1757 strExtraDataKey = strNextExtraDataKey;
1758 Utf8Str strExtraDataKeyUtf8 = Utf8Str(strExtraDataKey);
1759
1760 /* we only care about keys starting with "VBoxInternal/" */
1761 if (strncmp(strExtraDataKeyUtf8.raw(), "VBoxInternal/", 13) != 0)
1762 continue;
1763 char *pszExtraDataKey = (char*)strExtraDataKeyUtf8.raw() + 13;
1764
1765 /* the key will be in the format "Node1/Node2/Value" or simply "Value". */
1766 PCFGMNODE pNode;
1767 char *pszCFGMValueName = strrchr(pszExtraDataKey, '/');
1768 if (pszCFGMValueName)
1769 {
1770 /* terminate the node and advance to the value */
1771 *pszCFGMValueName = '\0';
1772 pszCFGMValueName++;
1773
1774 /* does the node already exist? */
1775 pNode = CFGMR3GetChild(pRoot, pszExtraDataKey);
1776 if (pNode)
1777 {
1778 /* the value might already exist, remove it to be safe */
1779 CFGMR3RemoveValue(pNode, pszCFGMValueName);
1780 }
1781 else
1782 {
1783 /* create the node */
1784 rc = CFGMR3InsertNode(pRoot, pszExtraDataKey, &pNode);
1785 AssertMsgRC(rc, ("failed to insert node '%s'\n", pszExtraDataKey));
1786 if (VBOX_FAILURE(rc) || !pNode)
1787 continue;
1788 }
1789 }
1790 else
1791 {
1792 pNode = pRoot;
1793 pszCFGMValueName = pszExtraDataKey;
1794 pszExtraDataKey--;
1795
1796 /* the value might already exist, remove it to be safe */
1797 CFGMR3RemoveValue(pNode, pszCFGMValueName);
1798 }
1799
1800 /* now let's have a look at the value */
1801 Utf8Str strCFGMValueUtf8 = Utf8Str(strExtraDataValue);
1802 const char *pszCFGMValue = strCFGMValueUtf8.raw();
1803 /* empty value means remove value which we've already done */
1804 if (pszCFGMValue && *pszCFGMValue)
1805 {
1806 /* if it's a valid number, we'll insert it as such, otherwise string */
1807 uint64_t u64Value;
1808 char *pszNext = NULL;
1809 if ( RTStrToUInt64Ex(pszCFGMValue, &pszNext, 0, &u64Value) == VINF_SUCCESS
1810 && (!pszNext || *pszNext == '\0') /* check if the _whole_ string is a valid number */
1811 )
1812 {
1813 rc = CFGMR3InsertInteger(pNode, pszCFGMValueName, u64Value);
1814 }
1815 else
1816 {
1817 rc = CFGMR3InsertString(pNode, pszCFGMValueName, pszCFGMValue);
1818 }
1819 AssertMsgRC(rc, ("failed to insert CFGM value '%s' to key '%s'\n", pszCFGMValue, pszExtraDataKey));
1820 }
1821 }
1822
1823#undef H
1824#undef RC_CHECK
1825#undef STR_FREE
1826#undef STR_CONV
1827
1828 /* Register VM state change handler */
1829 int rc2 = VMR3AtStateRegister (pVM, Console::vmstateChangeCallback, pConsole);
1830 AssertRC (rc2);
1831 if (VBOX_SUCCESS (rc))
1832 rc = rc2;
1833
1834 /* Register VM runtime error handler */
1835 rc2 = VMR3AtRuntimeErrorRegister (pVM, Console::setVMRuntimeErrorCallback, pConsole);
1836 AssertRC (rc2);
1837 if (VBOX_SUCCESS (rc))
1838 rc = rc2;
1839
1840 /* Save the VM pointer in the machine object */
1841 pConsole->mpVM = pVM;
1842
1843 LogFlowFunc (("vrc = %Vrc\n", rc));
1844 LogFlowFuncLeave();
1845
1846 return rc;
1847}
1848
1849
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette