VirtualBox

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

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

completed the -brdevN lanX code.

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