/* * Program eltorito.c - Handle El Torito specific extensions to iso9660. * Written by Michael Fulbright (1996). 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 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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, 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 $"; #include #include #include #include #include #include #include #include "config.h" #include "mkisofs.h" #include "iso9660.h" /* used by Win32 for opening binary file - not used by Unix */ #ifndef O_BINARY #define O_BINARY 0 #endif /* O_BINARY */ #undef MIN #define MIN(a, b) (((a) < (b))? (a): (b)) static struct eltorito_validation_entry valid_desc; static struct eltorito_defaultboot_entry default_desc; static struct eltorito_boot_descriptor gboot_desc; static int tvd_write __PR((FILE * outfile)); /* * Check for presence of boot catalog. If it does not exist then make it */ void FDECL1(init_boot_catalog, const char *, path) { int bcat; char * bootpath; /* filename of boot catalog */ char * buf; struct stat statbuf; bootpath = (char *) e_malloc(strlen(boot_catalog)+strlen(path)+2); strcpy(bootpath, path); if (bootpath[strlen(bootpath)-1] != '/') { strcat(bootpath,"/"); } strcat(bootpath, boot_catalog); /* * check for the file existing */ #ifdef DEBUG_TORITO fprintf(stderr,"Looking for boot catalog file %s\n",bootpath); #endif if (!stat_filter(bootpath, &statbuf)) { /* * make sure its big enough to hold what we want */ if (statbuf.st_size == 2048) { /* * printf("Boot catalog exists, so we do nothing\n"); */ free(bootpath); return; } else { fprintf(stderr, "A boot catalog exists and appears corrupted.\n"); fprintf(stderr, "Please check the following file: %s.\n",bootpath); fprintf(stderr, "This file must be removed before a bootable CD can be done.\n"); free(bootpath); exit(1); } } /* * file does not exist, so we create it * make it one CD sector long */ bcat = open(bootpath, O_WRONLY | O_CREAT | O_BINARY, S_IROTH | S_IRGRP | S_IRWXU ); if (bcat == -1) error (1, errno, "Error creating boot catalog (%s)", bootpath); buf = (char *) e_malloc( 2048 ); write(bcat, buf, 2048); close(bcat); free(bootpath); } /* init_boot_catalog(... */ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) { int bootcat; int checksum; unsigned char * checksum_ptr; struct directory_entry * de; struct directory_entry * de2; unsigned int i; int nsectors; memset(boot_desc, 0, sizeof(*boot_desc)); boot_desc->id[0] = 0; memcpy(boot_desc->id2, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID)); boot_desc->version[0] = 1; memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof(EL_TORITO_ID)); /* * search from root of iso fs to find boot catalog */ de2 = search_tree_file(root, boot_catalog); if (!de2) { fprintf(stderr,"Uh oh, I cant find the boot catalog!\n"); exit(1); } set_731(boot_desc->bootcat_ptr, (unsigned int) get_733(de2->isorec.extent)); /* * now adjust boot catalog * lets find boot image first */ de=search_tree_file(root, boot_image); if (!de) { fprintf(stderr,"Uh oh, I cant find the boot image!\n"); exit(1); } /* * we have the boot image, so write boot catalog information * Next we write out the primary descriptor for the disc */ memset(&valid_desc, 0, sizeof(valid_desc)); valid_desc.headerid[0] = 1; valid_desc.arch[0] = EL_TORITO_ARCH_x86; /* * we'll shove start of publisher id into id field, may get truncated * but who really reads this stuff! */ if (publisher) memcpy_max(valid_desc.id, publisher, MIN(23, strlen(publisher))); valid_desc.key1[0] = 0x55; valid_desc.key2[0] = 0xAA; /* * compute the checksum */ checksum=0; checksum_ptr = (unsigned char *) &valid_desc; for (i=0; isize + 511) & ~(511))/512; fprintf(stderr, "\nSize of boot image is %d sectors -> ", nsectors); 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!!! */ nsectors = 1; set_721(default_desc.nsect, (unsigned int) nsectors ); #ifdef DEBUG_TORITO fprintf(stderr,"Extent of boot images is %d\n",get_733(de->isorec.extent)); #endif set_731(default_desc.bootoff, (unsigned int) get_733(de->isorec.extent)); /* * now write it to disk */ bootcat = open(de2->whole_name, O_RDWR | O_BINARY); if (bootcat == -1) { fprintf(stderr,"Error opening boot catalog for update.\n"); perror(""); exit(1); } /* * write out */ 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(... */ /* * Function to write the EVD for the disc. */ static int FDECL1(tvd_write, FILE *, outfile) { /* * Next we write out the boot volume descriptor for the disc */ get_torito_desc(&gboot_desc); xfwrite(&gboot_desc, 1, 2048, outfile); last_extent_written ++; return 0; } struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write};