Changeset 8230 in vbox
- Timestamp:
- Apr 21, 2008 2:13:27 PM (17 years ago)
- Location:
- trunk/src/VBox/Frontends/VBoxManage
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk
r8155 r8230 36 36 VBoxInternalManage.cpp \ 37 37 VBoxManageSVN.cpp 38 ifndef VBOX_OSE39 VBoxManage_SOURCES += \40 VBoxInternalManageVmdk.cpp41 endif42 38 VBoxManage_LIBS += $(LIB_DDU) 43 39 -
trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp
r8155 r8230 44 44 45 45 #include <VBox/VBoxHDD.h> 46 #include <VBox/VBoxHDD-new.h> 46 47 #include <VBox/sup.h> 47 48 48 49 #include "VBoxManage.h" 49 50 50 #ifndef VBOX_OSE 51 HRESULT CmdListPartitions(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession); 52 HRESULT CmdCreateRawVMDK(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession); 53 #endif /* !VBOX_OSE */ 51 /* Includes for the raw disk stuff. */ 52 #ifdef RT_OS_WINDOWS 53 #include <windows.h> 54 #include <winioctl.h> 55 #elif RT_OS_LINUX 56 #include <errno.h> 57 #include <sys/ioctl.h> 58 #include <sys/types.h> 59 #include <sys/stat.h> 60 #include <unistd.h> 61 #include <linux/hdreg.h> 62 #include <linux/fs.h> 63 #endif /* !RT_OS_WINDOWS && !RT_OS_LINUX */ 54 64 55 65 using namespace com; 66 67 68 /** Macro for checking whether a partition is of extended type or not. */ 69 #define PARTTYPE_IS_EXTENDED(x) ((x) == 0x05 || (x) == 0x0f || (x) == 0x85) 70 71 /* Maximum number of partitions we can deal with. Ridiculously large number, 72 * but the memory consumption is rather low so who cares about never using 73 * most entries. */ 74 #define HOSTPARTITION_MAX 100 75 76 77 typedef struct HOSTPARTITION 78 { 79 unsigned uIndex; 80 unsigned uType; 81 unsigned uStartCylinder; 82 unsigned uStartHead; 83 unsigned uStartSector; 84 unsigned uEndCylinder; 85 unsigned uEndHead; 86 unsigned uEndSector; 87 uint64_t uStart; 88 uint64_t uSize; 89 uint64_t uPartDataStart; 90 uint64_t cPartDataSectors; 91 } HOSTPARTITION, *PHOSTPARTITION; 92 93 typedef struct HOSTPARTITIONS 94 { 95 unsigned cPartitions; 96 HOSTPARTITION aPartitions[HOSTPARTITION_MAX]; 97 } HOSTPARTITIONS, *PHOSTPARTITIONS; 56 98 57 99 /** flag whether we're in internal mode */ … … 414 456 } 415 457 458 459 static DECLCALLBACK(void) handleVDError(void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va) 460 { 461 RTPrintf("ERROR: "); 462 RTPrintfV(pszFormat, va); 463 RTPrintf("\n"); 464 RTPrintf("Error code %Vrc at %s(%u) in function %s\n", rc, RT_SRC_POS_ARGS); 465 } 466 467 static int partRead(RTFILE File, PHOSTPARTITIONS pPart) 468 { 469 uint8_t aBuffer[512]; 470 int rc; 471 472 pPart->cPartitions = 0; 473 memset(pPart->aPartitions, '\0', sizeof(pPart->aPartitions)); 474 rc = RTFileReadAt(File, 0, &aBuffer, sizeof(aBuffer), NULL); 475 if (VBOX_FAILURE(rc)) 476 return rc; 477 if (aBuffer[510] != 0x55 || aBuffer[511] != 0xaa) 478 return VERR_INVALID_PARAMETER; 479 480 unsigned uExtended = (unsigned)-1; 481 482 for (unsigned i = 0; i < 4; i++) 483 { 484 uint8_t *p = &aBuffer[0x1be + i * 16]; 485 if (p[4] == 0) 486 continue; 487 PHOSTPARTITION pCP = &pPart->aPartitions[pPart->cPartitions++]; 488 pCP->uIndex = i + 1; 489 pCP->uType = p[4]; 490 pCP->uStartCylinder = (uint32_t)p[3] + ((uint32_t)(p[2] & 0xc0) << 2); 491 pCP->uStartHead = p[1]; 492 pCP->uStartSector = p[2] & 0x3f; 493 pCP->uEndCylinder = (uint32_t)p[7] + ((uint32_t)(p[6] & 0xc0) << 2); 494 pCP->uEndHead = p[5]; 495 pCP->uEndSector = p[6] & 0x3f; 496 pCP->uStart = RT_MAKE_U32_FROM_U8(p[8], p[9], p[10], p[11]); 497 pCP->uSize = RT_MAKE_U32_FROM_U8(p[12], p[13], p[14], p[15]); 498 pCP->uPartDataStart = 0; /* will be filled out later properly. */ 499 pCP->cPartDataSectors = 0; 500 501 if (PARTTYPE_IS_EXTENDED(p[4])) 502 { 503 if (uExtended == (unsigned)-1) 504 uExtended = pCP - pPart->aPartitions; 505 else 506 { 507 RTPrintf("More than one extended partition. Aborting\n"); 508 return VERR_INVALID_PARAMETER; 509 } 510 } 511 } 512 513 if (uExtended != (unsigned)-1) 514 { 515 unsigned uIndex = 5; 516 uint64_t uStart = pPart->aPartitions[uExtended].uStart; 517 uint64_t uOffset = 0; 518 if (!uStart) 519 { 520 RTPrintf("Inconsistency for logical partition start. Aborting\n"); 521 return VERR_INVALID_PARAMETER; 522 } 523 524 do 525 { 526 rc = RTFileReadAt(File, (uStart + uOffset) * 512, &aBuffer, sizeof(aBuffer), NULL); 527 if (VBOX_FAILURE(rc)) 528 return rc; 529 530 if (aBuffer[510] != 0x55 || aBuffer[511] != 0xaa) 531 { 532 RTPrintf("Logical partition without magic. Aborting\n"); 533 return VERR_INVALID_PARAMETER; 534 } 535 uint8_t *p = &aBuffer[0x1be]; 536 537 if (p[4] == 0) 538 { 539 RTPrintf("Logical partition with type 0 encountered. Aborting\n"); 540 return VERR_INVALID_PARAMETER; 541 } 542 543 PHOSTPARTITION pCP = &pPart->aPartitions[pPart->cPartitions++]; 544 pCP->uIndex = uIndex; 545 pCP->uType = p[4]; 546 pCP->uStartCylinder = (uint32_t)p[3] + ((uint32_t)(p[2] & 0xc0) << 2); 547 pCP->uStartHead = p[1]; 548 pCP->uStartSector = p[2] & 0x3f; 549 pCP->uEndCylinder = (uint32_t)p[7] + ((uint32_t)(p[6] & 0xc0) << 2); 550 pCP->uEndHead = p[5]; 551 pCP->uEndSector = p[6] & 0x3f; 552 uint32_t uStartOffset = RT_MAKE_U32_FROM_U8(p[8], p[9], p[10], p[11]); 553 pCP->uStart = uStart + uOffset + uStartOffset; 554 pCP->uSize = RT_MAKE_U32_FROM_U8(p[12], p[13], p[14], p[15]); 555 /* Fill out partitioning location info for EBR. */ 556 pCP->uPartDataStart = uStart + uOffset; 557 pCP->cPartDataSectors = RT_MIN(uStartOffset, 63); 558 p += 16; 559 if (p[4] == 0) 560 uExtended = (unsigned)-1; 561 else if (PARTTYPE_IS_EXTENDED(p[4])) 562 { 563 uExtended = uIndex++; 564 uOffset = RT_MAKE_U32_FROM_U8(p[8], p[9], p[10], p[11]); 565 } 566 else 567 { 568 RTPrintf("Logical partition chain broken. Aborting\n"); 569 return VERR_INVALID_PARAMETER; 570 } 571 } while (uExtended != (unsigned)-1); 572 } 573 574 /* Sort partitions in ascending order of start sector. Also do a lot of 575 * consistency checking. */ 576 uint64_t uPrevEnd = 0; 577 for (unsigned i = 0; i < pPart->cPartitions-1; i++) 578 { 579 unsigned uMinIdx = i; 580 uint64_t uMinVal = pPart->aPartitions[i].uStart; 581 for (unsigned j = i + 1; j < pPart->cPartitions; j++) 582 { 583 if (pPart->aPartitions[j].uStart < uMinVal) 584 { 585 uMinIdx = j; 586 uMinVal = pPart->aPartitions[j].uStart; 587 } 588 else if (pPart->aPartitions[j].uStart == uMinVal) 589 { 590 RTPrintf("Two partitions start at the same place. Aborting\n"); 591 return VERR_INVALID_PARAMETER; 592 } else if (pPart->aPartitions[j].uStart == 0) 593 { 594 RTPrintf("Partition starts at sector 0. Aborting\n"); 595 return VERR_INVALID_PARAMETER; 596 } 597 } 598 if (uMinIdx != i) 599 { 600 /* Swap entries at index i and uMinIdx. */ 601 memcpy(&pPart->aPartitions[pPart->cPartitions], 602 &pPart->aPartitions[i], sizeof(HOSTPARTITION)); 603 memcpy(&pPart->aPartitions[i], 604 &pPart->aPartitions[uMinIdx], sizeof(HOSTPARTITION)); 605 memcpy(&pPart->aPartitions[uMinIdx], 606 &pPart->aPartitions[pPart->cPartitions], sizeof(HOSTPARTITION)); 607 } 608 if (pPart->aPartitions[i].cPartDataSectors) 609 { 610 if (pPart->aPartitions[i].uPartDataStart < uPrevEnd) 611 { 612 RTPrintf("Overlapping partition description areas. Aborting\n"); 613 return VERR_INVALID_PARAMETER; 614 } 615 uPrevEnd = pPart->aPartitions[i].uPartDataStart + pPart->aPartitions[i].cPartDataSectors; 616 } 617 if (pPart->aPartitions[i].uStart < uPrevEnd) 618 { 619 RTPrintf("Overlapping partitions. Aborting\n"); 620 return VERR_INVALID_PARAMETER; 621 } 622 if (!PARTTYPE_IS_EXTENDED(pPart->aPartitions[i].uType)) 623 uPrevEnd = pPart->aPartitions[i].uStart + pPart->aPartitions[i].uSize; 624 } 625 626 /* Fill out partitioning location info for MBR. */ 627 pPart->aPartitions[0].uPartDataStart = 0; 628 pPart->aPartitions[0].cPartDataSectors = RT_MIN(pPart->aPartitions[0].uStart, 63); 629 630 return VINF_SUCCESS; 631 } 632 633 HRESULT CmdListPartitions(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) 634 { 635 Utf8Str rawdisk; 636 637 /* let's have a closer look at the arguments */ 638 for (int i = 0; i < argc; i++) 639 { 640 if (strcmp(argv[i], "-rawdisk") == 0) 641 { 642 if (argc <= i + 1) 643 { 644 return errorArgument("Missing argument to '%s'", argv[i]); 645 } 646 i++; 647 rawdisk = argv[i]; 648 } 649 else 650 { 651 return errorSyntax(USAGE_LISTPARTITIONS, "Invalid parameter '%s'", Utf8Str(argv[i]).raw()); 652 } 653 } 654 655 if (rawdisk.isEmpty()) 656 return errorSyntax(USAGE_LISTPARTITIONS, "Mandatory parameter -rawdisk missing"); 657 658 RTFILE RawFile; 659 int vrc = RTFileOpen(&RawFile, rawdisk.raw(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); 660 if (VBOX_FAILURE(vrc)) 661 { 662 RTPrintf("Error opening the raw disk: %Vrc\n", vrc); 663 return vrc; 664 } 665 666 HOSTPARTITIONS partitions; 667 vrc = partRead(RawFile, &partitions); 668 if (VBOX_FAILURE(vrc)) 669 return vrc; 670 671 RTPrintf("Number Type StartCHS EndCHS Size (MiB) Start (Sect)\n"); 672 for (unsigned i = 0; i < partitions.cPartitions; i++) 673 { 674 /* Suppress printing the extended partition. Otherwise people 675 * might add it to the list of partitions for raw partition 676 * access (which is not good). */ 677 if (PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType)) 678 continue; 679 680 RTPrintf("%-7u %#04x %-4u/%-3u/%-2u %-4u/%-3u/%-2u %10llu %10llu\n", 681 partitions.aPartitions[i].uIndex, 682 partitions.aPartitions[i].uType, 683 partitions.aPartitions[i].uStartCylinder, 684 partitions.aPartitions[i].uStartHead, 685 partitions.aPartitions[i].uStartSector, 686 partitions.aPartitions[i].uEndCylinder, 687 partitions.aPartitions[i].uEndHead, 688 partitions.aPartitions[i].uEndSector, 689 partitions.aPartitions[i].uSize / 2048, 690 partitions.aPartitions[i].uStart); 691 } 692 693 return 0; 694 } 695 696 HRESULT CmdCreateRawVMDK(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) 697 { 698 HRESULT rc = S_OK; 699 Bstr filename; 700 const char *pszMBRFilename = NULL; 701 Utf8Str rawdisk; 702 const char *pszPartitions = NULL; 703 bool fRegister = false; 704 bool fRelative = false; 705 706 /* let's have a closer look at the arguments */ 707 for (int i = 0; i < argc; i++) 708 { 709 if (strcmp(argv[i], "-filename") == 0) 710 { 711 if (argc <= i + 1) 712 { 713 return errorArgument("Missing argument to '%s'", argv[i]); 714 } 715 i++; 716 filename = argv[i]; 717 } 718 else if (strcmp(argv[i], "-mbr") == 0) 719 { 720 if (argc <= i + 1) 721 { 722 return errorArgument("Missing argument to '%s'", argv[i]); 723 } 724 i++; 725 pszMBRFilename = argv[i]; 726 } 727 else if (strcmp(argv[i], "-rawdisk") == 0) 728 { 729 if (argc <= i + 1) 730 { 731 return errorArgument("Missing argument to '%s'", argv[i]); 732 } 733 i++; 734 rawdisk = argv[i]; 735 } 736 else if (strcmp(argv[i], "-partitions") == 0) 737 { 738 if (argc <= i + 1) 739 { 740 return errorArgument("Missing argument to '%s'", argv[i]); 741 } 742 i++; 743 pszPartitions = argv[i]; 744 } 745 else if (strcmp(argv[i], "-register") == 0) 746 { 747 fRegister = true; 748 } 749 #ifdef RT_OS_LINUX 750 else if (strcmp(argv[i], "-relative") == 0) 751 { 752 fRelative = true; 753 } 754 #endif /* RT_OS_LINUX */ 755 else 756 { 757 return errorSyntax(USAGE_CREATERAWVMDK, "Invalid parameter '%s'", Utf8Str(argv[i]).raw()); 758 } 759 } 760 761 if (filename.isEmpty()) 762 return errorSyntax(USAGE_CREATERAWVMDK, "Mandatory parameter -filename missing"); 763 if (rawdisk.isEmpty()) 764 return errorSyntax(USAGE_CREATERAWVMDK, "Mandatory parameter -rawdisk missing"); 765 if (!pszPartitions && pszMBRFilename) 766 return errorSyntax(USAGE_CREATERAWVMDK, "The parameter -mbr is only valid when the parameter -partitions is also present"); 767 768 RTFILE RawFile; 769 int vrc = RTFileOpen(&RawFile, rawdisk.raw(), RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); 770 if (VBOX_FAILURE(vrc)) 771 { 772 RTPrintf("Error opening the raw disk: %Vrc\n", vrc); 773 return vrc; 774 } 775 776 uint64_t cbSize = 0; 777 #ifdef RT_OS_WINDOWS 778 DISK_GEOMETRY DriveGeo; 779 DWORD cbDriveGeo; 780 /* Windows NT has no IOCTL_DISK_GET_LENGTH_INFORMATION ioctl. This was 781 * added to Windows XP, so use the available info from DriveGeo. */ 782 if (DeviceIoControl((HANDLE)RawFile, 783 IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, 784 &DriveGeo, sizeof(DriveGeo), &cbDriveGeo, NULL)) 785 { 786 if (DriveGeo.MediaType == FixedMedia) 787 { 788 cbSize = DriveGeo.Cylinders.QuadPart 789 * DriveGeo.TracksPerCylinder 790 * DriveGeo.SectorsPerTrack 791 * DriveGeo.BytesPerSector; 792 } 793 else 794 return VERR_MEDIA_NOT_RECOGNIZED; 795 } 796 else 797 rc = RTErrConvertFromWin32(GetLastError()); 798 #elif defined(RT_OS_LINUX) 799 struct stat DevStat; 800 if (!fstat(RawFile, &DevStat) && S_ISBLK(DevStat.st_mode)) 801 { 802 long cBlocks; 803 if (!ioctl(RawFile, BLKGETSIZE, &cBlocks)) 804 cbSize = (uint64_t)cBlocks * 512; 805 else 806 return RTErrConvertFromErrno(errno); 807 } 808 else 809 { 810 RTPrintf("File '%s' is no disk\n", rawdisk.raw()); 811 return VERR_INVALID_PARAMETER; 812 } 813 #else /* !RT_OS_WINDOWS && !RT_OS_LINUX */ 814 /* Hopefully this works on all other hosts. If it doesn't, it'll just fail 815 * creating the VMDK, so no real harm done. */ 816 vrc = RTFileGetSize(RawFile, &cbSize); 817 if (VBOX_FAILURE(vrc)) 818 { 819 RTPrintf("Error getting the size of the raw disk: %Vrc\n", vrc); 820 return vrc; 821 } 822 #endif /* !RT_OS_WINDOWS && !RT_OS_LINUX */ 823 824 PVBOXHDD pDisk = NULL; 825 VBOXHDDRAW RawDescriptor; 826 HOSTPARTITIONS partitions; 827 uint32_t uPartitions = 0; 828 829 RawDescriptor.szSignature[0] = 'R'; 830 RawDescriptor.szSignature[1] = 'A'; 831 RawDescriptor.szSignature[2] = 'W'; 832 RawDescriptor.szSignature[3] = '\0'; 833 if (!pszPartitions) 834 { 835 RawDescriptor.fRawDisk = true; 836 RawDescriptor.pszRawDisk = rawdisk.raw(); 837 } 838 else 839 { 840 RawDescriptor.fRawDisk = false; 841 RawDescriptor.pszRawDisk = NULL; 842 RawDescriptor.cPartitions = 0; 843 844 const char *p = pszPartitions; 845 char *pszNext; 846 uint32_t u32; 847 while (*p != '\0') 848 { 849 vrc = RTStrToUInt32Ex(p, &pszNext, 0, &u32); 850 if (VBOX_FAILURE(vrc)) 851 { 852 RTPrintf("Incorrect value in partitions parameter\n"); 853 return vrc; 854 } 855 uPartitions |= RT_BIT(u32); 856 p = pszNext; 857 if (*p == ',') 858 p++; 859 else if (*p != '\0') 860 { 861 RTPrintf("Incorrect separator in partitions parameter\n"); 862 return VERR_INVALID_PARAMETER; 863 } 864 } 865 866 vrc = partRead(RawFile, &partitions); 867 if (VBOX_FAILURE(vrc)) 868 { 869 RTPrintf("Error reading the partition information from '%s'\n", rawdisk.raw()); 870 return vrc; 871 } 872 873 for (unsigned i = 0; i < partitions.cPartitions; i++) 874 { 875 if ( uPartitions & RT_BIT(partitions.aPartitions[i].uIndex) 876 && PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType)) 877 { 878 /* Some ignorant user specified an extended partition. 879 * Bad idea, as this would trigger an overlapping 880 * partitions error later during VMDK creation. So warn 881 * here and ignore what the user requested. */ 882 RTPrintf("Warning: it is not possible (and necessary) to explicitly give access to the\n" 883 " extended partition %u. If required, enable access to all logical\n" 884 " partitions inside this extended partition.\n", partitions.aPartitions[i].uIndex); 885 uPartitions &= ~RT_BIT(partitions.aPartitions[i].uIndex); 886 } 887 } 888 889 RawDescriptor.cPartitions = partitions.cPartitions; 890 RawDescriptor.pPartitions = (PVBOXHDDRAWPART)RTMemAllocZ(partitions.cPartitions * sizeof(VBOXHDDRAWPART)); 891 if (!RawDescriptor.pPartitions) 892 return VERR_NO_MEMORY; 893 for (unsigned i = 0; i < partitions.cPartitions; i++) 894 { 895 if (uPartitions & RT_BIT(partitions.aPartitions[i].uIndex)) 896 { 897 if (fRelative) 898 { 899 #ifdef RT_OS_LINUX 900 /* Refer to the correct partition and use offset 0. */ 901 char *pszRawName; 902 vrc = RTStrAPrintf(&pszRawName, "%s%u", rawdisk.raw(), 903 partitions.aPartitions[i].uIndex); 904 if (VBOX_FAILURE(vrc)) 905 { 906 RTPrintf("Error creating reference to individual partition %u, rc=%Vrc\n", 907 partitions.aPartitions[i].uIndex, vrc); 908 return vrc; 909 } 910 RawDescriptor.pPartitions[i].pszRawDevice = pszRawName; 911 RawDescriptor.pPartitions[i].uPartitionStartOffset = 0; 912 RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512; 913 #else 914 /** @todo not implemented yet for Windows host. Treat just 915 * like not specified (this code is actually never reached). */ 916 RawDescriptor.pPartitions[i].pszRawDevice = rawdisk.raw(); 917 RawDescriptor.pPartitions[i].uPartitionStartOffset = partitions.aPartitions[i].uStart * 512; 918 RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512; 919 #endif 920 } 921 else 922 { 923 /* This is the "everything refers to the base raw device" 924 * variant. This requires opening the base device in RW 925 * mode even for creation. */ 926 RawDescriptor.pPartitions[i].pszRawDevice = rawdisk.raw(); 927 RawDescriptor.pPartitions[i].uPartitionStartOffset = partitions.aPartitions[i].uStart * 512; 928 RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512; 929 } 930 } 931 else 932 { 933 /* Suppress access to this partition. */ 934 RawDescriptor.pPartitions[i].pszRawDevice = NULL; 935 RawDescriptor.pPartitions[i].uPartitionStartOffset = 0; 936 /* This is used in the plausibility check in the creation 937 * code. In theory it's a dummy, but I don't want to make 938 * the VMDK creatiion any more complicated than what it needs 939 * to be. */ 940 RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512; 941 } 942 if (PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType)) 943 { 944 /* Suppress exporting the actual extended partition. Only 945 * logical partitions should be processed. However completely 946 * ignoring it leads to leaving out the MBR data. */ 947 RawDescriptor.pPartitions[i].cbPartition = 0; 948 } 949 else 950 RawDescriptor.pPartitions[i].cbPartition = partitions.aPartitions[i].uSize * 512; 951 RawDescriptor.pPartitions[i].uPartitionDataStart = partitions.aPartitions[i].uPartDataStart * 512; 952 RawDescriptor.pPartitions[i].cbPartitionData = partitions.aPartitions[i].cPartDataSectors * 512; 953 if (RawDescriptor.pPartitions[i].cbPartitionData) 954 { 955 Assert (RawDescriptor.pPartitions[i].cbPartitionData - 956 (size_t)RawDescriptor.pPartitions[i].cbPartitionData == 0); 957 void *pPartData = RTMemAlloc((size_t)RawDescriptor.pPartitions[i].cbPartitionData); 958 if (!pPartData) 959 return VERR_NO_MEMORY; 960 vrc = RTFileReadAt(RawFile, partitions.aPartitions[i].uPartDataStart * 512, pPartData, (size_t)RawDescriptor.pPartitions[i].cbPartitionData, NULL); 961 if (VBOX_FAILURE(vrc)) 962 { 963 RTPrintf("Cannot read partition data from raw device '%s': %Vrc\n", rawdisk.raw(), vrc); 964 return vrc; 965 } 966 /* Splice in the replacement MBR code if specified. */ 967 if ( partitions.aPartitions[i].uPartDataStart == 0 968 && pszMBRFilename) 969 { 970 RTFILE MBRFile; 971 vrc = RTFileOpen(&MBRFile, pszMBRFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); 972 if (VBOX_FAILURE(vrc)) 973 { 974 RTPrintf("Cannot open replacement MBR file '%s' specified with -mbr: %Vrc\n", pszMBRFilename, vrc); 975 return vrc; 976 } 977 vrc = RTFileReadAt(MBRFile, 0, pPartData, 0x1be, NULL); 978 RTFileClose(MBRFile); 979 if (VBOX_FAILURE(vrc)) 980 { 981 RTPrintf("Cannot read replacement MBR file '%s': %Vrc\n", pszMBRFilename, vrc); 982 return vrc; 983 } 984 } 985 RawDescriptor.pPartitions[i].pvPartitionData = pPartData; 986 } 987 } 988 } 989 990 RTFileClose(RawFile); 991 992 vrc = VDCreate(handleVDError, NULL, &pDisk); 993 if (VBOX_FAILURE(vrc)) 994 { 995 RTPrintf("Error while creating the virtual disk container: %Vrc\n", vrc); 996 return vrc; 997 } 998 999 Assert(RT_MIN(cbSize / 512 / 16 / 63, 16383) - 1000 (unsigned int)RT_MIN(cbSize / 512 / 16 / 63, 16383) == 0); 1001 PDMMEDIAGEOMETRY PCHS, LCHS; 1002 PCHS.cCylinders = (unsigned int)RT_MIN(cbSize / 512 / 16 / 63, 16383); 1003 PCHS.cHeads = 16; 1004 PCHS.cSectors = 63; 1005 LCHS.cCylinders = 0; 1006 LCHS.cHeads = 0; 1007 LCHS.cSectors = 0; 1008 vrc = VDCreateBase(pDisk, "VMDK", Utf8Str(filename).raw(), 1009 VD_IMAGE_TYPE_FIXED, cbSize, 1010 VD_VMDK_IMAGE_FLAGS_RAWDISK, (char *)&RawDescriptor, 1011 &PCHS, &LCHS, VD_OPEN_FLAGS_NORMAL, NULL, NULL); 1012 if (VBOX_FAILURE(vrc)) 1013 { 1014 RTPrintf("Error while creating the raw disk VMDK: %Vrc\n", vrc); 1015 return vrc; 1016 } 1017 RTPrintf("RAW host disk access VMDK file %s created successfully.\n", Utf8Str(filename).raw()); 1018 1019 VDCloseAll(pDisk); 1020 1021 /* Clean up allocated memory etc. */ 1022 if (pszPartitions) 1023 { 1024 for (unsigned i = 0; i < partitions.cPartitions; i++) 1025 { 1026 if (uPartitions & RT_BIT(partitions.aPartitions[i].uIndex)) 1027 { 1028 if (fRelative) 1029 { 1030 #ifdef RT_OS_LINUX 1031 /* Free memory allocated above. */ 1032 RTStrFree((char *)(void *)RawDescriptor.pPartitions[i].pszRawDevice); 1033 #endif /* RT_OS_LINUX */ 1034 } 1035 } 1036 } 1037 } 1038 1039 if (fRegister) 1040 { 1041 ComPtr<IHardDisk> hardDisk; 1042 CHECK_ERROR(aVirtualBox, OpenHardDisk(filename, hardDisk.asOutParam())); 1043 1044 if (SUCCEEDED(rc) && hardDisk) 1045 { 1046 CHECK_ERROR(aVirtualBox, RegisterHardDisk(hardDisk)); 1047 } 1048 } 1049 1050 return SUCCEEDED(rc) ? 0 : 1; 1051 } 1052 416 1053 /** 417 1054 * Unloads the neccessary driver. … … 470 1107 if (!strcmp(pszCmd, "setvdiuuid")) 471 1108 return handleSetVDIUUID(argc - 1, &argv[1], aVirtualBox, aSession); 472 #ifndef VBOX_OSE473 1109 if (!strcmp(pszCmd, "listpartitions")) 474 1110 return CmdListPartitions(argc - 1, &argv[1], aVirtualBox, aSession); 475 1111 if (!strcmp(pszCmd, "createrawvmdk")) 476 1112 return CmdCreateRawVMDK(argc - 1, &argv[1], aVirtualBox, aSession); 477 #endif /* !VBOX_OSE */478 1113 479 1114 if (!strcmp(pszCmd, "modinstall"))
Note:
See TracChangeset
for help on using the changeset viewer.