VirtualBox

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

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

Solaris/Audio: Boomer(OSS) support (disabled, requires snv_115+).

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