From 7e97a45b20af076523f7ba41dca844091d6e3526 Mon Sep 17 00:00:00 2001 From: Vreixo Formoso Date: Sun, 19 Oct 2008 16:03:13 +0200 Subject: [PATCH] Support for writing MBR in the system area, to make hybrid boot images. With the specified isolinux option, a MBR is written to the system area, and this allows the image to boot from either CD/DVD or USB sticks. This is also supported on overwriteable media (note that system area is always overwritten), but it should not work on multisession media. --- Makefile.am | 2 ++ libisofs/ecma119.c | 21 ++++++++++++--- libisofs/eltorito.h | 24 +++++------------ libisofs/system_area.c | 59 ++++++++++++++++++++++++++++++++++++++++++ libisofs/system_area.h | 48 ++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 22 deletions(-) create mode 100644 libisofs/system_area.c create mode 100644 libisofs/system_area.h diff --git a/Makefile.am b/Makefile.am index 34c3792..eb446f3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -52,6 +52,8 @@ libisofs_libisofs_la_SOURCES = \ libisofs/joliet.c \ libisofs/eltorito.h \ libisofs/eltorito.c \ + libisofs/system_area.h \ + libisofs/system_area.c \ libisofs/make_isohybrid_mbr.c \ libisofs/iso1999.h \ libisofs/iso1999.c \ diff --git a/libisofs/ecma119.c b/libisofs/ecma119.c index 973191e..d4196b4 100644 --- a/libisofs/ecma119.c +++ b/libisofs/ecma119.c @@ -19,6 +19,7 @@ #include "messages.h" #include "rockridge.h" #include "util.h" +#include "system_area.h" #include "libburn/libburn.h" @@ -784,10 +785,14 @@ void *write_function(void *arg) target->bytes_written = (off_t) 0; target->percent_written = 0; - /* Write System Area, 16 blocks of zeros (ECMA-119, 6.2.1) */ - memset(buf, 0, BLOCK_SIZE); - for (i = 0; i < 16; ++i) { - res = iso_write(target, buf, BLOCK_SIZE); + /* Write System Area (ECMA-119, 6.2.1) */ + { + uint8_t sa[16 * BLOCK_SIZE]; + res = iso_write_system_area(target, sa); + if (res < 0) { + goto write_error; + } + res = iso_write(target, sa, 16 * BLOCK_SIZE); if (res < 0) { goto write_error; } @@ -1054,6 +1059,14 @@ int ecma119_image_new(IsoImage *src, IsoWriteOpts *opts, Ecma119Image **img) } } + /* write the system area */ + ret = iso_write_system_area(target, opts->overwrite); + if (ret < 0) { + iso_msg_debug(target->image->id, + "Error writing system area to overwrite buffer"); + goto target_cleanup; + } + /* skip the first 16 blocks (system area) */ buf = opts->overwrite + 16 * BLOCK_SIZE; voldesc_size *= BLOCK_SIZE; diff --git a/libisofs/eltorito.h b/libisofs/eltorito.h index 07c72a0..9938eec 100644 --- a/libisofs/eltorito.h +++ b/libisofs/eltorito.h @@ -35,7 +35,12 @@ struct el_torito_boot_image { IsoFile *image; unsigned int bootable:1; /**< If the entry is bootable. */ - unsigned int isolinux:1; /**< If the image will be patched */ + /** + * isolinux options + * bit 0 -> whether to patch image + * bit 1 -> whether to create isolinux image + */ + unsigned int isolinux_options:2; unsigned char type; /**< The type of image */ unsigned char partition_type; /**< type of partition for HD-emul images */ short load_seg; /**< Load segment for the initial boot image. */ @@ -100,21 +105,4 @@ int el_torito_catalog_file_src_create(Ecma119Image *target, IsoFileSrc **src); */ int eltorito_writer_create(Ecma119Image *target); -/* - * Create a MBR for an isohybrid enabled ISOLINUX boot image. - * - * It is assumed that the caller has verified the readiness of the boot image - * by checking for 0xfb 0xc0 0x78 0x70 at bytes 0x40 to 0x43 of isolinux.bin. - * - * @param bin_lba The predicted LBA of isolinux.bin within the emerging ISO. - * @param img_blocks The predicted number of 2048 byte blocks in the ISO. - * It will get rounded up to full MBs and that many blocks - * must really be written as ISO 9660 image. - * @param mbr A buffer of at least 512 bytes to take the result which is - * to be written as the very beginning of the ISO. - * @param flag unused yet, submit 0 - * @return <0 = fatal, 0 = failed , 1 = ok , 2 = ok with size warning - */ -int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag); - #endif /* LIBISO_ELTORITO_H */ diff --git a/libisofs/system_area.c b/libisofs/system_area.c new file mode 100644 index 0000000..503a066 --- /dev/null +++ b/libisofs/system_area.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2008 Vreixo Formoso + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See COPYING file for details. + */ + +#include "system_area.h" +#include "eltorito.h" +#include "filesrc.h" + +#include + + + +/* + * Create a MBR for an isohybrid enabled ISOLINUX boot image. + * + * It is assumed that the caller has verified the readiness of the boot image + * by checking for 0xfb 0xc0 0x78 0x70 at bytes 0x40 to 0x43 of isolinux.bin. + * + * @param bin_lba The predicted LBA of isolinux.bin within the emerging ISO. + * @param img_blocks The predicted number of 2048 byte blocks in the ISO. + * It will get rounded up to full MBs and that many blocks + * must really be written as ISO 9660 image. + * @param mbr A buffer of at least 512 bytes to take the result which is + * to be written as the very beginning of the ISO. + * @param flag unused yet, submit 0 + * @return <0 = fatal, 0 = failed , 1 = ok , 2 = ok with size warning + */ +int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag); + +int iso_write_system_area(Ecma119Image *t, uint8_t *buf) +{ + if ((t == NULL) || (buf == NULL)) { + return ISO_NULL_POINTER; + } + + /* set buf to 0s */ + memset(buf, 0, 16 * BLOCK_SIZE); + + if (t->catalog != NULL && t->catalog->image->isolinux_options & 0x02) { + /* We need to write a MBR for an hybrid image */ + int ret; + int img_blocks; + + img_blocks = t->curblock; + ret = make_isohybrid_mbr(t->bootimg->sections[0].block, &img_blocks, (char*)buf, 0); + + // FIXME the new img_blocks size should be taken into account + + if (ret != 1) { + /* error, it should never happen */ + return ISO_ASSERT_FAILURE; + } + } + return ISO_SUCCESS; +} diff --git a/libisofs/system_area.h b/libisofs/system_area.h new file mode 100644 index 0000000..b175e64 --- /dev/null +++ b/libisofs/system_area.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008 Vreixo Formoso + * + * This file is part of the libisofs project; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. See COPYING file for details. + */ + +/* + * Functions for dealing with the system area, this is, the first 16 blocks + * of the image. + * + * At this time, this is only used for hybrid boot images with isolinux. + */ + +#ifndef SYSTEM_AREA_H_ +#define SYSTEM_AREA_H_ + +#include "ecma119.h" + +/* + * Create a MBR for an isohybrid enabled ISOLINUX boot image. + * + * It is assumed that the caller has verified the readiness of the boot image + * by checking for 0xfb 0xc0 0x78 0x70 at bytes 0x40 to 0x43 of isolinux.bin. + * + * @param bin_lba The predicted LBA of isolinux.bin within the emerging ISO. + * @param img_blocks The predicted number of 2048 byte blocks in the ISO. + * It will get rounded up to full MBs and that many blocks + * must really be written as ISO 9660 image. + * @param mbr A buffer of at least 512 bytes to take the result which is + * to be written as the very beginning of the ISO. + * @param flag unused yet, submit 0 + * @return <0 = fatal, 0 = failed , 1 = ok , 2 = ok with size warning + */ +int make_isohybrid_mbr(int bin_lba, int *img_blocks, char *mbr, int flag); + +/** + * Write the system area for the given image to the given buffer. + * + * @param buf + * A buffer with at least 32 K allocated + * @return + * 1 if success, < 0 on error + */ +int iso_write_system_area(Ecma119Image *t, uint8_t *buf); + +#endif /* SYSTEM_AREA_H_ */