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.
This commit is contained in:
Vreixo Formoso 2008-10-19 16:03:13 +02:00
parent 7db39f99b6
commit 7e97a45b20
5 changed files with 132 additions and 22 deletions

View File

@ -52,6 +52,8 @@ libisofs_libisofs_la_SOURCES = \
libisofs/joliet.c \ libisofs/joliet.c \
libisofs/eltorito.h \ libisofs/eltorito.h \
libisofs/eltorito.c \ libisofs/eltorito.c \
libisofs/system_area.h \
libisofs/system_area.c \
libisofs/make_isohybrid_mbr.c \ libisofs/make_isohybrid_mbr.c \
libisofs/iso1999.h \ libisofs/iso1999.h \
libisofs/iso1999.c \ libisofs/iso1999.c \

View File

@ -19,6 +19,7 @@
#include "messages.h" #include "messages.h"
#include "rockridge.h" #include "rockridge.h"
#include "util.h" #include "util.h"
#include "system_area.h"
#include "libburn/libburn.h" #include "libburn/libburn.h"
@ -784,10 +785,14 @@ void *write_function(void *arg)
target->bytes_written = (off_t) 0; target->bytes_written = (off_t) 0;
target->percent_written = 0; target->percent_written = 0;
/* Write System Area, 16 blocks of zeros (ECMA-119, 6.2.1) */ /* Write System Area (ECMA-119, 6.2.1) */
memset(buf, 0, BLOCK_SIZE); {
for (i = 0; i < 16; ++i) { uint8_t sa[16 * BLOCK_SIZE];
res = iso_write(target, buf, 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) { if (res < 0) {
goto write_error; 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) */ /* skip the first 16 blocks (system area) */
buf = opts->overwrite + 16 * BLOCK_SIZE; buf = opts->overwrite + 16 * BLOCK_SIZE;
voldesc_size *= BLOCK_SIZE; voldesc_size *= BLOCK_SIZE;

View File

@ -35,7 +35,12 @@ struct el_torito_boot_image {
IsoFile *image; IsoFile *image;
unsigned int bootable:1; /**< If the entry is bootable. */ 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 type; /**< The type of image */
unsigned char partition_type; /**< type of partition for HD-emul images */ unsigned char partition_type; /**< type of partition for HD-emul images */
short load_seg; /**< Load segment for the initial boot image. */ 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); 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 */ #endif /* LIBISO_ELTORITO_H */

59
libisofs/system_area.c Normal file
View File

@ -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 <string.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);
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;
}

48
libisofs/system_area.h Normal file
View File

@ -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_ */