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