VirtualBox

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

Last change on this file since 7932 was 7759, checked in by vboxsync, 17 years ago

The BIOS logo stuff moved to VGA device. Added 24bpp bitmaps support.

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