VirtualBox

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

Last change on this file since 38876 was 38636, checked in by vboxsync, 13 years ago

*,IPRT: Redid the ring-3 init to always convert the arguments to UTF-8.

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