eltorito.c revision 1.2
1/* 2 * Program eltorito.c - Handle El Torito specific extensions to iso9660. 3 * 4 5 Written by Michael Fulbright <msf@redhat.com> (1996). 6 7 Copyright 1996 RedHat Software, Incorporated 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2, or (at your option) 12 any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 22 23 24static char rcsid[] ="$Id: eltorito.c,v 1.2 2004/06/22 22:58:06 tom Exp $"; 25 26#include <stdio.h> 27#include <sys/types.h> 28#include <sys/stat.h> 29#include <unistd.h> 30#include <fcntl.h> 31#include <stdlib.h> 32 33#include "config.h" 34#include "mkisofs.h" 35#include "iso9660.h" 36 37/* used by Win32 for opening binary file - not used by Unix */ 38#ifndef O_BINARY 39#define O_BINARY 0 40#endif /* O_BINARY */ 41 42#undef MIN 43#define MIN(a, b) (((a) < (b))? (a): (b)) 44 45static struct eltorito_validation_entry valid_desc; 46static struct eltorito_defaultboot_entry default_desc; 47static struct eltorito_boot_descriptor gboot_desc; 48 49static int tvd_write __PR((FILE * outfile)); 50 51/* 52 * Check for presence of boot catalog. If it does not exist then make it 53 */ 54void FDECL1(init_boot_catalog, const char *, path) 55{ 56 57 int bcat; 58 char * bootpath; /* filename of boot catalog */ 59 char * buf; 60 struct stat statbuf; 61 62 bootpath = (char *) e_malloc(strlen(boot_catalog)+strlen(path)+2); 63 strcpy(bootpath, path); 64 if (bootpath[strlen(bootpath)-1] != '/') 65 { 66 strcat(bootpath,"/"); 67 } 68 69 strcat(bootpath, boot_catalog); 70 71 /* 72 * check for the file existing 73 */ 74#ifdef DEBUG_TORITO 75 fprintf(stderr,"Looking for boot catalog file %s\n",bootpath); 76#endif 77 78 if (!stat_filter(bootpath, &statbuf)) 79 { 80 /* 81 * make sure its big enough to hold what we want 82 */ 83 if (statbuf.st_size == 2048) 84 { 85 /* 86 * printf("Boot catalog exists, so we do nothing\n"); 87 */ 88 free(bootpath); 89 return; 90 } 91 else 92 { 93 fprintf(stderr, "A boot catalog exists and appears corrupted.\n"); 94 fprintf(stderr, "Please check the following file: %s.\n",bootpath); 95 fprintf(stderr, "This file must be removed before a bootable CD can be done.\n"); 96 free(bootpath); 97 exit(1); 98 } 99 } 100 101 /* 102 * file does not exist, so we create it 103 * make it one CD sector long 104 */ 105 bcat = open(bootpath, O_WRONLY | O_CREAT | O_BINARY, S_IROTH | S_IRGRP | S_IRWXU ); 106 if (bcat == -1) 107 { 108 fprintf(stderr, "Error creating boot catalog, exiting...\n"); 109 perror(""); 110 exit(1); 111 } 112 113 buf = (char *) e_malloc( 2048 ); 114 write(bcat, buf, 2048); 115 close(bcat); 116 free(bootpath); 117} /* init_boot_catalog(... */ 118 119void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) 120{ 121 int bootcat; 122 int checksum; 123 unsigned char * checksum_ptr; 124 struct directory_entry * de; 125 struct directory_entry * de2; 126 int i; 127 int nsectors; 128 129 memset(boot_desc, 0, sizeof(*boot_desc)); 130 boot_desc->id[0] = 0; 131 memcpy(boot_desc->id2, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID)); 132 boot_desc->version[0] = 1; 133 134 memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof(EL_TORITO_ID)); 135 136 /* 137 * search from root of iso fs to find boot catalog 138 */ 139 de2 = search_tree_file(root, boot_catalog); 140 if (!de2) 141 { 142 fprintf(stderr,"Uh oh, I cant find the boot catalog!\n"); 143 exit(1); 144 } 145 146 set_731(boot_desc->bootcat_ptr, 147 (unsigned int) get_733(de2->isorec.extent)); 148 149 /* 150 * now adjust boot catalog 151 * lets find boot image first 152 */ 153 de=search_tree_file(root, boot_image); 154 if (!de) 155 { 156 fprintf(stderr,"Uh oh, I cant find the boot image!\n"); 157 exit(1); 158 } 159 160 /* 161 * we have the boot image, so write boot catalog information 162 * Next we write out the primary descriptor for the disc 163 */ 164 memset(&valid_desc, 0, sizeof(valid_desc)); 165 valid_desc.headerid[0] = 1; 166 valid_desc.arch[0] = EL_TORITO_ARCH_x86; 167 168 /* 169 * we'll shove start of publisher id into id field, may get truncated 170 * but who really reads this stuff! 171 */ 172 if (publisher) 173 memcpy_max(valid_desc.id, publisher, MIN(23, strlen(publisher))); 174 175 valid_desc.key1[0] = 0x55; 176 valid_desc.key2[0] = 0xAA; 177 178 /* 179 * compute the checksum 180 */ 181 checksum=0; 182 checksum_ptr = (unsigned char *) &valid_desc; 183 for (i=0; i<sizeof(valid_desc); i+=2) 184 { 185 /* 186 * skip adding in ckecksum word, since we dont have it yet! 187 */ 188 if (i == 28) 189 { 190 continue; 191 } 192 checksum += (unsigned int)checksum_ptr[i]; 193 checksum += ((unsigned int)checksum_ptr[i+1])*256; 194 } 195 196 /* 197 * now find out the real checksum 198 */ 199 checksum = -checksum; 200 set_721(valid_desc.cksum, (unsigned int) checksum); 201 202 /* 203 * now make the initial/default entry for boot catalog 204 */ 205 memset(&default_desc, 0, sizeof(default_desc)); 206 default_desc.boot_id[0] = EL_TORITO_BOOTABLE; 207 208 /* 209 * use default BIOS loadpnt 210 */ 211 set_721(default_desc.loadseg, 0); 212 default_desc.arch[0] = EL_TORITO_ARCH_x86; 213 214 /* 215 * figure out size of boot image in sectors, for now hard code to 216 * assume 512 bytes/sector on a bootable floppy 217 */ 218 nsectors = ((de->size + 511) & ~(511))/512; 219#ifdef APPLE_HYB 220 /* NON-HFS change */ 221 if (verbose > 0 ) 222#endif /* APPLE_HYB */ 223 fprintf(stderr, "\nSize of boot image is %d sectors -> ", nsectors); 224 225 /* 226 * choose size of emulated floppy based on boot image size 227 */ 228 if (nsectors == 2880 ) 229 { 230 default_desc.boot_media[0] = EL_TORITO_MEDIA_144FLOP; 231#ifdef APPLE_HYB 232 /* NON-HFS change */ 233 if (verbose > 0 ) 234#endif /* APPLE_HYB */ 235 fprintf(stderr, "Emulating a 1.44 meg floppy\n"); 236 } 237 else if (nsectors == 5760 ) 238 { 239 default_desc.boot_media[0] = EL_TORITO_MEDIA_288FLOP; 240#ifdef APPLE_HYB 241 /* NON-HFS change */ 242 if (verbose > 0 ) 243#endif /* APPLE_HYB */ 244 fprintf(stderr,"Emulating a 2.88 meg floppy\n"); 245 } 246 else if (nsectors == 2400 ) 247 { 248 default_desc.boot_media[0] = EL_TORITO_MEDIA_12FLOP; 249#ifdef APPLE_HYB 250 /* NON-HFS change */ 251 if (verbose > 0 ) 252#endif /* APPLE_HYB */ 253 fprintf(stderr,"Emulating a 1.2 meg floppy\n"); 254 } 255 else if (nsectors == 4 ) 256 { 257 default_desc.boot_media[0] = EL_TORITO_MEDIA_NOEMUL; 258#ifdef APPLE_HYB 259 /* NON-HFS change */ 260 if (verbose > 0 ) 261#endif /* APPLE_HYB */ 262 fprintf(stderr,"No-emulation CD boot sector\n"); 263 } 264 else 265 { 266 fprintf(stderr,"\nError - boot image is not the an allowable size.\n"); 267 exit(1); 268 } 269 270 271 /* 272 * FOR NOW LOAD 1 SECTOR, JUST LIKE FLOPPY BOOT, unless it's no-emulation 273 * boot. 274 */ 275 if (default_desc.boot_media[0] != EL_TORITO_MEDIA_NOEMUL) 276 nsectors = 1; 277 set_721(default_desc.nsect, (unsigned int) nsectors ); 278#ifdef DEBUG_TORITO 279 fprintf(stderr,"Extent of boot images is %d\n",get_733(de->isorec.extent)); 280#endif 281 set_731(default_desc.bootoff, 282 (unsigned int) get_733(de->isorec.extent)); 283 284 /* 285 * now write it to disk 286 */ 287 bootcat = open(de2->whole_name, O_RDWR | O_BINARY); 288 if (bootcat == -1) 289 { 290 fprintf(stderr,"Error opening boot catalog for update.\n"); 291 perror(""); 292 exit(1); 293 } 294 295 /* 296 * write out 297 */ 298 write(bootcat, &valid_desc, 32); 299 write(bootcat, &default_desc, 32); 300 close(bootcat); 301} /* get_torito_desc(... */ 302 303/* 304 * Function to write the EVD for the disc. 305 */ 306static int FDECL1(tvd_write, FILE *, outfile) 307{ 308 /* 309 * Next we write out the boot volume descriptor for the disc 310 */ 311 get_torito_desc(&gboot_desc); 312 xfwrite(&gboot_desc, 1, 2048, outfile); 313 last_extent_written ++; 314 return 0; 315} 316 317struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write}; 318