diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index 1a8c3bc..12e9d66 100644 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -106,6 +106,10 @@ void ecma119_image_free(Ecma119Image *t) free(t->bootsrc); if (t->boot_appended_idx != NULL) free(t->boot_appended_idx); + if (t->boot_intvl_start != NULL) + free(t->boot_intvl_start); + if (t->boot_intvl_size != NULL) + free(t->boot_intvl_size); if (t->system_area_data != NULL) free(t->system_area_data); if (t->checksum_ctx != NULL) { /* dispose checksum context */ @@ -571,7 +575,8 @@ int ecma119_writer_write_vol_desc(IsoImageWriter *writer) strncpy_pad((char*)vol.volume_id, vol_id, 32); if (t->pvd_size_is_total_size) { iso_bb(vol.vol_space_size, - t->total_size / 2048 - t->eff_partition_offset, 4); + t->total_size / 2048 + t->opts->ms_block - t->eff_partition_offset, + 4); } else { iso_bb(vol.vol_space_size, t->vol_space_size - t->eff_partition_offset, 4); @@ -2385,13 +2390,21 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *in_opts, Ecma119Image **img) sizeof(IsoFileSrc *)); target->boot_appended_idx = calloc(target->num_bootsrc + 1, sizeof(int)); - if (target->bootsrc == NULL || target->boot_appended_idx == NULL) { + target->boot_intvl_start = calloc(target->num_bootsrc + 1, + sizeof(uint32_t)); + target->boot_intvl_size = calloc(target->num_bootsrc + 1, + sizeof(uint32_t)); + if (target->bootsrc == NULL || target->boot_appended_idx == NULL || + target->boot_intvl_start == NULL || + target->boot_intvl_size == NULL) { ret = ISO_OUT_OF_MEM; goto target_cleanup; } for (i= 0; i < target->num_bootsrc; i++) { target->bootsrc[i] = NULL; target->boot_appended_idx[i] = -1; + target->boot_intvl_start[i] = 0; + target->boot_intvl_size[i] = 0; } } else { target->num_bootsrc = 0; diff --git a/libisofs/ecma119.h b/libisofs/ecma119.h index d4d13cb..4e83385 100644 --- a/libisofs/ecma119.h +++ b/libisofs/ecma119.h @@ -651,6 +651,9 @@ struct ecma119_image int *boot_appended_idx; /* Appended partition which serve as boot images */ + uint32_t *boot_intvl_start; /* In blocks of 2048 bytes */ + uint32_t *boot_intvl_size; /* In blocks of 512 bytes */ + /* * System Area related information */ diff --git a/libisofs/eltorito.c b/libisofs/eltorito.c index c1c045b..f5d3152 100644 --- a/libisofs/eltorito.c +++ b/libisofs/eltorito.c @@ -313,6 +313,35 @@ int iso_tree_add_boot_node(IsoDir *parent, const char *name, IsoBoot **boot) return ++parent->nchildren; } +/* Get start and size from "%d_start_%lus_size_%lud" */ +static +void iso_parse_start_size(char *text, unsigned long *part_start, + unsigned long *part_size) +{ + char *cpt; + unsigned long start, size; + + cpt = strchr(text, '_'); + if (cpt == NULL) + return; + if (strncmp(cpt, "_start_", 7) != 0) + return; + sscanf(cpt + 7, "%lu", &start); + cpt = strchr(cpt + 7, '_'); + if (cpt == NULL) + return; + if (*(cpt - 1) != 's') + return; + if (strncmp(cpt, "_size_", 6) != 0) + return; + sscanf(cpt + 6, "%lu", &size); + for (cpt = cpt + 6; *cpt >= '0' && *cpt <= '9'; cpt++); + if (*cpt != 'd') + return; + + *part_start = start; + *part_size = size; +} static int create_image(IsoImage *image, const char *image_path, @@ -325,6 +354,7 @@ int create_image(IsoImage *image, const char *image_path, int boot_media_type = 0; int load_sectors = 0; /* number of sector to load */ int part_idx = -1; + unsigned long part_start = 0, part_size = 0; unsigned char partition_type = 0; off_t size; IsoNode *imgfile = NULL; @@ -351,6 +381,8 @@ int create_image(IsoImage *image, const char *image_path, "Appended partition index for El Torito boot image is out of range"); return ISO_BOOT_IMAGE_NOT_VALID; } + iso_parse_start_size((char *) (image_path + 30), + &part_start, &part_size); part_idx--; size = 1; } else { @@ -468,6 +500,8 @@ int create_image(IsoImage *image, const char *image_path, } boot->image = (IsoFile*)imgfile; boot->appended_idx = part_idx; + boot->appended_start = part_start; + boot->appended_size = part_size; if (imgfile != NULL) iso_node_ref(imgfile); /* get our ref */ boot->bootable = 1; @@ -864,7 +898,7 @@ int write_section_entry(uint8_t *buf, Ecma119Image *t, int idx) struct el_torito_boot_image *img; struct el_torito_section_entry *se = (struct el_torito_section_entry*)buf; - int app_idx; + int app_idx, mode = 0; img = t->catalog->bootimages[idx]; @@ -873,7 +907,44 @@ int write_section_entry(uint8_t *buf, Ecma119Image *t, int idx) iso_lsb(se->load_seg, img->load_seg, 2); se->system_type[0] = img->partition_type; - if (t->boot_appended_idx[idx] >= 0) { + if (t->boot_appended_idx[idx] >= 0) + if (t->appended_part_size[t->boot_appended_idx[idx]] > 0) + mode = 2; /* appended partition */ + if (mode == 0 && t->opts->appendable && + (t->boot_intvl_start[idx] > 0 || t->boot_intvl_size[idx] > 0) && + t->boot_intvl_start[idx] + (t->boot_intvl_size[idx] + 3) / 4 <= + t->opts->ms_block) + mode = 1; /* image interval */ + if (mode == 0 && t->boot_appended_idx[idx] >= 0) { + iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, + "Appended partition which shall serve as boot image does not exist"); + return ISO_BOOT_IMAGE_NOT_VALID; + } + + if (mode == 1) { + if (t->boot_intvl_start[idx] + (t->boot_intvl_size[idx] + 3) / 4 > + t->total_size / 2048 + t->opts->ms_block - t->eff_partition_offset + ) { + iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, + "Block interval which shall serve as boot image is outside result range"); + return ISO_BOOT_IMAGE_NOT_VALID; + } + + if (t->boot_intvl_size[idx] > 65535) { + if (img->platform_id == 0xef) + iso_lsb(se->sec_count, 0, 2); + else + iso_lsb(se->sec_count, 65535, 2); + } else { + if (t->boot_intvl_size[idx] == 0) { + iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, + "Block interval which shall serve as boot image has zero size"); + return ISO_BOOT_IMAGE_NOT_VALID; + } + iso_lsb(se->sec_count, t->boot_intvl_size[idx], 2); + } + iso_lsb(se->block, t->boot_intvl_start[idx], 4); + } else if (mode == 2) { app_idx = t->boot_appended_idx[idx]; if (t->appended_part_size[app_idx] * 4 > 65535) { if (img->platform_id == 0xef) @@ -881,11 +952,6 @@ int write_section_entry(uint8_t *buf, Ecma119Image *t, int idx) else iso_lsb(se->sec_count, 65535, 2); } else { - if (t->appended_part_size[app_idx] == 0) { - iso_msg_submit(t->image->id, ISO_BOOT_IMAGE_NOT_VALID, 0, - "Appended partition which shall serve as boot image does not exist"); - return ISO_BOOT_IMAGE_NOT_VALID; - } iso_lsb(se->sec_count, t->appended_part_size[app_idx] * 4, 2); } iso_lsb(se->block, t->appended_part_start[app_idx], 4); @@ -1387,6 +1453,10 @@ int eltorito_writer_create(Ecma119Image *target) /* Use an appended partition as boot image rather than IsoFile */ target->boot_appended_idx[idx] = target->catalog->bootimages[idx]->appended_idx; + target->boot_intvl_start[idx] = + target->catalog->bootimages[idx]->appended_start; + target->boot_intvl_size[idx] = + target->catalog->bootimages[idx]->appended_size; if (((target->system_area_options >> 2) & 0x3f) == 0 && (target->system_area_options & 3) == 1) { /* ISO will not be a partition. It can span the whole image. */ diff --git a/libisofs/eltorito.h b/libisofs/eltorito.h index a027d1d..bbd035a 100644 --- a/libisofs/eltorito.h +++ b/libisofs/eltorito.h @@ -55,6 +55,8 @@ struct el_torito_boot_image { /* Overrides .image if >= 0 : array index of appended partition */ int appended_idx; + uint32_t appended_start; /* In blocks of 2048 bytes */ + uint32_t appended_size; /* In blocks of 512 bytes */ unsigned int bootable:1; /**< If the entry is bootable. */ /** diff --git a/libisofs/libisofs.h b/libisofs/libisofs.h index 59d930b..2394285 100644 --- a/libisofs/libisofs.h +++ b/libisofs/libisofs.h @@ -3453,7 +3453,7 @@ int iso_image_set_boot_image(IsoImage *image, const char *image_path, * @param image_path * The absolute path of a IsoFile to be used as boot image. ->>> or --interval:appended_partition_$number... +>>> or --interval:appended_partition_${number}s_start_${start}d_size_$size:... * @param type * The boot media type. See iso_image_set_boot_image