VirtualBox

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

Last change on this file since 4183 was 4183, checked in by vboxsync, 18 years ago

Removed dead options from VBoxBFE for L4

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

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