VirtualBox

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

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

FE/BFE: added '-prealloc' option to force RAM preallocation

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette