1 /*
2  * This file has been modified for the cdrkit suite.
3  *
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).
6  *
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.
10  *
11  */
12 
13 /* @(#)eltorito.c	1.33 05/02/27 joerg */
14 /*
15  * Program eltorito.c - Handle El Torito specific extensions to iso9660.
16  *
17  *
18  *  Written by Michael Fulbright <msf@redhat.com> (1996).
19  *
20  * Copyright 1996 RedHat Software, Incorporated
21  * Copyright (c) 1999-2004 J. Schilling
22  *
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)
26  * any later version.
27  *
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.
32  *
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.
36  */
37 
38 #include <mconfig.h>
39 #include "genisoimage.h"
40 #include <fctldefs.h>
41 #include <utypes.h>
42 #include <intcvt.h>
43 #include "match.h"
44 #include "diskmbr.h"
45 #include "bootinfo.h"
46 #include <schily.h>
47 
48 #undef MIN
49 #define	MIN(a, b) (((a) < (b))? (a): (b))
50 
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;
55 
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);
64 
65 
66 static	char	*bootcat_path;		/* filename of boot catalog */
67 /*
68  * Make sure any existing boot catalog is excluded
69  */
70 void
init_boot_catalog(const char * path)71 init_boot_catalog(const char *path)
72 {
73 #ifdef	SORTING
74 	struct eltorito_boot_entry_info * cbe;
75 
76 	for (cbe = first_boot_entry;
77 	    cbe != NULL;
78 	    cbe = cbe->next) {
79 		char	*p;
80 
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);
84 		strcpy(p, path);
85 		if (p[strlen(p) - 1] != '/') {
86 			strcat(p, "/");
87 		}
88 		strcat(p, cbe->boot_image);
89 		add_sort_match(p, sort_matches(p, 1));
90 		free(p);
91 	}
92 #endif
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, "/");
97 	}
98 	strcat(bootcat_path, boot_catalog);
99 
100 	/*
101 	 * we are going to create a virtual catalog file
102 	 * - so make sure any existing is excluded
103 	 */
104 	add_match(bootcat_path);
105 
106 	/* flag the file as a memory file */
107 	bcat_de_flags = MEMORY_FILE;
108 
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;
112 
113 	if (j_matches(boot_catalog) || j_matches(bootcat_path))
114 		bcat_de_flags |= INHIBIT_JOLIET_ENTRY;
115 
116 }/* init_boot_catalog(... */
117 
118 /*
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
121  * similar way
122  */
123 void
insert_boot_cat()124 insert_boot_cat()
125 {
126 	struct directory_entry	*de;
127 	struct directory_entry	*s_entry;
128 	char			*p1;
129 	char			*p2;
130 	char			*p3;
131 	struct directory	*this_dir;
132 	struct directory	*dir;
133 	char			*buffer;
134 
135 	init_fstatbuf();
136 
137 	buffer = (char *) e_malloc(SECTOR_SIZE);
138 	memset(buffer, 0, SECTOR_SIZE);
139 
140 	/*
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
143 	 */
144 	p1 = strdup(boot_catalog);
145 
146 	/* get dirname (p1) and basename (p2) of boot.cat */
147 	if ((p2 = strrchr(p1, '/')) != NULL) {
148 		*p2 = '\0';
149 		p2++;
150 
151 		/* find the dirname directory entry */
152 		de = search_tree_file(root, p1);
153 		if (!de) {
154 #ifdef	USE_LIBSCHILY
155 			comerrno(EX_BAD,
156 			"Uh oh, I cant find the boot catalog directory '%s'!\n",
157 								p1);
158 #else
159 			fprintf(stderr,
160 			"Uh oh, I cant find the boot catalog directory '%s'!\n",
161 								p1);
162 			exit(1);
163 #endif
164 		}
165 		this_dir = 0;
166 
167 		/* get the basename (p3) of the directory */
168 		if ((p3 = strrchr(p1, '/')) != NULL)
169 			p3++;
170 		else
171 			p3 = p1;
172 
173 		/* find the correct sub-directory entry */
174 		for (dir = de->filedir->subdir; dir; dir = dir->next)
175 			if (!(strcmp(dir->de_name, p3)))
176 				this_dir = dir;
177 
178 		if (this_dir == 0) {
179 #ifdef	USE_LIBSCHILY
180 			comerrno(EX_BAD,
181 			"Uh oh, I cant find the boot catalog directory '%s'!\n",
182 								p3);
183 #else
184 			fprintf(stderr,
185 			"Uh oh, I cant find the boot catalog directory '%s'!\n",
186 								p3);
187 			exit(1);
188 #endif
189 		}
190 	} else {
191 		/* boot.cat is in the root directory */
192 		this_dir = root;
193 		p2 = p1;
194 	}
195 
196 	/*
197 	 * make a directory entry in memory (using the same set up as for table
198 	 * entries
199 	 */
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;
205 
206 #ifdef SORTING
207 	/* inherit any sort weight from parent directory */
208 	s_entry->sort = this_dir->sort;
209 	s_entry->sort += 2;
210 
211 	/* see if this entry should have a new weighting */
212 	if (do_sort) {
213 		s_entry->sort = sort_matches(bootcat_path, s_entry->sort);
214 	}
215 #endif /* SORTING */
216 
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);
229 
230 	/* flag file as necessary */
231 
232 	/*
233 	 * If the current directory is hidden, then hide this entry
234 	 */
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;
239 
240 	s_entry->de_flags = bcat_de_flags;
241 
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("",
247 			p2, s_entry,
248 			&fstatbuf, &fstatbuf, 0);
249 	}
250 	/*
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
255 	 */
256 	if (generate_tables && !(bcat_de_flags & INHIBIT_ISO9660_ENTRY)) {
257 		sprintf(buffer, "F\t%s\n", s_entry->name);
258 
259 		/* copy the TRANS.TBL entry info and clear the buffer */
260 		s_entry->table = strdup(buffer);
261 		memset(buffer, 0, SECTOR_SIZE);
262 
263 		/*
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
268 		 */
269 		s_entry->whole_name = buffer;
270 	} else {
271 		/* store the (empty) file data in the s_entry->table element */
272 		s_entry->table = buffer;
273 		s_entry->whole_name = NULL;
274 	}
275 }
276 
277 static void
get_torito_desc(struct eltorito_boot_descriptor * boot_desc)278 get_torito_desc(struct eltorito_boot_descriptor *boot_desc)
279 {
280 	int			checksum;
281 	unsigned char		*checksum_ptr;
282 	struct directory_entry	*de2;	/* Boot catalog */
283 	int			i;
284 	int			offset;
285 	struct eltorito_defaultboot_entry boot_desc_record;
286 
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;
291 
292 	memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof (EL_TORITO_ID));
293 
294 	/*
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!
299 	 */
300 	de2 = search_tree_file(root, boot_catalog);
301 	if (!de2 || !(de2->de_flags & MEMORY_FILE)) {
302 #ifdef	USE_LIBSCHILY
303 		comerrno(EX_BAD, "Uh oh, I cant find the boot catalog '%s'!\n",
304 							boot_catalog);
305 #else
306 		fprintf(stderr, "Uh oh, I cant find the boot catalog '%s'!\n",
307 							boot_catalog);
308 		exit(1);
309 #endif
310 	}
311 	set_731(boot_desc->bootcat_ptr,
312 		(unsigned int) get_733(de2->isorec.extent));
313 
314 	/*
315 	 * we have the boot image, so write boot catalog information
316 	 * Next we write out the primary descriptor for the disc
317 	 */
318 	memset(&valid_desc, 0, sizeof (valid_desc));
319 	valid_desc.headerid[0] = 1;
320 	valid_desc.arch[0] = EL_TORITO_ARCH_x86;
321 
322 	/*
323 	 * we'll shove start of publisher id into id field,
324 	 * may get truncated but who really reads this stuff!
325 	 */
326 	if (publisher)
327 		memcpy_max(valid_desc.id, publisher,
328 						MIN(23, strlen(publisher)));
329 
330 	valid_desc.key1[0] = (char) 0x55;
331 	valid_desc.key2[0] = (char) 0xAA;
332 
333 	/* compute the checksum */
334 	checksum = 0;
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;
341 	}
342 
343 	/* now find out the real checksum */
344 	checksum = -checksum;
345 	set_721(valid_desc.cksum, (unsigned int) checksum);
346 
347 	/* now write it to the virtual boot catalog */
348 	memcpy(de2->table, &valid_desc, 32);
349 
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)) {
354 
355 		if (offset >= SECTOR_SIZE) {
356 #ifdef	USE_LIBSCHILY
357 			comerrno(EX_BAD,
358 			"Too many El Torito boot entries\n");
359 #else
360 			fprintf(stderr,
361 			"Too many El Torito boot entries\n");
362 			exit(1);
363 #endif
364 		}
365 		fill_boot_desc(&boot_desc_record, current_boot_entry);
366 		memcpy(de2->table + offset, &boot_desc_record,
367 					sizeof (boot_desc_record));
368 	}
369 }/* get_torito_desc(... */
370 
371 static void
fill_boot_desc(struct eltorito_defaultboot_entry * boot_desc_entry,struct eltorito_boot_entry_info * boot_entry)372 fill_boot_desc(struct eltorito_defaultboot_entry *boot_desc_entry,
373 					struct eltorito_boot_entry_info *boot_entry)
374 {
375 	struct directory_entry	*de;	/* Boot file */
376 	int			bootmbr;
377 	int			i;
378 	int			nsectors;
379 	int			geosec;
380 
381 	if (!boot_desc_entry || !boot_entry)
382 		return;
383 
384 	/* now adjust boot catalog lets find boot image first */
385 	de = search_tree_file(root, boot_entry->boot_image);
386 	if (!de) {
387 #ifdef	USE_LIBSCHILY
388 		comerrno(EX_BAD, "Uh oh, I cant find the boot image '%s' !\n",
389 							boot_entry->boot_image);
390 #else
391 		fprintf(stderr, "Uh oh, I cant find the boot image '%s' !\n",
392 							boot_entry->boot_image);
393 		exit(1);
394 #endif
395 	}
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;
400 
401 	/* use default BIOS loadpnt */
402 	set_721(boot_desc_entry->loadseg, boot_entry->load_addr);
403 
404 	/*
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.
408 	 */
409 	nsectors = boot_entry->load_size ? boot_entry->load_size :
410 				ISO_BLOCKS(de->size) * (SECTOR_SIZE/512);
411 
412 	if (verbose > 0) {
413 		fprintf(stderr,
414 			"Size of boot image is %d sectors -> ", nsectors);
415 	}
416 
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;
420 		if (verbose > 0)
421 			fprintf(stderr, "Emulating a hard disk\n");
422 
423 		/* read MBR */
424 		bootmbr = open(de->whole_name, O_RDONLY | O_BINARY);
425 		if (bootmbr == -1) {
426 #ifdef	USE_LIBSCHILY
427 			comerr("Error opening boot image '%s' for read.\n",
428 							de->whole_name);
429 #else
430 			fprintf(stderr,
431 				"Error opening boot image '%s' for read.\n",
432 							de->whole_name);
433 			perror("");
434 			exit(1);
435 #endif
436 		}
437 		if (read(bootmbr, &disk_mbr, sizeof (disk_mbr)) !=
438 							sizeof (disk_mbr)) {
439 #ifdef	USE_LIBSCHILY
440 			comerr("Error reading MBR from boot image '%s'.\n",
441 							de->whole_name);
442 #else
443 			fprintf(stderr,
444 				"Error reading MBR from boot image '%s'.\n",
445 							de->whole_name);
446 			exit(1);
447 #endif
448 		}
449 		close(bootmbr);
450 		if (la_to_u_2_byte(disk_mbr.magic) != MBR_MAGIC) {
451 #ifdef	USE_LIBSCHILY
452 			errmsgno(EX_BAD,
453 			"Warning: boot image '%s' MBR is not a boot sector.\n",
454 							de->whole_name);
455 #else
456 			fprintf(stderr,
457 				"Warning: boot image '%s' MBR is not a boot sector.\n",
458 							de->whole_name);
459 #endif
460 		}
461 		/* find partition type */
462 		boot_desc_entry->sys_type[0] = PARTITION_UNUSED;
463 		for (i = 0; i < PARTITION_COUNT; ++i) {
464 			int		s_cyl_sec;
465 			int		e_cyl_sec;
466 
467 			s_cyl_sec =
468 			la_to_u_2_byte(disk_mbr.partition[i].s_cyl_sec);
469 			e_cyl_sec =
470 			la_to_u_2_byte(disk_mbr.partition[i].e_cyl_sec);
471 
472 			if (disk_mbr.partition[i].type != PARTITION_UNUSED) {
473 				if (boot_desc_entry->sys_type[0] !=
474 							PARTITION_UNUSED) {
475 #ifdef	USE_LIBSCHILY
476 					comerrno(EX_BAD,
477 					"Boot image '%s' has multiple partitions.\n",
478 							de->whole_name);
479 #else
480 					fprintf(stderr,
481 					"Boot image '%s' has multiple partitions.\n",
482 							de->whole_name);
483 					exit(1);
484 #endif
485 				}
486 				boot_desc_entry->sys_type[0] =
487 						disk_mbr.partition[i].type;
488 
489 				/* a few simple sanity warnings */
490 				if (!boot_entry->not_bootable &&
491 				    disk_mbr.partition[i].status !=
492 							PARTITION_ACTIVE) {
493 					fprintf(stderr,
494 					"Warning: partition not marked active.\n");
495 				}
496 				if (MBR_CYLINDER(s_cyl_sec) != 0 ||
497 					disk_mbr.partition[i].s_head != 1 ||
498 					MBR_SECTOR(s_cyl_sec != 1)) {
499 					fprintf(stderr,
500 					"Warning: partition does not start at 0/1/1.\n");
501 				}
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) {
506 					fprintf(stderr,
507 					"Warning: image size does not match geometry (%d)\n",
508 						geosec);
509 				}
510 #ifdef DEBUG_TORITO
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));
519 #endif
520 			}
521 		}
522 		if (boot_desc_entry->sys_type[0] == PARTITION_UNUSED) {
523 #ifdef	USE_LIBSCHILY
524 			comerrno(EX_BAD,
525 					"Boot image '%s' has no partitions.\n",
526 							de->whole_name);
527 #else
528 			fprintf(stderr,
529 					"Boot image '%s' has no partitions.\n",
530 							de->whole_name);
531 			exit(1);
532 #endif
533 		}
534 #ifdef DEBUG_TORITO
535 		fprintf(stderr, "Partition type %u\n",
536 						boot_desc_entry->sys_type[0]);
537 #endif
538 	/* load single boot sector, in this case the MBR */
539 		nsectors = 1;
540 
541 	} else if (boot_entry->no_emul_boot) {
542 		/*
543 		 * no emulation is a simple image boot of all the sectors
544 		 * in the boot image
545 		 */
546 		boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_NOEMUL;
547 		if (verbose > 0)
548 			fprintf(stderr, "No emulation\n");
549 
550 	} else {
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;
554 			if (verbose > 0)
555 				fprintf(stderr, "Emulating a 1440 kB floppy\n");
556 
557 		} else if (nsectors == 5760) {
558 			boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_288FLOP;
559 			if (verbose > 0)
560 				fprintf(stderr, "Emulating a 2880 kB floppy\n");
561 
562 		} else if (nsectors == 2400) {
563 			boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_12FLOP;
564 			if (verbose > 0)
565 				fprintf(stderr, "Emulating a 1200 kB floppy\n");
566 
567 		} else {
568 #ifdef	USE_LIBSCHILY
569 			comerrno(EX_BAD,
570 			"Error - boot image '%s' has not an allowable size.\n",
571 							de->whole_name);
572 #else
573 			fprintf(stderr,
574 			"Error - boot image '%s' has not an allowable size.\n",
575 							de->whole_name);
576 			exit(1);
577 #endif
578 		}
579 
580 		/* load single boot sector for floppies */
581 		nsectors = 1;
582 	}
583 
584 	/* fill in boot image details */
585 #ifdef DEBUG_TORITO
586 	fprintf(stderr, "Boot %u sectors\n", nsectors);
587 	fprintf(stderr, "Extent of boot images is %d\n",
588 				get_733(de->isorec.extent));
589 #endif
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));
593 
594 
595 	/* If the user has asked for it, patch the boot image */
596 	if (boot_entry->boot_info_table) {
597 		int		bootimage;
598 		unsigned int	bi_checksum;
599 		unsigned int	total_len;
600 		static char	csum_buffer[SECTOR_SIZE];
601 		int		len;
602 		struct genisoimage_boot_info bi_table;
603 		bootimage = open(de->whole_name, O_RDWR | O_BINARY);
604 		if (bootimage == -1) {
605 #ifdef	USE_LIBSCHILY
606 			comerr(
607 			"Error opening boot image file '%s' for update.\n",
608 							de->whole_name);
609 #else
610 			fprintf(stderr,
611 			"Error opening boot image file '%s' for update.\n",
612 							de->whole_name);
613 			perror("");
614 			exit(1);
615 #endif
616 		}
617 	/* Compute checksum of boot image, sans 64 bytes */
618 		total_len = 0;
619 		bi_checksum = 0;
620 		while ((len = read(bootimage, csum_buffer, SECTOR_SIZE)) > 0) {
621 			if (total_len & 3) {
622 #ifdef	USE_LIBSCHILY
623 				comerrno(EX_BAD,
624 				"Odd alignment at non-end-of-file in boot image '%s'.\n",
625 							de->whole_name);
626 #else
627 				fprintf(stderr,
628 				"Odd alignment at non-end-of-file in boot image '%s'.\n",
629 							de->whole_name);
630 				exit(1);
631 #endif
632 			}
633 			if (total_len < 64)
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]);
639 			total_len += len;
640 		}
641 
642 		if (total_len != de->size) {
643 #ifdef	USE_LIBSCHILY
644 			comerrno(EX_BAD,
645 			"Boot image file '%s' changed underneath us!\n",
646 						de->whole_name);
647 #else
648 			fprintf(stderr,
649 			"Boot image file '%s' changed underneath us!\n",
650 						de->whole_name);
651 			exit(1);
652 #endif
653 		}
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);
662 
663 		write(bootimage, &bi_table, sizeof (bi_table)); /* FIXME: check return value */
664 		close(bootimage);
665 	}
666 }/* fill_boot_desc(... */
667 
668 void
get_boot_entry()669 get_boot_entry()
670 {
671 	if (current_boot_entry)
672 		return;
673 
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));
677 
678 	if (!first_boot_entry) {
679 		first_boot_entry = current_boot_entry;
680 		last_boot_entry = current_boot_entry;
681 	} else {
682 		last_boot_entry->next = current_boot_entry;
683 		last_boot_entry = current_boot_entry;
684 	}
685 }
686 
687 void
new_boot_entry()688 new_boot_entry()
689 {
690 	current_boot_entry = NULL;
691 }
692 
693 /*
694  * Function to write the EVD for the disc.
695  */
696 static int
tvd_write(FILE * outfile)697 tvd_write(FILE *outfile)
698 {
699 	/* check the boot image is not NULL */
700 	if (!boot_image) {
701 #ifdef	USE_LIBSCHILY
702 		comerrno(EX_BAD, "No boot image specified.\n");
703 #else
704 		fprintf(stderr, "No boot image specified.\n");
705 		exit(1);
706 #endif
707 	}
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++;
713 	return (0);
714 }
715 
716 struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write, "Eltorito Volume Descriptor"};
717