Changeset 30746 in vbox for trunk/src/VBox
- Timestamp:
- Jul 8, 2010 4:42:49 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 63518
- Location:
- trunk/src/VBox
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ApplianceImplExport.cpp
r29984 r30746 1617 1617 pcszManifestFileOnly, vrc); 1618 1618 } 1619 catch (xml::Error &x)1619 catch (iprt::Error &x) // includes all XML exceptions 1620 1620 { 1621 1621 rc = setError(VBOX_E_FILE_ERROR, 1622 1622 x.what()); 1623 1623 } 1624 catch (HRESULT aRC)1624 catch (HRESULT aRC) 1625 1625 { 1626 1626 rc = aRC; -
trunk/src/VBox/Main/ApplianceImplImport.cpp
r30739 r30746 684 684 RTStrFree(pszDigest); 685 685 } 686 catch (xml::Error &x)686 catch (iprt::Error &x) // includes all XML exceptions 687 687 { 688 688 rc = setError(VBOX_E_FILE_ERROR, 689 689 x.what()); 690 690 } 691 catch (HRESULT aRC)691 catch (HRESULT aRC) 692 692 { 693 693 rc = aRC; -
trunk/src/VBox/Main/ConsoleImpl2.cpp
r30742 r30746 49 49 #include <iprt/string.h> 50 50 #include <iprt/system.h> 51 #include <iprt/cpp/exception.h> 51 52 #if 0 /* enable to play with lots of memory. */ 52 53 # include <iprt/env.h> … … 309 310 } 310 311 312 class RT_DECL_CLASS ConfigError : public iprt::Error 313 { 314 public: 315 316 ConfigError(const char *pcszFunction, 317 int vrc, 318 const char *pcszName) 319 : iprt::Error(Utf8StrFmt("%s failed: rc=%Rrc, pcszName=%s", pcszFunction, vrc, pcszName)), 320 m_vrc(vrc) 321 { 322 AssertMsgFailed(("%s\n", what())); // in strict mode, hit a breakpoint here 323 } 324 325 int m_vrc; 326 }; 327 328 329 /** 330 * Helper that calls CFGMR3InsertString and throws an iprt::Error if that 331 * fails (C-string variant). 332 * @param pParent 333 * @param pcszNodeName 334 * @param strValue 335 */ 336 void InsertConfigString(PCFGMNODE pNode, 337 const char *pcszName, 338 const char *pcszValue) 339 { 340 int vrc = CFGMR3InsertString(pNode, 341 pcszName, 342 pcszValue); 343 if (RT_FAILURE(vrc)) 344 throw ConfigError("CFGMR3InsertString", vrc, pcszName); 345 } 346 347 /** 348 * Helper that calls CFGMR3InsertString and throws an iprt::Error if that 349 * fails (Utf8Str variant). 350 * @param pParent 351 * @param pcszNodeName 352 * @param strValue 353 */ 354 void InsertConfigString(PCFGMNODE pNode, 355 const char *pcszName, 356 const Utf8Str &strValue) 357 { 358 InsertConfigString(pNode, pcszName, strValue.c_str()); 359 } 360 361 /** 362 * Helper that calls CFGMR3InsertString and throws an iprt::Error if that 363 * fails (Bstr variant). 364 * @param pParent 365 * @param pcszNodeName 366 * @param strValue 367 */ 368 void InsertConfigString(PCFGMNODE pNode, 369 const char *pcszName, 370 const Bstr &bstrValue) 371 { 372 InsertConfigString(pNode, pcszName, Utf8Str(bstrValue).c_str()); 373 } 374 375 /** 376 * 377 * @param pNode 378 * @param pcszName 379 * @param pvBytes 380 * @param cbBytes 381 */ 382 void InsertConfigBytes(PCFGMNODE pNode, 383 const char *pcszName, 384 const void *pvBytes, 385 size_t cbBytes) 386 { 387 int vrc = CFGMR3InsertBytes(pNode, 388 pcszName, 389 pvBytes, 390 cbBytes); 391 if (RT_FAILURE(vrc)) 392 throw ConfigError("CFGMR3InsertBytes", vrc, pcszName); 393 } 394 395 /** 396 * 397 * @param pNode 398 * @param pcszName 399 * @param u64Integer 400 */ 401 void InsertConfigInteger(PCFGMNODE pNode, 402 const char *pcszName, 403 uint64_t u64Integer) 404 { 405 int vrc = CFGMR3InsertInteger(pNode, 406 pcszName, 407 u64Integer); 408 if (RT_FAILURE(vrc)) 409 throw ConfigError("CFGMR3InsertInteger", vrc, pcszName); 410 } 411 412 /** 413 * 414 * @param pNode 415 * @param pcszName 416 * @param ppChild 417 */ 418 void InsertConfigNode(PCFGMNODE pNode, 419 const char *pcszName, 420 PCFGMNODE *ppChild) 421 { 422 int vrc = CFGMR3InsertNode(pNode, pcszName, ppChild); 423 if (RT_FAILURE(vrc)) 424 throw ConfigError("CFGMR3InsertNode", vrc, pcszName); 425 } 426 427 /** 428 * 429 * @param pNode 430 * @param pcszName 431 */ 432 void RemoveConfigValue(PCFGMNODE pNode, 433 const char *pcszName) 434 { 435 int vrc = CFGMR3RemoveValue(pNode, pcszName); 436 if (RT_FAILURE(vrc)) 437 throw ConfigError("CFGMR3RemoveValue", vrc, pcszName); 438 } 439 311 440 /** 312 441 * Construct the VM configuration tree (CFGM). … … 359 488 Bstr bstr; 360 489 361 #define RC_CHECK() AssertMsgReturn(RT_SUCCESS(rc), ("rc=%Rrc\n", rc), rc)362 490 #define H() AssertMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_GENERAL_FAILURE) 363 491 … … 379 507 hrc = pMachine->COMGETTER(HardwareUUID)(bstr.asOutParam()); H(); 380 508 RTUUID HardwareUuid; 381 rc = RTUuidFromUtf16(&HardwareUuid, bstr.raw()); RC_CHECK(); 509 rc = RTUuidFromUtf16(&HardwareUuid, bstr.raw()); 510 AssertMsgReturn(RT_SUCCESS(rc), ("rc=%Rrc\n", rc), rc); 382 511 383 512 ULONG cRamMBs; … … 413 542 Assert(pRoot); 414 543 415 /* 416 * Set the root (and VMM) level values. 417 */ 418 hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H(); 419 rc = CFGMR3InsertStringW(pRoot, "Name", bstr.raw()); RC_CHECK(); 420 rc = CFGMR3InsertBytes(pRoot, "UUID", &HardwareUuid, sizeof(HardwareUuid)); RC_CHECK(); 421 rc = CFGMR3InsertInteger(pRoot, "RamSize", cbRam); RC_CHECK(); 422 rc = CFGMR3InsertInteger(pRoot, "RamHoleSize", cbRamHole); RC_CHECK(); 423 rc = CFGMR3InsertInteger(pRoot, "NumCPUs", cCpus); RC_CHECK(); 424 rc = CFGMR3InsertInteger(pRoot, "TimerMillies", 10); RC_CHECK(); 544 // InsertConfigString throws 545 try 546 { 547 548 /* 549 * Set the root (and VMM) level values. 550 */ 551 hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H(); 552 InsertConfigString(pRoot, "Name", bstr); 553 InsertConfigBytes(pRoot, "UUID", &HardwareUuid, sizeof(HardwareUuid)); 554 InsertConfigInteger(pRoot, "RamSize", cbRam); 555 InsertConfigInteger(pRoot, "RamHoleSize", cbRamHole); 556 InsertConfigInteger(pRoot, "NumCPUs", cCpus); 557 InsertConfigInteger(pRoot, "TimerMillies", 10); 425 558 #ifdef VBOX_WITH_RAW_MODE 426 rc = CFGMR3InsertInteger(pRoot, "RawR3Enabled", 1); /* boolean */ RC_CHECK();427 rc = CFGMR3InsertInteger(pRoot, "RawR0Enabled", 1); /* boolean */ RC_CHECK();428 /** @todo Config: RawR0, PATMEnabled and CSAMEnabled needs attention later. */429 rc = CFGMR3InsertInteger(pRoot, "PATMEnabled", 1); /* boolean */ RC_CHECK();430 rc = CFGMR3InsertInteger(pRoot, "CSAMEnabled", 1); /* boolean */ RC_CHECK();559 InsertConfigInteger(pRoot, "RawR3Enabled", 1); /* boolean */ 560 InsertConfigInteger(pRoot, "RawR0Enabled", 1); /* boolean */ 561 /** @todo Config: RawR0, PATMEnabled and CSAMEnabled needs attention later. */ 562 InsertConfigInteger(pRoot, "PATMEnabled", 1); /* boolean */ 563 InsertConfigInteger(pRoot, "CSAMEnabled", 1); /* boolean */ 431 564 #endif 432 /* Not necessary, but to make sure these two settings end up in the release log. */ 433 BOOL fPageFusion = FALSE; 434 hrc = pMachine->COMGETTER(PageFusionEnabled)(&fPageFusion); H(); 435 rc = CFGMR3InsertInteger(pRoot, "PageFusion", fPageFusion); /* boolean */ RC_CHECK(); 436 ULONG ulBalloonSize = 0; 437 hrc = pMachine->COMGETTER(MemoryBalloonSize)(&ulBalloonSize); H(); 438 rc = CFGMR3InsertInteger(pRoot, "MemBalloonSize", ulBalloonSize); RC_CHECK(); 439 440 /* 441 * CPUM values. 442 */ 443 PCFGMNODE pCPUM; 444 rc = CFGMR3InsertNode(pRoot, "CPUM", &pCPUM); RC_CHECK(); 445 446 /* cpuid leaf overrides. */ 447 static uint32_t const s_auCpuIdRanges[] = 448 { 449 UINT32_C(0x00000000), UINT32_C(0x0000000a), 450 UINT32_C(0x80000000), UINT32_C(0x8000000a) 451 }; 452 for (unsigned i = 0; i < RT_ELEMENTS(s_auCpuIdRanges); i += 2) 453 for (uint32_t uLeaf = s_auCpuIdRanges[i]; uLeaf < s_auCpuIdRanges[i + 1]; uLeaf++) 565 /* Not necessary, but to make sure these two settings end up in the release log. */ 566 BOOL fPageFusion = FALSE; 567 hrc = pMachine->COMGETTER(PageFusionEnabled)(&fPageFusion); H(); 568 InsertConfigInteger(pRoot, "PageFusion", fPageFusion); /* boolean */ 569 ULONG ulBalloonSize = 0; 570 hrc = pMachine->COMGETTER(MemoryBalloonSize)(&ulBalloonSize); H(); 571 InsertConfigInteger(pRoot, "MemBalloonSize", ulBalloonSize); 572 573 /* 574 * CPUM values. 575 */ 576 PCFGMNODE pCPUM; 577 InsertConfigNode(pRoot, "CPUM", &pCPUM); 578 579 /* cpuid leaf overrides. */ 580 static uint32_t const s_auCpuIdRanges[] = 454 581 { 455 ULONG ulEax, ulEbx, ulEcx, ulEdx; 456 hrc = pMachine->GetCPUIDLeaf(uLeaf, &ulEax, &ulEbx, &ulEcx, &ulEdx); 457 if (SUCCEEDED(hrc)) 458 { 459 PCFGMNODE pLeaf; 460 rc = CFGMR3InsertNodeF(pCPUM, &pLeaf, "HostCPUID/%RX32", uLeaf); RC_CHECK(); 461 462 rc = CFGMR3InsertInteger(pLeaf, "eax", ulEax); RC_CHECK(); 463 rc = CFGMR3InsertInteger(pLeaf, "ebx", ulEbx); RC_CHECK(); 464 rc = CFGMR3InsertInteger(pLeaf, "ecx", ulEcx); RC_CHECK(); 465 rc = CFGMR3InsertInteger(pLeaf, "edx", ulEdx); RC_CHECK(); 466 } 467 else if (hrc != E_INVALIDARG) H(); 582 UINT32_C(0x00000000), UINT32_C(0x0000000a), 583 UINT32_C(0x80000000), UINT32_C(0x8000000a) 584 }; 585 for (unsigned i = 0; i < RT_ELEMENTS(s_auCpuIdRanges); i += 2) 586 for (uint32_t uLeaf = s_auCpuIdRanges[i]; uLeaf < s_auCpuIdRanges[i + 1]; uLeaf++) 587 { 588 ULONG ulEax, ulEbx, ulEcx, ulEdx; 589 hrc = pMachine->GetCPUIDLeaf(uLeaf, &ulEax, &ulEbx, &ulEcx, &ulEdx); 590 if (SUCCEEDED(hrc)) 591 { 592 PCFGMNODE pLeaf; 593 InsertConfigNode(pCPUM, Utf8StrFmt("HostCPUID/%RX32", uLeaf).c_str(), &pLeaf); 594 595 InsertConfigInteger(pLeaf, "eax", ulEax); 596 InsertConfigInteger(pLeaf, "ebx", ulEbx); 597 InsertConfigInteger(pLeaf, "ecx", ulEcx); 598 InsertConfigInteger(pLeaf, "edx", ulEdx); 599 } 600 else if (hrc != E_INVALIDARG) H(); 601 } 602 603 /* We must limit CPUID count for Windows NT 4, as otherwise it stops 604 with error 0x3e (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED). */ 605 if (osTypeId == "WindowsNT4") 606 { 607 LogRel(("Limiting CPUID leaf count for NT4 guests\n")); 608 InsertConfigInteger(pCPUM, "NT4LeafLimit", true); 468 609 } 469 610 470 /* We must limit CPUID count for Windows NT 4, as otherwise it stops 471 with error 0x3e (MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED). */ 472 if (osTypeId == "WindowsNT4") 473 { 474 LogRel(("Limiting CPUID leaf count for NT4 guests\n")); 475 rc = CFGMR3InsertInteger(pCPUM, "NT4LeafLimit", true); RC_CHECK(); 476 } 477 478 /* Expose extended MWAIT features to Mac OS X guests. */ 479 if (fOsXGuest) 480 { 481 LogRel(("Using MWAIT extensions\n")); 482 rc = CFGMR3InsertInteger(pCPUM, "MWaitExtensions", true); RC_CHECK(); 483 } 484 485 /* 486 * Hardware virtualization extensions. 487 */ 488 BOOL fHWVirtExEnabled; 489 BOOL fHwVirtExtForced; 611 /* Expose extended MWAIT features to Mac OS X guests. */ 612 if (fOsXGuest) 613 { 614 LogRel(("Using MWAIT extensions\n")); 615 InsertConfigInteger(pCPUM, "MWaitExtensions", true); 616 } 617 618 /* 619 * Hardware virtualization extensions. 620 */ 621 BOOL fHWVirtExEnabled; 622 BOOL fHwVirtExtForced; 490 623 #ifdef VBOX_WITH_RAW_MODE 491 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Enabled, &fHWVirtExEnabled); H();492 if (cCpus > 1) /** @todo SMP: This isn't nice, but things won't work on mac otherwise. */493 fHWVirtExEnabled = TRUE;624 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Enabled, &fHWVirtExEnabled); H(); 625 if (cCpus > 1) /** @todo SMP: This isn't nice, but things won't work on mac otherwise. */ 626 fHWVirtExEnabled = TRUE; 494 627 # ifdef RT_OS_DARWIN 495 fHwVirtExtForced = fHWVirtExEnabled;628 fHwVirtExtForced = fHWVirtExEnabled; 496 629 # else 497 /* - With more than 4GB PGM will use different RAMRANGE sizes for raw498 mode and hv mode to optimize lookup times.499 - With more than one virtual CPU, raw-mode isn't a fallback option. */500 fHwVirtExtForced = fHWVirtExEnabled501 && ( cbRam > (_4G - cbRamHole)502 || cCpus > 1);630 /* - With more than 4GB PGM will use different RAMRANGE sizes for raw 631 mode and hv mode to optimize lookup times. 632 - With more than one virtual CPU, raw-mode isn't a fallback option. */ 633 fHwVirtExtForced = fHWVirtExEnabled 634 && ( cbRam > (_4G - cbRamHole) 635 || cCpus > 1); 503 636 # endif 504 637 #else /* !VBOX_WITH_RAW_MODE */ 505 fHWVirtExEnabled = fHwVirtExtForced = TRUE;638 fHWVirtExEnabled = fHwVirtExtForced = TRUE; 506 639 #endif /* !VBOX_WITH_RAW_MODE */ 507 rc = CFGMR3InsertInteger(pRoot, "HwVirtExtForced", fHwVirtExtForced); RC_CHECK(); 508 509 PCFGMNODE pHWVirtExt; 510 rc = CFGMR3InsertNode(pRoot, "HWVirtExt", &pHWVirtExt); RC_CHECK(); 511 if (fHWVirtExEnabled) 512 { 513 rc = CFGMR3InsertInteger(pHWVirtExt, "Enabled", 1); RC_CHECK(); 514 515 /* Indicate whether 64-bit guests are supported or not. */ 516 /** @todo This is currently only forced off on 32-bit hosts only because it 517 * makes a lof of difference there (REM and Solaris performance). 518 */ 519 BOOL fSupportsLongMode = false; 520 hrc = host->GetProcessorFeature(ProcessorFeature_LongMode, 521 &fSupportsLongMode); H(); 522 hrc = guestOSType->COMGETTER(Is64Bit)(&fIs64BitGuest); H(); 523 524 if (fSupportsLongMode && fIs64BitGuest) 640 InsertConfigInteger(pRoot, "HwVirtExtForced", fHwVirtExtForced); 641 642 PCFGMNODE pHWVirtExt; 643 InsertConfigNode(pRoot, "HWVirtExt", &pHWVirtExt); 644 if (fHWVirtExEnabled) 525 645 { 526 rc = CFGMR3InsertInteger(pHWVirtExt, "64bitEnabled", 1); RC_CHECK(); 646 InsertConfigInteger(pHWVirtExt, "Enabled", 1); 647 648 /* Indicate whether 64-bit guests are supported or not. */ 649 /** @todo This is currently only forced off on 32-bit hosts only because it 650 * makes a lof of difference there (REM and Solaris performance). 651 */ 652 BOOL fSupportsLongMode = false; 653 hrc = host->GetProcessorFeature(ProcessorFeature_LongMode, 654 &fSupportsLongMode); H(); 655 hrc = guestOSType->COMGETTER(Is64Bit)(&fIs64BitGuest); H(); 656 657 if (fSupportsLongMode && fIs64BitGuest) 658 { 659 InsertConfigInteger(pHWVirtExt, "64bitEnabled", 1); 527 660 #if ARCH_BITS == 32 /* The recompiler must use VBoxREM64 (32-bit host only). */ 528 PCFGMNODE pREM;529 rc = CFGMR3InsertNode(pRoot, "REM", &pREM); RC_CHECK();530 rc = CFGMR3InsertInteger(pREM, "64bitEnabled", 1); RC_CHECK();661 PCFGMNODE pREM; 662 InsertConfigNode(pRoot, "REM", &pREM); 663 InsertConfigInteger(pREM, "64bitEnabled", 1); 531 664 #endif 665 } 666 #if ARCH_BITS == 32 /* 32-bit guests only. */ 667 else 668 { 669 InsertConfigInteger(pHWVirtExt, "64bitEnabled", 0); 670 } 671 #endif 672 673 /** @todo Not exactly pretty to check strings; VBOXOSTYPE would be better, but that requires quite a bit of API change in Main. */ 674 if ( !fIs64BitGuest 675 && fIOAPIC 676 && ( osTypeId == "WindowsNT4" 677 || osTypeId == "Windows2000" 678 || osTypeId == "WindowsXP" 679 || osTypeId == "Windows2003")) 680 { 681 /* Only allow TPR patching for NT, Win2k, XP and Windows Server 2003. (32 bits mode) 682 * We may want to consider adding more guest OSes (Solaris) later on. 683 */ 684 InsertConfigInteger(pHWVirtExt, "TPRPatchingEnabled", 1); 685 } 532 686 } 533 #if ARCH_BITS == 32 /* 32-bit guests only. */ 687 688 /* HWVirtEx exclusive mode */ 689 BOOL fHWVirtExExclusive = true; 690 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Exclusive, &fHWVirtExExclusive); H(); 691 InsertConfigInteger(pHWVirtExt, "Exclusive", fHWVirtExExclusive); 692 693 /* Nested paging (VT-x/AMD-V) */ 694 BOOL fEnableNestedPaging = false; 695 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_NestedPaging, &fEnableNestedPaging); H(); 696 InsertConfigInteger(pHWVirtExt, "EnableNestedPaging", fEnableNestedPaging); 697 698 /* Large pages; requires nested paging */ 699 BOOL fEnableLargePages = false; 700 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_LargePages, &fEnableLargePages); H(); 701 InsertConfigInteger(pHWVirtExt, "EnableLargePages", fEnableLargePages); 702 703 /* VPID (VT-x) */ 704 BOOL fEnableVPID = false; 705 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_VPID, &fEnableVPID); H(); 706 InsertConfigInteger(pHWVirtExt, "EnableVPID", fEnableVPID); 707 708 /* Physical Address Extension (PAE) */ 709 BOOL fEnablePAE = false; 710 hrc = pMachine->GetCPUProperty(CPUPropertyType_PAE, &fEnablePAE); H(); 711 InsertConfigInteger(pRoot, "EnablePAE", fEnablePAE); 712 713 /* Synthetic CPU */ 714 BOOL fSyntheticCpu = false; 715 hrc = pMachine->GetCPUProperty(CPUPropertyType_Synthetic, &fSyntheticCpu); H(); 716 InsertConfigInteger(pRoot, "SyntheticCpu", fSyntheticCpu); 717 718 BOOL fPXEDebug; 719 hrc = biosSettings->COMGETTER(PXEDebugEnabled)(&fPXEDebug); H(); 720 721 /* 722 * PDM config. 723 * Load drivers in VBoxC.[so|dll] 724 */ 725 PCFGMNODE pPDM; 726 PCFGMNODE pDrivers; 727 PCFGMNODE pMod; 728 InsertConfigNode(pRoot, "PDM", &pPDM); 729 InsertConfigNode(pPDM, "Drivers", &pDrivers); 730 InsertConfigNode(pDrivers, "VBoxC", &pMod); 731 #ifdef VBOX_WITH_XPCOM 732 // VBoxC is located in the components subdirectory 733 char szPathVBoxC[RTPATH_MAX]; 734 rc = RTPathAppPrivateArch(szPathVBoxC, RTPATH_MAX - sizeof("/components/VBoxC")); AssertRC(rc); 735 strcat(szPathVBoxC, "/components/VBoxC"); 736 InsertConfigString(pMod, "Path", szPathVBoxC); 737 #else 738 InsertConfigString(pMod, "Path", "VBoxC"); 739 #endif 740 741 /* 742 * I/O settings (cach, max bandwidth, ...). 743 */ 744 PCFGMNODE pPDMAc; 745 PCFGMNODE pPDMAcFile; 746 InsertConfigNode(pPDM, "AsyncCompletion", &pPDMAc); 747 InsertConfigNode(pPDMAc, "File", &pPDMAcFile); 748 749 /* Builtin I/O cache */ 750 BOOL fIoCache = true; 751 hrc = pMachine->COMGETTER(IoCacheEnabled)(&fIoCache); H(); 752 InsertConfigInteger(pPDMAcFile, "CacheEnabled", fIoCache); 753 754 /* I/O cache size */ 755 ULONG ioCacheSize = 5; 756 hrc = pMachine->COMGETTER(IoCacheSize)(&ioCacheSize); H(); 757 InsertConfigInteger(pPDMAcFile, "CacheSize", ioCacheSize * _1M); 758 759 /* Maximum I/O bandwidth */ 760 ULONG ioBandwidthMax = 0; 761 hrc = pMachine->COMGETTER(IoBandwidthMax)(&ioBandwidthMax); H(); 762 if (ioBandwidthMax != 0) 763 { 764 InsertConfigInteger(pPDMAcFile, "VMTransferPerSecMax", ioBandwidthMax * _1M); 765 } 766 767 /* 768 * Devices 769 */ 770 PCFGMNODE pDevices = NULL; /* /Devices */ 771 PCFGMNODE pDev = NULL; /* /Devices/Dev/ */ 772 PCFGMNODE pInst = NULL; /* /Devices/Dev/0/ */ 773 PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */ 774 PCFGMNODE pLunL0 = NULL; /* /Devices/Dev/0/LUN#0/ */ 775 PCFGMNODE pLunL1 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/ */ 776 PCFGMNODE pLunL2 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/Config/ */ 777 PCFGMNODE pBiosCfg = NULL; /* /Devices/pcbios/0/Config/ */ 778 PCFGMNODE pNetBootCfg = NULL; /* /Devices/pcbios/0/Config/NetBoot/ */ 779 780 InsertConfigNode(pRoot, "Devices", &pDevices); 781 782 /* 783 * PC Arch. 784 */ 785 InsertConfigNode(pDevices, "pcarch", &pDev); 786 InsertConfigNode(pDev, "0", &pInst); 787 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 788 InsertConfigNode(pInst, "Config", &pCfg); 789 790 /* 791 * The time offset 792 */ 793 LONG64 timeOffset; 794 hrc = biosSettings->COMGETTER(TimeOffset)(&timeOffset); H(); 795 PCFGMNODE pTMNode; 796 InsertConfigNode(pRoot, "TM", &pTMNode); 797 InsertConfigInteger(pTMNode, "UTCOffset", timeOffset * 1000000); 798 799 /* 800 * DMA 801 */ 802 InsertConfigNode(pDevices, "8237A", &pDev); 803 InsertConfigNode(pDev, "0", &pInst); 804 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 805 806 /* 807 * PCI buses. 808 */ 809 InsertConfigNode(pDevices, "pci", &pDev); /* piix3 */ 810 InsertConfigNode(pDev, "0", &pInst); 811 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 812 InsertConfigNode(pInst, "Config", &pCfg); 813 InsertConfigInteger(pCfg, "IOAPIC", fIOAPIC); 814 815 #if 0 /* enable this to test PCI bridging */ 816 InsertConfigNode(pDevices, "pcibridge", &pDev); 817 InsertConfigNode(pDev, "0", &pInst); 818 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 819 InsertConfigNode(pInst, "Config", &pCfg); 820 InsertConfigInteger(pInst, "PCIDeviceNo", 14); 821 InsertConfigInteger(pInst, "PCIFunctionNo", 0); 822 rc = CFGMR3InsertInteger(pInst, "PCIBusNo", 0);/* -> pci[0] */ RC_CHECK(); 823 824 InsertConfigNode(pDev, "1", &pInst); 825 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 826 InsertConfigNode(pInst, "Config", &pCfg); 827 InsertConfigInteger(pInst, "PCIDeviceNo", 1); 828 InsertConfigInteger(pInst, "PCIFunctionNo", 0); 829 rc = CFGMR3InsertInteger(pInst, "PCIBusNo", 1);/* ->pcibridge[0] */ RC_CHECK(); 830 831 InsertConfigNode(pDev, "2", &pInst); 832 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 833 InsertConfigNode(pInst, "Config", &pCfg); 834 InsertConfigInteger(pInst, "PCIDeviceNo", 3); 835 InsertConfigInteger(pInst, "PCIFunctionNo", 0); 836 rc = CFGMR3InsertInteger(pInst, "PCIBusNo", 1);/* ->pcibridge[0] */ RC_CHECK(); 837 #endif 838 839 /* 840 * Enable 3 following devices: HPET, SMC, LPC on MacOS X guests 841 */ 842 /* 843 * High Precision Event Timer (HPET) 844 */ 845 BOOL fHpetEnabled; 846 #ifdef VBOX_WITH_HPET 847 /* Other guests may wish to use HPET too, but MacOS X not functional without it */ 848 hrc = pMachine->COMGETTER(HpetEnabled)(&fHpetEnabled); H(); 849 /* so always enable HPET in extended profile */ 850 fHpetEnabled |= fOsXGuest; 851 #else 852 fHpetEnabled = false; 853 #endif 854 if (fHpetEnabled) 855 { 856 InsertConfigNode(pDevices, "hpet", &pDev); 857 InsertConfigNode(pDev, "0", &pInst); 858 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 859 } 860 861 /* 862 * System Management Controller (SMC) 863 */ 864 BOOL fSmcEnabled; 865 #ifdef VBOX_WITH_SMC 866 fSmcEnabled = fOsXGuest; 867 #else 868 fSmcEnabled = false; 869 #endif 870 if (fSmcEnabled) 871 { 872 InsertConfigNode(pDevices, "smc", &pDev); 873 InsertConfigNode(pDev, "0", &pInst); 874 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 875 InsertConfigNode(pInst, "Config", &pCfg); 876 877 bool fGetKeyFromRealSMC; 878 Bstr bstrKey; 879 rc = getSmcDeviceKey(pMachine, bstrKey.asOutParam(), &fGetKeyFromRealSMC); 880 AssertMsgReturn(RT_SUCCESS(rc), ("rc=%Rrc\n", rc), rc); 881 882 InsertConfigString(pCfg, "DeviceKey", bstrKey); 883 InsertConfigInteger(pCfg, "GetKeyFromRealSMC", fGetKeyFromRealSMC); 884 } 885 886 /* 887 * Low Pin Count (LPC) bus 888 */ 889 BOOL fLpcEnabled; 890 /** @todo: implement appropriate getter */ 891 #ifdef VBOX_WITH_LPC 892 fLpcEnabled = fOsXGuest; 893 #else 894 fLpcEnabled = false; 895 #endif 896 if (fLpcEnabled) 897 { 898 InsertConfigNode(pDevices, "lpc", &pDev); 899 InsertConfigNode(pDev, "0", &pInst); 900 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 901 } 902 903 /* 904 * PS/2 keyboard & mouse. 905 */ 906 InsertConfigNode(pDevices, "pckbd", &pDev); 907 InsertConfigNode(pDev, "0", &pInst); 908 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 909 InsertConfigNode(pInst, "Config", &pCfg); 910 911 InsertConfigNode(pInst, "LUN#0", &pLunL0); 912 InsertConfigString(pLunL0, "Driver", "KeyboardQueue"); 913 InsertConfigNode(pLunL0, "Config", &pCfg); 914 InsertConfigInteger(pCfg, "QueueSize", 64); 915 916 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1); 917 InsertConfigString(pLunL1, "Driver", "MainKeyboard"); 918 InsertConfigNode(pLunL1, "Config", &pCfg); 919 Keyboard *pKeyboard = pConsole->mKeyboard; 920 InsertConfigInteger(pCfg, "Object", (uintptr_t)pKeyboard); 921 922 InsertConfigNode(pInst, "LUN#1", &pLunL0); 923 InsertConfigString(pLunL0, "Driver", "MouseQueue"); 924 InsertConfigNode(pLunL0, "Config", &pCfg); 925 InsertConfigInteger(pCfg, "QueueSize", 128); 926 927 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1); 928 InsertConfigString(pLunL1, "Driver", "MainMouse"); 929 InsertConfigNode(pLunL1, "Config", &pCfg); 930 Mouse *pMouse = pConsole->mMouse; 931 InsertConfigInteger(pCfg, "Object", (uintptr_t)pMouse); 932 933 /* 934 * i8254 Programmable Interval Timer And Dummy Speaker 935 */ 936 InsertConfigNode(pDevices, "i8254", &pDev); 937 InsertConfigNode(pDev, "0", &pInst); 938 InsertConfigNode(pInst, "Config", &pCfg); 939 #ifdef DEBUG 940 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 941 #endif 942 943 /* 944 * i8259 Programmable Interrupt Controller. 945 */ 946 InsertConfigNode(pDevices, "i8259", &pDev); 947 InsertConfigNode(pDev, "0", &pInst); 948 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 949 InsertConfigNode(pInst, "Config", &pCfg); 950 951 /* 952 * Advanced Programmable Interrupt Controller. 953 * SMP: Each CPU has a LAPIC, but we have a single device representing all LAPICs states, 954 * thus only single insert 955 */ 956 InsertConfigNode(pDevices, "apic", &pDev); 957 InsertConfigNode(pDev, "0", &pInst); 958 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 959 InsertConfigNode(pInst, "Config", &pCfg); 960 InsertConfigInteger(pCfg, "IOAPIC", fIOAPIC); 961 InsertConfigInteger(pCfg, "NumCPUs", cCpus); 962 963 if (fIOAPIC) 964 { 965 /* 966 * I/O Advanced Programmable Interrupt Controller. 967 */ 968 InsertConfigNode(pDevices, "ioapic", &pDev); 969 InsertConfigNode(pDev, "0", &pInst); 970 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 971 InsertConfigNode(pInst, "Config", &pCfg); 972 } 973 974 /* 975 * RTC MC146818. 976 */ 977 InsertConfigNode(pDevices, "mc146818", &pDev); 978 InsertConfigNode(pDev, "0", &pInst); 979 InsertConfigNode(pInst, "Config", &pCfg); 980 BOOL fRTCUseUTC; 981 hrc = pMachine->COMGETTER(RTCUseUTC)(&fRTCUseUTC); H(); 982 InsertConfigInteger(pCfg, "UseUTC", fRTCUseUTC ? 1 : 0); 983 984 /* 985 * VGA. 986 */ 987 InsertConfigNode(pDevices, "vga", &pDev); 988 InsertConfigNode(pDev, "0", &pInst); 989 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 990 InsertConfigInteger(pInst, "PCIDeviceNo", 2); 991 Assert(!afPciDeviceNo[2]); 992 afPciDeviceNo[2] = true; 993 InsertConfigInteger(pInst, "PCIFunctionNo", 0); 994 InsertConfigNode(pInst, "Config", &pCfg); 995 ULONG cVRamMBs; 996 hrc = pMachine->COMGETTER(VRAMSize)(&cVRamMBs); H(); 997 InsertConfigInteger(pCfg, "VRamSize", cVRamMBs * _1M); 998 ULONG cMonitorCount; 999 hrc = pMachine->COMGETTER(MonitorCount)(&cMonitorCount); H(); 1000 InsertConfigInteger(pCfg, "MonitorCount", cMonitorCount); 1001 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE 1002 InsertConfigInteger(pCfg, "R0Enabled", fHWVirtExEnabled); 1003 #endif 1004 1005 /* 1006 * BIOS logo 1007 */ 1008 BOOL fFadeIn; 1009 hrc = biosSettings->COMGETTER(LogoFadeIn)(&fFadeIn); H(); 1010 InsertConfigInteger(pCfg, "FadeIn", fFadeIn ? 1 : 0); 1011 BOOL fFadeOut; 1012 hrc = biosSettings->COMGETTER(LogoFadeOut)(&fFadeOut); H(); 1013 InsertConfigInteger(pCfg, "FadeOut", fFadeOut ? 1: 0); 1014 ULONG logoDisplayTime; 1015 hrc = biosSettings->COMGETTER(LogoDisplayTime)(&logoDisplayTime); H(); 1016 InsertConfigInteger(pCfg, "LogoTime", logoDisplayTime); 1017 Bstr logoImagePath; 1018 hrc = biosSettings->COMGETTER(LogoImagePath)(logoImagePath.asOutParam()); H(); 1019 InsertConfigString(pCfg, "LogoFile", Utf8Str(logoImagePath ? logoImagePath : "") ); 1020 1021 /* 1022 * Boot menu 1023 */ 1024 BIOSBootMenuMode_T eBootMenuMode; 1025 int iShowBootMenu; 1026 biosSettings->COMGETTER(BootMenuMode)(&eBootMenuMode); 1027 switch (eBootMenuMode) 1028 { 1029 case BIOSBootMenuMode_Disabled: iShowBootMenu = 0; break; 1030 case BIOSBootMenuMode_MenuOnly: iShowBootMenu = 1; break; 1031 default: iShowBootMenu = 2; break; 1032 } 1033 InsertConfigInteger(pCfg, "ShowBootMenu", iShowBootMenu); 1034 1035 /* Custom VESA mode list */ 1036 unsigned cModes = 0; 1037 for (unsigned iMode = 1; iMode <= 16; ++iMode) 1038 { 1039 char szExtraDataKey[sizeof("CustomVideoModeXX")]; 1040 RTStrPrintf(szExtraDataKey, sizeof(szExtraDataKey), "CustomVideoMode%u", iMode); 1041 hrc = pMachine->GetExtraData(Bstr(szExtraDataKey), bstr.asOutParam()); H(); 1042 if (bstr.isEmpty()) 1043 break; 1044 InsertConfigString(pCfg, szExtraDataKey, bstr); 1045 ++cModes; 1046 } 1047 InsertConfigInteger(pCfg, "CustomVideoModes", cModes); 1048 1049 /* VESA height reduction */ 1050 ULONG ulHeightReduction; 1051 IFramebuffer *pFramebuffer = pConsole->getDisplay()->getFramebuffer(); 1052 if (pFramebuffer) 1053 { 1054 hrc = pFramebuffer->COMGETTER(HeightReduction)(&ulHeightReduction); H(); 1055 } 534 1056 else 535 1057 { 536 rc = CFGMR3InsertInteger(pHWVirtExt, "64bitEnabled", 0); RC_CHECK(); 1058 /* If framebuffer is not available, there is no height reduction. */ 1059 ulHeightReduction = 0; 537 1060 } 1061 InsertConfigInteger(pCfg, "HeightReduction", ulHeightReduction); 1062 1063 /* Attach the display. */ 1064 InsertConfigNode(pInst, "LUN#0", &pLunL0); 1065 InsertConfigString(pLunL0, "Driver", "MainDisplay"); 1066 InsertConfigNode(pLunL0, "Config", &pCfg); 1067 Display *pDisplay = pConsole->mDisplay; 1068 InsertConfigInteger(pCfg, "Object", (uintptr_t)pDisplay); 1069 1070 1071 /* 1072 * Firmware. 1073 */ 1074 FirmwareType_T eFwType = FirmwareType_BIOS; 1075 hrc = pMachine->COMGETTER(FirmwareType)(&eFwType); H(); 1076 1077 #ifdef VBOX_WITH_EFI 1078 BOOL fEfiEnabled = (eFwType >= FirmwareType_EFI) && (eFwType <= FirmwareType_EFIDUAL); 1079 #else 1080 BOOL fEfiEnabled = false; 538 1081 #endif 539 540 /** @todo Not exactly pretty to check strings; VBOXOSTYPE would be better, but that requires quite a bit of API change in Main. */ 541 if ( !fIs64BitGuest 542 && fIOAPIC 543 && ( osTypeId == "WindowsNT4" 544 || osTypeId == "Windows2000" 545 || osTypeId == "WindowsXP" 546 || osTypeId == "Windows2003")) 1082 if (!fEfiEnabled) 547 1083 { 548 /* Only allow TPR patching for NT, Win2k, XP and Windows Server 2003. (32 bits mode)549 * We may want to consider adding more guest OSes (Solaris) later on.1084 /* 1085 * PC Bios. 550 1086 */ 551 rc = CFGMR3InsertInteger(pHWVirtExt, "TPRPatchingEnabled", 1); RC_CHECK(); 1087 InsertConfigNode(pDevices, "pcbios", &pDev); 1088 InsertConfigNode(pDev, "0", &pInst); 1089 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 1090 InsertConfigNode(pInst, "Config", &pBiosCfg); 1091 InsertConfigInteger(pBiosCfg, "RamSize", cbRam); 1092 InsertConfigInteger(pBiosCfg, "RamHoleSize", cbRamHole); 1093 InsertConfigInteger(pBiosCfg, "NumCPUs", cCpus); 1094 InsertConfigString(pBiosCfg, "HardDiskDevice", "piix3ide"); 1095 InsertConfigString(pBiosCfg, "FloppyDevice", "i82078"); 1096 InsertConfigInteger(pBiosCfg, "IOAPIC", fIOAPIC); 1097 InsertConfigInteger(pBiosCfg, "PXEDebug", fPXEDebug); 1098 InsertConfigBytes(pBiosCfg, "UUID", &HardwareUuid,sizeof(HardwareUuid)); 1099 InsertConfigNode(pBiosCfg, "NetBoot", &pNetBootCfg); 1100 1101 DeviceType_T bootDevice; 1102 if (SchemaDefs::MaxBootPosition > 9) 1103 { 1104 AssertMsgFailed(("Too many boot devices %d\n", 1105 SchemaDefs::MaxBootPosition)); 1106 return VERR_INVALID_PARAMETER; 1107 } 1108 1109 for (ULONG pos = 1; pos <= SchemaDefs::MaxBootPosition; ++pos) 1110 { 1111 hrc = pMachine->GetBootOrder(pos, &bootDevice); H(); 1112 1113 char szParamName[] = "BootDeviceX"; 1114 szParamName[sizeof(szParamName) - 2] = ((char (pos - 1)) + '0'); 1115 1116 const char *pszBootDevice; 1117 switch (bootDevice) 1118 { 1119 case DeviceType_Null: 1120 pszBootDevice = "NONE"; 1121 break; 1122 case DeviceType_HardDisk: 1123 pszBootDevice = "IDE"; 1124 break; 1125 case DeviceType_DVD: 1126 pszBootDevice = "DVD"; 1127 break; 1128 case DeviceType_Floppy: 1129 pszBootDevice = "FLOPPY"; 1130 break; 1131 case DeviceType_Network: 1132 pszBootDevice = "LAN"; 1133 break; 1134 default: 1135 AssertMsgFailed(("Invalid bootDevice=%d\n", bootDevice)); 1136 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS, 1137 N_("Invalid boot device '%d'"), bootDevice); 1138 } 1139 InsertConfigString(pBiosCfg, szParamName, pszBootDevice); 1140 } 552 1141 } 553 } 554 555 /* HWVirtEx exclusive mode */ 556 BOOL fHWVirtExExclusive = true; 557 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_Exclusive, &fHWVirtExExclusive); H(); 558 rc = CFGMR3InsertInteger(pHWVirtExt, "Exclusive", fHWVirtExExclusive); RC_CHECK(); 559 560 /* Nested paging (VT-x/AMD-V) */ 561 BOOL fEnableNestedPaging = false; 562 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_NestedPaging, &fEnableNestedPaging); H(); 563 rc = CFGMR3InsertInteger(pHWVirtExt, "EnableNestedPaging", fEnableNestedPaging); RC_CHECK(); 564 565 /* Large pages; requires nested paging */ 566 BOOL fEnableLargePages = false; 567 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_LargePages, &fEnableLargePages); H(); 568 rc = CFGMR3InsertInteger(pHWVirtExt, "EnableLargePages", fEnableLargePages); RC_CHECK(); 569 570 /* VPID (VT-x) */ 571 BOOL fEnableVPID = false; 572 hrc = pMachine->GetHWVirtExProperty(HWVirtExPropertyType_VPID, &fEnableVPID); H(); 573 rc = CFGMR3InsertInteger(pHWVirtExt, "EnableVPID", fEnableVPID); RC_CHECK(); 574 575 /* Physical Address Extension (PAE) */ 576 BOOL fEnablePAE = false; 577 hrc = pMachine->GetCPUProperty(CPUPropertyType_PAE, &fEnablePAE); H(); 578 rc = CFGMR3InsertInteger(pRoot, "EnablePAE", fEnablePAE); RC_CHECK(); 579 580 /* Synthetic CPU */ 581 BOOL fSyntheticCpu = false; 582 hrc = pMachine->GetCPUProperty(CPUPropertyType_Synthetic, &fSyntheticCpu); H(); 583 rc = CFGMR3InsertInteger(pRoot, "SyntheticCpu", fSyntheticCpu); RC_CHECK(); 584 585 BOOL fPXEDebug; 586 hrc = biosSettings->COMGETTER(PXEDebugEnabled)(&fPXEDebug); H(); 587 588 /* 589 * PDM config. 590 * Load drivers in VBoxC.[so|dll] 591 */ 592 PCFGMNODE pPDM; 593 PCFGMNODE pDrivers; 594 PCFGMNODE pMod; 595 rc = CFGMR3InsertNode(pRoot, "PDM", &pPDM); RC_CHECK(); 596 rc = CFGMR3InsertNode(pPDM, "Drivers", &pDrivers); RC_CHECK(); 597 rc = CFGMR3InsertNode(pDrivers, "VBoxC", &pMod); RC_CHECK(); 598 #ifdef VBOX_WITH_XPCOM 599 // VBoxC is located in the components subdirectory 600 char szPathVBoxC[RTPATH_MAX]; 601 rc = RTPathAppPrivateArch(szPathVBoxC, RTPATH_MAX - sizeof("/components/VBoxC")); AssertRC(rc); 602 strcat(szPathVBoxC, "/components/VBoxC"); 603 rc = CFGMR3InsertString(pMod, "Path", szPathVBoxC); RC_CHECK(); 604 #else 605 rc = CFGMR3InsertString(pMod, "Path", "VBoxC"); RC_CHECK(); 606 #endif 607 608 /* 609 * I/O settings (cach, max bandwidth, ...). 610 */ 611 PCFGMNODE pPDMAc; 612 PCFGMNODE pPDMAcFile; 613 rc = CFGMR3InsertNode(pPDM, "AsyncCompletion", &pPDMAc); RC_CHECK(); 614 rc = CFGMR3InsertNode(pPDMAc, "File", &pPDMAcFile); RC_CHECK(); 615 616 /* Builtin I/O cache */ 617 BOOL fIoCache = true; 618 hrc = pMachine->COMGETTER(IoCacheEnabled)(&fIoCache); H(); 619 rc = CFGMR3InsertInteger(pPDMAcFile, "CacheEnabled", fIoCache); RC_CHECK(); 620 621 /* I/O cache size */ 622 ULONG ioCacheSize = 5; 623 hrc = pMachine->COMGETTER(IoCacheSize)(&ioCacheSize); H(); 624 rc = CFGMR3InsertInteger(pPDMAcFile, "CacheSize", ioCacheSize * _1M); RC_CHECK(); 625 626 /* Maximum I/O bandwidth */ 627 ULONG ioBandwidthMax = 0; 628 hrc = pMachine->COMGETTER(IoBandwidthMax)(&ioBandwidthMax); H(); 629 if (ioBandwidthMax != 0) 630 { 631 rc = CFGMR3InsertInteger(pPDMAcFile, "VMTransferPerSecMax", ioBandwidthMax * _1M); RC_CHECK(); 632 } 633 634 /* 635 * Devices 636 */ 637 PCFGMNODE pDevices = NULL; /* /Devices */ 638 PCFGMNODE pDev = NULL; /* /Devices/Dev/ */ 639 PCFGMNODE pInst = NULL; /* /Devices/Dev/0/ */ 640 PCFGMNODE pCfg = NULL; /* /Devices/Dev/.../Config/ */ 641 PCFGMNODE pLunL0 = NULL; /* /Devices/Dev/0/LUN#0/ */ 642 PCFGMNODE pLunL1 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/ */ 643 PCFGMNODE pLunL2 = NULL; /* /Devices/Dev/0/LUN#0/AttachedDriver/Config/ */ 644 PCFGMNODE pBiosCfg = NULL; /* /Devices/pcbios/0/Config/ */ 645 PCFGMNODE pNetBootCfg = NULL; /* /Devices/pcbios/0/Config/NetBoot/ */ 646 647 rc = CFGMR3InsertNode(pRoot, "Devices", &pDevices); RC_CHECK(); 648 649 /* 650 * PC Arch. 651 */ 652 rc = CFGMR3InsertNode(pDevices, "pcarch", &pDev); RC_CHECK(); 653 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 654 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 655 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 656 657 /* 658 * The time offset 659 */ 660 LONG64 timeOffset; 661 hrc = biosSettings->COMGETTER(TimeOffset)(&timeOffset); H(); 662 PCFGMNODE pTMNode; 663 rc = CFGMR3InsertNode(pRoot, "TM", &pTMNode); RC_CHECK(); 664 rc = CFGMR3InsertInteger(pTMNode, "UTCOffset", timeOffset * 1000000); RC_CHECK(); 665 666 /* 667 * DMA 668 */ 669 rc = CFGMR3InsertNode(pDevices, "8237A", &pDev); RC_CHECK(); 670 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 671 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 672 673 /* 674 * PCI buses. 675 */ 676 rc = CFGMR3InsertNode(pDevices, "pci", &pDev); /* piix3 */ RC_CHECK(); 677 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 678 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 679 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 680 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK(); 681 682 #if 0 /* enable this to test PCI bridging */ 683 rc = CFGMR3InsertNode(pDevices, "pcibridge", &pDev); RC_CHECK(); 684 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 685 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 686 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 687 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 14); RC_CHECK(); 688 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK(); 689 rc = CFGMR3InsertInteger(pInst, "PCIBusNo", 0);/* -> pci[0] */ RC_CHECK(); 690 691 rc = CFGMR3InsertNode(pDev, "1", &pInst); RC_CHECK(); 692 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 693 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 694 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 1); RC_CHECK(); 695 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK(); 696 rc = CFGMR3InsertInteger(pInst, "PCIBusNo", 1);/* ->pcibridge[0] */ RC_CHECK(); 697 698 rc = CFGMR3InsertNode(pDev, "2", &pInst); RC_CHECK(); 699 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 700 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 701 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 3); RC_CHECK(); 702 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK(); 703 rc = CFGMR3InsertInteger(pInst, "PCIBusNo", 1);/* ->pcibridge[0] */ RC_CHECK(); 704 #endif 705 706 /* 707 * Enable 3 following devices: HPET, SMC, LPC on MacOS X guests 708 */ 709 /* 710 * High Precision Event Timer (HPET) 711 */ 712 BOOL fHpetEnabled; 713 #ifdef VBOX_WITH_HPET 714 /* Other guests may wish to use HPET too, but MacOS X not functional without it */ 715 hrc = pMachine->COMGETTER(HpetEnabled)(&fHpetEnabled); H(); 716 /* so always enable HPET in extended profile */ 717 fHpetEnabled |= fOsXGuest; 718 #else 719 fHpetEnabled = false; 720 #endif 721 if (fHpetEnabled) 722 { 723 rc = CFGMR3InsertNode(pDevices, "hpet", &pDev); RC_CHECK(); 724 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 725 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 726 } 727 728 /* 729 * System Management Controller (SMC) 730 */ 731 BOOL fSmcEnabled; 732 #ifdef VBOX_WITH_SMC 733 fSmcEnabled = fOsXGuest; 734 #else 735 fSmcEnabled = false; 736 #endif 737 if (fSmcEnabled) 738 { 739 rc = CFGMR3InsertNode(pDevices, "smc", &pDev); RC_CHECK(); 740 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 741 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 742 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 743 bool fGetKeyFromRealSMC; 744 Bstr bstrKey; 745 rc = getSmcDeviceKey(pMachine, bstrKey.asOutParam(), &fGetKeyFromRealSMC); RC_CHECK(); 746 rc = CFGMR3InsertString(pCfg, "DeviceKey", Utf8Str(bstrKey).raw()); RC_CHECK(); 747 rc = CFGMR3InsertInteger(pCfg, "GetKeyFromRealSMC", fGetKeyFromRealSMC); RC_CHECK(); 748 } 749 750 /* 751 * Low Pin Count (LPC) bus 752 */ 753 BOOL fLpcEnabled; 754 /** @todo: implement appropriate getter */ 755 #ifdef VBOX_WITH_LPC 756 fLpcEnabled = fOsXGuest; 757 #else 758 fLpcEnabled = false; 759 #endif 760 if (fLpcEnabled) 761 { 762 rc = CFGMR3InsertNode(pDevices, "lpc", &pDev); RC_CHECK(); 763 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 764 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 765 } 766 767 /* 768 * PS/2 keyboard & mouse. 769 */ 770 rc = CFGMR3InsertNode(pDevices, "pckbd", &pDev); RC_CHECK(); 771 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 772 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 773 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 774 775 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 776 rc = CFGMR3InsertString(pLunL0, "Driver", "KeyboardQueue"); RC_CHECK(); 777 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 778 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 64); RC_CHECK(); 779 780 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK(); 781 rc = CFGMR3InsertString(pLunL1, "Driver", "MainKeyboard"); RC_CHECK(); 782 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK(); 783 Keyboard *pKeyboard = pConsole->mKeyboard; 784 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pKeyboard); RC_CHECK(); 785 786 rc = CFGMR3InsertNode(pInst, "LUN#1", &pLunL0); RC_CHECK(); 787 rc = CFGMR3InsertString(pLunL0, "Driver", "MouseQueue"); RC_CHECK(); 788 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 789 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 128); RC_CHECK(); 790 791 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK(); 792 rc = CFGMR3InsertString(pLunL1, "Driver", "MainMouse"); RC_CHECK(); 793 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK(); 794 Mouse *pMouse = pConsole->mMouse; 795 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pMouse); RC_CHECK(); 796 797 /* 798 * i8254 Programmable Interval Timer And Dummy Speaker 799 */ 800 rc = CFGMR3InsertNode(pDevices, "i8254", &pDev); RC_CHECK(); 801 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 802 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 803 #ifdef DEBUG 804 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 805 #endif 806 807 /* 808 * i8259 Programmable Interrupt Controller. 809 */ 810 rc = CFGMR3InsertNode(pDevices, "i8259", &pDev); RC_CHECK(); 811 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 812 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 813 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 814 815 /* 816 * Advanced Programmable Interrupt Controller. 817 * SMP: Each CPU has a LAPIC, but we have a single device representing all LAPICs states, 818 * thus only single insert 819 */ 820 rc = CFGMR3InsertNode(pDevices, "apic", &pDev); RC_CHECK(); 821 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 822 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 823 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 824 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK(); 825 rc = CFGMR3InsertInteger(pCfg, "NumCPUs", cCpus); RC_CHECK(); 826 827 if (fIOAPIC) 828 { 829 /* 830 * I/O Advanced Programmable Interrupt Controller. 831 */ 832 rc = CFGMR3InsertNode(pDevices, "ioapic", &pDev); RC_CHECK(); 833 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 834 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 835 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 836 } 837 838 /* 839 * RTC MC146818. 840 */ 841 rc = CFGMR3InsertNode(pDevices, "mc146818", &pDev); RC_CHECK(); 842 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 843 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 844 BOOL fRTCUseUTC; 845 hrc = pMachine->COMGETTER(RTCUseUTC)(&fRTCUseUTC); H(); 846 rc = CFGMR3InsertInteger(pCfg, "UseUTC", fRTCUseUTC ? 1 : 0); RC_CHECK(); 847 848 /* 849 * VGA. 850 */ 851 rc = CFGMR3InsertNode(pDevices, "vga", &pDev); RC_CHECK(); 852 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 853 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 854 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 2); RC_CHECK(); 855 Assert(!afPciDeviceNo[2]); 856 afPciDeviceNo[2] = true; 857 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK(); 858 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 859 ULONG cVRamMBs; 860 hrc = pMachine->COMGETTER(VRAMSize)(&cVRamMBs); H(); 861 rc = CFGMR3InsertInteger(pCfg, "VRamSize", cVRamMBs * _1M); RC_CHECK(); 862 ULONG cMonitorCount; 863 hrc = pMachine->COMGETTER(MonitorCount)(&cMonitorCount); H(); 864 rc = CFGMR3InsertInteger(pCfg, "MonitorCount", cMonitorCount); RC_CHECK(); 865 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE 866 rc = CFGMR3InsertInteger(pCfg, "R0Enabled", fHWVirtExEnabled); RC_CHECK(); 867 #endif 868 869 /* 870 * BIOS logo 871 */ 872 BOOL fFadeIn; 873 hrc = biosSettings->COMGETTER(LogoFadeIn)(&fFadeIn); H(); 874 rc = CFGMR3InsertInteger(pCfg, "FadeIn", fFadeIn ? 1 : 0); RC_CHECK(); 875 BOOL fFadeOut; 876 hrc = biosSettings->COMGETTER(LogoFadeOut)(&fFadeOut); H(); 877 rc = CFGMR3InsertInteger(pCfg, "FadeOut", fFadeOut ? 1: 0); RC_CHECK(); 878 ULONG logoDisplayTime; 879 hrc = biosSettings->COMGETTER(LogoDisplayTime)(&logoDisplayTime); H(); 880 rc = CFGMR3InsertInteger(pCfg, "LogoTime", logoDisplayTime); RC_CHECK(); 881 Bstr logoImagePath; 882 hrc = biosSettings->COMGETTER(LogoImagePath)(logoImagePath.asOutParam()); H(); 883 rc = CFGMR3InsertString(pCfg, "LogoFile", logoImagePath ? Utf8Str(logoImagePath).c_str() : ""); RC_CHECK(); 884 885 /* 886 * Boot menu 887 */ 888 BIOSBootMenuMode_T eBootMenuMode; 889 int iShowBootMenu; 890 biosSettings->COMGETTER(BootMenuMode)(&eBootMenuMode); 891 switch (eBootMenuMode) 892 { 893 case BIOSBootMenuMode_Disabled: iShowBootMenu = 0; break; 894 case BIOSBootMenuMode_MenuOnly: iShowBootMenu = 1; break; 895 default: iShowBootMenu = 2; break; 896 } 897 rc = CFGMR3InsertInteger(pCfg, "ShowBootMenu", iShowBootMenu); RC_CHECK(); 898 899 /* Custom VESA mode list */ 900 unsigned cModes = 0; 901 for (unsigned iMode = 1; iMode <= 16; ++iMode) 902 { 903 char szExtraDataKey[sizeof("CustomVideoModeXX")]; 904 RTStrPrintf(szExtraDataKey, sizeof(szExtraDataKey), "CustomVideoMode%u", iMode); 905 hrc = pMachine->GetExtraData(Bstr(szExtraDataKey), bstr.asOutParam()); H(); 906 if (bstr.isEmpty()) 907 break; 908 rc = CFGMR3InsertStringW(pCfg, szExtraDataKey, bstr.raw()); RC_CHECK(); 909 ++cModes; 910 } 911 rc = CFGMR3InsertInteger(pCfg, "CustomVideoModes", cModes); RC_CHECK(); 912 913 /* VESA height reduction */ 914 ULONG ulHeightReduction; 915 IFramebuffer *pFramebuffer = pConsole->getDisplay()->getFramebuffer(); 916 if (pFramebuffer) 917 { 918 hrc = pFramebuffer->COMGETTER(HeightReduction)(&ulHeightReduction); H(); 919 } 920 else 921 { 922 /* If framebuffer is not available, there is no height reduction. */ 923 ulHeightReduction = 0; 924 } 925 rc = CFGMR3InsertInteger(pCfg, "HeightReduction", ulHeightReduction); RC_CHECK(); 926 927 /* Attach the display. */ 928 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 929 rc = CFGMR3InsertString(pLunL0, "Driver", "MainDisplay"); RC_CHECK(); 930 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 931 Display *pDisplay = pConsole->mDisplay; 932 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pDisplay); RC_CHECK(); 933 934 935 /* 936 * Firmware. 937 */ 938 FirmwareType_T eFwType = FirmwareType_BIOS; 939 hrc = pMachine->COMGETTER(FirmwareType)(&eFwType); H(); 940 941 #ifdef VBOX_WITH_EFI 942 BOOL fEfiEnabled = (eFwType >= FirmwareType_EFI) && (eFwType <= FirmwareType_EFIDUAL); 943 #else 944 BOOL fEfiEnabled = false; 945 #endif 946 if (!fEfiEnabled) 947 { 948 /* 949 * PC Bios. 950 */ 951 rc = CFGMR3InsertNode(pDevices, "pcbios", &pDev); RC_CHECK(); 952 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 953 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 954 rc = CFGMR3InsertNode(pInst, "Config", &pBiosCfg); RC_CHECK(); 955 rc = CFGMR3InsertInteger(pBiosCfg, "RamSize", cbRam); RC_CHECK(); 956 rc = CFGMR3InsertInteger(pBiosCfg, "RamHoleSize", cbRamHole); RC_CHECK(); 957 rc = CFGMR3InsertInteger(pBiosCfg, "NumCPUs", cCpus); RC_CHECK(); 958 rc = CFGMR3InsertString(pBiosCfg, "HardDiskDevice", "piix3ide"); RC_CHECK(); 959 rc = CFGMR3InsertString(pBiosCfg, "FloppyDevice", "i82078"); RC_CHECK(); 960 rc = CFGMR3InsertInteger(pBiosCfg, "IOAPIC", fIOAPIC); RC_CHECK(); 961 rc = CFGMR3InsertInteger(pBiosCfg, "PXEDebug", fPXEDebug); RC_CHECK(); 962 rc = CFGMR3InsertBytes(pBiosCfg, "UUID", &HardwareUuid,sizeof(HardwareUuid));RC_CHECK(); 963 rc = CFGMR3InsertNode(pBiosCfg, "NetBoot", &pNetBootCfg); RC_CHECK(); 964 965 DeviceType_T bootDevice; 966 if (SchemaDefs::MaxBootPosition > 9) 1142 else 967 1143 { 968 AssertMsgFailed(("Too many boot devices %d\n", 969 SchemaDefs::MaxBootPosition)); 970 return VERR_INVALID_PARAMETER; 1144 Utf8Str efiRomFile; 1145 1146 /* Autodetect firmware type, basing on guest type */ 1147 if (eFwType == FirmwareType_EFI) 1148 { 1149 eFwType = 1150 fIs64BitGuest ? 1151 (FirmwareType_T)FirmwareType_EFI64 1152 : 1153 (FirmwareType_T)FirmwareType_EFI32; 1154 } 1155 bool f64BitEntry = eFwType == FirmwareType_EFI64; 1156 1157 rc = findEfiRom(virtualBox, eFwType, efiRomFile); 1158 AssertMsgReturn(RT_SUCCESS(rc), ("rc=%Rrc\n", rc), rc); 1159 1160 /* Get boot args */ 1161 Bstr bootArgs; 1162 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EfiBootArgs"), bootArgs.asOutParam()); H(); 1163 1164 /* Get device props */ 1165 Bstr deviceProps; 1166 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EfiDeviceProps"), deviceProps.asOutParam()); H(); 1167 /* Get GOP mode settings */ 1168 uint32_t u32GopMode = UINT32_MAX; 1169 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EfiGopMode"), bstr.asOutParam()); H(); 1170 if (!bstr.isEmpty()) 1171 u32GopMode = Utf8Str(bstr).toUInt32(); 1172 1173 /* UGA mode settings */ 1174 uint32_t u32UgaHorisontal = 0; 1175 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EfiUgaHorizontalResolution"), bstr.asOutParam()); H(); 1176 if (!bstr.isEmpty()) 1177 u32UgaHorisontal = Utf8Str(bstr).toUInt32(); 1178 1179 uint32_t u32UgaVertical = 0; 1180 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EfiUgaVerticalResolution"), bstr.asOutParam()); H(); 1181 if (!bstr.isEmpty()) 1182 u32UgaVertical = Utf8Str(bstr).toUInt32(); 1183 1184 /* 1185 * EFI subtree. 1186 */ 1187 InsertConfigNode(pDevices, "efi", &pDev); 1188 InsertConfigNode(pDev, "0", &pInst); 1189 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 1190 InsertConfigNode(pInst, "Config", &pCfg); 1191 InsertConfigInteger(pCfg, "RamSize", cbRam); 1192 InsertConfigInteger(pCfg, "RamHoleSize", cbRamHole); 1193 InsertConfigInteger(pCfg, "NumCPUs", cCpus); 1194 InsertConfigString(pCfg, "EfiRom", efiRomFile.raw()); 1195 InsertConfigString(pCfg, "BootArgs", Utf8Str(bootArgs).raw()); 1196 InsertConfigString(pCfg, "DeviceProps", Utf8Str(deviceProps).raw()); 1197 InsertConfigInteger(pCfg, "IOAPIC", fIOAPIC); 1198 InsertConfigBytes(pCfg, "UUID", &HardwareUuid,sizeof(HardwareUuid)); 1199 InsertConfigInteger(pCfg, "64BitEntry", f64BitEntry); /* boolean */ 1200 InsertConfigInteger(pCfg, "GopMode", u32GopMode); 1201 InsertConfigInteger(pCfg, "UgaHorizontalResolution", u32UgaHorisontal); 1202 InsertConfigInteger(pCfg, "UgaVerticalResolution", u32UgaVertical); 1203 1204 /* For OS X guests we'll force passing host's DMI info to the guest */ 1205 if (fOsXGuest) 1206 { 1207 InsertConfigInteger(pCfg, "DmiUseHostInfo", 1); 1208 InsertConfigInteger(pCfg, "DmiExposeMemoryTable", 1); 1209 } 971 1210 } 972 1211 973 for (ULONG pos = 1; pos <= SchemaDefs::MaxBootPosition; ++pos) 1212 /* 1213 * Storage controllers. 1214 */ 1215 com::SafeIfaceArray<IStorageController> ctrls; 1216 PCFGMNODE aCtrlNodes[StorageControllerType_LsiLogicSas + 1] = {}; 1217 hrc = pMachine->COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(ctrls)); H(); 1218 1219 for (size_t i = 0; i < ctrls.size(); ++i) 974 1220 { 975 hrc = pMachine->GetBootOrder(pos, &bootDevice); H(); 976 977 char szParamName[] = "BootDeviceX"; 978 szParamName[sizeof(szParamName) - 2] = ((char (pos - 1)) + '0'); 979 980 const char *pszBootDevice; 981 switch (bootDevice) 982 { 983 case DeviceType_Null: 984 pszBootDevice = "NONE"; 1221 DeviceType_T *paLedDevType = NULL; 1222 1223 StorageControllerType_T enmCtrlType; 1224 rc = ctrls[i]->COMGETTER(ControllerType)(&enmCtrlType); H(); 1225 AssertRelease((unsigned)enmCtrlType < RT_ELEMENTS(aCtrlNodes)); 1226 1227 StorageBus_T enmBus; 1228 rc = ctrls[i]->COMGETTER(Bus)(&enmBus); H(); 1229 1230 Bstr controllerName; 1231 rc = ctrls[i]->COMGETTER(Name)(controllerName.asOutParam()); H(); 1232 1233 ULONG ulInstance = 999; 1234 rc = ctrls[i]->COMGETTER(Instance)(&ulInstance); H(); 1235 1236 BOOL fUseHostIOCache; 1237 rc = ctrls[i]->COMGETTER(UseHostIOCache)(&fUseHostIOCache); H(); 1238 1239 /* /Devices/<ctrldev>/ */ 1240 const char *pszCtrlDev = pConsole->convertControllerTypeToDev(enmCtrlType); 1241 pDev = aCtrlNodes[enmCtrlType]; 1242 if (!pDev) 1243 { 1244 InsertConfigNode(pDevices, pszCtrlDev, &pDev); 1245 aCtrlNodes[enmCtrlType] = pDev; /* IDE variants are handled in the switch */ 1246 } 1247 1248 /* /Devices/<ctrldev>/<instance>/ */ 1249 PCFGMNODE pCtlInst = NULL; 1250 InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pCtlInst); 1251 1252 /* Device config: /Devices/<ctrldev>/<instance>/<values> & /ditto/Config/<values> */ 1253 InsertConfigInteger(pCtlInst, "Trusted", 1); 1254 InsertConfigNode(pCtlInst, "Config", &pCfg); 1255 1256 switch (enmCtrlType) 1257 { 1258 case StorageControllerType_LsiLogic: 1259 { 1260 InsertConfigInteger(pCtlInst, "PCIDeviceNo", 20); 1261 Assert(!afPciDeviceNo[20]); 1262 afPciDeviceNo[20] = true; 1263 InsertConfigInteger(pCtlInst, "PCIFunctionNo", 0); 1264 1265 /* Attach the status driver */ 1266 InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); 1267 InsertConfigString(pLunL0, "Driver", "MainStatus"); 1268 InsertConfigNode(pLunL0, "Config", &pCfg); 1269 InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapStorageLeds[iLedScsi]); 1270 InsertConfigInteger(pCfg, "First", 0); 1271 Assert(cLedScsi >= 16); 1272 InsertConfigInteger(pCfg, "Last", 15); 1273 paLedDevType = &pConsole->maStorageDevType[iLedScsi]; 985 1274 break; 986 case DeviceType_HardDisk: 987 pszBootDevice = "IDE"; 1275 } 1276 1277 case StorageControllerType_BusLogic: 1278 { 1279 InsertConfigInteger(pCtlInst, "PCIDeviceNo", 21); 1280 Assert(!afPciDeviceNo[21]); 1281 afPciDeviceNo[21] = true; 1282 InsertConfigInteger(pCtlInst, "PCIFunctionNo", 0); 1283 1284 /* Attach the status driver */ 1285 InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); 1286 InsertConfigString(pLunL0, "Driver", "MainStatus"); 1287 InsertConfigNode(pLunL0, "Config", &pCfg); 1288 InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapStorageLeds[iLedScsi]); 1289 InsertConfigInteger(pCfg, "First", 0); 1290 Assert(cLedScsi >= 16); 1291 InsertConfigInteger(pCfg, "Last", 15); 1292 paLedDevType = &pConsole->maStorageDevType[iLedScsi]; 988 1293 break; 989 case DeviceType_DVD: 990 pszBootDevice = "DVD"; 991 break; 992 case DeviceType_Floppy: 993 pszBootDevice = "FLOPPY"; 994 break; 995 case DeviceType_Network: 996 pszBootDevice = "LAN"; 997 break; 998 default: 999 AssertMsgFailed(("Invalid bootDevice=%d\n", bootDevice)); 1000 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS, 1001 N_("Invalid boot device '%d'"), bootDevice); 1002 } 1003 rc = CFGMR3InsertString(pBiosCfg, szParamName, pszBootDevice); RC_CHECK(); 1004 } 1005 } 1006 else 1007 { 1008 Utf8Str efiRomFile; 1009 1010 /* Autodetect firmware type, basing on guest type */ 1011 if (eFwType == FirmwareType_EFI) 1012 { 1013 eFwType = 1014 fIs64BitGuest ? 1015 (FirmwareType_T)FirmwareType_EFI64 1016 : 1017 (FirmwareType_T)FirmwareType_EFI32; 1018 } 1019 bool f64BitEntry = eFwType == FirmwareType_EFI64; 1020 1021 rc = findEfiRom(virtualBox, eFwType, efiRomFile); RC_CHECK(); 1022 1023 /* Get boot args */ 1024 Bstr bootArgs; 1025 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EfiBootArgs"), bootArgs.asOutParam()); H(); 1026 1027 /* Get device props */ 1028 Bstr deviceProps; 1029 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EfiDeviceProps"), deviceProps.asOutParam()); H(); 1030 /* Get GOP mode settings */ 1031 uint32_t u32GopMode = UINT32_MAX; 1032 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EfiGopMode"), bstr.asOutParam()); H(); 1033 if (!bstr.isEmpty()) 1034 u32GopMode = Utf8Str(bstr).toUInt32(); 1035 1036 /* UGA mode settings */ 1037 uint32_t u32UgaHorisontal = 0; 1038 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EfiUgaHorizontalResolution"), bstr.asOutParam()); H(); 1039 if (!bstr.isEmpty()) 1040 u32UgaHorisontal = Utf8Str(bstr).toUInt32(); 1041 1042 uint32_t u32UgaVertical = 0; 1043 hrc = pMachine->GetExtraData(Bstr("VBoxInternal2/EfiUgaVerticalResolution"), bstr.asOutParam()); H(); 1044 if (!bstr.isEmpty()) 1045 u32UgaVertical = Utf8Str(bstr).toUInt32(); 1046 1047 /* 1048 * EFI subtree. 1049 */ 1050 rc = CFGMR3InsertNode(pDevices, "efi", &pDev); RC_CHECK(); 1051 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 1052 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 1053 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1054 rc = CFGMR3InsertInteger(pCfg, "RamSize", cbRam); RC_CHECK(); 1055 rc = CFGMR3InsertInteger(pCfg, "RamHoleSize", cbRamHole); RC_CHECK(); 1056 rc = CFGMR3InsertInteger(pCfg, "NumCPUs", cCpus); RC_CHECK(); 1057 rc = CFGMR3InsertString(pCfg, "EfiRom", efiRomFile.raw()); RC_CHECK(); 1058 rc = CFGMR3InsertString(pCfg, "BootArgs", Utf8Str(bootArgs).raw()); RC_CHECK(); 1059 rc = CFGMR3InsertString(pCfg, "DeviceProps", Utf8Str(deviceProps).raw());RC_CHECK(); 1060 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK(); 1061 rc = CFGMR3InsertBytes(pCfg, "UUID", &HardwareUuid,sizeof(HardwareUuid)); RC_CHECK(); 1062 rc = CFGMR3InsertInteger(pCfg, "64BitEntry", f64BitEntry); /* boolean */ RC_CHECK(); 1063 rc = CFGMR3InsertInteger(pCfg, "GopMode", u32GopMode); RC_CHECK(); 1064 rc = CFGMR3InsertInteger(pCfg, "UgaHorizontalResolution", u32UgaHorisontal); RC_CHECK(); 1065 rc = CFGMR3InsertInteger(pCfg, "UgaVerticalResolution", u32UgaVertical); RC_CHECK(); 1066 1067 /* For OS X guests we'll force passing host's DMI info to the guest */ 1068 if (fOsXGuest) 1069 { 1070 rc = CFGMR3InsertInteger(pCfg, "DmiUseHostInfo", 1); RC_CHECK(); 1071 rc = CFGMR3InsertInteger(pCfg, "DmiExposeMemoryTable", 1); RC_CHECK(); 1072 } 1073 } 1074 1075 /* 1076 * Storage controllers. 1077 */ 1078 com::SafeIfaceArray<IStorageController> ctrls; 1079 PCFGMNODE aCtrlNodes[StorageControllerType_LsiLogicSas + 1] = {}; 1080 hrc = pMachine->COMGETTER(StorageControllers)(ComSafeArrayAsOutParam(ctrls)); H(); 1081 1082 for (size_t i = 0; i < ctrls.size(); ++i) 1083 { 1084 DeviceType_T *paLedDevType = NULL; 1085 1086 StorageControllerType_T enmCtrlType; 1087 rc = ctrls[i]->COMGETTER(ControllerType)(&enmCtrlType); H(); 1088 AssertRelease((unsigned)enmCtrlType < RT_ELEMENTS(aCtrlNodes)); 1089 1090 StorageBus_T enmBus; 1091 rc = ctrls[i]->COMGETTER(Bus)(&enmBus); H(); 1092 1093 Bstr controllerName; 1094 rc = ctrls[i]->COMGETTER(Name)(controllerName.asOutParam()); H(); 1095 1096 ULONG ulInstance = 999; 1097 rc = ctrls[i]->COMGETTER(Instance)(&ulInstance); H(); 1098 1099 BOOL fUseHostIOCache; 1100 rc = ctrls[i]->COMGETTER(UseHostIOCache)(&fUseHostIOCache); H(); 1101 1102 /* /Devices/<ctrldev>/ */ 1103 const char *pszCtrlDev = pConsole->convertControllerTypeToDev(enmCtrlType); 1104 pDev = aCtrlNodes[enmCtrlType]; 1105 if (!pDev) 1106 { 1107 rc = CFGMR3InsertNode(pDevices, pszCtrlDev, &pDev); RC_CHECK(); 1108 aCtrlNodes[enmCtrlType] = pDev; /* IDE variants are handled in the switch */ 1109 } 1110 1111 /* /Devices/<ctrldev>/<instance>/ */ 1112 PCFGMNODE pCtlInst = NULL; 1113 rc = CFGMR3InsertNodeF(pDev, &pCtlInst, "%u", ulInstance); RC_CHECK(); 1114 1115 /* Device config: /Devices/<ctrldev>/<instance>/<values> & /ditto/Config/<values> */ 1116 rc = CFGMR3InsertInteger(pCtlInst, "Trusted", 1); RC_CHECK(); 1117 rc = CFGMR3InsertNode(pCtlInst, "Config", &pCfg); RC_CHECK(); 1118 1119 switch (enmCtrlType) 1120 { 1121 case StorageControllerType_LsiLogic: 1122 { 1123 rc = CFGMR3InsertInteger(pCtlInst, "PCIDeviceNo", 20); RC_CHECK(); 1124 Assert(!afPciDeviceNo[20]); 1125 afPciDeviceNo[20] = true; 1126 rc = CFGMR3InsertInteger(pCtlInst, "PCIFunctionNo", 0); RC_CHECK(); 1127 1128 /* Attach the status driver */ 1129 rc = CFGMR3InsertNode(pCtlInst, "LUN#999", &pLunL0); RC_CHECK(); 1130 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK(); 1131 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1132 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapStorageLeds[iLedScsi]); RC_CHECK(); 1133 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK(); 1134 Assert(cLedScsi >= 16); 1135 rc = CFGMR3InsertInteger(pCfg, "Last", 15); RC_CHECK(); 1136 paLedDevType = &pConsole->maStorageDevType[iLedScsi]; 1137 break; 1138 } 1139 1140 case StorageControllerType_BusLogic: 1141 { 1142 rc = CFGMR3InsertInteger(pCtlInst, "PCIDeviceNo", 21); RC_CHECK(); 1143 Assert(!afPciDeviceNo[21]); 1144 afPciDeviceNo[21] = true; 1145 rc = CFGMR3InsertInteger(pCtlInst, "PCIFunctionNo", 0); RC_CHECK(); 1146 1147 /* Attach the status driver */ 1148 rc = CFGMR3InsertNode(pCtlInst, "LUN#999", &pLunL0); RC_CHECK(); 1149 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK(); 1150 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1151 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapStorageLeds[iLedScsi]); RC_CHECK(); 1152 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK(); 1153 Assert(cLedScsi >= 16); 1154 rc = CFGMR3InsertInteger(pCfg, "Last", 15); RC_CHECK(); 1155 paLedDevType = &pConsole->maStorageDevType[iLedScsi]; 1156 break; 1157 } 1158 1159 case StorageControllerType_IntelAhci: 1160 { 1161 rc = CFGMR3InsertInteger(pCtlInst, "PCIDeviceNo", 13); RC_CHECK(); 1162 Assert(!afPciDeviceNo[13]); 1163 afPciDeviceNo[13] = true; 1164 rc = CFGMR3InsertInteger(pCtlInst, "PCIFunctionNo", 0); RC_CHECK(); 1165 1166 ULONG cPorts = 0; 1167 hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts); H(); 1168 rc = CFGMR3InsertInteger(pCfg, "PortCount", cPorts); RC_CHECK(); 1169 1170 /* Needed configuration values for the bios. */ 1171 if (pBiosCfg) 1172 { 1173 rc = CFGMR3InsertString(pBiosCfg, "SataHardDiskDevice", "ahci"); RC_CHECK(); 1174 } 1175 1176 for (uint32_t j = 0; j < 4; ++j) 1177 { 1178 static const char * const s_apszConfig[4] = 1179 { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" }; 1180 static const char * const s_apszBiosConfig[4] = 1181 { "SataPrimaryMasterLUN", "SataPrimarySlaveLUN", "SataSecondaryMasterLUN", "SataSecondarySlaveLUN" }; 1182 1183 LONG lPortNumber = -1; 1184 hrc = ctrls[i]->GetIDEEmulationPort(j, &lPortNumber); H(); 1185 rc = CFGMR3InsertInteger(pCfg, s_apszConfig[j], lPortNumber); RC_CHECK(); 1294 } 1295 1296 case StorageControllerType_IntelAhci: 1297 { 1298 InsertConfigInteger(pCtlInst, "PCIDeviceNo", 13); 1299 Assert(!afPciDeviceNo[13]); 1300 afPciDeviceNo[13] = true; 1301 InsertConfigInteger(pCtlInst, "PCIFunctionNo", 0); 1302 1303 ULONG cPorts = 0; 1304 hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts); H(); 1305 InsertConfigInteger(pCfg, "PortCount", cPorts); 1306 1307 /* Needed configuration values for the bios. */ 1186 1308 if (pBiosCfg) 1187 1309 { 1188 rc = CFGMR3InsertInteger(pBiosCfg, s_apszBiosConfig[j], lPortNumber); RC_CHECK();1310 InsertConfigString(pBiosCfg, "SataHardDiskDevice", "ahci"); 1189 1311 } 1190 } 1191 1192 /* Attach the status driver */ 1193 rc = CFGMR3InsertNode(pCtlInst, "LUN#999", &pLunL0); RC_CHECK(); 1194 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK(); 1195 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1196 AssertRelease(cPorts <= cLedSata); 1197 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapStorageLeds[iLedSata]); RC_CHECK(); 1198 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK(); 1199 rc = CFGMR3InsertInteger(pCfg, "Last", cPorts - 1); RC_CHECK(); 1200 paLedDevType = &pConsole->maStorageDevType[iLedSata]; 1201 break; 1202 } 1203 1204 case StorageControllerType_PIIX3: 1205 case StorageControllerType_PIIX4: 1206 case StorageControllerType_ICH6: 1207 { 1208 /* 1209 * IDE (update this when the main interface changes) 1210 */ 1211 rc = CFGMR3InsertInteger(pCtlInst, "PCIDeviceNo", 1); RC_CHECK(); 1212 Assert(!afPciDeviceNo[1]); 1213 afPciDeviceNo[1] = true; 1214 rc = CFGMR3InsertInteger(pCtlInst, "PCIFunctionNo", 1); RC_CHECK(); 1215 rc = CFGMR3InsertString(pCfg, "Type", controllerString(enmCtrlType)); RC_CHECK(); 1216 1217 /* Attach the status driver */ 1218 rc = CFGMR3InsertNode(pCtlInst, "LUN#999", &pLunL0); RC_CHECK(); 1219 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK(); 1220 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1221 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapStorageLeds[iLedIde]); RC_CHECK(); 1222 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK(); 1223 Assert(cLedIde >= 4); 1224 rc = CFGMR3InsertInteger(pCfg, "Last", 3); RC_CHECK(); 1225 paLedDevType = &pConsole->maStorageDevType[iLedIde]; 1226 1227 /* IDE flavors */ 1228 aCtrlNodes[StorageControllerType_PIIX3] = pDev; 1229 aCtrlNodes[StorageControllerType_PIIX4] = pDev; 1230 aCtrlNodes[StorageControllerType_ICH6] = pDev; 1231 break; 1232 } 1233 1234 case StorageControllerType_I82078: 1235 { 1236 /* 1237 * i82078 Floppy drive controller 1238 */ 1239 fFdcEnabled = true; 1240 rc = CFGMR3InsertInteger(pCfg, "IRQ", 6); RC_CHECK(); 1241 rc = CFGMR3InsertInteger(pCfg, "DMA", 2); RC_CHECK(); 1242 rc = CFGMR3InsertInteger(pCfg, "MemMapped", 0 ); RC_CHECK(); 1243 rc = CFGMR3InsertInteger(pCfg, "IOBase", 0x3f0); RC_CHECK(); 1244 1245 /* Attach the status driver */ 1246 rc = CFGMR3InsertNode(pCtlInst, "LUN#999", &pLunL0); RC_CHECK(); 1247 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK(); 1248 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1249 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapStorageLeds[iLedFloppy]); RC_CHECK(); 1250 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK(); 1251 Assert(cLedFloppy >= 1); 1252 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK(); 1253 paLedDevType = &pConsole->maStorageDevType[iLedFloppy]; 1254 break; 1255 } 1256 1257 case StorageControllerType_LsiLogicSas: 1258 { 1259 rc = CFGMR3InsertInteger(pCtlInst, "PCIDeviceNo", 22); RC_CHECK(); 1260 Assert(!afPciDeviceNo[22]); 1261 afPciDeviceNo[22] = true; 1262 rc = CFGMR3InsertInteger(pCtlInst, "PCIFunctionNo", 0); RC_CHECK(); 1263 1264 rc = CFGMR3InsertString(pCfg, "ControllerType", "SAS1068"); RC_CHECK(); 1265 1266 /* Attach the status driver */ 1267 rc = CFGMR3InsertNode(pCtlInst, "LUN#999", &pLunL0); RC_CHECK(); 1268 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK(); 1269 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1270 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapStorageLeds[iLedSas]); RC_CHECK(); 1271 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK(); 1272 Assert(cLedSas >= 8); 1273 rc = CFGMR3InsertInteger(pCfg, "Last", 7); RC_CHECK(); 1274 paLedDevType = &pConsole->maStorageDevType[iLedSas]; 1275 break; 1276 } 1277 1278 default: 1279 AssertMsgFailedReturn(("invalid storage controller type: %d\n", enmCtrlType), VERR_GENERAL_FAILURE); 1280 } 1281 1282 /* Attach the media to the storage controllers. */ 1283 com::SafeIfaceArray<IMediumAttachment> atts; 1284 hrc = pMachine->GetMediumAttachmentsOfController(controllerName, 1285 ComSafeArrayAsOutParam(atts)); H(); 1286 1287 for (size_t j = 0; j < atts.size(); ++j) 1288 { 1289 rc = pConsole->configMediumAttachment(pCtlInst, 1290 pszCtrlDev, 1291 ulInstance, 1292 enmBus, 1293 fUseHostIOCache, 1294 false /* fSetupMerge */, 1295 0 /* uMergeSource */, 1296 0 /* uMergeTarget */, 1297 atts[j], 1298 pConsole->mMachineState, 1299 NULL /* phrc */, 1300 false /* fAttachDetach */, 1301 false /* fForceUnmount */, 1302 pVM, 1303 paLedDevType); RC_CHECK(); 1312 1313 for (uint32_t j = 0; j < 4; ++j) 1314 { 1315 static const char * const s_apszConfig[4] = 1316 { "PrimaryMaster", "PrimarySlave", "SecondaryMaster", "SecondarySlave" }; 1317 static const char * const s_apszBiosConfig[4] = 1318 { "SataPrimaryMasterLUN", "SataPrimarySlaveLUN", "SataSecondaryMasterLUN", "SataSecondarySlaveLUN" }; 1319 1320 LONG lPortNumber = -1; 1321 hrc = ctrls[i]->GetIDEEmulationPort(j, &lPortNumber); H(); 1322 InsertConfigInteger(pCfg, s_apszConfig[j], lPortNumber); 1323 if (pBiosCfg) 1324 InsertConfigInteger(pBiosCfg, s_apszBiosConfig[j], lPortNumber); 1325 } 1326 1327 /* Attach the status driver */ 1328 InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); 1329 InsertConfigString(pLunL0, "Driver", "MainStatus"); 1330 InsertConfigNode(pLunL0, "Config", &pCfg); 1331 AssertRelease(cPorts <= cLedSata); 1332 InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapStorageLeds[iLedSata]); 1333 InsertConfigInteger(pCfg, "First", 0); 1334 InsertConfigInteger(pCfg, "Last", cPorts - 1); 1335 paLedDevType = &pConsole->maStorageDevType[iLedSata]; 1336 break; 1337 } 1338 1339 case StorageControllerType_PIIX3: 1340 case StorageControllerType_PIIX4: 1341 case StorageControllerType_ICH6: 1342 { 1343 /* 1344 * IDE (update this when the main interface changes) 1345 */ 1346 InsertConfigInteger(pCtlInst, "PCIDeviceNo", 1); 1347 Assert(!afPciDeviceNo[1]); 1348 afPciDeviceNo[1] = true; 1349 InsertConfigInteger(pCtlInst, "PCIFunctionNo", 1); 1350 InsertConfigString(pCfg, "Type", controllerString(enmCtrlType)); 1351 1352 /* Attach the status driver */ 1353 InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); 1354 InsertConfigString(pLunL0, "Driver", "MainStatus"); 1355 InsertConfigNode(pLunL0, "Config", &pCfg); 1356 InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapStorageLeds[iLedIde]); 1357 InsertConfigInteger(pCfg, "First", 0); 1358 Assert(cLedIde >= 4); 1359 InsertConfigInteger(pCfg, "Last", 3); 1360 paLedDevType = &pConsole->maStorageDevType[iLedIde]; 1361 1362 /* IDE flavors */ 1363 aCtrlNodes[StorageControllerType_PIIX3] = pDev; 1364 aCtrlNodes[StorageControllerType_PIIX4] = pDev; 1365 aCtrlNodes[StorageControllerType_ICH6] = pDev; 1366 break; 1367 } 1368 1369 case StorageControllerType_I82078: 1370 { 1371 /* 1372 * i82078 Floppy drive controller 1373 */ 1374 fFdcEnabled = true; 1375 InsertConfigInteger(pCfg, "IRQ", 6); 1376 InsertConfigInteger(pCfg, "DMA", 2); 1377 InsertConfigInteger(pCfg, "MemMapped", 0 ); 1378 InsertConfigInteger(pCfg, "IOBase", 0x3f0); 1379 1380 /* Attach the status driver */ 1381 InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); 1382 InsertConfigString(pLunL0, "Driver", "MainStatus"); 1383 InsertConfigNode(pLunL0, "Config", &pCfg); 1384 InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapStorageLeds[iLedFloppy]); 1385 InsertConfigInteger(pCfg, "First", 0); 1386 Assert(cLedFloppy >= 1); 1387 InsertConfigInteger(pCfg, "Last", 0); 1388 paLedDevType = &pConsole->maStorageDevType[iLedFloppy]; 1389 break; 1390 } 1391 1392 case StorageControllerType_LsiLogicSas: 1393 { 1394 InsertConfigInteger(pCtlInst, "PCIDeviceNo", 22); 1395 Assert(!afPciDeviceNo[22]); 1396 afPciDeviceNo[22] = true; 1397 InsertConfigInteger(pCtlInst, "PCIFunctionNo", 0); 1398 1399 InsertConfigString(pCfg, "ControllerType", "SAS1068"); 1400 1401 /* Attach the status driver */ 1402 InsertConfigNode(pCtlInst, "LUN#999", &pLunL0); 1403 InsertConfigString(pLunL0, "Driver", "MainStatus"); 1404 InsertConfigNode(pLunL0, "Config", &pCfg); 1405 InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapStorageLeds[iLedSas]); 1406 InsertConfigInteger(pCfg, "First", 0); 1407 Assert(cLedSas >= 8); 1408 InsertConfigInteger(pCfg, "Last", 7); 1409 paLedDevType = &pConsole->maStorageDevType[iLedSas]; 1410 break; 1411 } 1412 1413 default: 1414 AssertMsgFailedReturn(("invalid storage controller type: %d\n", enmCtrlType), VERR_GENERAL_FAILURE); 1415 } 1416 1417 /* Attach the media to the storage controllers. */ 1418 com::SafeIfaceArray<IMediumAttachment> atts; 1419 hrc = pMachine->GetMediumAttachmentsOfController(controllerName, 1420 ComSafeArrayAsOutParam(atts)); H(); 1421 1422 for (size_t j = 0; j < atts.size(); ++j) 1423 { 1424 rc = pConsole->configMediumAttachment(pCtlInst, 1425 pszCtrlDev, 1426 ulInstance, 1427 enmBus, 1428 fUseHostIOCache, 1429 false /* fSetupMerge */, 1430 0 /* uMergeSource */, 1431 0 /* uMergeTarget */, 1432 atts[j], 1433 pConsole->mMachineState, 1434 NULL /* phrc */, 1435 false /* fAttachDetach */, 1436 false /* fForceUnmount */, 1437 pVM, 1438 paLedDevType); 1439 if (RT_FAILURE(rc)) 1440 return rc; 1441 } 1442 H(); 1304 1443 } 1305 1444 H(); 1306 } 1307 H(); 1308 1309 /* 1310 * Network adapters 1311 */ 1445 1446 /* 1447 * Network adapters 1448 */ 1312 1449 #ifdef VMWARE_NET_IN_SLOT_11 1313 bool fSwapSlots3and11 = false;1450 bool fSwapSlots3and11 = false; 1314 1451 #endif 1315 PCFGMNODE pDevPCNet = NULL; /* PCNet-type devices */1316 rc = CFGMR3InsertNode(pDevices, "pcnet", &pDevPCNet); RC_CHECK();1452 PCFGMNODE pDevPCNet = NULL; /* PCNet-type devices */ 1453 InsertConfigNode(pDevices, "pcnet", &pDevPCNet); 1317 1454 #ifdef VBOX_WITH_E1000 1318 PCFGMNODE pDevE1000 = NULL; /* E1000-type devices */1319 rc = CFGMR3InsertNode(pDevices, "e1000", &pDevE1000); RC_CHECK();1455 PCFGMNODE pDevE1000 = NULL; /* E1000-type devices */ 1456 InsertConfigNode(pDevices, "e1000", &pDevE1000); 1320 1457 #endif 1321 1458 #ifdef VBOX_WITH_VIRTIO 1322 PCFGMNODE pDevVirtioNet = NULL; /* Virtio network devices */1323 rc = CFGMR3InsertNode(pDevices, "virtio-net", &pDevVirtioNet); RC_CHECK();1459 PCFGMNODE pDevVirtioNet = NULL; /* Virtio network devices */ 1460 InsertConfigNode(pDevices, "virtio-net", &pDevVirtioNet); 1324 1461 #endif /* VBOX_WITH_VIRTIO */ 1325 std::list<BootNic> llBootNics; 1326 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::NetworkAdapterCount; ++ulInstance) 1327 { 1328 ComPtr<INetworkAdapter> networkAdapter; 1329 hrc = pMachine->GetNetworkAdapter(ulInstance, networkAdapter.asOutParam()); H(); 1330 BOOL fEnabled = FALSE; 1331 hrc = networkAdapter->COMGETTER(Enabled)(&fEnabled); H(); 1332 if (!fEnabled) 1333 continue; 1334 1335 /* 1336 * The virtual hardware type. Create appropriate device first. 1337 */ 1338 const char *pszAdapterName = "pcnet"; 1339 NetworkAdapterType_T adapterType; 1340 hrc = networkAdapter->COMGETTER(AdapterType)(&adapterType); H(); 1341 switch (adapterType) 1462 std::list<BootNic> llBootNics; 1463 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::NetworkAdapterCount; ++ulInstance) 1342 1464 { 1343 case NetworkAdapterType_Am79C970A: 1344 case NetworkAdapterType_Am79C973: 1345 pDev = pDevPCNet; 1346 break; 1465 ComPtr<INetworkAdapter> networkAdapter; 1466 hrc = pMachine->GetNetworkAdapter(ulInstance, networkAdapter.asOutParam()); H(); 1467 BOOL fEnabled = FALSE; 1468 hrc = networkAdapter->COMGETTER(Enabled)(&fEnabled); H(); 1469 if (!fEnabled) 1470 continue; 1471 1472 /* 1473 * The virtual hardware type. Create appropriate device first. 1474 */ 1475 const char *pszAdapterName = "pcnet"; 1476 NetworkAdapterType_T adapterType; 1477 hrc = networkAdapter->COMGETTER(AdapterType)(&adapterType); H(); 1478 switch (adapterType) 1479 { 1480 case NetworkAdapterType_Am79C970A: 1481 case NetworkAdapterType_Am79C973: 1482 pDev = pDevPCNet; 1483 break; 1347 1484 #ifdef VBOX_WITH_E1000 1348 case NetworkAdapterType_I82540EM:1349 case NetworkAdapterType_I82543GC:1350 case NetworkAdapterType_I82545EM:1351 pDev = pDevE1000;1352 pszAdapterName = "e1000";1353 break;1485 case NetworkAdapterType_I82540EM: 1486 case NetworkAdapterType_I82543GC: 1487 case NetworkAdapterType_I82545EM: 1488 pDev = pDevE1000; 1489 pszAdapterName = "e1000"; 1490 break; 1354 1491 #endif 1355 1492 #ifdef VBOX_WITH_VIRTIO 1356 case NetworkAdapterType_Virtio:1357 pDev = pDevVirtioNet;1358 pszAdapterName = "virtio-net";1359 break;1493 case NetworkAdapterType_Virtio: 1494 pDev = pDevVirtioNet; 1495 pszAdapterName = "virtio-net"; 1496 break; 1360 1497 #endif /* VBOX_WITH_VIRTIO */ 1361 default: 1362 AssertMsgFailed(("Invalid network adapter type '%d' for slot '%d'", 1363 adapterType, ulInstance)); 1364 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS, 1365 N_("Invalid network adapter type '%d' for slot '%d'"), 1366 adapterType, ulInstance); 1498 default: 1499 AssertMsgFailed(("Invalid network adapter type '%d' for slot '%d'", 1500 adapterType, ulInstance)); 1501 return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS, 1502 N_("Invalid network adapter type '%d' for slot '%d'"), 1503 adapterType, ulInstance); 1504 } 1505 1506 InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pInst); 1507 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 1508 /* the first network card gets the PCI ID 3, the next 3 gets 8..10, 1509 * next 4 get 16..19. */ 1510 unsigned iPciDeviceNo = 3; 1511 if (ulInstance) 1512 { 1513 if (ulInstance < 4) 1514 iPciDeviceNo = ulInstance - 1 + 8; 1515 else 1516 iPciDeviceNo = ulInstance - 4 + 16; 1517 } 1518 #ifdef VMWARE_NET_IN_SLOT_11 1519 /* 1520 * Dirty hack for PCI slot compatibility with VMWare, 1521 * it assigns slot 11 to the first network controller. 1522 */ 1523 if (iPciDeviceNo == 3 && adapterType == NetworkAdapterType_I82545EM) 1524 { 1525 iPciDeviceNo = 0x11; 1526 fSwapSlots3and11 = true; 1527 } 1528 else if (iPciDeviceNo == 0x11 && fSwapSlots3and11) 1529 iPciDeviceNo = 3; 1530 #endif 1531 InsertConfigInteger(pInst, "PCIDeviceNo", iPciDeviceNo); 1532 Assert(!afPciDeviceNo[iPciDeviceNo]); 1533 afPciDeviceNo[iPciDeviceNo] = true; 1534 InsertConfigInteger(pInst, "PCIFunctionNo", 0); 1535 InsertConfigNode(pInst, "Config", &pCfg); 1536 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE not safe here yet. */ 1537 if (pDev == pDevPCNet) 1538 { 1539 InsertConfigInteger(pCfg, "R0Enabled", false); 1540 } 1541 #endif 1542 /* 1543 * Collect information needed for network booting and add it to the list. 1544 */ 1545 BootNic nic; 1546 1547 nic.mInstance = ulInstance; 1548 nic.mPciDev = iPciDeviceNo; 1549 nic.mPciFn = 0; 1550 1551 hrc = networkAdapter->COMGETTER(BootPriority)(&nic.mBootPrio); H(); 1552 1553 llBootNics.push_back(nic); 1554 1555 /* 1556 * The virtual hardware type. PCNet supports two types. 1557 */ 1558 switch (adapterType) 1559 { 1560 case NetworkAdapterType_Am79C970A: 1561 InsertConfigInteger(pCfg, "Am79C973", 0); 1562 break; 1563 case NetworkAdapterType_Am79C973: 1564 InsertConfigInteger(pCfg, "Am79C973", 1); 1565 break; 1566 case NetworkAdapterType_I82540EM: 1567 InsertConfigInteger(pCfg, "AdapterType", 0); 1568 break; 1569 case NetworkAdapterType_I82543GC: 1570 InsertConfigInteger(pCfg, "AdapterType", 1); 1571 break; 1572 case NetworkAdapterType_I82545EM: 1573 InsertConfigInteger(pCfg, "AdapterType", 2); 1574 break; 1575 } 1576 1577 /* 1578 * Get the MAC address and convert it to binary representation 1579 */ 1580 Bstr macAddr; 1581 hrc = networkAdapter->COMGETTER(MACAddress)(macAddr.asOutParam()); H(); 1582 Assert(macAddr); 1583 Utf8Str macAddrUtf8 = macAddr; 1584 char *macStr = (char*)macAddrUtf8.raw(); 1585 Assert(strlen(macStr) == 12); 1586 RTMAC Mac; 1587 memset(&Mac, 0, sizeof(Mac)); 1588 char *pMac = (char*)&Mac; 1589 for (uint32_t i = 0; i < 6; ++i) 1590 { 1591 char c1 = *macStr++ - '0'; 1592 if (c1 > 9) 1593 c1 -= 7; 1594 char c2 = *macStr++ - '0'; 1595 if (c2 > 9) 1596 c2 -= 7; 1597 *pMac++ = ((c1 & 0x0f) << 4) | (c2 & 0x0f); 1598 } 1599 InsertConfigBytes(pCfg, "MAC", &Mac, sizeof(Mac)); 1600 1601 /* 1602 * Check if the cable is supposed to be unplugged 1603 */ 1604 BOOL fCableConnected; 1605 hrc = networkAdapter->COMGETTER(CableConnected)(&fCableConnected); H(); 1606 InsertConfigInteger(pCfg, "CableConnected", fCableConnected ? 1 : 0); 1607 1608 /* 1609 * Line speed to report from custom drivers 1610 */ 1611 ULONG ulLineSpeed; 1612 hrc = networkAdapter->COMGETTER(LineSpeed)(&ulLineSpeed); H(); 1613 InsertConfigInteger(pCfg, "LineSpeed", ulLineSpeed); 1614 1615 /* 1616 * Attach the status driver. 1617 */ 1618 InsertConfigNode(pInst, "LUN#999", &pLunL0); 1619 InsertConfigString(pLunL0, "Driver", "MainStatus"); 1620 InsertConfigNode(pLunL0, "Config", &pCfg); 1621 InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapNetworkLeds[ulInstance]); 1622 1623 /* 1624 * Configure the network card now 1625 */ 1626 rc = pConsole->configNetwork(pszAdapterName, 1627 ulInstance, 1628 0, 1629 networkAdapter, 1630 pCfg, 1631 pLunL0, 1632 pInst, 1633 false /*fAttachDetach*/); 1634 if (RT_FAILURE(rc)) 1635 return rc; 1367 1636 } 1368 1637 1369 rc = CFGMR3InsertNodeF(pDev, &pInst, "%u", ulInstance); RC_CHECK(); 1370 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 1371 /* the first network card gets the PCI ID 3, the next 3 gets 8..10, 1372 * next 4 get 16..19. */ 1373 unsigned iPciDeviceNo = 3; 1374 if (ulInstance) 1638 /* 1639 * Build network boot information and transfer it to the BIOS. 1640 */ 1641 if (pNetBootCfg && !llBootNics.empty()) /* NetBoot node doesn't exist for EFI! */ 1375 1642 { 1376 if (ulInstance < 4) 1377 iPciDeviceNo = ulInstance - 1 + 8; 1378 else 1379 iPciDeviceNo = ulInstance - 4 + 16; 1643 llBootNics.sort(); /* Sort the list by boot priority. */ 1644 1645 char achBootIdx[] = "0"; 1646 unsigned uBootIdx = 0; 1647 1648 for (std::list<BootNic>::iterator it = llBootNics.begin(); it != llBootNics.end(); ++it) 1649 { 1650 /* A NIC with priority 0 is only used if it's first in the list. */ 1651 if (it->mBootPrio == 0 && uBootIdx != 0) 1652 break; 1653 1654 PCFGMNODE pNetBtDevCfg; 1655 achBootIdx[0] = '0' + uBootIdx++; /* Boot device order. */ 1656 InsertConfigNode(pNetBootCfg, achBootIdx, &pNetBtDevCfg); 1657 InsertConfigInteger(pNetBtDevCfg, "NIC", it->mInstance); 1658 InsertConfigInteger(pNetBtDevCfg, "PCIDeviceNo", it->mPciDev); 1659 InsertConfigInteger(pNetBtDevCfg, "PCIFunctionNo", it->mPciFn); 1660 } 1380 1661 } 1381 #ifdef VMWARE_NET_IN_SLOT_11 1382 /* 1383 * Dirty hack for PCI slot compatibility with VMWare,1384 * it assigns slot 11 to the first network controller.1385 */1386 if (iPciDeviceNo == 3 && adapterType == NetworkAdapterType_I82545EM)1662 1663 /* 1664 * Serial (UART) Ports 1665 */ 1666 InsertConfigNode(pDevices, "serial", &pDev); 1667 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::SerialPortCount; ++ulInstance) 1387 1668 { 1388 iPciDeviceNo = 0x11; 1389 fSwapSlots3and11 = true; 1669 ComPtr<ISerialPort> serialPort; 1670 hrc = pMachine->GetSerialPort(ulInstance, serialPort.asOutParam()); H(); 1671 BOOL fEnabled = FALSE; 1672 if (serialPort) 1673 hrc = serialPort->COMGETTER(Enabled)(&fEnabled); H(); 1674 if (!fEnabled) 1675 continue; 1676 1677 InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pInst); 1678 InsertConfigNode(pInst, "Config", &pCfg); 1679 1680 ULONG ulIRQ; 1681 hrc = serialPort->COMGETTER(IRQ)(&ulIRQ); H(); 1682 InsertConfigInteger(pCfg, "IRQ", ulIRQ); 1683 ULONG ulIOBase; 1684 hrc = serialPort->COMGETTER(IOBase)(&ulIOBase); H(); 1685 InsertConfigInteger(pCfg, "IOBase", ulIOBase); 1686 BOOL fServer; 1687 hrc = serialPort->COMGETTER(Server)(&fServer); H(); 1688 hrc = serialPort->COMGETTER(Path)(bstr.asOutParam()); H(); 1689 PortMode_T eHostMode; 1690 hrc = serialPort->COMGETTER(HostMode)(&eHostMode); H(); 1691 if (eHostMode != PortMode_Disconnected) 1692 { 1693 InsertConfigNode(pInst, "LUN#0", &pLunL0); 1694 if (eHostMode == PortMode_HostPipe) 1695 { 1696 InsertConfigString(pLunL0, "Driver", "Char"); 1697 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1); 1698 InsertConfigString(pLunL1, "Driver", "NamedPipe"); 1699 InsertConfigNode(pLunL1, "Config", &pLunL2); 1700 InsertConfigString(pLunL2, "Location", bstr); 1701 InsertConfigInteger(pLunL2, "IsServer", fServer); 1702 } 1703 else if (eHostMode == PortMode_HostDevice) 1704 { 1705 InsertConfigString(pLunL0, "Driver", "Host Serial"); 1706 InsertConfigNode(pLunL0, "Config", &pLunL1); 1707 InsertConfigString(pLunL1, "DevicePath", bstr); 1708 } 1709 else if (eHostMode == PortMode_RawFile) 1710 { 1711 InsertConfigString(pLunL0, "Driver", "Char"); 1712 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1); 1713 InsertConfigString(pLunL1, "Driver", "RawFile"); 1714 InsertConfigNode(pLunL1, "Config", &pLunL2); 1715 InsertConfigString(pLunL2, "Location", bstr); 1716 } 1717 } 1390 1718 } 1391 else if (iPciDeviceNo == 0x11 && fSwapSlots3and11) 1392 iPciDeviceNo = 3; 1393 #endif 1394 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", iPciDeviceNo); RC_CHECK(); 1395 Assert(!afPciDeviceNo[iPciDeviceNo]); 1396 afPciDeviceNo[iPciDeviceNo] = true; 1397 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK(); 1398 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1399 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE /* not safe here yet. */ 1400 if (pDev == pDevPCNet) 1719 1720 /* 1721 * Parallel (LPT) Ports 1722 */ 1723 InsertConfigNode(pDevices, "parallel", &pDev); 1724 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::ParallelPortCount; ++ulInstance) 1401 1725 { 1402 rc = CFGMR3InsertInteger(pCfg, "R0Enabled", false); RC_CHECK(); 1726 ComPtr<IParallelPort> parallelPort; 1727 hrc = pMachine->GetParallelPort(ulInstance, parallelPort.asOutParam()); H(); 1728 BOOL fEnabled = FALSE; 1729 if (parallelPort) 1730 { 1731 hrc = parallelPort->COMGETTER(Enabled)(&fEnabled); H(); 1732 } 1733 if (!fEnabled) 1734 continue; 1735 1736 InsertConfigNode(pDev, Utf8StrFmt("%u", ulInstance).c_str(), &pInst); 1737 InsertConfigNode(pInst, "Config", &pCfg); 1738 1739 ULONG ulIRQ; 1740 hrc = parallelPort->COMGETTER(IRQ)(&ulIRQ); H(); 1741 InsertConfigInteger(pCfg, "IRQ", ulIRQ); 1742 ULONG ulIOBase; 1743 hrc = parallelPort->COMGETTER(IOBase)(&ulIOBase); H(); 1744 InsertConfigInteger(pCfg, "IOBase", ulIOBase); 1745 InsertConfigNode(pInst, "LUN#0", &pLunL0); 1746 InsertConfigString(pLunL0, "Driver", "HostParallel"); 1747 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1); 1748 hrc = parallelPort->COMGETTER(Path)(bstr.asOutParam()); H(); 1749 InsertConfigString(pLunL1, "DevicePath", bstr); 1403 1750 } 1404 #endif 1405 /* 1406 * Collect information needed for network booting and add it to the list. 1407 */ 1408 BootNic nic; 1409 1410 nic.mInstance = ulInstance; 1411 nic.mPciDev = iPciDeviceNo; 1412 nic.mPciFn = 0; 1413 1414 hrc = networkAdapter->COMGETTER(BootPriority)(&nic.mBootPrio); H(); 1415 1416 llBootNics.push_back(nic); 1417 1418 /* 1419 * The virtual hardware type. PCNet supports two types. 1420 */ 1421 switch (adapterType) 1751 1752 /* 1753 * VMM Device 1754 */ 1755 InsertConfigNode(pDevices, "VMMDev", &pDev); 1756 InsertConfigNode(pDev, "0", &pInst); 1757 InsertConfigNode(pInst, "Config", &pCfg); 1758 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 1759 InsertConfigInteger(pInst, "PCIDeviceNo", 4); 1760 Assert(!afPciDeviceNo[4]); 1761 afPciDeviceNo[4] = true; 1762 InsertConfigInteger(pInst, "PCIFunctionNo", 0); 1763 Bstr hwVersion; 1764 hrc = pMachine->COMGETTER(HardwareVersion)(hwVersion.asOutParam()); H(); 1765 InsertConfigInteger(pCfg, "RamSize", cbRam); 1766 if (hwVersion.compare(Bstr("1")) == 0) /* <= 2.0.x */ 1767 InsertConfigInteger(pCfg, "HeapEnabled", 0); 1768 1769 /* the VMM device's Main driver */ 1770 InsertConfigNode(pInst, "LUN#0", &pLunL0); 1771 InsertConfigString(pLunL0, "Driver", "HGCM"); 1772 InsertConfigNode(pLunL0, "Config", &pCfg); 1773 VMMDev *pVMMDev = pConsole->mVMMDev; 1774 InsertConfigInteger(pCfg, "Object", (uintptr_t)pVMMDev); 1775 1776 /* 1777 * Attach the status driver. 1778 */ 1779 InsertConfigNode(pInst, "LUN#999", &pLunL0); 1780 InsertConfigString(pLunL0, "Driver", "MainStatus"); 1781 InsertConfigNode(pLunL0, "Config", &pCfg); 1782 InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapSharedFolderLed); 1783 InsertConfigInteger(pCfg, "First", 0); 1784 InsertConfigInteger(pCfg, "Last", 0); 1785 1786 /* 1787 * Audio Sniffer Device 1788 */ 1789 InsertConfigNode(pDevices, "AudioSniffer", &pDev); 1790 InsertConfigNode(pDev, "0", &pInst); 1791 InsertConfigNode(pInst, "Config", &pCfg); 1792 1793 /* the Audio Sniffer device's Main driver */ 1794 InsertConfigNode(pInst, "LUN#0", &pLunL0); 1795 InsertConfigString(pLunL0, "Driver", "MainAudioSniffer"); 1796 InsertConfigNode(pLunL0, "Config", &pCfg); 1797 AudioSniffer *pAudioSniffer = pConsole->mAudioSniffer; 1798 InsertConfigInteger(pCfg, "Object", (uintptr_t)pAudioSniffer); 1799 1800 /* 1801 * AC'97 ICH / SoundBlaster16 audio 1802 */ 1803 BOOL enabled; 1804 ComPtr<IAudioAdapter> audioAdapter; 1805 hrc = pMachine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam()); H(); 1806 if (audioAdapter) 1807 hrc = audioAdapter->COMGETTER(Enabled)(&enabled); H(); 1808 1809 if (enabled) 1422 1810 { 1423 case NetworkAdapterType_Am79C970A: 1424 rc = CFGMR3InsertInteger(pCfg, "Am79C973", 0); RC_CHECK(); 1425 break; 1426 case NetworkAdapterType_Am79C973: 1427 rc = CFGMR3InsertInteger(pCfg, "Am79C973", 1); RC_CHECK(); 1428 break; 1429 case NetworkAdapterType_I82540EM: 1430 rc = CFGMR3InsertInteger(pCfg, "AdapterType", 0); RC_CHECK(); 1431 break; 1432 case NetworkAdapterType_I82543GC: 1433 rc = CFGMR3InsertInteger(pCfg, "AdapterType", 1); RC_CHECK(); 1434 break; 1435 case NetworkAdapterType_I82545EM: 1436 rc = CFGMR3InsertInteger(pCfg, "AdapterType", 2); RC_CHECK(); 1437 break; 1438 } 1439 1440 /* 1441 * Get the MAC address and convert it to binary representation 1442 */ 1443 Bstr macAddr; 1444 hrc = networkAdapter->COMGETTER(MACAddress)(macAddr.asOutParam()); H(); 1445 Assert(macAddr); 1446 Utf8Str macAddrUtf8 = macAddr; 1447 char *macStr = (char*)macAddrUtf8.raw(); 1448 Assert(strlen(macStr) == 12); 1449 RTMAC Mac; 1450 memset(&Mac, 0, sizeof(Mac)); 1451 char *pMac = (char*)&Mac; 1452 for (uint32_t i = 0; i < 6; ++i) 1453 { 1454 char c1 = *macStr++ - '0'; 1455 if (c1 > 9) 1456 c1 -= 7; 1457 char c2 = *macStr++ - '0'; 1458 if (c2 > 9) 1459 c2 -= 7; 1460 *pMac++ = ((c1 & 0x0f) << 4) | (c2 & 0x0f); 1461 } 1462 rc = CFGMR3InsertBytes(pCfg, "MAC", &Mac, sizeof(Mac)); RC_CHECK(); 1463 1464 /* 1465 * Check if the cable is supposed to be unplugged 1466 */ 1467 BOOL fCableConnected; 1468 hrc = networkAdapter->COMGETTER(CableConnected)(&fCableConnected); H(); 1469 rc = CFGMR3InsertInteger(pCfg, "CableConnected", fCableConnected ? 1 : 0); RC_CHECK(); 1470 1471 /* 1472 * Line speed to report from custom drivers 1473 */ 1474 ULONG ulLineSpeed; 1475 hrc = networkAdapter->COMGETTER(LineSpeed)(&ulLineSpeed); H(); 1476 rc = CFGMR3InsertInteger(pCfg, "LineSpeed", ulLineSpeed); RC_CHECK(); 1477 1478 /* 1479 * Attach the status driver. 1480 */ 1481 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK(); 1482 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK(); 1483 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1484 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapNetworkLeds[ulInstance]); RC_CHECK(); 1485 1486 /* 1487 * Configure the network card now 1488 */ 1489 rc = pConsole->configNetwork(pszAdapterName, ulInstance, 0, 1490 networkAdapter, pCfg, pLunL0, pInst, 1491 false /*fAttachDetach*/); RC_CHECK(); 1492 } 1493 1494 /* 1495 * Build network boot information and transfer it to the BIOS. 1496 */ 1497 if (pNetBootCfg && !llBootNics.empty()) /* NetBoot node doesn't exist for EFI! */ 1498 { 1499 llBootNics.sort(); /* Sort the list by boot priority. */ 1500 1501 char achBootIdx[] = "0"; 1502 unsigned uBootIdx = 0; 1503 1504 for (std::list<BootNic>::iterator it = llBootNics.begin(); it != llBootNics.end(); ++it) 1505 { 1506 /* A NIC with priority 0 is only used if it's first in the list. */ 1507 if (it->mBootPrio == 0 && uBootIdx != 0) 1508 break; 1509 1510 PCFGMNODE pNetBtDevCfg; 1511 achBootIdx[0] = '0' + uBootIdx++; /* Boot device order. */ 1512 rc = CFGMR3InsertNode(pNetBootCfg, achBootIdx, &pNetBtDevCfg); RC_CHECK(); 1513 rc = CFGMR3InsertInteger(pNetBtDevCfg, "NIC", it->mInstance); RC_CHECK(); 1514 rc = CFGMR3InsertInteger(pNetBtDevCfg, "PCIDeviceNo", it->mPciDev); RC_CHECK(); 1515 rc = CFGMR3InsertInteger(pNetBtDevCfg, "PCIFunctionNo", it->mPciFn); RC_CHECK(); 1516 } 1517 } 1518 1519 /* 1520 * Serial (UART) Ports 1521 */ 1522 rc = CFGMR3InsertNode(pDevices, "serial", &pDev); RC_CHECK(); 1523 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::SerialPortCount; ++ulInstance) 1524 { 1525 ComPtr<ISerialPort> serialPort; 1526 hrc = pMachine->GetSerialPort(ulInstance, serialPort.asOutParam()); H(); 1527 BOOL fEnabled = FALSE; 1528 if (serialPort) 1529 hrc = serialPort->COMGETTER(Enabled)(&fEnabled); H(); 1530 if (!fEnabled) 1531 continue; 1532 1533 rc = CFGMR3InsertNodeF(pDev, &pInst, "%u", ulInstance); RC_CHECK(); 1534 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1535 1536 ULONG ulIRQ; 1537 hrc = serialPort->COMGETTER(IRQ)(&ulIRQ); H(); 1538 rc = CFGMR3InsertInteger(pCfg, "IRQ", ulIRQ); RC_CHECK(); 1539 ULONG ulIOBase; 1540 hrc = serialPort->COMGETTER(IOBase)(&ulIOBase); H(); 1541 rc = CFGMR3InsertInteger(pCfg, "IOBase", ulIOBase); RC_CHECK(); 1542 BOOL fServer; 1543 hrc = serialPort->COMGETTER(Server)(&fServer); H(); 1544 hrc = serialPort->COMGETTER(Path)(bstr.asOutParam()); H(); 1545 PortMode_T eHostMode; 1546 hrc = serialPort->COMGETTER(HostMode)(&eHostMode); H(); 1547 if (eHostMode != PortMode_Disconnected) 1548 { 1549 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 1550 if (eHostMode == PortMode_HostPipe) 1551 { 1552 rc = CFGMR3InsertString(pLunL0, "Driver", "Char"); RC_CHECK(); 1553 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK(); 1554 rc = CFGMR3InsertString(pLunL1, "Driver", "NamedPipe"); RC_CHECK(); 1555 rc = CFGMR3InsertNode(pLunL1, "Config", &pLunL2); RC_CHECK(); 1556 rc = CFGMR3InsertStringW(pLunL2, "Location", bstr.raw()); RC_CHECK(); 1557 rc = CFGMR3InsertInteger(pLunL2, "IsServer", fServer); RC_CHECK(); 1558 } 1559 else if (eHostMode == PortMode_HostDevice) 1560 { 1561 rc = CFGMR3InsertString(pLunL0, "Driver", "Host Serial"); RC_CHECK(); 1562 rc = CFGMR3InsertNode(pLunL0, "Config", &pLunL1); RC_CHECK(); 1563 rc = CFGMR3InsertStringW(pLunL1, "DevicePath", bstr.raw()); RC_CHECK(); 1564 } 1565 else if (eHostMode == PortMode_RawFile) 1566 { 1567 rc = CFGMR3InsertString(pLunL0, "Driver", "Char"); RC_CHECK(); 1568 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK(); 1569 rc = CFGMR3InsertString(pLunL1, "Driver", "RawFile"); RC_CHECK(); 1570 rc = CFGMR3InsertNode(pLunL1, "Config", &pLunL2); RC_CHECK(); 1571 rc = CFGMR3InsertStringW(pLunL2, "Location", bstr.raw()); RC_CHECK(); 1572 } 1573 } 1574 } 1575 1576 /* 1577 * Parallel (LPT) Ports 1578 */ 1579 rc = CFGMR3InsertNode(pDevices, "parallel", &pDev); RC_CHECK(); 1580 for (ULONG ulInstance = 0; ulInstance < SchemaDefs::ParallelPortCount; ++ulInstance) 1581 { 1582 ComPtr<IParallelPort> parallelPort; 1583 hrc = pMachine->GetParallelPort(ulInstance, parallelPort.asOutParam()); H(); 1584 BOOL fEnabled = FALSE; 1585 if (parallelPort) 1586 { 1587 hrc = parallelPort->COMGETTER(Enabled)(&fEnabled); H(); 1588 } 1589 if (!fEnabled) 1590 continue; 1591 1592 rc = CFGMR3InsertNodeF(pDev, &pInst, "%u", ulInstance); RC_CHECK(); 1593 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1594 1595 ULONG ulIRQ; 1596 hrc = parallelPort->COMGETTER(IRQ)(&ulIRQ); H(); 1597 rc = CFGMR3InsertInteger(pCfg, "IRQ", ulIRQ); RC_CHECK(); 1598 ULONG ulIOBase; 1599 hrc = parallelPort->COMGETTER(IOBase)(&ulIOBase); H(); 1600 rc = CFGMR3InsertInteger(pCfg, "IOBase", ulIOBase); RC_CHECK(); 1601 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 1602 rc = CFGMR3InsertString(pLunL0, "Driver", "HostParallel"); RC_CHECK(); 1603 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK(); 1604 hrc = parallelPort->COMGETTER(Path)(bstr.asOutParam()); H(); 1605 rc = CFGMR3InsertStringW(pLunL1, "DevicePath", bstr.raw()); RC_CHECK(); 1606 } 1607 1608 /* 1609 * VMM Device 1610 */ 1611 rc = CFGMR3InsertNode(pDevices, "VMMDev", &pDev); RC_CHECK(); 1612 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 1613 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1614 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 1615 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 4); RC_CHECK(); 1616 Assert(!afPciDeviceNo[4]); 1617 afPciDeviceNo[4] = true; 1618 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK(); 1619 Bstr hwVersion; 1620 hrc = pMachine->COMGETTER(HardwareVersion)(hwVersion.asOutParam()); H(); 1621 rc = CFGMR3InsertInteger(pCfg, "RamSize", cbRam); RC_CHECK(); 1622 if (hwVersion.compare(Bstr("1")) == 0) /* <= 2.0.x */ 1623 { 1624 CFGMR3InsertInteger(pCfg, "HeapEnabled", 0); RC_CHECK(); 1625 } 1626 1627 /* the VMM device's Main driver */ 1628 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 1629 rc = CFGMR3InsertString(pLunL0, "Driver", "HGCM"); RC_CHECK(); 1630 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1631 VMMDev *pVMMDev = pConsole->mVMMDev; 1632 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pVMMDev); RC_CHECK(); 1633 1634 /* 1635 * Attach the status driver. 1636 */ 1637 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK(); 1638 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK(); 1639 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1640 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapSharedFolderLed); RC_CHECK(); 1641 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK(); 1642 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK(); 1643 1644 /* 1645 * Audio Sniffer Device 1646 */ 1647 rc = CFGMR3InsertNode(pDevices, "AudioSniffer", &pDev); RC_CHECK(); 1648 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 1649 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1650 1651 /* the Audio Sniffer device's Main driver */ 1652 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 1653 rc = CFGMR3InsertString(pLunL0, "Driver", "MainAudioSniffer"); RC_CHECK(); 1654 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1655 AudioSniffer *pAudioSniffer = pConsole->mAudioSniffer; 1656 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pAudioSniffer); RC_CHECK(); 1657 1658 /* 1659 * AC'97 ICH / SoundBlaster16 audio 1660 */ 1661 BOOL enabled; 1662 ComPtr<IAudioAdapter> audioAdapter; 1663 hrc = pMachine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam()); H(); 1664 if (audioAdapter) 1665 hrc = audioAdapter->COMGETTER(Enabled)(&enabled); H(); 1666 1667 if (enabled) 1668 { 1669 AudioControllerType_T audioController; 1670 hrc = audioAdapter->COMGETTER(AudioController)(&audioController); H(); 1671 switch (audioController) 1672 { 1673 case AudioControllerType_AC97: 1674 { 1675 /* default: ICH AC97 */ 1676 rc = CFGMR3InsertNode(pDevices, "ichac97", &pDev); RC_CHECK(); 1677 rc = CFGMR3InsertNode(pDev, "0", &pInst); 1678 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* bool */ RC_CHECK(); 1679 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 5); RC_CHECK(); 1680 Assert(!afPciDeviceNo[5]); 1681 afPciDeviceNo[5] = true; 1682 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK(); 1683 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1684 break; 1685 } 1686 case AudioControllerType_SB16: 1687 { 1688 /* legacy SoundBlaster16 */ 1689 rc = CFGMR3InsertNode(pDevices, "sb16", &pDev); RC_CHECK(); 1690 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 1691 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* bool */ RC_CHECK(); 1692 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1693 rc = CFGMR3InsertInteger(pCfg, "IRQ", 5); RC_CHECK(); 1694 rc = CFGMR3InsertInteger(pCfg, "DMA", 1); RC_CHECK(); 1695 rc = CFGMR3InsertInteger(pCfg, "DMA16", 5); RC_CHECK(); 1696 rc = CFGMR3InsertInteger(pCfg, "Port", 0x220); RC_CHECK(); 1697 rc = CFGMR3InsertInteger(pCfg, "Version", 0x0405); RC_CHECK(); 1698 break; 1699 } 1700 } 1701 1702 /* the Audio driver */ 1703 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 1704 rc = CFGMR3InsertString(pLunL0, "Driver", "AUDIO"); RC_CHECK(); 1705 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1706 1707 AudioDriverType_T audioDriver; 1708 hrc = audioAdapter->COMGETTER(AudioDriver)(&audioDriver); H(); 1709 switch (audioDriver) 1710 { 1711 case AudioDriverType_Null: 1712 { 1713 rc = CFGMR3InsertString(pCfg, "AudioDriver", "null"); RC_CHECK(); 1714 break; 1715 } 1811 AudioControllerType_T audioController; 1812 hrc = audioAdapter->COMGETTER(AudioController)(&audioController); H(); 1813 switch (audioController) 1814 { 1815 case AudioControllerType_AC97: 1816 { 1817 /* default: ICH AC97 */ 1818 InsertConfigNode(pDevices, "ichac97", &pDev); 1819 rc = CFGMR3InsertNode(pDev, "0", &pInst); 1820 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 1821 InsertConfigInteger(pInst, "PCIDeviceNo", 5); 1822 Assert(!afPciDeviceNo[5]); 1823 afPciDeviceNo[5] = true; 1824 InsertConfigInteger(pInst, "PCIFunctionNo", 0); 1825 InsertConfigNode(pInst, "Config", &pCfg); 1826 break; 1827 } 1828 case AudioControllerType_SB16: 1829 { 1830 /* legacy SoundBlaster16 */ 1831 InsertConfigNode(pDevices, "sb16", &pDev); 1832 InsertConfigNode(pDev, "0", &pInst); 1833 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 1834 InsertConfigNode(pInst, "Config", &pCfg); 1835 InsertConfigInteger(pCfg, "IRQ", 5); 1836 InsertConfigInteger(pCfg, "DMA", 1); 1837 InsertConfigInteger(pCfg, "DMA16", 5); 1838 InsertConfigInteger(pCfg, "Port", 0x220); 1839 InsertConfigInteger(pCfg, "Version", 0x0405); 1840 break; 1841 } 1842 } 1843 1844 /* the Audio driver */ 1845 InsertConfigNode(pInst, "LUN#0", &pLunL0); 1846 InsertConfigString(pLunL0, "Driver", "AUDIO"); 1847 InsertConfigNode(pLunL0, "Config", &pCfg); 1848 1849 AudioDriverType_T audioDriver; 1850 hrc = audioAdapter->COMGETTER(AudioDriver)(&audioDriver); H(); 1851 switch (audioDriver) 1852 { 1853 case AudioDriverType_Null: 1854 { 1855 InsertConfigString(pCfg, "AudioDriver", "null"); 1856 break; 1857 } 1716 1858 #ifdef RT_OS_WINDOWS 1717 1859 #ifdef VBOX_WITH_WINMM 1718 case AudioDriverType_WinMM:1719 {1720 rc = CFGMR3InsertString(pCfg, "AudioDriver", "winmm"); RC_CHECK();1721 break;1722 }1860 case AudioDriverType_WinMM: 1861 { 1862 InsertConfigString(pCfg, "AudioDriver", "winmm"); 1863 break; 1864 } 1723 1865 #endif 1724 case AudioDriverType_DirectSound:1725 {1726 rc = CFGMR3InsertString(pCfg, "AudioDriver", "dsound"); RC_CHECK();1727 break;1728 }1866 case AudioDriverType_DirectSound: 1867 { 1868 InsertConfigString(pCfg, "AudioDriver", "dsound"); 1869 break; 1870 } 1729 1871 #endif /* RT_OS_WINDOWS */ 1730 1872 #ifdef RT_OS_SOLARIS 1731 case AudioDriverType_SolAudio:1732 {1733 rc = CFGMR3InsertString(pCfg, "AudioDriver", "solaudio"); RC_CHECK();1734 break;1735 }1873 case AudioDriverType_SolAudio: 1874 { 1875 InsertConfigString(pCfg, "AudioDriver", "solaudio"); 1876 break; 1877 } 1736 1878 #endif 1737 1879 #ifdef RT_OS_LINUX 1738 1880 # ifdef VBOX_WITH_ALSA 1739 case AudioDriverType_ALSA:1740 {1741 rc = CFGMR3InsertString(pCfg, "AudioDriver", "alsa"); RC_CHECK();1742 break;1743 }1881 case AudioDriverType_ALSA: 1882 { 1883 InsertConfigString(pCfg, "AudioDriver", "alsa"); 1884 break; 1885 } 1744 1886 # endif 1745 1887 # ifdef VBOX_WITH_PULSE 1746 case AudioDriverType_Pulse:1747 {1748 rc = CFGMR3InsertString(pCfg, "AudioDriver", "pulse"); RC_CHECK();1749 break;1750 }1888 case AudioDriverType_Pulse: 1889 { 1890 InsertConfigString(pCfg, "AudioDriver", "pulse"); 1891 break; 1892 } 1751 1893 # endif 1752 1894 #endif /* RT_OS_LINUX */ 1753 1895 #if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(VBOX_WITH_SOLARIS_OSS) 1754 case AudioDriverType_OSS:1755 {1756 rc = CFGMR3InsertString(pCfg, "AudioDriver", "oss"); RC_CHECK();1757 break;1758 }1896 case AudioDriverType_OSS: 1897 { 1898 InsertConfigString(pCfg, "AudioDriver", "oss"); 1899 break; 1900 } 1759 1901 #endif 1760 1902 #ifdef RT_OS_FREEBSD 1761 1903 # ifdef VBOX_WITH_PULSE 1762 case AudioDriverType_Pulse:1763 {1764 rc = CFGMR3InsertString(pCfg, "AudioDriver", "pulse"); RC_CHECK();1765 break;1766 }1904 case AudioDriverType_Pulse: 1905 { 1906 InsertConfigString(pCfg, "AudioDriver", "pulse"); 1907 break; 1908 } 1767 1909 # endif 1768 1910 #endif 1769 1911 #ifdef RT_OS_DARWIN 1770 case AudioDriverType_CoreAudio:1771 {1772 rc = CFGMR3InsertString(pCfg, "AudioDriver", "coreaudio"); RC_CHECK();1773 break;1774 }1912 case AudioDriverType_CoreAudio: 1913 { 1914 InsertConfigString(pCfg, "AudioDriver", "coreaudio"); 1915 break; 1916 } 1775 1917 #endif 1918 } 1919 hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H(); 1920 InsertConfigString(pCfg, "StreamName", bstr); 1776 1921 } 1777 hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H(); 1778 rc = CFGMR3InsertStringW(pCfg, "StreamName", bstr.raw()); RC_CHECK(); 1779 } 1780 1781 /* 1782 * The USB Controller. 1783 */ 1784 ComPtr<IUSBController> USBCtlPtr; 1785 hrc = pMachine->COMGETTER(USBController)(USBCtlPtr.asOutParam()); 1786 if (USBCtlPtr) 1787 { 1788 BOOL fOhciEnabled; 1789 hrc = USBCtlPtr->COMGETTER(Enabled)(&fOhciEnabled); H(); 1790 if (fOhciEnabled) 1922 1923 /* 1924 * The USB Controller. 1925 */ 1926 ComPtr<IUSBController> USBCtlPtr; 1927 hrc = pMachine->COMGETTER(USBController)(USBCtlPtr.asOutParam()); 1928 if (USBCtlPtr) 1791 1929 { 1792 rc = CFGMR3InsertNode(pDevices, "usb-ohci", &pDev); RC_CHECK(); 1793 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 1794 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1795 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK(); 1796 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 6); RC_CHECK(); 1797 Assert(!afPciDeviceNo[6]); 1798 afPciDeviceNo[6] = true; 1799 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK(); 1800 1801 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 1802 rc = CFGMR3InsertString(pLunL0, "Driver", "VUSBRootHub"); RC_CHECK(); 1803 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1930 BOOL fOhciEnabled; 1931 hrc = USBCtlPtr->COMGETTER(Enabled)(&fOhciEnabled); H(); 1932 if (fOhciEnabled) 1933 { 1934 InsertConfigNode(pDevices, "usb-ohci", &pDev); 1935 InsertConfigNode(pDev, "0", &pInst); 1936 InsertConfigNode(pInst, "Config", &pCfg); 1937 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 1938 InsertConfigInteger(pInst, "PCIDeviceNo", 6); 1939 Assert(!afPciDeviceNo[6]); 1940 afPciDeviceNo[6] = true; 1941 InsertConfigInteger(pInst, "PCIFunctionNo", 0); 1942 1943 InsertConfigNode(pInst, "LUN#0", &pLunL0); 1944 InsertConfigString(pLunL0, "Driver", "VUSBRootHub"); 1945 InsertConfigNode(pLunL0, "Config", &pCfg); 1946 1947 /* 1948 * Attach the status driver. 1949 */ 1950 InsertConfigNode(pInst, "LUN#999", &pLunL0); 1951 InsertConfigString(pLunL0, "Driver", "MainStatus"); 1952 InsertConfigNode(pLunL0, "Config", &pCfg); 1953 InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapUSBLed[0]); 1954 InsertConfigInteger(pCfg, "First", 0); 1955 InsertConfigInteger(pCfg, "Last", 0); 1956 1957 #ifdef VBOX_WITH_EHCI 1958 BOOL fEhciEnabled; 1959 hrc = USBCtlPtr->COMGETTER(EnabledEhci)(&fEhciEnabled); H(); 1960 if (fEhciEnabled) 1961 { 1962 InsertConfigNode(pDevices, "usb-ehci", &pDev); 1963 InsertConfigNode(pDev, "0", &pInst); 1964 InsertConfigNode(pInst, "Config", &pCfg); 1965 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 1966 InsertConfigInteger(pInst, "PCIDeviceNo", 11); 1967 Assert(!afPciDeviceNo[11]); 1968 afPciDeviceNo[11] = true; 1969 InsertConfigInteger(pInst, "PCIFunctionNo", 0); 1970 1971 InsertConfigNode(pInst, "LUN#0", &pLunL0); 1972 InsertConfigString(pLunL0, "Driver", "VUSBRootHub"); 1973 InsertConfigNode(pLunL0, "Config", &pCfg); 1974 1975 /* 1976 * Attach the status driver. 1977 */ 1978 InsertConfigNode(pInst, "LUN#999", &pLunL0); 1979 InsertConfigString(pLunL0, "Driver", "MainStatus"); 1980 InsertConfigNode(pLunL0, "Config", &pCfg); 1981 InsertConfigInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapUSBLed[1]); 1982 InsertConfigInteger(pCfg, "First", 0); 1983 InsertConfigInteger(pCfg, "Last", 0); 1984 } 1985 #endif 1986 1987 /* 1988 * Virtual USB Devices. 1989 */ 1990 PCFGMNODE pUsbDevices = NULL; 1991 InsertConfigNode(pRoot, "USB", &pUsbDevices); 1992 1993 #ifdef VBOX_WITH_USB 1994 { 1995 /* 1996 * Global USB options, currently unused as we'll apply the 2.0 -> 1.1 morphing 1997 * on a per device level now. 1998 */ 1999 InsertConfigNode(pUsbDevices, "USBProxy", &pCfg); 2000 InsertConfigNode(pCfg, "GlobalConfig", &pCfg); 2001 // This globally enables the 2.0 -> 1.1 device morphing of proxied devies to keep windows quiet. 2002 //InsertConfigInteger(pCfg, "Force11Device", true); 2003 // The following breaks stuff, but it makes MSDs work in vista. (I include it here so 2004 // that it's documented somewhere.) Users needing it can use: 2005 // VBoxManage setextradata "myvm" "VBoxInternal/USB/USBProxy/GlobalConfig/Force11PacketSize" 1 2006 //InsertConfigInteger(pCfg, "Force11PacketSize", true); 2007 } 2008 #endif 2009 2010 # if 0 /* Virtual MSD*/ 2011 2012 InsertConfigNode(pUsbDevices, "Msd", &pDev); 2013 InsertConfigNode(pDev, "0", &pInst); 2014 InsertConfigNode(pInst, "Config", &pCfg); 2015 InsertConfigNode(pInst, "LUN#0", &pLunL0); 2016 2017 InsertConfigString(pLunL0, "Driver", "SCSI"); 2018 InsertConfigNode(pLunL0, "Config", &pCfg); 2019 2020 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1); 2021 InsertConfigString(pLunL1, "Driver", "Block"); 2022 InsertConfigNode(pLunL1, "Config", &pCfg); 2023 InsertConfigString(pCfg, "Type", "HardDisk"); 2024 InsertConfigInteger(pCfg, "Mountable", 0); 2025 2026 InsertConfigNode(pLunL1, "AttachedDriver", &pLunL2); 2027 InsertConfigString(pLunL2, "Driver", "VD"); 2028 InsertConfigNode(pLunL2, "Config", &pCfg); 2029 InsertConfigString(pCfg, "Path", "/Volumes/DataHFS/bird/VDIs/linux.vdi"); 2030 InsertConfigString(pCfg, "Format", "VDI"); 2031 # endif 2032 2033 /* Virtual USB Mouse/Tablet */ 2034 PointingHidType_T aPointingHid; 2035 hrc = pMachine->COMGETTER(PointingHidType)(&aPointingHid); H(); 2036 if (aPointingHid == PointingHidType_USBMouse || aPointingHid == PointingHidType_USBTablet) 2037 { 2038 InsertConfigNode(pUsbDevices, "HidMouse", &pDev); 2039 InsertConfigNode(pDev, "0", &pInst); 2040 InsertConfigNode(pInst, "Config", &pCfg); 2041 2042 if (aPointingHid == PointingHidType_USBTablet) 2043 { 2044 InsertConfigInteger(pCfg, "Absolute", 1); 2045 } 2046 else 2047 { 2048 InsertConfigInteger(pCfg, "Absolute", 0); 2049 } 2050 InsertConfigNode(pInst, "LUN#0", &pLunL0); 2051 InsertConfigString(pLunL0, "Driver", "MouseQueue"); 2052 InsertConfigNode(pLunL0, "Config", &pCfg); 2053 InsertConfigInteger(pCfg, "QueueSize", 128); 2054 2055 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1); 2056 InsertConfigString(pLunL1, "Driver", "MainMouse"); 2057 InsertConfigNode(pLunL1, "Config", &pCfg); 2058 pMouse = pConsole->mMouse; 2059 InsertConfigInteger(pCfg, "Object", (uintptr_t)pMouse); 2060 } 2061 2062 /* Virtual USB Keyboard */ 2063 KeyboardHidType_T aKbdHid; 2064 hrc = pMachine->COMGETTER(KeyboardHidType)(&aKbdHid); H(); 2065 if (aKbdHid == KeyboardHidType_USBKeyboard) 2066 { 2067 InsertConfigNode(pUsbDevices, "HidKeyboard", &pDev); 2068 InsertConfigNode(pDev, "0", &pInst); 2069 InsertConfigNode(pInst, "Config", &pCfg); 2070 2071 InsertConfigNode(pInst, "LUN#0", &pLunL0); 2072 InsertConfigString(pLunL0, "Driver", "KeyboardQueue"); 2073 InsertConfigNode(pLunL0, "Config", &pCfg); 2074 InsertConfigInteger(pCfg, "QueueSize", 64); 2075 2076 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1); 2077 InsertConfigString(pLunL1, "Driver", "MainKeyboard"); 2078 InsertConfigNode(pLunL1, "Config", &pCfg); 2079 pKeyboard = pConsole->mKeyboard; 2080 InsertConfigInteger(pCfg, "Object", (uintptr_t)pKeyboard); 2081 } 2082 } 2083 } 2084 2085 /* 2086 * Clipboard 2087 */ 2088 { 2089 ClipboardMode_T mode = ClipboardMode_Disabled; 2090 hrc = pMachine->COMGETTER(ClipboardMode)(&mode); H(); 2091 2092 if (mode != ClipboardMode_Disabled) 2093 { 2094 /* Load the service */ 2095 rc = pConsole->mVMMDev->hgcmLoadService("VBoxSharedClipboard", "VBoxSharedClipboard"); 2096 2097 if (RT_FAILURE(rc)) 2098 { 2099 LogRel(("VBoxSharedClipboard is not available. rc = %Rrc\n", rc)); 2100 /* That is not a fatal failure. */ 2101 rc = VINF_SUCCESS; 2102 } 2103 else 2104 { 2105 /* Setup the service. */ 2106 VBOXHGCMSVCPARM parm; 2107 2108 parm.type = VBOX_HGCM_SVC_PARM_32BIT; 2109 2110 switch (mode) 2111 { 2112 default: 2113 case ClipboardMode_Disabled: 2114 { 2115 LogRel(("VBoxSharedClipboard mode: Off\n")); 2116 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_OFF; 2117 break; 2118 } 2119 case ClipboardMode_GuestToHost: 2120 { 2121 LogRel(("VBoxSharedClipboard mode: Guest to Host\n")); 2122 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST; 2123 break; 2124 } 2125 case ClipboardMode_HostToGuest: 2126 { 2127 LogRel(("VBoxSharedClipboard mode: Host to Guest\n")); 2128 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST; 2129 break; 2130 } 2131 case ClipboardMode_Bidirectional: 2132 { 2133 LogRel(("VBoxSharedClipboard mode: Bidirectional\n")); 2134 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL; 2135 break; 2136 } 2137 } 2138 2139 pConsole->mVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm); 2140 2141 Log(("Set VBoxSharedClipboard mode\n")); 2142 } 2143 } 2144 } 2145 2146 #ifdef VBOX_WITH_CROGL 2147 /* 2148 * crOpenGL 2149 */ 2150 { 2151 BOOL fEnabled = false; 2152 hrc = pMachine->COMGETTER(Accelerate3DEnabled)(&fEnabled); H(); 2153 2154 if (fEnabled) 2155 { 2156 /* Load the service */ 2157 rc = pConsole->mVMMDev->hgcmLoadService("VBoxSharedCrOpenGL", "VBoxSharedCrOpenGL"); 2158 if (RT_FAILURE(rc)) 2159 { 2160 LogRel(("Failed to load Shared OpenGL service %Rrc\n", rc)); 2161 /* That is not a fatal failure. */ 2162 rc = VINF_SUCCESS; 2163 } 2164 else 2165 { 2166 LogRel(("Shared crOpenGL service loaded.\n")); 2167 2168 /* Setup the service. */ 2169 VBOXHGCMSVCPARM parm; 2170 parm.type = VBOX_HGCM_SVC_PARM_PTR; 2171 2172 parm.u.pointer.addr = (IConsole*) (Console*) pConsole; 2173 parm.u.pointer.size = sizeof(IConsole *); 2174 2175 rc = pConsole->mVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_CONSOLE, 2176 SHCRGL_CPARMS_SET_CONSOLE, &parm); 2177 if (!RT_SUCCESS(rc)) 2178 AssertMsgFailed(("SHCRGL_HOST_FN_SET_CONSOLE failed with %Rrc\n", rc)); 2179 2180 parm.u.pointer.addr = pVM; 2181 parm.u.pointer.size = sizeof(pVM); 2182 rc = pConsole->mVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_VM, 2183 SHCRGL_CPARMS_SET_VM, &parm); 2184 if (!RT_SUCCESS(rc)) 2185 AssertMsgFailed(("SHCRGL_HOST_FN_SET_VM failed with %Rrc\n", rc)); 2186 } 2187 2188 } 2189 } 2190 #endif 2191 2192 #ifdef VBOX_WITH_GUEST_PROPS 2193 /* 2194 * Guest property service 2195 */ 2196 2197 rc = configGuestProperties(pConsole); 2198 #endif /* VBOX_WITH_GUEST_PROPS defined */ 2199 2200 #ifdef VBOX_WITH_GUEST_CONTROL 2201 /* 2202 * Guest control service 2203 */ 2204 2205 rc = configGuestControl(pConsole); 2206 #endif /* VBOX_WITH_GUEST_CONTROL defined */ 2207 2208 /* 2209 * ACPI 2210 */ 2211 BOOL fACPI; 2212 hrc = biosSettings->COMGETTER(ACPIEnabled)(&fACPI); H(); 2213 if (fACPI) 2214 { 2215 BOOL fCpuHotPlug = false; 2216 BOOL fShowCpu = fOsXGuest; 2217 /* Always show the CPU leafs when we have multiple VCPUs or when the IO-APIC is enabled. 2218 * The Windows SMP kernel needs a CPU leaf or else its idle loop will burn cpu cycles; the 2219 * intelppm driver refuses to register an idle state handler. 2220 */ 2221 if ((cCpus > 1) || fIOAPIC) 2222 fShowCpu = true; 2223 2224 hrc = pMachine->COMGETTER(CPUHotPlugEnabled)(&fCpuHotPlug); H(); 2225 2226 InsertConfigNode(pDevices, "acpi", &pDev); 2227 InsertConfigNode(pDev, "0", &pInst); 2228 InsertConfigInteger(pInst, "Trusted", 1); /* boolean */ 2229 InsertConfigNode(pInst, "Config", &pCfg); 2230 InsertConfigInteger(pCfg, "RamSize", cbRam); 2231 InsertConfigInteger(pCfg, "RamHoleSize", cbRamHole); 2232 InsertConfigInteger(pCfg, "NumCPUs", cCpus); 2233 2234 InsertConfigInteger(pCfg, "IOAPIC", fIOAPIC); 2235 InsertConfigInteger(pCfg, "FdcEnabled", fFdcEnabled); 2236 InsertConfigInteger(pCfg, "HpetEnabled", fHpetEnabled); 2237 InsertConfigInteger(pCfg, "SmcEnabled", fSmcEnabled); 2238 InsertConfigInteger(pCfg, "ShowRtc", fOsXGuest); 2239 if (fOsXGuest && !llBootNics.empty()) 2240 { 2241 BootNic aNic = llBootNics.front(); 2242 uint32_t u32NicPciAddr = (aNic.mPciDev << 16) | aNic.mPciFn; 2243 InsertConfigInteger(pCfg, "NicPciAddress", u32NicPciAddr); 2244 } 2245 InsertConfigInteger(pCfg, "ShowCpu", fShowCpu); 2246 InsertConfigInteger(pCfg, "CpuHotPlug", fCpuHotPlug); 2247 InsertConfigInteger(pInst, "PCIDeviceNo", 7); 2248 Assert(!afPciDeviceNo[7]); 2249 afPciDeviceNo[7] = true; 2250 InsertConfigInteger(pInst, "PCIFunctionNo", 0); 2251 2252 InsertConfigNode(pInst, "LUN#0", &pLunL0); 2253 InsertConfigString(pLunL0, "Driver", "ACPIHost"); 2254 InsertConfigNode(pLunL0, "Config", &pCfg); 2255 2256 /* Attach the dummy CPU drivers */ 2257 for (ULONG iCpuCurr = 1; iCpuCurr < cCpus; iCpuCurr++) 2258 { 2259 BOOL fCpuAttached = true; 2260 2261 if (fCpuHotPlug) 2262 { 2263 hrc = pMachine->GetCPUStatus(iCpuCurr, &fCpuAttached); H(); 2264 } 2265 2266 if (fCpuAttached) 2267 { 2268 InsertConfigNode(pInst, Utf8StrFmt("LUN#%u", iCpuCurr).c_str(), &pLunL0); 2269 InsertConfigString(pLunL0, "Driver", "ACPICpu"); 2270 InsertConfigNode(pLunL0, "Config", &pCfg); 2271 } 2272 } 2273 } 2274 2275 /* 2276 * CFGM overlay handling. 2277 * 2278 * Here we check the extra data entries for CFGM values 2279 * and create the nodes and insert the values on the fly. Existing 2280 * values will be removed and reinserted. CFGM is typed, so by default 2281 * we will guess whether it's a string or an integer (byte arrays are 2282 * not currently supported). It's possible to override this autodetection 2283 * by adding "string:", "integer:" or "bytes:" (future). 2284 * 2285 * We first perform a run on global extra data, then on the machine 2286 * extra data to support global settings with local overrides. 2287 */ 2288 /** @todo add support for removing nodes and byte blobs. */ 2289 SafeArray<BSTR> aGlobalExtraDataKeys; 2290 SafeArray<BSTR> aMachineExtraDataKeys; 2291 /* 2292 * Get the next key 2293 */ 2294 if (FAILED(hrc = virtualBox->GetExtraDataKeys(ComSafeArrayAsOutParam(aGlobalExtraDataKeys)))) 2295 AssertMsgFailed(("VirtualBox::GetExtraDataKeys failed with %Rrc\n", hrc)); 2296 2297 // remember the no. of global values so we can call the correct method below 2298 size_t cGlobalValues = aGlobalExtraDataKeys.size(); 2299 2300 if (FAILED(hrc = pMachine->GetExtraDataKeys(ComSafeArrayAsOutParam(aMachineExtraDataKeys)))) 2301 AssertMsgFailed(("IMachine::GetExtraDataKeys failed with %Rrc\n", hrc)); 2302 2303 // build a combined list from global keys... 2304 std::list<Utf8Str> llExtraDataKeys; 2305 2306 for (size_t i = 0; i < aGlobalExtraDataKeys.size(); ++i) 2307 llExtraDataKeys.push_back(Utf8Str(aGlobalExtraDataKeys[i])); 2308 // ... and machine keys 2309 for (size_t i = 0; i < aMachineExtraDataKeys.size(); ++i) 2310 llExtraDataKeys.push_back(Utf8Str(aMachineExtraDataKeys[i])); 2311 2312 size_t i2 = 0; 2313 for (std::list<Utf8Str>::const_iterator it = llExtraDataKeys.begin(); 2314 it != llExtraDataKeys.end(); 2315 ++it, ++i2) 2316 { 2317 const Utf8Str &strKey = *it; 1804 2318 1805 2319 /* 1806 * Attach the status driver.2320 * We only care about keys starting with "VBoxInternal/" (skip "G:" or "M:") 1807 2321 */ 1808 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK(); 1809 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK(); 1810 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1811 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapUSBLed[0]);RC_CHECK(); 1812 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK(); 1813 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK(); 1814 1815 #ifdef VBOX_WITH_EHCI 1816 BOOL fEhciEnabled; 1817 hrc = USBCtlPtr->COMGETTER(EnabledEhci)(&fEhciEnabled); H(); 1818 if (fEhciEnabled) 1819 { 1820 rc = CFGMR3InsertNode(pDevices, "usb-ehci", &pDev); RC_CHECK(); 1821 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 1822 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1823 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* bool */ RC_CHECK(); 1824 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 11); RC_CHECK(); 1825 Assert(!afPciDeviceNo[11]); 1826 afPciDeviceNo[11] = true; 1827 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK(); 1828 1829 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 1830 rc = CFGMR3InsertString(pLunL0, "Driver", "VUSBRootHub"); RC_CHECK(); 1831 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1832 1833 /* 1834 * Attach the status driver. 1835 */ 1836 rc = CFGMR3InsertNode(pInst, "LUN#999", &pLunL0); RC_CHECK(); 1837 rc = CFGMR3InsertString(pLunL0, "Driver", "MainStatus"); RC_CHECK(); 1838 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1839 rc = CFGMR3InsertInteger(pCfg, "papLeds", (uintptr_t)&pConsole->mapUSBLed[1]);RC_CHECK(); 1840 rc = CFGMR3InsertInteger(pCfg, "First", 0); RC_CHECK(); 1841 rc = CFGMR3InsertInteger(pCfg, "Last", 0); RC_CHECK(); 1842 } 1843 #endif 2322 if (!strKey.startsWith("VBoxInternal/")) 2323 continue; 2324 2325 const char *pszExtraDataKey = strKey.raw() + sizeof("VBoxInternal/") - 1; 2326 2327 // get the value 2328 Bstr strExtraDataValue; 2329 if (i2 < cGlobalValues) 2330 // this is still one of the global values: 2331 hrc = virtualBox->GetExtraData(Bstr(strKey), strExtraDataValue.asOutParam()); 2332 else 2333 hrc = pMachine->GetExtraData(Bstr(strKey), strExtraDataValue.asOutParam()); 2334 if (FAILED(hrc)) 2335 LogRel(("Warning: Cannot get extra data key %s, rc = %Rrc\n", strKey.raw(), hrc)); 1844 2336 1845 2337 /* 1846 * Virtual USB Devices. 2338 * The key will be in the format "Node1/Node2/Value" or simply "Value". 2339 * Split the two and get the node, delete the value and create the node 2340 * if necessary. 1847 2341 */ 1848 PCFGMNODE pUsbDevices = NULL; 1849 rc = CFGMR3InsertNode(pRoot, "USB", &pUsbDevices); RC_CHECK(); 1850 1851 #ifdef VBOX_WITH_USB 1852 { 1853 /* 1854 * Global USB options, currently unused as we'll apply the 2.0 -> 1.1 morphing 1855 * on a per device level now. 1856 */ 1857 rc = CFGMR3InsertNode(pUsbDevices, "USBProxy", &pCfg); RC_CHECK(); 1858 rc = CFGMR3InsertNode(pCfg, "GlobalConfig", &pCfg); RC_CHECK(); 1859 // This globally enables the 2.0 -> 1.1 device morphing of proxied devies to keep windows quiet. 1860 //rc = CFGMR3InsertInteger(pCfg, "Force11Device", true); RC_CHECK(); 1861 // The following breaks stuff, but it makes MSDs work in vista. (I include it here so 1862 // that it's documented somewhere.) Users needing it can use: 1863 // VBoxManage setextradata "myvm" "VBoxInternal/USB/USBProxy/GlobalConfig/Force11PacketSize" 1 1864 //rc = CFGMR3InsertInteger(pCfg, "Force11PacketSize", true); RC_CHECK(); 1865 } 1866 #endif 1867 1868 # if 0 /* Virtual MSD*/ 1869 1870 rc = CFGMR3InsertNode(pUsbDevices, "Msd", &pDev); RC_CHECK(); 1871 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 1872 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1873 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 1874 1875 rc = CFGMR3InsertString(pLunL0, "Driver", "SCSI"); RC_CHECK(); 1876 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1877 1878 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK(); 1879 rc = CFGMR3InsertString(pLunL1, "Driver", "Block"); RC_CHECK(); 1880 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK(); 1881 rc = CFGMR3InsertString(pCfg, "Type", "HardDisk"); RC_CHECK(); 1882 rc = CFGMR3InsertInteger(pCfg, "Mountable", 0); RC_CHECK(); 1883 1884 rc = CFGMR3InsertNode(pLunL1, "AttachedDriver", &pLunL2); RC_CHECK(); 1885 rc = CFGMR3InsertString(pLunL2, "Driver", "VD"); RC_CHECK(); 1886 rc = CFGMR3InsertNode(pLunL2, "Config", &pCfg); RC_CHECK(); 1887 rc = CFGMR3InsertString(pCfg, "Path", "/Volumes/DataHFS/bird/VDIs/linux.vdi"); RC_CHECK(); 1888 rc = CFGMR3InsertString(pCfg, "Format", "VDI"); RC_CHECK(); 1889 # endif 1890 1891 /* Virtual USB Mouse/Tablet */ 1892 PointingHidType_T aPointingHid; 1893 hrc = pMachine->COMGETTER(PointingHidType)(&aPointingHid); H(); 1894 if (aPointingHid == PointingHidType_USBMouse || aPointingHid == PointingHidType_USBTablet) 1895 { 1896 rc = CFGMR3InsertNode(pUsbDevices, "HidMouse", &pDev); RC_CHECK(); 1897 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 1898 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1899 1900 if (aPointingHid == PointingHidType_USBTablet) 1901 { 1902 rc = CFGMR3InsertInteger(pCfg, "Absolute", 1); RC_CHECK(); 1903 } 2342 PCFGMNODE pNode; 2343 const char *pszCFGMValueName = strrchr(pszExtraDataKey, '/'); 2344 if (pszCFGMValueName) 2345 { 2346 /* terminate the node and advance to the value (Utf8Str might not 2347 offically like this but wtf) */ 2348 *(char*)pszCFGMValueName = '\0'; 2349 ++pszCFGMValueName; 2350 2351 /* does the node already exist? */ 2352 pNode = CFGMR3GetChild(pRoot, pszExtraDataKey); 2353 if (pNode) 2354 CFGMR3RemoveValue(pNode, pszCFGMValueName); 1904 2355 else 1905 2356 { 1906 rc = CFGMR3InsertInteger(pCfg, "Absolute", 0); RC_CHECK(); 1907 } 1908 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 1909 rc = CFGMR3InsertString(pLunL0, "Driver", "MouseQueue"); RC_CHECK(); 1910 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1911 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 128); RC_CHECK(); 1912 1913 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK(); 1914 rc = CFGMR3InsertString(pLunL1, "Driver", "MainMouse"); RC_CHECK(); 1915 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK(); 1916 pMouse = pConsole->mMouse; 1917 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pMouse); RC_CHECK(); 1918 } 1919 1920 /* Virtual USB Keyboard */ 1921 KeyboardHidType_T aKbdHid; 1922 hrc = pMachine->COMGETTER(KeyboardHidType)(&aKbdHid); H(); 1923 if (aKbdHid == KeyboardHidType_USBKeyboard) 1924 { 1925 rc = CFGMR3InsertNode(pUsbDevices, "HidKeyboard", &pDev); RC_CHECK(); 1926 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK(); 1927 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK(); 1928 1929 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 1930 rc = CFGMR3InsertString(pLunL0, "Driver", "KeyboardQueue"); RC_CHECK(); 1931 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 1932 rc = CFGMR3InsertInteger(pCfg, "QueueSize", 64); RC_CHECK(); 1933 1934 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK(); 1935 rc = CFGMR3InsertString(pLunL1, "Driver", "MainKeyboard"); RC_CHECK(); 1936 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK(); 1937 pKeyboard = pConsole->mKeyboard; 1938 rc = CFGMR3InsertInteger(pCfg, "Object", (uintptr_t)pKeyboard); RC_CHECK(); 2357 /* create the node */ 2358 rc = CFGMR3InsertNode(pRoot, pszExtraDataKey, &pNode); 2359 if (RT_FAILURE(rc)) 2360 { 2361 AssertLogRelMsgRC(rc, ("failed to insert node '%s'\n", pszExtraDataKey)); 2362 continue; 2363 } 2364 Assert(pNode); 2365 } 2366 } 2367 else 2368 { 2369 /* root value (no node path). */ 2370 pNode = pRoot; 2371 pszCFGMValueName = pszExtraDataKey; 2372 pszExtraDataKey--; 2373 CFGMR3RemoveValue(pNode, pszCFGMValueName); 2374 } 2375 2376 /* 2377 * Now let's have a look at the value. 2378 * Empty strings means that we should remove the value, which we've 2379 * already done above. 2380 */ 2381 Utf8Str strCFGMValueUtf8(strExtraDataValue); 2382 const char *pszCFGMValue = strCFGMValueUtf8.raw(); 2383 if ( pszCFGMValue 2384 && *pszCFGMValue) 2385 { 2386 uint64_t u64Value; 2387 2388 /* check for type prefix first. */ 2389 if (!strncmp(pszCFGMValue, "string:", sizeof("string:") - 1)) 2390 InsertConfigString(pNode, pszCFGMValueName, pszCFGMValue + sizeof("string:") - 1); 2391 else if (!strncmp(pszCFGMValue, "integer:", sizeof("integer:") - 1)) 2392 { 2393 rc = RTStrToUInt64Full(pszCFGMValue + sizeof("integer:") - 1, 0, &u64Value); 2394 if (RT_SUCCESS(rc)) 2395 rc = CFGMR3InsertInteger(pNode, pszCFGMValueName, u64Value); 2396 } 2397 else if (!strncmp(pszCFGMValue, "bytes:", sizeof("bytes:") - 1)) 2398 rc = VERR_NOT_IMPLEMENTED; 2399 /* auto detect type. */ 2400 else if (RT_SUCCESS(RTStrToUInt64Full(pszCFGMValue, 0, &u64Value))) 2401 rc = CFGMR3InsertInteger(pNode, pszCFGMValueName, u64Value); 2402 else 2403 InsertConfigString(pNode, pszCFGMValueName, pszCFGMValue); 2404 AssertLogRelMsgRC(rc, ("failed to insert CFGM value '%s' to key '%s'\n", pszCFGMValue, pszExtraDataKey)); 1939 2405 } 1940 2406 } 1941 2407 } 1942 1943 /* 1944 * Clipboard 1945 */ 2408 catch (ConfigError &x) 1946 2409 { 1947 ClipboardMode_T mode = ClipboardMode_Disabled; 1948 hrc = pMachine->COMGETTER(ClipboardMode)(&mode); H(); 1949 1950 if (mode != ClipboardMode_Disabled) 1951 { 1952 /* Load the service */ 1953 rc = pConsole->mVMMDev->hgcmLoadService("VBoxSharedClipboard", "VBoxSharedClipboard"); 1954 1955 if (RT_FAILURE(rc)) 1956 { 1957 LogRel(("VBoxSharedClipboard is not available. rc = %Rrc\n", rc)); 1958 /* That is not a fatal failure. */ 1959 rc = VINF_SUCCESS; 1960 } 1961 else 1962 { 1963 /* Setup the service. */ 1964 VBOXHGCMSVCPARM parm; 1965 1966 parm.type = VBOX_HGCM_SVC_PARM_32BIT; 1967 1968 switch (mode) 1969 { 1970 default: 1971 case ClipboardMode_Disabled: 1972 { 1973 LogRel(("VBoxSharedClipboard mode: Off\n")); 1974 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_OFF; 1975 break; 1976 } 1977 case ClipboardMode_GuestToHost: 1978 { 1979 LogRel(("VBoxSharedClipboard mode: Guest to Host\n")); 1980 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_GUEST_TO_HOST; 1981 break; 1982 } 1983 case ClipboardMode_HostToGuest: 1984 { 1985 LogRel(("VBoxSharedClipboard mode: Host to Guest\n")); 1986 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_HOST_TO_GUEST; 1987 break; 1988 } 1989 case ClipboardMode_Bidirectional: 1990 { 1991 LogRel(("VBoxSharedClipboard mode: Bidirectional\n")); 1992 parm.u.uint32 = VBOX_SHARED_CLIPBOARD_MODE_BIDIRECTIONAL; 1993 break; 1994 } 1995 } 1996 1997 pConsole->mVMMDev->hgcmHostCall("VBoxSharedClipboard", VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE, 1, &parm); 1998 1999 Log(("Set VBoxSharedClipboard mode\n")); 2000 } 2001 } 2410 // InsertConfig threw something: 2411 return x.m_vrc; 2002 2412 } 2003 2413 2004 #ifdef VBOX_WITH_CROGL2005 /*2006 * crOpenGL2007 */2008 {2009 BOOL fEnabled = false;2010 hrc = pMachine->COMGETTER(Accelerate3DEnabled)(&fEnabled); H();2011 2012 if (fEnabled)2013 {2014 /* Load the service */2015 rc = pConsole->mVMMDev->hgcmLoadService("VBoxSharedCrOpenGL", "VBoxSharedCrOpenGL");2016 if (RT_FAILURE(rc))2017 {2018 LogRel(("Failed to load Shared OpenGL service %Rrc\n", rc));2019 /* That is not a fatal failure. */2020 rc = VINF_SUCCESS;2021 }2022 else2023 {2024 LogRel(("Shared crOpenGL service loaded.\n"));2025 2026 /* Setup the service. */2027 VBOXHGCMSVCPARM parm;2028 parm.type = VBOX_HGCM_SVC_PARM_PTR;2029 2030 parm.u.pointer.addr = (IConsole*) (Console*) pConsole;2031 parm.u.pointer.size = sizeof(IConsole *);2032 2033 rc = pConsole->mVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_CONSOLE,2034 SHCRGL_CPARMS_SET_CONSOLE, &parm);2035 if (!RT_SUCCESS(rc))2036 AssertMsgFailed(("SHCRGL_HOST_FN_SET_CONSOLE failed with %Rrc\n", rc));2037 2038 parm.u.pointer.addr = pVM;2039 parm.u.pointer.size = sizeof(pVM);2040 rc = pConsole->mVMMDev->hgcmHostCall("VBoxSharedCrOpenGL", SHCRGL_HOST_FN_SET_VM,2041 SHCRGL_CPARMS_SET_VM, &parm);2042 if (!RT_SUCCESS(rc))2043 AssertMsgFailed(("SHCRGL_HOST_FN_SET_VM failed with %Rrc\n", rc));2044 }2045 2046 }2047 }2048 #endif2049 2050 #ifdef VBOX_WITH_GUEST_PROPS2051 /*2052 * Guest property service2053 */2054 2055 rc = configGuestProperties(pConsole);2056 #endif /* VBOX_WITH_GUEST_PROPS defined */2057 2058 #ifdef VBOX_WITH_GUEST_CONTROL2059 /*2060 * Guest control service2061 */2062 2063 rc = configGuestControl(pConsole);2064 #endif /* VBOX_WITH_GUEST_CONTROL defined */2065 2066 /*2067 * ACPI2068 */2069 BOOL fACPI;2070 hrc = biosSettings->COMGETTER(ACPIEnabled)(&fACPI); H();2071 if (fACPI)2072 {2073 BOOL fCpuHotPlug = false;2074 BOOL fShowCpu = fOsXGuest;2075 /* Always show the CPU leafs when we have multiple VCPUs or when the IO-APIC is enabled.2076 * The Windows SMP kernel needs a CPU leaf or else its idle loop will burn cpu cycles; the2077 * intelppm driver refuses to register an idle state handler.2078 */2079 if ((cCpus > 1) || fIOAPIC)2080 fShowCpu = true;2081 2082 hrc = pMachine->COMGETTER(CPUHotPlugEnabled)(&fCpuHotPlug); H();2083 2084 rc = CFGMR3InsertNode(pDevices, "acpi", &pDev); RC_CHECK();2085 rc = CFGMR3InsertNode(pDev, "0", &pInst); RC_CHECK();2086 rc = CFGMR3InsertInteger(pInst, "Trusted", 1); /* boolean */ RC_CHECK();2087 rc = CFGMR3InsertNode(pInst, "Config", &pCfg); RC_CHECK();2088 rc = CFGMR3InsertInteger(pCfg, "RamSize", cbRam); RC_CHECK();2089 rc = CFGMR3InsertInteger(pCfg, "RamHoleSize", cbRamHole); RC_CHECK();2090 rc = CFGMR3InsertInteger(pCfg, "NumCPUs", cCpus); RC_CHECK();2091 2092 rc = CFGMR3InsertInteger(pCfg, "IOAPIC", fIOAPIC); RC_CHECK();2093 rc = CFGMR3InsertInteger(pCfg, "FdcEnabled", fFdcEnabled); RC_CHECK();2094 rc = CFGMR3InsertInteger(pCfg, "HpetEnabled", fHpetEnabled); RC_CHECK();2095 rc = CFGMR3InsertInteger(pCfg, "SmcEnabled", fSmcEnabled); RC_CHECK();2096 rc = CFGMR3InsertInteger(pCfg, "ShowRtc", fOsXGuest); RC_CHECK();2097 if (fOsXGuest && !llBootNics.empty())2098 {2099 BootNic aNic = llBootNics.front();2100 uint32_t u32NicPciAddr = (aNic.mPciDev << 16) | aNic.mPciFn;2101 rc = CFGMR3InsertInteger(pCfg, "NicPciAddress", u32NicPciAddr); RC_CHECK();2102 }2103 rc = CFGMR3InsertInteger(pCfg, "ShowCpu", fShowCpu); RC_CHECK();2104 rc = CFGMR3InsertInteger(pCfg, "CpuHotPlug", fCpuHotPlug); RC_CHECK();2105 rc = CFGMR3InsertInteger(pInst, "PCIDeviceNo", 7); RC_CHECK();2106 Assert(!afPciDeviceNo[7]);2107 afPciDeviceNo[7] = true;2108 rc = CFGMR3InsertInteger(pInst, "PCIFunctionNo", 0); RC_CHECK();2109 2110 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();2111 rc = CFGMR3InsertString(pLunL0, "Driver", "ACPIHost"); RC_CHECK();2112 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();2113 2114 /* Attach the dummy CPU drivers */2115 for (ULONG iCpuCurr = 1; iCpuCurr < cCpus; iCpuCurr++)2116 {2117 BOOL fCpuAttached = true;2118 2119 if (fCpuHotPlug)2120 {2121 hrc = pMachine->GetCPUStatus(iCpuCurr, &fCpuAttached); H();2122 }2123 2124 if (fCpuAttached)2125 {2126 rc = CFGMR3InsertNodeF(pInst, &pLunL0, "LUN#%u", iCpuCurr); RC_CHECK();2127 rc = CFGMR3InsertString(pLunL0, "Driver", "ACPICpu"); RC_CHECK();2128 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();2129 }2130 }2131 }2132 2133 2134 /*2135 * CFGM overlay handling.2136 *2137 * Here we check the extra data entries for CFGM values2138 * and create the nodes and insert the values on the fly. Existing2139 * values will be removed and reinserted. CFGM is typed, so by default2140 * we will guess whether it's a string or an integer (byte arrays are2141 * not currently supported). It's possible to override this autodetection2142 * by adding "string:", "integer:" or "bytes:" (future).2143 *2144 * We first perform a run on global extra data, then on the machine2145 * extra data to support global settings with local overrides.2146 *2147 */2148 /** @todo add support for removing nodes and byte blobs. */2149 SafeArray<BSTR> aGlobalExtraDataKeys;2150 SafeArray<BSTR> aMachineExtraDataKeys;2151 /*2152 * Get the next key2153 */2154 if (FAILED(hrc = virtualBox->GetExtraDataKeys(ComSafeArrayAsOutParam(aGlobalExtraDataKeys))))2155 AssertMsgFailed(("VirtualBox::GetExtraDataKeys failed with %Rrc\n", hrc));2156 2157 // remember the no. of global values so we can call the correct method below2158 size_t cGlobalValues = aGlobalExtraDataKeys.size();2159 2160 if (FAILED(hrc = pMachine->GetExtraDataKeys(ComSafeArrayAsOutParam(aMachineExtraDataKeys))))2161 AssertMsgFailed(("IMachine::GetExtraDataKeys failed with %Rrc\n", hrc));2162 2163 // build a combined list from global keys...2164 std::list<Utf8Str> llExtraDataKeys;2165 2166 for (size_t i = 0; i < aGlobalExtraDataKeys.size(); ++i)2167 llExtraDataKeys.push_back(Utf8Str(aGlobalExtraDataKeys[i]));2168 // ... and machine keys2169 for (size_t i = 0; i < aMachineExtraDataKeys.size(); ++i)2170 llExtraDataKeys.push_back(Utf8Str(aMachineExtraDataKeys[i]));2171 2172 size_t i2 = 0;2173 for (std::list<Utf8Str>::const_iterator it = llExtraDataKeys.begin();2174 it != llExtraDataKeys.end();2175 ++it, ++i2)2176 {2177 const Utf8Str &strKey = *it;2178 2179 /*2180 * We only care about keys starting with "VBoxInternal/" (skip "G:" or "M:")2181 */2182 if (!strKey.startsWith("VBoxInternal/"))2183 continue;2184 2185 const char *pszExtraDataKey = strKey.raw() + sizeof("VBoxInternal/") - 1;2186 2187 // get the value2188 Bstr strExtraDataValue;2189 if (i2 < cGlobalValues)2190 // this is still one of the global values:2191 hrc = virtualBox->GetExtraData(Bstr(strKey), strExtraDataValue.asOutParam());2192 else2193 hrc = pMachine->GetExtraData(Bstr(strKey), strExtraDataValue.asOutParam());2194 if (FAILED(hrc))2195 LogRel(("Warning: Cannot get extra data key %s, rc = %Rrc\n", strKey.raw(), hrc));2196 2197 /*2198 * The key will be in the format "Node1/Node2/Value" or simply "Value".2199 * Split the two and get the node, delete the value and create the node2200 * if necessary.2201 */2202 PCFGMNODE pNode;2203 const char *pszCFGMValueName = strrchr(pszExtraDataKey, '/');2204 if (pszCFGMValueName)2205 {2206 /* terminate the node and advance to the value (Utf8Str might not2207 offically like this but wtf) */2208 *(char*)pszCFGMValueName = '\0';2209 ++pszCFGMValueName;2210 2211 /* does the node already exist? */2212 pNode = CFGMR3GetChild(pRoot, pszExtraDataKey);2213 if (pNode)2214 CFGMR3RemoveValue(pNode, pszCFGMValueName);2215 else2216 {2217 /* create the node */2218 rc = CFGMR3InsertNode(pRoot, pszExtraDataKey, &pNode);2219 if (RT_FAILURE(rc))2220 {2221 AssertLogRelMsgRC(rc, ("failed to insert node '%s'\n", pszExtraDataKey));2222 continue;2223 }2224 Assert(pNode);2225 }2226 }2227 else2228 {2229 /* root value (no node path). */2230 pNode = pRoot;2231 pszCFGMValueName = pszExtraDataKey;2232 pszExtraDataKey--;2233 CFGMR3RemoveValue(pNode, pszCFGMValueName);2234 }2235 2236 /*2237 * Now let's have a look at the value.2238 * Empty strings means that we should remove the value, which we've2239 * already done above.2240 */2241 Utf8Str strCFGMValueUtf8(strExtraDataValue);2242 const char *pszCFGMValue = strCFGMValueUtf8.raw();2243 if ( pszCFGMValue2244 && *pszCFGMValue)2245 {2246 uint64_t u64Value;2247 2248 /* check for type prefix first. */2249 if (!strncmp(pszCFGMValue, "string:", sizeof("string:") - 1))2250 rc = CFGMR3InsertString(pNode, pszCFGMValueName, pszCFGMValue + sizeof("string:") - 1);2251 else if (!strncmp(pszCFGMValue, "integer:", sizeof("integer:") - 1))2252 {2253 rc = RTStrToUInt64Full(pszCFGMValue + sizeof("integer:") - 1, 0, &u64Value);2254 if (RT_SUCCESS(rc))2255 rc = CFGMR3InsertInteger(pNode, pszCFGMValueName, u64Value);2256 }2257 else if (!strncmp(pszCFGMValue, "bytes:", sizeof("bytes:") - 1))2258 rc = VERR_NOT_IMPLEMENTED;2259 /* auto detect type. */2260 else if (RT_SUCCESS(RTStrToUInt64Full(pszCFGMValue, 0, &u64Value)))2261 rc = CFGMR3InsertInteger(pNode, pszCFGMValueName, u64Value);2262 else2263 rc = CFGMR3InsertString(pNode, pszCFGMValueName, pszCFGMValue);2264 AssertLogRelMsgRC(rc, ("failed to insert CFGM value '%s' to key '%s'\n", pszCFGMValue, pszExtraDataKey));2265 }2266 }2267 2268 2414 #undef H 2269 #undef RC_CHECK2270 2415 2271 2416 /* Register VM state change handler */ … … 2290 2435 * Ellipsis to va_list wrapper for calling setVMRuntimeErrorCallback. 2291 2436 */ 2292 /*static*/ void Console::setVMRuntimeErrorCallbackF(PVM pVM, void *pvConsole, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...) 2437 /*static*/ 2438 void Console::setVMRuntimeErrorCallbackF(PVM pVM, void *pvConsole, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...) 2293 2439 { 2294 2440 va_list va; … … 2334 2480 DeviceType_T *paLedDevType) 2335 2481 { 2336 int rc = VINF_SUCCESS; 2337 HRESULT hrc; 2338 Bstr bstr; 2339 2340 #define RC_CHECK() AssertMsgReturn(RT_SUCCESS(rc), ("rc=%Rrc\n", rc), rc) 2482 // InsertConfig* throws 2483 try 2484 { 2485 int rc = VINF_SUCCESS; 2486 HRESULT hrc; 2487 Bstr bstr; 2488 2489 // #define RC_CHECK() AssertMsgReturn(RT_SUCCESS(rc), ("rc=%Rrc\n", rc), rc) 2341 2490 #define H() AssertMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_GENERAL_FAILURE) 2342 2491 2343 LONG lDev; 2344 hrc = pMediumAtt->COMGETTER(Device)(&lDev); H(); 2345 LONG lPort; 2346 hrc = pMediumAtt->COMGETTER(Port)(&lPort); H(); 2347 DeviceType_T lType; 2348 hrc = pMediumAtt->COMGETTER(Type)(&lType); H(); 2349 2350 unsigned uLUN; 2351 PCFGMNODE pLunL0 = NULL; 2352 PCFGMNODE pCfg = NULL; 2353 hrc = Console::convertBusPortDeviceToLun(enmBus, lPort, lDev, uLUN); H(); 2354 2355 /* First check if the LUN already exists. */ 2356 pLunL0 = CFGMR3GetChildF(pCtlInst, "LUN#%u", uLUN); 2357 if (pLunL0) 2358 { 2359 if (fAttachDetach) 2492 LONG lDev; 2493 hrc = pMediumAtt->COMGETTER(Device)(&lDev); H(); 2494 LONG lPort; 2495 hrc = pMediumAtt->COMGETTER(Port)(&lPort); H(); 2496 DeviceType_T lType; 2497 hrc = pMediumAtt->COMGETTER(Type)(&lType); H(); 2498 2499 unsigned uLUN; 2500 PCFGMNODE pLunL0 = NULL; 2501 PCFGMNODE pCfg = NULL; 2502 hrc = Console::convertBusPortDeviceToLun(enmBus, lPort, lDev, uLUN); H(); 2503 2504 /* First check if the LUN already exists. */ 2505 pLunL0 = CFGMR3GetChildF(pCtlInst, "LUN#%u", uLUN); 2506 if (pLunL0) 2360 2507 { 2361 if (lType != DeviceType_HardDisk) 2362 { 2363 /* Unmount existing media only for floppy and DVD drives. */ 2364 PPDMIBASE pBase; 2365 rc = PDMR3QueryLun(pVM, pcszDevice, uInstance, uLUN, &pBase); 2366 if (RT_FAILURE(rc)) 2367 { 2368 if (rc == VERR_PDM_LUN_NOT_FOUND || rc == VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN) 2369 rc = VINF_SUCCESS; 2370 AssertRC(rc); 2371 } 2372 else 2373 { 2374 PPDMIMOUNT pIMount = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMOUNT); 2375 AssertReturn(pIMount, VERR_INVALID_POINTER); 2376 2377 /* Unmount the media. */ 2378 rc = pIMount->pfnUnmount(pIMount, fForceUnmount); 2379 if (rc == VERR_PDM_MEDIA_NOT_MOUNTED) 2380 rc = VINF_SUCCESS; 2381 } 2382 } 2383 2384 rc = PDMR3DeviceDetach(pVM, pcszDevice, 0, uLUN, PDM_TACH_FLAGS_NOT_HOT_PLUG); 2385 if (rc == VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN) 2386 rc = VINF_SUCCESS; 2387 RC_CHECK(); 2388 2389 CFGMR3RemoveNode(pLunL0); 2508 if (fAttachDetach) 2509 { 2510 if (lType != DeviceType_HardDisk) 2511 { 2512 /* Unmount existing media only for floppy and DVD drives. */ 2513 PPDMIBASE pBase; 2514 rc = PDMR3QueryLun(pVM, pcszDevice, uInstance, uLUN, &pBase); 2515 if (RT_FAILURE(rc)) 2516 { 2517 if (rc == VERR_PDM_LUN_NOT_FOUND || rc == VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN) 2518 rc = VINF_SUCCESS; 2519 AssertRC(rc); 2520 } 2521 else 2522 { 2523 PPDMIMOUNT pIMount = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMOUNT); 2524 AssertReturn(pIMount, VERR_INVALID_POINTER); 2525 2526 /* Unmount the media. */ 2527 rc = pIMount->pfnUnmount(pIMount, fForceUnmount); 2528 if (rc == VERR_PDM_MEDIA_NOT_MOUNTED) 2529 rc = VINF_SUCCESS; 2530 } 2531 } 2532 2533 rc = PDMR3DeviceDetach(pVM, pcszDevice, 0, uLUN, PDM_TACH_FLAGS_NOT_HOT_PLUG); 2534 if (rc == VERR_PDM_NO_DRIVER_ATTACHED_TO_LUN) 2535 rc = VINF_SUCCESS; 2536 AssertMsgReturn(RT_SUCCESS(rc), ("rc=%Rrc\n", rc), rc); 2537 2538 CFGMR3RemoveNode(pLunL0); 2539 } 2540 else 2541 AssertFailedReturn(VERR_INTERNAL_ERROR); 2390 2542 } 2391 else 2392 AssertFailedReturn(VERR_INTERNAL_ERROR); 2393 } 2394 2395 rc = CFGMR3InsertNodeF(pCtlInst, &pLunL0, "LUN#%u", uLUN); RC_CHECK(); 2396 2397 /* SCSI has a another driver between device and block. */ 2398 if (enmBus == StorageBus_SCSI || enmBus == StorageBus_SAS) 2399 { 2400 rc = CFGMR3InsertString(pLunL0, "Driver", "SCSI"); RC_CHECK(); 2401 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 2402 2403 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK(); 2404 } 2405 2406 ComPtr<IMedium> pMedium; 2407 hrc = pMediumAtt->COMGETTER(Medium)(pMedium.asOutParam()); H(); 2408 2409 if (lType == DeviceType_HardDisk) 2410 { 2411 /* 2412 * Some sanity checks. 2413 */ 2414 ComPtr<IMediumFormat> pMediumFormat; 2415 hrc = pMedium->COMGETTER(MediumFormat)(pMediumFormat.asOutParam()); H(); 2416 ULONG uCaps; 2417 hrc = pMediumFormat->COMGETTER(Capabilities)(&uCaps); H(); 2418 if (uCaps & MediumFormatCapabilities_File) 2543 2544 InsertConfigNode(pCtlInst, Utf8StrFmt("LUN#%u", uLUN).c_str(), &pLunL0); 2545 2546 /* SCSI has a another driver between device and block. */ 2547 if (enmBus == StorageBus_SCSI || enmBus == StorageBus_SAS) 2419 2548 { 2420 Bstr strFile; 2421 hrc = pMedium->COMGETTER(Location)(strFile.asOutParam()); H(); 2422 Utf8Str utfFile = Utf8Str(strFile); 2423 Bstr strSnap; 2424 ComPtr<IMachine> pMachine = machine(); 2425 hrc = pMachine->COMGETTER(SnapshotFolder)(strSnap.asOutParam()); H(); 2426 Utf8Str utfSnap = Utf8Str(strSnap); 2427 RTFSTYPE enmFsTypeFile = RTFSTYPE_UNKNOWN; 2428 RTFSTYPE enmFsTypeSnap = RTFSTYPE_UNKNOWN; 2429 int rc2 = RTFsQueryType(utfFile.c_str(), &enmFsTypeFile); 2430 AssertMsgRCReturn(rc2, ("Querying the file type of '%s' failed!\n", utfFile.c_str()), rc2); 2431 /* Ignore the error code. On error, the file system type is still 'unknown' so 2432 * none of the following pathes is taken. This can happen for new VMs which 2433 * still don't have a snapshot folder. */ 2434 (void)RTFsQueryType(utfSnap.c_str(), &enmFsTypeSnap); 2435 LogRel(("File system of '%s' is %s\n", utfFile.c_str(), RTFsTypeName(enmFsTypeFile))); 2436 ULONG64 u64Size; 2437 hrc = pMedium->COMGETTER(LogicalSize)(&u64Size); H(); 2438 u64Size *= _1M; 2549 InsertConfigString(pLunL0, "Driver", "SCSI"); 2550 InsertConfigNode(pLunL0, "Config", &pCfg); 2551 2552 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0); 2553 } 2554 2555 ComPtr<IMedium> pMedium; 2556 hrc = pMediumAtt->COMGETTER(Medium)(pMedium.asOutParam()); H(); 2557 2558 if (lType == DeviceType_HardDisk) 2559 { 2560 /* 2561 * Some sanity checks. 2562 */ 2563 ComPtr<IMediumFormat> pMediumFormat; 2564 hrc = pMedium->COMGETTER(MediumFormat)(pMediumFormat.asOutParam()); H(); 2565 ULONG uCaps; 2566 hrc = pMediumFormat->COMGETTER(Capabilities)(&uCaps); H(); 2567 if (uCaps & MediumFormatCapabilities_File) 2568 { 2569 Bstr strFile; 2570 hrc = pMedium->COMGETTER(Location)(strFile.asOutParam()); H(); 2571 Utf8Str utfFile = Utf8Str(strFile); 2572 Bstr strSnap; 2573 ComPtr<IMachine> pMachine = machine(); 2574 hrc = pMachine->COMGETTER(SnapshotFolder)(strSnap.asOutParam()); H(); 2575 Utf8Str utfSnap = Utf8Str(strSnap); 2576 RTFSTYPE enmFsTypeFile = RTFSTYPE_UNKNOWN; 2577 RTFSTYPE enmFsTypeSnap = RTFSTYPE_UNKNOWN; 2578 int rc2 = RTFsQueryType(utfFile.c_str(), &enmFsTypeFile); 2579 AssertMsgRCReturn(rc2, ("Querying the file type of '%s' failed!\n", utfFile.c_str()), rc2); 2580 /* Ignore the error code. On error, the file system type is still 'unknown' so 2581 * none of the following pathes is taken. This can happen for new VMs which 2582 * still don't have a snapshot folder. */ 2583 (void)RTFsQueryType(utfSnap.c_str(), &enmFsTypeSnap); 2584 LogRel(("File system of '%s' is %s\n", utfFile.c_str(), RTFsTypeName(enmFsTypeFile))); 2585 ULONG64 u64Size; 2586 hrc = pMedium->COMGETTER(LogicalSize)(&u64Size); H(); 2587 u64Size *= _1M; 2439 2588 #ifdef RT_OS_WINDOWS 2440 if ( enmFsTypeFile == RTFSTYPE_FAT2441 && u64Size >= _4G)2442 {2443 const char *pszUnit;2444 uint64_t u64Print = formatDiskSize(u64Size, &pszUnit);2445 setVMRuntimeErrorCallbackF(pVM, this, 0,2446 "FatPartitionDetected",2447 N_("The medium '%ls' has a logical size of %RU64%s "2448 "but the file system the medium is located on seems "2449 "to be FAT(32) which cannot handle files bigger than 4GB.\n"2450 "We strongly recommend to put all your virtual disk images and "2451 "the snapshot folder onto an NTFS partition"),2452 strFile.raw(), u64Print, pszUnit);2453 }2589 if ( enmFsTypeFile == RTFSTYPE_FAT 2590 && u64Size >= _4G) 2591 { 2592 const char *pszUnit; 2593 uint64_t u64Print = formatDiskSize(u64Size, &pszUnit); 2594 setVMRuntimeErrorCallbackF(pVM, this, 0, 2595 "FatPartitionDetected", 2596 N_("The medium '%ls' has a logical size of %RU64%s " 2597 "but the file system the medium is located on seems " 2598 "to be FAT(32) which cannot handle files bigger than 4GB.\n" 2599 "We strongly recommend to put all your virtual disk images and " 2600 "the snapshot folder onto an NTFS partition"), 2601 strFile.raw(), u64Print, pszUnit); 2602 } 2454 2603 #else /* !RT_OS_WINDOWS */ 2455 if ( enmFsTypeFile == RTFSTYPE_FAT 2456 || enmFsTypeFile == RTFSTYPE_EXT 2457 || enmFsTypeFile == RTFSTYPE_EXT2 2458 || enmFsTypeFile == RTFSTYPE_EXT3 2459 || enmFsTypeFile == RTFSTYPE_EXT4) 2460 { 2461 RTFILE file; 2462 rc = RTFileOpen(&file, utfFile.c_str(), RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); 2463 if (RT_SUCCESS(rc)) 2464 { 2465 RTFOFF maxSize; 2466 /* Careful: This function will work only on selected local file systems! */ 2467 rc = RTFileGetMaxSizeEx(file, &maxSize); 2468 RTFileClose(file); 2469 if ( RT_SUCCESS(rc) 2470 && maxSize > 0 2471 && u64Size > (ULONG64)maxSize) 2604 if ( enmFsTypeFile == RTFSTYPE_FAT 2605 || enmFsTypeFile == RTFSTYPE_EXT 2606 || enmFsTypeFile == RTFSTYPE_EXT2 2607 || enmFsTypeFile == RTFSTYPE_EXT3 2608 || enmFsTypeFile == RTFSTYPE_EXT4) 2609 { 2610 RTFILE file; 2611 rc = RTFileOpen(&file, utfFile.c_str(), RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE); 2612 if (RT_SUCCESS(rc)) 2472 2613 { 2473 const char *pszUnitSiz; 2474 const char *pszUnitMax; 2475 uint64_t u64PrintSiz = formatDiskSize(u64Size, &pszUnitSiz); 2476 uint64_t u64PrintMax = formatDiskSize(maxSize, &pszUnitMax); 2477 setVMRuntimeErrorCallbackF(pVM, this, 0, 2478 "FatPartitionDetected", /* <= not exact but ... */ 2479 N_("The medium '%ls' has a logical size of %RU64%s " 2480 "but the file system the medium is located on can " 2481 "only handle files up to %RU64%s in theory.\n" 2482 "We strongly recommend to put all your virtual disk " 2483 "images and the snapshot folder onto a proper " 2484 "file system (e.g. ext3) with a sufficient size"), 2485 strFile.raw(), u64PrintSiz, pszUnitSiz, u64PrintMax, pszUnitMax); 2614 RTFOFF maxSize; 2615 /* Careful: This function will work only on selected local file systems! */ 2616 rc = RTFileGetMaxSizeEx(file, &maxSize); 2617 RTFileClose(file); 2618 if ( RT_SUCCESS(rc) 2619 && maxSize > 0 2620 && u64Size > (ULONG64)maxSize) 2621 { 2622 const char *pszUnitSiz; 2623 const char *pszUnitMax; 2624 uint64_t u64PrintSiz = formatDiskSize(u64Size, &pszUnitSiz); 2625 uint64_t u64PrintMax = formatDiskSize(maxSize, &pszUnitMax); 2626 setVMRuntimeErrorCallbackF(pVM, this, 0, 2627 "FatPartitionDetected", /* <= not exact but ... */ 2628 N_("The medium '%ls' has a logical size of %RU64%s " 2629 "but the file system the medium is located on can " 2630 "only handle files up to %RU64%s in theory.\n" 2631 "We strongly recommend to put all your virtual disk " 2632 "images and the snapshot folder onto a proper " 2633 "file system (e.g. ext3) with a sufficient size"), 2634 strFile.raw(), u64PrintSiz, pszUnitSiz, u64PrintMax, pszUnitMax); 2635 } 2486 2636 } 2487 2637 } 2488 }2489 2638 #endif /* !RT_OS_WINDOWS */ 2490 2639 2491 /*2492 * Snapshot folder:2493 * Here we test only for a FAT partition as we had to create a dummy file otherwise2494 */2495 if ( enmFsTypeSnap == RTFSTYPE_FAT2496 && u64Size >= _4G2497 && !mfSnapshotFolderSizeWarningShown)2498 {2499 const char *pszUnit;2500 uint64_t u64Print = formatDiskSize(u64Size, &pszUnit);2501 setVMRuntimeErrorCallbackF(pVM, this, 0,2502 "FatPartitionDetected",2640 /* 2641 * Snapshot folder: 2642 * Here we test only for a FAT partition as we had to create a dummy file otherwise 2643 */ 2644 if ( enmFsTypeSnap == RTFSTYPE_FAT 2645 && u64Size >= _4G 2646 && !mfSnapshotFolderSizeWarningShown) 2647 { 2648 const char *pszUnit; 2649 uint64_t u64Print = formatDiskSize(u64Size, &pszUnit); 2650 setVMRuntimeErrorCallbackF(pVM, this, 0, 2651 "FatPartitionDetected", 2503 2652 #ifdef RT_OS_WINDOWS 2504 N_("The snapshot folder of this VM '%ls' seems to be located on " 2505 "a FAT(32) file system. The logical size of the medium '%ls' " 2506 "(%RU64%s) is bigger than the maximum file size this file " 2507 "system can handle (4GB).\n" 2508 "We strongly recommend to put all your virtual disk images and " 2509 "the snapshot folder onto an NTFS partition"), 2510 #else 2511 N_("The snapshot folder of this VM '%ls' seems to be located on " 2653 N_("The snapshot folder of this VM '%ls' seems to be located on " 2512 2654 "a FAT(32) file system. The logical size of the medium '%ls' " 2513 2655 "(%RU64%s) is bigger than the maximum file size this file " 2514 2656 "system can handle (4GB).\n" 2515 2657 "We strongly recommend to put all your virtual disk images and " 2516 "the snapshot folder onto a proper file system (e.g. ext3)"), 2658 "the snapshot folder onto an NTFS partition"), 2659 #else 2660 N_("The snapshot folder of this VM '%ls' seems to be located on " 2661 "a FAT(32) file system. The logical size of the medium '%ls' " 2662 "(%RU64%s) is bigger than the maximum file size this file " 2663 "system can handle (4GB).\n" 2664 "We strongly recommend to put all your virtual disk images and " 2665 "the snapshot folder onto a proper file system (e.g. ext3)"), 2517 2666 #endif 2518 strSnap.raw(), strFile.raw(), u64Print, pszUnit);2519 /* Show this particular warning only once */2520 mfSnapshotFolderSizeWarningShown = true;2521 }2667 strSnap.raw(), strFile.raw(), u64Print, pszUnit); 2668 /* Show this particular warning only once */ 2669 mfSnapshotFolderSizeWarningShown = true; 2670 } 2522 2671 2523 2672 #ifdef RT_OS_LINUX 2524 /*2525 * Ext4 bug: Check if the host I/O cache is disabled and the disk image is located2526 * on an ext4 partition. Later we have to check the Linux kernel version!2527 * This bug apparently applies to the XFS file system as well.2528 */2529 if ( (uCaps & MediumFormatCapabilities_Asynchronous)2530 && !fUseHostIOCache2531 && ( enmFsTypeFile == RTFSTYPE_EXT42532 || enmFsTypeFile == RTFSTYPE_XFS))2533 {2534 setVMRuntimeErrorCallbackF(pVM, this, 0,2535 "Ext4PartitionDetected",2536 N_("The host I/O cache for at least one controller is disabled "2537 "and the medium '%ls' for this VM "2538 "is located on an %s partition. There is a known Linux "2539 "kernel bug which can lead to the corruption of the virtual "2540 "disk image under these conditions.\n"2541 "Either enable the host I/O cache permanently in the VM "2542 "settings or put the disk image and the snapshot folder "2543 "onto a different file system.\n"2544 "The host I/O cache will now be enabled for this medium"),2545 strFile.raw(), enmFsTypeFile == RTFSTYPE_EXT4 ? "ext4" : "xfs");2546 fUseHostIOCache = true;2547 }2548 else if ( (uCaps & MediumFormatCapabilities_Asynchronous)2549 && !fUseHostIOCache2550 && ( enmFsTypeSnap == RTFSTYPE_EXT42551 || enmFsTypeSnap == RTFSTYPE_XFS)2552 && !mfSnapshotFolderExt4WarningShown)2553 {2554 setVMRuntimeErrorCallbackF(pVM, this, 0,2555 "Ext4PartitionDetected",2556 N_("The host I/O cache for at least one controller is disabled "2557 "and the snapshot folder for this VM "2558 "is located on an %s partition. There is a known Linux "2559 "kernel bug which can lead to the corruption of the virtual "2560 "disk image under these conditions.\n"2561 "Either enable the host I/O cache permanently in the VM "2562 "settings or put the disk image and the snapshot folder "2563 "onto a different file system.\n"2564 "The host I/O cache will now be enabled for this medium"),2565 enmFsTypeSnap == RTFSTYPE_EXT4 ? "ext4" : "xfs");2566 fUseHostIOCache = true;2567 mfSnapshotFolderExt4WarningShown = true;2568 }2673 /* 2674 * Ext4 bug: Check if the host I/O cache is disabled and the disk image is located 2675 * on an ext4 partition. Later we have to check the Linux kernel version! 2676 * This bug apparently applies to the XFS file system as well. 2677 */ 2678 if ( (uCaps & MediumFormatCapabilities_Asynchronous) 2679 && !fUseHostIOCache 2680 && ( enmFsTypeFile == RTFSTYPE_EXT4 2681 || enmFsTypeFile == RTFSTYPE_XFS)) 2682 { 2683 setVMRuntimeErrorCallbackF(pVM, this, 0, 2684 "Ext4PartitionDetected", 2685 N_("The host I/O cache for at least one controller is disabled " 2686 "and the medium '%ls' for this VM " 2687 "is located on an %s partition. There is a known Linux " 2688 "kernel bug which can lead to the corruption of the virtual " 2689 "disk image under these conditions.\n" 2690 "Either enable the host I/O cache permanently in the VM " 2691 "settings or put the disk image and the snapshot folder " 2692 "onto a different file system.\n" 2693 "The host I/O cache will now be enabled for this medium"), 2694 strFile.raw(), enmFsTypeFile == RTFSTYPE_EXT4 ? "ext4" : "xfs"); 2695 fUseHostIOCache = true; 2696 } 2697 else if ( (uCaps & MediumFormatCapabilities_Asynchronous) 2698 && !fUseHostIOCache 2699 && ( enmFsTypeSnap == RTFSTYPE_EXT4 2700 || enmFsTypeSnap == RTFSTYPE_XFS) 2701 && !mfSnapshotFolderExt4WarningShown) 2702 { 2703 setVMRuntimeErrorCallbackF(pVM, this, 0, 2704 "Ext4PartitionDetected", 2705 N_("The host I/O cache for at least one controller is disabled " 2706 "and the snapshot folder for this VM " 2707 "is located on an %s partition. There is a known Linux " 2708 "kernel bug which can lead to the corruption of the virtual " 2709 "disk image under these conditions.\n" 2710 "Either enable the host I/O cache permanently in the VM " 2711 "settings or put the disk image and the snapshot folder " 2712 "onto a different file system.\n" 2713 "The host I/O cache will now be enabled for this medium"), 2714 enmFsTypeSnap == RTFSTYPE_EXT4 ? "ext4" : "xfs"); 2715 fUseHostIOCache = true; 2716 mfSnapshotFolderExt4WarningShown = true; 2717 } 2569 2718 #endif 2719 } 2570 2720 } 2721 2722 BOOL fPassthrough; 2723 hrc = pMediumAtt->COMGETTER(Passthrough)(&fPassthrough); H(); 2724 rc = configMedium(pLunL0, 2725 !!fPassthrough, 2726 lType, 2727 fUseHostIOCache, 2728 fSetupMerge, 2729 uMergeSource, 2730 uMergeTarget, 2731 pMedium, 2732 aMachineState, 2733 phrc); 2734 if (RT_FAILURE(rc)) 2735 return rc; 2736 2737 if (fAttachDetach) 2738 { 2739 /* Attach the new driver. */ 2740 rc = PDMR3DeviceAttach(pVM, pcszDevice, 0, uLUN, 2741 PDM_TACH_FLAGS_NOT_HOT_PLUG, NULL /*ppBase*/); 2742 AssertMsgReturn(RT_SUCCESS(rc), ("rc=%Rrc\n", rc), rc); 2743 2744 /* There is no need to handle removable medium mounting, as we 2745 * unconditionally replace everthing including the block driver level. 2746 * This means the new medium will be picked up automatically. */ 2747 } 2748 2749 if (paLedDevType) 2750 paLedDevType[uLUN] = lType; 2571 2751 } 2572 2573 BOOL fPassthrough; 2574 hrc = pMediumAtt->COMGETTER(Passthrough)(&fPassthrough); H(); 2575 rc = configMedium(pLunL0, 2576 !!fPassthrough, 2577 lType, 2578 fUseHostIOCache, 2579 fSetupMerge, 2580 uMergeSource, 2581 uMergeTarget, 2582 pMedium, 2583 aMachineState, 2584 phrc); RC_CHECK(); 2585 2586 if (fAttachDetach) 2752 catch (ConfigError &x) 2587 2753 { 2588 /* Attach the new driver. */ 2589 rc = PDMR3DeviceAttach(pVM, pcszDevice, 0, uLUN, 2590 PDM_TACH_FLAGS_NOT_HOT_PLUG, NULL /*ppBase*/); RC_CHECK(); 2591 2592 /* There is no need to handle removable medium mounting, as we 2593 * unconditionally replace everthing including the block driver level. 2594 * This means the new medium will be picked up automatically. */ 2754 // InsertConfig threw something: 2755 return x.m_vrc; 2595 2756 } 2596 2757 2597 if (paLedDevType)2598 paLedDevType[uLUN] = lType;2599 2600 2758 #undef H 2601 #undef RC_CHECK2602 2759 2603 2760 return VINF_SUCCESS;; … … 2615 2772 HRESULT *phrc) 2616 2773 { 2617 int rc = VINF_SUCCESS; 2618 HRESULT hrc; 2619 Bstr bstr; 2620 2621 #define RC_CHECK() AssertMsgReturn(RT_SUCCESS(rc), ("rc=%Rrc\n", rc), rc) 2774 // InsertConfig* throws 2775 try 2776 { 2777 int rc = VINF_SUCCESS; 2778 HRESULT hrc; 2779 Bstr bstr; 2780 2622 2781 #define H() AssertMsgReturnStmt(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), if (phrc) *phrc = hrc, VERR_GENERAL_FAILURE) 2623 2782 2624 PCFGMNODE pLunL1 = NULL; 2625 PCFGMNODE pCfg = NULL; 2626 2627 BOOL fHostDrive = FALSE; 2628 if (pMedium) 2629 { 2630 hrc = pMedium->COMGETTER(HostDrive)(&fHostDrive); H(); 2631 } 2632 2633 if (fHostDrive) 2634 { 2635 Assert(pMedium); 2636 if (enmType == DeviceType_DVD) 2637 { 2638 rc = CFGMR3InsertString(pLunL0, "Driver", "HostDVD"); RC_CHECK(); 2639 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 2640 2641 hrc = pMedium->COMGETTER(Location)(bstr.asOutParam()); H(); 2642 rc = CFGMR3InsertStringW(pCfg, "Path", bstr.raw()); RC_CHECK(); 2643 2644 rc = CFGMR3InsertInteger(pCfg, "Passthrough", fPassthrough); RC_CHECK(); 2645 } 2646 else if (enmType == DeviceType_Floppy) 2647 { 2648 rc = CFGMR3InsertString(pLunL0, "Driver", "HostFloppy"); RC_CHECK(); 2649 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 2650 2651 hrc = pMedium->COMGETTER(Location)(bstr.asOutParam()); H(); 2652 rc = CFGMR3InsertStringW(pCfg, "Path", bstr.raw()); RC_CHECK(); 2653 } 2654 } 2655 else 2656 { 2657 rc = CFGMR3InsertString(pLunL0, "Driver", "Block"); RC_CHECK(); 2658 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 2659 switch (enmType) 2660 { 2661 case DeviceType_DVD: 2662 rc = CFGMR3InsertString(pCfg, "Type", "DVD"); RC_CHECK(); 2663 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK(); 2664 break; 2665 case DeviceType_Floppy: 2666 rc = CFGMR3InsertString(pCfg, "Type", "Floppy 1.44"); RC_CHECK(); 2667 rc = CFGMR3InsertInteger(pCfg, "Mountable", 1); RC_CHECK(); 2668 break; 2669 case DeviceType_HardDisk: 2670 default: 2671 rc = CFGMR3InsertString(pCfg, "Type", "HardDisk"); RC_CHECK(); 2672 rc = CFGMR3InsertInteger(pCfg, "Mountable", 0); RC_CHECK(); 2673 } 2674 2675 if ( pMedium 2676 && ( enmType == DeviceType_DVD 2677 || enmType == DeviceType_Floppy 2678 )) 2679 { 2680 // if this medium represents an ISO image and this image is inaccessible, 2681 // the ignore it instead of causing a failure; this can happen when we 2682 // restore a VM state and the ISO has disappeared, e.g. because the Guest 2683 // Additions were mounted and the user upgraded VirtualBox. Previously 2684 // we failed on startup, but that's not good because the only way out then 2685 // would be to discard the VM state... 2686 MediumState_T mediumState; 2687 rc = pMedium->RefreshState(&mediumState); 2688 RC_CHECK(); 2689 if (mediumState == MediumState_Inaccessible) 2690 { 2691 Bstr loc; 2692 rc = pMedium->COMGETTER(Location)(loc.asOutParam()); 2693 if (FAILED(rc)) return rc; 2694 2695 setVMRuntimeErrorCallbackF(mpVM, 2696 this, 2697 0, 2698 "DvdOrFloppyImageInaccessible", 2699 "The image file '%ls' is inaccessible and is being ignored. Please select a different image file for the virtual %s drive.", 2700 loc.raw(), 2701 (enmType == DeviceType_DVD) ? "DVD" : "floppy"); 2702 pMedium = NULL; 2703 } 2704 } 2705 2783 PCFGMNODE pLunL1 = NULL; 2784 PCFGMNODE pCfg = NULL; 2785 2786 BOOL fHostDrive = FALSE; 2706 2787 if (pMedium) 2707 2788 { 2708 /* Start with length of parent chain, as the list is reversed */ 2709 unsigned uImage = 0; 2710 IMedium *pTmp = pMedium; 2711 while (pTmp) 2712 { 2713 uImage++; 2714 hrc = pTmp->COMGETTER(Parent)(&pTmp); H(); 2715 } 2716 /* Index of last image */ 2717 uImage--; 2789 hrc = pMedium->COMGETTER(HostDrive)(&fHostDrive); H(); 2790 } 2791 2792 if (fHostDrive) 2793 { 2794 Assert(pMedium); 2795 if (enmType == DeviceType_DVD) 2796 { 2797 InsertConfigString(pLunL0, "Driver", "HostDVD"); 2798 InsertConfigNode(pLunL0, "Config", &pCfg); 2799 2800 hrc = pMedium->COMGETTER(Location)(bstr.asOutParam()); H(); 2801 InsertConfigString(pCfg, "Path", bstr); 2802 2803 InsertConfigInteger(pCfg, "Passthrough", fPassthrough); 2804 } 2805 else if (enmType == DeviceType_Floppy) 2806 { 2807 InsertConfigString(pLunL0, "Driver", "HostFloppy"); 2808 InsertConfigNode(pLunL0, "Config", &pCfg); 2809 2810 hrc = pMedium->COMGETTER(Location)(bstr.asOutParam()); H(); 2811 InsertConfigString(pCfg, "Path", bstr); 2812 } 2813 } 2814 else 2815 { 2816 InsertConfigString(pLunL0, "Driver", "Block"); 2817 InsertConfigNode(pLunL0, "Config", &pCfg); 2818 switch (enmType) 2819 { 2820 case DeviceType_DVD: 2821 InsertConfigString(pCfg, "Type", "DVD"); 2822 InsertConfigInteger(pCfg, "Mountable", 1); 2823 break; 2824 case DeviceType_Floppy: 2825 InsertConfigString(pCfg, "Type", "Floppy 1.44"); 2826 InsertConfigInteger(pCfg, "Mountable", 1); 2827 break; 2828 case DeviceType_HardDisk: 2829 default: 2830 InsertConfigString(pCfg, "Type", "HardDisk"); 2831 InsertConfigInteger(pCfg, "Mountable", 0); 2832 } 2833 2834 if ( pMedium 2835 && ( enmType == DeviceType_DVD 2836 || enmType == DeviceType_Floppy 2837 )) 2838 { 2839 // if this medium represents an ISO image and this image is inaccessible, 2840 // the ignore it instead of causing a failure; this can happen when we 2841 // restore a VM state and the ISO has disappeared, e.g. because the Guest 2842 // Additions were mounted and the user upgraded VirtualBox. Previously 2843 // we failed on startup, but that's not good because the only way out then 2844 // would be to discard the VM state... 2845 MediumState_T mediumState; 2846 rc = pMedium->RefreshState(&mediumState); 2847 AssertMsgReturn(RT_SUCCESS(rc), ("rc=%Rrc\n", rc), rc); 2848 2849 if (mediumState == MediumState_Inaccessible) 2850 { 2851 Bstr loc; 2852 rc = pMedium->COMGETTER(Location)(loc.asOutParam()); 2853 if (FAILED(rc)) return rc; 2854 2855 setVMRuntimeErrorCallbackF(mpVM, 2856 this, 2857 0, 2858 "DvdOrFloppyImageInaccessible", 2859 "The image file '%ls' is inaccessible and is being ignored. Please select a different image file for the virtual %s drive.", 2860 loc.raw(), 2861 (enmType == DeviceType_DVD) ? "DVD" : "floppy"); 2862 pMedium = NULL; 2863 } 2864 } 2865 2866 if (pMedium) 2867 { 2868 /* Start with length of parent chain, as the list is reversed */ 2869 unsigned uImage = 0; 2870 IMedium *pTmp = pMedium; 2871 while (pTmp) 2872 { 2873 uImage++; 2874 hrc = pTmp->COMGETTER(Parent)(&pTmp); H(); 2875 } 2876 /* Index of last image */ 2877 uImage--; 2718 2878 2719 2879 #if 0 /* Enable for I/O debugging */ 2720 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();2721 rc = CFGMR3InsertString(pLunL0, "Driver", "DiskIntegrity"); RC_CHECK();2722 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();2723 rc = CFGMR3InsertInteger(pCfg, "CheckConsistency", 0); RC_CHECK();2724 rc = CFGMR3InsertInteger(pCfg, "CheckDoubleCompletions", 1); RC_CHECK();2880 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0); 2881 InsertConfigString(pLunL0, "Driver", "DiskIntegrity"); 2882 InsertConfigNode(pLunL0, "Config", &pCfg); 2883 InsertConfigInteger(pCfg, "CheckConsistency", 0); 2884 InsertConfigInteger(pCfg, "CheckDoubleCompletions", 1); 2725 2885 #endif 2726 2886 2727 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1); RC_CHECK(); 2728 rc = CFGMR3InsertString(pLunL1, "Driver", "VD"); RC_CHECK(); 2729 rc = CFGMR3InsertNode(pLunL1, "Config", &pCfg); RC_CHECK(); 2730 2731 hrc = pMedium->COMGETTER(Location)(bstr.asOutParam()); H(); 2732 rc = CFGMR3InsertStringW(pCfg, "Path", bstr.raw()); RC_CHECK(); 2733 2734 hrc = pMedium->COMGETTER(Format)(bstr.asOutParam()); H(); 2735 rc = CFGMR3InsertStringW(pCfg, "Format", bstr.raw()); RC_CHECK(); 2736 2737 /* DVDs are always readonly */ 2738 if (enmType == DeviceType_DVD) 2739 { 2740 rc = CFGMR3InsertInteger(pCfg, "ReadOnly", 1); RC_CHECK(); 2741 } 2742 2743 /* Start without exclusive write access to the images. */ 2744 /** @todo Live Migration: I don't quite like this, we risk screwing up when 2745 * we're resuming the VM if some 3rd dude have any of the VDIs open 2746 * with write sharing denied. However, if the two VMs are sharing a 2747 * image it really is necessary.... 2748 * 2749 * So, on the "lock-media" command, the target teleporter should also 2750 * make DrvVD undo TempReadOnly. It gets interesting if we fail after 2751 * that. Grumble. */ 2752 else if (aMachineState == MachineState_TeleportingIn) 2753 { 2754 rc = CFGMR3InsertInteger(pCfg, "TempReadOnly", 1); RC_CHECK(); 2755 } 2756 2757 if (!fUseHostIOCache) 2758 { 2759 rc = CFGMR3InsertInteger(pCfg, "UseNewIo", 1); RC_CHECK(); 2760 } 2761 2762 if (fSetupMerge) 2763 { 2764 rc = CFGMR3InsertInteger(pCfg, "SetupMerge", 1); RC_CHECK(); 2765 if (uImage == uMergeSource) 2766 { 2767 rc = CFGMR3InsertInteger(pCfg, "MergeSource", 1); RC_CHECK(); 2768 } 2769 else if (uImage == uMergeTarget) 2770 { 2771 rc = CFGMR3InsertInteger(pCfg, "MergeTarget", 1); RC_CHECK(); 2772 } 2773 } 2774 2775 /* Pass all custom parameters. */ 2776 bool fHostIP = true; 2777 SafeArray<BSTR> names; 2778 SafeArray<BSTR> values; 2779 hrc = pMedium->GetProperties(NULL, 2780 ComSafeArrayAsOutParam(names), 2781 ComSafeArrayAsOutParam(values)); H(); 2782 2783 if (names.size() != 0) 2784 { 2785 PCFGMNODE pVDC; 2786 rc = CFGMR3InsertNode(pCfg, "VDConfig", &pVDC); RC_CHECK(); 2787 for (size_t ii = 0; ii < names.size(); ++ii) 2788 { 2789 if (values[ii] && *values[ii]) 2790 { 2791 Utf8Str name = names[ii]; 2792 Utf8Str value = values[ii]; 2793 rc = CFGMR3InsertString(pVDC, name.c_str(), value.c_str()); RC_CHECK(); 2794 if ( name.compare("HostIPStack") == 0 2795 && value.compare("0") == 0) 2796 fHostIP = false; 2797 } 2798 } 2799 } 2800 2801 /* Create an inversed list of parents. */ 2802 uImage--; 2803 IMedium *pParentMedium = pMedium; 2804 for (PCFGMNODE pParent = pCfg;; uImage--) 2805 { 2806 hrc = pParentMedium->COMGETTER(Parent)(&pMedium); H(); 2807 if (!pMedium) 2808 break; 2809 2810 PCFGMNODE pCur; 2811 rc = CFGMR3InsertNode(pParent, "Parent", &pCur); RC_CHECK(); 2812 hrc = pMedium->COMGETTER(Location)(bstr.asOutParam()); H(); 2813 rc = CFGMR3InsertStringW(pCur, "Path", bstr.raw()); RC_CHECK(); 2814 2815 hrc = pMedium->COMGETTER(Format)(bstr.asOutParam()); H(); 2816 rc = CFGMR3InsertStringW(pCur, "Format", bstr.raw()); RC_CHECK(); 2887 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL1); 2888 InsertConfigString(pLunL1, "Driver", "VD"); 2889 InsertConfigNode(pLunL1, "Config", &pCfg); 2890 2891 hrc = pMedium->COMGETTER(Location)(bstr.asOutParam()); H(); 2892 InsertConfigString(pCfg, "Path", bstr); 2893 2894 hrc = pMedium->COMGETTER(Format)(bstr.asOutParam()); H(); 2895 InsertConfigString(pCfg, "Format", bstr); 2896 2897 /* DVDs are always readonly */ 2898 if (enmType == DeviceType_DVD) 2899 { 2900 InsertConfigInteger(pCfg, "ReadOnly", 1); 2901 } 2902 2903 /* Start without exclusive write access to the images. */ 2904 /** @todo Live Migration: I don't quite like this, we risk screwing up when 2905 * we're resuming the VM if some 3rd dude have any of the VDIs open 2906 * with write sharing denied. However, if the two VMs are sharing a 2907 * image it really is necessary.... 2908 * 2909 * So, on the "lock-media" command, the target teleporter should also 2910 * make DrvVD undo TempReadOnly. It gets interesting if we fail after 2911 * that. Grumble. */ 2912 else if (aMachineState == MachineState_TeleportingIn) 2913 { 2914 InsertConfigInteger(pCfg, "TempReadOnly", 1); 2915 } 2916 2917 if (!fUseHostIOCache) 2918 { 2919 InsertConfigInteger(pCfg, "UseNewIo", 1); 2920 } 2817 2921 2818 2922 if (fSetupMerge) 2819 2923 { 2924 InsertConfigInteger(pCfg, "SetupMerge", 1); 2820 2925 if (uImage == uMergeSource) 2821 2926 { 2822 rc = CFGMR3InsertInteger(pCur, "MergeSource", 1); RC_CHECK();2927 InsertConfigInteger(pCfg, "MergeSource", 1); 2823 2928 } 2824 2929 else if (uImage == uMergeTarget) 2825 2930 { 2826 rc = CFGMR3InsertInteger(pCur, "MergeTarget", 1); RC_CHECK();2931 InsertConfigInteger(pCfg, "MergeTarget", 1); 2827 2932 } 2828 2933 } 2829 2934 2830 2935 /* Pass all custom parameters. */ 2831 SafeArray<BSTR> aNames; 2832 SafeArray<BSTR> aValues; 2936 bool fHostIP = true; 2937 SafeArray<BSTR> names; 2938 SafeArray<BSTR> values; 2833 2939 hrc = pMedium->GetProperties(NULL, 2834 ComSafeArrayAsOutParam(aNames),2835 ComSafeArrayAsOutParam(aValues));H();2836 2837 if ( aNames.size() != 0)2940 ComSafeArrayAsOutParam(names), 2941 ComSafeArrayAsOutParam(values)); H(); 2942 2943 if (names.size() != 0) 2838 2944 { 2839 2945 PCFGMNODE pVDC; 2840 rc = CFGMR3InsertNode(pCur, "VDConfig", &pVDC); RC_CHECK();2841 for (size_t ii = 0; ii < aNames.size(); ++ii)2946 InsertConfigNode(pCfg, "VDConfig", &pVDC); 2947 for (size_t ii = 0; ii < names.size(); ++ii) 2842 2948 { 2843 if ( aValues[ii] && *aValues[ii])2949 if (values[ii] && *values[ii]) 2844 2950 { 2845 Utf8Str name = aNames[ii];2846 Utf8Str value = aValues[ii];2847 rc = CFGMR3InsertString(pVDC, name.c_str(), value.c_str()); RC_CHECK();2951 Utf8Str name = names[ii]; 2952 Utf8Str value = values[ii]; 2953 InsertConfigString(pVDC, name.c_str(), value); 2848 2954 if ( name.compare("HostIPStack") == 0 2849 2955 && value.compare("0") == 0) … … 2853 2959 } 2854 2960 2855 /* Custom code: put marker to not use host IP stack to driver 2856 * configuration node. Simplifies life of DrvVD a bit. */ 2857 if (!fHostIP) 2858 { 2859 rc = CFGMR3InsertInteger(pCfg, "HostIPStack", 0); RC_CHECK(); 2860 } 2861 2862 /* next */ 2863 pParent = pCur; 2864 pParentMedium = pMedium; 2961 /* Create an inversed list of parents. */ 2962 uImage--; 2963 IMedium *pParentMedium = pMedium; 2964 for (PCFGMNODE pParent = pCfg;; uImage--) 2965 { 2966 hrc = pParentMedium->COMGETTER(Parent)(&pMedium); H(); 2967 if (!pMedium) 2968 break; 2969 2970 PCFGMNODE pCur; 2971 InsertConfigNode(pParent, "Parent", &pCur); 2972 hrc = pMedium->COMGETTER(Location)(bstr.asOutParam()); H(); 2973 InsertConfigString(pCur, "Path", bstr); 2974 2975 hrc = pMedium->COMGETTER(Format)(bstr.asOutParam()); H(); 2976 InsertConfigString(pCur, "Format", bstr); 2977 2978 if (fSetupMerge) 2979 { 2980 if (uImage == uMergeSource) 2981 { 2982 InsertConfigInteger(pCur, "MergeSource", 1); 2983 } 2984 else if (uImage == uMergeTarget) 2985 { 2986 InsertConfigInteger(pCur, "MergeTarget", 1); 2987 } 2988 } 2989 2990 /* Pass all custom parameters. */ 2991 SafeArray<BSTR> aNames; 2992 SafeArray<BSTR> aValues; 2993 hrc = pMedium->GetProperties(NULL, 2994 ComSafeArrayAsOutParam(aNames), 2995 ComSafeArrayAsOutParam(aValues)); H(); 2996 2997 if (aNames.size() != 0) 2998 { 2999 PCFGMNODE pVDC; 3000 InsertConfigNode(pCur, "VDConfig", &pVDC); 3001 for (size_t ii = 0; ii < aNames.size(); ++ii) 3002 { 3003 if (aValues[ii] && *aValues[ii]) 3004 { 3005 Utf8Str name = aNames[ii]; 3006 Utf8Str value = aValues[ii]; 3007 InsertConfigString(pVDC, name.c_str(), value); 3008 if ( name.compare("HostIPStack") == 0 3009 && value.compare("0") == 0) 3010 fHostIP = false; 3011 } 3012 } 3013 } 3014 3015 /* Custom code: put marker to not use host IP stack to driver 3016 * configuration node. Simplifies life of DrvVD a bit. */ 3017 if (!fHostIP) 3018 { 3019 InsertConfigInteger(pCfg, "HostIPStack", 0); 3020 } 3021 3022 /* next */ 3023 pParent = pCur; 3024 pParentMedium = pMedium; 3025 } 2865 3026 } 2866 3027 } 2867 3028 } 3029 catch (ConfigError &x) 3030 { 3031 // InsertConfig threw something: 3032 return x.m_vrc; 3033 } 2868 3034 2869 3035 #undef H 2870 #undef RC_CHECK2871 3036 2872 3037 return VINF_SUCCESS; … … 2891 3056 * @note Locks this object for writing. 2892 3057 */ 2893 int Console::configNetwork(const char *pszDevice, unsigned uInstance, 2894 unsigned uLun, INetworkAdapter *aNetworkAdapter, 2895 PCFGMNODE pCfg, PCFGMNODE pLunL0, PCFGMNODE pInst, 3058 int Console::configNetwork(const char *pszDevice, 3059 unsigned uInstance, 3060 unsigned uLun, 3061 INetworkAdapter *aNetworkAdapter, 3062 PCFGMNODE pCfg, 3063 PCFGMNODE pLunL0, 3064 PCFGMNODE pInst, 2896 3065 bool fAttachDetach) 2897 3066 { … … 2899 3068 AssertComRCReturn(autoCaller.rc(), VERR_ACCESS_DENIED); 2900 3069 2901 int rc = VINF_SUCCESS; 2902 HRESULT hrc; 2903 Bstr bstr; 2904 2905 #define RC_CHECK() AssertMsgReturn(RT_SUCCESS(rc), ("rc=%Rrc\n", rc), rc) 3070 // InsertConfig* throws 3071 try 3072 { 3073 int rc = VINF_SUCCESS; 3074 HRESULT hrc; 3075 Bstr bstr; 3076 2906 3077 #define H() AssertMsgReturn(!FAILED(hrc), ("hrc=%Rhrc\n", hrc), VERR_GENERAL_FAILURE) 2907 3078 2908 /*2909 * Locking the object before doing VMR3* calls is quite safe here, since2910 * we're on EMT. Write lock is necessary because we indirectly modify the2911 * meAttachmentType member.2912 */2913 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);2914 2915 PVM pVM = mpVM;2916 2917 ComPtr<IMachine> pMachine = machine();2918 2919 ComPtr<IVirtualBox> virtualBox;2920 hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam());2921 H();2922 2923 ComPtr<IHost> host;2924 hrc = virtualBox->COMGETTER(Host)(host.asOutParam());2925 H();2926 2927 BOOL fSniffer;2928 hrc = aNetworkAdapter->COMGETTER(TraceEnabled)(&fSniffer);2929 H();2930 2931 if (fAttachDetach && fSniffer)2932 {2933 const char *pszNetDriver = "IntNet";2934 if (meAttachmentType[uInstance] == NetworkAttachmentType_NAT)2935 pszNetDriver = "NAT";3079 /* 3080 * Locking the object before doing VMR3* calls is quite safe here, since 3081 * we're on EMT. Write lock is necessary because we indirectly modify the 3082 * meAttachmentType member. 3083 */ 3084 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 3085 3086 PVM pVM = mpVM; 3087 3088 ComPtr<IMachine> pMachine = machine(); 3089 3090 ComPtr<IVirtualBox> virtualBox; 3091 hrc = pMachine->COMGETTER(Parent)(virtualBox.asOutParam()); 3092 H(); 3093 3094 ComPtr<IHost> host; 3095 hrc = virtualBox->COMGETTER(Host)(host.asOutParam()); 3096 H(); 3097 3098 BOOL fSniffer; 3099 hrc = aNetworkAdapter->COMGETTER(TraceEnabled)(&fSniffer); 3100 H(); 3101 3102 if (fAttachDetach && fSniffer) 3103 { 3104 const char *pszNetDriver = "IntNet"; 3105 if (meAttachmentType[uInstance] == NetworkAttachmentType_NAT) 3106 pszNetDriver = "NAT"; 2936 3107 #if !defined(VBOX_WITH_NETFLT) && defined(RT_OS_LINUX) 2937 if (meAttachmentType[uInstance] == NetworkAttachmentType_Bridged)2938 pszNetDriver = "HostInterface";3108 if (meAttachmentType[uInstance] == NetworkAttachmentType_Bridged) 3109 pszNetDriver = "HostInterface"; 2939 3110 #endif 2940 3111 2941 rc = PDMR3DriverDetach(pVM, pszDevice, uInstance, uLun, pszNetDriver, 0, 0 /*fFlags*/); 2942 if (rc == VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN) 2943 rc = VINF_SUCCESS; 2944 AssertLogRelRCReturn(rc, rc); 2945 2946 pLunL0 = CFGMR3GetChildF(pInst, "LUN#%u", uLun); 2947 PCFGMNODE pLunAD = CFGMR3GetChildF(pLunL0, "AttachedDriver"); 2948 if (pLunAD) 3112 rc = PDMR3DriverDetach(pVM, pszDevice, uInstance, uLun, pszNetDriver, 0, 0 /*fFlags*/); 3113 if (rc == VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN) 3114 rc = VINF_SUCCESS; 3115 AssertLogRelRCReturn(rc, rc); 3116 3117 pLunL0 = CFGMR3GetChildF(pInst, "LUN#%u", uLun); 3118 PCFGMNODE pLunAD = CFGMR3GetChildF(pLunL0, "AttachedDriver"); 3119 if (pLunAD) 3120 { 3121 CFGMR3RemoveNode(pLunAD); 3122 } 3123 else 3124 { 3125 CFGMR3RemoveNode(pLunL0); 3126 InsertConfigNode(pInst, "LUN#0", &pLunL0); 3127 InsertConfigString(pLunL0, "Driver", "NetSniffer"); 3128 InsertConfigNode(pLunL0, "Config", &pCfg); 3129 hrc = aNetworkAdapter->COMGETTER(TraceFile)(bstr.asOutParam()); H(); 3130 if (!bstr.isEmpty()) /* check convention for indicating default file. */ 3131 { 3132 InsertConfigString(pCfg, "File", bstr); 3133 } 3134 } 3135 } 3136 else if (fAttachDetach && !fSniffer) 2949 3137 { 2950 CFGMR3RemoveNode(pLunAD); 3138 rc = PDMR3DeviceDetach(pVM, pszDevice, uInstance, uLun, 0 /*fFlags*/); 3139 if (rc == VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN) 3140 rc = VINF_SUCCESS; 3141 AssertLogRelRCReturn(rc, rc); 3142 3143 /* nuke anything which might have been left behind. */ 3144 CFGMR3RemoveNode(CFGMR3GetChildF(pInst, "LUN#%u", uLun)); 2951 3145 } 2952 else 3146 else if (!fAttachDetach && fSniffer) 2953 3147 { 2954 CFGMR3RemoveNode(pLunL0);2955 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();2956 rc = CFGMR3InsertString(pLunL0, "Driver", "NetSniffer"); RC_CHECK();2957 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();2958 hrc = aNetworkAdapter->COMGETTER(TraceFile)(bstr.asOutParam()); H();3148 /* insert the sniffer filter driver. */ 3149 InsertConfigNode(pInst, "LUN#0", &pLunL0); 3150 InsertConfigString(pLunL0, "Driver", "NetSniffer"); 3151 InsertConfigNode(pLunL0, "Config", &pCfg); 3152 hrc = aNetworkAdapter->COMGETTER(TraceFile)(bstr.asOutParam()); H(); 2959 3153 if (!bstr.isEmpty()) /* check convention for indicating default file. */ 2960 3154 { 2961 rc = CFGMR3InsertStringW(pCfg, "File", bstr.raw()); RC_CHECK();3155 InsertConfigString(pCfg, "File", bstr); 2962 3156 } 2963 3157 } 2964 } 2965 else if (fAttachDetach && !fSniffer) 2966 { 2967 rc = PDMR3DeviceDetach(pVM, pszDevice, uInstance, uLun, 0 /*fFlags*/); 2968 if (rc == VINF_PDM_NO_DRIVER_ATTACHED_TO_LUN) 2969 rc = VINF_SUCCESS; 2970 AssertLogRelRCReturn(rc, rc); 2971 2972 /* nuke anything which might have been left behind. */ 2973 CFGMR3RemoveNode(CFGMR3GetChildF(pInst, "LUN#%u", uLun)); 2974 } 2975 else if (!fAttachDetach && fSniffer) 2976 { 2977 /* insert the sniffer filter driver. */ 2978 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 2979 rc = CFGMR3InsertString(pLunL0, "Driver", "NetSniffer"); RC_CHECK(); 2980 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 2981 hrc = aNetworkAdapter->COMGETTER(TraceFile)(bstr.asOutParam()); H(); 2982 if (!bstr.isEmpty()) /* check convention for indicating default file. */ 3158 3159 Bstr networkName, trunkName, trunkType; 3160 NetworkAttachmentType_T eAttachmentType; 3161 hrc = aNetworkAdapter->COMGETTER(AttachmentType)(&eAttachmentType); H(); 3162 switch (eAttachmentType) 2983 3163 { 2984 rc = CFGMR3InsertStringW(pCfg, "File", bstr.raw()); RC_CHECK(); 2985 } 2986 } 2987 2988 Bstr networkName, trunkName, trunkType; 2989 NetworkAttachmentType_T eAttachmentType; 2990 hrc = aNetworkAdapter->COMGETTER(AttachmentType)(&eAttachmentType); H(); 2991 switch (eAttachmentType) 2992 { 2993 case NetworkAttachmentType_Null: 2994 break; 2995 2996 case NetworkAttachmentType_NAT: 2997 { 2998 ComPtr<INATEngine> natDriver; 2999 hrc = aNetworkAdapter->COMGETTER(NatDriver)(natDriver.asOutParam()); H(); 3000 if (fSniffer) 3001 { 3002 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK(); 3003 } 3004 else 3005 { 3006 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 3007 } 3008 rc = CFGMR3InsertString(pLunL0, "Driver", "NAT"); RC_CHECK(); 3009 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 3010 3011 /* Configure TFTP prefix and boot filename. */ 3012 hrc = virtualBox->COMGETTER(HomeFolder)(bstr.asOutParam()); H(); 3013 if (!bstr.isEmpty()) 3014 { 3015 rc = CFGMR3InsertStringF(pCfg, "TFTPPrefix", "%ls%c%s", bstr.raw(), RTPATH_DELIMITER, "TFTP"); RC_CHECK(); 3016 } 3017 hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H(); 3018 rc = CFGMR3InsertStringF(pCfg, "BootFile", "%ls.pxe", bstr.raw()); RC_CHECK(); 3019 3020 hrc = natDriver->COMGETTER(Network)(bstr.asOutParam()); H(); 3021 if (!bstr.isEmpty()) 3022 { 3023 rc = CFGMR3InsertStringW(pCfg, "Network", bstr.raw()); RC_CHECK(); 3024 } 3025 else 3026 { 3027 ULONG uSlot; 3028 hrc = aNetworkAdapter->COMGETTER(Slot)(&uSlot); H(); 3029 rc = CFGMR3InsertStringF(pCfg, "Network", "10.0.%d.0/24", uSlot+2); RC_CHECK(); 3030 } 3031 hrc = natDriver->COMGETTER(HostIP)(bstr.asOutParam()); H(); 3032 if (!bstr.isEmpty()) 3033 { 3034 rc = CFGMR3InsertStringW(pCfg, "BindIP", bstr.raw()); RC_CHECK(); 3035 } 3036 ULONG mtu = 0; 3037 ULONG sockSnd = 0; 3038 ULONG sockRcv = 0; 3039 ULONG tcpSnd = 0; 3040 ULONG tcpRcv = 0; 3041 hrc = natDriver->GetNetworkSettings(&mtu, &sockSnd, &sockRcv, &tcpSnd, &tcpRcv); H(); 3042 if (mtu) 3043 { 3044 rc = CFGMR3InsertInteger(pCfg, "SlirpMTU", mtu); RC_CHECK(); 3045 } 3046 if (sockRcv) 3047 { 3048 rc = CFGMR3InsertInteger(pCfg, "SockRcv", sockRcv); RC_CHECK(); 3049 } 3050 if (sockSnd) 3051 { 3052 rc = CFGMR3InsertInteger(pCfg, "SockSnd", sockSnd); RC_CHECK(); 3053 } 3054 if (tcpRcv) 3055 { 3056 rc = CFGMR3InsertInteger(pCfg, "TcpRcv", tcpRcv); RC_CHECK(); 3057 } 3058 if (tcpSnd) 3059 { 3060 rc = CFGMR3InsertInteger(pCfg, "TcpSnd", tcpSnd); RC_CHECK(); 3061 } 3062 hrc = natDriver->COMGETTER(TftpPrefix)(bstr.asOutParam()); H(); 3063 if (!bstr.isEmpty()) 3064 { 3065 rc = CFGMR3RemoveValue(pCfg, "TFTPPrefix"); RC_CHECK(); 3066 rc = CFGMR3InsertStringW(pCfg, "TFTPPrefix", bstr); RC_CHECK(); 3067 } 3068 hrc = natDriver->COMGETTER(TftpBootFile)(bstr.asOutParam()); H(); 3069 if (!bstr.isEmpty()) 3070 { 3071 rc = CFGMR3RemoveValue(pCfg, "BootFile"); RC_CHECK(); 3072 rc = CFGMR3InsertStringW(pCfg, "BootFile", bstr); RC_CHECK(); 3073 } 3074 hrc = natDriver->COMGETTER(TftpNextServer)(bstr.asOutParam()); H(); 3075 if (!bstr.isEmpty()) 3076 { 3077 rc = CFGMR3InsertStringW(pCfg, "NextServer", bstr); RC_CHECK(); 3078 } 3079 BOOL fDnsFlag; 3080 hrc = natDriver->COMGETTER(DnsPassDomain)(&fDnsFlag); H(); 3081 rc = CFGMR3InsertInteger(pCfg, "PassDomain", fDnsFlag); RC_CHECK(); 3082 hrc = natDriver->COMGETTER(DnsProxy)(&fDnsFlag); H(); 3083 rc = CFGMR3InsertInteger(pCfg, "DNSProxy", fDnsFlag); RC_CHECK(); 3084 hrc = natDriver->COMGETTER(DnsUseHostResolver)(&fDnsFlag); H(); 3085 rc = CFGMR3InsertInteger(pCfg, "UseHostResolver", fDnsFlag); RC_CHECK(); 3086 3087 ULONG aliasMode; 3088 hrc = natDriver->COMGETTER(AliasMode)(&aliasMode); H(); 3089 rc = CFGMR3InsertInteger(pCfg, "AliasMode", aliasMode); RC_CHECK(); 3090 3091 /* port-forwarding */ 3092 SafeArray<BSTR> pfs; 3093 hrc = natDriver->COMGETTER(Redirects)(ComSafeArrayAsOutParam(pfs)); H(); 3094 PCFGMNODE pPF = NULL; /* /Devices/Dev/.../Config/PF#0/ */ 3095 for (unsigned int i = 0; i < pfs.size(); ++i) 3096 { 3097 uint16_t port = 0; 3098 BSTR r = pfs[i]; 3099 Utf8Str utf = Utf8Str(r); 3100 Utf8Str strName; 3101 Utf8Str strProto; 3102 Utf8Str strHostPort; 3103 Utf8Str strHostIP; 3104 Utf8Str strGuestPort; 3105 Utf8Str strGuestIP; 3106 size_t pos, ppos; 3107 pos = ppos = 0; 3164 case NetworkAttachmentType_Null: 3165 break; 3166 3167 case NetworkAttachmentType_NAT: 3168 { 3169 ComPtr<INATEngine> natDriver; 3170 hrc = aNetworkAdapter->COMGETTER(NatDriver)(natDriver.asOutParam()); H(); 3171 if (fSniffer) 3172 { 3173 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0); 3174 } 3175 else 3176 { 3177 InsertConfigNode(pInst, "LUN#0", &pLunL0); 3178 } 3179 InsertConfigString(pLunL0, "Driver", "NAT"); 3180 InsertConfigNode(pLunL0, "Config", &pCfg); 3181 3182 /* Configure TFTP prefix and boot filename. */ 3183 hrc = virtualBox->COMGETTER(HomeFolder)(bstr.asOutParam()); H(); 3184 if (!bstr.isEmpty()) 3185 { 3186 InsertConfigString(pCfg, "TFTPPrefix", Utf8StrFmt("%ls%c%s", bstr.raw(), RTPATH_DELIMITER, "TFTP")); 3187 } 3188 hrc = pMachine->COMGETTER(Name)(bstr.asOutParam()); H(); 3189 InsertConfigString(pCfg, "BootFile", Utf8StrFmt("%ls.pxe", bstr.raw())); 3190 3191 hrc = natDriver->COMGETTER(Network)(bstr.asOutParam()); H(); 3192 if (!bstr.isEmpty()) 3193 { 3194 InsertConfigString(pCfg, "Network", bstr); 3195 } 3196 else 3197 { 3198 ULONG uSlot; 3199 hrc = aNetworkAdapter->COMGETTER(Slot)(&uSlot); H(); 3200 InsertConfigString(pCfg, "Network", Utf8StrFmt("10.0.%d.0/24", uSlot+2)); 3201 } 3202 hrc = natDriver->COMGETTER(HostIP)(bstr.asOutParam()); H(); 3203 if (!bstr.isEmpty()) 3204 { 3205 InsertConfigString(pCfg, "BindIP", bstr); 3206 } 3207 ULONG mtu = 0; 3208 ULONG sockSnd = 0; 3209 ULONG sockRcv = 0; 3210 ULONG tcpSnd = 0; 3211 ULONG tcpRcv = 0; 3212 hrc = natDriver->GetNetworkSettings(&mtu, &sockSnd, &sockRcv, &tcpSnd, &tcpRcv); H(); 3213 if (mtu) 3214 { 3215 InsertConfigInteger(pCfg, "SlirpMTU", mtu); 3216 } 3217 if (sockRcv) 3218 { 3219 InsertConfigInteger(pCfg, "SockRcv", sockRcv); 3220 } 3221 if (sockSnd) 3222 { 3223 InsertConfigInteger(pCfg, "SockSnd", sockSnd); 3224 } 3225 if (tcpRcv) 3226 { 3227 InsertConfigInteger(pCfg, "TcpRcv", tcpRcv); 3228 } 3229 if (tcpSnd) 3230 { 3231 InsertConfigInteger(pCfg, "TcpSnd", tcpSnd); 3232 } 3233 hrc = natDriver->COMGETTER(TftpPrefix)(bstr.asOutParam()); H(); 3234 if (!bstr.isEmpty()) 3235 { 3236 RemoveConfigValue(pCfg, "TFTPPrefix"); 3237 InsertConfigString(pCfg, "TFTPPrefix", bstr); 3238 } 3239 hrc = natDriver->COMGETTER(TftpBootFile)(bstr.asOutParam()); H(); 3240 if (!bstr.isEmpty()) 3241 { 3242 RemoveConfigValue(pCfg, "BootFile"); 3243 InsertConfigString(pCfg, "BootFile", bstr); 3244 } 3245 hrc = natDriver->COMGETTER(TftpNextServer)(bstr.asOutParam()); H(); 3246 if (!bstr.isEmpty()) 3247 { 3248 InsertConfigString(pCfg, "NextServer", bstr); 3249 } 3250 BOOL fDnsFlag; 3251 hrc = natDriver->COMGETTER(DnsPassDomain)(&fDnsFlag); H(); 3252 InsertConfigInteger(pCfg, "PassDomain", fDnsFlag); 3253 hrc = natDriver->COMGETTER(DnsProxy)(&fDnsFlag); H(); 3254 InsertConfigInteger(pCfg, "DNSProxy", fDnsFlag); 3255 hrc = natDriver->COMGETTER(DnsUseHostResolver)(&fDnsFlag); H(); 3256 InsertConfigInteger(pCfg, "UseHostResolver", fDnsFlag); 3257 3258 ULONG aliasMode; 3259 hrc = natDriver->COMGETTER(AliasMode)(&aliasMode); H(); 3260 InsertConfigInteger(pCfg, "AliasMode", aliasMode); 3261 3262 /* port-forwarding */ 3263 SafeArray<BSTR> pfs; 3264 hrc = natDriver->COMGETTER(Redirects)(ComSafeArrayAsOutParam(pfs)); H(); 3265 PCFGMNODE pPF = NULL; /* /Devices/Dev/.../Config/PF#0/ */ 3266 for (unsigned int i = 0; i < pfs.size(); ++i) 3267 { 3268 uint16_t port = 0; 3269 BSTR r = pfs[i]; 3270 Utf8Str utf = Utf8Str(r); 3271 Utf8Str strName; 3272 Utf8Str strProto; 3273 Utf8Str strHostPort; 3274 Utf8Str strHostIP; 3275 Utf8Str strGuestPort; 3276 Utf8Str strGuestIP; 3277 size_t pos, ppos; 3278 pos = ppos = 0; 3108 3279 #define ITERATE_TO_NEXT_TERM(res, str, pos, ppos) \ 3109 3280 do { \ … … 3126 3297 #undef ITERATE_TO_NEXT_TERM 3127 3298 3128 uint32_t proto = strProto.toUInt32(); 3129 bool fValid = true; 3130 switch (proto) 3131 { 3132 case NATProtocol_UDP: 3133 strProto = "UDP"; 3134 break; 3135 case NATProtocol_TCP: 3136 strProto = "TCP"; 3137 break; 3138 default: 3139 fValid = false; 3140 } 3141 /* continue with next rule if no valid proto was passed */ 3142 if (!fValid) 3143 continue; 3144 3145 rc = CFGMR3InsertNode(pCfg, strName.raw(), &pPF); RC_CHECK(); 3146 rc = CFGMR3InsertString(pPF, "Protocol", strProto.raw()); RC_CHECK(); 3147 3148 if (!strHostIP.isEmpty()) 3149 { 3150 rc = CFGMR3InsertString(pPF, "BindIP", strHostIP.raw()); RC_CHECK(); 3151 } 3152 3153 if (!strGuestIP.isEmpty()) 3154 { 3155 rc = CFGMR3InsertString(pPF, "GuestIP", strGuestIP.raw()); RC_CHECK(); 3156 } 3157 3158 port = RTStrToUInt16(strHostPort.raw()); 3159 if (port) 3160 { 3161 rc = CFGMR3InsertInteger(pPF, "HostPort", port); RC_CHECK(); 3162 } 3163 3164 port = RTStrToUInt16(strGuestPort.raw()); 3165 if (port) 3166 { 3167 rc = CFGMR3InsertInteger(pPF, "GuestPort", port); RC_CHECK(); 3168 } 3169 } 3170 break; 3171 } 3172 3173 case NetworkAttachmentType_Bridged: 3174 { 3299 uint32_t proto = strProto.toUInt32(); 3300 bool fValid = true; 3301 switch (proto) 3302 { 3303 case NATProtocol_UDP: 3304 strProto = "UDP"; 3305 break; 3306 case NATProtocol_TCP: 3307 strProto = "TCP"; 3308 break; 3309 default: 3310 fValid = false; 3311 } 3312 /* continue with next rule if no valid proto was passed */ 3313 if (!fValid) 3314 continue; 3315 3316 InsertConfigNode(pCfg, strName.raw(), &pPF); 3317 InsertConfigString(pPF, "Protocol", strProto); 3318 3319 if (!strHostIP.isEmpty()) 3320 InsertConfigString(pPF, "BindIP", strHostIP); 3321 3322 if (!strGuestIP.isEmpty()) 3323 InsertConfigString(pPF, "GuestIP", strGuestIP); 3324 3325 port = RTStrToUInt16(strHostPort.raw()); 3326 if (port) 3327 { 3328 InsertConfigInteger(pPF, "HostPort", port); 3329 } 3330 3331 port = RTStrToUInt16(strGuestPort.raw()); 3332 if (port) 3333 { 3334 InsertConfigInteger(pPF, "GuestPort", port); 3335 } 3336 } 3337 break; 3338 } 3339 3340 case NetworkAttachmentType_Bridged: 3341 { 3175 3342 #if (defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)) && !defined(VBOX_WITH_NETFLT) 3176 hrc = attachToTapInterface(aNetworkAdapter);3177 if (FAILED(hrc))3178 {3179 switch (hrc)3180 {3181 case VERR_ACCESS_DENIED:3182 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_(3183 "Failed to open '/dev/net/tun' for read/write access. Please check the "3184 "permissions of that node. Either run 'chmod 0666 /dev/net/tun' or "3185 "change the group of that node and make yourself a member of that group. Make "3186 "sure that these changes are permanent, especially if you are "3187 "using udev"));3188 default:3189 AssertMsgFailed(("Could not attach to host interface! Bad!\n"));3190 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_(3191 "Failed to initialize Host Interface Networking"));3192 }3193 }3194 3195 Assert((int)maTapFD[uInstance] >= 0);3196 if ((int)maTapFD[uInstance] >= 0)3197 {3198 if (fSniffer)3199 {3200 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();3201 }3202 else3203 {3204 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();3205 }3206 rc = CFGMR3InsertString(pLunL0, "Driver", "HostInterface"); RC_CHECK();3207 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK();3208 rc = CFGMR3InsertInteger(pCfg, "FileHandle", maTapFD[uInstance]); RC_CHECK();3209 }3210 3211 #elif defined(VBOX_WITH_NETFLT)3212 /*3213 * This is the new VBoxNetFlt+IntNet stuff.3214 */3215 if (fSniffer)3216 {3217 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); RC_CHECK();3218 }3219 else3220 {3221 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();3222 }3223 3224 Bstr HifName;3225 hrc = aNetworkAdapter->COMGETTER(HostInterface)(HifName.asOutParam());3226 if (FAILED(hrc))3227 {3228 LogRel(("NetworkAttachmentType_Bridged: COMGETTER(HostInterface) failed, hrc (0x%x)", hrc));3229 H();3230 }3231 3232 Utf8Str HifNameUtf8(HifName);3233 const char *pszHifName = HifNameUtf8.raw();3234 3235 # if defined(RT_OS_DARWIN)3236 /* The name is on the form 'ifX: long name', chop it off at the colon. */3237 char szTrunk[8];3238 strncpy(szTrunk, pszHifName, sizeof(szTrunk));3239 char *pszColon = (char *)memchr(szTrunk, ':', sizeof(szTrunk));3240 if (!pszColon)3241 {3242 /*3243 * Dynamic changing of attachment causes an attempt to configure3244 * network with invalid host adapter (as it is must be changed before3245 * the attachment), calling Detach here will cause a deadlock.3246 * See #4750.3247 * hrc = aNetworkAdapter->Detach(); H();3248 */3249 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS,3250 N_("Malformed host interface networking name '%ls'"),3251 HifName.raw());3252 }3253 *pszColon = '\0';3254 const char *pszTrunk = szTrunk;3255 3256 # elif defined(RT_OS_SOLARIS)3257 /* The name is on the form format 'ifX[:1] - long name, chop it off at space. */3258 char szTrunk[256];3259 strlcpy(szTrunk, pszHifName, sizeof(szTrunk));3260 char *pszSpace = (char *)memchr(szTrunk, ' ', sizeof(szTrunk));3261 3262 /*3263 * Currently don't bother about malformed names here for the sake of people using3264 * VBoxManage and setting only the NIC name from there. If there is a space we3265 * chop it off and proceed, otherwise just use whatever we've got.3266 */3267 if (pszSpace)3268 *pszSpace = '\0';3269 3270 /* Chop it off at the colon (zone naming eg: e1000g:1 we need only the e1000g) */3271 char *pszColon = (char *)memchr(szTrunk, ':', sizeof(szTrunk));3272 if (pszColon)3273 *pszColon = '\0';3274 3275 const char *pszTrunk = szTrunk;3276 3277 # elif defined(RT_OS_WINDOWS)3278 ComPtr<IHostNetworkInterface> hostInterface;3279 hrc = host->FindHostNetworkInterfaceByName(HifName, hostInterface.asOutParam());3280 if (!SUCCEEDED(hrc))3281 {3282 AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: FindByName failed, rc=%Rhrc (0x%x)", hrc, hrc));3283 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS,3284 N_("Inexistent host networking interface, name '%ls'"),3285 HifName.raw());3286 }3287 3288 HostNetworkInterfaceType_T eIfType;3289 hrc = hostInterface->COMGETTER(InterfaceType)(&eIfType);3290 if (FAILED(hrc))3291 {3292 LogRel(("NetworkAttachmentType_Bridged: COMGETTER(InterfaceType) failed, hrc (0x%x)", hrc));3293 H();3294 }3295 3296 if (eIfType != HostNetworkInterfaceType_Bridged)3297 {3298 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS,3299 N_("Interface ('%ls') is not a Bridged Adapter interface"),3300 HifName.raw());3301 }3302 3303 hrc = hostInterface->COMGETTER(Id)(bstr.asOutParam());3304 if (FAILED(hrc))3305 {3306 LogRel(("NetworkAttachmentType_Bridged: COMGETTER(Id) failed, hrc (0x%x)", hrc));3307 H();3308 }3309 Guid hostIFGuid(bstr);3310 3311 INetCfg *pNc;3312 ComPtr<INetCfgComponent> pAdaptorComponent;3313 LPWSTR pszApp;3314 int rc = VERR_INTNET_FLT_IF_NOT_FOUND;3315 3316 hrc = VBoxNetCfgWinQueryINetCfg(FALSE /*fGetWriteLock*/,3317 L"VirtualBox",3318 &pNc,3319 &pszApp);3320 Assert(hrc == S_OK);3321 if (hrc == S_OK)3322 {3323 /* get the adapter's INetCfgComponent*/3324 hrc = VBoxNetCfgWinGetComponentByGuid(pNc, &GUID_DEVCLASS_NET, (GUID*)hostIFGuid.ptr(), pAdaptorComponent.asOutParam());3325 if (hrc != S_OK)3326 {3327 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);3328 LogRel(("NetworkAttachmentType_Bridged: VBoxNetCfgWinGetComponentByGuid failed, hrc (0x%x)", hrc));3329 H();3330 }3331 }3332 #define VBOX_WIN_BINDNAME_PREFIX "\\DEVICE\\"3333 char szTrunkName[INTNET_MAX_TRUNK_NAME];3334 char *pszTrunkName = szTrunkName;3335 wchar_t * pswzBindName;3336 hrc = pAdaptorComponent->GetBindName(&pswzBindName);3337 Assert(hrc == S_OK);3338 if (hrc == S_OK)3339 {3340 int cwBindName = (int)wcslen(pswzBindName) + 1;3341 int cbFullBindNamePrefix = sizeof(VBOX_WIN_BINDNAME_PREFIX);3342 if (sizeof(szTrunkName) > cbFullBindNamePrefix + cwBindName)3343 {3344 strcpy(szTrunkName, VBOX_WIN_BINDNAME_PREFIX);3345 pszTrunkName += cbFullBindNamePrefix-1;3346 if (!WideCharToMultiByte(CP_ACP, 0, pswzBindName, cwBindName, pszTrunkName,3347 sizeof(szTrunkName) - cbFullBindNamePrefix + 1, NULL, NULL))3348 {3349 DWORD err = GetLastError();3350 hrc = HRESULT_FROM_WIN32(err);3351 AssertMsgFailed(("%hrc=%Rhrc %#x\n", hrc, hrc));3352 AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: WideCharToMultiByte failed, hr=%Rhrc (0x%x) err=%u\n", hrc, hrc, err));3353 }3354 }3355 else3356 {3357 AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: insufficient szTrunkName buffer space\n"));3358 /** @todo set appropriate error code */3359 hrc = E_FAIL;3360 }3361 3362 if (hrc != S_OK)3363 {3364 AssertFailed();3365 CoTaskMemFree(pswzBindName);3366 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);3367 H();3368 }3369 3370 /* we're not freeing the bind name since we'll use it later for detecting wireless*/3371 }3372 else3373 {3374 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/);3375 AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: VBoxNetCfgWinGetComponentByGuid failed, hrc (0x%x)", hrc));3376 H();3377 }3378 const char *pszTrunk = szTrunkName;3379 /* we're not releasing the INetCfg stuff here since we use it later to figure out whether it is wireless */3380 3381 # elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)3382 # if defined(RT_OS_FREEBSD)3383 /*3384 * If we bridge to a tap interface open it the `old' direct way.3385 * This works and performs better than bridging a physical3386 * interface via the current FreeBSD vboxnetflt implementation.3387 */3388 if (!strncmp(pszHifName, "tap", sizeof "tap" - 1)) {3389 3343 hrc = attachToTapInterface(aNetworkAdapter); 3390 3344 if (FAILED(hrc)) … … 3394 3348 case VERR_ACCESS_DENIED: 3395 3349 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_( 3396 "Failed to open '/dev/%s' for read/write access.Please check the "3397 "permissions of that node, and that the net.link.tap.user_open"3398 "sysctl is set. Either run 'chmod 0666 /dev/%s' or"3399 "change the group of that node to vboxusers and make yourself"3400 "a member of that group. Make sure that these changes are permanent."), pszHifName, pszHifName);3350 "Failed to open '/dev/net/tun' for read/write access. Please check the " 3351 "permissions of that node. Either run 'chmod 0666 /dev/net/tun' or " 3352 "change the group of that node and make yourself a member of that group. Make " 3353 "sure that these changes are permanent, especially if you are " 3354 "using udev")); 3401 3355 default: 3402 AssertMsgFailed(("Could not attach to tapinterface! Bad!\n"));3356 AssertMsgFailed(("Could not attach to host interface! Bad!\n")); 3403 3357 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_( 3404 3358 "Failed to initialize Host Interface Networking")); 3405 3359 } 3406 3360 } … … 3409 3363 if ((int)maTapFD[uInstance] >= 0) 3410 3364 { 3411 rc = CFGMR3InsertString(pLunL0, "Driver", "HostInterface"); RC_CHECK(); 3412 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 3413 rc = CFGMR3InsertInteger(pCfg, "FileHandle", maTapFD[uInstance]); RC_CHECK(); 3414 } 3415 break; 3416 } 3365 if (fSniffer) 3366 { 3367 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0); 3368 } 3369 else 3370 { 3371 InsertConfigNode(pInst, "LUN#0", &pLunL0); 3372 } 3373 InsertConfigString(pLunL0, "Driver", "HostInterface"); 3374 InsertConfigNode(pLunL0, "Config", &pCfg); 3375 InsertConfigInteger(pCfg, "FileHandle", maTapFD[uInstance]); 3376 } 3377 3378 #elif defined(VBOX_WITH_NETFLT) 3379 /* 3380 * This is the new VBoxNetFlt+IntNet stuff. 3381 */ 3382 if (fSniffer) 3383 { 3384 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0); 3385 } 3386 else 3387 { 3388 InsertConfigNode(pInst, "LUN#0", &pLunL0); 3389 } 3390 3391 Bstr HifName; 3392 hrc = aNetworkAdapter->COMGETTER(HostInterface)(HifName.asOutParam()); 3393 if (FAILED(hrc)) 3394 { 3395 LogRel(("NetworkAttachmentType_Bridged: COMGETTER(HostInterface) failed, hrc (0x%x)", hrc)); 3396 H(); 3397 } 3398 3399 Utf8Str HifNameUtf8(HifName); 3400 const char *pszHifName = HifNameUtf8.raw(); 3401 3402 # if defined(RT_OS_DARWIN) 3403 /* The name is on the form 'ifX: long name', chop it off at the colon. */ 3404 char szTrunk[8]; 3405 strncpy(szTrunk, pszHifName, sizeof(szTrunk)); 3406 char *pszColon = (char *)memchr(szTrunk, ':', sizeof(szTrunk)); 3407 if (!pszColon) 3408 { 3409 /* 3410 * Dynamic changing of attachment causes an attempt to configure 3411 * network with invalid host adapter (as it is must be changed before 3412 * the attachment), calling Detach here will cause a deadlock. 3413 * See #4750. 3414 * hrc = aNetworkAdapter->Detach(); H(); 3415 */ 3416 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS, 3417 N_("Malformed host interface networking name '%ls'"), 3418 HifName.raw()); 3419 } 3420 *pszColon = '\0'; 3421 const char *pszTrunk = szTrunk; 3422 3423 # elif defined(RT_OS_SOLARIS) 3424 /* The name is on the form format 'ifX[:1] - long name, chop it off at space. */ 3425 char szTrunk[256]; 3426 strlcpy(szTrunk, pszHifName, sizeof(szTrunk)); 3427 char *pszSpace = (char *)memchr(szTrunk, ' ', sizeof(szTrunk)); 3428 3429 /* 3430 * Currently don't bother about malformed names here for the sake of people using 3431 * VBoxManage and setting only the NIC name from there. If there is a space we 3432 * chop it off and proceed, otherwise just use whatever we've got. 3433 */ 3434 if (pszSpace) 3435 *pszSpace = '\0'; 3436 3437 /* Chop it off at the colon (zone naming eg: e1000g:1 we need only the e1000g) */ 3438 char *pszColon = (char *)memchr(szTrunk, ':', sizeof(szTrunk)); 3439 if (pszColon) 3440 *pszColon = '\0'; 3441 3442 const char *pszTrunk = szTrunk; 3443 3444 # elif defined(RT_OS_WINDOWS) 3445 ComPtr<IHostNetworkInterface> hostInterface; 3446 hrc = host->FindHostNetworkInterfaceByName(HifName, hostInterface.asOutParam()); 3447 if (!SUCCEEDED(hrc)) 3448 { 3449 AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: FindByName failed, rc=%Rhrc (0x%x)", hrc, hrc)); 3450 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS, 3451 N_("Inexistent host networking interface, name '%ls'"), 3452 HifName.raw()); 3453 } 3454 3455 HostNetworkInterfaceType_T eIfType; 3456 hrc = hostInterface->COMGETTER(InterfaceType)(&eIfType); 3457 if (FAILED(hrc)) 3458 { 3459 LogRel(("NetworkAttachmentType_Bridged: COMGETTER(InterfaceType) failed, hrc (0x%x)", hrc)); 3460 H(); 3461 } 3462 3463 if (eIfType != HostNetworkInterfaceType_Bridged) 3464 { 3465 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS, 3466 N_("Interface ('%ls') is not a Bridged Adapter interface"), 3467 HifName.raw()); 3468 } 3469 3470 hrc = hostInterface->COMGETTER(Id)(bstr.asOutParam()); 3471 if (FAILED(hrc)) 3472 { 3473 LogRel(("NetworkAttachmentType_Bridged: COMGETTER(Id) failed, hrc (0x%x)", hrc)); 3474 H(); 3475 } 3476 Guid hostIFGuid(bstr); 3477 3478 INetCfg *pNc; 3479 ComPtr<INetCfgComponent> pAdaptorComponent; 3480 LPWSTR pszApp; 3481 int rc = VERR_INTNET_FLT_IF_NOT_FOUND; 3482 3483 hrc = VBoxNetCfgWinQueryINetCfg(FALSE /*fGetWriteLock*/, 3484 L"VirtualBox", 3485 &pNc, 3486 &pszApp); 3487 Assert(hrc == S_OK); 3488 if (hrc == S_OK) 3489 { 3490 /* get the adapter's INetCfgComponent*/ 3491 hrc = VBoxNetCfgWinGetComponentByGuid(pNc, &GUID_DEVCLASS_NET, (GUID*)hostIFGuid.ptr(), pAdaptorComponent.asOutParam()); 3492 if (hrc != S_OK) 3493 { 3494 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/); 3495 LogRel(("NetworkAttachmentType_Bridged: VBoxNetCfgWinGetComponentByGuid failed, hrc (0x%x)", hrc)); 3496 H(); 3497 } 3498 } 3499 #define VBOX_WIN_BINDNAME_PREFIX "\\DEVICE\\" 3500 char szTrunkName[INTNET_MAX_TRUNK_NAME]; 3501 char *pszTrunkName = szTrunkName; 3502 wchar_t * pswzBindName; 3503 hrc = pAdaptorComponent->GetBindName(&pswzBindName); 3504 Assert(hrc == S_OK); 3505 if (hrc == S_OK) 3506 { 3507 int cwBindName = (int)wcslen(pswzBindName) + 1; 3508 int cbFullBindNamePrefix = sizeof(VBOX_WIN_BINDNAME_PREFIX); 3509 if (sizeof(szTrunkName) > cbFullBindNamePrefix + cwBindName) 3510 { 3511 strcpy(szTrunkName, VBOX_WIN_BINDNAME_PREFIX); 3512 pszTrunkName += cbFullBindNamePrefix-1; 3513 if (!WideCharToMultiByte(CP_ACP, 0, pswzBindName, cwBindName, pszTrunkName, 3514 sizeof(szTrunkName) - cbFullBindNamePrefix + 1, NULL, NULL)) 3515 { 3516 DWORD err = GetLastError(); 3517 hrc = HRESULT_FROM_WIN32(err); 3518 AssertMsgFailed(("%hrc=%Rhrc %#x\n", hrc, hrc)); 3519 AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: WideCharToMultiByte failed, hr=%Rhrc (0x%x) err=%u\n", hrc, hrc, err)); 3520 } 3521 } 3522 else 3523 { 3524 AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: insufficient szTrunkName buffer space\n")); 3525 /** @todo set appropriate error code */ 3526 hrc = E_FAIL; 3527 } 3528 3529 if (hrc != S_OK) 3530 { 3531 AssertFailed(); 3532 CoTaskMemFree(pswzBindName); 3533 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/); 3534 H(); 3535 } 3536 3537 /* we're not freeing the bind name since we'll use it later for detecting wireless*/ 3538 } 3539 else 3540 { 3541 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/); 3542 AssertLogRelMsgFailed(("NetworkAttachmentType_Bridged: VBoxNetCfgWinGetComponentByGuid failed, hrc (0x%x)", hrc)); 3543 H(); 3544 } 3545 const char *pszTrunk = szTrunkName; 3546 /* we're not releasing the INetCfg stuff here since we use it later to figure out whether it is wireless */ 3547 3548 # elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) 3549 # if defined(RT_OS_FREEBSD) 3550 /* 3551 * If we bridge to a tap interface open it the `old' direct way. 3552 * This works and performs better than bridging a physical 3553 * interface via the current FreeBSD vboxnetflt implementation. 3554 */ 3555 if (!strncmp(pszHifName, "tap", sizeof "tap" - 1)) { 3556 hrc = attachToTapInterface(aNetworkAdapter); 3557 if (FAILED(hrc)) 3558 { 3559 switch (hrc) 3560 { 3561 case VERR_ACCESS_DENIED: 3562 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_( 3563 "Failed to open '/dev/%s' for read/write access. Please check the " 3564 "permissions of that node, and that the net.link.tap.user_open " 3565 "sysctl is set. Either run 'chmod 0666 /dev/%s' or " 3566 "change the group of that node to vboxusers and make yourself " 3567 "a member of that group. Make sure that these changes are permanent."), pszHifName, pszHifName); 3568 default: 3569 AssertMsgFailed(("Could not attach to tap interface! Bad!\n")); 3570 return VMSetError(pVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_( 3571 "Failed to initialize Host Interface Networking")); 3572 } 3573 } 3574 3575 Assert((int)maTapFD[uInstance] >= 0); 3576 if ((int)maTapFD[uInstance] >= 0) 3577 { 3578 InsertConfigString(pLunL0, "Driver", "HostInterface"); 3579 InsertConfigNode(pLunL0, "Config", &pCfg); 3580 InsertConfigInteger(pCfg, "FileHandle", maTapFD[uInstance]); 3581 } 3582 break; 3583 } 3417 3584 # endif 3418 /** @todo Check for malformed names. */3419 const char *pszTrunk = pszHifName;3420 3421 /* Issue a warning if the interface is down */3422 {3423 int iSock = socket(AF_INET, SOCK_DGRAM, 0);3424 if (iSock >= 0)3425 {3426 struct ifreq Req;3427 3428 memset(&Req, 0, sizeof(Req));3429 strncpy(Req.ifr_name, pszHifName, sizeof(Req.ifr_name) - 1);3430 if (ioctl(iSock, SIOCGIFFLAGS, &Req) >= 0)3431 if ((Req.ifr_flags & IFF_UP) == 0)3432 {3433 setVMRuntimeErrorCallbackF(pVM, this, 0, "BridgedInterfaceDown", "Bridged interface %s is down. Guest will not be able to use this interface", pszHifName);3434 }3435 3436 close(iSock);3437 }3438 }3585 /** @todo Check for malformed names. */ 3586 const char *pszTrunk = pszHifName; 3587 3588 /* Issue a warning if the interface is down */ 3589 { 3590 int iSock = socket(AF_INET, SOCK_DGRAM, 0); 3591 if (iSock >= 0) 3592 { 3593 struct ifreq Req; 3594 3595 memset(&Req, 0, sizeof(Req)); 3596 strncpy(Req.ifr_name, pszHifName, sizeof(Req.ifr_name) - 1); 3597 if (ioctl(iSock, SIOCGIFFLAGS, &Req) >= 0) 3598 if ((Req.ifr_flags & IFF_UP) == 0) 3599 { 3600 setVMRuntimeErrorCallbackF(pVM, this, 0, "BridgedInterfaceDown", "Bridged interface %s is down. Guest will not be able to use this interface", pszHifName); 3601 } 3602 3603 close(iSock); 3604 } 3605 } 3439 3606 3440 3607 # else … … 3442 3609 # endif 3443 3610 3444 rc = CFGMR3InsertString(pLunL0, "Driver", "IntNet"); RC_CHECK(); 3445 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 3446 rc = CFGMR3InsertString(pCfg, "Trunk", pszTrunk); RC_CHECK(); 3447 rc = CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_NetFlt); 3448 RC_CHECK(); 3449 char szNetwork[INTNET_MAX_NETWORK_NAME]; 3450 RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszHifName); 3451 rc = CFGMR3InsertString(pCfg, "Network", szNetwork); RC_CHECK(); 3452 networkName = Bstr(szNetwork); 3453 trunkName = Bstr(pszTrunk); 3454 trunkType = Bstr(TRUNKTYPE_NETFLT); 3611 InsertConfigString(pLunL0, "Driver", "IntNet"); 3612 InsertConfigNode(pLunL0, "Config", &pCfg); 3613 InsertConfigString(pCfg, "Trunk", pszTrunk); 3614 InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_NetFlt); 3615 char szNetwork[INTNET_MAX_NETWORK_NAME]; 3616 RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszHifName); 3617 InsertConfigString(pCfg, "Network", szNetwork); 3618 networkName = Bstr(szNetwork); 3619 trunkName = Bstr(pszTrunk); 3620 trunkType = Bstr(TRUNKTYPE_NETFLT); 3455 3621 3456 3622 # if defined(RT_OS_DARWIN) 3457 /** @todo Come up with a better deal here. Problem is that IHostNetworkInterface is completely useless here. */3458 if ( strstr(pszHifName, "Wireless")3459 || strstr(pszHifName, "AirPort" ))3460 {3461 rc = CFGMR3InsertInteger(pCfg, "SharedMacOnWire", true); RC_CHECK();3462 }3623 /** @todo Come up with a better deal here. Problem is that IHostNetworkInterface is completely useless here. */ 3624 if ( strstr(pszHifName, "Wireless") 3625 || strstr(pszHifName, "AirPort" )) 3626 { 3627 InsertConfigInteger(pCfg, "SharedMacOnWire", true); 3628 } 3463 3629 # elif defined(RT_OS_LINUX) 3464 int iSock = socket(AF_INET, SOCK_DGRAM, 0); 3465 if (iSock >= 0) 3466 { 3467 struct iwreq WRq; 3468 3469 memset(&WRq, 0, sizeof(WRq)); 3470 strncpy(WRq.ifr_name, pszHifName, IFNAMSIZ); 3471 bool fSharedMacOnWire = ioctl(iSock, SIOCGIWNAME, &WRq) >= 0; 3472 close(iSock); 3473 if (fSharedMacOnWire) 3474 { 3475 rc = CFGMR3InsertInteger(pCfg, "SharedMacOnWire", true); 3476 RC_CHECK(); 3477 Log(("Set SharedMacOnWire\n")); 3630 int iSock = socket(AF_INET, SOCK_DGRAM, 0); 3631 if (iSock >= 0) 3632 { 3633 struct iwreq WRq; 3634 3635 memset(&WRq, 0, sizeof(WRq)); 3636 strncpy(WRq.ifr_name, pszHifName, IFNAMSIZ); 3637 bool fSharedMacOnWire = ioctl(iSock, SIOCGIWNAME, &WRq) >= 0; 3638 close(iSock); 3639 if (fSharedMacOnWire) 3640 { 3641 InsertConfigInteger(pCfg, "SharedMacOnWire", true); 3642 Log(("Set SharedMacOnWire\n")); 3643 } 3644 else 3645 Log(("Failed to get wireless name\n")); 3478 3646 } 3479 3647 else 3480 Log(("Failed to get wireless name\n")); 3481 } 3482 else 3483 Log(("Failed to open wireless socket\n")); 3648 Log(("Failed to open wireless socket\n")); 3484 3649 # elif defined(RT_OS_FREEBSD) 3485 int iSock = socket(AF_INET, SOCK_DGRAM, 0); 3486 if (iSock >= 0) 3487 { 3488 struct ieee80211req WReq; 3489 uint8_t abData[32]; 3490 3491 memset(&WReq, 0, sizeof(WReq)); 3492 strncpy(WReq.i_name, pszHifName, sizeof(WReq.i_name)); 3493 WReq.i_type = IEEE80211_IOC_SSID; 3494 WReq.i_val = -1; 3495 WReq.i_data = abData; 3496 WReq.i_len = sizeof(abData); 3497 3498 bool fSharedMacOnWire = ioctl(iSock, SIOCG80211, &WReq) >= 0; 3499 close(iSock); 3500 if (fSharedMacOnWire) 3501 { 3502 rc = CFGMR3InsertInteger(pCfg, "SharedMacOnWire", true); 3503 RC_CHECK(); 3504 Log(("Set SharedMacOnWire\n")); 3650 int iSock = socket(AF_INET, SOCK_DGRAM, 0); 3651 if (iSock >= 0) 3652 { 3653 struct ieee80211req WReq; 3654 uint8_t abData[32]; 3655 3656 memset(&WReq, 0, sizeof(WReq)); 3657 strncpy(WReq.i_name, pszHifName, sizeof(WReq.i_name)); 3658 WReq.i_type = IEEE80211_IOC_SSID; 3659 WReq.i_val = -1; 3660 WReq.i_data = abData; 3661 WReq.i_len = sizeof(abData); 3662 3663 bool fSharedMacOnWire = ioctl(iSock, SIOCG80211, &WReq) >= 0; 3664 close(iSock); 3665 if (fSharedMacOnWire) 3666 { 3667 InsertConfigInteger(pCfg, "SharedMacOnWire", true); 3668 Log(("Set SharedMacOnWire\n")); 3669 } 3670 else 3671 Log(("Failed to get wireless name\n")); 3505 3672 } 3506 3673 else 3507 Log(("Failed to get wireless name\n")); 3508 } 3509 else 3510 Log(("Failed to open wireless socket\n")); 3674 Log(("Failed to open wireless socket\n")); 3511 3675 # elif defined(RT_OS_WINDOWS) 3512 3676 # define DEVNAME_PREFIX L"\\\\.\\" 3513 /* we are getting the medium type via IOCTL_NDIS_QUERY_GLOBAL_STATS Io Control 3514 * there is a pretty long way till there though since we need to obtain the symbolic link name 3515 * for the adapter device we are going to query given the device Guid */ 3516 3517 3518 /* prepend the "\\\\.\\" to the bind name to obtain the link name */ 3519 3520 wchar_t FileName[MAX_PATH]; 3521 wcscpy(FileName, DEVNAME_PREFIX); 3522 wcscpy((wchar_t*)(((char*)FileName) + sizeof(DEVNAME_PREFIX) - sizeof(FileName[0])), pswzBindName); 3523 3524 /* open the device */ 3525 HANDLE hDevice = CreateFile(FileName, 3526 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 3527 NULL, 3528 OPEN_EXISTING, 3529 FILE_ATTRIBUTE_NORMAL, 3530 NULL); 3531 3532 if (hDevice != INVALID_HANDLE_VALUE) 3533 { 3534 bool fSharedMacOnWire = false; 3535 3536 /* now issue the OID_GEN_PHYSICAL_MEDIUM query */ 3537 DWORD Oid = OID_GEN_PHYSICAL_MEDIUM; 3538 NDIS_PHYSICAL_MEDIUM PhMedium; 3539 DWORD cbResult; 3540 if (DeviceIoControl(hDevice, 3541 IOCTL_NDIS_QUERY_GLOBAL_STATS, 3542 &Oid, 3543 sizeof(Oid), 3544 &PhMedium, 3545 sizeof(PhMedium), 3546 &cbResult, 3547 NULL)) 3548 { 3549 /* that was simple, now examine PhMedium */ 3550 if ( PhMedium == NdisPhysicalMediumWirelessWan 3551 || PhMedium == NdisPhysicalMediumWirelessLan 3552 || PhMedium == NdisPhysicalMediumNative802_11 3553 || PhMedium == NdisPhysicalMediumBluetooth) 3554 fSharedMacOnWire = true; 3677 /* we are getting the medium type via IOCTL_NDIS_QUERY_GLOBAL_STATS Io Control 3678 * there is a pretty long way till there though since we need to obtain the symbolic link name 3679 * for the adapter device we are going to query given the device Guid */ 3680 3681 3682 /* prepend the "\\\\.\\" to the bind name to obtain the link name */ 3683 3684 wchar_t FileName[MAX_PATH]; 3685 wcscpy(FileName, DEVNAME_PREFIX); 3686 wcscpy((wchar_t*)(((char*)FileName) + sizeof(DEVNAME_PREFIX) - sizeof(FileName[0])), pswzBindName); 3687 3688 /* open the device */ 3689 HANDLE hDevice = CreateFile(FileName, 3690 GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 3691 NULL, 3692 OPEN_EXISTING, 3693 FILE_ATTRIBUTE_NORMAL, 3694 NULL); 3695 3696 if (hDevice != INVALID_HANDLE_VALUE) 3697 { 3698 bool fSharedMacOnWire = false; 3699 3700 /* now issue the OID_GEN_PHYSICAL_MEDIUM query */ 3701 DWORD Oid = OID_GEN_PHYSICAL_MEDIUM; 3702 NDIS_PHYSICAL_MEDIUM PhMedium; 3703 DWORD cbResult; 3704 if (DeviceIoControl(hDevice, 3705 IOCTL_NDIS_QUERY_GLOBAL_STATS, 3706 &Oid, 3707 sizeof(Oid), 3708 &PhMedium, 3709 sizeof(PhMedium), 3710 &cbResult, 3711 NULL)) 3712 { 3713 /* that was simple, now examine PhMedium */ 3714 if ( PhMedium == NdisPhysicalMediumWirelessWan 3715 || PhMedium == NdisPhysicalMediumWirelessLan 3716 || PhMedium == NdisPhysicalMediumNative802_11 3717 || PhMedium == NdisPhysicalMediumBluetooth) 3718 fSharedMacOnWire = true; 3719 } 3720 else 3721 { 3722 int winEr = GetLastError(); 3723 LogRel(("Console::configConstructor: DeviceIoControl failed, err (0x%x), ignoring\n", winEr)); 3724 Assert(winEr == ERROR_INVALID_PARAMETER || winEr == ERROR_NOT_SUPPORTED || winEr == ERROR_BAD_COMMAND); 3725 } 3726 CloseHandle(hDevice); 3727 3728 if (fSharedMacOnWire) 3729 { 3730 Log(("this is a wireless adapter")); 3731 InsertConfigInteger(pCfg, "SharedMacOnWire", true); 3732 Log(("Set SharedMacOnWire\n")); 3733 } 3734 else 3735 Log(("this is NOT a wireless adapter")); 3555 3736 } 3556 3737 else 3557 3738 { 3558 3739 int winEr = GetLastError(); 3559 LogRel(("Console::configConstructor: DeviceIoControl failed, err (0x%x), ignoring\n", winEr)); 3560 Assert(winEr == ERROR_INVALID_PARAMETER || winEr == ERROR_NOT_SUPPORTED || winEr == ERROR_BAD_COMMAND); 3561 } 3562 CloseHandle(hDevice); 3563 3564 if (fSharedMacOnWire) 3565 { 3566 Log(("this is a wireless adapter")); 3567 rc = CFGMR3InsertInteger(pCfg, "SharedMacOnWire", true); RC_CHECK(); 3568 Log(("Set SharedMacOnWire\n")); 3569 } 3570 else 3571 Log(("this is NOT a wireless adapter")); 3572 } 3573 else 3574 { 3575 int winEr = GetLastError(); 3576 AssertLogRelMsgFailed(("Console::configConstructor: CreateFile failed, err (0x%x), ignoring\n", winEr)); 3577 } 3578 3579 CoTaskMemFree(pswzBindName); 3580 3581 pAdaptorComponent.setNull(); 3582 /* release the pNc finally */ 3583 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/); 3740 AssertLogRelMsgFailed(("Console::configConstructor: CreateFile failed, err (0x%x), ignoring\n", winEr)); 3741 } 3742 3743 CoTaskMemFree(pswzBindName); 3744 3745 pAdaptorComponent.setNull(); 3746 /* release the pNc finally */ 3747 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/); 3584 3748 # else 3585 /** @todo PORTME: wireless detection */3749 /** @todo PORTME: wireless detection */ 3586 3750 # endif 3587 3751 … … 3592 3756 if (ZoneId != GLOBAL_ZONEID) 3593 3757 { 3594 rc = CFGMR3InsertInteger(pCfg, "IgnoreAllPromisc", true); RC_CHECK();3758 InsertConfigInteger(pCfg, "IgnoreAllPromisc", true); 3595 3759 } 3596 3760 # endif … … 3606 3770 # error "Port me" 3607 3771 #endif 3608 break; 3609 } 3610 3611 case NetworkAttachmentType_Internal: 3612 { 3613 hrc = aNetworkAdapter->COMGETTER(InternalNetwork)(bstr.asOutParam()); H(); 3614 if (!bstr.isEmpty()) 3772 break; 3773 } 3774 3775 case NetworkAttachmentType_Internal: 3776 { 3777 hrc = aNetworkAdapter->COMGETTER(InternalNetwork)(bstr.asOutParam()); H(); 3778 if (!bstr.isEmpty()) 3779 { 3780 if (fSniffer) 3781 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0); 3782 else 3783 InsertConfigNode(pInst, "LUN#0", &pLunL0); 3784 InsertConfigString(pLunL0, "Driver", "IntNet"); 3785 InsertConfigNode(pLunL0, "Config", &pCfg); 3786 InsertConfigString(pCfg, "Network", bstr); 3787 InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_WhateverNone); 3788 networkName = bstr; 3789 trunkType = Bstr(TRUNKTYPE_WHATEVER); 3790 } 3791 break; 3792 } 3793 3794 case NetworkAttachmentType_HostOnly: 3615 3795 { 3616 3796 if (fSniffer) 3617 { 3618 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); 3619 RC_CHECK(); 3620 } 3797 InsertConfigNode(pLunL0, "AttachedDriver", &pLunL0); 3621 3798 else 3622 { 3623 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); 3624 RC_CHECK(); 3625 } 3626 rc = CFGMR3InsertString(pLunL0, "Driver", "IntNet"); RC_CHECK(); 3627 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 3628 rc = CFGMR3InsertStringW(pCfg, "Network", bstr); RC_CHECK(); 3629 rc = CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_WhateverNone); RC_CHECK(); 3630 networkName = bstr; 3631 trunkType = Bstr(TRUNKTYPE_WHATEVER); 3632 } 3633 break; 3634 } 3635 3636 case NetworkAttachmentType_HostOnly: 3637 { 3638 if (fSniffer) 3639 { 3640 rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL0); 3641 RC_CHECK(); 3642 } 3643 else 3644 { 3645 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); 3646 RC_CHECK(); 3647 } 3648 3649 rc = CFGMR3InsertString(pLunL0, "Driver", "IntNet"); RC_CHECK(); 3650 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 3651 3652 Bstr HifName; 3653 hrc = aNetworkAdapter->COMGETTER(HostInterface)(HifName.asOutParam()); 3654 if (FAILED(hrc)) 3655 { 3656 LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(HostInterface) failed, hrc (0x%x)\n", hrc)); 3657 H(); 3658 } 3659 3660 Utf8Str HifNameUtf8(HifName); 3661 const char *pszHifName = HifNameUtf8.raw(); 3662 ComPtr<IHostNetworkInterface> hostInterface; 3663 rc = host->FindHostNetworkInterfaceByName(HifName, hostInterface.asOutParam()); 3664 if (!SUCCEEDED(rc)) 3665 { 3666 LogRel(("NetworkAttachmentType_HostOnly: FindByName failed, rc (0x%x)\n", rc)); 3667 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS, 3668 N_("Inexistent host networking interface, name '%ls'"), 3669 HifName.raw()); 3670 } 3671 3672 char szNetwork[INTNET_MAX_NETWORK_NAME]; 3673 RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszHifName); 3799 InsertConfigNode(pInst, "LUN#0", &pLunL0); 3800 3801 InsertConfigString(pLunL0, "Driver", "IntNet"); 3802 InsertConfigNode(pLunL0, "Config", &pCfg); 3803 3804 Bstr HifName; 3805 hrc = aNetworkAdapter->COMGETTER(HostInterface)(HifName.asOutParam()); 3806 if (FAILED(hrc)) 3807 { 3808 LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(HostInterface) failed, hrc (0x%x)\n", hrc)); 3809 H(); 3810 } 3811 3812 Utf8Str HifNameUtf8(HifName); 3813 const char *pszHifName = HifNameUtf8.raw(); 3814 ComPtr<IHostNetworkInterface> hostInterface; 3815 rc = host->FindHostNetworkInterfaceByName(HifName, hostInterface.asOutParam()); 3816 if (!SUCCEEDED(rc)) 3817 { 3818 LogRel(("NetworkAttachmentType_HostOnly: FindByName failed, rc (0x%x)\n", rc)); 3819 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS, 3820 N_("Inexistent host networking interface, name '%ls'"), 3821 HifName.raw()); 3822 } 3823 3824 char szNetwork[INTNET_MAX_NETWORK_NAME]; 3825 RTStrPrintf(szNetwork, sizeof(szNetwork), "HostInterfaceNetworking-%s", pszHifName); 3674 3826 3675 3827 #if defined(RT_OS_WINDOWS) 3676 3828 # ifndef VBOX_WITH_NETFLT 3677 hrc = E_NOTIMPL;3678 LogRel(("NetworkAttachmentType_HostOnly: Not Implemented\n"));3679 H();3829 hrc = E_NOTIMPL; 3830 LogRel(("NetworkAttachmentType_HostOnly: Not Implemented\n")); 3831 H(); 3680 3832 # else /* defined VBOX_WITH_NETFLT*/ 3681 /** @todo r=bird: Put this in a function. */ 3682 3683 HostNetworkInterfaceType_T eIfType; 3684 hrc = hostInterface->COMGETTER(InterfaceType)(&eIfType); 3685 if (FAILED(hrc)) 3686 { 3687 LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(InterfaceType) failed, hrc (0x%x)\n", hrc)); 3688 H(); 3689 } 3690 3691 if (eIfType != HostNetworkInterfaceType_HostOnly) 3692 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS, 3693 N_("Interface ('%ls') is not a Host-Only Adapter interface"), 3694 HifName.raw()); 3695 3696 hrc = hostInterface->COMGETTER(Id)(bstr.asOutParam()); 3697 if (FAILED(hrc)) 3698 { 3699 LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(Id) failed, hrc (0x%x)\n", hrc)); 3700 H(); 3701 } 3702 Guid hostIFGuid(bstr); 3703 3704 INetCfg *pNc; 3705 ComPtr<INetCfgComponent> pAdaptorComponent; 3706 LPWSTR pszApp; 3707 rc = VERR_INTNET_FLT_IF_NOT_FOUND; 3708 3709 hrc = VBoxNetCfgWinQueryINetCfg(FALSE, 3710 L"VirtualBox", 3711 &pNc, 3712 &pszApp); 3713 Assert(hrc == S_OK); 3714 if (hrc == S_OK) 3715 { 3716 /* get the adapter's INetCfgComponent*/ 3717 hrc = VBoxNetCfgWinGetComponentByGuid(pNc, &GUID_DEVCLASS_NET, (GUID*)hostIFGuid.ptr(), pAdaptorComponent.asOutParam()); 3718 if (hrc != S_OK) 3833 /** @todo r=bird: Put this in a function. */ 3834 3835 HostNetworkInterfaceType_T eIfType; 3836 hrc = hostInterface->COMGETTER(InterfaceType)(&eIfType); 3837 if (FAILED(hrc)) 3838 { 3839 LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(InterfaceType) failed, hrc (0x%x)\n", hrc)); 3840 H(); 3841 } 3842 3843 if (eIfType != HostNetworkInterfaceType_HostOnly) 3844 return VMSetError(pVM, VERR_INTERNAL_ERROR, RT_SRC_POS, 3845 N_("Interface ('%ls') is not a Host-Only Adapter interface"), 3846 HifName.raw()); 3847 3848 hrc = hostInterface->COMGETTER(Id)(bstr.asOutParam()); 3849 if (FAILED(hrc)) 3850 { 3851 LogRel(("NetworkAttachmentType_HostOnly: COMGETTER(Id) failed, hrc (0x%x)\n", hrc)); 3852 H(); 3853 } 3854 Guid hostIFGuid(bstr); 3855 3856 INetCfg *pNc; 3857 ComPtr<INetCfgComponent> pAdaptorComponent; 3858 LPWSTR pszApp; 3859 rc = VERR_INTNET_FLT_IF_NOT_FOUND; 3860 3861 hrc = VBoxNetCfgWinQueryINetCfg(FALSE, 3862 L"VirtualBox", 3863 &pNc, 3864 &pszApp); 3865 Assert(hrc == S_OK); 3866 if (hrc == S_OK) 3867 { 3868 /* get the adapter's INetCfgComponent*/ 3869 hrc = VBoxNetCfgWinGetComponentByGuid(pNc, &GUID_DEVCLASS_NET, (GUID*)hostIFGuid.ptr(), pAdaptorComponent.asOutParam()); 3870 if (hrc != S_OK) 3871 { 3872 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/); 3873 LogRel(("NetworkAttachmentType_HostOnly: VBoxNetCfgWinGetComponentByGuid failed, hrc=%Rhrc (0x%x)\n", hrc, hrc)); 3874 H(); 3875 } 3876 } 3877 #define VBOX_WIN_BINDNAME_PREFIX "\\DEVICE\\" 3878 char szTrunkName[INTNET_MAX_TRUNK_NAME]; 3879 char *pszTrunkName = szTrunkName; 3880 wchar_t * pswzBindName; 3881 hrc = pAdaptorComponent->GetBindName(&pswzBindName); 3882 Assert(hrc == S_OK); 3883 if (hrc == S_OK) 3884 { 3885 int cwBindName = (int)wcslen(pswzBindName) + 1; 3886 int cbFullBindNamePrefix = sizeof(VBOX_WIN_BINDNAME_PREFIX); 3887 if (sizeof(szTrunkName) > cbFullBindNamePrefix + cwBindName) 3888 { 3889 strcpy(szTrunkName, VBOX_WIN_BINDNAME_PREFIX); 3890 pszTrunkName += cbFullBindNamePrefix-1; 3891 if (!WideCharToMultiByte(CP_ACP, 0, pswzBindName, cwBindName, pszTrunkName, 3892 sizeof(szTrunkName) - cbFullBindNamePrefix + 1, NULL, NULL)) 3893 { 3894 DWORD err = GetLastError(); 3895 hrc = HRESULT_FROM_WIN32(err); 3896 AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: WideCharToMultiByte failed, hr=%Rhrc (0x%x) err=%u\n", hrc, hrc, err)); 3897 } 3898 } 3899 else 3900 { 3901 AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: insufficient szTrunkName buffer space\n")); 3902 /** @todo set appropriate error code */ 3903 hrc = E_FAIL; 3904 } 3905 3906 if (hrc != S_OK) 3907 { 3908 AssertFailed(); 3909 CoTaskMemFree(pswzBindName); 3910 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/); 3911 H(); 3912 } 3913 } 3914 else 3719 3915 { 3720 3916 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/); 3721 LogRel(("NetworkAttachmentType_HostOnly: VBoxNetCfgWinGetComponentByGuid failed, hrc=%Rhrc (0x%x)\n", hrc, hrc));3917 AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: VBoxNetCfgWinGetComponentByGuid failed, hrc=%Rhrc (0x%x)\n", hrc, hrc)); 3722 3918 H(); 3723 3919 } 3724 } 3725 #define VBOX_WIN_BINDNAME_PREFIX "\\DEVICE\\" 3726 char szTrunkName[INTNET_MAX_TRUNK_NAME]; 3727 char *pszTrunkName = szTrunkName; 3728 wchar_t * pswzBindName; 3729 hrc = pAdaptorComponent->GetBindName(&pswzBindName); 3730 Assert(hrc == S_OK); 3731 if (hrc == S_OK) 3732 { 3733 int cwBindName = (int)wcslen(pswzBindName) + 1; 3734 int cbFullBindNamePrefix = sizeof(VBOX_WIN_BINDNAME_PREFIX); 3735 if (sizeof(szTrunkName) > cbFullBindNamePrefix + cwBindName) 3736 { 3737 strcpy(szTrunkName, VBOX_WIN_BINDNAME_PREFIX); 3738 pszTrunkName += cbFullBindNamePrefix-1; 3739 if (!WideCharToMultiByte(CP_ACP, 0, pswzBindName, cwBindName, pszTrunkName, 3740 sizeof(szTrunkName) - cbFullBindNamePrefix + 1, NULL, NULL)) 3741 { 3742 DWORD err = GetLastError(); 3743 hrc = HRESULT_FROM_WIN32(err); 3744 AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: WideCharToMultiByte failed, hr=%Rhrc (0x%x) err=%u\n", hrc, hrc, err)); 3745 } 3746 } 3747 else 3748 { 3749 AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: insufficient szTrunkName buffer space\n")); 3750 /** @todo set appropriate error code */ 3751 hrc = E_FAIL; 3752 } 3753 3754 if (hrc != S_OK) 3755 { 3756 AssertFailed(); 3757 CoTaskMemFree(pswzBindName); 3758 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/); 3759 H(); 3760 } 3761 } 3762 else 3763 { 3920 3921 3922 CoTaskMemFree(pswzBindName); 3923 3924 pAdaptorComponent.setNull(); 3925 /* release the pNc finally */ 3764 3926 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/); 3765 AssertLogRelMsgFailed(("NetworkAttachmentType_HostOnly: VBoxNetCfgWinGetComponentByGuid failed, hrc=%Rhrc (0x%x)\n", hrc, hrc)); 3766 H(); 3767 } 3768 3769 3770 CoTaskMemFree(pswzBindName); 3771 3772 pAdaptorComponent.setNull(); 3773 /* release the pNc finally */ 3774 VBoxNetCfgWinReleaseINetCfg(pNc, FALSE /*fHasWriteLock*/); 3775 3776 const char *pszTrunk = szTrunkName; 3777 3778 rc = CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_NetAdp); RC_CHECK(); 3779 rc = CFGMR3InsertString(pCfg, "Trunk", pszTrunk); RC_CHECK(); 3780 rc = CFGMR3InsertString(pCfg, "Network", szNetwork); RC_CHECK(); 3781 networkName = Bstr(szNetwork); 3782 trunkName = Bstr(pszTrunk); 3783 trunkType = TRUNKTYPE_NETADP; 3927 3928 const char *pszTrunk = szTrunkName; 3929 3930 InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_NetAdp); 3931 InsertConfigString(pCfg, "Trunk", pszTrunk); 3932 InsertConfigString(pCfg, "Network", szNetwork); 3933 networkName = Bstr(szNetwork); 3934 trunkName = Bstr(pszTrunk); 3935 trunkType = TRUNKTYPE_NETADP; 3784 3936 # endif /* defined VBOX_WITH_NETFLT*/ 3785 3937 #elif defined(RT_OS_DARWIN) 3786 rc = CFGMR3InsertString(pCfg, "Trunk", pszHifName); RC_CHECK();3787 rc = CFGMR3InsertString(pCfg, "Network", szNetwork); RC_CHECK();3788 rc = CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_NetAdp); RC_CHECK();3789 networkName = Bstr(szNetwork);3790 trunkName = Bstr(pszHifName);3791 trunkType = TRUNKTYPE_NETADP;3938 InsertConfigString(pCfg, "Trunk", pszHifName); 3939 InsertConfigString(pCfg, "Network", szNetwork); 3940 InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_NetAdp); 3941 networkName = Bstr(szNetwork); 3942 trunkName = Bstr(pszHifName); 3943 trunkType = TRUNKTYPE_NETADP; 3792 3944 #else 3793 rc = CFGMR3InsertString(pCfg, "Trunk", pszHifName); RC_CHECK();3794 rc = CFGMR3InsertString(pCfg, "Network", szNetwork); RC_CHECK();3795 rc = CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_NetFlt); RC_CHECK();3796 networkName = Bstr(szNetwork);3797 trunkName = Bstr(pszHifName);3798 trunkType = TRUNKTYPE_NETFLT;3945 InsertConfigString(pCfg, "Trunk", pszHifName); 3946 InsertConfigString(pCfg, "Network", szNetwork); 3947 InsertConfigInteger(pCfg, "TrunkType", kIntNetTrunkType_NetFlt); 3948 networkName = Bstr(szNetwork); 3949 trunkName = Bstr(pszHifName); 3950 trunkType = TRUNKTYPE_NETFLT; 3799 3951 #endif 3800 3952 #if !defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) 3801 3953 3802 Bstr tmpAddr, tmpMask; 3803 3804 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPAddress", pszHifName), tmpAddr.asOutParam()); 3805 if (SUCCEEDED(hrc) && !tmpAddr.isEmpty()) 3806 { 3807 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPNetMask", pszHifName), tmpMask.asOutParam()); 3808 if (SUCCEEDED(hrc) && !tmpMask.isEmpty()) 3809 hrc = hostInterface->EnableStaticIpConfig(tmpAddr, tmpMask); 3954 Bstr tmpAddr, tmpMask; 3955 3956 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPAddress", pszHifName), tmpAddr.asOutParam()); 3957 if (SUCCEEDED(hrc) && !tmpAddr.isEmpty()) 3958 { 3959 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPNetMask", pszHifName), tmpMask.asOutParam()); 3960 if (SUCCEEDED(hrc) && !tmpMask.isEmpty()) 3961 hrc = hostInterface->EnableStaticIpConfig(tmpAddr, tmpMask); 3962 else 3963 hrc = hostInterface->EnableStaticIpConfig(tmpAddr, 3964 Bstr(VBOXNET_IPV4MASK_DEFAULT)); 3965 } 3810 3966 else 3811 hrc = hostInterface->EnableStaticIpConfig(tmpAddr, 3812 Bstr(VBOXNET_IPV4MASK_DEFAULT)); 3813 } 3814 else 3815 { 3816 /* Grab the IP number from the 'vboxnetX' instance number (see netif.h) */ 3817 hrc = hostInterface->EnableStaticIpConfig(getDefaultIPv4Address(Bstr(pszHifName)), 3818 Bstr(VBOXNET_IPV4MASK_DEFAULT)); 3819 } 3820 3821 ComAssertComRC(hrc); /** @todo r=bird: Why this isn't fatal? (H()) */ 3822 3823 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6Address", pszHifName), tmpAddr.asOutParam()); 3824 if (SUCCEEDED(hrc)) 3825 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6NetMask", pszHifName), tmpMask.asOutParam()); 3826 if (SUCCEEDED(hrc) && !tmpAddr.isEmpty() && !tmpMask.isEmpty()) 3827 { 3828 hrc = hostInterface->EnableStaticIpConfigV6(tmpAddr, Utf8Str(tmpMask).toUInt32()); 3967 { 3968 /* Grab the IP number from the 'vboxnetX' instance number (see netif.h) */ 3969 hrc = hostInterface->EnableStaticIpConfig(getDefaultIPv4Address(Bstr(pszHifName)), 3970 Bstr(VBOXNET_IPV4MASK_DEFAULT)); 3971 } 3972 3829 3973 ComAssertComRC(hrc); /** @todo r=bird: Why this isn't fatal? (H()) */ 3830 } 3974 3975 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6Address", pszHifName), tmpAddr.asOutParam()); 3976 if (SUCCEEDED(hrc)) 3977 hrc = virtualBox->GetExtraData(BstrFmt("HostOnly/%s/IPV6NetMask", pszHifName), tmpMask.asOutParam()); 3978 if (SUCCEEDED(hrc) && !tmpAddr.isEmpty() && !tmpMask.isEmpty()) 3979 { 3980 hrc = hostInterface->EnableStaticIpConfigV6(tmpAddr, Utf8Str(tmpMask).toUInt32()); 3981 ComAssertComRC(hrc); /** @todo r=bird: Why this isn't fatal? (H()) */ 3982 } 3831 3983 #endif 3832 break; 3984 break; 3985 } 3986 3987 #if defined(VBOX_WITH_VDE) 3988 case NetworkAttachmentType_VDE: 3989 { 3990 hrc = aNetworkAdapter->COMGETTER(VDENetwork)(bstr.asOutParam()); H(); 3991 InsertConfigNode(pInst, "LUN#0", &pLunL0); 3992 InsertConfigString(pLunL0, "Driver", "VDE"); 3993 InsertConfigNode(pLunL0, "Config", &pCfg); 3994 if (!bstr.isEmpty()) 3995 { 3996 InsertConfigString(pCfg, "Network", bstr); 3997 networkName = bstr; 3998 } 3999 break; 4000 } 4001 #endif 4002 4003 default: 4004 AssertMsgFailed(("should not get here!\n")); 4005 break; 3833 4006 } 3834 4007 4008 /* 4009 * Attempt to attach the driver. 4010 */ 4011 switch (eAttachmentType) 4012 { 4013 case NetworkAttachmentType_Null: 4014 break; 4015 4016 case NetworkAttachmentType_Bridged: 4017 case NetworkAttachmentType_Internal: 4018 case NetworkAttachmentType_HostOnly: 4019 case NetworkAttachmentType_NAT: 3835 4020 #if defined(VBOX_WITH_VDE) 3836 case NetworkAttachmentType_VDE: 3837 { 3838 hrc = aNetworkAdapter->COMGETTER(VDENetwork)(bstr.asOutParam()); H(); 3839 rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK(); 3840 rc = CFGMR3InsertString(pLunL0, "Driver", "VDE"); RC_CHECK(); 3841 rc = CFGMR3InsertNode(pLunL0, "Config", &pCfg); RC_CHECK(); 3842 if (!bstr.isEmpty()) 3843 { 3844 rc = CFGMR3InsertStringW(pCfg, "Network", bstr); RC_CHECK(); 3845 networkName = bstr; 3846 } 3847 break; 4021 case NetworkAttachmentType_VDE: 4022 #endif 4023 { 4024 if (SUCCEEDED(hrc) && SUCCEEDED(rc)) 4025 { 4026 if (fAttachDetach) 4027 { 4028 rc = PDMR3DriverAttach(pVM, pszDevice, uInstance, uLun, 0 /*fFlags*/, NULL /* ppBase */); 4029 //AssertRC(rc); 4030 } 4031 4032 { 4033 /** @todo pritesh: get the dhcp server name from the 4034 * previous network configuration and then stop the server 4035 * else it may conflict with the dhcp server running with 4036 * the current attachment type 4037 */ 4038 /* Stop the hostonly DHCP Server */ 4039 } 4040 4041 if (!networkName.isEmpty()) 4042 { 4043 /* 4044 * Until we implement service reference counters DHCP Server will be stopped 4045 * by DHCPServerRunner destructor. 4046 */ 4047 ComPtr<IDHCPServer> dhcpServer; 4048 hrc = virtualBox->FindDHCPServerByNetworkName(networkName, dhcpServer.asOutParam()); 4049 if (SUCCEEDED(hrc)) 4050 { 4051 /* there is a DHCP server available for this network */ 4052 BOOL fEnabled; 4053 hrc = dhcpServer->COMGETTER(Enabled)(&fEnabled); 4054 if (FAILED(hrc)) 4055 { 4056 LogRel(("DHCP svr: COMGETTER(Enabled) failed, hrc (%Rhrc)", hrc)); 4057 H(); 4058 } 4059 4060 if (fEnabled) 4061 hrc = dhcpServer->Start(networkName, trunkName, trunkType); 4062 } 4063 else 4064 hrc = S_OK; 4065 } 4066 } 4067 4068 break; 4069 } 4070 4071 default: 4072 AssertMsgFailed(("should not get here!\n")); 4073 break; 3848 4074 } 3849 #endif 3850 3851 default: 3852 AssertMsgFailed(("should not get here!\n")); 3853 break; 4075 4076 meAttachmentType[uInstance] = eAttachmentType; 3854 4077 } 3855 3856 /* 3857 * Attempt to attach the driver. 3858 */ 3859 switch (eAttachmentType) 4078 catch (ConfigError &x) 3860 4079 { 3861 case NetworkAttachmentType_Null: 3862 break; 3863 3864 case NetworkAttachmentType_Bridged: 3865 case NetworkAttachmentType_Internal: 3866 case NetworkAttachmentType_HostOnly: 3867 case NetworkAttachmentType_NAT: 3868 #if defined(VBOX_WITH_VDE) 3869 case NetworkAttachmentType_VDE: 3870 #endif 3871 { 3872 if (SUCCEEDED(hrc) && SUCCEEDED(rc)) 3873 { 3874 if (fAttachDetach) 3875 { 3876 rc = PDMR3DriverAttach(pVM, pszDevice, uInstance, uLun, 0 /*fFlags*/, NULL /* ppBase */); 3877 //AssertRC(rc); 3878 } 3879 3880 { 3881 /** @todo pritesh: get the dhcp server name from the 3882 * previous network configuration and then stop the server 3883 * else it may conflict with the dhcp server running with 3884 * the current attachment type 3885 */ 3886 /* Stop the hostonly DHCP Server */ 3887 } 3888 3889 if (!networkName.isEmpty()) 3890 { 3891 /* 3892 * Until we implement service reference counters DHCP Server will be stopped 3893 * by DHCPServerRunner destructor. 3894 */ 3895 ComPtr<IDHCPServer> dhcpServer; 3896 hrc = virtualBox->FindDHCPServerByNetworkName(networkName, dhcpServer.asOutParam()); 3897 if (SUCCEEDED(hrc)) 3898 { 3899 /* there is a DHCP server available for this network */ 3900 BOOL fEnabled; 3901 hrc = dhcpServer->COMGETTER(Enabled)(&fEnabled); 3902 if (FAILED(hrc)) 3903 { 3904 LogRel(("DHCP svr: COMGETTER(Enabled) failed, hrc (%Rhrc)", hrc)); 3905 H(); 3906 } 3907 3908 if (fEnabled) 3909 hrc = dhcpServer->Start(networkName, trunkName, trunkType); 3910 } 3911 else 3912 hrc = S_OK; 3913 } 3914 } 3915 3916 break; 3917 } 3918 3919 default: 3920 AssertMsgFailed(("should not get here!\n")); 3921 break; 4080 // InsertConfig threw something: 4081 return x.m_vrc; 3922 4082 } 3923 4083 3924 meAttachmentType[uInstance] = eAttachmentType;3925 3926 4084 #undef H 3927 #undef RC_CHECK3928 4085 3929 4086 return VINF_SUCCESS; … … 3934 4091 * Set an array of guest properties 3935 4092 */ 3936 static void configSetProperties(VMMDev * const pVMMDev, void *names, 3937 void *values, void *timestamps, void *flags) 4093 static void configSetProperties(VMMDev * const pVMMDev, 4094 void *names, 4095 void *values, 4096 void *timestamps, 4097 void *flags) 3938 4098 { 3939 4099 VBOXHGCMSVCPARM parms[4]; -
trunk/src/VBox/Main/VirtualBoxImpl.cpp
r30742 r30746 4082 4082 throw; 4083 4083 } 4084 catch (const xml::Error &err)4084 catch (const iprt::Error &err) // includes all XML exceptions 4085 4085 { 4086 4086 return setErrorStatic(E_FAIL, -
trunk/src/VBox/Runtime/r3/xml.cpp
r29873 r30746 1384 1384 } 1385 1385 1386 void setError(const xml::Error &x)1386 void setError(const iprt::Error &x) 1387 1387 { 1388 1388 error = x.what(); … … 1456 1456 } 1457 1457 catch (const xml::EIPRTFailure &err) { pContext->setError(err); } 1458 catch (const xml::Error &err) { pContext->setError(err); }1458 catch (const iprt::Error &err) { pContext->setError(err); } 1459 1459 catch (const std::exception &err) { pContext->setError(err); } 1460 1460 catch (...) { pContext->setError(xml::LogicError(RT_SRC_POS)); } … … 1581 1581 } 1582 1582 catch (const xml::EIPRTFailure &err) { pContext->setError(err); } 1583 catch (const xml::Error &err) { pContext->setError(err); }1583 catch (const iprt::Error &err) { pContext->setError(err); } 1584 1584 catch (const std::exception &err) { pContext->setError(err); } 1585 1585 catch (...) { pContext->setError(xml::LogicError(RT_SRC_POS)); }
Note:
See TracChangeset
for help on using the changeset viewer.