diff --git a/src/ecma119.c b/src/ecma119.c index 8bba8f8..a6f417b 100644 --- a/src/ecma119.c +++ b/src/ecma119.c @@ -10,6 +10,7 @@ #include "libisofs.h" #include "ecma119.h" #include "joliet.h" +#include "eltorito.h" #include "ecma119_tree.h" #include "error.h" #include "filesrc.h" @@ -856,6 +857,7 @@ int ecma119_image_new(IsoImage *src, Ecma119WriteOpts *opts, Ecma119Image **img) /* el-torito? */ target->eltorito = (src->bootcat == NULL ? 0 : 1); + target->catalog = src->bootcat; /* default to locale charset */ setlocale(LC_CTYPE, ""); @@ -890,6 +892,9 @@ int ecma119_image_new(IsoImage *src, Ecma119WriteOpts *opts, Ecma119Image **img) /* the number of writers is dependent of the extensions */ nwriters = 1 + 1 + 1; /* ECMA-119 + padding + files */ + if (target->eltorito) { + nwriters++; + } if (target->joliet) { nwriters++; } @@ -907,6 +912,14 @@ int ecma119_image_new(IsoImage *src, Ecma119WriteOpts *opts, Ecma119Image **img) goto target_cleanup; } + /* create writer for El-Torito */ + if (target->eltorito) { + ret = eltorito_writer_create(target); + if (ret < 0) { + goto target_cleanup; + } + } + /* create writer for Joliet structure */ if (target->joliet) { ret = joliet_writer_create(target); diff --git a/src/ecma119.h b/src/ecma119.h index 8d6d46b..57ff04b 100644 --- a/src/ecma119.h +++ b/src/ecma119.h @@ -113,7 +113,7 @@ struct ecma119_image */ struct el_torito_boot_catalog *catalog; IsoFileSrc *cat; /**< location of the boot catalog in the new image */ - uint32_t imgblock; /**< location of the boot image in the new image */ + IsoFileSrc *bootimg; /**< location of the boot image in the new image */ /* * Number of pad blocks that we need to write. Padding blocks are blocks @@ -222,6 +222,18 @@ struct ecma119_sup_vol_desc uint8_t reserved2 BP(1396, 2048); }; +/* ECMA-119, 8.2 */ +struct ecma119_boot_rec_vol_desc +{ + uint8_t vol_desc_type BP(1, 1); + uint8_t std_identifier BP(2, 6); + uint8_t vol_desc_version BP(7, 7); + uint8_t boot_sys_id BP(8, 39); + uint8_t boot_id BP(40, 71); + uint8_t boot_catalog BP(72, 75); + uint8_t unused BP(76, 2048); +}; + /* ECMA-119, 9.1 */ struct ecma119_dir_record { diff --git a/src/eltorito.c b/src/eltorito.c index 85ba458..1ef4b02 100644 --- a/src/eltorito.c +++ b/src/eltorito.c @@ -13,6 +13,7 @@ #include "filesrc.h" #include "image.h" #include "messages.h" +#include "writer.h" #include #include @@ -528,7 +529,7 @@ write_section_entry(uint8_t *buf, Ecma119Image *t) iso_lsb(se->load_seg, img->load_seg, 2); se->system_type[0] = img->partition_type; iso_lsb(se->sec_count, img->load_size, 2); - iso_lsb(se->block, t->imgblock, 4); + iso_lsb(se->block, t->bootimg->block, 4); } static @@ -715,6 +716,110 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src) if (ret <= 0) { iso_stream_unref(stream); free(file); + } else { + target->cat = *src; } return ret; } + +/******************* EL-TORITO WRITER *******************************/ + +static +int eltorito_writer_compute_data_blocks(IsoImageWriter *writer) +{ + /* nothing to do, the files are written by the file writer */ + return ISO_SUCCESS; +} + +/** + * Write the Boot Record Volume Descriptor (ECMA-119, 8.2) + */ +static +int eltorito_writer_write_vol_desc(IsoImageWriter *writer) +{ + Ecma119Image *t; + struct el_torito_boot_catalog *cat; + struct ecma119_boot_rec_vol_desc vol; + + if (writer == NULL) { + return ISO_MEM_ERROR; + } + + t = writer->target; + cat = t->catalog; + + iso_msg_debug(t->image->messenger, "Write El-Torito boot record"); + + memset(&vol, 0, sizeof(struct ecma119_boot_rec_vol_desc)); + vol.vol_desc_type[0] = 0; + memcpy(vol.std_identifier, "CD001", 5); + vol.vol_desc_version[0] = 1; + memcpy(vol.boot_sys_id, "EL TORITO SPECIFICATION", 23); + iso_lsb(vol.boot_catalog, t->cat->block, 4); + + return iso_write(t, &vol, sizeof(struct ecma119_boot_rec_vol_desc)); +} + +static +int eltorito_writer_write_data(IsoImageWriter *writer) +{ + /* nothing to do */ + return ISO_SUCCESS; +} + +static +int eltorito_writer_free_data(IsoImageWriter *writer) +{ + /* nothing to do */ + return ISO_SUCCESS; +} + +int eltorito_writer_create(Ecma119Image *target) +{ + int ret; + IsoImageWriter *writer; + IsoFile *bootimg; + IsoFileSrc *src; + + writer = malloc(sizeof(IsoImageWriter)); + if (writer == NULL) { + return ISO_MEM_ERROR; + } + + writer->compute_data_blocks = eltorito_writer_compute_data_blocks; + writer->write_vol_desc = eltorito_writer_write_vol_desc; + writer->write_data = eltorito_writer_write_data; + writer->free_data = eltorito_writer_free_data; + writer->data = NULL; + writer->target = target; + + /* add this writer to image */ + target->writers[target->nwriters++] = writer; + + /* + * get catalog and image file sources. + * Note that the catalog may be already added, when creating the low + * level ECMA-119 tree. + */ + if (target->cat == NULL) { + ret = el_torito_catalog_file_src_create(target, &src); + if (ret < 0) { + return ret; + } + } + bootimg = target->catalog->image->image; + ret = iso_file_src_create(target, bootimg, &src); + if (ret < 0) { + return ret; + } + target->bootimg = src; + + if (target->catalog->image->isolinux) { + // TODO + } + + /* we need the bootable volume descriptor */ + target->curblock++; + return ISO_SUCCESS; +} + diff --git a/src/eltorito.h b/src/eltorito.h index 2082b85..095d4a7 100644 --- a/src/eltorito.h +++ b/src/eltorito.h @@ -100,4 +100,9 @@ void el_torito_boot_catalog_free(struct el_torito_boot_catalog *cat); */ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src); +/** + * Create a writer for el-torito information. + */ +int eltorito_writer_create(Ecma119Image *target); + #endif /* LIBISO_ELTORITO_H */