1 /* @(#)eltorito.c 1.52 15/11/23 joerg */
2 #include <schily/mconfig.h>
4 static UConst
char sccsid
[] =
5 "@(#)eltorito.c 1.52 15/11/23 joerg";
9 * Program eltorito.c - Handle El Torito specific extensions to iso9660.
12 * Written by Michael Fulbright <msf@redhat.com> (1996).
14 * Copyright 1996 RedHat Software, Incorporated
15 * Copyright (c) 1999-2015 J. Schilling
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2, or (at your option)
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 #include <schily/fcntl.h>
34 #include <schily/utypes.h>
35 #include <schily/intcvt.h>
39 #include <schily/schily.h>
42 #define MIN(a, b) (((a) < (b))? (a): (b))
44 EXPORT
void init_boot_catalog
__PR((const char *path
));
45 EXPORT
void insert_boot_cat
__PR((void));
46 LOCAL
void get_torito_desc
__PR((struct eltorito_boot_descriptor
*boot_desc
));
47 LOCAL
void fill_boot_shdr
__PR((struct eltorito_sectionheader_entry
*boot_shdr_entry
,
49 LOCAL
void fill_boot_desc
__PR((struct eltorito_defaultboot_entry
*boot_desc_entry
,
50 struct eltorito_boot_entry_info
*boot_entry
));
51 EXPORT
void get_boot_entry
__PR((void));
52 EXPORT
int new_boot_entry
__PR((void));
53 EXPORT
void ex_boot_enoent
__PR((char *msg
, char *pname
));
54 LOCAL
int tvd_write
__PR((FILE *outfile
));
57 LOCAL
struct eltorito_validation_entry valid_desc
;
58 LOCAL
struct eltorito_boot_descriptor gboot_desc
;
59 LOCAL
struct disk_master_boot_record disk_mbr
;
60 LOCAL
unsigned int bcat_de_flags
;
61 LOCAL
char *bootcat_path
; /* name of bootcatalog */
64 * Make sure any existing boot catalog is excluded
67 init_boot_catalog(path
)
71 struct eltorito_boot_entry_info
*cbe
;
73 for (cbe
= first_boot_entry
;
78 if (cbe
->boot_image
== NULL
)
79 comerrno(EX_BAD
, _("Missing boot image name, use -eltorito-boot option.\n"));
80 p
= (char *)e_malloc(strlen(cbe
->boot_image
) + strlen(path
) + 2);
82 if (p
[strlen(p
) - 1] != '/') {
85 strcat(p
, cbe
->boot_image
);
86 add_sort_match(p
, sort_matches(p
, 1));
90 bootcat_path
= (char *)e_malloc(strlen(boot_catalog
) + strlen(path
) + 2);
91 strcpy(bootcat_path
, path
);
92 if (bootcat_path
[strlen(bootcat_path
) - 1] != '/') {
93 strcat(bootcat_path
, "/");
95 strcat(bootcat_path
, boot_catalog
);
98 * we are going to create a virtual catalog file
99 * - so make sure any existing is excluded
101 add_match(bootcat_path
);
103 /* flag the file as a memory file */
104 bcat_de_flags
= MEMORY_FILE
;
106 /* find out if we want to "hide" this file */
107 if (i_matches(boot_catalog
) || i_matches(bootcat_path
))
108 bcat_de_flags
|= INHIBIT_ISO9660_ENTRY
;
110 if (j_matches(boot_catalog
) || j_matches(bootcat_path
))
111 bcat_de_flags
|= INHIBIT_JOLIET_ENTRY
;
113 if (u_matches(boot_catalog
) || u_matches(bootcat_path
))
114 bcat_de_flags
|= INHIBIT_UDF_ENTRY
;
116 } /* init_boot_catalog(... */
119 * Create a boot catalog file in memory - mkisofs 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
= e_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
);
154 ex_boot_enoent(_("catalog directory"), p1
);
159 /* get the basename (p3) of the directory */
160 if ((p3
= strrchr(p1
, '/')) != NULL
)
165 /* find the correct sub-directory entry */
166 for (dir
= de
->filedir
->subdir
; dir
; dir
= dir
->next
)
167 if (strcmp(dir
->de_name
, p3
) == 0)
171 ex_boot_enoent(_("catalog directory"), p3
);
175 /* boot.cat is in the root directory */
181 * make a directory entry in memory (using the same set up as for table
184 s_entry
= (struct directory_entry
*)
185 e_malloc(sizeof (struct directory_entry
));
186 memset(s_entry
, 0, sizeof (struct directory_entry
));
187 s_entry
->next
= this_dir
->contents
;
188 this_dir
->contents
= s_entry
;
191 /* inherit any sort weight from parent directory */
192 s_entry
->sort
= this_dir
->sort
;
195 /* see if this entry should have a new weighting */
197 s_entry
->sort
= sort_matches(bootcat_path
, s_entry
->sort
);
201 s_entry
->isorec
.flags
[0] = ISO_FILE
;
202 s_entry
->priority
= 32768;
203 iso9660_date(s_entry
->isorec
.date
, fstatbuf
.st_mtime
);
204 s_entry
->inode
= TABLE_INODE
;
205 s_entry
->dev
= (dev_t
)UNCACHED_DEVICE
;
206 set_723(s_entry
->isorec
.volume_sequence_number
,
207 volume_sequence_number
);
208 set_733((char *)s_entry
->isorec
.size
, SECTOR_SIZE
);
209 s_entry
->size
= SECTOR_SIZE
;
210 s_entry
->filedir
= this_dir
;
211 s_entry
->name
= e_strdup(p2
);
212 iso9660_file_length(p2
, s_entry
, 0);
214 /* flag file as necessary */
215 s_entry
->de_flags
= bcat_de_flags
;
217 if ((use_XA
|| use_RockRidge
) &&
218 !(bcat_de_flags
& INHIBIT_ISO9660_ENTRY
)) {
219 fstatbuf
.st_mode
= 0444 | S_IFREG
;
220 fstatbuf
.st_nlink
= 1;
221 generate_xa_rr_attributes("",
223 &fstatbuf
, &fstatbuf
, 0);
226 * memory files are stored at s_entry->table
227 * - but this is also used for each s_entry to generate
228 * TRANS.TBL entries. So if we are generating tables,
229 * store the TRANS.TBL data here for the moment
231 if (generate_tables
&& !(bcat_de_flags
& INHIBIT_ISO9660_ENTRY
)) {
232 sprintf(buffer
, "F\t%s\n", s_entry
->name
);
234 /* copy the TRANS.TBL entry info and clear the buffer */
235 s_entry
->table
= e_strdup(buffer
);
236 memset(buffer
, 0, SECTOR_SIZE
);
239 * store the (empty) file data in the
240 * unused s_entry->whole_name element for the time being
241 * - this will be transferred to s_entry->table after any
242 * TRANS.TBL processing later
244 s_entry
->whole_name
= buffer
;
246 /* store the (empty) file data in the s_entry->table element */
247 s_entry
->table
= buffer
;
248 s_entry
->whole_name
= NULL
;
253 get_torito_desc(boot_desc
)
254 struct eltorito_boot_descriptor
*boot_desc
;
257 unsigned char *checksum_ptr
;
258 struct directory_entry
*de2
; /* Boot catalog */
263 struct eltorito_defaultboot_entry boot_desc_record
;
264 struct eltorito_sectionheader_entry boot_shdr_record
;
266 struct eltorito_section_entry boot_section_record
;
268 struct eltorito_sectionheader_entry
*last_section_header
= 0;
270 memset(boot_desc
, 0, sizeof (*boot_desc
));
271 boot_desc
->type
[0] = 0;
272 strncpy(boot_desc
->id
, ISO_STANDARD_ID
, sizeof (boot_desc
->id
));
273 boot_desc
->version
[0] = 1;
275 memcpy(boot_desc
->system_id
, EL_TORITO_ID
, sizeof (EL_TORITO_ID
));
278 * search from root of iso fs to find boot catalog
279 * - we already know where the boot catalog is
280 * - we created it above - but lets search for it anyway
281 * - good sanity check!
283 de2
= search_tree_file(root
, boot_catalog
);
284 if (!de2
|| !(de2
->de_flags
& MEMORY_FILE
)) {
285 ex_boot_enoent(_("catalog"), boot_catalog
);
288 set_731(boot_desc
->bootcat_ptr
,
289 (unsigned int) get_733(de2
->isorec
.extent
));
292 * If the platform id for the first (default) boot entry has not been
293 * explicitly set, we default to EL_TORITO_ARCH_x86
295 if ((first_boot_entry
->type
& ELTORITO_BOOT_ID
) == 0) {
296 first_boot_entry
->boot_platform
= EL_TORITO_ARCH_x86
;
298 arch
= first_boot_entry
->boot_platform
;
301 * we have the boot image, so write boot catalog information
302 * Next we write out the primary descriptor for the disc
304 memset(&valid_desc
, 0, sizeof (valid_desc
));
305 valid_desc
.headerid
[0] = 1;
306 valid_desc
.arch
[0] = arch
; /* Platform id for the default boot */
309 * we'll shove start of publisher id into id field,
310 * may get truncated but who really reads this stuff!
313 memcpy_max(valid_desc
.id
, publisher
,
314 MIN(23, strlen(publisher
)));
316 valid_desc
.key1
[0] = (char)0x55;
317 valid_desc
.key2
[0] = (char)0xAA;
319 /* compute the checksum */
321 checksum_ptr
= (unsigned char *) &valid_desc
;
322 /* Set checksum to 0 before computing checksum */
323 set_721(valid_desc
.cksum
, 0);
324 for (i
= 0; i
< (int)sizeof (valid_desc
); i
+= 2) {
325 checksum
+= (unsigned int) checksum_ptr
[i
];
326 checksum
+= ((unsigned int) checksum_ptr
[i
+ 1]) * 256;
329 /* now find out the real checksum */
330 checksum
= -checksum
;
331 set_721(valid_desc
.cksum
, (unsigned int) checksum
);
333 /* now write it to the virtual boot catalog */
334 memcpy(de2
->table
, &valid_desc
, 32);
336 for (current_boot_entry
= first_boot_entry
, offset
= sizeof (valid_desc
);
337 current_boot_entry
!= NULL
;
338 current_boot_entry
= current_boot_entry
->next
,
339 offset
+= sizeof (boot_desc_record
)) {
342 if (current_boot_entry
->type
& ELTORITO_BOOT_ID
)
343 newarch
= current_boot_entry
->boot_platform
;
345 current_boot_entry
->boot_platform
= arch
;
348 * El Torito has no such limitation but we currently have...
350 if (offset
>= (SECTOR_SIZE
- sizeof (boot_desc_record
))) {
352 _("Too many El Torito boot entries\n"));
354 if (current_boot_entry
== first_boot_entry
) {
357 } else if ((current_boot_entry
== first_boot_entry
->next
) ||
359 (current_boot_entry
->type
& ELTORITO_SECTION_HEADER
)) {
360 if (last_section_header
)
361 set_721(&last_section_header
->entry_count
, nentries
);
363 last_section_header
= (struct eltorito_sectionheader_entry
*)
364 (de2
->table
+ offset
);
365 fill_boot_shdr(&boot_shdr_record
, newarch
);
366 memcpy(de2
->table
+ offset
, &boot_shdr_record
,
367 sizeof (boot_shdr_record
));
368 offset
+= sizeof (boot_desc_record
);
370 nentries
++; /* Add entry to this section header */
373 * This works because a section entry has the same essential
374 * layout as a default entry (and we do not populate the
375 * selection criteria fields).
377 fill_boot_desc(&boot_desc_record
, current_boot_entry
);
378 memcpy(de2
->table
+ offset
, &boot_desc_record
,
379 sizeof (boot_desc_record
));
382 if (last_section_header
) {
383 set_721(&last_section_header
->entry_count
, nentries
);
384 last_section_header
->header_id
[0] = EL_TORITO_SHDR_ID_LAST_SHDR
;
387 } /* get_torito_desc(... */
390 fill_boot_shdr(boot_shdr_entry
, arch
)
391 struct eltorito_sectionheader_entry
*boot_shdr_entry
;
394 memset(boot_shdr_entry
, 0, sizeof (struct eltorito_sectionheader_entry
));
395 boot_shdr_entry
->header_id
[0] = EL_TORITO_SHDR_ID_SHDR
;
396 boot_shdr_entry
->platform_id
[0] = arch
;
400 fill_boot_desc(boot_desc_entry
, boot_entry
)
401 struct eltorito_defaultboot_entry
*boot_desc_entry
;
402 struct eltorito_boot_entry_info
*boot_entry
;
404 struct directory_entry
*de
; /* Boot file */
410 if (!boot_desc_entry
|| !boot_entry
)
413 /* now adjust boot catalog lets find boot image first */
414 de
= search_tree_file(root
, boot_entry
->boot_image
);
416 ex_boot_enoent(_("image"), boot_entry
->boot_image
);
419 /* now make the initial/default entry for boot catalog */
420 memset(boot_desc_entry
, 0, sizeof (*boot_desc_entry
));
421 boot_desc_entry
->boot_id
[0] = (char)boot_entry
->not_bootable
?
422 EL_TORITO_NOT_BOOTABLE
: EL_TORITO_BOOTABLE
;
424 /* use default BIOS loadpnt */
425 set_721(boot_desc_entry
->loadseg
, boot_entry
->load_addr
);
428 * figure out size of boot image in 512-byte sectors.
429 * However, round up to the nearest integral CD (2048-byte) sector.
430 * This is only used for no-emulation booting.
432 nsectors
= boot_entry
->load_size
? boot_entry
->load_size
:
433 ISO_BLOCKS(de
->size
) * (SECTOR_SIZE
/512);
437 _("Size of boot image is %d sectors -> "), nsectors
);
440 if (boot_entry
->hard_disk_boot
) {
441 /* sanity test hard disk boot image */
442 boot_desc_entry
->boot_media
[0] = EL_TORITO_MEDIA_HD
;
444 fprintf(stderr
, _("Emulating a hard disk\n"));
447 bootmbr
= open(de
->whole_name
, O_RDONLY
| O_BINARY
);
449 comerr(_("Error opening boot image '%s' for read.\n"),
452 if (read(bootmbr
, &disk_mbr
, sizeof (disk_mbr
)) !=
454 comerr(_("Error reading MBR from boot image '%s'.\n"),
458 if (la_to_u_2_byte(disk_mbr
.magic
) != MBR_MAGIC
) {
460 _("Warning: boot image '%s' MBR is not a boot sector.\n"),
463 /* find partition type */
464 boot_desc_entry
->sys_type
[0] = PARTITION_UNUSED
;
465 for (i
= 0; i
< PARTITION_COUNT
; ++i
) {
470 la_to_u_2_byte(disk_mbr
.partition
[i
].s_cyl_sec
);
472 la_to_u_2_byte(disk_mbr
.partition
[i
].e_cyl_sec
);
474 if (disk_mbr
.partition
[i
].type
!= PARTITION_UNUSED
) {
475 if (boot_desc_entry
->sys_type
[0] !=
478 _("Boot image '%s' has multiple partitions.\n"),
481 boot_desc_entry
->sys_type
[0] =
482 disk_mbr
.partition
[i
].type
;
484 /* a few simple sanity warnings */
485 if (!boot_entry
->not_bootable
&&
486 disk_mbr
.partition
[i
].status
!=
489 _("Warning: partition not marked active.\n"));
491 if (MBR_CYLINDER(s_cyl_sec
) != 0 ||
492 disk_mbr
.partition
[i
].s_head
!= 1 ||
493 MBR_SECTOR(s_cyl_sec
!= 1)) {
495 _("Warning: partition does not start at 0/1/1.\n"));
497 geosec
= (MBR_CYLINDER(e_cyl_sec
) + 1) *
498 (disk_mbr
.partition
[i
].e_head
+ 1) *
499 MBR_SECTOR(e_cyl_sec
);
500 if (geosec
!= nsectors
) {
502 _("Warning: image size does not match geometry (%d)\n"),
506 fprintf(stderr
, "Partition start %u/%u/%u\n",
507 MBR_CYLINDER(s_cyl_sec
),
508 disk_mbr
.partition
[i
].s_head
,
509 MBR_SECTOR(s_cyl_sec
));
510 fprintf(stderr
, "Partition end %u/%u/%u\n",
511 MBR_CYLINDER(e_cyl_sec
),
512 disk_mbr
.partition
[i
].e_head
,
513 MBR_SECTOR(e_cyl_sec
));
517 if (boot_desc_entry
->sys_type
[0] == PARTITION_UNUSED
) {
519 _("Boot image '%s' has no partitions.\n"),
523 fprintf(stderr
, "Partition type %u\n",
524 boot_desc_entry
->sys_type
[0]);
526 /* load single boot sector, in this case the MBR */
529 } else if (boot_entry
->no_emul_boot
) {
531 * no emulation is a simple image boot of all the sectors
534 boot_desc_entry
->boot_media
[0] = EL_TORITO_MEDIA_NOEMUL
;
536 fprintf(stderr
, _("No emulation\n"));
539 /* choose size of emulated floppy based on boot image size */
540 if (nsectors
== 2880) {
541 boot_desc_entry
->boot_media
[0] = EL_TORITO_MEDIA_144FLOP
;
543 fprintf(stderr
, _("Emulating a 1440 kB floppy\n"));
545 } else if (nsectors
== 5760) {
546 boot_desc_entry
->boot_media
[0] = EL_TORITO_MEDIA_288FLOP
;
548 fprintf(stderr
, _("Emulating a 2880 kB floppy\n"));
550 } else if (nsectors
== 2400) {
551 boot_desc_entry
->boot_media
[0] = EL_TORITO_MEDIA_12FLOP
;
553 fprintf(stderr
, _("Emulating a 1200 kB floppy\n"));
557 _("Error - boot image '%s' has not an allowable size.\n"),
561 /* load single boot sector for floppies */
565 /* fill in boot image details */
567 fprintf(stderr
, "Boot %u sectors\n", nsectors
);
568 fprintf(stderr
, "Extent of boot images is %d\n",
569 get_733(de
->isorec
.extent
));
571 set_721(boot_desc_entry
->nsect
, (unsigned int) nsectors
);
572 set_731(boot_desc_entry
->bootoff
,
573 (unsigned int) get_733(de
->isorec
.extent
));
576 /* If the user has asked for it, patch the boot image */
577 if (boot_entry
->boot_info_table
) {
579 unsigned int bi_checksum
;
580 unsigned int total_len
;
581 static char csum_buffer
[SECTOR_SIZE
];
583 struct mkisofs_boot_info bi_table
;
585 bootimage
= open(de
->whole_name
, O_RDWR
| O_BINARY
);
586 if (bootimage
== -1) {
588 _("Error opening boot image file '%s' for update.\n"),
591 /* Compute checksum of boot image, sans 64 bytes */
594 while ((len
= read(bootimage
, csum_buffer
, SECTOR_SIZE
)) > 0) {
597 _("Odd alignment at non-end-of-file in boot image '%s'.\n"),
601 memset(csum_buffer
, 0, 64 - total_len
);
602 if (len
< SECTOR_SIZE
)
603 memset(csum_buffer
+ len
, 0, SECTOR_SIZE
-len
);
604 for (i
= 0; i
< SECTOR_SIZE
; i
+= 4)
605 bi_checksum
+= get_731(&csum_buffer
[i
]);
609 if (total_len
!= de
->size
) {
611 _("Boot image file '%s' changed underneath us!\n"),
614 /* End of file, set position to byte 8 */
615 lseek(bootimage
, (off_t
)8, SEEK_SET
);
616 memset(&bi_table
, 0, sizeof (bi_table
));
617 /* Is it always safe to assume PVD is at session_start+16? */
618 set_731(bi_table
.bi_pvd
, session_start
+ 16);
619 set_731(bi_table
.bi_file
, de
->starting_block
);
620 set_731(bi_table
.bi_length
, de
->size
);
621 set_731(bi_table
.bi_csum
, bi_checksum
);
623 write(bootimage
, &bi_table
, sizeof (bi_table
));
626 } /* fill_boot_desc(... */
631 if (current_boot_entry
)
634 current_boot_entry
= (struct eltorito_boot_entry_info
*)
635 e_malloc(sizeof (struct eltorito_boot_entry_info
));
636 memset(current_boot_entry
, 0, sizeof (*current_boot_entry
));
638 if (!first_boot_entry
) {
639 first_boot_entry
= current_boot_entry
;
640 last_boot_entry
= current_boot_entry
;
641 current_boot_entry
->boot_platform
= EL_TORITO_ARCH_x86
;
643 current_boot_entry
->boot_platform
= last_boot_entry
->boot_platform
;
644 last_boot_entry
->next
= current_boot_entry
;
645 last_boot_entry
= current_boot_entry
;
652 current_boot_entry
= NULL
;
657 * Exit with a boot no entry message.
660 ex_boot_enoent(msg
, pname
)
664 comerrno(EX_BAD
, _("Uh oh, I cant find the boot %s '%s' inside the target tree.\n"), msg
, pname
);
669 * Function to write the EVD for the disc.
675 /* check the boot image is not NULL */
677 comerrno(EX_BAD
, _("No boot image specified.\n"));
679 /* Next we write out the boot volume descriptor for the disc */
680 get_torito_desc(&gboot_desc
);
681 xfwrite(&gboot_desc
, SECTOR_SIZE
, 1, outfile
, 0, FALSE
);
682 last_extent_written
++;
686 struct output_fragment torito_desc
= {NULL
, oneblock_size
, NULL
, tvd_write
, "Eltorito Volume Descriptor"};