VirtualBox

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

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

FE/BFE: the MainVMMDev driver is now called HGCM

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