VirtualBox

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

Last change on this file since 13068 was 12320, checked in by vboxsync, 16 years ago

small banner fix

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 75.5 KB
Line 
1/* $Id: VBoxBFE.cpp 12320 2008-09-09 20:03:07Z vboxsync $ */
2/** @file
3 * Basic Frontend (BFE): VBoxBFE main routines.
4 *
5 * VBoxBFE is a limited frontend that sits directly on the Virtual Machine
6 * Manager (VMM) and does _not_ use COM to communicate.
7 * On Linux and Windows, VBoxBFE is based on SDL; on L4 it's based on the
8 * L4 console. Much of the code has been copied over from the other frontends
9 * in VBox/Main/ and src/Frontends/VBoxSDL/.
10 */
11
12/*
13 * Copyright (C) 2006-2007 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/alloca.h>
52#include <iprt/assert.h>
53#include <iprt/ctype.h>
54#include <iprt/file.h>
55#include <iprt/path.h>
56#include <iprt/runtime.h>
57#include <iprt/semaphore.h>
58#include <iprt/stream.h>
59#include <iprt/string.h>
60#include <iprt/thread.h>
61#include <iprt/uuid.h>
62
63#include "VBoxBFE.h"
64
65#include <stdio.h>
66#include <stdlib.h> /* putenv */
67#include <errno.h>
68
69#if defined(RT_OS_LINUX) || defined(RT_OS_L4)
70#include <fcntl.h>
71#include <net/if.h>
72#include <sys/ioctl.h>
73#include <linux/if_tun.h>
74#endif
75
76#include "ConsoleImpl.h"
77#include "DisplayImpl.h"
78#include "MouseImpl.h"
79#include "KeyboardImpl.h"
80#include "VMMDevInterface.h"
81#include "StatusImpl.h"
82#include "Framebuffer.h"
83#include "MachineDebuggerImpl.h"
84#ifdef VBOXBFE_WITH_USB
85# include "HostUSBImpl.h"
86#endif
87
88#if defined(USE_SDL) && ! defined(RT_OS_L4)
89#include "SDLConsole.h"
90#include "SDLFramebuffer.h"
91#endif
92
93#ifdef RT_OS_L4
94#include "L4Console.h"
95#include "L4Framebuffer.h"
96#include "L4IDLInterface.h"
97#endif
98
99#ifdef RT_OS_L4
100# include <l4/sys/ktrace.h>
101# include <l4/vboxserver/file.h>
102#endif
103
104/*******************************************************************************
105* Defined Constants And Macros *
106*******************************************************************************/
107
108#define VBOXSDL_ADVANCED_OPTIONS
109#define MAC_STRING_LEN 12
110
111
112/*******************************************************************************
113* Internal Functions *
114*******************************************************************************/
115static DECLCALLBACK(int) vboxbfeConfigConstructor(PVM pVM, void *pvUser);
116static DECLCALLBACK(void) vmstateChangeCallback(PVM pVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser);
117static DECLCALLBACK(void) setVMErrorCallback(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL,
118 const char *pszFormat, va_list args);
119static DECLCALLBACK(int) VMPowerUpThread(RTTHREAD Thread, void *pvUser);
120
121
122/*******************************************************************************
123* Global Variables *
124*******************************************************************************/
125
126PVM pVM = NULL;
127Mouse *gMouse = NULL;
128VMDisplay *gDisplay = NULL;
129Keyboard *gKeyboard = NULL;
130VMMDev *gVMMDev = NULL;
131Framebuffer *gFramebuffer = NULL;
132MachineDebugger *gMachineDebugger = NULL;
133VMStatus *gStatus = NULL;
134Console *gConsole = NULL;
135#ifdef VBOXBFE_WITH_USB
136HostUSB *gHostUSB = NULL;
137#endif
138
139VMSTATE machineState = VMSTATE_CREATING;
140
141static PPDMLED mapFDLeds[2] = {0};
142
143/** flag whether keyboard/mouse events are grabbed */
144#ifdef RT_OS_L4
145/** see <l4/input/macros.h> for key definitions */
146int gHostKey; /* not used */
147int gHostKeySym = KEY_RIGHTCTRL;
148#elif defined (DEBUG_dmik)
149// my mini kbd doesn't have RCTRL...
150int gHostKey = KMOD_RSHIFT;
151int gHostKeySym = SDLK_RSHIFT;
152#else
153int gHostKey = KMOD_RCTRL;
154int gHostKeySym = SDLK_RCTRL;
155#endif
156bool gfAllowFullscreenToggle = true;
157
158static bool g_fIOAPIC = false;
159static bool g_fACPI = true;
160static bool g_fAudio = false;
161#ifdef VBOXBFE_WITH_USB
162static bool g_fUSB = false;
163#endif
164static char *g_pszHdaFile = NULL;
165static bool g_fHdaSpf = false;
166static char *g_pszHdbFile = NULL;
167static bool g_fHdbSpf = false;
168static char *g_pszCdromFile = NULL;
169static char *g_pszFdaFile = NULL;
170 const char *g_pszStateFile = NULL;
171static const char *g_pszBootDevice = "IDE";
172static uint32_t g_u32MemorySizeMB = 128;
173static uint32_t g_u32VRamSize = 4 * _1M;
174#ifdef VBOXSDL_ADVANCED_OPTIONS
175static bool g_fRawR0 = true;
176static bool g_fRawR3 = true;
177static bool g_fPATM = true;
178static bool g_fCSAM = true;
179#endif
180static bool g_fRestoreState = false;
181static const char *g_pszShareDir[MaxSharedFolders];
182static const char *g_pszShareName[MaxSharedFolders];
183static bool g_fShareReadOnly[MaxSharedFolders];
184static unsigned g_uNumShares;
185static bool g_fPreAllocRam = false;
186static int g_iBootMenu = 2;
187static bool g_fReleaseLog = true; /**< Set if we should open the release. */
188 const char *g_pszProgressString;
189 unsigned g_uProgressPercent = ~0U;
190
191
192/**
193 * Network device config info.
194 */
195typedef struct BFENetworkDevice
196{
197 enum
198 {
199 NOT_CONFIGURED = 0,
200 NONE,
201 NAT,
202 HIF,
203 INTNET
204 } enmType; /**< The type of network driver. */
205 bool fSniff; /**< Set if the network sniffer should be installed. */
206 const char *pszSniff; /**< Output file for the network sniffer. */
207 RTMAC Mac; /**< The mac address for the device. */
208 const char *pszName; /**< The device name of a HIF device. The name of the internal network. */
209#ifdef RT_OS_OS2
210 bool fHaveConnectTo; /**< Whether fConnectTo is set. */
211 int32_t iConnectTo; /**< The lanX to connect to (bridge with). */
212#elif 1//defined(RT_OS_LINUX)
213 bool fHaveFd; /**< Set if fd is valid. */
214 int32_t fd; /**< The file descriptor of a HIF device.*/
215#endif
216} BFENETDEV, *PBFENETDEV;
217
218/** Array of network device configurations. */
219static BFENETDEV g_aNetDevs[NetworkAdapterCount];
220
221
222/** @todo currently this is only set but never read. */
223static char szError[512];
224
225
226/**
227 */
228bool fActivateHGCM()
229{
230 return !!(g_uNumShares > 0);
231}
232
233/**
234 * Converts the passed in network option
235 *
236 * @returns Index into g_aNetDevs on success. (positive)
237 * @returns VERR_INVALID_PARAMETER on failure. (negative)
238 * @param pszArg The argument.
239 * @param cchRoot The length of the argument root.
240 */
241static int networkArg2Index(const char *pszArg, int cchRoot)
242{
243 uint32_t n;
244 int rc = RTStrToUInt32Ex(&pszArg[cchRoot], NULL, 10, &n);
245 if (VBOX_FAILURE(rc))
246 {
247 RTPrintf("Error: invalid network device option (rc=%Vrc): %s\n", rc, pszArg);
248 return -1;
249 }
250 if (n < 1 || n > NetworkAdapterCount)
251 {
252 RTPrintf("Error: The network device number is out of range: %RU32 (1 <= 0 <= %u) (%s)\n",
253 n, NetworkAdapterCount, pszArg);
254 return -1;
255 }
256 return n;
257}
258
259/**
260 * Generates a new unique MAC address based on our vendor ID and
261 * parts of a GUID.
262 *
263 * @returns iprt status code
264 * @param pAddress An array into which to store the newly generated address
265 */
266int GenerateMACAddress(char pszAddress[MAC_STRING_LEN + 1])
267{
268 /*
269 * Our strategy is as follows: the first three bytes are our fixed
270 * vendor ID (080027). The remaining 3 bytes will be taken from the
271 * start of a GUID. This is a fairly safe algorithm.
272 */
273 LogFlowFunc(("called\n"));
274 RTUUID uuid;
275 int rc = RTUuidCreate(&uuid);
276 if (RT_FAILURE(rc))
277 {
278 LogFlowFunc(("RTUuidCreate failed, returning %Vrc\n", rc));
279 return rc;
280 }
281 RTStrPrintf(pszAddress, MAC_STRING_LEN + 1, "080027%02X%02X%02X",
282 uuid.au8[0], uuid.au8[1], uuid.au8[2]);
283 LogFlowFunc(("generated MAC: '%s'\n", pszAddress));
284 return VINF_SUCCESS;
285}
286
287/**
288 * Print a syntax error.
289 *
290 * @returns return value for main().
291 * @param pszMsg The message format string.
292 * @param ... Format arguments.
293 */
294static int SyntaxError(const char *pszMsg, ...)
295{
296 va_list va;
297 RTPrintf("error: ");
298 va_start(va, pszMsg);
299 RTPrintfV(pszMsg, va);
300 va_end(va);
301 return 1;
302}
303
304
305/**
306 * Print a fatal error.
307 *
308 * @returns return value for main().
309 * @param pszMsg The message format string.
310 * @param ... Format arguments.
311 */
312static int FatalError(const char *pszMsg, ...)
313{
314 va_list va;
315 RTPrintf("fatal error: ");
316 va_start(va, pszMsg);
317 RTPrintfV(pszMsg, va);
318 va_end(va);
319 return 1;
320}
321
322/**
323 * Start progress display.
324 */
325void startProgressInfo(const char *pszStr)
326{
327 g_pszProgressString = pszStr;
328 g_uProgressPercent = 0;
329}
330
331/**
332 * Update progress display.
333 */
334void callProgressInfo(PVM pVM, unsigned uPercent, void *pvUser)
335{
336 if (gConsole)
337 gConsole->progressInfo(pVM, uPercent, pvUser);
338}
339
340/**
341 * End progress display.
342 */
343void endProgressInfo(void)
344{
345 g_uProgressPercent = ~0U;
346}
347
348
349/**
350 * Print program usage.
351 */
352static void show_usage()
353{
354 RTPrintf("Usage:\n"
355 " -hda <file> Set first hard disk to file\n"
356 " -hdb <file> Set second hard disk to file\n"
357 " -fda <file> Set first floppy disk to file\n"
358 " -cdrom <file> Set CDROM to file/device ('none' to unmount)\n"
359 " -boot <a|c|d> Set boot device (a = floppy, c = first hard disk, d = DVD)\n"
360 " -boot menu <0|1|2> Boot menu (0 = disable, 1 = menu only, 2 = message + menu)\n"
361 " -m <size> Set memory size in megabytes (default 128MB)\n"
362 " -vram <size> Set size of video memory in megabytes\n"
363 " -prealloc Force RAM pre-allocation\n"
364 " -fullscreen Start VM in fullscreen mode\n"
365 " -statefile <file> Define the file name for VM save/restore\n"
366 " -restore Restore the VM if the statefile exists, normal start otherwise\n"
367 " -nofstoggle Forbid switching to/from fullscreen mode\n"
368 " -share <dir> <name> [readonly]\n"
369 " Share directory <dir> as name <name>. Optionally read-only.\n"
370 " -nohostkey Disable hostkey\n"
371 " -[no]acpi Enable or disable ACPI (default: enabled)\n"
372 " -[no]ioapic Enable or disable the IO-APIC (default: disabled)\n"
373 " -audio Enable audio\n"
374#ifndef RT_OS_L4
375 " -natdev<1-N> [mac] Use NAT networking on network adapter <N>. Use hardware\n"
376 " address <mac> if specified.\n"
377#endif
378 " -hifdev<1-N> Use Host Interface Networking with host interface <int>\n"
379 " <int> [mac] on network adapter <N>. Use hardware address <mac> if\n"
380 " specified.\n"
381#ifndef RT_OS_L4
382 " -intnet<1-N> Attach network adapter <N> to internal network <net>. Use\n"
383 " <net> [mac] hardware address <mac> if specified.\n"
384#endif
385#if 0
386 " -netsniff<1-N> Enable packet sniffer\n"
387#endif
388#ifdef RT_OS_OS2
389 " -brdev<1-N> lan<X> Bridge network adaptor <N> with the 'lanX' device.\n"
390#endif
391#ifdef RT_OS_LINUX
392 " -tapfd<1-N> <fd> Use existing TAP device, don't allocate\n"
393#endif
394#ifdef VBOX_WITH_VRDP
395 " -vrdp [port] Listen for VRDP connections on port (default if not specified)\n"
396#endif
397#ifdef VBOX_SECURELABEL
398 " -securelabel Display a secure VM label at the top of the screen\n"
399 " -seclabelfnt TrueType (.ttf) font file for secure session label\n"
400 " -seclabelsiz Font point size for secure session label (default 12)\n"
401#endif
402 " -[no]rellog Enable or disable the release log './VBoxBFE.log' (default: enabled)\n"
403#ifdef VBOXSDL_ADVANCED_OPTIONS
404 " -[no]rawr0 Enable or disable raw ring 3\n"
405 " -[no]rawr3 Enable or disable raw ring 0\n"
406 " -[no]patm Enable or disable PATM\n"
407 " -[no]csam Enable or disable CSAM\n"
408#endif
409#ifdef RT_OS_L4
410 " -env <var=value> Set the given environment variable to \"value\"\n"
411#endif
412 "\n");
413}
414
415
416/** entry point */
417extern "C" DECLEXPORT(int) TrustedMain (int argc, char **argv, char **envp)
418{
419 bool fFullscreen = false;
420#ifdef VBOX_WITH_VRDP
421 int32_t portVRDP = -1;
422#endif
423#ifdef VBOX_SECURELABEL
424 bool fSecureLabel = false;
425 uint32_t secureLabelPointSize = 12;
426 char *secureLabelFontFile = NULL;
427#endif
428#ifdef RT_OS_L4
429 uint32_t u32MaxVRAM;
430#endif
431 int rc = VINF_SUCCESS;
432
433 RTPrintf("Sun xVM VirtualBox Simple SDL GUI built %s %s\n", __DATE__, __TIME__);
434
435 // less than one parameter is not possible
436 if (argc < 2)
437 {
438 show_usage();
439 return 1;
440 }
441
442 /*
443 * Parse the command line arguments.
444 */
445 for (int curArg = 1; curArg < argc; curArg++)
446 {
447 const char * const pszArg = argv[curArg];
448 if (strcmp(pszArg, "-boot") == 0)
449 {
450 if (++curArg >= argc)
451 return SyntaxError("missing argument for boot drive!\n");
452 if (strlen(argv[curArg]) != 1)
453 return SyntaxError("invalid argument for boot drive! (%s)\n", argv[curArg]);
454 rc = VINF_SUCCESS;
455 switch (argv[curArg][0])
456 {
457 case 'a':
458 {
459 g_pszBootDevice = "FLOPPY";
460 break;
461 }
462
463 case 'c':
464 {
465 g_pszBootDevice = "IDE";
466 break;
467 }
468
469 case 'd':
470 {
471 g_pszBootDevice = "DVD";
472 break;
473 }
474
475 default:
476 return SyntaxError("wrong argument for boot drive! (%s)\n", argv[curArg]);
477 }
478 }
479 else if (strcmp(pszArg, "-bootmenu") == 0)
480 {
481 if (++curArg >= argc)
482 return SyntaxError("missing argument for boot menu!\n");
483 if (strlen(argv[curArg]) != 1 || *argv[curArg] < '0' || *argv[curArg] > '2')
484 return SyntaxError("invalid argument for boot menu! (%s)\n", argv[curArg]);
485 rc = VINF_SUCCESS;
486 g_iBootMenu = *argv[curArg] - 0;
487 }
488 else if (strcmp(pszArg, "-m") == 0)
489 {
490 if (++curArg >= argc)
491 return SyntaxError("missing argument for memory size!\n");
492 rc = RTStrToUInt32Ex(argv[curArg], NULL, 0, &g_u32MemorySizeMB);
493 if (VBOX_FAILURE(rc))
494 return SyntaxError("bad memory size: %s (error %Vrc)\n",
495 argv[curArg], rc);
496 }
497 else if (strcmp(pszArg, "-vram") == 0)
498 {
499 if (++curArg >= argc)
500 return SyntaxError("missing argument for vram size!\n");
501 uint32_t uVRAMMB;
502 rc = RTStrToUInt32Ex(argv[curArg], NULL, 0, &uVRAMMB);
503 g_u32VRamSize = uVRAMMB * _1M;
504 if (VBOX_FAILURE(rc))
505 return SyntaxError("bad video ram size: %s (error %Vrc)\n",
506 argv[curArg], rc);
507 }
508 else if (strcmp(pszArg, "-statefile") == 0)
509 {
510 if (++curArg >= argc)
511 return SyntaxError("missing argument for restore!\n");
512 g_pszStateFile = argv[curArg];
513 }
514 else if (strcmp(pszArg, "-restore") == 0)
515 g_fRestoreState = true;
516 else if (strcmp(pszArg, "-share") == 0)
517 {
518 if (g_uNumShares >= MaxSharedFolders)
519 return SyntaxError("too many shared folders specified!\n");
520 if (++curArg >= argc)
521 return SyntaxError("missing 1s argument for share!\n");
522 g_pszShareDir[g_uNumShares] = argv[curArg];
523 if (++curArg >= argc)
524 return SyntaxError("missing 2nd argument for share!\n");
525 g_pszShareName[g_uNumShares] = argv[curArg];
526 if (curArg < argc-1 && strcmp(argv[curArg+1], "readonly") == 0)
527 {
528 g_fShareReadOnly[g_uNumShares] = true;
529 curArg++;
530 }
531 g_uNumShares++;
532 }
533 else if (strcmp(pszArg, "-fullscreen") == 0)
534 fFullscreen = true;
535 else if (strcmp(pszArg, "-nofstoggle") == 0)
536 gfAllowFullscreenToggle = false;
537 else if (strcmp(pszArg, "-nohostkey") == 0)
538 {
539 gHostKey = 0;
540 gHostKeySym = 0;
541 }
542 else if (strcmp(pszArg, "-acpi") == 0)
543 g_fACPI = true;
544 else if (strcmp(pszArg, "-noacpi") == 0)
545 g_fACPI = false;
546 else if (strcmp(pszArg, "-ioapic") == 0)
547 g_fIOAPIC = true;
548 else if (strcmp(pszArg, "-noioapic") == 0)
549 g_fIOAPIC = false;
550 else if (strcmp(pszArg, "-audio") == 0)
551 g_fAudio = true;
552#ifdef VBOXBFE_WITH_USB
553 else if (strcmp(pszArg, "-usb") == 0)
554 g_fUSB = true;
555#endif
556 else if (strcmp(pszArg, "-hda") == 0)
557 {
558 if (++curArg >= argc)
559 return SyntaxError("missing file name for first hard disk!\n");
560
561 /* resolve it. */
562 if (RTPathExists(argv[curArg]))
563 g_pszHdaFile = RTPathRealDup(argv[curArg]);
564 if (!g_pszHdaFile)
565 return SyntaxError("The path to the specified harddisk, '%s', could not be resolved.\n", argv[curArg]);
566 }
567 else if (strcmp(pszArg, "-hdaspf") == 0)
568 {
569 g_fHdaSpf = true;
570 }
571 else if (strcmp(pszArg, "-hdb") == 0)
572 {
573 if (++curArg >= argc)
574 return SyntaxError("missing file name for second hard disk!\n");
575
576 /* resolve it. */
577 if (RTPathExists(argv[curArg]))
578 g_pszHdbFile = RTPathRealDup(argv[curArg]);
579 if (!g_pszHdbFile)
580 return SyntaxError("The path to the specified harddisk, '%s', could not be resolved.\n", argv[curArg]);
581 }
582 else if (strcmp(pszArg, "-hdbspf") == 0)
583 {
584 g_fHdbSpf = true;
585 }
586 else if (strcmp(pszArg, "-fda") == 0)
587 {
588 if (++curArg >= argc)
589 return SyntaxError("missing file/device name for first floppy disk!\n");
590
591 /* resolve it. */
592 if (RTPathExists(argv[curArg]))
593 g_pszFdaFile = RTPathRealDup(argv[curArg]);
594 if (!g_pszFdaFile)
595 return SyntaxError("The path to the specified floppy disk, '%s', could not be resolved.\n", argv[curArg]);
596 }
597 else if (strcmp(pszArg, "-cdrom") == 0)
598 {
599 if (++curArg >= argc)
600 return SyntaxError("missing file/device name for first hard disk!\n");
601
602 /* resolve it. */
603 if (RTPathExists(argv[curArg]))
604 g_pszCdromFile = RTPathRealDup(argv[curArg]);
605 if (!g_pszCdromFile)
606 return SyntaxError("The path to the specified cdrom, '%s', could not be resolved.\n", argv[curArg]);
607 }
608#ifdef RT_OS_L4
609 /* This is leaving a lot of dead code in the L4 version of course,
610 but I don't think that that is a major problem. We may even
611 activate it sometime... */
612 else if ( strncmp(pszArg, "-hifdev", 7) == 0
613 || strncmp(pszArg, "-nonetd", 7) == 0)
614#else
615 else if ( strncmp(pszArg, "-natdev", 7) == 0
616 || strncmp(pszArg, "-hifdev", 7) == 0
617 || strncmp(pszArg, "-nonetd", 7) == 0
618 || strncmp(pszArg, "-intnet", 7) == 0)
619#endif
620 {
621 int i = networkArg2Index(pszArg, 7);
622 if (i < 0)
623 return 1;
624 g_aNetDevs[i].enmType = !strncmp(pszArg, "-natdev", 7)
625 ? BFENETDEV::NAT
626 : !strncmp(pszArg, "-hifdev", 7)
627 ? BFENETDEV::HIF
628 : !strncmp(pszArg, "-intnet", 7)
629 ? BFENETDEV::INTNET
630 : BFENETDEV::NONE;
631
632 /* The HIF device name / The Internal Network name. */
633 g_aNetDevs[i].pszName = NULL;
634 if ( g_aNetDevs[i].enmType == BFENETDEV::HIF
635 || g_aNetDevs[i].enmType == BFENETDEV::INTNET)
636 {
637 if (curArg + 1 >= argc)
638 return SyntaxError(g_aNetDevs[i].enmType == BFENETDEV::HIF
639 ? "The TAP network device name is missing! (%s)\n"
640 : "The internal network name is missing! (%s)\n"
641 , pszArg);
642 g_aNetDevs[i].pszName = argv[++curArg];
643 }
644
645 /* The MAC address. */
646 const char *pszMac;
647 char szMacGen[MAC_STRING_LEN + 1];
648 if ((curArg + 1 < argc) && (argv[curArg + 1][0] != '-'))
649 pszMac = argv[++curArg];
650 else
651 {
652 rc = GenerateMACAddress(szMacGen);
653 if (RT_FAILURE(rc))
654 return SyntaxError("failed to generate a hardware address for network device %d (error %Vrc)\n",
655 i, rc);
656 pszMac = szMacGen;
657 }
658 if (strlen(pszMac) != MAC_STRING_LEN)
659 return SyntaxError("The network MAC address has an invalid length: %s (%s)\n", pszMac, pszArg);
660 for (unsigned j = 0; j < RT_ELEMENTS(g_aNetDevs[i].Mac.au8); j++)
661 {
662 char c1 = toupper(*pszMac++) - '0';
663 if (c1 > 9)
664 c1 -= 7;
665 char c2 = toupper(*pszMac++) - '0';
666 if (c2 > 9)
667 c2 -= 7;
668 if (c2 > 16 || c1 > 16)
669 return SyntaxError("Invalid MAC address: %s\n", argv[curArg]);
670 g_aNetDevs[i].Mac.au8[j] = ((c1 & 0x0f) << 4) | (c2 & 0x0f);
671 }
672 }
673 else if (strncmp(pszArg, "-netsniff", 9) == 0)
674 {
675 int i = networkArg2Index(pszArg, 9);
676 if (i < 0)
677 return 1;
678 g_aNetDevs[i].fSniff = true;
679 /** @todo filename */
680 }
681#ifdef RT_OS_OS2
682 else if (strncmp(pszArg, "-brdev", 6) == 0)
683 {
684 int i = networkArg2Index(pszArg, 6);
685 if (i < 0)
686 return 1;
687 if (g_aNetDevs[i].enmType != BFENETDEV::HIF)
688 return SyntaxError("%d is not a hif device! Make sure you put the -hifdev argument first.\n", i);
689 if (++curArg >= argc)
690 return SyntaxError("missing argument for %s!\n", pszArg);
691 if ( strncmp(argv[curArg], "lan", 3)
692 || argv[curArg][3] < '0'
693 || argv[curArg][3] >= '8'
694 || argv[curArg][4])
695 return SyntaxError("bad interface name '%s' specified with '%s'. Expected 'lan0', 'lan1' and similar.\n",
696 argv[curArg], pszArg);
697 g_aNetDevs[i].iConnectTo = argv[curArg][3] - '0';
698 g_aNetDevs[i].fHaveConnectTo = true;
699 }
700#endif
701#ifdef RT_OS_LINUX
702 else if (strncmp(pszArg, "-tapfd", 6) == 0)
703 {
704 int i = networkArg2Index(pszArg, 6);
705 if (i < 0)
706 return 1;
707 if (++curArg >= argc)
708 return SyntaxError("missing argument for %s!\n", pszArg);
709 rc = RTStrToInt32Ex(argv[curArg], NULL, 0, &g_aNetDevs[i].fd);
710 if (VBOX_FAILURE(rc))
711 return SyntaxError("bad tap file descriptor: %s (error %VRc)\n", argv[curArg], rc);
712 g_aNetDevs[i].fHaveFd = true;
713 }
714#endif /* RT_OS_LINUX */
715#ifdef VBOX_WITH_VRDP
716 else if (strcmp(pszArg, "-vrdp") == 0)
717 {
718 // -vrdp might take a port number (positive).
719 portVRDP = 0; // indicate that it was encountered.
720 if (curArg + 1 < argc && argv[curArg + 1][0] != '-')
721 {
722 rc = RTStrToInt32Ex(argv[curArg], NULL, 0, &portVRDP);
723 if (VBOX_FAILURE(rc))
724 return SyntaxError("cannot vrpd port: %s (%VRc)\n", argv[curArg], rc);
725 if (portVRDP < 0 || portVRDP >= 0x10000)
726 return SyntaxError("vrdp port number is out of range: %RI32\n", portVRDP);
727 }
728 }
729#endif /* VBOX_WITH_VRDP */
730#ifdef VBOX_SECURELABEL
731 else if (strcmp(pszArg, "-securelabel") == 0)
732 {
733 fSecureLabel = true;
734 LogFlow(("Secure labelling turned on\n"));
735 }
736 else if (strcmp(pszArg, "-seclabelfnt") == 0)
737 {
738 if (++curArg >= argc)
739 return SyntaxError("missing font file name for secure label!\n");
740 secureLabelFontFile = argv[curArg];
741 }
742 else if (strcmp(pszArg, "-seclabelsiz") == 0)
743 {
744 if (++curArg >= argc)
745 return SyntaxError("missing font point size for secure label!\n");
746 secureLabelPointSize = atoi(argv[curArg]);
747 }
748#endif
749 else if (strcmp(pszArg, "-rellog") == 0)
750 g_fReleaseLog = true;
751 else if (strcmp(pszArg, "-norellog") == 0)
752 g_fReleaseLog = false;
753 else if (strcmp(pszArg, "-prealloc") == 0)
754 g_fPreAllocRam = true;
755#ifdef VBOXSDL_ADVANCED_OPTIONS
756 else if (strcmp(pszArg, "-rawr0") == 0)
757 g_fRawR0 = true;
758 else if (strcmp(pszArg, "-norawr0") == 0)
759 g_fRawR0 = false;
760 else if (strcmp(pszArg, "-rawr3") == 0)
761 g_fRawR3 = true;
762 else if (strcmp(pszArg, "-norawr3") == 0)
763 g_fRawR3 = false;
764 else if (strcmp(pszArg, "-patm") == 0)
765 g_fPATM = true;
766 else if (strcmp(pszArg, "-nopatm") == 0)
767 g_fPATM = false;
768 else if (strcmp(pszArg, "-csam") == 0)
769 g_fCSAM = true;
770 else if (strcmp(pszArg, "-nocsam") == 0)
771 g_fCSAM = false;
772#endif /* VBOXSDL_ADVANCED_OPTIONS */
773#ifdef RT_OS_L4
774 else if (strcmp(pszArg, "-env") == 0)
775 ++curArg;
776#endif /* RT_OS_L4 */
777 /* just show the help screen */
778 else
779 {
780 SyntaxError("unrecognized argument '%s'\n", pszArg);
781 show_usage();
782 return 1;
783 }
784 }
785
786 gMachineDebugger = new MachineDebugger();
787 gStatus = new VMStatus();
788 gKeyboard = new Keyboard();
789 gMouse = new Mouse();
790 gVMMDev = new VMMDev();
791 gDisplay = new VMDisplay();
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->RegisterExternalFramebuffer(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 (VBOX_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 (pVM)
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 PVMREQ pReq;
967 rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)VMR3PowerOff, 1, pVM);
968 }
969
970 /* And destroy it */
971 rc = VMR3Destroy(pVM);
972 AssertRC(rc);
973 }
974
975 delete gFramebuffer;
976 delete gConsole;
977 delete gDisplay;
978 delete gKeyboard;
979 delete gMouse;
980 delete gStatus;
981 delete gMachineDebugger;
982
983 RTLogFlush(NULL);
984 return VBOX_FAILURE (rc) ? 1 : 0;
985}
986
987
988#ifndef VBOX_WITH_HARDENING
989/**
990 * Main entry point.
991 */
992int main(int argc, char **argv)
993{
994# ifdef RT_OS_L4
995# ifndef L4API_l4v2onv4
996 /* clear Fiasco kernel trace buffer */
997 fiasco_tbuf_clear();
998# endif
999 /* set the environment. Must be done before the runtime is
1000 initialised. Yes, it really must. */
1001 for (int i = 0; i < argc; i++)
1002 if (strcmp(argv[i], "-env") == 0)
1003 {
1004 if (++i >= argc)
1005 return SyntaxError("missing argument to -env (format: var=value)!\n");
1006 /* add it to the environment */
1007 if (putenv(argv[i]) != 0)
1008 return SyntaxError("Error setting environment string %s.\n", argv[i]);
1009 }
1010# endif /* RT_OS_L4 */
1011
1012 /*
1013 * Before we do *anything*, we initialize the runtime.
1014 */
1015 int rc = RTR3Init();
1016 if (VBOX_FAILURE(rc))
1017 return FatalError("RTR3Init failed rc=%Vrc\n", rc);
1018
1019 return TrustedMain(argc, argv, NULL);
1020}
1021#endif /* !VBOX_WITH_HARDENING */
1022
1023
1024/**
1025 * VM state callback function. Called by the VMM
1026 * using its state machine states.
1027 *
1028 * Primarily used to handle VM initiated power off, suspend and state saving,
1029 * but also for doing termination completed work (VMSTATE_TERMINATE).
1030 *
1031 * In general this function is called in the context of the EMT.
1032 *
1033 * @todo machineState is set to VMSTATE_RUNNING before all devices have received power on events
1034 * this can prematurely allow the main thread to enter the event loop
1035 *
1036 * @param pVM The VM handle.
1037 * @param enmState The new state.
1038 * @param enmOldState The old state.
1039 * @param pvUser The user argument.
1040 */
1041static DECLCALLBACK(void) vmstateChangeCallback(PVM pVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser)
1042{
1043 LogFlow(("vmstateChangeCallback: changing state from %d to %d\n", enmOldState, enmState));
1044 machineState = enmState;
1045
1046 switch (enmState)
1047 {
1048 /*
1049 * The VM has terminated
1050 */
1051 case VMSTATE_OFF:
1052 {
1053 gConsole->eventQuit();
1054 break;
1055 }
1056
1057 /*
1058 * The VM has been completely destroyed.
1059 *
1060 * Note: This state change can happen at two points:
1061 * 1) At the end of VMR3Destroy() if it was not called from EMT.
1062 * 2) At the end of vmR3EmulationThread if VMR3Destroy() was called by EMT.
1063 */
1064 case VMSTATE_TERMINATED:
1065 {
1066 break;
1067 }
1068
1069 default: /* shut up gcc */
1070 break;
1071 }
1072}
1073
1074
1075/**
1076 * VM error callback function. Called by the various VM components.
1077 *
1078 * @param pVM The VM handle.
1079 * @param pvUser The user argument.
1080 * @param rc VBox status code.
1081 * @param pszError Error message format string.
1082 * @param args Error message arguments.
1083 * @thread EMT.
1084 */
1085DECLCALLBACK(void) setVMErrorCallback(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL,
1086 const char *pszFormat, va_list args)
1087{
1088 /** @todo accessing shared resource without any kind of synchronization */
1089 if (VBOX_SUCCESS(rc))
1090 szError[0] = '\0';
1091 else
1092 {
1093 va_list va2;
1094 va_copy(va2, args); /* Have to make a copy here or GCC will break. */
1095 RTStrPrintf(szError, sizeof(szError),
1096 "%N!\nVBox status code: %d (%Vrc)", pszFormat, &va2, rc, rc);
1097 RTPrintf("%s\n", szError);
1098 va_end(va2);
1099 }
1100}
1101
1102
1103/**
1104 * VM Runtime error callback function. Called by the various VM components.
1105 *
1106 * @param pVM The VM handle.
1107 * @param pvUser The user argument.
1108 * @param fFata Wheather it is a fatal error or not.
1109 * @param pszErrorId Error ID string.
1110 * @param pszError Error message format string.
1111 * @param args Error message arguments.
1112 * @thread EMT.
1113 */
1114DECLCALLBACK(void) setVMRuntimeErrorCallback(PVM pVM, void *pvUser, bool fFatal,
1115 const char *pszErrorId,
1116 const char *pszFormat, va_list args)
1117{
1118 va_list va2;
1119 va_copy(va2, args); /* Have to make a copy here or GCC will break. */
1120 RTPrintf("%s: %s!\n%N!\n", fFatal ? "Error" : "Warning", pszErrorId, pszFormat, &va2);
1121 va_end(va2);
1122}
1123
1124
1125/** VM asynchronous operations thread */
1126DECLCALLBACK(int) VMPowerUpThread(RTTHREAD Thread, void *pvUser)
1127{
1128 int rc = VINF_SUCCESS;
1129 int rc2;
1130
1131 /*
1132 * Setup the release log instance in current directory.
1133 */
1134 if (g_fReleaseLog)
1135 {
1136 static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES;
1137 static char szError[RTPATH_MAX + 128] = "";
1138 PRTLOGGER pLogger;
1139 rc2 = RTLogCreateEx(&pLogger, RTLOGFLAGS_PREFIX_TIME_PROG, "all",
1140 "VBOX_RELEASE_LOG", ELEMENTS(s_apszGroups), s_apszGroups,
1141 RTLOGDEST_FILE, szError, sizeof(szError), "./VBoxBFE.log");
1142 if (VBOX_SUCCESS(rc2))
1143 {
1144 /* some introductory information */
1145 RTTIMESPEC TimeSpec;
1146 char szNowUct[64];
1147 RTTimeSpecToString(RTTimeNow(&TimeSpec), szNowUct, sizeof(szNowUct));
1148 RTLogRelLogger(pLogger, 0, ~0U,
1149 "VBoxBFE %s (%s %s) release log\n"
1150 "Log opened %s\n",
1151 VBOX_VERSION_STRING, __DATE__, __TIME__,
1152 szNowUct);
1153
1154 /* register this logger as the release logger */
1155 RTLogRelSetDefaultInstance(pLogger);
1156 }
1157 else
1158 RTPrintf("Could not open release log (%s)\n", szError);
1159 }
1160
1161 /*
1162 * Start VM (also from saved state) and track progress
1163 */
1164 LogFlow(("VMPowerUp\n"));
1165
1166 /*
1167 * Create empty VM.
1168 */
1169 rc = VMR3Create(setVMErrorCallback, NULL, vboxbfeConfigConstructor, NULL, &pVM);
1170 if (VBOX_FAILURE(rc))
1171 {
1172 RTPrintf("Error: VM creation failed with %Vrc.\n", rc);
1173 goto failure;
1174 }
1175
1176
1177 /*
1178 * Register VM state change handler
1179 */
1180 rc = VMR3AtStateRegister(pVM, vmstateChangeCallback, NULL);
1181 if (VBOX_FAILURE(rc))
1182 {
1183 RTPrintf("Error: VMR3AtStateRegister failed with %Vrc.\n", rc);
1184 goto failure;
1185 }
1186
1187#ifdef VBOX_WITH_HGCM
1188 /*
1189 * Add shared folders to the VM
1190 */
1191 if (fActivateHGCM() && gVMMDev->isShFlActive())
1192 {
1193 for (unsigned i=0; i<g_uNumShares; i++)
1194 {
1195 VBOXHGCMSVCPARM parms[SHFL_CPARMS_ADD_MAPPING];
1196 SHFLSTRING *pFolderName, *pMapName;
1197 int cbString;
1198 PRTUTF16 aHostPath, aMapName;
1199 int rc;
1200
1201 rc = RTStrToUtf16(g_pszShareDir[i], &aHostPath);
1202 AssertRC(rc);
1203 rc = RTStrToUtf16(g_pszShareName[i], &aMapName);
1204 AssertRC(rc);
1205
1206 cbString = (RTUtf16Len (aHostPath) + 1) * sizeof (RTUTF16);
1207 pFolderName = (SHFLSTRING *) RTMemAllocZ (sizeof (SHFLSTRING) + cbString);
1208 Assert (pFolderName);
1209 memcpy (pFolderName->String.ucs2, aHostPath, cbString);
1210
1211 pFolderName->u16Size = cbString;
1212 pFolderName->u16Length = cbString - sizeof(RTUTF16);
1213
1214 parms[0].type = VBOX_HGCM_SVC_PARM_PTR;
1215 parms[0].u.pointer.addr = pFolderName;
1216 parms[0].u.pointer.size = sizeof (SHFLSTRING) + cbString;
1217
1218 cbString = (RTUtf16Len (aMapName) + 1) * sizeof (RTUTF16);
1219 pMapName = (SHFLSTRING *) RTMemAllocZ (sizeof(SHFLSTRING) + cbString);
1220 Assert (pMapName);
1221 memcpy (pMapName->String.ucs2, aMapName, cbString);
1222
1223 pMapName->u16Size = cbString;
1224 pMapName->u16Length = cbString - sizeof (RTUTF16);
1225
1226 parms[1].type = VBOX_HGCM_SVC_PARM_PTR;
1227 parms[1].u.pointer.addr = pMapName;
1228 parms[1].u.pointer.size = sizeof (SHFLSTRING) + cbString;
1229
1230 parms[2].type = VBOX_HGCM_SVC_PARM_32BIT;
1231 parms[2].u.uint32 = !g_fShareReadOnly[i];
1232
1233 rc = gVMMDev->hgcmHostCall ("VBoxSharedFolders",
1234 SHFL_FN_ADD_MAPPING, SHFL_CPARMS_ADD_MAPPING, &parms[0]);
1235 AssertRC(rc);
1236 LogRel(("Added share %s: (%s)\n", g_pszShareName[i], g_pszShareDir[i]));
1237 RTMemFree (pFolderName);
1238 RTMemFree (pMapName);
1239 RTUtf16Free (aHostPath);
1240 RTUtf16Free (aMapName);
1241 }
1242 }
1243#endif
1244
1245#ifdef VBOXBFE_WITH_USB
1246 /*
1247 * Capture USB devices.
1248 */
1249 if (g_fUSB)
1250 {
1251 gHostUSB = new HostUSB();
1252 gHostUSB->init(pVM);
1253 }
1254#endif /* VBOXBFE_WITH_USB */
1255
1256#ifdef RT_OS_L4
1257 /* L4 console cannot draw a host cursor */
1258 gMouse->setHostCursor(false);
1259#else
1260 gMouse->setHostCursor(true);
1261#endif
1262
1263 /*
1264 * Power on the VM (i.e. start executing).
1265 */
1266 if (VBOX_SUCCESS(rc))
1267 {
1268 PVMREQ pReq;
1269
1270 if ( g_fRestoreState
1271 && g_pszStateFile
1272 && *g_pszStateFile
1273 && RTPathExists(g_pszStateFile))
1274 {
1275 startProgressInfo("Restoring");
1276 rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT,
1277 (PFNRT)VMR3Load, 4, pVM, g_pszStateFile, &callProgressInfo, NULL);
1278 endProgressInfo();
1279 if (VBOX_SUCCESS(rc))
1280 {
1281 VMR3ReqFree(pReq);
1282 rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT,
1283 (PFNRT)VMR3Resume, 1, pVM);
1284 if (VBOX_SUCCESS(rc))
1285 {
1286 rc = pReq->iStatus;
1287 VMR3ReqFree(pReq);
1288 }
1289 gDisplay->setRunning();
1290 }
1291 else
1292 AssertMsgFailed(("VMR3Load failed, rc=%Vrc\n", rc));
1293 }
1294 else
1295 {
1296 rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)VMR3PowerOn, 1, pVM);
1297 if (VBOX_SUCCESS(rc))
1298 {
1299 rc = pReq->iStatus;
1300 AssertRC(rc);
1301 VMR3ReqFree(pReq);
1302 }
1303 else
1304 AssertMsgFailed(("VMR3PowerOn failed, rc=%Vrc\n", rc));
1305 }
1306 }
1307
1308 /*
1309 * On failure destroy the VM.
1310 */
1311 if (VBOX_FAILURE(rc))
1312 goto failure;
1313
1314 return 0;
1315
1316failure:
1317 if (pVM)
1318 {
1319 rc2 = VMR3Destroy(pVM);
1320 AssertRC(rc2);
1321 pVM = NULL;
1322 }
1323 machineState = VMSTATE_TERMINATED;
1324
1325 return 0;
1326}
1327
1328/**
1329 * Register the main drivers.
1330 *
1331 * @returns VBox status code.
1332 * @param pCallbacks Pointer to the callback table.
1333 * @param u32Version VBox version number.
1334 */
1335DECLCALLBACK(int) VBoxDriversRegister(PCPDMDRVREGCB pCallbacks, uint32_t u32Version)
1336{
1337 int rc;
1338
1339 LogFlow(("VBoxDriversRegister: u32Version=%#x\n", u32Version));
1340 AssertReleaseMsg(u32Version == VBOX_VERSION, ("u32Version=%#x VBOX_VERSION=%#x\n", u32Version, VBOX_VERSION));
1341
1342 rc = pCallbacks->pfnRegister(pCallbacks, &Mouse::DrvReg);
1343 AssertRC(rc);
1344 if (VBOX_FAILURE(rc))
1345 return rc;
1346 rc = pCallbacks->pfnRegister(pCallbacks, &Keyboard::DrvReg);
1347 AssertRC(rc);
1348 if (VBOX_FAILURE(rc))
1349 return rc;
1350
1351 rc = pCallbacks->pfnRegister(pCallbacks, &VMDisplay::DrvReg);
1352 AssertRC(rc);
1353 if (VBOX_FAILURE(rc))
1354 return rc;
1355 rc = pCallbacks->pfnRegister(pCallbacks, &VMMDev::DrvReg);
1356 AssertRC(rc);
1357 if (VBOX_FAILURE(rc))
1358 return rc;
1359
1360 rc = pCallbacks->pfnRegister(pCallbacks, &VMStatus::DrvReg);
1361 if (VBOX_FAILURE(rc))
1362 return rc;
1363
1364 return VINF_SUCCESS;
1365}
1366
1367
1368/**
1369 * Constructs the VMM configuration tree.
1370 *
1371 * @returns VBox status code.
1372 * @param pVM VM handle.
1373 */
1374static DECLCALLBACK(int) vboxbfeConfigConstructor(PVM pVM, void *pvUser)
1375{
1376 int rcAll = VINF_SUCCESS;
1377 int rc;
1378
1379#define UPDATE_RC() do { if (VBOX_FAILURE(rc) && VBOX_SUCCESS(rcAll)) rcAll = rc; } while (0)
1380
1381 /*
1382 * Root values.
1383 */
1384 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
1385 rc = CFGMR3InsertString(pRoot, "Name", "Default VM"); UPDATE_RC();
1386 rc = CFGMR3InsertInteger(pRoot, "RamSize", g_u32MemorySizeMB * _1M); UPDATE_RC();
1387 if (g_fPreAllocRam)
1388 {
1389 rc = CFGMR3InsertInteger(pRoot, "RamPreAlloc", 1); UPDATE_RC();
1390 }
1391 rc = CFGMR3InsertInteger(pRoot, "TimerMillies", 10); UPDATE_RC();
1392#ifdef VBOXSDL_ADVANCED_OPTIONS
1393 rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled", g_fRawR3); UPDATE_RC();
1394 rc = CFGMR3InsertInteger(pRoot, "RawR0Enabled", g_fRawR0); UPDATE_RC();
1395 rc = CFGMR3InsertInteger(pRoot, "PATMEnabled", g_fPATM); UPDATE_RC();
1396 rc = CFGMR3InsertInteger(pRoot, "CSAMEnabled", g_fCSAM); UPDATE_RC();
1397#else
1398 rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled", 1); UPDATE_RC();
1399 rc = CFGMR3InsertInteger(pRoot, "RawR0Enabled", 1); UPDATE_RC();
1400 rc = CFGMR3InsertInteger(pRoot, "PATMEnabled", 1); UPDATE_RC();
1401 rc = CFGMR3InsertInteger(pRoot, "CSAMEnabled", 1); UPDATE_RC();
1402#endif
1403
1404 /*
1405 * PDM.
1406 */
1407 rc = PDMR3RegisterDrivers(pVM, VBoxDriversRegister); UPDATE_RC();
1408
1409 /*
1410 * Devices
1411 */
1412 PCFGMNODE pDevices = NULL;
1413 rc = CFGMR3InsertNode(pRoot, "Devices", &pDevices); UPDATE_RC();
1414 /* device */
1415 PCFGMNODE pDev = NULL;
1416 PCFGMNODE pInst = NULL;
1417 PCFGMNODE pCfg = NULL;
1418 PCFGMNODE pLunL0 = NULL;
1419 PCFGMNODE pLunL1 = NULL;
1420 PCFGMNODE pDrv = NULL;
1421
1422 /*
1423 * PC Arch.
1424 */
1425 rc = CFGMR3InsertNode(pDevices, "pcarch", &pDev); UPDATE_RC();
1426 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1427 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1428 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1429
1430 /*
1431 * PC Bios.
1432 */
1433 rc = CFGMR3InsertNode(pDevices, "pcbios", &pDev); UPDATE_RC();
1434 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1435 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1436 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1437 rc = CFGMR3InsertInteger(pCfg, "RamSize", g_u32MemorySizeMB * _1M); UPDATE_RC();
1438 rc = CFGMR3InsertString(pCfg, "BootDevice0", g_pszBootDevice); UPDATE_RC();
1439 rc = CFGMR3InsertString(pCfg, "BootDevice1", "NONE"); UPDATE_RC();
1440 rc = CFGMR3InsertString(pCfg, "BootDevice2", "NONE"); UPDATE_RC();
1441 rc = CFGMR3InsertString(pCfg, "BootDevice3", "NONE"); UPDATE_RC();
1442 rc = CFGMR3InsertString(pCfg, "HardDiskDevice", "piix3ide"); UPDATE_RC();
1443 rc = CFGMR3InsertString(pCfg, "FloppyDevice", "i82078"); UPDATE_RC();
1444 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", g_fIOAPIC); UPDATE_RC();
1445 RTUUID Uuid;
1446 RTUuidClear(&Uuid);
1447 rc = CFGMR3InsertBytes(pCfg, "UUID", &Uuid, sizeof(Uuid)); UPDATE_RC();
1448
1449 /*
1450 * ACPI
1451 */
1452 if (g_fACPI)
1453 {
1454 rc = CFGMR3InsertNode(pDevices, "acpi", &pDev); UPDATE_RC();
1455 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1456 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1457 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1458 rc = CFGMR3InsertInteger(pCfg, "RamSize", g_u32MemorySizeMB * _1M); UPDATE_RC();
1459 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", g_fIOAPIC); UPDATE_RC();
1460 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 7); UPDATE_RC();
1461 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATE_RC();
1462
1463 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1464 rc = CFGMR3InsertString(pLunL0, "Driver", "ACPIHost"); UPDATE_RC();
1465 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1466 }
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 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", g_fIOAPIC); UPDATE_RC();
1476
1477 /*
1478 * DMA
1479 */
1480 rc = CFGMR3InsertNode(pDevices, "8237A", &pDev); UPDATE_RC();
1481 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1482 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1483
1484 /*
1485 * PCI bus.
1486 */
1487 rc = CFGMR3InsertNode(pDevices, "pci", &pDev); /* piix3 */ UPDATE_RC();
1488 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1489 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1490 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1491
1492 /*
1493 * PS/2 keyboard & mouse.
1494 */
1495 rc = CFGMR3InsertNode(pDevices, "pckbd", &pDev); UPDATE_RC();
1496 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1497 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1498 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1499
1500 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1501 rc = CFGMR3InsertString(pLunL0, "Driver", "KeyboardQueue"); UPDATE_RC();
1502 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1503 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 64); UPDATE_RC();
1504
1505 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pDrv); UPDATE_RC();
1506 rc = CFGMR3InsertString(pDrv, "Driver", "MainKeyboard"); UPDATE_RC();
1507 rc = CFGMR3InsertNode(pDrv, "Config", &pCfg); UPDATE_RC();
1508 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)gKeyboard); UPDATE_RC();
1509
1510 rc = CFGMR3InsertNode(pInst, "LUN#1", &pLunL0); UPDATE_RC();
1511 rc = CFGMR3InsertString(pLunL0, "Driver", "MouseQueue"); UPDATE_RC();
1512 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1513 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 128); UPDATE_RC();
1514
1515 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pDrv); UPDATE_RC();
1516 rc = CFGMR3InsertString(pDrv, "Driver", "MainMouse"); UPDATE_RC();
1517 rc = CFGMR3InsertNode(pDrv, "Config", &pCfg); UPDATE_RC();
1518 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)gMouse); UPDATE_RC();
1519
1520
1521 /*
1522 * i82078 Floppy drive controller
1523 */
1524 rc = CFGMR3InsertNode(pDevices, "i82078", &pDev); UPDATE_RC();
1525 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1526 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); UPDATE_RC();
1527 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1528 rc = CFGMR3InsertInteger(pCfg, "IRQ", 6); UPDATE_RC();
1529 rc = CFGMR3InsertInteger(pCfg, "DMA", 2); UPDATE_RC();
1530 rc = CFGMR3InsertInteger(pCfg, "MemMapped", 0 ); UPDATE_RC();
1531 rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x3f0); UPDATE_RC();
1532
1533 /* Attach the status driver */
1534 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); UPDATE_RC();
1535 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); UPDATE_RC();
1536 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1537 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&mapFDLeds[0]); UPDATE_RC();
1538 rc = CFGMR3InsertInteger(pCfg, "First", 0); UPDATE_RC();
1539 rc = CFGMR3InsertInteger(pCfg, "Last", 0); UPDATE_RC();
1540
1541 if (g_pszFdaFile)
1542 {
1543 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1544 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); UPDATE_RC();
1545 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1546 rc = CFGMR3InsertString(pCfg, "Type", "Floppy 1.44"); UPDATE_RC();
1547 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); UPDATE_RC();
1548
1549 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pDrv); UPDATE_RC();
1550 rc = CFGMR3InsertString(pDrv, "Driver", "RawImage"); UPDATE_RC();
1551 rc = CFGMR3InsertNode(pDrv, "Config", &pCfg); UPDATE_RC();
1552 rc = CFGMR3InsertString(pCfg, "Path", g_pszFdaFile); UPDATE_RC();
1553 }
1554
1555 /*
1556 * i8254 Programmable Interval Timer And Dummy Speaker
1557 */
1558 rc = CFGMR3InsertNode(pDevices, "i8254", &pDev); UPDATE_RC();
1559 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1560 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1561#ifdef DEBUG
1562 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1563#endif
1564
1565 /*
1566 * i8259 Programmable Interrupt Controller.
1567 */
1568 rc = CFGMR3InsertNode(pDevices, "i8259", &pDev); UPDATE_RC();
1569 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1570 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1571 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1572
1573 /*
1574 * Advanced Programmable Interrupt Controller.
1575 */
1576 rc = CFGMR3InsertNode(pDevices, "apic", &pDev); UPDATE_RC();
1577 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1578 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1579 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1580 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", g_fIOAPIC); UPDATE_RC();
1581
1582 /*
1583 * I/O Advanced Programmable Interrupt Controller.
1584 */
1585 if (g_fIOAPIC)
1586 {
1587 rc = CFGMR3InsertNode(pDevices, "ioapic", &pDev); UPDATE_RC();
1588 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1589 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1590 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1591 }
1592
1593 /*
1594 * RTC MC146818.
1595 */
1596 rc = CFGMR3InsertNode(pDevices, "mc146818", &pDev); UPDATE_RC();
1597 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1598 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1599
1600 /*
1601 * Serial ports
1602 */
1603 rc = CFGMR3InsertNode(pDevices, "serial", &pDev); UPDATE_RC();
1604 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1605 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1606 rc = CFGMR3InsertInteger(pCfg, "IRQ", 4); UPDATE_RC();
1607 rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x3f8); UPDATE_RC();
1608
1609 rc = CFGMR3InsertNode(pDev, "1", &pInst); UPDATE_RC();
1610 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1611 rc = CFGMR3InsertInteger(pCfg, "IRQ", 3); UPDATE_RC();
1612 rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x2f8); UPDATE_RC();
1613
1614 /*
1615 * VGA.
1616 */
1617 rc = CFGMR3InsertNode(pDevices, "vga", &pDev); UPDATE_RC();
1618 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1619 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1620 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 2); UPDATE_RC();
1621 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATE_RC();
1622 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1623 rc = CFGMR3InsertInteger(pCfg, "VRamSize", g_u32VRamSize); UPDATE_RC();
1624
1625 /* Default: no bios logo. */
1626 rc = CFGMR3InsertInteger(pCfg, "FadeIn", 1); UPDATE_RC();
1627 rc = CFGMR3InsertInteger(pCfg, "FadeOut", 0); UPDATE_RC();
1628 rc = CFGMR3InsertInteger(pCfg, "LogoTime", 0); UPDATE_RC();
1629 rc = CFGMR3InsertString(pCfg, "LogoFile", ""); UPDATE_RC();
1630
1631 /* Boot menu */
1632 rc = CFGMR3InsertInteger(pCfg, "ShowBootMenu", g_iBootMenu); UPDATE_RC();
1633
1634#ifdef RT_OS_L4
1635 /* XXX hard-coded */
1636 rc = CFGMR3InsertInteger(pCfg, "HeightReduction", 18); UPDATE_RC();
1637 rc = CFGMR3InsertInteger(pCfg, "CustomVideoModes", 1); UPDATE_RC();
1638 char szBuf[64];
1639 /* Tell the guest which is the ideal video mode to use */
1640 RTStrPrintf(szBuf, sizeof(szBuf), "%dx%dx%d",
1641 gFramebuffer->getHostXres(),
1642 gFramebuffer->getHostYres(),
1643 gFramebuffer->getHostBitsPerPixel());
1644 rc = CFGMR3InsertString(pCfg, "CustomVideoMode1", szBuf); UPDATE_RC();
1645#endif
1646
1647 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1648 rc = CFGMR3InsertString(pLunL0, "Driver", "MainDisplay"); UPDATE_RC();
1649 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1650 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)gDisplay); UPDATE_RC();
1651
1652 /*
1653 * IDE (update this when the main interface changes)
1654 */
1655 rc = CFGMR3InsertNode(pDevices, "piix3ide", &pDev); /* piix3 */ UPDATE_RC();
1656 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1657 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1658 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 1); UPDATE_RC();
1659 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 1); UPDATE_RC();
1660 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1661
1662 if (g_pszHdaFile)
1663 {
1664 const char *szDriver;
1665 if (0 == strcmp(RTPathExt(g_pszHdaFile), ".vdi"))
1666 szDriver = "VBoxHDD"; /* .vdi */
1667 else
1668 szDriver = "VD"; /* .vmdk */
1669
1670 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1671 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); UPDATE_RC();
1672 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1673 rc = CFGMR3InsertString(pCfg, "Type", "HardDisk"); UPDATE_RC();
1674 rc = CFGMR3InsertInteger(pCfg, "Mountable", 0); UPDATE_RC();
1675
1676 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pDrv); UPDATE_RC();
1677 rc = CFGMR3InsertString(pDrv, "Driver", szDriver); UPDATE_RC();
1678 rc = CFGMR3InsertNode(pDrv, "Config", &pCfg); UPDATE_RC();
1679 rc = CFGMR3InsertString(pCfg, "Path", g_pszHdaFile); UPDATE_RC();
1680
1681 if (g_fHdaSpf)
1682 {
1683 rc = CFGMR3InsertString(pCfg, "Format", "SPF"); UPDATE_RC();
1684 }
1685 }
1686
1687 if (g_pszHdbFile)
1688 {
1689 const char *szDriver;
1690 if (0 == strcmp(RTPathExt(g_pszHdbFile), ".vdi"))
1691 szDriver = "VBoxHDD"; /* .vdi */
1692 else
1693 szDriver = "VD"; /* .vmdk */
1694
1695 rc = CFGMR3InsertNode(pInst, "LUN#1", &pLunL1); UPDATE_RC();
1696 rc = CFGMR3InsertString(pLunL1, "Driver", "Block"); UPDATE_RC();
1697 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); UPDATE_RC();
1698 rc = CFGMR3InsertString(pCfg, "Type", "HardDisk"); UPDATE_RC();
1699 rc = CFGMR3InsertInteger(pCfg, "Mountable", 0); UPDATE_RC();
1700
1701 rc = CFGMR3InsertNode(pLunL1, "AttachedDriver", &pDrv); UPDATE_RC();
1702 rc = CFGMR3InsertString(pDrv, "Driver", szDriver); UPDATE_RC();
1703 rc = CFGMR3InsertNode(pDrv, "Config", &pCfg); UPDATE_RC();
1704 rc = CFGMR3InsertString(pCfg, "Path", g_pszHdbFile); UPDATE_RC();
1705
1706 if (g_fHdbSpf)
1707 {
1708 rc = CFGMR3InsertString(pCfg, "Format", "SPF"); UPDATE_RC();
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 (VBOX_FAILURE(rc))
1810 {
1811 FatalError("Failed to open /dev/net/tun: %Vrc\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 (%Vrc)\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 (%Vrc)\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", "MainVMMDev"); 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_L4)
1934 rc = CFGMR3InsertString(pCfg, "AudioDriver", "oss"); UPDATE_RC();
1935#else /* portme */
1936 rc = CFGMR3InsertString(pCfg, "AudioDriver", "none"); UPDATE_RC();
1937#endif /* !RT_OS_WINDOWS */
1938 }
1939
1940#ifdef VBOXBFE_WITH_USB
1941 /*
1942 * The USB Controller.
1943 */
1944 if (g_fUSB)
1945 {
1946 rc = CFGMR3InsertNode(pDevices, "usb-ohci", &pDev); UPDATE_RC();
1947 rc = CFGMR3InsertNode(pDev, "0", &pInst); UPDATE_RC();
1948 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); UPDATE_RC();
1949 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ UPDATE_RC();
1950 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 6); UPDATE_RC();
1951 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); UPDATE_RC();
1952
1953 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); UPDATE_RC();
1954 rc = CFGMR3InsertString(pLunL0, "Driver", "VUSBRootHub"); UPDATE_RC();
1955 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); UPDATE_RC();
1956 }
1957#endif /* VBOXBFE_WITH_USB */
1958
1959#undef UPDATE_RC
1960#undef UPDATE_RC
1961
1962 VMR3AtRuntimeErrorRegister (pVM, setVMRuntimeErrorCallback, NULL);
1963
1964 return rc;
1965}
1966
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