VirtualBox

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

Last change on this file since 2916 was 2916, checked in by vboxsync, 18 years ago

FE/BFE: at least show runtime errors on the text console

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