VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxBFE/VBoxBFE.cpp@ 3669

Last change on this file since 3669 was 3669, checked in by vboxsync, 17 years ago

replace underscore symbols in VBoxBFE/ and VBoxSDL/

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 63.8 KB
Line 
1/** @file
2 *
3 * VBox frontends: Basic Frontend (BFE):
4 * VBoxBFE main routines
5 *
6 * VBoxBFE is a limited frontend that sits directly on the Virtual Machine
7 * Manager (VMM) and does _not_ use COM to communicate.
8 * On Linux and Windows, VBoxBFE is based on SDL; on L4 it's based on the
9 * L4 console. Much of the code has been copied over from the other frontends
10 * in VBox/Main/ and src/Frontends/VBoxSDL/.
11 */
12
13/*
14 * Copyright (C) 2006-2007 innotek GmbH
15 *
16 * This file is part of VirtualBox Open Source Edition (OSE), as
17 * available from http://www.virtualbox.org. This file is free software;
18 * you can redistribute it and/or modify it under the terms of the GNU
19 * General Public License as published by the Free Software Foundation,
20 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
21 * distribution. VirtualBox OSE is distributed in the hope that it will
22 * be useful, but WITHOUT ANY WARRANTY of any kind.
23 *
24 * If you received this file as part of a commercial VirtualBox
25 * distribution, then only the terms of your commercial VirtualBox
26 * license agreement apply instead of the previous paragraph.
27 */
28
29/*******************************************************************************
30* Header Files *
31*******************************************************************************/
32#define LOG_GROUP LOG_GROUP_GUI
33
34#ifndef VBOXBFE_WITHOUT_COM
35# include <VBox/com/Guid.h>
36# include <VBox/com/string.h>
37using namespace com;
38#endif
39
40#include <VBox/types.h>
41#include <VBox/err.h>
42#include <VBox/param.h>
43#include <VBox/pdm.h>
44#include <VBox/version.h>
45#ifdef VBOXBFE_WITH_USB
46# include <VBox/vusb.h>
47#endif
48#include <VBox/log.h>
49#include <iprt/path.h>
50#include <iprt/string.h>
51#include <iprt/runtime.h>
52#include <iprt/assert.h>
53#include <iprt/semaphore.h>
54#include <iprt/stream.h>
55#include <iprt/thread.h>
56#include <iprt/uuid.h>
57#include <iprt/file.h>
58#include <iprt/alloca.h>
59#include <iprt/ctype.h>
60
61#include "VBoxBFE.h"
62
63#include <stdio.h>
64#include <stdlib.h> /* putenv */
65#include <errno.h>
66
67#if defined(RT_OS_LINUX) || defined(__L4__)
68#include <fcntl.h>
69#include <net/if.h>
70#include <sys/ioctl.h>
71#include <linux/if_tun.h>
72#endif
73
74#ifndef __L4ENV__
75#include <vector>
76#endif
77
78#include "ConsoleImpl.h"
79#include "DisplayImpl.h"
80#include "MouseImpl.h"
81#include "KeyboardImpl.h"
82#include "VMMDevInterface.h"
83#include "StatusImpl.h"
84#include "Framebuffer.h"
85#include "MachineDebuggerImpl.h"
86#ifdef VBOXBFE_WITH_USB
87# include "HostUSBImpl.h"
88#endif
89
90#if defined(USE_SDL) && ! defined(__L4__)
91#include "SDLConsole.h"
92#include "SDLFramebuffer.h"
93#endif
94
95#ifdef __L4__
96#include "L4Console.h"
97#include "L4Framebuffer.h"
98#endif
99
100#ifdef __L4ENV__
101# ifndef L4API_l4v2onv4
102# include <l4/sys/ktrace.h>
103# endif
104# include <l4/vboxserver/file.h>
105#endif
106
107/*******************************************************************************
108* Defined Constants And Macros *
109*******************************************************************************/
110
111#define VBOXSDL_ADVANCED_OPTIONS
112
113
114/*******************************************************************************
115* Internal Functions *
116*******************************************************************************/
117static DECLCALLBACK(int) vboxbfeConfigConstructor(PVM pVM, void *pvUser);
118static DECLCALLBACK(void) vmstateChangeCallback(PVM pVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser);
119static DECLCALLBACK(void) setVMErrorCallback(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL,
120 const char *pszFormat, va_list args);
121static DECLCALLBACK(int) VMPowerUpThread(RTTHREAD Thread, void *pvUser);
122
123
124/*******************************************************************************
125* Global Variables *
126*******************************************************************************/
127
128PVM pVM = NULL;
129Mouse *gMouse = NULL;
130VMDisplay *gDisplay = NULL;
131Keyboard *gKeyboard = NULL;
132VMMDev *gVMMDev = NULL;
133Framebuffer *gFramebuffer = NULL;
134MachineDebugger *gMachineDebugger = NULL;
135VMStatus *gStatus = NULL;
136Console *gConsole = NULL;
137#ifdef VBOXBFE_WITH_USB
138HostUSB *gHostUSB = NULL;
139#endif
140
141VMSTATE machineState = VMSTATE_CREATING;
142
143PPDMLED mapFDLeds[2] = {0};
144PPDMLED mapIDELeds[4] = {0};
145
146/** flag whether keyboard/mouse events are grabbed */
147#ifdef __L4__
148/** see <l4/input/macros.h> for key definitions */
149int gHostKey; /* not used */
150int gHostKeySym = KEY_RIGHTCTRL;
151#elif defined (DEBUG_dmik)
152// my mini kbd doesn't have RCTRL...
153int gHostKey = KMOD_RSHIFT;
154int gHostKeySym = SDLK_RSHIFT;
155#else
156int gHostKey = KMOD_RCTRL;
157int gHostKeySym = SDLK_RCTRL;
158#endif
159bool gfAllowFullscreenToggle = true;
160
161static bool g_fIOAPIC = false;
162static bool g_fACPI = true;
163static bool g_fAudio = false;
164#ifdef VBOXBFE_WITH_USB
165static bool g_fUSB = false;
166#endif
167static char *g_pszHdaFile = NULL;
168static char *g_pszHdbFile = NULL;
169static char *g_pszCdromFile = NULL;
170static char *g_pszFdaFile = NULL;
171static const char *pszBootDevice = "IDE";
172static uint32_t g_u32MemorySizeMB = 128;
173static uint32_t g_u32VRamSizeMB = 4;
174#ifdef VBOXSDL_ADVANCED_OPTIONS
175static bool g_fRawR0 = true;
176static bool g_fRawR3 = true;
177static bool g_fPATM = true;
178static bool g_fCSAM = true;
179#endif
180static bool g_fPreAllocRam = false;
181static int g_iBootMenu = 2;
182static bool g_fReleaseLog = true; /**< Set if we should open the release. */
183
184
185/**
186 * Network device config info.
187 */
188typedef struct BFENetworkDevice
189{
190 enum
191 {
192 NOT_CONFIGURED = 0,
193 NONE,
194 NAT,
195 HIF,
196 INTNET
197 } enmType; /**< The type of network driver. */
198 bool fSniff; /**< Set if the network sniffer should be installed. */
199 const char *pszSniff; /**< Output file for the network sniffer. */
200 PDMMAC Mac; /**< The mac address for the device. */
201 const char *pszName; /**< The device name of a HIF device. The name of the internal network. */
202#if 1//defined(RT_OS_LINUX)
203 bool fHaveFd; /**< Set if fd is valid. */
204 int32_t fd; /**< The file descriptor of a HIF device.*/
205#endif
206} BFENETDEV, *PBFENETDEV;
207
208/** Array of network device configurations. */
209static BFENETDEV g_aNetDevs[NetworkAdapterCount];
210
211
212/** @todo currently this is only set but never read. */
213static char szError[512];
214
215
216/**
217 * Converts the passed in network option
218 *
219 * @returns Index into g_aNetDevs on success. (positive)
220 * @returns VERR_INVALID_PARAMETER on failure. (negative)
221 * @param pszArg The argument.
222 * @param cchRoot The length of the argument root.
223 */
224static int networkArg2Index(const char *pszArg, int cchRoot)
225{
226 uint32_t n;
227 int rc = RTStrToUInt32Ex(&pszArg[cchRoot], NULL, 10, &n);
228 if (VBOX_FAILURE(rc))
229 {
230 RTPrintf("Error: invalid network device option (rc=%Vrc): %s\n", rc, pszArg);
231 return -1;
232 }
233 if (n < 1 || n > NetworkAdapterCount)
234 {
235 RTPrintf("Error: The network device number is out of range: %RU32 (1 <= 0 <= %u) (%s)\n",
236 n, NetworkAdapterCount, pszArg);
237 return -1;
238 }
239 return n;
240}
241
242
243/**
244 * Print a syntax error.
245 *
246 * @returns return value for main().
247 * @param pszMsg The message format string.
248 * @param ... Format arguments.
249 */
250static int SyntaxError(const char *pszMsg, ...)
251{
252 va_list va;
253 RTPrintf("error: ");
254 va_start(va, pszMsg);
255 RTPrintfV(pszMsg, va);
256 va_end(va);
257 return 1;
258}
259
260
261/**
262 * Print a fatal error.
263 *
264 * @returns return value for main().
265 * @param pszMsg The message format string.
266 * @param ... Format arguments.
267 */
268static int FatalError(const char *pszMsg, ...)
269{
270 va_list va;
271 RTPrintf("fatal error: ");
272 va_start(va, pszMsg);
273 RTPrintfV(pszMsg, va);
274 va_end(va);
275 return 1;
276}
277
278
279/**
280 * Print program usage.
281 */
282static void show_usage()
283{
284 RTPrintf("Usage:\n"
285 " -hda <file> Set first hard disk to file\n"
286 " -hdb <file> Set second hard disk to file\n"
287 " -fda <file> Set first floppy disk to file\n"
288 " -cdrom <file> Set CDROM to file/device ('none' to unmount)\n"
289 " -boot <a|c|d> Set boot device (a = floppy, c = first hard disk, d = DVD)\n"
290 " -boot menu <0|1|2> Boot menu (0 = disable, 1 = menu only, 2 = message + menu)\n"
291 " -m <size> Set memory size in megabytes (default 128MB)\n"
292 " -vram <size> Set size of video memory in megabytes\n"
293 " -prealloc Force RAM pre-allocation\n"
294 " -fullscreen Start VM in fullscreen mode\n"
295 " -nofstoggle Forbid switching to/from fullscreen mode\n"
296 " -nohostkey Disable hostkey\n"
297 " -[no]acpi Enable or disable ACPI (default: enabled)\n"
298 " -[no]ioapic Enable or disable the IO-APIC (default: disabled)\n"
299 " -audio Enable audio\n"
300 " -natdev<1-N> Configure NAT for network device N\n"
301 " -hifdev<1-N> <dev> <mac> Use existing Host Interface Network Device with the given name and MAC address\n"
302#if 0
303 " -netsniff<1-N> Enable packet sniffer\n"
304#endif
305#ifdef RT_OS_LINUX
306 " -tapfd<1-N> <fd> Use existing TAP device, don't allocate\n"
307#endif
308#ifdef VBOX_VRDP
309 " -vrdp [port] Listen for VRDP connections on port (default if not specified)\n"
310#endif
311#ifdef VBOX_SECURELABEL
312 " -securelabel Display a secure VM label at the top of the screen\n"
313 " -seclabelfnt TrueType (.ttf) font file for secure session label\n"
314 " -seclabelsiz Font point size for secure session label (default 12)\n"
315#endif
316 " -[no]rellog Enable or disable the release log './VBoxBFE.log' (default: enabled)\n"
317#ifdef VBOXSDL_ADVANCED_OPTIONS
318 " -[no]rawr0 Enable or disable raw ring 3\n"
319 " -[no]rawr3 Enable or disable raw ring 0\n"
320 " -[no]patm Enable or disable PATM\n"
321 " -[no]csam Enable or disable CSAM\n"
322#endif
323#ifdef __L4ENV__
324 " -env <var=value> Set the given environment variable to \"value\"\n"
325#endif
326 "\n");
327}
328
329
330/** entry point */
331int main(int argc, char **argv)
332{
333#ifdef __L4ENV__
334#ifndef L4API_l4v2onv4
335 /* clear Fiasco kernel trace buffer */
336 fiasco_tbuf_clear();
337#endif
338 /* set the environment. Must be done before the runtime is
339 initialised. Yes, it really must. */
340 for (int i = 0; i < argc; i++)
341 if (strcmp(argv[i], "-env") == 0)
342 {
343 if (++i >= argc)
344 return SyntaxError("missing argument to -env (format: var=value)!\n");
345 /* add it to the environment */
346 if (putenv(argv[i]) != 0)
347 return SyntaxError("Error setting environment string %s.\n", argv[i]);
348 }
349#endif /* __L4ENV__ */
350
351 /*
352 * Before we do *anything*, we initialize the runtime.
353 */
354 int rc = RTR3Init();
355 if (VBOX_FAILURE(rc))
356 return FatalError("RTR3Init failed rc=%Vrc\n", rc);
357
358
359 bool fFullscreen = false;
360#ifdef VBOX_VRDP
361 int32_t portVRDP = -1;
362#endif
363#ifdef VBOX_SECURELABEL
364 bool fSecureLabel = false;
365 uint32_t secureLabelPointSize = 12;
366 char *secureLabelFontFile = NULL;
367#endif
368 RTPrintf("VirtualBox Simple SDL GUI built %s %s\n", __DATE__, __TIME__);
369
370 // less than one parameter is not possible
371 if (argc < 2)
372 {
373 show_usage();
374 return 1;
375 }
376
377 /*
378 * Parse the command line arguments.
379 */
380 for (int curArg = 1; curArg < argc; curArg++)
381 {
382 const char * const pszArg = argv[curArg];
383 if (strcmp(pszArg, "-boot") == 0)
384 {
385 if (++curArg >= argc)
386 return SyntaxError("missing argument for boot drive!\n");
387 if (strlen(argv[curArg]) != 1)
388 return SyntaxError("invalid argument for boot drive! (%s)\n", argv[curArg]);
389 rc = VINF_SUCCESS;
390 switch (argv[curArg][0])
391 {
392 case 'a':
393 {
394 pszBootDevice = "FLOPPY";
395 break;
396 }
397
398 case 'c':
399 {
400 pszBootDevice = "IDE";
401 break;
402 }
403
404 case 'd':
405 {
406 pszBootDevice = "DVD";
407 break;
408 }
409
410 default:
411 return SyntaxError("wrong argument for boot drive! (%s)\n", argv[curArg]);
412 }
413 }
414 else if (strcmp(pszArg, "-bootmenu") == 0)
415 {
416 if (++curArg >= argc)
417 return SyntaxError("missing argument for boot menu!\n");
418 if (strlen(argv[curArg]) != 1 || *argv[curArg] < '0' || *argv[curArg] > '2')
419 return SyntaxError("invalid argument for boot menu! (%s)\n", argv[curArg]);
420 rc = VINF_SUCCESS;
421 g_iBootMenu = *argv[curArg] - 0;
422 }
423 else if (strcmp(pszArg, "-m") == 0)
424 {
425 if (++curArg >= argc)
426 return SyntaxError("missing argument for memory size!\n");
427 rc = RTStrToUInt32Ex(argv[curArg], NULL, 0, &g_u32MemorySizeMB);
428 if (VBOX_FAILURE(rc))
429 return SyntaxError("cannot grok the memory size: %s (%Vrc)\n",
430 argv[curArg], rc);
431 }
432 else if (strcmp(pszArg, "-vram") == 0)
433 {
434 if (++curArg >= argc)
435 return SyntaxError("missing argument for vram size!\n");
436 rc = RTStrToUInt32Ex(argv[curArg], NULL, 0, &g_u32VRamSizeMB);
437 if (VBOX_FAILURE(rc))
438 return SyntaxError("cannot grok the vram size: %s (%Vrc)\n",
439 argv[curArg], rc);
440 }
441 else if (strcmp(pszArg, "-fullscreen") == 0)
442 fFullscreen = true;
443 else if (strcmp(pszArg, "-nofstoggle") == 0)
444 gfAllowFullscreenToggle = false;
445 else if (strcmp(pszArg, "-nohostkey") == 0)
446 {
447 gHostKey = 0;
448 gHostKeySym = 0;
449 }
450 else if (strcmp(pszArg, "-acpi") == 0)
451 g_fACPI = true;
452 else if (strcmp(pszArg, "-noacpi") == 0)
453 g_fACPI = false;
454 else if (strcmp(pszArg, "-ioapic") == 0)
455 g_fIOAPIC = true;
456 else if (strcmp(pszArg, "-noioapic") == 0)
457 g_fIOAPIC = false;
458 else if (strcmp(pszArg, "-audio") == 0)
459 g_fAudio = true;
460#ifdef VBOXBFE_WITH_USB
461 else if (strcmp(pszArg, "-usb") == 0)
462 g_fUSB = true;
463#endif
464 else if (strcmp(pszArg, "-hda") == 0)
465 {
466 if (++curArg >= argc)
467 return SyntaxError("missing file name for first hard disk!\n");
468
469 /* resolve it. */
470 if (RTPathExists(argv[curArg]))
471 g_pszHdaFile = RTPathRealDup(argv[curArg]);
472 if (!g_pszHdaFile)
473 return SyntaxError("The path to the specified harddisk, '%s', could not be resolved.\n", argv[curArg]);
474 }
475 else if (strcmp(pszArg, "-hdb") == 0)
476 {
477 if (++curArg >= argc)
478 return SyntaxError("missing file name for second hard disk!\n");
479
480 /* resolve it. */
481 if (RTPathExists(argv[curArg]))
482 g_pszHdbFile = RTPathRealDup(argv[curArg]);
483 if (!g_pszHdbFile)
484 return SyntaxError("The path to the specified harddisk, '%s', could not be resolved.\n", argv[curArg]);
485 }
486 else if (strcmp(pszArg, "-fda") == 0)
487 {
488 if (++curArg >= argc)
489 return SyntaxError("missing file/device name for first floppy disk!\n");
490
491 /* resolve it. */
492 if (RTPathExists(argv[curArg]))
493 g_pszFdaFile = RTPathRealDup(argv[curArg]);
494 if (!g_pszFdaFile)
495 return SyntaxError("The path to the specified floppy disk, '%s', could not be resolved.\n", argv[curArg]);
496 }
497 else if (strcmp(pszArg, "-cdrom") == 0)
498 {
499 if (++curArg >= argc)
500 return SyntaxError("missing file/device name for first hard disk!\n");
501
502 /* resolve it. */
503 if (RTPathExists(argv[curArg]))
504 g_pszCdromFile = RTPathRealDup(argv[curArg]);
505 if (!g_pszCdromFile)
506 return SyntaxError("The path to the specified cdrom, '%s', could not be resolved.\n", argv[curArg]);
507 }
508 else if ( strncmp(pszArg, "-natdev", 7) == 0
509 || strncmp(pszArg, "-hifdev", 7) == 0
510 || strncmp(pszArg, "-nonetd", 7) == 0
511 || strncmp(pszArg, "-intnet", 7) == 0)
512 {
513 int i = networkArg2Index(pszArg, 7);
514 if (i < 0)
515 return 1;
516 g_aNetDevs[i].enmType = !strncmp(pszArg, "-natdev", 7)
517 ? BFENETDEV::NAT
518 : !strncmp(pszArg, "-hifdev", 7)
519 ? BFENETDEV::HIF
520 : !strncmp(pszArg, "-intnet", 7)
521 ? BFENETDEV::INTNET
522 : BFENETDEV::NONE;
523
524 /* The HIF device name / The Internal Network name. */
525 g_aNetDevs[i].pszName = NULL;
526 if ( g_aNetDevs[i].enmType == BFENETDEV::HIF
527 || g_aNetDevs[i].enmType == BFENETDEV::INTNET)
528 {
529 if (curArg + 1 >= argc)
530 return SyntaxError(g_aNetDevs[i].enmType == BFENETDEV::HIF
531 ? "The TAP network device name is missing! (%s)\n"
532 : "The internal network name is missing! (%s)\n"
533 , pszArg);
534 g_aNetDevs[i].pszName = argv[++curArg];
535 }
536
537 /* The MAC address. */
538 if (++curArg >= argc)
539 return SyntaxError("The network MAC address is missing! (%s)\n", pszArg);
540 if (strlen(argv[curArg]) != 12)
541 return SyntaxError("The network MAC address has an invalid length: %s (%s)\n", argv[curArg], pszArg);
542 const char *pszMac = argv[curArg];
543 for (unsigned j = 0; j < RT_ELEMENTS(g_aNetDevs[i].Mac.au8); j++)
544 {
545 char c1 = toupper(*pszMac++) - '0';
546 if (c1 > 9)
547 c1 -= 7;
548 char c2 = toupper(*pszMac++) - '0';
549 if (c2 > 9)
550 c2 -= 7;
551 if (c2 > 16 || c1 > 16)
552 return SyntaxError("Invalid MAC address: %s\n", argv[curArg]);
553 g_aNetDevs[i].Mac.au8[j] = ((c1 & 0x0f) << 4) | (c2 & 0x0f);
554 }
555 }
556 else if (strncmp(pszArg, "-netsniff", 9) == 0)
557 {
558 int i = networkArg2Index(pszArg, 7);
559 if (rc < 0)
560 return 1;
561 g_aNetDevs[i].fSniff = true;
562 /** @todo filename */
563 }
564#ifdef RT_OS_LINUX
565 else if (strncmp(pszArg, "-tapfd", 6) == 0)
566 {
567 int i = networkArg2Index(pszArg, 7);
568 if (++curArg >= argc)
569 return SyntaxError("missing argument for %s!\n", pszArg);
570 rc = RTStrToInt32Ex(argv[curArg], NULL, 0, &g_aNetDevs[i].fd);
571 if (VBOX_FAILURE(rc))
572 return SyntaxError("cannot grok tap fd: %s (%VRc)\n", argv[curArg], rc);
573 g_aNetDevs[i].fHaveFd = true;
574 }
575#endif /* RT_OS_LINUX */
576#ifdef VBOX_VRDP
577 else if (strcmp(pszArg, "-vrdp") == 0)
578 {
579 // -vrdp might take a port number (positive).
580 portVRDP = 0; // indicate that it was encountered.
581 if (curArg + 1 < argc && argv[curArg + 1][0] != '-')
582 {
583 rc = RTStrToInt32Ex(argv[curArg], NULL, 0, &portVRDP);
584 if (VBOX_FAILURE(rc))
585 return SyntaxError("cannot vrpd port: %s (%VRc)\n", argv[curArg], rc);
586 if (portVRDP < 0 || portVRDP >= 0x10000)
587 return SyntaxError("vrdp port number is out of range: %RI32\n", portVRDP);
588 }
589 }
590#endif /* VBOX_VRDP */
591#ifdef VBOX_SECURELABEL
592 else if (strcmp(pszArg, "-securelabel") == 0)
593 {
594 fSecureLabel = true;
595 LogFlow(("Secure labelling turned on\n"));
596 }
597 else if (strcmp(pszArg, "-seclabelfnt") == 0)
598 {
599 if (++curArg >= argc)
600 return SyntaxError("missing font file name for secure label!\n");
601 secureLabelFontFile = argv[curArg];
602 }
603 else if (strcmp(pszArg, "-seclabelsiz") == 0)
604 {
605 if (++curArg >= argc)
606 return SyntaxError("missing font point size for secure label!\n");
607 secureLabelPointSize = atoi(argv[curArg]);
608 }
609#endif
610 else if (strcmp(pszArg, "-rellog") == 0)
611 g_fReleaseLog = true;
612 else if (strcmp(pszArg, "-norellog") == 0)
613 g_fReleaseLog = false;
614 else if (strcmp(pszArg, "-prealloc") == 0)
615 g_fPreAllocRam = true;
616#ifdef VBOXSDL_ADVANCED_OPTIONS
617 else if (strcmp(pszArg, "-rawr0") == 0)
618 g_fRawR0 = true;
619 else if (strcmp(pszArg, "-norawr0") == 0)
620 g_fRawR0 = false;
621 else if (strcmp(pszArg, "-rawr3") == 0)
622 g_fRawR3 = true;
623 else if (strcmp(pszArg, "-norawr3") == 0)
624 g_fRawR3 = false;
625 else if (strcmp(pszArg, "-patm") == 0)
626 g_fPATM = true;
627 else if (strcmp(pszArg, "-nopatm") == 0)
628 g_fPATM = false;
629 else if (strcmp(pszArg, "-csam") == 0)
630 g_fCSAM = true;
631 else if (strcmp(pszArg, "-nocsam") == 0)
632 g_fCSAM = false;
633#endif /* VBOXSDL_ADVANCED_OPTIONS */
634#ifdef __L4__
635 else if (strcmp(pszArg, "-env") == 0)
636 ++curArg;
637#endif /* __L4__ */
638 /* just show the help screen */
639 else
640 {
641 SyntaxError("unrecognized argument '%s'\n", pszArg);
642 show_usage();
643 return 1;
644 }
645 }
646
647 gMachineDebugger = new MachineDebugger();
648 gStatus = new VMStatus();
649 gKeyboard = new Keyboard();
650 gMouse = new Mouse();
651 gVMMDev = new VMMDev();
652 gDisplay = new VMDisplay();
653#if defined(USE_SDL)
654 /* First console, then framebuffer!! */
655 gConsole = new SDLConsole();
656 gFramebuffer = new SDLFramebuffer();
657#elif defined(__L4ENV__)
658 gConsole = new L4Console();
659 gFramebuffer = new L4Framebuffer();
660#else
661#error "todo"
662#endif
663 if (!gConsole->initialized())
664 goto leave;
665 gDisplay->RegisterExternalFramebuffer(gFramebuffer);
666
667 /* start with something in the titlebar */
668 gConsole->updateTitlebar();
669
670 /*
671 * Start the VM execution thread. This has to be done
672 * asynchronously as powering up can take some time
673 * (accessing devices such as the host DVD drive). In
674 * the meantime, we have to service the SDL event loop.
675 */
676
677 RTTHREAD thread;
678 rc = RTThreadCreate(&thread, VMPowerUpThread, 0, 0, RTTHREADTYPE_MAIN_WORKER, 0, "PowerUp");
679 if (VBOX_FAILURE(rc))
680 {
681 RTPrintf("Error: Thread creation failed with %d\n", rc);
682 return -1;
683 }
684
685 /* loop until the powerup processing is done */
686 do
687 {
688#if defined(RT_OS_LINUX) && defined(USE_SDL)
689 if ( machineState == VMSTATE_CREATING
690 || machineState == VMSTATE_LOADING)
691 {
692 int event = gConsole->eventWait();
693
694 switch (event)
695 {
696 case CONEVENT_USR_SCREENRESIZE:
697 LogFlow(("CONEVENT_USR_SCREENRESIZE\n"));
698 gFramebuffer->resize();
699 /* notify the display that the resize has been completed */
700 gDisplay->ResizeCompleted();
701 break;
702
703 case CONEVENT_USR_QUIT:
704 RTPrintf("Error: failed to power up VM! No error text available.\n");
705 goto leave;
706 }
707 }
708 else
709#endif
710 RTThreadSleep(1000);
711 }
712 while ( machineState == VMSTATE_CREATING
713 || machineState == VMSTATE_LOADING);
714
715 if (machineState == VMSTATE_TERMINATED)
716 goto leave;
717
718 /* did the power up succeed? */
719 if (machineState != VMSTATE_RUNNING)
720 {
721 RTPrintf("Error: failed to power up VM! No error text available (rc = 0x%x state = %d)\n", rc, machineState);
722 goto leave;
723 }
724
725 gConsole->updateTitlebar();
726
727#ifdef __L4__
728 /* The L4 console provides (currently) a fixed resolution. */
729 if (g_u32VRamSizeMB * _1M >= gFramebuffer->getHostXres()
730 * gFramebuffer->getHostYres()
731 * (gDisplay->getColorDepth() / 8))
732 gDisplay->SetVideoModeHint(gFramebuffer->getHostXres(), gFramebuffer->getHostYres(), 0, 0);
733#endif
734
735 /*
736 * Main event loop
737 */
738 LogFlow(("VBoxSDL: Entering big event loop\n"));
739
740 while (1)
741 {
742 int event = gConsole->eventWait();
743
744 switch (event)
745 {
746 case CONEVENT_NONE:
747 /* Handled internally */
748 break;
749
750 case CONEVENT_QUIT:
751 case CONEVENT_USR_QUIT:
752 goto leave;
753
754 case CONEVENT_SCREENUPDATE:
755 /// @todo that somehow doesn't seem to work!
756 gFramebuffer->repaint();
757 break;
758
759 case CONEVENT_USR_TITLEBARUPDATE:
760 gConsole->updateTitlebar();
761 break;
762
763 case CONEVENT_USR_SCREENRESIZE:
764 {
765 LogFlow(("CONEVENT_USR_SCREENRESIZE\n"));
766 gFramebuffer->resize();
767 /* notify the display that the resize has been completed */
768 gDisplay->ResizeCompleted();
769 break;
770 }
771
772#ifdef VBOX_SECURELABEL
773 case CONEVENT_USR_SECURELABELUPDATE:
774 {
775 /*
776 * Query the new label text
777 */
778 Bstr key = VBOXSDL_SECURELABEL_EXTRADATA;
779 Bstr label;
780 gMachine->COMGETTER(ExtraData)(key, label.asOutParam());
781 Utf8Str labelUtf8 = label;
782 /*
783 * Now update the label
784 */
785 gFramebuffer->setSecureLabelText(labelUtf8.raw());
786 break;
787 }
788#endif /* VBOX_SECURELABEL */
789
790 }
791
792 }
793
794leave:
795 LogFlow(("Returning from main()!\n"));
796
797 if (pVM)
798 {
799 /*
800 * If get here because the guest terminated using ACPI off we don't have to
801 * switch off the VM because we were notified via vmstateChangeCallback()
802 * that this already happened. In any other case stop the VM before killing her.
803 */
804 if (machineState != VMSTATE_OFF)
805 {
806 /* Power off VM */
807 PVMREQ pReq;
808 rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)VMR3PowerOff, 1, pVM);
809 }
810
811 /* And destroy it */
812 rc = VMR3Destroy(pVM);
813 AssertRC(rc);
814 }
815
816 delete gFramebuffer;
817 delete gConsole;
818 delete gDisplay;
819 delete gKeyboard;
820 delete gMouse;
821 delete gStatus;
822 delete gMachineDebugger;
823
824 RTLogFlush(NULL);
825 return VBOX_FAILURE (rc) ? 1 : 0;
826}
827
828
829
830/**
831 * VM state callback function. Called by the VMM
832 * using its state machine states.
833 *
834 * Primarily used to handle VM initiated power off, suspend and state saving,
835 * but also for doing termination completed work (VMSTATE_TERMINATE).
836 *
837 * In general this function is called in the context of the EMT.
838 *
839 * @todo machineState is set to VMSTATE_RUNNING before all devices have received power on events
840 * this can prematurely allow the main thread to enter the event loop
841 *
842 * @param pVM The VM handle.
843 * @param enmState The new state.
844 * @param enmOldState The old state.
845 * @param pvUser The user argument.
846 */
847static DECLCALLBACK(void) vmstateChangeCallback(PVM pVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser)
848{
849 LogFlow(("vmstateChangeCallback: changing state from %d to %d\n", enmOldState, enmState));
850 machineState = enmState;
851
852 switch (enmState)
853 {
854 /*
855 * The VM has terminated
856 */
857 case VMSTATE_OFF:
858 {
859 gConsole->eventQuit();
860 break;
861 }
862
863 /*
864 * The VM has been completely destroyed.
865 *
866 * Note: This state change can happen at two points:
867 * 1) At the end of VMR3Destroy() if it was not called from EMT.
868 * 2) At the end of vmR3EmulationThread if VMR3Destroy() was called by EMT.
869 */
870 case VMSTATE_TERMINATED:
871 {
872 break;
873 }
874
875 default: /* shut up gcc */
876 break;
877 }
878}
879
880
881/**
882 * VM error callback function. Called by the various VM components.
883 *
884 * @param pVM The VM handle.
885 * @param pvUser The user argument.
886 * @param rc VBox status code.
887 * @param pszError Error message format string.
888 * @param args Error message arguments.
889 * @thread EMT.
890 */
891DECLCALLBACK(void) setVMErrorCallback(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL,
892 const char *pszFormat, va_list args)
893{
894 /** @todo accessing shared resource without any kind of synchronization */
895 if (VBOX_SUCCESS(rc))
896 szError[0] = '\0';
897 else
898 {
899 RTStrPrintf(szError, sizeof(szError),
900 "%N!\nVBox status code: %d (%Vrc)", pszFormat, &args, rc, rc);
901 RTPrintf("%s\n", szError);
902 }
903}
904
905
906/**
907 * VM Runtime error callback function. Called by the various VM components.
908 *
909 * @param pVM The VM handle.
910 * @param pvUser The user argument.
911 * @param fFata Wheather it is a fatal error or not.
912 * @param pszErrorId Error ID string.
913 * @param pszError Error message format string.
914 * @param args Error message arguments.
915 * @thread EMT.
916 */
917DECLCALLBACK(void) setVMRuntimeErrorCallback(PVM pVM, void *pvUser, bool fFatal,
918 const char *pszErrorId,
919 const char *pszFormat, va_list args)
920{
921 RTPrintf("%s: %s!\n%N!\n", fFatal ? "Error" : "Warning", pszErrorId, pszFormat, &args);
922}
923
924
925/** VM asynchronous operations thread */
926DECLCALLBACK(int) VMPowerUpThread(RTTHREAD Thread, void *pvUser)
927{
928 int rc = VINF_SUCCESS;
929 int rc2;
930
931 /*
932 * Setup the release log instance in current directory.
933 */
934 if (g_fReleaseLog)
935 {
936 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
937 static char szError[RTPATH_MAX + 128] = "";
938 PRTLOGGER pLogger;
939 rc2 = RTLogCreateEx(&pLogger, RTLOGFLAGS_PREFIX_TIME_PROG, "all",
940 "VBOX_RELEASE_LOG", ELEMENTS(s_apszGroups), s_apszGroups,
941 RTLOGDEST_FILE, szError, sizeof(szError), "./VBoxBFE.log");
942 if (VBOX_SUCCESS(rc2))
943 {
944 /* some introductory information */
945 RTTIMESPEC TimeSpec;
946 char szNowUct[64];
947 RTTimeSpecToString(RTTimeNow(&TimeSpec), szNowUct, sizeof(szNowUct));
948 RTLogRelLogger(pLogger, 0, ~0U,
949 "VBoxBFE %s (%s %s) release log\n"
950 "Log opened %s\n",
951 VBOX_VERSION_STRING, __DATE__, __TIME__,
952 szNowUct);
953
954 /* register this logger as the release logger */
955 RTLogRelSetDefaultInstance(pLogger);
956 }
957 else
958 RTPrintf("Could not open release log (%s)\n", szError);
959 }
960
961 /*
962 * Start VM (also from saved state) and track progress
963 */
964 LogFlow(("VMPowerUp\n"));
965
966 /*
967 * Create empty VM.
968 */
969 rc = VMR3Create(setVMErrorCallback, NULL, vboxbfeConfigConstructor, NULL, &pVM);
970 if (VBOX_FAILURE(rc))
971 {
972 RTPrintf("Error: VM creation failed with %Vrc.\n", rc);
973 goto failure;
974 }
975
976
977 /*
978 * Register VM state change handler
979 */
980 rc = VMR3AtStateRegister(pVM, vmstateChangeCallback, NULL);
981 if (VBOX_FAILURE(rc))
982 {
983 RTPrintf("Error: VMR3AtStateRegister failed with %Vrc.\n", rc);
984 goto failure;
985 }
986
987#ifdef VBOXBFE_WITH_USB
988 /*
989 * Capture USB devices.
990 */
991 if (g_fUSB)
992 {
993 gHostUSB = new HostUSB();
994 gHostUSB->init(pVM);
995 }
996#endif /* VBOXBFE_WITH_USB */
997
998#ifdef __L4ENV__
999 /* L4 console cannot draw a host cursor */
1000 gMouse->setHostCursor(false);
1001#else
1002 gMouse->setHostCursor(true);
1003#endif
1004
1005 /*
1006 * Power on the VM (i.e. start executing).
1007 */
1008 if (VBOX_SUCCESS(rc))
1009 {
1010 PVMREQ pReq;
1011 rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)VMR3PowerOn, 1, pVM);
1012 if (VBOX_SUCCESS(rc))
1013 {
1014 rc = pReq->iStatus;
1015 AssertRC(rc);
1016 VMR3ReqFree(pReq);
1017 }
1018 else
1019 AssertMsgFailed(("VMR3PowerOn failed, rc=%Vrc\n", rc));
1020 }
1021
1022 /*
1023 * On failure destroy the VM.
1024 */
1025 if (VBOX_FAILURE(rc))
1026 goto failure;
1027
1028 return 0;
1029
1030failure:
1031 if (pVM)
1032 {
1033 rc2 = VMR3Destroy(pVM);
1034 AssertRC(rc2);
1035 pVM = NULL;
1036 }
1037 machineState = VMSTATE_TERMINATED;
1038
1039 return 0;
1040}
1041
1042/**
1043 * Register the main drivers.
1044 *
1045 * @returns VBox status code.
1046 * @param pCallbacks Pointer to the callback table.
1047 * @param u32Version VBox version number.
1048 */
1049DECLCALLBACK(int) VBoxDriversRegister(PCPDMDRVREGCB pCallbacks, uint32_t u32Version)
1050{
1051 int rc;
1052
1053 LogFlow(("VBoxDriversRegister: u32Version=%#x\n", u32Version));
1054 AssertReleaseMsg(u32Version == VBOX_VERSION, ("u32Version=%#x VBOX_VERSION=%#x\n", u32Version, VBOX_VERSION));
1055
1056 rc = pCallbacks->pfnRegister(pCallbacks, &Mouse::DrvReg);
1057 AssertRC(rc);
1058 if (VBOX_FAILURE(rc))
1059 return rc;
1060 rc = pCallbacks->pfnRegister(pCallbacks, &Keyboard::DrvReg);
1061 AssertRC(rc);
1062 if (VBOX_FAILURE(rc))
1063 return rc;
1064
1065 rc = pCallbacks->pfnRegister(pCallbacks, &VMDisplay::DrvReg);
1066 AssertRC(rc);
1067 if (VBOX_FAILURE(rc))
1068 return rc;
1069 rc = pCallbacks->pfnRegister(pCallbacks, &VMMDev::DrvReg);
1070 AssertRC(rc);
1071 if (VBOX_FAILURE(rc))
1072 return rc;
1073
1074 rc = pCallbacks->pfnRegister(pCallbacks, &VMStatus::DrvReg);
1075 if (VBOX_FAILURE(rc))
1076 return rc;
1077
1078 return VINF_SUCCESS;
1079}
1080
1081
1082/**
1083 * Constructs the VMM configuration tree.
1084 *
1085 * @returns VBox status code.
1086 * @param pVM VM handle.
1087 */
1088static DECLCALLBACK(int) vboxbfeConfigConstructor(PVM pVM, void *pvUser)
1089{
1090 int rcAll = VINF_SUCCESS;
1091 int rc;
1092
1093#define UPDATE_RC() do { if (VBOX_FAILURE(rc) && VBOX_SUCCESS(rcAll)) rcAll = rc; } while (0)
1094
1095 /*
1096 * Root values.
1097 */
1098 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
1099 rc = CFGMR3InsertString(pRoot, "Name", "Default VM"); UPDATE_RC();
1100 rc = CFGMR3InsertInteger(pRoot, "RamSize", g_u32MemorySizeMB * _1M); UPDATE_RC();
1101 if (g_fPreAllocRam)
1102 {
1103 rc = CFGMR3InsertInteger(pRoot, "RamPreAlloc", 1); UPDATE_RC();
1104 }
1105 rc = CFGMR3InsertInteger(pRoot, "TimerMillies", 10); UPDATE_RC();
1106#ifdef VBOXSDL_ADVANCED_OPTIONS
1107 rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled", g_fRawR3); UPDATE_RC();
1108 rc = CFGMR3InsertInteger(pRoot, "RawR0Enabled", g_fRawR0); UPDATE_RC();
1109 rc = CFGMR3InsertInteger(pRoot, "PATMEnabled", g_fPATM); UPDATE_RC();
1110 rc = CFGMR3InsertInteger(pRoot, "CSAMEnabled", g_fCSAM); UPDATE_RC();
1111#else
1112 rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled", 1); UPDATE_RC();
1113 rc = CFGMR3InsertInteger(pRoot, "RawR0Enabled", 1); UPDATE_RC();
1114 rc = CFGMR3InsertInteger(pRoot, "PATMEnabled", 1); UPDATE_RC();
1115 rc = CFGMR3InsertInteger(pRoot, "CSAMEnabled", 1); UPDATE_RC();
1116#endif
1117
1118 /*
1119 * PDM.
1120 */
1121 rc = PDMR3RegisterDrivers(pVM, VBoxDriversRegister); UPDATE_RC();
1122
1123 /*
1124 * Devices
1125 */
1126 PCFGMNODE pDevices = NULL;
1127 rc = CFGMR3InsertNode(pRoot, "Devices", &pDevices); UPDATE_RC();
1128 /* device */
1129 PCFGMNODE pDev = NULL;
1130 PCFGMNODE pInst = NULL;
1131 PCFGMNODE pCfg = NULL;
1132 PCFGMNODE pLunL0 = NULL;
1133 PCFGMNODE pLunL1 = NULL;
1134 PCFGMNODE pDrv = NULL;
1135
1136 /*
1137 * PC Arch.
1138 */
1139 rc = CFGMR3InsertNode(pDevices, "pcarch", &pDev); UPDATE_RC();
1140 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1141 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1142 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1143
1144 /*
1145 * PC Bios.
1146 */
1147 rc = CFGMR3InsertNode(pDevices, "pcbios", &pDev); UPDATE_RC();
1148 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1149 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1150 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1151 rc = CFGMR3InsertInteger(pCfg, "RamSize", g_u32MemorySizeMB * _1M); UPDATE_RC();
1152 rc = CFGMR3InsertString(pCfg, "BootDevice0", pszBootDevice); UPDATE_RC();
1153 rc = CFGMR3InsertString(pCfg, "BootDevice1", "NONE"); UPDATE_RC();
1154 rc = CFGMR3InsertString(pCfg, "BootDevice2", "NONE"); UPDATE_RC();
1155 rc = CFGMR3InsertString(pCfg, "BootDevice3", "NONE"); UPDATE_RC();
1156 rc = CFGMR3InsertString(pCfg, "HardDiskDevice", "piix3ide"); UPDATE_RC();
1157 rc = CFGMR3InsertString(pCfg, "FloppyDevice", "i82078"); UPDATE_RC();
1158 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", g_fIOAPIC); UPDATE_RC();
1159
1160 /* Default: no bios logo. */
1161 rc = CFGMR3InsertInteger(pCfg, "FadeIn", 1); UPDATE_RC();
1162 rc = CFGMR3InsertInteger(pCfg, "FadeOut", 0); UPDATE_RC();
1163 rc = CFGMR3InsertInteger(pCfg, "LogoTime", 0); UPDATE_RC();
1164 rc = CFGMR3InsertString(pCfg, "LogoFile", ""); UPDATE_RC();
1165
1166 /* Boot menu */
1167 rc = CFGMR3InsertInteger(pCfg, "ShowBootMenu", g_iBootMenu); UPDATE_RC();
1168
1169 /*
1170 * ACPI
1171 */
1172 if (g_fACPI)
1173 {
1174 rc = CFGMR3InsertNode(pDevices, "acpi", &pDev); UPDATE_RC();
1175 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1176 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1177 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1178 rc = CFGMR3InsertInteger(pCfg, "RamSize", g_u32MemorySizeMB * _1M); UPDATE_RC();
1179 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", g_fIOAPIC); UPDATE_RC();
1180 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 7); UPDATE_RC();
1181 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATE_RC();
1182
1183 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1184 rc = CFGMR3InsertString(pLunL0, "Driver", "ACPIHost"); UPDATE_RC();
1185 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1186 }
1187
1188 /*
1189 * PCI bus.
1190 */
1191 rc = CFGMR3InsertNode(pDevices, "pci", &pDev); /* piix3 */ UPDATE_RC();
1192 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1193 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1194 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1195 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", g_fIOAPIC); UPDATE_RC();
1196
1197 /*
1198 * DMA
1199 */
1200 rc = CFGMR3InsertNode(pDevices, "8237A", &pDev); UPDATE_RC();
1201 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1202 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1203
1204 /*
1205 * PCI bus.
1206 */
1207 rc = CFGMR3InsertNode(pDevices, "pci", &pDev); /* piix3 */ UPDATE_RC();
1208 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1209 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1210 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1211
1212 /*
1213 * PS/2 keyboard & mouse.
1214 */
1215 rc = CFGMR3InsertNode(pDevices, "pckbd", &pDev); UPDATE_RC();
1216 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1217 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1218 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1219
1220 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1221 rc = CFGMR3InsertString(pLunL0, "Driver", "KeyboardQueue"); UPDATE_RC();
1222 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1223 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 64); UPDATE_RC();
1224
1225 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pDrv); UPDATE_RC();
1226 rc = CFGMR3InsertString(pDrv, "Driver", "MainKeyboard"); UPDATE_RC();
1227 rc = CFGMR3InsertNode(pDrv, "Config", &pCfg); UPDATE_RC();
1228 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)gKeyboard); UPDATE_RC();
1229
1230 rc = CFGMR3InsertNode(pInst, "LUN#1", &pLunL0); UPDATE_RC();
1231 rc = CFGMR3InsertString(pLunL0, "Driver", "MouseQueue"); UPDATE_RC();
1232 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1233 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 128); UPDATE_RC();
1234
1235 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pDrv); UPDATE_RC();
1236 rc = CFGMR3InsertString(pDrv, "Driver", "MainMouse"); UPDATE_RC();
1237 rc = CFGMR3InsertNode(pDrv, "Config", &pCfg); UPDATE_RC();
1238 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)gMouse); UPDATE_RC();
1239
1240
1241 /*
1242 * i82078 Floppy drive controller
1243 */
1244 rc = CFGMR3InsertNode(pDevices, "i82078", &pDev); UPDATE_RC();
1245 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1246 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); UPDATE_RC();
1247 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1248 rc = CFGMR3InsertInteger(pCfg, "IRQ", 6); UPDATE_RC();
1249 rc = CFGMR3InsertInteger(pCfg, "DMA", 2); UPDATE_RC();
1250 rc = CFGMR3InsertInteger(pCfg, "MemMapped", 0 ); UPDATE_RC();
1251 rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x3f0); UPDATE_RC();
1252
1253 /* Attach the status driver */
1254 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); UPDATE_RC();
1255 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); UPDATE_RC();
1256 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1257 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&mapFDLeds[0]); UPDATE_RC();
1258 rc = CFGMR3InsertInteger(pCfg, "First", 0); UPDATE_RC();
1259 rc = CFGMR3InsertInteger(pCfg, "Last", 0); UPDATE_RC();
1260
1261 if (g_pszFdaFile)
1262 {
1263 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1264 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); UPDATE_RC();
1265 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1266 rc = CFGMR3InsertString(pCfg, "Type", "Floppy 1.44"); UPDATE_RC();
1267 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); UPDATE_RC();
1268
1269 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pDrv); UPDATE_RC();
1270 rc = CFGMR3InsertString(pDrv, "Driver", "RawImage"); UPDATE_RC();
1271 rc = CFGMR3InsertNode(pDrv, "Config", &pCfg); UPDATE_RC();
1272 rc = CFGMR3InsertString(pCfg, "Path", g_pszFdaFile); UPDATE_RC();
1273 }
1274
1275 /*
1276 * i8254 Programmable Interval Timer And Dummy Speaker
1277 */
1278 rc = CFGMR3InsertNode(pDevices, "i8254", &pDev); UPDATE_RC();
1279 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1280 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1281#ifdef DEBUG
1282 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1283#endif
1284
1285 /*
1286 * i8259 Programmable Interrupt Controller.
1287 */
1288 rc = CFGMR3InsertNode(pDevices, "i8259", &pDev); UPDATE_RC();
1289 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1290 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1291 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1292
1293 /*
1294 * Advanced Programmable Interrupt Controller.
1295 */
1296 rc = CFGMR3InsertNode(pDevices, "apic", &pDev); UPDATE_RC();
1297 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1298 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1299 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1300 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", g_fIOAPIC); UPDATE_RC();
1301
1302 /*
1303 * I/O Advanced Programmable Interrupt Controller.
1304 */
1305 if (g_fIOAPIC)
1306 {
1307 rc = CFGMR3InsertNode(pDevices, "ioapic", &pDev); UPDATE_RC();
1308 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1309 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1310 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1311 }
1312
1313 /*
1314 * RTC MC146818.
1315 */
1316 rc = CFGMR3InsertNode(pDevices, "mc146818", &pDev); UPDATE_RC();
1317 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1318 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1319
1320 /*
1321 * Serial ports
1322 */
1323 rc = CFGMR3InsertNode(pDevices, "serial", &pDev); UPDATE_RC();
1324 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1325 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1326 rc = CFGMR3InsertInteger(pCfg, "IRQ", 4); UPDATE_RC();
1327 rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x3f8); UPDATE_RC();
1328
1329 rc = CFGMR3InsertNode(pDev, "1", &pInst); UPDATE_RC();
1330 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1331 rc = CFGMR3InsertInteger(pCfg, "IRQ", 3); UPDATE_RC();
1332 rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x2f8); UPDATE_RC();
1333
1334 /*
1335 * VGA.
1336 */
1337 rc = CFGMR3InsertNode(pDevices, "vga", &pDev); UPDATE_RC();
1338 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1339 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1340 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 2); UPDATE_RC();
1341 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATE_RC();
1342 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1343 rc = CFGMR3InsertInteger(pCfg, "VRamSize", g_u32VRamSizeMB * _1M); UPDATE_RC();
1344
1345#ifdef __L4ENV__
1346 /* XXX hard-coded */
1347 rc = CFGMR3InsertInteger(pCfg, "HeightReduction", 18); UPDATE_RC();
1348 rc = CFGMR3InsertInteger(pCfg, "CustomVideoModes", 1); UPDATE_RC();
1349 char szBuf[64];
1350 /* Tell the guest which is the ideal video mode to use */
1351 RTStrPrintf(szBuf, sizeof(szBuf), "%dx%dx%d",
1352 gFramebuffer->getHostXres(),
1353 gFramebuffer->getHostYres(),
1354 gFramebuffer->getHostBitsPerPixel());
1355 rc = CFGMR3InsertString(pCfg, "CustomVideoMode1", szBuf); UPDATE_RC();
1356#endif
1357
1358 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1359 rc = CFGMR3InsertString(pLunL0, "Driver", "MainDisplay"); UPDATE_RC();
1360 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1361 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)gDisplay); UPDATE_RC();
1362
1363 /*
1364 * IDE (update this when the main interface changes)
1365 */
1366 rc = CFGMR3InsertNode(pDevices, "piix3ide", &pDev); /* piix3 */ UPDATE_RC();
1367 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1368 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1369 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 1); UPDATE_RC();
1370 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 1); UPDATE_RC();
1371 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1372
1373 if (g_pszHdaFile)
1374 {
1375 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1376 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); UPDATE_RC();
1377 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1378 rc = CFGMR3InsertString(pCfg, "Type", "HardDisk"); UPDATE_RC();
1379 rc = CFGMR3InsertInteger(pCfg, "Mountable", 0); UPDATE_RC();
1380
1381 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pDrv); UPDATE_RC();
1382 rc = CFGMR3InsertString(pDrv, "Driver", "VBoxHDD"); UPDATE_RC();
1383 rc = CFGMR3InsertNode(pDrv, "Config", &pCfg); UPDATE_RC();
1384 rc = CFGMR3InsertString(pCfg, "Path", g_pszHdaFile); UPDATE_RC();
1385 }
1386
1387 if (g_pszHdbFile)
1388 {
1389 rc = CFGMR3InsertNode(pInst, "LUN#1", &pLunL1); UPDATE_RC();
1390 rc = CFGMR3InsertString(pLunL1, "Driver", "Block"); UPDATE_RC();
1391 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); UPDATE_RC();
1392 rc = CFGMR3InsertString(pCfg, "Type", "HardDisk"); UPDATE_RC();
1393 rc = CFGMR3InsertInteger(pCfg, "Mountable", 0); UPDATE_RC();
1394
1395 rc = CFGMR3InsertNode(pLunL1, "AttachedDriver", &pDrv); UPDATE_RC();
1396 rc = CFGMR3InsertString(pDrv, "Driver", "VBoxHDD"); UPDATE_RC();
1397 rc = CFGMR3InsertNode(pDrv, "Config", &pCfg); UPDATE_RC();
1398 rc = CFGMR3InsertString(pCfg, "Path", g_pszHdbFile); UPDATE_RC();
1399 }
1400
1401 if (g_pszCdromFile)
1402 {
1403 // ASSUME: DVD drive is always attached to LUN#2 (i.e. secondary IDE master)
1404 rc = CFGMR3InsertNode(pInst, "LUN#2", &pLunL0); UPDATE_RC();
1405 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); UPDATE_RC();
1406 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1407 rc = CFGMR3InsertString(pCfg, "Type", "DVD"); UPDATE_RC();
1408 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); UPDATE_RC();
1409
1410 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pDrv); UPDATE_RC();
1411 rc = CFGMR3InsertString(pDrv, "Driver", "MediaISO"); UPDATE_RC();
1412 rc = CFGMR3InsertNode(pDrv, "Config", &pCfg); UPDATE_RC();
1413 rc = CFGMR3InsertString(pCfg, "Path", g_pszCdromFile); UPDATE_RC();
1414 }
1415
1416 /*
1417 * Network adapters
1418 */
1419 rc = CFGMR3InsertNode(pDevices, "pcnet", &pDev); UPDATE_RC();
1420 for (ULONG ulInstance = 0; ulInstance < NetworkAdapterCount; ulInstance++)
1421 {
1422 if (g_aNetDevs[ulInstance].enmType != BFENETDEV::NOT_CONFIGURED)
1423 {
1424 char szInstance[4];
1425 RTStrPrintf(szInstance, sizeof(szInstance), "%lu", ulInstance);
1426 rc = CFGMR3InsertNode(pDev, szInstance, &pInst); UPDATE_RC();
1427 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); UPDATE_RC();
1428 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo",
1429 !ulInstance ? 3 : ulInstance - 1 + 8); UPDATE_RC();
1430 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATE_RC();
1431 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1432 rc = CFGMR3InsertBytes(pCfg, "MAC", &g_aNetDevs[ulInstance].Mac, sizeof(PDMMAC));
1433 UPDATE_RC();
1434
1435 /*
1436 * Enable the packet sniffer if requested.
1437 */
1438 if (g_aNetDevs[ulInstance].fSniff)
1439 {
1440 /* insert the sniffer filter driver. */
1441 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1442 rc = CFGMR3InsertString(pLunL0, "Driver", "NetSniffer"); UPDATE_RC();
1443 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1444 if (g_aNetDevs[ulInstance].pszSniff)
1445 {
1446 rc = CFGMR3InsertString(pCfg, "File", g_aNetDevs[ulInstance].pszSniff);
1447 UPDATE_RC();
1448 }
1449 }
1450
1451 /*
1452 * Create the driver config (if any).
1453 */
1454 if (g_aNetDevs[ulInstance].enmType != BFENETDEV::NONE)
1455 {
1456 if (g_aNetDevs[ulInstance].fSniff)
1457 {
1458 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); UPDATE_RC();
1459 }
1460 else
1461 {
1462 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1463 }
1464 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1465 }
1466
1467 /*
1468 * Configure the driver.
1469 */
1470 if (g_aNetDevs[ulInstance].enmType == BFENETDEV::NAT)
1471 {
1472 rc = CFGMR3InsertString(pLunL0, "Driver", "NAT"); UPDATE_RC();
1473 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1474 /* (Port forwarding goes here.) */
1475 }
1476 else if (g_aNetDevs[ulInstance].enmType == BFENETDEV::HIF)
1477 {
1478 rc = CFGMR3InsertString(pLunL0, "Driver", "HostInterface"); UPDATE_RC();
1479 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1480
1481#if defined(RT_OS_LINUX)
1482 if (g_aNetDevs[ulInstance].fHaveFd)
1483 {
1484 rc = CFGMR3InsertString(pCfg, "Device", g_aNetDevs[ulInstance].pszName);
1485 UPDATE_RC();
1486 rc = CFGMR3InsertInteger(pCfg, "FileHandle", g_aNetDevs[ulInstance].fd);
1487 UPDATE_RC();
1488 }
1489 else
1490#endif
1491 {
1492#if defined (RT_OS_LINUX) || defined (__L4__)
1493 /*
1494 * Create/Open the TAP the device.
1495 */
1496 RTFILE tapFD;
1497 rc = RTFileOpen(&tapFD, "/dev/net/tun",
1498 RTFILE_O_READWRITE | RTFILE_O_OPEN |
1499 RTFILE_O_DENY_NONE | RTFILE_O_INHERIT);
1500 if (VBOX_FAILURE(rc))
1501 {
1502 FatalError("Failed to open /dev/net/tun: %Vrc\n", rc);
1503 return rc;
1504 }
1505
1506 struct ifreq IfReq;
1507 memset(&IfReq, 0, sizeof(IfReq));
1508 if (g_aNetDevs[ulInstance].pszName && g_aNetDevs[ulInstance].pszName[0])
1509 {
1510 size_t cch = strlen(g_aNetDevs[ulInstance].pszName);
1511 if (cch >= sizeof(IfReq.ifr_name))
1512 {
1513 FatalError("HIF name too long for device #%d: %s\n",
1514 ulInstance + 1, g_aNetDevs[ulInstance].pszName);
1515 return VERR_BUFFER_OVERFLOW;
1516 }
1517 memcpy(IfReq.ifr_name, g_aNetDevs[ulInstance].pszName, cch + 1);
1518 }
1519 else
1520 strcpy(IfReq.ifr_name, "tun%d");
1521 IfReq.ifr_flags = IFF_TAP | IFF_NO_PI;
1522 rc = ioctl(tapFD, TUNSETIFF, &IfReq);
1523 if (rc)
1524 {
1525 int rc2 = RTErrConvertFromErrno(errno);
1526 FatalError("ioctl TUNSETIFF '%s' failed: errno=%d rc=%d (%Vrc)\n",
1527 IfReq.ifr_name, errno, rc, rc2);
1528 return rc2;
1529 }
1530
1531 rc = fcntl(tapFD, F_SETFL, O_NONBLOCK);
1532 if (rc)
1533 {
1534 int rc2 = RTErrConvertFromErrno(errno);
1535 FatalError("fcntl F_SETFL/O_NONBLOCK '%s' failed: errno=%d rc=%d (%Vrc)\n",
1536 IfReq.ifr_name, errno, rc, rc2);
1537 return rc2;
1538 }
1539
1540 rc = CFGMR3InsertString(pCfg, "Device", g_aNetDevs[ulInstance].pszName); UPDATE_RC();
1541 rc = CFGMR3InsertInteger(pCfg, "FileHandle", (RTFILE)tapFD); UPDATE_RC();
1542
1543#elif defined(RT_OS_WINDOWS)
1544 /*
1545 * We need the GUID too here...
1546 */
1547 rc = CFGMR3InsertString(pCfg, "Device", g_aNetDevs[ulInstance].pszName); UPDATE_RC();
1548 rc = CFGMR3InsertString(pCfg, "HostInterfaceName", g_aNetDevs[ulInstance].pszName); UPDATE_RC();
1549 rc = CFGMR3InsertString(pCfg, "GUID", g_aNetDevs[ulInstance].pszName /*pszGUID*/); UPDATE_RC();
1550
1551
1552#else /* !RT_OS_LINUX && !__L4__ */
1553 FatalError("Name based HIF devices not implemented yet for this host platform\n");
1554 return VERR_NOT_IMPLEMENTED;
1555#endif
1556 }
1557 }
1558 else if (g_aNetDevs[ulInstance].enmType == BFENETDEV::INTNET)
1559 {
1560 /*
1561 * Internal networking.
1562 */
1563 rc = CFGMR3InsertString(pCfg, "Network", g_aNetDevs[ulInstance].pszName); UPDATE_RC();
1564 }
1565 }
1566 }
1567
1568 /*
1569 * VMM Device
1570 */
1571 rc = CFGMR3InsertNode(pDevices, "VMMDev", &pDev); UPDATE_RC();
1572 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1573 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1574 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1575 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 4); UPDATE_RC();
1576 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATE_RC();
1577
1578 /* the VMM device's Main driver */
1579 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1580 rc = CFGMR3InsertString(pLunL0, "Driver", "MainVMMDev"); UPDATE_RC();
1581 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1582 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)gVMMDev); UPDATE_RC();
1583
1584 /*
1585 * AC'97 ICH audio
1586 */
1587 if (g_fAudio)
1588 {
1589 rc = CFGMR3InsertNode(pDevices, "ichac97", &pDev); UPDATE_RC();
1590 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1591 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1592 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 5); UPDATE_RC();
1593 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATE_RC();
1594 rc = CFGMR3InsertNode(pInst, "Config", &pCfg);
1595
1596 /* the Audio driver */
1597 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1598 rc = CFGMR3InsertString(pLunL0, "Driver", "AUDIO"); UPDATE_RC();
1599 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1600#ifdef RT_OS_WINDOWS
1601 rc = CFGMR3InsertString(pCfg, "AudioDriver", "winmm"); UPDATE_RC();
1602#elif defined(RT_OS_DARWIN)
1603 rc = CFGMR3InsertString(pCfg, "AudioDriver", "coreaudio"); UPDATE_RC();
1604#elif defined(RT_OS_LINUX)
1605 rc = CFGMR3InsertString(pCfg, "AudioDriver", "oss"); UPDATE_RC();
1606#elif defined(__L4ENV__)
1607 rc = CFGMR3InsertString(pCfg, "AudioDriver", "oss"); UPDATE_RC();
1608#else /* portme */
1609 rc = CFGMR3InsertString(pCfg, "AudioDriver", "none"); UPDATE_RC();
1610#endif /* !RT_OS_WINDOWS */
1611 }
1612
1613#ifdef VBOXBFE_WITH_USB
1614 /*
1615 * The USB Controller.
1616 */
1617 if (g_fUSB)
1618 {
1619 rc = CFGMR3InsertNode(pDevices, "usb-ohci", &pDev); UPDATE_RC();
1620 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1621 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1622 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1623 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 6); UPDATE_RC();
1624 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATE_RC();
1625
1626 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1627 rc = CFGMR3InsertString(pLunL0, "Driver", "VUSBRootHub"); UPDATE_RC();
1628 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1629 }
1630#endif /* VBOXBFE_WITH_USB */
1631
1632#undef UPDATE_RC
1633#undef UPDATE_RC
1634
1635 VMR3AtRuntimeErrorRegister (pVM, setVMRuntimeErrorCallback, NULL);
1636
1637 return rc;
1638}
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