diff --git a/ChangeLog b/ChangeLog index 4e868b5b9..1a15e8d86 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2009-11-11 Robert Millan + + Support for El Torito without floppy emulation. + + * util/mkisofs/eltorito.c: Include `'. + (init_boot_catalog): Improve error handling. + (get_torito_desc): Don't use floppy emulation unless requested by + user. Patch boot information table when requested via + `-boot-info-table'. + * util/mkisofs/iso9660.h (struct eltorito_boot_info): New struct. + * util/mkisofs/mkisofs.c (use_eltorito_emul_floppy) + (use_boot_info_table): New variables. + (OPTION_BOOT_INFO_TABLE, OPTION_NO_EMUL_BOOT) + (OPTION_ELTORITO_EMUL_FLOPPY): New macros. + (ld_options): Handle `-boot-info-table', `-no-emul-boot' and + `--eltorito-emul-floppy'. + (main): Handle `OPTION_BOOT_INFO_TABLE', `OPTION_NO_EMUL_BOOT' + and `OPTION_ELTORITO_EMUL_FLOPPY'. + * util/mkisofs/mkisofs.h (use_eltorito_emul_floppy) + (use_boot_info_table, get_731): New prototypes. + * util/mkisofs/write.c (get_731): New function. + 2009-11-11 Felix Zielcke Fix the generation of the man page. diff --git a/util/mkisofs/eltorito.c b/util/mkisofs/eltorito.c index e003f2b67..858aa79dc 100644 --- a/util/mkisofs/eltorito.c +++ b/util/mkisofs/eltorito.c @@ -6,9 +6,14 @@ Copyright 1996 RedHat Software, Incorporated + Copyright (C) 2009 Free Software Foundation, Inc. + + Boot Info Table generation based on code from genisoimage.c + (from cdrkit 1.1.9), which was originally licensed under GPLv2+. + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,8 +22,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + along with this program; if not, see . + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ static char rcsid[] ="$Id: eltorito.c,v 1.13 1999/03/02 03:41:25 eric Exp $"; @@ -29,6 +34,7 @@ static char rcsid[] ="$Id: eltorito.c,v 1.13 1999/03/02 03:41:25 eric Exp $"; #include #include #include +#include #include "config.h" #include "mkisofs.h" @@ -103,12 +109,8 @@ void FDECL1(init_boot_catalog, const char *, path) * make it one CD sector long */ bcat = open(bootpath, O_WRONLY | O_CREAT | O_BINARY, S_IROTH | S_IRGRP | S_IRWXU ); - if (bcat == -1) - { - fprintf(stderr, "Error creating boot catalog, exiting...\n"); - perror(""); - exit(1); - } + if (bcat == -1) + error (1, errno, "Error creating boot catalog (%s)", bootpath); buf = (char *) e_malloc( 2048 ); write(bcat, buf, 2048); @@ -217,31 +219,35 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) */ nsectors = ((de->size + 511) & ~(511))/512; fprintf(stderr, "\nSize of boot image is %d sectors -> ", nsectors); - - /* - * choose size of emulated floppy based on boot image size - */ - if (nsectors == 2880 ) - { + + if (! use_eltorito_emul_floppy) + { + default_desc.boot_media[0] = EL_TORITO_MEDIA_NOEMUL; + fprintf (stderr, "No emulation\n"); + } + else if (nsectors == 2880 ) + /* + * choose size of emulated floppy based on boot image size + */ + { default_desc.boot_media[0] = EL_TORITO_MEDIA_144FLOP; fprintf(stderr, "Emulating a 1.44 meg floppy\n"); - } + } else if (nsectors == 5760 ) - { + { default_desc.boot_media[0] = EL_TORITO_MEDIA_288FLOP; fprintf(stderr,"Emulating a 2.88 meg floppy\n"); - } + } else if (nsectors == 2400 ) - { + { default_desc.boot_media[0] = EL_TORITO_MEDIA_12FLOP; fprintf(stderr,"Emulating a 1.2 meg floppy\n"); - } + } else - { + { fprintf(stderr,"\nError - boot image is not the an allowable size.\n"); exit(1); - } - + } /* * FOR NOW LOAD 1 SECTOR, JUST LIKE FLOPPY BOOT!!! @@ -271,6 +277,53 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) write(bootcat, &valid_desc, 32); write(bootcat, &default_desc, 32); close(bootcat); + + /* If the user has asked for it, patch the boot image */ + if (use_boot_info_table) + { + int bootimage; + uint32_t bi_checksum; + unsigned int total_len; + static char csum_buffer[SECTOR_SIZE]; + int len; + struct eltorito_boot_info bi_table; + bootimage = open (de->whole_name, O_RDWR | O_BINARY); + if (bootimage == -1) + error (1, errno, "Error opening boot image file '%s' for update", + de->whole_name); + /* Compute checksum of boot image, sans 64 bytes */ + total_len = 0; + bi_checksum = 0; + while ((len = read (bootimage, csum_buffer, SECTOR_SIZE)) > 0) + { + if (total_len & 3) + error (1, 0, "Odd alignment at non-end-of-file in boot image '%s'", + de->whole_name); + if (total_len < 64) + memset (csum_buffer, 0, 64 - total_len); + if (len < SECTOR_SIZE) + memset (csum_buffer + len, 0, SECTOR_SIZE - len); + for (i = 0; i < SECTOR_SIZE; i += 4) + bi_checksum += get_731 (&csum_buffer[i]); + total_len += len; + } + + if (total_len != de->size) + error (1, 0, "Boot image file '%s' changed underneath us", + de->whole_name); + /* End of file, set position to byte 8 */ + lseek (bootimage, (off_t) 8, SEEK_SET); + memset (&bi_table, 0, sizeof (bi_table)); + /* Is it always safe to assume PVD is at session_start+16? */ + set_731 (bi_table.pvd_addr, session_start + 16); + set_731 (bi_table.file_addr, de->starting_block); + set_731 (bi_table.file_length, de->size); + set_731 (bi_table.file_checksum, bi_checksum); + + write (bootimage, &bi_table, sizeof (bi_table)); /* FIXME: check return value */ + close (bootimage); + } + } /* get_torito_desc(... */ /* diff --git a/util/mkisofs/iso9660.h b/util/mkisofs/iso9660.h index 65320121d..3ba0faaac 100644 --- a/util/mkisofs/iso9660.h +++ b/util/mkisofs/iso9660.h @@ -6,9 +6,11 @@ Copyright 1993 Yggdrasil Computing, Incorporated + Copyright (C) 2009 Free Software Foundation, Inc. + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -17,7 +19,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software + along with this program; if not, see . Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* @@ -129,6 +131,20 @@ struct eltorito_defaultboot_entry { char pad2 [ISODCL ( 13, 32)]; }; +/* El Torito boot information table */ +struct eltorito_boot_info +{ + /* Address of Primary Volume Descriptor. */ + char pvd_addr[ISODCL (1, 4)]; + /* Boot file address. */ + char file_addr[ISODCL (5, 8)]; + /* Boot file length. */ + char file_length[ISODCL (9, 12)]; + /* Boot file checksum. */ + char file_checksum[ISODCL (13, 16)]; + char dummy[ISODCL (17, 56)]; +}; + /* We use this to help us look up the parent inode numbers. */ diff --git a/util/mkisofs/mkisofs.c b/util/mkisofs/mkisofs.c index 8497723e6..0c89a2d8c 100644 --- a/util/mkisofs/mkisofs.c +++ b/util/mkisofs/mkisofs.c @@ -89,6 +89,8 @@ int extension_record_size = 0; /* These variables are associated with command line options */ int use_eltorito = 0; +int use_eltorito_emul_floppy = 0; +int use_boot_info_table = 0; int use_RockRidge = 0; int use_Joliet = 0; int verbose = 1; @@ -189,6 +191,10 @@ struct ld_option #define OPTION_EXPIR_DATE 168 #define OPTION_EFFEC_DATE 169 +#define OPTION_BOOT_INFO_TABLE 170 +#define OPTION_NO_EMUL_BOOT 171 +#define OPTION_ELTORITO_EMUL_FLOPPY 172 + static const struct ld_option ld_options[] = { { {"all-files", no_argument, NULL, 'a'}, @@ -205,6 +211,12 @@ static const struct ld_option ld_options[] = 'b', "FILE", "Set El Torito boot image name" , ONE_DASH }, { {"eltorito-catalog", required_argument, NULL, 'c'}, 'c', "FILE", "Set El Torito boot catalog name" , ONE_DASH }, + { {"boot-info-table", no_argument, NULL, OPTION_BOOT_INFO_TABLE }, + '\0', NULL, "Patch Boot Info Table in El Torito boot image" , ONE_DASH }, + { {"no-emul-boot", no_argument, NULL, OPTION_NO_EMUL_BOOT }, + '\0', NULL, "Dummy option for backward compatibility" , ONE_DASH }, + { {"eltorito-emul-floppy", no_argument, NULL, OPTION_ELTORITO_EMUL_FLOPPY }, + '\0', NULL, "Enable floppy drive emulation for El Torito" , TWO_DASHES }, { {"cdwrite-params", required_argument, NULL, 'C'}, 'C', "PARAMS", "Magic parameters from cdrecord" , ONE_DASH }, { {"omit-period", no_argument, NULL, 'd'}, @@ -716,6 +728,15 @@ int FDECL2(main, int, argc, char **, argv){ exit(1); } break; + case OPTION_BOOT_INFO_TABLE: + use_boot_info_table = 1; + break; + case OPTION_NO_EMUL_BOOT: + fprintf (stderr, "Ignoring -no-emul-boot (no-emulation is the default behaviour)\n"); + break; + case OPTION_ELTORITO_EMUL_FLOPPY: + use_eltorito_emul_floppy = 1; + break; case OPTION_ABSTRACT: abstract = optarg; if(strlen(abstract) > 37) { diff --git a/util/mkisofs/mkisofs.h b/util/mkisofs/mkisofs.h index 52acc72b5..79266e08a 100644 --- a/util/mkisofs/mkisofs.h +++ b/util/mkisofs/mkisofs.h @@ -291,6 +291,8 @@ extern struct iso_directory_record root_record; extern struct iso_directory_record jroot_record; extern int use_eltorito; +extern int use_eltorito_emul_floppy; +extern int use_boot_info_table; extern int use_RockRidge; extern int use_Joliet; extern int rationalize; @@ -335,6 +337,7 @@ extern void DECL(init_boot_catalog, (const char * path )); extern void DECL(get_torito_desc, (struct eltorito_boot_descriptor * path )); /* write.c */ +extern int DECL(get_731,(char *)); extern int DECL(get_733,(char *)); extern int DECL(isonum_733,(unsigned char *)); extern void DECL(set_723,(char *, unsigned int)); diff --git a/util/mkisofs/write.c b/util/mkisofs/write.c index 7c4540492..45b630693 100644 --- a/util/mkisofs/write.c +++ b/util/mkisofs/write.c @@ -111,6 +111,14 @@ void FDECL2(set_732, char *, pnt, unsigned int, i) pnt[0] = (i >> 24) & 0xff; } +int FDECL1(get_731, char *, p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + int FDECL1(get_733, char *, p) { return ((p[0] & 0xff)