2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* @(#)eltorito.c 1.33 05/02/27 joerg */
15 * Program eltorito.c - Handle El Torito specific extensions to iso9660.
18 * Written by Michael Fulbright <msf@redhat.com> (1996).
20 * Copyright 1996 RedHat Software, Incorporated
21 * Copyright (c) 1999-2004 J. Schilling
23 * This program is free software; you can redistribute it and/or modify
24 * it under the terms of the GNU General Public License as published by
25 * the Free Software Foundation; either version 2, or (at your option)
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
39 #include "genisoimage.h"
49 #define MIN(a, b) (((a) < (b))? (a): (b))
51 static struct eltorito_validation_entry valid_desc;
52 static struct eltorito_boot_descriptor gboot_desc;
53 static struct disk_master_boot_record disk_mbr;
54 static unsigned int bcat_de_flags;
56 void init_boot_catalog(const char *path);
57 void insert_boot_cat(void);
58 static void get_torito_desc(struct eltorito_boot_descriptor *boot_desc);
59 static void fill_boot_desc(struct eltorito_defaultboot_entry *boot_desc_entry,
60 struct eltorito_boot_entry_info *boot_entry);
61 void get_boot_entry(void);
62 void new_boot_entry(void);
63 static int tvd_write(FILE *outfile);
66 static char *bootcat_path; /* filename of boot catalog */
68 * Make sure any existing boot catalog is excluded
71 init_boot_catalog(const char *path)
74 struct eltorito_boot_entry_info * cbe;
76 for (cbe = first_boot_entry;
81 if (cbe->boot_image == NULL)
82 comerrno(EX_BAD, "Missing boot image name, use -eltorito-boot option.\n");
83 p = (char *) e_malloc(strlen(cbe->boot_image) + strlen(path) + 2);
85 if (p[strlen(p) - 1] != '/') {
88 strcat(p, cbe->boot_image);
89 add_sort_match(p, sort_matches(p, 1));
93 bootcat_path = (char *) e_malloc(strlen(boot_catalog) + strlen(path) + 2);
94 strcpy(bootcat_path, path);
95 if (bootcat_path[strlen(bootcat_path) - 1] != '/') {
96 strcat(bootcat_path, "/");
98 strcat(bootcat_path, boot_catalog);
101 * we are going to create a virtual catalog file
102 * - so make sure any existing is excluded
104 add_match(bootcat_path);
106 /* flag the file as a memory file */
107 bcat_de_flags = MEMORY_FILE;
109 /* find out if we want to "hide" this file */
110 if (i_matches(boot_catalog) || i_matches(bootcat_path))
111 bcat_de_flags |= INHIBIT_ISO9660_ENTRY;
113 if (j_matches(boot_catalog) || j_matches(bootcat_path))
114 bcat_de_flags |= INHIBIT_JOLIET_ENTRY;
116 }/* init_boot_catalog(... */
119 * Create a boot catalog file in memory - genisoimage already uses this type of
120 * file for the TRANS.TBL files. Therefore the boot catalog is set up in
126 struct directory_entry *de;
127 struct directory_entry *s_entry;
131 struct directory *this_dir;
132 struct directory *dir;
137 buffer = (char *) e_malloc(SECTOR_SIZE);
138 memset(buffer, 0, SECTOR_SIZE);
141 * try to find the directory that will contain the boot.cat file
142 * - not very neat, but I can't think of a better way
144 p1 = strdup(boot_catalog);
146 /* get dirname (p1) and basename (p2) of boot.cat */
147 if ((p2 = strrchr(p1, '/')) != NULL) {
151 /* find the dirname directory entry */
152 de = search_tree_file(root, p1);
156 "Uh oh, I cant find the boot catalog directory '%s'!\n",
160 "Uh oh, I cant find the boot catalog directory '%s'!\n",
167 /* get the basename (p3) of the directory */
168 if ((p3 = strrchr(p1, '/')) != NULL)
173 /* find the correct sub-directory entry */
174 for (dir = de->filedir->subdir; dir; dir = dir->next)
175 if (!(strcmp(dir->de_name, p3)))
181 "Uh oh, I cant find the boot catalog directory '%s'!\n",
185 "Uh oh, I cant find the boot catalog directory '%s'!\n",
191 /* boot.cat is in the root directory */
197 * make a directory entry in memory (using the same set up as for table
200 s_entry = (struct directory_entry *)
201 e_malloc(sizeof (struct directory_entry));
202 memset(s_entry, 0, sizeof (struct directory_entry));
203 s_entry->next = this_dir->contents;
204 this_dir->contents = s_entry;
207 /* inherit any sort weight from parent directory */
208 s_entry->sort = this_dir->sort;
211 /* see if this entry should have a new weighting */
213 s_entry->sort = sort_matches(bootcat_path, s_entry->sort);
217 s_entry->isorec.flags[0] = ISO_FILE;
218 s_entry->priority = 32768;
219 iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime);
220 s_entry->inode = TABLE_INODE;
221 s_entry->dev = (dev_t) UNCACHED_DEVICE;
222 set_723(s_entry->isorec.volume_sequence_number,
223 volume_sequence_number);
224 set_733((char *) s_entry->isorec.size, SECTOR_SIZE);
225 s_entry->size = SECTOR_SIZE;
226 s_entry->filedir = this_dir;
227 s_entry->name = strdup(p2);
228 iso9660_file_length(p2, s_entry, 0);
230 /* flag file as necessary */
233 * If the current directory is hidden, then hide this entry
235 if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY)
236 bcat_de_flags |= INHIBIT_ISO9660_ENTRY;
237 if (this_dir->dir_flags & INHIBIT_JOLIET_ENTRY)
238 bcat_de_flags |= INHIBIT_JOLIET_ENTRY;
240 s_entry->de_flags = bcat_de_flags;
242 if ((use_XA || use_RockRidge) &&
243 !(bcat_de_flags & INHIBIT_ISO9660_ENTRY)) {
244 fstatbuf.st_mode = 0444 | S_IFREG;
245 fstatbuf.st_nlink = 1;
246 generate_xa_rr_attributes("",
248 &fstatbuf, &fstatbuf, 0);
251 * memory files are stored at s_entry->table
252 * - but this is also used for each s_entry to generate
253 * TRANS.TBL entries. So if we are generating tables,
254 * store the TRANS.TBL data here for the moment
256 if (generate_tables && !(bcat_de_flags & INHIBIT_ISO9660_ENTRY)) {
257 sprintf(buffer, "F\t%s\n", s_entry->name);
259 /* copy the TRANS.TBL entry info and clear the buffer */
260 s_entry->table = strdup(buffer);
261 memset(buffer, 0, SECTOR_SIZE);
264 * store the (empty) file data in the
265 * unused s_entry->whole_name element for the time being
266 * - this will be transferred to s_entry->table after any
267 * TRANS.TBL processing later
269 s_entry->whole_name = buffer;
271 /* store the (empty) file data in the s_entry->table element */
272 s_entry->table = buffer;
273 s_entry->whole_name = NULL;
278 get_torito_desc(struct eltorito_boot_descriptor *boot_desc)
281 unsigned char *checksum_ptr;
282 struct directory_entry *de2; /* Boot catalog */
285 struct eltorito_defaultboot_entry boot_desc_record;
287 memset(boot_desc, 0, sizeof (*boot_desc));
288 boot_desc->type[0] = 0;
289 memcpy(boot_desc->id, ISO_STANDARD_ID, sizeof (ISO_STANDARD_ID));
290 boot_desc->version[0] = 1;
292 memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof (EL_TORITO_ID));
295 * search from root of iso fs to find boot catalog
296 * - we already know where the boot catalog is
297 * - we created it above - but lets search for it anyway
298 * - good sanity check!
300 de2 = search_tree_file(root, boot_catalog);
301 if (!de2 || !(de2->de_flags & MEMORY_FILE)) {
303 comerrno(EX_BAD, "Uh oh, I cant find the boot catalog '%s'!\n",
306 fprintf(stderr, "Uh oh, I cant find the boot catalog '%s'!\n",
311 set_731(boot_desc->bootcat_ptr,
312 (unsigned int) get_733(de2->isorec.extent));
315 * we have the boot image, so write boot catalog information
316 * Next we write out the primary descriptor for the disc
318 memset(&valid_desc, 0, sizeof (valid_desc));
319 valid_desc.headerid[0] = 1;
320 valid_desc.arch[0] = EL_TORITO_ARCH_x86;
323 * we'll shove start of publisher id into id field,
324 * may get truncated but who really reads this stuff!
327 memcpy_max(valid_desc.id, publisher,
328 MIN(23, strlen(publisher)));
330 valid_desc.key1[0] = (char) 0x55;
331 valid_desc.key2[0] = (char) 0xAA;
333 /* compute the checksum */
335 checksum_ptr = (unsigned char *) &valid_desc;
336 /* Set checksum to 0 before computing checksum */
337 set_721(valid_desc.cksum, 0);
338 for (i = 0; i < (int)sizeof (valid_desc); i += 2) {
339 checksum += (unsigned int) checksum_ptr[i];
340 checksum += ((unsigned int) checksum_ptr[i + 1]) * 256;
343 /* now find out the real checksum */
344 checksum = -checksum;
345 set_721(valid_desc.cksum, (unsigned int) checksum);
347 /* now write it to the virtual boot catalog */
348 memcpy(de2->table, &valid_desc, 32);
350 for (current_boot_entry = first_boot_entry, offset = sizeof (valid_desc);
351 current_boot_entry != NULL;
352 current_boot_entry = current_boot_entry->next,
353 offset += sizeof (boot_desc_record)) {
355 if (offset >= SECTOR_SIZE) {
358 "Too many El Torito boot entries\n");
361 "Too many El Torito boot entries\n");
365 fill_boot_desc(&boot_desc_record, current_boot_entry);
366 memcpy(de2->table + offset, &boot_desc_record,
367 sizeof (boot_desc_record));
369 }/* get_torito_desc(... */
372 fill_boot_desc(struct eltorito_defaultboot_entry *boot_desc_entry,
373 struct eltorito_boot_entry_info *boot_entry)
375 struct directory_entry *de; /* Boot file */
381 if (!boot_desc_entry || !boot_entry)
384 /* now adjust boot catalog lets find boot image first */
385 de = search_tree_file(root, boot_entry->boot_image);
388 comerrno(EX_BAD, "Uh oh, I cant find the boot image '%s' !\n",
389 boot_entry->boot_image);
391 fprintf(stderr, "Uh oh, I cant find the boot image '%s' !\n",
392 boot_entry->boot_image);
396 /* now make the initial/default entry for boot catalog */
397 memset(boot_desc_entry, 0, sizeof (*boot_desc_entry));
398 boot_desc_entry->boot_id[0] = (char) boot_entry->not_bootable ?
399 EL_TORITO_NOT_BOOTABLE : EL_TORITO_BOOTABLE;
401 /* use default BIOS loadpnt */
402 set_721(boot_desc_entry->loadseg, boot_entry->load_addr);
405 * figure out size of boot image in 512-byte sectors.
406 * However, round up to the nearest integral CD (2048-byte) sector.
407 * This is only used for no-emulation booting.
409 nsectors = boot_entry->load_size ? boot_entry->load_size :
410 ISO_BLOCKS(de->size) * (SECTOR_SIZE/512);
414 "Size of boot image is %d sectors -> ", nsectors);
417 if (boot_entry->hard_disk_boot) {
418 /* sanity test hard disk boot image */
419 boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_HD;
421 fprintf(stderr, "Emulating a hard disk\n");
424 bootmbr = open(de->whole_name, O_RDONLY | O_BINARY);
427 comerr("Error opening boot image '%s' for read.\n",
431 "Error opening boot image '%s' for read.\n",
437 if (read(bootmbr, &disk_mbr, sizeof (disk_mbr)) !=
440 comerr("Error reading MBR from boot image '%s'.\n",
444 "Error reading MBR from boot image '%s'.\n",
450 if (la_to_u_2_byte(disk_mbr.magic) != MBR_MAGIC) {
453 "Warning: boot image '%s' MBR is not a boot sector.\n",
457 "Warning: boot image '%s' MBR is not a boot sector.\n",
461 /* find partition type */
462 boot_desc_entry->sys_type[0] = PARTITION_UNUSED;
463 for (i = 0; i < PARTITION_COUNT; ++i) {
468 la_to_u_2_byte(disk_mbr.partition[i].s_cyl_sec);
470 la_to_u_2_byte(disk_mbr.partition[i].e_cyl_sec);
472 if (disk_mbr.partition[i].type != PARTITION_UNUSED) {
473 if (boot_desc_entry->sys_type[0] !=
477 "Boot image '%s' has multiple partitions.\n",
481 "Boot image '%s' has multiple partitions.\n",
486 boot_desc_entry->sys_type[0] =
487 disk_mbr.partition[i].type;
489 /* a few simple sanity warnings */
490 if (!boot_entry->not_bootable &&
491 disk_mbr.partition[i].status !=
494 "Warning: partition not marked active.\n");
496 if (MBR_CYLINDER(s_cyl_sec) != 0 ||
497 disk_mbr.partition[i].s_head != 1 ||
498 MBR_SECTOR(s_cyl_sec != 1)) {
500 "Warning: partition does not start at 0/1/1.\n");
502 geosec = (MBR_CYLINDER(e_cyl_sec) + 1) *
503 (disk_mbr.partition[i].e_head + 1) *
504 MBR_SECTOR(e_cyl_sec);
505 if (geosec != nsectors) {
507 "Warning: image size does not match geometry (%d)\n",
511 fprintf(stderr, "Partition start %u/%u/%u\n",
512 MBR_CYLINDER(s_cyl_sec),
513 disk_mbr.partition[i].s_head,
514 MBR_SECTOR(s_cyl_sec));
515 fprintf(stderr, "Partition end %u/%u/%u\n",
516 MBR_CYLINDER(e_cyl_sec),
517 disk_mbr.partition[i].e_head,
518 MBR_SECTOR(e_cyl_sec));
522 if (boot_desc_entry->sys_type[0] == PARTITION_UNUSED) {
525 "Boot image '%s' has no partitions.\n",
529 "Boot image '%s' has no partitions.\n",
535 fprintf(stderr, "Partition type %u\n",
536 boot_desc_entry->sys_type[0]);
538 /* load single boot sector, in this case the MBR */
541 } else if (boot_entry->no_emul_boot) {
543 * no emulation is a simple image boot of all the sectors
546 boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_NOEMUL;
548 fprintf(stderr, "No emulation\n");
551 /* choose size of emulated floppy based on boot image size */
552 if (nsectors == 2880) {
553 boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_144FLOP;
555 fprintf(stderr, "Emulating a 1440 kB floppy\n");
557 } else if (nsectors == 5760) {
558 boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_288FLOP;
560 fprintf(stderr, "Emulating a 2880 kB floppy\n");
562 } else if (nsectors == 2400) {
563 boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_12FLOP;
565 fprintf(stderr, "Emulating a 1200 kB floppy\n");
570 "Error - boot image '%s' has not an allowable size.\n",
574 "Error - boot image '%s' has not an allowable size.\n",
580 /* load single boot sector for floppies */
584 /* fill in boot image details */
586 fprintf(stderr, "Boot %u sectors\n", nsectors);
587 fprintf(stderr, "Extent of boot images is %d\n",
588 get_733(de->isorec.extent));
590 set_721(boot_desc_entry->nsect, (unsigned int) nsectors);
591 set_731(boot_desc_entry->bootoff,
592 (unsigned int) get_733(de->isorec.extent));
595 /* If the user has asked for it, patch the boot image */
596 if (boot_entry->boot_info_table) {
598 unsigned int bi_checksum;
599 unsigned int total_len;
600 static char csum_buffer[SECTOR_SIZE];
602 struct genisoimage_boot_info bi_table;
603 bootimage = open(de->whole_name, O_RDWR | O_BINARY);
604 if (bootimage == -1) {
607 "Error opening boot image file '%s' for update.\n",
611 "Error opening boot image file '%s' for update.\n",
617 /* Compute checksum of boot image, sans 64 bytes */
620 while ((len = read(bootimage, csum_buffer, SECTOR_SIZE)) > 0) {
624 "Odd alignment at non-end-of-file in boot image '%s'.\n",
628 "Odd alignment at non-end-of-file in boot image '%s'.\n",
634 memset(csum_buffer, 0, 64 - total_len);
635 if (len < SECTOR_SIZE)
636 memset(csum_buffer + len, 0, SECTOR_SIZE-len);
637 for (i = 0; i < SECTOR_SIZE; i += 4)
638 bi_checksum += get_731(&csum_buffer[i]);
642 if (total_len != de->size) {
645 "Boot image file '%s' changed underneath us!\n",
649 "Boot image file '%s' changed underneath us!\n",
654 /* End of file, set position to byte 8 */
655 lseek(bootimage, (off_t)8, SEEK_SET);
656 memset(&bi_table, 0, sizeof (bi_table));
657 /* Is it always safe to assume PVD is at session_start+16? */
658 set_731(bi_table.bi_pvd, session_start + 16);
659 set_731(bi_table.bi_file, de->starting_block);
660 set_731(bi_table.bi_length, de->size);
661 set_731(bi_table.bi_csum, bi_checksum);
663 write(bootimage, &bi_table, sizeof (bi_table)); /* FIXME: check return value */
666 }/* fill_boot_desc(... */
671 if (current_boot_entry)
674 current_boot_entry = (struct eltorito_boot_entry_info *)
675 e_malloc(sizeof (struct eltorito_boot_entry_info));
676 memset(current_boot_entry, 0, sizeof (*current_boot_entry));
678 if (!first_boot_entry) {
679 first_boot_entry = current_boot_entry;
680 last_boot_entry = current_boot_entry;
682 last_boot_entry->next = current_boot_entry;
683 last_boot_entry = current_boot_entry;
690 current_boot_entry = NULL;
694 * Function to write the EVD for the disc.
697 tvd_write(FILE *outfile)
699 /* check the boot image is not NULL */
702 comerrno(EX_BAD, "No boot image specified.\n");
704 fprintf(stderr, "No boot image specified.\n");
708 /* Next we write out the boot volume descriptor for the disc */
709 get_torito_desc(&gboot_desc);
710 jtwrite(&gboot_desc, SECTOR_SIZE, 1, 0, FALSE);
711 xfwrite(&gboot_desc, SECTOR_SIZE, 1, outfile, 0, FALSE);
712 last_extent_written++;
716 struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write, "Eltorito Volume Descriptor"};