VirtualBox

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

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

introduced RTLogCreateEx and RTLogCreateExV to be able to pass an error string back to the caller

  • 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(__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(__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 __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 __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 /* __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(__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);
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, "PreAllocRam", 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(__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 (__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(__WIN__)
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 /* !__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 __WIN__
1601 rc = CFGMR3InsertString(pCfg, "AudioDriver", "winmm"); UPDATE_RC();
1602#elif defined(__DARWIN__)
1603 rc = CFGMR3InsertString(pCfg, "AudioDriver", "coreaudio"); UPDATE_RC();
1604#elif defined(__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 /* !__WIN__ */
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