VirtualBox

Changeset 8230 in vbox


Ignore:
Timestamp:
Apr 21, 2008 2:13:27 PM (17 years ago)
Author:
vboxsync
Message:

Move raw disk/partition code to regular internalcommands.

Location:
trunk/src/VBox/Frontends/VBoxManage
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk

    r8155 r8230  
    3636        VBoxInternalManage.cpp \
    3737        VBoxManageSVN.cpp
    38 ifndef VBOX_OSE
    39  VBoxManage_SOURCES   += \
    40         VBoxInternalManageVmdk.cpp
    41 endif
    4238VBoxManage_LIBS       += $(LIB_DDU)
    4339
  • trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp

    r8155 r8230  
    4444
    4545#include <VBox/VBoxHDD.h>
     46#include <VBox/VBoxHDD-new.h>
    4647#include <VBox/sup.h>
    4748
    4849#include "VBoxManage.h"
    4950
    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 */
    5464
    5565using 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
     77typedef 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
     93typedef struct HOSTPARTITIONS
     94{
     95    unsigned        cPartitions;
     96    HOSTPARTITION   aPartitions[HOSTPARTITION_MAX];
     97} HOSTPARTITIONS, *PHOSTPARTITIONS;
    5698
    5799/** flag whether we're in internal mode */
     
    414456}
    415457
     458
     459static 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
     467static 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
     633HRESULT 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
     696HRESULT 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
    4161053/**
    4171054 * Unloads the neccessary driver.
     
    4701107    if (!strcmp(pszCmd, "setvdiuuid"))
    4711108        return handleSetVDIUUID(argc - 1, &argv[1], aVirtualBox, aSession);
    472 #ifndef VBOX_OSE
    4731109    if (!strcmp(pszCmd, "listpartitions"))
    4741110        return CmdListPartitions(argc - 1, &argv[1], aVirtualBox, aSession);
    4751111    if (!strcmp(pszCmd, "createrawvmdk"))
    4761112        return CmdCreateRawVMDK(argc - 1, &argv[1], aVirtualBox, aSession);
    477 #endif /* !VBOX_OSE */
    4781113
    4791114    if (!strcmp(pszCmd, "modinstall"))
Note: See TracChangeset for help on using the changeset viewer.

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