VirtualBox

Changeset 40906 in vbox for trunk


Ignore:
Timestamp:
Apr 13, 2012 7:38:21 PM (13 years ago)
Author:
vboxsync
Message:

Storage/VDI: Make the backend work on big endian architectures

Location:
trunk/src/VBox/Storage
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/VDI.cpp

    r40739 r40906  
    3232
    3333#define VDI_IMAGE_DEFAULT_BLOCK_SIZE _1M
     34
     35/** Macros for endianess conversion. */
     36#define SET_ENDIAN_U32(conv, u32) (conv == VDIECONV_H2F ? RT_H2LE_U32(u32) : RT_LE2H_U32(u32))
     37#define SET_ENDIAN_U64(conv, u64) (conv == VDIECONV_H2F ? RT_H2LE_U64(u64) : RT_LE2H_U64(u64))
    3438
    3539/*******************************************************************************
     
    6266
    6367/**
     68 * Internal: Convert the PreHeader fields to the appropriate endianess.
     69 * @param   enmConv     Direction of the conversion.
     70 * @param   pPreHdrConv Where to store the converted pre header.
     71 * @param   pPreHdr     PreHeader pointer.
     72 */
     73static void vdiConvPreHeaderEndianess(VDIECONV enmConv, PVDIPREHEADER pPreHdrConv,
     74                                      PVDIPREHEADER pPreHdr)
     75{
     76    pPreHdrConv->u32Signature = SET_ENDIAN_U32(enmConv, pPreHdr->u32Signature);
     77    pPreHdrConv->u32Version   = SET_ENDIAN_U32(enmConv, pPreHdr->u32Version);
     78}
     79
     80/**
     81 * Internal: Convert the VDIDISKGEOMETRY fields to the appropriate endianess.
     82 * @param   enmConv      Direction of the conversion.
     83 * @param   pDiskGeoConv Where to store the converted geometry.
     84 * @param   pDiskGeo     Pointer to the disk geometry to convert.
     85 */
     86static void vdiConvGeometryEndianess(VDIECONV enmConv, PVDIDISKGEOMETRY pDiskGeoConv,
     87                                     PVDIDISKGEOMETRY pDiskGeo)
     88{
     89    pDiskGeoConv->cCylinders = SET_ENDIAN_U32(enmConv, pDiskGeo->cCylinders);
     90    pDiskGeoConv->cHeads     = SET_ENDIAN_U32(enmConv, pDiskGeo->cHeads);
     91    pDiskGeoConv->cSectors   = SET_ENDIAN_U32(enmConv, pDiskGeo->cSectors);
     92    pDiskGeoConv->cbSector   = SET_ENDIAN_U32(enmConv, pDiskGeo->cbSector);
     93}
     94
     95/**
     96 * Internal: Convert the Header - version 0 fields to the appropriate endianess.
     97 * @param   enmConv      Direction of the conversion.
     98 * @param   pHdrConv     Where to store the converted header.
     99 * @param   pHdr         Pointer to the version 0 header.
     100 */
     101static void vdiConvHeaderEndianessV0(VDIECONV enmConv, PVDIHEADER0 pHdrConv,
     102                                     PVDIHEADER0 pHdr)
     103{
     104    pHdrConv->u32Type          = SET_ENDIAN_U32(enmConv, pHdr->u32Type);
     105    pHdrConv->fFlags           = SET_ENDIAN_U32(enmConv, pHdr->fFlags);
     106    vdiConvGeometryEndianess(enmConv, &pHdrConv->LegacyGeometry, &pHdr->LegacyGeometry);
     107    pHdrConv->cbDisk           = SET_ENDIAN_U64(enmConv, pHdr->cbDisk);
     108    pHdrConv->cbBlock          = SET_ENDIAN_U32(enmConv, pHdr->cbBlock);
     109    pHdrConv->cBlocks          = SET_ENDIAN_U32(enmConv, pHdr->cBlocks);
     110    pHdrConv->cBlocksAllocated = SET_ENDIAN_U32(enmConv, pHdr->cBlocksAllocated);
     111    /* Don't touch the RTUUID fields. */
     112}
     113
     114/**
     115 * Internal: Set the Header - version 1 fields to the appropriate endianess.
     116 * @param   enmConv      Direction of the conversion.
     117 * @param   pHdrConv     Where to store the converted header.
     118 * @param   pHdr         Version 1 Header pointer.
     119 */
     120static void vdiConvHeaderEndianessV1(VDIECONV enmConv, PVDIHEADER1 pHdrConv,
     121                                     PVDIHEADER1 pHdr)
     122{
     123    pHdrConv->cbHeader         = SET_ENDIAN_U32(enmConv, pHdr->cbHeader);
     124    pHdrConv->u32Type          = SET_ENDIAN_U32(enmConv, pHdr->u32Type);
     125    pHdrConv->fFlags           = SET_ENDIAN_U32(enmConv, pHdr->fFlags);
     126    pHdrConv->offBlocks        = SET_ENDIAN_U32(enmConv, pHdr->offBlocks);
     127    pHdrConv->offData          = SET_ENDIAN_U32(enmConv, pHdr->offData);
     128    vdiConvGeometryEndianess(enmConv, &pHdrConv->LegacyGeometry, &pHdr->LegacyGeometry);
     129    pHdrConv->u32Dummy         = SET_ENDIAN_U32(enmConv, pHdr->u32Dummy);
     130    pHdrConv->cbDisk           = SET_ENDIAN_U64(enmConv, pHdr->cbDisk);
     131    pHdrConv->cbBlock          = SET_ENDIAN_U32(enmConv, pHdr->cbBlock);
     132    pHdrConv->cbBlockExtra     = SET_ENDIAN_U32(enmConv, pHdr->cbBlockExtra);
     133    pHdrConv->cBlocks          = SET_ENDIAN_U32(enmConv, pHdr->cBlocks);
     134    pHdrConv->cBlocksAllocated = SET_ENDIAN_U32(enmConv, pHdr->cBlocksAllocated);
     135    /* don't touch the RTUUID */
     136}
     137
     138/**
     139 * Internal: Set the Header - version 1plus fields to the appropriate endianess.
     140 * @param   enmConv      Direction of the conversion.
     141 * @param   pHdrConv     Where to store the converted header.
     142 * @param   pHdr         Version 1+ Header pointer.
     143 */
     144static void vdiConvHeaderEndianessV1p(VDIECONV enmConv, PVDIHEADER1PLUS pHdrConv,
     145                                      PVDIHEADER1PLUS pHdr)
     146{
     147    pHdrConv->cbHeader         = SET_ENDIAN_U32(enmConv, pHdr->cbHeader);
     148    pHdrConv->u32Type          = SET_ENDIAN_U32(enmConv, pHdr->u32Type);
     149    pHdrConv->fFlags           = SET_ENDIAN_U32(enmConv, pHdr->fFlags);
     150    pHdrConv->offBlocks        = SET_ENDIAN_U32(enmConv, pHdr->offBlocks);
     151    pHdrConv->offData          = SET_ENDIAN_U32(enmConv, pHdr->offData);
     152    vdiConvGeometryEndianess(enmConv, &pHdrConv->LegacyGeometry, &pHdr->LegacyGeometry);
     153    pHdrConv->u32Dummy         = SET_ENDIAN_U32(enmConv, pHdr->u32Dummy);
     154    pHdrConv->cbDisk           = SET_ENDIAN_U64(enmConv, pHdr->cbDisk);
     155    pHdrConv->cbBlock          = SET_ENDIAN_U32(enmConv, pHdr->cbBlock);
     156    pHdrConv->cbBlockExtra     = SET_ENDIAN_U32(enmConv, pHdr->cbBlockExtra);
     157    pHdrConv->cBlocks          = SET_ENDIAN_U32(enmConv, pHdr->cBlocks);
     158    pHdrConv->cBlocksAllocated = SET_ENDIAN_U32(enmConv, pHdr->cBlocksAllocated);
     159    /* don't touch the RTUUID */
     160    vdiConvGeometryEndianess(enmConv, &pHdrConv->LCHSGeometry, &pHdr->LCHSGeometry);
     161}
     162
     163/**
     164 * Internal: Set the appropriate endianess on all the Blocks pointed.
     165 * @param   enmConv      Direction of the conversion.
     166 * @param   paBlocks     Pointer to the block array.
     167 * @param   cEntries     Number of entries in the block array.
     168 *
     169 * @note Unlike the other conversion functions this method does an in place conversion
     170 *       to avoid temporary memory allocations when writing the block array.
     171 */
     172static void vdiConvBlocksEndianess(VDIECONV enmConv, PVDIIMAGEBLOCKPOINTER paBlocks,
     173                                   unsigned cEntries)
     174{
     175    for (unsigned i = 0; i < cEntries; i++)
     176        paBlocks[i] = SET_ENDIAN_U32(enmConv, paBlocks[i]);
     177}
     178
     179/**
    64180 * Internal: Flush the image file to disk.
    65181 */
     
    509625
    510626    /* Write pre-header. */
     627    VDIPREHEADER PreHeader;
     628    vdiConvPreHeaderEndianess(VDIECONV_H2F, &PreHeader, &pImage->PreHeader);
    511629    rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, 0,
    512                                 &pImage->PreHeader, sizeof(pImage->PreHeader), NULL);
     630                                &PreHeader, sizeof(PreHeader), NULL);
    513631    if (RT_FAILURE(rc))
    514632    {
     
    519637
    520638    /* Write header. */
     639    VDIHEADER1PLUS Hdr;
     640    vdiConvHeaderEndianessV1p(VDIECONV_H2F, &Hdr, &pImage->Header.u.v1plus);
    521641    rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, sizeof(pImage->PreHeader),
    522                                 &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
     642                                &Hdr, sizeof(Hdr), NULL);
    523643    if (RT_FAILURE(rc))
    524644    {
     
    528648    }
    529649
     650    vdiConvBlocksEndianess(VDIECONV_H2F, pImage->paBlocks, getImageBlocks(&pImage->Header));
    530651    rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, pImage->offStartBlocks, pImage->paBlocks,
    531652                                getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER),
    532653                                NULL);
     654    vdiConvBlocksEndianess(VDIECONV_F2H, pImage->paBlocks, getImageBlocks(&pImage->Header));
    533655    if (RT_FAILURE(rc))
    534656    {
     
    631753
    632754    /* Read pre-header. */
     755    VDIPREHEADER PreHeader;
    633756    rc = vdIfIoIntFileReadSync(pImage->pIfIo, pImage->pStorage, 0,
    634                                &pImage->PreHeader, sizeof(pImage->PreHeader), NULL);
     757                               &PreHeader, sizeof(PreHeader), NULL);
    635758    if (RT_FAILURE(rc))
    636759    {
     
    639762        goto out;
    640763    }
     764    vdiConvPreHeaderEndianess(VDIECONV_F2H, &pImage->PreHeader, &PreHeader);
    641765    rc = vdiValidatePreHeader(&pImage->PreHeader);
    642766    if (RT_FAILURE(rc))
     
    659783                goto out;
    660784            }
     785            vdiConvHeaderEndianessV0(VDIECONV_F2H, &pImage->Header.u.v0, &pImage->Header.u.v0);
    661786            break;
    662787        case 1:
     
    669794                goto out;
    670795            }
     796            vdiConvHeaderEndianessV1(VDIECONV_F2H, &pImage->Header.u.v1, &pImage->Header.u.v1);
    671797            /* Convert VDI 1.1 images to VDI 1.1+ on open in read/write mode.
    672798             * Conversion is harmless, as any VirtualBox version supporting VDI
     
    694820                    goto out;
    695821                }
     822                vdiConvHeaderEndianessV1p(VDIECONV_F2H, &pImage->Header.u.v1plus, &pImage->Header.u.v1plus);
    696823            }
    697824            break;
     
    723850                               getImageBlocks(&pImage->Header) * sizeof(VDIIMAGEBLOCKPOINTER),
    724851                               NULL);
     852    if (RT_FAILURE(rc))
     853    {
     854        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VDI: Error reading the block table in '%s'"), pImage->pszFilename);
     855        goto out;
     856    }
     857    vdiConvBlocksEndianess(VDIECONV_F2H, pImage->paBlocks, getImageBlocks(&pImage->Header));
    725858
    726859    if (uOpenFlags & VD_OPEN_FLAGS_DISCARD)
     
    782915    {
    783916        case 0:
     917        {
     918            VDIHEADER0 Hdr;
     919            vdiConvHeaderEndianessV0(VDIECONV_H2F, &Hdr, &pImage->Header.u.v0);
    784920            rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, sizeof(VDIPREHEADER),
    785                                         &pImage->Header.u.v0, sizeof(pImage->Header.u.v0),
    786                                         NULL);
     921                                        &Hdr, sizeof(Hdr), NULL);
    787922            break;
     923        }
    788924        case 1:
    789925            if (pImage->Header.u.v1plus.cbHeader < sizeof(pImage->Header.u.v1plus))
     926            {
     927                VDIHEADER1 Hdr;
     928                vdiConvHeaderEndianessV1(VDIECONV_H2F, &Hdr, &pImage->Header.u.v1);
    790929                rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, sizeof(VDIPREHEADER),
    791                                             &pImage->Header.u.v1, sizeof(pImage->Header.u.v1),
    792                                             NULL);
     930                                            &Hdr, sizeof(Hdr), NULL);
     931            }
    793932            else
     933            {
     934                VDIHEADER1PLUS Hdr;
     935                vdiConvHeaderEndianessV1p(VDIECONV_H2F, &Hdr, &pImage->Header.u.v1plus);
    794936                rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, sizeof(VDIPREHEADER),
    795                                             &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus),
    796                                             NULL);
     937                                            &Hdr, sizeof(Hdr), NULL);
     938            }
    797939            break;
    798940        default:
     
    813955    {
    814956        case 0:
     957        {
     958            VDIHEADER0 Hdr;
     959            vdiConvHeaderEndianessV0(VDIECONV_H2F, &Hdr, &pImage->Header.u.v0);
    815960            rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage,
    816                                              sizeof(VDIPREHEADER), &pImage->Header.u.v0,
    817                                              sizeof(pImage->Header.u.v0),
     961                                             sizeof(VDIPREHEADER), &Hdr, sizeof(Hdr),
    818962                                             pIoCtx, NULL, NULL);
    819963            break;
     964        }
    820965        case 1:
    821966            if (pImage->Header.u.v1plus.cbHeader < sizeof(pImage->Header.u.v1plus))
     967            {
     968                VDIHEADER1 Hdr;
     969                vdiConvHeaderEndianessV1(VDIECONV_H2F, &Hdr, &pImage->Header.u.v1);
    822970                rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage,
    823                                                  sizeof(VDIPREHEADER), &pImage->Header.u.v1,
    824                                                  sizeof(pImage->Header.u.v1),
     971                                                 sizeof(VDIPREHEADER), &Hdr, sizeof(Hdr),
    825972                                                 pIoCtx, NULL, NULL);
     973            }
    826974            else
     975            {
     976                VDIHEADER1PLUS Hdr;
     977                vdiConvHeaderEndianessV1p(VDIECONV_H2F, &Hdr, &pImage->Header.u.v1plus);
    827978                rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage,
    828                                                  sizeof(VDIPREHEADER), &pImage->Header.u.v1plus,
    829                                                  sizeof(pImage->Header.u.v1plus),
     979                                                 sizeof(VDIPREHEADER), &Hdr, sizeof(Hdr),
    830980                                                 pIoCtx, NULL, NULL);
     981            }
    831982            break;
    832983        default:
     
    8491000    {
    8501001        /* write only one block pointer. */
     1002        VDIIMAGEBLOCKPOINTER ptrBlock = RT_H2LE_U32(pImage->paBlocks[uBlock]);
    8511003        rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage,
    8521004                                    pImage->offStartBlocks + uBlock * sizeof(VDIIMAGEBLOCKPOINTER),
    853                                     &pImage->paBlocks[uBlock], sizeof(VDIIMAGEBLOCKPOINTER),
     1005                                    &ptrBlock, sizeof(VDIIMAGEBLOCKPOINTER),
    8541006                                    NULL);
    8551007        AssertMsgRC(rc, ("vdiUpdateBlockInfo failed to update block=%u, filename=\"%s\", rc=%Rrc\n",
     
    8741026    {
    8751027        /* write only one block pointer. */
     1028        VDIIMAGEBLOCKPOINTER ptrBlock = RT_H2LE_U32(pImage->paBlocks[uBlock]);
    8761029        rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pImage->pStorage,
    8771030                                         pImage->offStartBlocks + uBlock * sizeof(VDIIMAGEBLOCKPOINTER),
    878                                          &pImage->paBlocks[uBlock],
    879                                          sizeof(VDIIMAGEBLOCKPOINTER),
     1031                                         &ptrBlock, sizeof(VDIIMAGEBLOCKPOINTER),
    8801032                                         pIoCtx, NULL, NULL);
    8811033        AssertMsg(RT_SUCCESS(rc) || rc == VERR_VD_ASYNC_IO_IN_PROGRESS,
     
    28803032
    28813033            /* Write the block array before updating the rest. */
     3034            vdiConvBlocksEndianess(VDIECONV_H2F, pImage->paBlocks, cBlocksNew);
    28823035            rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pImage->pStorage, pImage->offStartBlocks,
    28833036                                        pImage->paBlocks, cbBlockspaceNew, NULL);
     3037            vdiConvBlocksEndianess(VDIECONV_F2H, pImage->paBlocks, cBlocksNew);
    28843038
    28853039            if (RT_SUCCESS(rc))
     
    32323386            break;
    32333387        }
     3388        vdiConvPreHeaderEndianess(VDIECONV_F2H, &PreHdr, &PreHdr);
    32343389        rc = vdiValidatePreHeader(&PreHdr);
    32353390        if (RT_FAILURE(rc))
     
    32413396
    32423397        /* Read header. */
    3243         Hdr.uVersion = RT_H2LE_U32(PreHdr.u32Version);
     3398        Hdr.uVersion = PreHdr.u32Version;
    32443399        switch (GET_MAJOR_HEADER_VERSION(&Hdr))
    32453400        {
     
    32513406                    rc = vdIfError(pIfError, rc, RT_SRC_POS, N_("VDI: error reading v0 header in '%s'"),
    32523407                                   pszFilename);
     3408                vdiConvHeaderEndianessV0(VDIECONV_F2H, &Hdr.u.v0, &Hdr.u.v0);
    32533409                break;
    32543410            case 1:
     
    32603416                                   pszFilename);
    32613417                }
     3418                vdiConvHeaderEndianessV1(VDIECONV_F2H, &Hdr.u.v1, &Hdr.u.v1);
    32623419                if (Hdr.u.v1.cbHeader >= sizeof(Hdr.u.v1plus))
    32633420                {
     
    32693426                        rc = vdIfError(pIfError, rc, RT_SRC_POS, N_("VDI: error reading v1.1+ header in '%s'"),
    32703427                                       pszFilename);
     3428                    vdiConvHeaderEndianessV1p(VDIECONV_F2H, &Hdr.u.v1plus, &Hdr.u.v1plus);
    32713429                }
    32723430                break;
     
    33173475            break;
    33183476        }
    3319 
    3320         for (uint32_t i = 0; i < getImageBlocks(&Hdr); i++)
    3321             paBlocks[i] = RT_LE2H_U32(paBlocks[i]);
     3477        vdiConvBlocksEndianess(VDIECONV_F2H, paBlocks, getImageBlocks(&Hdr));
    33223478
    33233479        pu32BlockBitmap = (uint32_t *)RTMemAllocZ(RT_ALIGN_Z(getImageBlocks(&Hdr) / 8, 4));
     
    33623518        else if (!(fFlags & VD_REPAIR_DRY_RUN))
    33633519        {
    3364             for (uint32_t i = 0; i < getImageBlocks(&Hdr); i++)
    3365                 paBlocks[i] = RT_H2LE_U32(paBlocks[i]);
    3366 
    33673520            vdIfErrorMessage(pIfError, "Writing repaired block allocation table...\n");
    33683521
     3522            vdiConvBlocksEndianess(VDIECONV_H2F, paBlocks, getImageBlocks(&Hdr));
    33693523            rc = vdIfIoIntFileWriteSync(pIfIo, pStorage, offStartBlocks, paBlocks,
    33703524                                        getImageBlocks(&Hdr) * sizeof(VDIIMAGEBLOCKPOINTER),
  • trunk/src/VBox/Storage/VDICore.h

    r40713 r40906  
    605605} VDIASYNCBLOCKALLOC, *PVDIASYNCBLOCKALLOC;
    606606
     607/**
     608 * Endianess conversion direction.
     609 */
     610typedef enum VDIECONV
     611{
     612    /** Host to file endianess. */
     613    VDIECONV_H2F = 0,
     614    /** File to host endianess. */
     615    VDIECONV_F2H
     616} VDIECONV;
     617
    607618#endif
    608619
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