VirtualBox

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

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

The Giant CDDL Dual-License Header Change.

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