VirtualBox

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

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

support .vmdk files in VBoxBFE

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