VirtualBox

Changeset 67450 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Jun 16, 2017 3:35:31 PM (7 years ago)
Author:
vboxsync
Message:

IPRT: More ISO maker code (booting related).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/fs/isomaker.cpp

    r67445 r67450  
    9292#define RTFSISOMAKER_CALC_PATHREC_SIZE(a_cbNameInDirRec) \
    9393    ( RT_UOFFSETOF(ISO9660PATHREC, achDirId[(a_cbNameInDirRec) + ((a_cbNameInDirRec) & 1)]) )
     94
     95
     96/** No validation entry in the boot catalog. */
     97#define VERR_ISOMK_BOOT_CAT_NO_VALIDATION_ENTRY                 (-24900)
     98/** No default entry in the boot catalog. */
     99#define VERR_ISOMK_BOOT_CAT_NO_DEFAULT_ENTRY                    (-24901)
     100/** Expected section header. */
     101#define VERR_ISOMK_BOOT_CAT_EXPECTED_SECTION_HEADER             (-24902)
     102/** Entry in a boot catalog section is empty. */
     103#define VERR_ISOMK_BOOT_CAT_EMPTY_ENTRY                         (-24903)
     104/** Entry in a boot catalog section is another section. */
     105#define VERR_ISOMK_BOOT_CAT_INVALID_SECTION_SIZE                (-24904)
     106/** Unsectioned boot catalog entry. */
     107#define VERR_ISOMK_BOOT_CAT_ERRATIC_ENTRY                       (-24905)
    94108
    95109
     
    488502    /** Pointer to the primary volume descriptor. */
    489503    PISO9660PRIMARYVOLDESC  pPrimaryVolDesc;
    490     /** El Torito volume descriptor.
    491      * @todo fix type  */
    492     PISO9660BOOTRECORD      pElToritoDesc;
     504    /** El Torito volume descriptor. */
     505    PISO9660BOOTRECORDELTORITO pElToritoDesc;
    493506    /** Pointer to the primary volume descriptor. */
    494507    PISO9660SUPVOLDESC      pJolietVolDesc;
     
    29352948            pFile->Core.cNotOrphan  = 1;
    29362949
    2937             /* Save file pointer and we're done. */
     2950            /* Save file pointer and allocate a volume descriptor. */
    29382951            pThis->pBootCatFile = pFile;
     2952            pThis->cVolumeDescriptors++;
     2953
    29392954            return VINF_SUCCESS;
    29402955        }
     
    31403155                                                     uint8_t idPlatform, const char *pszString)
    31413156{
    3142     RT_NOREF(hIsoMaker, idxBootCat, cEntries, idPlatform, pszString);
    3143     return VERR_NOT_IMPLEMENTED;
     3157    /*
     3158     * Validate input.
     3159     */
     3160    PRTFSISOMAKERINT pThis = hIsoMaker;
     3161    RTFSISOMAKER_ASSERT_VALID_HANDLE_RET(pThis);
     3162
     3163    AssertReturn(idxBootCat >= 2 && idxBootCat < RT_ELEMENTS(pThis->aBootCatEntries) - 1U, VERR_OUT_OF_RANGE);
     3164    AssertReturn(cEntries < RT_ELEMENTS(pThis->aBootCatEntries) - 2U - 1U, VERR_OUT_OF_RANGE);
     3165    AssertReturn(idxBootCat + cEntries + 1 < RT_ELEMENTS(pThis->aBootCatEntries), VERR_OUT_OF_RANGE);
     3166
     3167    size_t cchString = 0;
     3168    if (pszString)
     3169    {
     3170        cchString = RTStrCalcLatin1Len(pszString);
     3171        AssertReturn(cchString < RT_SIZEOFMEMB(ISO9660ELTORITOVALIDATIONENTRY, achId), VERR_OUT_OF_RANGE);
     3172    }
     3173
     3174    /*
     3175     * Make sure we've got a boot file.
     3176     */
     3177    int rc = rtFsIsoMakerEnsureBootCatFile(pThis);
     3178    if (RT_SUCCESS(rc))
     3179    {
     3180        /*
     3181         * Construct the entry data.
     3182         */
     3183        ISO9660ELTORITOSECTIONHEADER Entry;
     3184        Entry.bHeaderId   = ISO9660_ELTORITO_HEADER_ID_SECTION_HEADER;
     3185        Entry.bPlatformId = idPlatform;
     3186        Entry.cEntries    = RT_H2LE_U16(cEntries);
     3187        RT_ZERO(Entry.achSectionId);
     3188        if (cchString)
     3189        {
     3190            char *pszTmp = Entry.achSectionId;
     3191            rc = RTStrToLatin1Ex(pszString, RTSTR_MAX, &pszTmp, sizeof(Entry.achSectionId), NULL);
     3192            AssertRC(rc);
     3193        }
     3194
     3195        /*
     3196         * Write the entry and update our internal tracker.
     3197         */
     3198        rc = RTVfsFileWriteAt(pThis->pBootCatFile->u.hVfsFile, 32 * idxBootCat, &Entry, sizeof(Entry), NULL);
     3199        if (RT_SUCCESS(rc))
     3200        {
     3201            if (pThis->aBootCatEntries[idxBootCat].pBootFile != NULL)
     3202            {
     3203                pThis->aBootCatEntries[idxBootCat].pBootFile->Core.cNotOrphan--;
     3204                pThis->aBootCatEntries[idxBootCat].pBootFile = NULL;
     3205            }
     3206
     3207            pThis->aBootCatEntries[idxBootCat].bType    = ISO9660_ELTORITO_HEADER_ID_SECTION_HEADER;
     3208            pThis->aBootCatEntries[idxBootCat].cEntries = cEntries + 1;
     3209        }
     3210    }
     3211    return rc;
    31443212}
    31453213
     
    31943262
    31953263/**
    3196  * Finalizes the El Torito boot stuff.
     3264 * Finalizes the El Torito boot stuff, part 1.
    31973265 *
    31983266 * This includes generating the boot catalog data and fixing the location of all
     
    32013269 * @returns IPRT status code.
    32023270 * @param   pThis               The ISO maker instance.
    3203  * @param   poffData            The data offset (in/out).
    3204  */
    3205 static int rtFsIsoMakerFinalizeBootStuff(PRTFSISOMAKERINT pThis, uint64_t *poffData)
    3206 {
    3207     RT_NOREF(pThis, poffData);
     3271 */
     3272static int rtFsIsoMakerFinalizeBootStuffPart1(PRTFSISOMAKERINT pThis)
     3273{
     3274    /*
     3275     * Anything?
     3276     */
     3277    if (!pThis->pBootCatFile)
     3278        return VINF_SUCCESS;
     3279
     3280    /*
     3281     * Validate the boot catalog file.
     3282     */
     3283    AssertReturn(pThis->aBootCatEntries[0].bType == ISO9660_ELTORITO_HEADER_ID_VALIDATION_ENTRY,
     3284                 VERR_ISOMK_BOOT_CAT_NO_VALIDATION_ENTRY);
     3285    AssertReturn(pThis->aBootCatEntries[1].pBootFile != NULL, VERR_ISOMK_BOOT_CAT_NO_DEFAULT_ENTRY);
     3286
     3287    /* Check any sections following the default one. */
     3288    uint32_t cEntries = 2;
     3289    while (   cEntries < RT_ELEMENTS(pThis->aBootCatEntries) - 1U
     3290           && pThis->aBootCatEntries[cEntries].cEntries > 0)
     3291    {
     3292        AssertReturn(pThis->aBootCatEntries[cEntries].bType == ISO9660_ELTORITO_HEADER_ID_SECTION_HEADER,
     3293                     VERR_ISOMK_BOOT_CAT_EXPECTED_SECTION_HEADER);
     3294        for (uint32_t i = 1; i < pThis->aBootCatEntries[cEntries].cEntries; i++)
     3295            AssertReturn(pThis->aBootCatEntries[cEntries].pBootFile != NULL,
     3296                         pThis->aBootCatEntries[cEntries].cEntries == 0
     3297                         ? VERR_ISOMK_BOOT_CAT_EMPTY_ENTRY : VERR_ISOMK_BOOT_CAT_INVALID_SECTION_SIZE);
     3298        cEntries += pThis->aBootCatEntries[cEntries].cEntries;
     3299    }
     3300
     3301    /* Check that the remaining entries are empty. */
     3302    while (cEntries < RT_ELEMENTS(pThis->aBootCatEntries) - 1U)
     3303    {
     3304        AssertReturn(pThis->aBootCatEntries[cEntries].cEntries == 0, VERR_ISOMK_BOOT_CAT_ERRATIC_ENTRY);
     3305        cEntries++;
     3306    }
     3307
     3308    /*
     3309     * Move up the boot images and boot catalog to the start of the image.
     3310     */
     3311    for (uint32_t i = RT_ELEMENTS(pThis->aBootCatEntries) - 2; i > 0; i--)
     3312        if (pThis->aBootCatEntries[i].pBootFile)
     3313        {
     3314            RTListNodeRemove(&pThis->aBootCatEntries[i].pBootFile->Core.Entry);
     3315            RTListPrepend(&pThis->ObjectHead, &pThis->aBootCatEntries[i].pBootFile->Core.Entry);
     3316        }
     3317
     3318    /* The boot catalog comes first. */
     3319    RTListNodeRemove(&pThis->pBootCatFile->Core.Entry);
     3320    RTListPrepend(&pThis->ObjectHead, &pThis->pBootCatFile->Core.Entry);
     3321
     3322    return VINF_SUCCESS;
     3323}
     3324
     3325
     3326/**
     3327 * Finalizes the El Torito boot stuff, part 1.
     3328 *
     3329 * This includes generating the boot catalog data and fixing the location of all
     3330 * related image files.
     3331 *
     3332 * @returns IPRT status code.
     3333 * @param   pThis               The ISO maker instance.
     3334 */
     3335static int rtFsIsoMakerFinalizeBootStuffPart2(PRTFSISOMAKERINT pThis)
     3336{
     3337    /*
     3338     * Fill in the descriptor.
     3339     */
     3340    PISO9660BOOTRECORDELTORITO pDesc = pThis->pElToritoDesc;
     3341    pDesc->Hdr.bDescType    = ISO9660VOLDESC_TYPE_BOOT_RECORD;
     3342    pDesc->Hdr.bDescVersion = ISO9660PRIMARYVOLDESC_VERSION;
     3343    memcpy(pDesc->Hdr.achStdId, ISO9660VOLDESC_STD_ID, sizeof(pDesc->Hdr.achStdId));
     3344    memcpy(pDesc->achBootSystemId, RT_STR_TUPLE(ISO9660BOOTRECORDELTORITO_BOOT_SYSTEM_ID));
     3345    pDesc->offBootCatalog   = RT_H2LE_U32((uint32_t)(pThis->pBootCatFile->offData / RTFSISOMAKER_SECTOR_SIZE));
     3346
     3347    /*
     3348     * Update the image file locations.
     3349     */
     3350    uint32_t cEntries = 2;
     3351    for (uint32_t i = 1; i < RT_ELEMENTS(pThis->aBootCatEntries) - 1; i++)
     3352        if (pThis->aBootCatEntries[i].pBootFile)
     3353        {
     3354            uint32_t off = pThis->aBootCatEntries[i].pBootFile->offData / RTFSISOMAKER_SECTOR_SIZE;
     3355            off = RT_H2LE_U32(off);
     3356            int rc = RTVfsFileWriteAt(pThis->pBootCatFile->u.hVfsFile,
     3357                                      i * 32 + RT_UOFFSETOF(ISO9660ELTORITOSECTIONENTRY, offBootImage),
     3358                                      &off, sizeof(off), NULL /*pcbWritten*/);
     3359            AssertRCReturn(rc, rc);
     3360            if (i == cEntries)
     3361                cEntries = i + 1;
     3362        }
     3363
     3364    /*
     3365     * Write end section.
     3366     */
     3367    ISO9660ELTORITOSECTIONHEADER Entry;
     3368    Entry.bHeaderId   = ISO9660_ELTORITO_HEADER_ID_FINAL_SECTION_HEADER;
     3369    Entry.bPlatformId = ISO9660_ELTORITO_PLATFORM_ID_X86;
     3370    Entry.cEntries    = 0;
     3371    RT_ZERO(Entry.achSectionId);
     3372    int rc = RTVfsFileWriteAt(pThis->pBootCatFile->u.hVfsFile, cEntries * 32, &Entry, sizeof(Entry), NULL /*pcbWritten*/);
     3373    AssertRCReturn(rc, rc);
     3374
    32083375    return VINF_SUCCESS;
    32093376}
     
    36793846 * Allocate and prepare the volume descriptors.
    36803847 *
    3681  * What's not done here gets done later by rtFsIsoMakerFinalizeBootStuff, or at
    3682  * teh very end of the finalization by rtFsIsoMakerFinalizeVolumeDescriptors.
     3848 * What's not done here gets done later by rtFsIsoMakerFinalizeBootStuffPart2,
     3849 * or at teh very end of the finalization by
     3850 * rtFsIsoMakerFinalizeVolumeDescriptors.
    36833851 *
    36843852 * @returns IPRT status code
     
    36993867    offVolDescs += RTFSISOMAKER_SECTOR_SIZE;
    37003868
    3701     if (true)
     3869    if (!pThis->pBootCatFile)
    37023870        pThis->pElToritoDesc = NULL;
    37033871    else
    37043872    {
    3705         pThis->pElToritoDesc = (PISO9660BOOTRECORD)&pThis->pbVolDescs[offVolDescs];
     3873        pThis->pElToritoDesc = (PISO9660BOOTRECORDELTORITO)&pThis->pbVolDescs[offVolDescs];
    37063874        offVolDescs += RTFSISOMAKER_SECTOR_SIZE;
    37073875    }
     
    39484116     */
    39494117    uint64_t offData = _32K + pThis->cVolumeDescriptors * RTFSISOMAKER_SECTOR_SIZE;
    3950     rc = rtFsIsoMakerFinalizeBootStuff(pThis, &offData);
     4118    rc = rtFsIsoMakerFinalizeBootStuffPart1(pThis);
    39514119    if (RT_SUCCESS(rc))
    39524120    {
     
    39664134
    39674135                /*
    3968                  * Finally, finalize the volume descriptors as they depend on some of the
    3969                  * block allocations done in the previous steps.
     4136                 * Do a 2nd pass over the boot stuff to finalize locations.
    39704137                 */
    3971                 rc = rtFsIsoMakerFinalizeVolumeDescriptors(pThis);
     4138                rc = rtFsIsoMakerFinalizeBootStuffPart2(pThis);
    39724139                if (RT_SUCCESS(rc))
    39734140                {
    3974                     pThis->fFinalized = true;
    3975                     return VINF_SUCCESS;
     4141                    /*
     4142                     * Finally, finalize the volume descriptors as they depend on some of the
     4143                     * block allocations done in the previous steps.
     4144                     */
     4145                    rc = rtFsIsoMakerFinalizeVolumeDescriptors(pThis);
     4146                    if (RT_SUCCESS(rc))
     4147                    {
     4148                        pThis->fFinalized = true;
     4149                        return VINF_SUCCESS;
     4150                    }
    39764151                }
    39774152            }
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