1 /* @(#)eltorito.c	1.52 15/11/23 joerg */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)eltorito.c	1.52 15/11/23 joerg";
6 
7 #endif
8 /*
9  * Program eltorito.c - Handle El Torito specific extensions to iso9660.
10  *
11  *
12  *  Written by Michael Fulbright <msf@redhat.com> (1996).
13  *
14  * Copyright 1996 RedHat Software, Incorporated
15  * Copyright (c) 1999-2015 J. Schilling
16  *
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)
20  * any later version.
21  *
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.
26  *
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.
30  */
31 
32 #include "mkisofs.h"
33 #include <schily/fcntl.h>
34 #include <schily/utypes.h>
35 #include <schily/intcvt.h>
36 #include "match.h"
37 #include "diskmbr.h"
38 #include "bootinfo.h"
39 #include <schily/schily.h>
40 
41 #undef MIN
42 #define	MIN(a, b) (((a) < (b))? (a): (b))
43 
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,
48 						int arch));
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));
55 
56 
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 */
62 
63 /*
64  * Make sure any existing boot catalog is excluded
65  */
66 EXPORT void
init_boot_catalog(path)67 init_boot_catalog(path)
68 	const char	*path;
69 {
70 #ifdef	SORTING
71 	struct eltorito_boot_entry_info	*cbe;
72 
73 	for (cbe = first_boot_entry;
74 	    cbe != NULL;
75 	    cbe = cbe->next) {
76 		char	*p;
77 
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);
81 		strcpy(p, path);
82 		if (p[strlen(p) - 1] != '/') {
83 			strcat(p, "/");
84 		}
85 		strcat(p, cbe->boot_image);
86 		add_sort_match(p, sort_matches(p, 1));
87 		free(p);
88 	}
89 #endif
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, "/");
94 	}
95 	strcat(bootcat_path, boot_catalog);
96 
97 	/*
98 	 * we are going to create a virtual catalog file
99 	 * - so make sure any existing is excluded
100 	 */
101 	add_match(bootcat_path);
102 
103 	/* flag the file as a memory file */
104 	bcat_de_flags = MEMORY_FILE;
105 
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;
109 
110 	if (j_matches(boot_catalog) || j_matches(bootcat_path))
111 		bcat_de_flags |= INHIBIT_JOLIET_ENTRY;
112 
113 	if (u_matches(boot_catalog) || u_matches(bootcat_path))
114 		bcat_de_flags |= INHIBIT_UDF_ENTRY;
115 
116 } /* init_boot_catalog(... */
117 
118 /*
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
121  * similar way
122  */
123 EXPORT 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 = e_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 			ex_boot_enoent(_("catalog directory"), p1);
155 			/* NOTREACHED */
156 		}
157 		this_dir = 0;
158 
159 		/* get the basename (p3) of the directory */
160 		if ((p3 = strrchr(p1, '/')) != NULL)
161 			p3++;
162 		else
163 			p3 = p1;
164 
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)
168 				this_dir = dir;
169 
170 		if (this_dir == 0) {
171 			ex_boot_enoent(_("catalog directory"), p3);
172 			/* NOTREACHED */
173 		}
174 	} else {
175 		/* boot.cat is in the root directory */
176 		this_dir = root;
177 		p2 = p1;
178 	}
179 
180 	/*
181 	 * make a directory entry in memory (using the same set up as for table
182 	 * entries
183 	 */
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;
189 
190 #ifdef SORTING
191 	/* inherit any sort weight from parent directory */
192 	s_entry->sort = this_dir->sort;
193 	s_entry->sort += 2;
194 
195 	/* see if this entry should have a new weighting */
196 	if (do_sort) {
197 		s_entry->sort = sort_matches(bootcat_path, s_entry->sort);
198 	}
199 #endif /* SORTING */
200 
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);
213 
214 	/* flag file as necessary */
215 	s_entry->de_flags = bcat_de_flags;
216 
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("",
222 			p2, s_entry,
223 			&fstatbuf, &fstatbuf, 0);
224 	}
225 	/*
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
230 	 */
231 	if (generate_tables && !(bcat_de_flags & INHIBIT_ISO9660_ENTRY)) {
232 		sprintf(buffer, "F\t%s\n", s_entry->name);
233 
234 		/* copy the TRANS.TBL entry info and clear the buffer */
235 		s_entry->table = e_strdup(buffer);
236 		memset(buffer, 0, SECTOR_SIZE);
237 
238 		/*
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
243 		 */
244 		s_entry->whole_name = buffer;
245 	} else {
246 		/* store the (empty) file data in the s_entry->table element */
247 		s_entry->table = buffer;
248 		s_entry->whole_name = NULL;
249 	}
250 }
251 
252 LOCAL void
get_torito_desc(boot_desc)253 get_torito_desc(boot_desc)
254 	struct eltorito_boot_descriptor	*boot_desc;
255 {
256 	int			checksum;
257 	unsigned char		*checksum_ptr;
258 	struct directory_entry	*de2;	/* Boot catalog */
259 	int			i;
260 	int			offset;
261 	int			arch = 0;
262 	int			nentries = 0;
263 	struct eltorito_defaultboot_entry boot_desc_record;
264 	struct eltorito_sectionheader_entry boot_shdr_record;
265 #ifdef	__needed__
266 	struct eltorito_section_entry boot_section_record;
267 #endif
268 	struct eltorito_sectionheader_entry *last_section_header = 0;
269 
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;
274 
275 	memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof (EL_TORITO_ID));
276 
277 	/*
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!
282 	 */
283 	de2 = search_tree_file(root, boot_catalog);
284 	if (!de2 || !(de2->de_flags & MEMORY_FILE)) {
285 		ex_boot_enoent(_("catalog"), boot_catalog);
286 		/* NOTREACHED */
287 	}
288 	set_731(boot_desc->bootcat_ptr,
289 		(unsigned int) get_733(de2->isorec.extent));
290 
291 	/*
292 	 * If the platform id for the first (default) boot entry has not been
293 	 * explicitly set, we default to EL_TORITO_ARCH_x86
294 	 */
295 	if ((first_boot_entry->type & ELTORITO_BOOT_ID) == 0) {
296 		first_boot_entry->boot_platform = EL_TORITO_ARCH_x86;
297 	}
298 	arch = first_boot_entry->boot_platform;
299 
300 	/*
301 	 * we have the boot image, so write boot catalog information
302 	 * Next we write out the primary descriptor for the disc
303 	 */
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 */
307 
308 	/*
309 	 * we'll shove start of publisher id into id field,
310 	 * may get truncated but who really reads this stuff!
311 	 */
312 	if (publisher)
313 		memcpy_max(valid_desc.id, publisher,
314 						MIN(23, strlen(publisher)));
315 
316 	valid_desc.key1[0] = (char)0x55;
317 	valid_desc.key2[0] = (char)0xAA;
318 
319 	/* compute the checksum */
320 	checksum = 0;
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;
327 	}
328 
329 	/* now find out the real checksum */
330 	checksum = -checksum;
331 	set_721(valid_desc.cksum, (unsigned int) checksum);
332 
333 	/* now write it to the virtual boot catalog */
334 	memcpy(de2->table, &valid_desc, 32);
335 
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)) {
340 		int	newarch = arch;
341 
342 		if (current_boot_entry->type & ELTORITO_BOOT_ID)
343 			newarch = current_boot_entry->boot_platform;
344 		else
345 			current_boot_entry->boot_platform = arch;
346 
347 		/*
348 		 * El Torito has no such limitation but we currently have...
349 		 */
350 		if (offset >= (SECTOR_SIZE - sizeof (boot_desc_record))) {
351 			comerrno(EX_BAD,
352 			_("Too many El Torito boot entries\n"));
353 		}
354 		if (current_boot_entry == first_boot_entry) {
355 			;
356 			/* EMPTY */
357 		} else if ((current_boot_entry == first_boot_entry->next) ||
358 			    (arch != newarch) ||
359 			    (current_boot_entry->type & ELTORITO_SECTION_HEADER)) {
360 			if (last_section_header)
361 				set_721(&last_section_header->entry_count, nentries);
362 			nentries = 1;
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);
369 		} else {
370 			nentries++;	/* Add entry to this section header */
371 		}
372 		/*
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).
376 		 */
377 		fill_boot_desc(&boot_desc_record, current_boot_entry);
378 		memcpy(de2->table + offset, &boot_desc_record,
379 					sizeof (boot_desc_record));
380 	}
381 
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;
385 	}
386 
387 } /* get_torito_desc(... */
388 
389 LOCAL void
fill_boot_shdr(boot_shdr_entry,arch)390 fill_boot_shdr(boot_shdr_entry, arch)
391 	struct eltorito_sectionheader_entry	*boot_shdr_entry;
392 	int					arch;
393 {
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;
397 }
398 
399 LOCAL void
fill_boot_desc(boot_desc_entry,boot_entry)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;
403 {
404 	struct directory_entry	*de;	/* Boot file */
405 	int			bootmbr;
406 	int			i;
407 	int			nsectors;
408 	int			geosec;
409 
410 	if (!boot_desc_entry || !boot_entry)
411 		return;
412 
413 	/* now adjust boot catalog lets find boot image first */
414 	de = search_tree_file(root, boot_entry->boot_image);
415 	if (!de) {
416 		ex_boot_enoent(_("image"), boot_entry->boot_image);
417 		/* NOTREACHED */
418 	}
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;
423 
424 	/* use default BIOS loadpnt */
425 	set_721(boot_desc_entry->loadseg, boot_entry->load_addr);
426 
427 	/*
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.
431 	 */
432 	nsectors = boot_entry->load_size ? boot_entry->load_size :
433 				ISO_BLOCKS(de->size) * (SECTOR_SIZE/512);
434 
435 	if (verbose > 0) {
436 		fprintf(stderr,
437 			_("Size of boot image is %d sectors -> "), nsectors);
438 	}
439 
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;
443 		if (verbose > 0)
444 			fprintf(stderr, _("Emulating a hard disk\n"));
445 
446 		/* read MBR */
447 		bootmbr = open(de->whole_name, O_RDONLY | O_BINARY);
448 		if (bootmbr == -1) {
449 			comerr(_("Error opening boot image '%s' for read.\n"),
450 							de->whole_name);
451 		}
452 		if (read(bootmbr, &disk_mbr, sizeof (disk_mbr)) !=
453 							sizeof (disk_mbr)) {
454 			comerr(_("Error reading MBR from boot image '%s'.\n"),
455 							de->whole_name);
456 		}
457 		close(bootmbr);
458 		if (la_to_u_2_byte(disk_mbr.magic) != MBR_MAGIC) {
459 			errmsgno(EX_BAD,
460 			_("Warning: boot image '%s' MBR is not a boot sector.\n"),
461 							de->whole_name);
462 		}
463 		/* find partition type */
464 		boot_desc_entry->sys_type[0] = PARTITION_UNUSED;
465 		for (i = 0; i < PARTITION_COUNT; ++i) {
466 			int		s_cyl_sec;
467 			int		e_cyl_sec;
468 
469 			s_cyl_sec =
470 			la_to_u_2_byte(disk_mbr.partition[i].s_cyl_sec);
471 			e_cyl_sec =
472 			la_to_u_2_byte(disk_mbr.partition[i].e_cyl_sec);
473 
474 			if (disk_mbr.partition[i].type != PARTITION_UNUSED) {
475 				if (boot_desc_entry->sys_type[0] !=
476 							PARTITION_UNUSED) {
477 					comerrno(EX_BAD,
478 					_("Boot image '%s' has multiple partitions.\n"),
479 							de->whole_name);
480 				}
481 				boot_desc_entry->sys_type[0] =
482 						disk_mbr.partition[i].type;
483 
484 				/* a few simple sanity warnings */
485 				if (!boot_entry->not_bootable &&
486 				    disk_mbr.partition[i].status !=
487 							PARTITION_ACTIVE) {
488 					fprintf(stderr,
489 					_("Warning: partition not marked active.\n"));
490 				}
491 				if (MBR_CYLINDER(s_cyl_sec) != 0 ||
492 					disk_mbr.partition[i].s_head != 1 ||
493 					MBR_SECTOR(s_cyl_sec != 1)) {
494 					fprintf(stderr,
495 					_("Warning: partition does not start at 0/1/1.\n"));
496 				}
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) {
501 					fprintf(stderr,
502 					_("Warning: image size does not match geometry (%d)\n"),
503 						geosec);
504 				}
505 #ifdef DEBUG_TORITO
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));
514 #endif
515 			}
516 		}
517 		if (boot_desc_entry->sys_type[0] == PARTITION_UNUSED) {
518 			comerrno(EX_BAD,
519 					_("Boot image '%s' has no partitions.\n"),
520 							de->whole_name);
521 		}
522 #ifdef DEBUG_TORITO
523 		fprintf(stderr, "Partition type %u\n",
524 						boot_desc_entry->sys_type[0]);
525 #endif
526 	/* load single boot sector, in this case the MBR */
527 		nsectors = 1;
528 
529 	} else if (boot_entry->no_emul_boot) {
530 		/*
531 		 * no emulation is a simple image boot of all the sectors
532 		 * in the boot image
533 		 */
534 		boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_NOEMUL;
535 		if (verbose > 0)
536 			fprintf(stderr, _("No emulation\n"));
537 
538 	} else {
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;
542 			if (verbose > 0)
543 				fprintf(stderr, _("Emulating a 1440 kB floppy\n"));
544 
545 		} else if (nsectors == 5760) {
546 			boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_288FLOP;
547 			if (verbose > 0)
548 				fprintf(stderr, _("Emulating a 2880 kB floppy\n"));
549 
550 		} else if (nsectors == 2400) {
551 			boot_desc_entry->boot_media[0] = EL_TORITO_MEDIA_12FLOP;
552 			if (verbose > 0)
553 				fprintf(stderr, _("Emulating a 1200 kB floppy\n"));
554 
555 		} else {
556 			comerrno(EX_BAD,
557 			_("Error - boot image '%s' has not an allowable size.\n"),
558 							de->whole_name);
559 		}
560 
561 		/* load single boot sector for floppies */
562 		nsectors = 1;
563 	}
564 
565 	/* fill in boot image details */
566 #ifdef DEBUG_TORITO
567 	fprintf(stderr, "Boot %u sectors\n", nsectors);
568 	fprintf(stderr, "Extent of boot images is %d\n",
569 				get_733(de->isorec.extent));
570 #endif
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));
574 
575 
576 	/* If the user has asked for it, patch the boot image */
577 	if (boot_entry->boot_info_table) {
578 		int		bootimage;
579 		unsigned int	bi_checksum;
580 		unsigned int	total_len;
581 		static char	csum_buffer[SECTOR_SIZE];
582 		int		len;
583 		struct mkisofs_boot_info bi_table;
584 
585 		bootimage = open(de->whole_name, O_RDWR | O_BINARY);
586 		if (bootimage == -1) {
587 			comerr(
588 			_("Error opening boot image file '%s' for update.\n"),
589 							de->whole_name);
590 		}
591 	/* Compute checksum of boot image, sans 64 bytes */
592 		total_len = 0;
593 		bi_checksum = 0;
594 		while ((len = read(bootimage, csum_buffer, SECTOR_SIZE)) > 0) {
595 			if (total_len & 3) {
596 				comerrno(EX_BAD,
597 				_("Odd alignment at non-end-of-file in boot image '%s'.\n"),
598 							de->whole_name);
599 			}
600 			if (total_len < 64)
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]);
606 			total_len += len;
607 		}
608 
609 		if (total_len != de->size) {
610 			comerrno(EX_BAD,
611 			_("Boot image file '%s' changed underneath us!\n"),
612 						de->whole_name);
613 		}
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);
622 
623 		write(bootimage, &bi_table, sizeof (bi_table));
624 		close(bootimage);
625 	}
626 } /* fill_boot_desc(... */
627 
628 EXPORT void
get_boot_entry()629 get_boot_entry()
630 {
631 	if (current_boot_entry)
632 		return;
633 
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));
637 
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;
642 	} else {
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;
646 	}
647 }
648 
649 EXPORT int
new_boot_entry()650 new_boot_entry()
651 {
652 	current_boot_entry = NULL;
653 	return (1);
654 }
655 
656 /*
657  * Exit with a boot no entry message.
658  */
659 EXPORT void
ex_boot_enoent(msg,pname)660 ex_boot_enoent(msg, pname)
661 	char	*msg;
662 	char	*pname;
663 {
664 	comerrno(EX_BAD, _("Uh oh, I cant find the boot %s '%s' inside the target tree.\n"), msg, pname);
665 	/* NOTREACHED */
666 }
667 
668 /*
669  * Function to write the EVD for the disc.
670  */
671 LOCAL int
tvd_write(outfile)672 tvd_write(outfile)
673 	FILE	*outfile;
674 {
675 	/* check the boot image is not NULL */
676 	if (!boot_image) {
677 		comerrno(EX_BAD, _("No boot image specified.\n"));
678 	}
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++;
683 	return (0);
684 }
685 
686 struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write, "Eltorito Volume Descriptor"};
687