VirtualBox

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

Last change on this file since 29809 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

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