xref: /minix3/usr.sbin/makefs/cd9660/cd9660_eltorito.c (revision 9f988b79349f9b89ecc822458c30ec8897558560)
1*9f988b79SJean-Baptiste Boric /*	$NetBSD: cd9660_eltorito.c,v 1.20 2013/01/28 21:03:28 christos Exp $	*/
2*9f988b79SJean-Baptiste Boric 
3*9f988b79SJean-Baptiste Boric /*
4*9f988b79SJean-Baptiste Boric  * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
5*9f988b79SJean-Baptiste Boric  * Perez-Rathke and Ram Vedam.  All rights reserved.
6*9f988b79SJean-Baptiste Boric  *
7*9f988b79SJean-Baptiste Boric  * This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
8*9f988b79SJean-Baptiste Boric  * Alan Perez-Rathke and Ram Vedam.
9*9f988b79SJean-Baptiste Boric  *
10*9f988b79SJean-Baptiste Boric  * Redistribution and use in source and binary forms, with or
11*9f988b79SJean-Baptiste Boric  * without modification, are permitted provided that the following
12*9f988b79SJean-Baptiste Boric  * conditions are met:
13*9f988b79SJean-Baptiste Boric  * 1. Redistributions of source code must retain the above copyright
14*9f988b79SJean-Baptiste Boric  *    notice, this list of conditions and the following disclaimer.
15*9f988b79SJean-Baptiste Boric  * 2. Redistributions in binary form must reproduce the above
16*9f988b79SJean-Baptiste Boric  *    copyright notice, this list of conditions and the following
17*9f988b79SJean-Baptiste Boric  *    disclaimer in the documentation and/or other materials provided
18*9f988b79SJean-Baptiste Boric  *    with the distribution.
19*9f988b79SJean-Baptiste Boric  *
20*9f988b79SJean-Baptiste Boric  * THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
21*9f988b79SJean-Baptiste Boric  * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
22*9f988b79SJean-Baptiste Boric  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23*9f988b79SJean-Baptiste Boric  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24*9f988b79SJean-Baptiste Boric  * DISCLAIMED.  IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
25*9f988b79SJean-Baptiste Boric  * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
26*9f988b79SJean-Baptiste Boric  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27*9f988b79SJean-Baptiste Boric  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28*9f988b79SJean-Baptiste Boric  * USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29*9f988b79SJean-Baptiste Boric  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30*9f988b79SJean-Baptiste Boric  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*9f988b79SJean-Baptiste Boric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32*9f988b79SJean-Baptiste Boric  * OF SUCH DAMAGE.
33*9f988b79SJean-Baptiste Boric  */
34*9f988b79SJean-Baptiste Boric 
35*9f988b79SJean-Baptiste Boric 
36*9f988b79SJean-Baptiste Boric #include "cd9660.h"
37*9f988b79SJean-Baptiste Boric #include "cd9660_eltorito.h"
38*9f988b79SJean-Baptiste Boric #include <sys/bootblock.h>
39*9f988b79SJean-Baptiste Boric #include <util.h>
40*9f988b79SJean-Baptiste Boric 
41*9f988b79SJean-Baptiste Boric #include <sys/cdefs.h>
42*9f988b79SJean-Baptiste Boric #if defined(__RCSID) && !defined(__lint)
43*9f988b79SJean-Baptiste Boric __RCSID("$NetBSD: cd9660_eltorito.c,v 1.20 2013/01/28 21:03:28 christos Exp $");
44*9f988b79SJean-Baptiste Boric #endif  /* !__lint */
45*9f988b79SJean-Baptiste Boric 
46*9f988b79SJean-Baptiste Boric #ifdef DEBUG
47*9f988b79SJean-Baptiste Boric #define	ELTORITO_DPRINTF(__x)	printf __x
48*9f988b79SJean-Baptiste Boric #else
49*9f988b79SJean-Baptiste Boric #define	ELTORITO_DPRINTF(__x)
50*9f988b79SJean-Baptiste Boric #endif
51*9f988b79SJean-Baptiste Boric 
52*9f988b79SJean-Baptiste Boric #include <util.h>
53*9f988b79SJean-Baptiste Boric 
54*9f988b79SJean-Baptiste Boric static struct boot_catalog_entry *cd9660_init_boot_catalog_entry(void);
55*9f988b79SJean-Baptiste Boric static struct boot_catalog_entry *cd9660_boot_setup_validation_entry(char);
56*9f988b79SJean-Baptiste Boric static struct boot_catalog_entry *cd9660_boot_setup_default_entry(
57*9f988b79SJean-Baptiste Boric     struct cd9660_boot_image *);
58*9f988b79SJean-Baptiste Boric static struct boot_catalog_entry *cd9660_boot_setup_section_head(char);
59*9f988b79SJean-Baptiste Boric static struct boot_catalog_entry *cd9660_boot_setup_validation_entry(char);
60*9f988b79SJean-Baptiste Boric #if 0
61*9f988b79SJean-Baptiste Boric static u_char cd9660_boot_get_system_type(struct cd9660_boot_image *);
62*9f988b79SJean-Baptiste Boric #endif
63*9f988b79SJean-Baptiste Boric 
64*9f988b79SJean-Baptiste Boric int
cd9660_add_boot_disk(iso9660_disk * diskStructure,const char * boot_info)65*9f988b79SJean-Baptiste Boric cd9660_add_boot_disk(iso9660_disk *diskStructure, const char *boot_info)
66*9f988b79SJean-Baptiste Boric {
67*9f988b79SJean-Baptiste Boric 	struct stat stbuf;
68*9f988b79SJean-Baptiste Boric 	const char *mode_msg;
69*9f988b79SJean-Baptiste Boric 	char *temp;
70*9f988b79SJean-Baptiste Boric 	char *sysname;
71*9f988b79SJean-Baptiste Boric 	char *filename;
72*9f988b79SJean-Baptiste Boric 	struct cd9660_boot_image *new_image, *tmp_image;
73*9f988b79SJean-Baptiste Boric 
74*9f988b79SJean-Baptiste Boric 	assert(boot_info != NULL);
75*9f988b79SJean-Baptiste Boric 
76*9f988b79SJean-Baptiste Boric 	if (*boot_info == '\0') {
77*9f988b79SJean-Baptiste Boric 		warnx("Error: Boot disk information must be in the "
78*9f988b79SJean-Baptiste Boric 		      "format 'system;filename'");
79*9f988b79SJean-Baptiste Boric 		return 0;
80*9f988b79SJean-Baptiste Boric 	}
81*9f988b79SJean-Baptiste Boric 
82*9f988b79SJean-Baptiste Boric 	/* First decode the boot information */
83*9f988b79SJean-Baptiste Boric 	temp = estrdup(boot_info);
84*9f988b79SJean-Baptiste Boric 
85*9f988b79SJean-Baptiste Boric 	sysname = temp;
86*9f988b79SJean-Baptiste Boric 	filename = strchr(sysname, ';');
87*9f988b79SJean-Baptiste Boric 	if (filename == NULL) {
88*9f988b79SJean-Baptiste Boric 		warnx("supply boot disk information in the format "
89*9f988b79SJean-Baptiste Boric 		    "'system;filename'");
90*9f988b79SJean-Baptiste Boric 		free(temp);
91*9f988b79SJean-Baptiste Boric 		return 0;
92*9f988b79SJean-Baptiste Boric 	}
93*9f988b79SJean-Baptiste Boric 
94*9f988b79SJean-Baptiste Boric 	*filename++ = '\0';
95*9f988b79SJean-Baptiste Boric 
96*9f988b79SJean-Baptiste Boric 	if (diskStructure->verbose_level > 0) {
97*9f988b79SJean-Baptiste Boric 		printf("Found bootdisk with system %s, and filename %s\n",
98*9f988b79SJean-Baptiste Boric 		    sysname, filename);
99*9f988b79SJean-Baptiste Boric 	}
100*9f988b79SJean-Baptiste Boric 	new_image = ecalloc(1, sizeof(*new_image));
101*9f988b79SJean-Baptiste Boric 	new_image->loadSegment = 0;	/* default for now */
102*9f988b79SJean-Baptiste Boric 
103*9f988b79SJean-Baptiste Boric 	/* Decode System */
104*9f988b79SJean-Baptiste Boric 	if (strcmp(sysname, "i386") == 0)
105*9f988b79SJean-Baptiste Boric 		new_image->system = ET_SYS_X86;
106*9f988b79SJean-Baptiste Boric 	else if (strcmp(sysname, "powerpc") == 0)
107*9f988b79SJean-Baptiste Boric 		new_image->system = ET_SYS_PPC;
108*9f988b79SJean-Baptiste Boric 	else if (strcmp(sysname, "macppc") == 0 ||
109*9f988b79SJean-Baptiste Boric 	         strcmp(sysname, "mac68k") == 0)
110*9f988b79SJean-Baptiste Boric 		new_image->system = ET_SYS_MAC;
111*9f988b79SJean-Baptiste Boric 	else {
112*9f988b79SJean-Baptiste Boric 		warnx("boot disk system must be "
113*9f988b79SJean-Baptiste Boric 		      "i386, powerpc, macppc, or mac68k");
114*9f988b79SJean-Baptiste Boric 		free(temp);
115*9f988b79SJean-Baptiste Boric 		free(new_image);
116*9f988b79SJean-Baptiste Boric 		return 0;
117*9f988b79SJean-Baptiste Boric 	}
118*9f988b79SJean-Baptiste Boric 
119*9f988b79SJean-Baptiste Boric 
120*9f988b79SJean-Baptiste Boric 	new_image->filename = estrdup(filename);
121*9f988b79SJean-Baptiste Boric 
122*9f988b79SJean-Baptiste Boric 	free(temp);
123*9f988b79SJean-Baptiste Boric 
124*9f988b79SJean-Baptiste Boric 	/* Get information about the file */
125*9f988b79SJean-Baptiste Boric 	if (lstat(new_image->filename, &stbuf) == -1)
126*9f988b79SJean-Baptiste Boric 		err(EXIT_FAILURE, "%s: lstat(\"%s\")", __func__,
127*9f988b79SJean-Baptiste Boric 		    new_image->filename);
128*9f988b79SJean-Baptiste Boric 
129*9f988b79SJean-Baptiste Boric 	switch (stbuf.st_size) {
130*9f988b79SJean-Baptiste Boric 	case 1440 * 1024:
131*9f988b79SJean-Baptiste Boric 		new_image->targetMode = ET_MEDIA_144FDD;
132*9f988b79SJean-Baptiste Boric 		mode_msg = "Assigned boot image to 1.44 emulation mode";
133*9f988b79SJean-Baptiste Boric 		break;
134*9f988b79SJean-Baptiste Boric 	case 1200 * 1024:
135*9f988b79SJean-Baptiste Boric 		new_image->targetMode = ET_MEDIA_12FDD;
136*9f988b79SJean-Baptiste Boric 		mode_msg = "Assigned boot image to 1.2 emulation mode";
137*9f988b79SJean-Baptiste Boric 		break;
138*9f988b79SJean-Baptiste Boric 	case 2880 * 1024:
139*9f988b79SJean-Baptiste Boric 		new_image->targetMode = ET_MEDIA_288FDD;
140*9f988b79SJean-Baptiste Boric 		mode_msg = "Assigned boot image to 2.88 emulation mode";
141*9f988b79SJean-Baptiste Boric 		break;
142*9f988b79SJean-Baptiste Boric 	default:
143*9f988b79SJean-Baptiste Boric 		new_image->targetMode = ET_MEDIA_NOEM;
144*9f988b79SJean-Baptiste Boric 		mode_msg = "Assigned boot image to no emulation mode";
145*9f988b79SJean-Baptiste Boric 		break;
146*9f988b79SJean-Baptiste Boric 	}
147*9f988b79SJean-Baptiste Boric 
148*9f988b79SJean-Baptiste Boric 	if (diskStructure->verbose_level > 0)
149*9f988b79SJean-Baptiste Boric 		printf("%s\n", mode_msg);
150*9f988b79SJean-Baptiste Boric 
151*9f988b79SJean-Baptiste Boric 	new_image->size = stbuf.st_size;
152*9f988b79SJean-Baptiste Boric 	new_image->num_sectors =
153*9f988b79SJean-Baptiste Boric 	    howmany(new_image->size, diskStructure->sectorSize) *
154*9f988b79SJean-Baptiste Boric 	    howmany(diskStructure->sectorSize, 512);
155*9f988b79SJean-Baptiste Boric 	if (diskStructure->verbose_level > 0) {
156*9f988b79SJean-Baptiste Boric 		printf("New image has size %d, uses %d 512-byte sectors\n",
157*9f988b79SJean-Baptiste Boric 		    new_image->size, new_image->num_sectors);
158*9f988b79SJean-Baptiste Boric 	}
159*9f988b79SJean-Baptiste Boric 	new_image->sector = -1;
160*9f988b79SJean-Baptiste Boric 	/* Bootable by default */
161*9f988b79SJean-Baptiste Boric 	new_image->bootable = ET_BOOTABLE;
162*9f988b79SJean-Baptiste Boric 	/* Add boot disk */
163*9f988b79SJean-Baptiste Boric 
164*9f988b79SJean-Baptiste Boric 	/* Group images for the same platform together. */
165*9f988b79SJean-Baptiste Boric 	TAILQ_FOREACH(tmp_image, &diskStructure->boot_images, image_list) {
166*9f988b79SJean-Baptiste Boric 		if (tmp_image->system != new_image->system)
167*9f988b79SJean-Baptiste Boric 			break;
168*9f988b79SJean-Baptiste Boric 	}
169*9f988b79SJean-Baptiste Boric 
170*9f988b79SJean-Baptiste Boric 	if (tmp_image == NULL) {
171*9f988b79SJean-Baptiste Boric 		TAILQ_INSERT_HEAD(&diskStructure->boot_images, new_image,
172*9f988b79SJean-Baptiste Boric 		    image_list);
173*9f988b79SJean-Baptiste Boric 	} else
174*9f988b79SJean-Baptiste Boric 		TAILQ_INSERT_BEFORE(tmp_image, new_image, image_list);
175*9f988b79SJean-Baptiste Boric 
176*9f988b79SJean-Baptiste Boric 	new_image->serialno = diskStructure->image_serialno++;
177*9f988b79SJean-Baptiste Boric 
178*9f988b79SJean-Baptiste Boric 	/* TODO : Need to do anything about the boot image in the tree? */
179*9f988b79SJean-Baptiste Boric 	diskStructure->is_bootable = 1;
180*9f988b79SJean-Baptiste Boric 
181*9f988b79SJean-Baptiste Boric 	return 1;
182*9f988b79SJean-Baptiste Boric }
183*9f988b79SJean-Baptiste Boric 
184*9f988b79SJean-Baptiste Boric int
cd9660_eltorito_add_boot_option(iso9660_disk * diskStructure,const char * option_string,const char * value)185*9f988b79SJean-Baptiste Boric cd9660_eltorito_add_boot_option(iso9660_disk *diskStructure,
186*9f988b79SJean-Baptiste Boric     const char *option_string, const char *value)
187*9f988b79SJean-Baptiste Boric {
188*9f988b79SJean-Baptiste Boric 	char *eptr;
189*9f988b79SJean-Baptiste Boric 	struct cd9660_boot_image *image;
190*9f988b79SJean-Baptiste Boric 
191*9f988b79SJean-Baptiste Boric 	assert(option_string != NULL);
192*9f988b79SJean-Baptiste Boric 
193*9f988b79SJean-Baptiste Boric 	/* Find the last image added */
194*9f988b79SJean-Baptiste Boric 	TAILQ_FOREACH(image, &diskStructure->boot_images, image_list) {
195*9f988b79SJean-Baptiste Boric 		if (image->serialno + 1 == diskStructure->image_serialno)
196*9f988b79SJean-Baptiste Boric 			break;
197*9f988b79SJean-Baptiste Boric 	}
198*9f988b79SJean-Baptiste Boric 	if (image == NULL)
199*9f988b79SJean-Baptiste Boric 		errx(EXIT_FAILURE, "Attempted to add boot option, "
200*9f988b79SJean-Baptiste Boric 		    "but no boot images have been specified");
201*9f988b79SJean-Baptiste Boric 
202*9f988b79SJean-Baptiste Boric 	if (strcmp(option_string, "no-emul-boot") == 0) {
203*9f988b79SJean-Baptiste Boric 		image->targetMode = ET_MEDIA_NOEM;
204*9f988b79SJean-Baptiste Boric 	} else if (strcmp(option_string, "no-boot") == 0) {
205*9f988b79SJean-Baptiste Boric 		image->bootable = ET_NOT_BOOTABLE;
206*9f988b79SJean-Baptiste Boric 	} else if (strcmp(option_string, "hard-disk-boot") == 0) {
207*9f988b79SJean-Baptiste Boric 		image->targetMode = ET_MEDIA_HDD;
208*9f988b79SJean-Baptiste Boric 	} else if (strcmp(option_string, "boot-load-segment") == 0) {
209*9f988b79SJean-Baptiste Boric 		image->loadSegment = strtoul(value, &eptr, 16);
210*9f988b79SJean-Baptiste Boric 		if (eptr == value || *eptr != '\0' || errno != ERANGE) {
211*9f988b79SJean-Baptiste Boric 			warn("%s: strtoul", __func__);
212*9f988b79SJean-Baptiste Boric 			return 0;
213*9f988b79SJean-Baptiste Boric 		}
214*9f988b79SJean-Baptiste Boric 	} else {
215*9f988b79SJean-Baptiste Boric 		return 0;
216*9f988b79SJean-Baptiste Boric 	}
217*9f988b79SJean-Baptiste Boric 	return 1;
218*9f988b79SJean-Baptiste Boric }
219*9f988b79SJean-Baptiste Boric 
220*9f988b79SJean-Baptiste Boric static struct boot_catalog_entry *
cd9660_init_boot_catalog_entry(void)221*9f988b79SJean-Baptiste Boric cd9660_init_boot_catalog_entry(void)
222*9f988b79SJean-Baptiste Boric {
223*9f988b79SJean-Baptiste Boric 	return ecalloc(1, sizeof(struct boot_catalog_entry));
224*9f988b79SJean-Baptiste Boric }
225*9f988b79SJean-Baptiste Boric 
226*9f988b79SJean-Baptiste Boric static struct boot_catalog_entry *
cd9660_boot_setup_validation_entry(char sys)227*9f988b79SJean-Baptiste Boric cd9660_boot_setup_validation_entry(char sys)
228*9f988b79SJean-Baptiste Boric {
229*9f988b79SJean-Baptiste Boric 	struct boot_catalog_entry *entry;
230*9f988b79SJean-Baptiste Boric 	boot_catalog_validation_entry *ve;
231*9f988b79SJean-Baptiste Boric 	int16_t checksum;
232*9f988b79SJean-Baptiste Boric 	unsigned char *csptr;
233*9f988b79SJean-Baptiste Boric 	size_t i;
234*9f988b79SJean-Baptiste Boric 	entry = cd9660_init_boot_catalog_entry();
235*9f988b79SJean-Baptiste Boric 
236*9f988b79SJean-Baptiste Boric 	ve = &entry->entry_data.VE;
237*9f988b79SJean-Baptiste Boric 
238*9f988b79SJean-Baptiste Boric 	ve->header_id[0] = 1;
239*9f988b79SJean-Baptiste Boric 	ve->platform_id[0] = sys;
240*9f988b79SJean-Baptiste Boric 	ve->key[0] = 0x55;
241*9f988b79SJean-Baptiste Boric 	ve->key[1] = 0xAA;
242*9f988b79SJean-Baptiste Boric 
243*9f988b79SJean-Baptiste Boric 	/* Calculate checksum */
244*9f988b79SJean-Baptiste Boric 	checksum = 0;
245*9f988b79SJean-Baptiste Boric 	cd9660_721(0, ve->checksum);
246*9f988b79SJean-Baptiste Boric 	csptr = (unsigned char*)ve;
247*9f988b79SJean-Baptiste Boric 	for (i = 0; i < sizeof(*ve); i += 2) {
248*9f988b79SJean-Baptiste Boric 		checksum += (int16_t)csptr[i];
249*9f988b79SJean-Baptiste Boric 		checksum += 256 * (int16_t)csptr[i + 1];
250*9f988b79SJean-Baptiste Boric 	}
251*9f988b79SJean-Baptiste Boric 	checksum = -checksum;
252*9f988b79SJean-Baptiste Boric 	cd9660_721(checksum, ve->checksum);
253*9f988b79SJean-Baptiste Boric 
254*9f988b79SJean-Baptiste Boric         ELTORITO_DPRINTF(("%s: header_id %d, platform_id %d, key[0] %d, key[1] %d, "
255*9f988b79SJean-Baptiste Boric 	    "checksum %04x\n", __func__, ve->header_id[0], ve->platform_id[0],
256*9f988b79SJean-Baptiste Boric 	    ve->key[0], ve->key[1], checksum));
257*9f988b79SJean-Baptiste Boric 	return entry;
258*9f988b79SJean-Baptiste Boric }
259*9f988b79SJean-Baptiste Boric 
260*9f988b79SJean-Baptiste Boric static struct boot_catalog_entry *
cd9660_boot_setup_default_entry(struct cd9660_boot_image * disk)261*9f988b79SJean-Baptiste Boric cd9660_boot_setup_default_entry(struct cd9660_boot_image *disk)
262*9f988b79SJean-Baptiste Boric {
263*9f988b79SJean-Baptiste Boric 	struct boot_catalog_entry *default_entry;
264*9f988b79SJean-Baptiste Boric 	boot_catalog_initial_entry *ie;
265*9f988b79SJean-Baptiste Boric 
266*9f988b79SJean-Baptiste Boric 	default_entry = cd9660_init_boot_catalog_entry();
267*9f988b79SJean-Baptiste Boric 	if (default_entry == NULL)
268*9f988b79SJean-Baptiste Boric 		return NULL;
269*9f988b79SJean-Baptiste Boric 
270*9f988b79SJean-Baptiste Boric 	ie = &default_entry->entry_data.IE;
271*9f988b79SJean-Baptiste Boric 
272*9f988b79SJean-Baptiste Boric 	ie->boot_indicator[0] = disk->bootable;
273*9f988b79SJean-Baptiste Boric 	ie->media_type[0] = disk->targetMode;
274*9f988b79SJean-Baptiste Boric 	cd9660_721(disk->loadSegment, ie->load_segment);
275*9f988b79SJean-Baptiste Boric 	ie->system_type[0] = disk->system;
276*9f988b79SJean-Baptiste Boric 	cd9660_721(disk->num_sectors, ie->sector_count);
277*9f988b79SJean-Baptiste Boric 	cd9660_731(disk->sector, ie->load_rba);
278*9f988b79SJean-Baptiste Boric 
279*9f988b79SJean-Baptiste Boric 	ELTORITO_DPRINTF(("%s: boot indicator %d, media type %d, "
280*9f988b79SJean-Baptiste Boric 	    "load segment %04x, system type %d, sector count %d, "
281*9f988b79SJean-Baptiste Boric 	    "load rba %d\n", __func__, ie->boot_indicator[0],
282*9f988b79SJean-Baptiste Boric 	    ie->media_type[0], disk->loadSegment, ie->system_type[0],
283*9f988b79SJean-Baptiste Boric 	    disk->num_sectors, disk->sector));
284*9f988b79SJean-Baptiste Boric 	return default_entry;
285*9f988b79SJean-Baptiste Boric }
286*9f988b79SJean-Baptiste Boric 
287*9f988b79SJean-Baptiste Boric static struct boot_catalog_entry *
cd9660_boot_setup_section_head(char platform)288*9f988b79SJean-Baptiste Boric cd9660_boot_setup_section_head(char platform)
289*9f988b79SJean-Baptiste Boric {
290*9f988b79SJean-Baptiste Boric 	struct boot_catalog_entry *entry;
291*9f988b79SJean-Baptiste Boric 	boot_catalog_section_header *sh;
292*9f988b79SJean-Baptiste Boric 
293*9f988b79SJean-Baptiste Boric 	entry = cd9660_init_boot_catalog_entry();
294*9f988b79SJean-Baptiste Boric 	if (entry == NULL)
295*9f988b79SJean-Baptiste Boric 		return NULL;
296*9f988b79SJean-Baptiste Boric 
297*9f988b79SJean-Baptiste Boric 	sh = &entry->entry_data.SH;
298*9f988b79SJean-Baptiste Boric 	/* More by default. The last one will manually be set to 0x91 */
299*9f988b79SJean-Baptiste Boric 	sh->header_indicator[0] = ET_SECTION_HEADER_MORE;
300*9f988b79SJean-Baptiste Boric 	sh->platform_id[0] = platform;
301*9f988b79SJean-Baptiste Boric 	sh->num_section_entries[0] = 0;
302*9f988b79SJean-Baptiste Boric 	return entry;
303*9f988b79SJean-Baptiste Boric }
304*9f988b79SJean-Baptiste Boric 
305*9f988b79SJean-Baptiste Boric static struct boot_catalog_entry *
cd9660_boot_setup_section_entry(struct cd9660_boot_image * disk)306*9f988b79SJean-Baptiste Boric cd9660_boot_setup_section_entry(struct cd9660_boot_image *disk)
307*9f988b79SJean-Baptiste Boric {
308*9f988b79SJean-Baptiste Boric 	struct boot_catalog_entry *entry;
309*9f988b79SJean-Baptiste Boric 	boot_catalog_section_entry *se;
310*9f988b79SJean-Baptiste Boric 	if ((entry = cd9660_init_boot_catalog_entry()) == NULL)
311*9f988b79SJean-Baptiste Boric 		return NULL;
312*9f988b79SJean-Baptiste Boric 
313*9f988b79SJean-Baptiste Boric 	se = &entry->entry_data.SE;
314*9f988b79SJean-Baptiste Boric 
315*9f988b79SJean-Baptiste Boric 	se->boot_indicator[0] = ET_BOOTABLE;
316*9f988b79SJean-Baptiste Boric 	se->media_type[0] = disk->targetMode;
317*9f988b79SJean-Baptiste Boric 	cd9660_721(disk->loadSegment, se->load_segment);
318*9f988b79SJean-Baptiste Boric 	cd9660_721(disk->num_sectors, se->sector_count);
319*9f988b79SJean-Baptiste Boric 	cd9660_731(disk->sector, se->load_rba);
320*9f988b79SJean-Baptiste Boric 	return entry;
321*9f988b79SJean-Baptiste Boric }
322*9f988b79SJean-Baptiste Boric 
323*9f988b79SJean-Baptiste Boric #if 0
324*9f988b79SJean-Baptiste Boric static u_char
325*9f988b79SJean-Baptiste Boric cd9660_boot_get_system_type(struct cd9660_boot_image *disk)
326*9f988b79SJean-Baptiste Boric {
327*9f988b79SJean-Baptiste Boric 	/*
328*9f988b79SJean-Baptiste Boric 		For hard drive booting, we need to examine the MBR to figure
329*9f988b79SJean-Baptiste Boric 		out what the partition type is
330*9f988b79SJean-Baptiste Boric 	*/
331*9f988b79SJean-Baptiste Boric 	return 0;
332*9f988b79SJean-Baptiste Boric }
333*9f988b79SJean-Baptiste Boric #endif
334*9f988b79SJean-Baptiste Boric 
335*9f988b79SJean-Baptiste Boric /*
336*9f988b79SJean-Baptiste Boric  * Set up the BVD, Boot catalog, and the boot entries, but do no writing
337*9f988b79SJean-Baptiste Boric  */
338*9f988b79SJean-Baptiste Boric int
cd9660_setup_boot(iso9660_disk * diskStructure,int first_sector)339*9f988b79SJean-Baptiste Boric cd9660_setup_boot(iso9660_disk *diskStructure, int first_sector)
340*9f988b79SJean-Baptiste Boric {
341*9f988b79SJean-Baptiste Boric 	int sector;
342*9f988b79SJean-Baptiste Boric 	int used_sectors;
343*9f988b79SJean-Baptiste Boric 	int num_entries = 0;
344*9f988b79SJean-Baptiste Boric 	int catalog_sectors;
345*9f988b79SJean-Baptiste Boric 	struct boot_catalog_entry *x86_head, *mac_head, *ppc_head,
346*9f988b79SJean-Baptiste Boric 		*valid_entry, *default_entry, *temp, *head, **headp, *next;
347*9f988b79SJean-Baptiste Boric 	struct cd9660_boot_image *tmp_disk;
348*9f988b79SJean-Baptiste Boric 
349*9f988b79SJean-Baptiste Boric 	headp = NULL;
350*9f988b79SJean-Baptiste Boric 	x86_head = mac_head = ppc_head = NULL;
351*9f988b79SJean-Baptiste Boric 
352*9f988b79SJean-Baptiste Boric 	/* If there are no boot disks, don't bother building boot information */
353*9f988b79SJean-Baptiste Boric 	if (TAILQ_EMPTY(&diskStructure->boot_images))
354*9f988b79SJean-Baptiste Boric 		return 0;
355*9f988b79SJean-Baptiste Boric 
356*9f988b79SJean-Baptiste Boric 	/* Point to catalog: For now assume it consumes one sector */
357*9f988b79SJean-Baptiste Boric 	ELTORITO_DPRINTF(("Boot catalog will go in sector %d\n", first_sector));
358*9f988b79SJean-Baptiste Boric 	diskStructure->boot_catalog_sector = first_sector;
359*9f988b79SJean-Baptiste Boric 	cd9660_bothendian_dword(first_sector,
360*9f988b79SJean-Baptiste Boric 		diskStructure->boot_descriptor->boot_catalog_pointer);
361*9f988b79SJean-Baptiste Boric 
362*9f988b79SJean-Baptiste Boric 	/* Step 1: Generate boot catalog */
363*9f988b79SJean-Baptiste Boric 	/* Step 1a: Validation entry */
364*9f988b79SJean-Baptiste Boric 	valid_entry = cd9660_boot_setup_validation_entry(ET_SYS_X86);
365*9f988b79SJean-Baptiste Boric 	if (valid_entry == NULL)
366*9f988b79SJean-Baptiste Boric 		return -1;
367*9f988b79SJean-Baptiste Boric 
368*9f988b79SJean-Baptiste Boric 	/*
369*9f988b79SJean-Baptiste Boric 	 * Count how many boot images there are,
370*9f988b79SJean-Baptiste Boric 	 * and how many sectors they consume.
371*9f988b79SJean-Baptiste Boric 	 */
372*9f988b79SJean-Baptiste Boric 	num_entries = 1;
373*9f988b79SJean-Baptiste Boric 	used_sectors = 0;
374*9f988b79SJean-Baptiste Boric 
375*9f988b79SJean-Baptiste Boric 	TAILQ_FOREACH(tmp_disk, &diskStructure->boot_images, image_list) {
376*9f988b79SJean-Baptiste Boric 		used_sectors += tmp_disk->num_sectors;
377*9f988b79SJean-Baptiste Boric 
378*9f988b79SJean-Baptiste Boric 		/* One default entry per image */
379*9f988b79SJean-Baptiste Boric 		num_entries++;
380*9f988b79SJean-Baptiste Boric 	}
381*9f988b79SJean-Baptiste Boric 	catalog_sectors = howmany(num_entries * 0x20, diskStructure->sectorSize);
382*9f988b79SJean-Baptiste Boric 	used_sectors += catalog_sectors;
383*9f988b79SJean-Baptiste Boric 
384*9f988b79SJean-Baptiste Boric 	if (diskStructure->verbose_level > 0) {
385*9f988b79SJean-Baptiste Boric 		printf("%s: there will be %i entries consuming %i sectors. "
386*9f988b79SJean-Baptiste Boric 		       "Catalog is %i sectors\n", __func__, num_entries,
387*9f988b79SJean-Baptiste Boric 		       used_sectors, catalog_sectors);
388*9f988b79SJean-Baptiste Boric 	}
389*9f988b79SJean-Baptiste Boric 
390*9f988b79SJean-Baptiste Boric 	/* Populate sector numbers */
391*9f988b79SJean-Baptiste Boric 	sector = first_sector + catalog_sectors;
392*9f988b79SJean-Baptiste Boric 	TAILQ_FOREACH(tmp_disk, &diskStructure->boot_images, image_list) {
393*9f988b79SJean-Baptiste Boric 		tmp_disk->sector = sector;
394*9f988b79SJean-Baptiste Boric 		sector += tmp_disk->num_sectors;
395*9f988b79SJean-Baptiste Boric 	}
396*9f988b79SJean-Baptiste Boric 
397*9f988b79SJean-Baptiste Boric 	LIST_INSERT_HEAD(&diskStructure->boot_entries, valid_entry, ll_struct);
398*9f988b79SJean-Baptiste Boric 
399*9f988b79SJean-Baptiste Boric 	/* Step 1b: Initial/default entry */
400*9f988b79SJean-Baptiste Boric 	/* TODO : PARAM */
401*9f988b79SJean-Baptiste Boric 	tmp_disk = TAILQ_FIRST(&diskStructure->boot_images);
402*9f988b79SJean-Baptiste Boric 	default_entry = cd9660_boot_setup_default_entry(tmp_disk);
403*9f988b79SJean-Baptiste Boric 	if (default_entry == NULL) {
404*9f988b79SJean-Baptiste Boric 		warnx("Error: memory allocation failed in cd9660_setup_boot");
405*9f988b79SJean-Baptiste Boric 		return -1;
406*9f988b79SJean-Baptiste Boric 	}
407*9f988b79SJean-Baptiste Boric 
408*9f988b79SJean-Baptiste Boric 	LIST_INSERT_AFTER(valid_entry, default_entry, ll_struct);
409*9f988b79SJean-Baptiste Boric 
410*9f988b79SJean-Baptiste Boric 	/* Todo: multiple default entries? */
411*9f988b79SJean-Baptiste Boric 
412*9f988b79SJean-Baptiste Boric 	tmp_disk = TAILQ_NEXT(tmp_disk, image_list);
413*9f988b79SJean-Baptiste Boric 
414*9f988b79SJean-Baptiste Boric 	temp = default_entry;
415*9f988b79SJean-Baptiste Boric 
416*9f988b79SJean-Baptiste Boric 	/* If multiple boot images are given : */
417*9f988b79SJean-Baptiste Boric 	while (tmp_disk != NULL) {
418*9f988b79SJean-Baptiste Boric 		/* Step 2: Section header */
419*9f988b79SJean-Baptiste Boric 		switch (tmp_disk->system) {
420*9f988b79SJean-Baptiste Boric 		case ET_SYS_X86:
421*9f988b79SJean-Baptiste Boric 			headp = &x86_head;
422*9f988b79SJean-Baptiste Boric 			break;
423*9f988b79SJean-Baptiste Boric 		case ET_SYS_PPC:
424*9f988b79SJean-Baptiste Boric 			headp = &ppc_head;
425*9f988b79SJean-Baptiste Boric 			break;
426*9f988b79SJean-Baptiste Boric 		case ET_SYS_MAC:
427*9f988b79SJean-Baptiste Boric 			headp = &mac_head;
428*9f988b79SJean-Baptiste Boric 			break;
429*9f988b79SJean-Baptiste Boric 		default:
430*9f988b79SJean-Baptiste Boric 			warnx("%s: internal error: unknown system type",
431*9f988b79SJean-Baptiste Boric 			    __func__);
432*9f988b79SJean-Baptiste Boric 			return -1;
433*9f988b79SJean-Baptiste Boric 		}
434*9f988b79SJean-Baptiste Boric 
435*9f988b79SJean-Baptiste Boric 		if (*headp == NULL) {
436*9f988b79SJean-Baptiste Boric 			head =
437*9f988b79SJean-Baptiste Boric 			    cd9660_boot_setup_section_head(tmp_disk->system);
438*9f988b79SJean-Baptiste Boric 			if (head == NULL) {
439*9f988b79SJean-Baptiste Boric 				warnx("Error: memory allocation failed in "
440*9f988b79SJean-Baptiste Boric 				      "cd9660_setup_boot");
441*9f988b79SJean-Baptiste Boric 				return -1;
442*9f988b79SJean-Baptiste Boric 			}
443*9f988b79SJean-Baptiste Boric 			LIST_INSERT_AFTER(default_entry, head, ll_struct);
444*9f988b79SJean-Baptiste Boric 			*headp = head;
445*9f988b79SJean-Baptiste Boric 		} else
446*9f988b79SJean-Baptiste Boric 			head = *headp;
447*9f988b79SJean-Baptiste Boric 
448*9f988b79SJean-Baptiste Boric 		head->entry_data.SH.num_section_entries[0]++;
449*9f988b79SJean-Baptiste Boric 
450*9f988b79SJean-Baptiste Boric 		/* Step 2a: Section entry and extensions */
451*9f988b79SJean-Baptiste Boric 		temp = cd9660_boot_setup_section_entry(tmp_disk);
452*9f988b79SJean-Baptiste Boric 		if (temp == NULL) {
453*9f988b79SJean-Baptiste Boric 			warn("%s: cd9660_boot_setup_section_entry", __func__);
454*9f988b79SJean-Baptiste Boric 			return -1;
455*9f988b79SJean-Baptiste Boric 		}
456*9f988b79SJean-Baptiste Boric 
457*9f988b79SJean-Baptiste Boric 		while ((next = LIST_NEXT(head, ll_struct)) != NULL &&
458*9f988b79SJean-Baptiste Boric 		       next->entry_type == ET_ENTRY_SE)
459*9f988b79SJean-Baptiste Boric 			head = next;
460*9f988b79SJean-Baptiste Boric 
461*9f988b79SJean-Baptiste Boric 		LIST_INSERT_AFTER(head, temp, ll_struct);
462*9f988b79SJean-Baptiste Boric 		tmp_disk = TAILQ_NEXT(tmp_disk, image_list);
463*9f988b79SJean-Baptiste Boric 	}
464*9f988b79SJean-Baptiste Boric 
465*9f988b79SJean-Baptiste Boric 	/* TODO: Remaining boot disks when implemented */
466*9f988b79SJean-Baptiste Boric 
467*9f988b79SJean-Baptiste Boric 	return first_sector + used_sectors;
468*9f988b79SJean-Baptiste Boric }
469*9f988b79SJean-Baptiste Boric 
470*9f988b79SJean-Baptiste Boric int
cd9660_setup_boot_volume_descriptor(iso9660_disk * diskStructure,volume_descriptor * bvd)471*9f988b79SJean-Baptiste Boric cd9660_setup_boot_volume_descriptor(iso9660_disk *diskStructure,
472*9f988b79SJean-Baptiste Boric     volume_descriptor *bvd)
473*9f988b79SJean-Baptiste Boric {
474*9f988b79SJean-Baptiste Boric 	boot_volume_descriptor *bvdData =
475*9f988b79SJean-Baptiste Boric 	    (boot_volume_descriptor*)bvd->volumeDescriptorData;
476*9f988b79SJean-Baptiste Boric 
477*9f988b79SJean-Baptiste Boric 	bvdData->boot_record_indicator[0] = ISO_VOLUME_DESCRIPTOR_BOOT;
478*9f988b79SJean-Baptiste Boric 	memcpy(bvdData->identifier, ISO_VOLUME_DESCRIPTOR_STANDARD_ID, 5);
479*9f988b79SJean-Baptiste Boric 	bvdData->version[0] = 1;
480*9f988b79SJean-Baptiste Boric 	memcpy(bvdData->boot_system_identifier, ET_ID, 23);
481*9f988b79SJean-Baptiste Boric 	memcpy(bvdData->identifier, ISO_VOLUME_DESCRIPTOR_STANDARD_ID, 5);
482*9f988b79SJean-Baptiste Boric 	diskStructure->boot_descriptor =
483*9f988b79SJean-Baptiste Boric 	    (boot_volume_descriptor*) bvd->volumeDescriptorData;
484*9f988b79SJean-Baptiste Boric 	return 1;
485*9f988b79SJean-Baptiste Boric }
486*9f988b79SJean-Baptiste Boric 
487*9f988b79SJean-Baptiste Boric static int
cd9660_write_mbr_partition_entry(FILE * fd,int idx,off_t sector_start,off_t nsectors,int type)488*9f988b79SJean-Baptiste Boric cd9660_write_mbr_partition_entry(FILE *fd, int idx, off_t sector_start,
489*9f988b79SJean-Baptiste Boric     off_t nsectors, int type)
490*9f988b79SJean-Baptiste Boric {
491*9f988b79SJean-Baptiste Boric 	uint8_t val;
492*9f988b79SJean-Baptiste Boric 	uint32_t lba;
493*9f988b79SJean-Baptiste Boric 
494*9f988b79SJean-Baptiste Boric 	if (fseeko(fd, (off_t)(idx) * 16 + 0x1be, SEEK_SET) == -1)
495*9f988b79SJean-Baptiste Boric 		err(1, "fseeko");
496*9f988b79SJean-Baptiste Boric 
497*9f988b79SJean-Baptiste Boric 	val = 0x80; /* Bootable */
498*9f988b79SJean-Baptiste Boric 	fwrite(&val, sizeof(val), 1, fd);
499*9f988b79SJean-Baptiste Boric 
500*9f988b79SJean-Baptiste Boric 	val = 0xff; /* CHS begin */
501*9f988b79SJean-Baptiste Boric 	fwrite(&val, sizeof(val), 1, fd);
502*9f988b79SJean-Baptiste Boric 	fwrite(&val, sizeof(val), 1, fd);
503*9f988b79SJean-Baptiste Boric 	fwrite(&val, sizeof(val), 1, fd);
504*9f988b79SJean-Baptiste Boric 
505*9f988b79SJean-Baptiste Boric 	val = type; /* Part type */
506*9f988b79SJean-Baptiste Boric 	fwrite(&val, sizeof(val), 1, fd);
507*9f988b79SJean-Baptiste Boric 
508*9f988b79SJean-Baptiste Boric 	val = 0xff; /* CHS end */
509*9f988b79SJean-Baptiste Boric 	fwrite(&val, sizeof(val), 1, fd);
510*9f988b79SJean-Baptiste Boric 	fwrite(&val, sizeof(val), 1, fd);
511*9f988b79SJean-Baptiste Boric 	fwrite(&val, sizeof(val), 1, fd);
512*9f988b79SJean-Baptiste Boric 
513*9f988b79SJean-Baptiste Boric 	/* LBA extent */
514*9f988b79SJean-Baptiste Boric 	lba = htole32(sector_start);
515*9f988b79SJean-Baptiste Boric 	fwrite(&lba, sizeof(lba), 1, fd);
516*9f988b79SJean-Baptiste Boric 	lba = htole32(nsectors);
517*9f988b79SJean-Baptiste Boric 	fwrite(&lba, sizeof(lba), 1, fd);
518*9f988b79SJean-Baptiste Boric 
519*9f988b79SJean-Baptiste Boric 	return 0;
520*9f988b79SJean-Baptiste Boric }
521*9f988b79SJean-Baptiste Boric 
522*9f988b79SJean-Baptiste Boric static int
cd9660_write_apm_partition_entry(FILE * fd,int idx,int total_partitions,off_t sector_start,off_t nsectors,off_t sector_size,const char * part_name,const char * part_type)523*9f988b79SJean-Baptiste Boric cd9660_write_apm_partition_entry(FILE *fd, int idx, int total_partitions,
524*9f988b79SJean-Baptiste Boric     off_t sector_start, off_t nsectors, off_t sector_size,
525*9f988b79SJean-Baptiste Boric     const char *part_name, const char *part_type)
526*9f988b79SJean-Baptiste Boric {
527*9f988b79SJean-Baptiste Boric 	uint32_t apm32, part_status;
528*9f988b79SJean-Baptiste Boric 	uint16_t apm16;
529*9f988b79SJean-Baptiste Boric 
530*9f988b79SJean-Baptiste Boric 	/* See Apple Tech Note 1189 for the details about the pmPartStatus
531*9f988b79SJean-Baptiste Boric 	 * flags.
532*9f988b79SJean-Baptiste Boric 	 * Below the flags which are default:
533*9f988b79SJean-Baptiste Boric 	 * - IsValid     0x01
534*9f988b79SJean-Baptiste Boric 	 * - IsAllocated 0x02
535*9f988b79SJean-Baptiste Boric 	 * - IsReadable  0x10
536*9f988b79SJean-Baptiste Boric 	 * - IsWritable  0x20
537*9f988b79SJean-Baptiste Boric 	 */
538*9f988b79SJean-Baptiste Boric 	part_status = APPLE_PS_VALID | APPLE_PS_ALLOCATED | APPLE_PS_READABLE |
539*9f988b79SJean-Baptiste Boric 	    APPLE_PS_WRITABLE;
540*9f988b79SJean-Baptiste Boric 
541*9f988b79SJean-Baptiste Boric 	if (fseeko(fd, (off_t)(idx + 1) * sector_size, SEEK_SET) == -1)
542*9f988b79SJean-Baptiste Boric 		err(1, "fseeko");
543*9f988b79SJean-Baptiste Boric 
544*9f988b79SJean-Baptiste Boric 	/* Signature */
545*9f988b79SJean-Baptiste Boric 	apm16 = htobe16(0x504d);
546*9f988b79SJean-Baptiste Boric 	fwrite(&apm16, sizeof(apm16), 1, fd);
547*9f988b79SJean-Baptiste Boric 	apm16 = 0;
548*9f988b79SJean-Baptiste Boric 	fwrite(&apm16, sizeof(apm16), 1, fd);
549*9f988b79SJean-Baptiste Boric 
550*9f988b79SJean-Baptiste Boric 	/* Total number of partitions */
551*9f988b79SJean-Baptiste Boric 	apm32 = htobe32(total_partitions);
552*9f988b79SJean-Baptiste Boric 	fwrite(&apm32, sizeof(apm32), 1, fd);
553*9f988b79SJean-Baptiste Boric 	/* Bounds */
554*9f988b79SJean-Baptiste Boric 	apm32 = htobe32(sector_start);
555*9f988b79SJean-Baptiste Boric 	fwrite(&apm32, sizeof(apm32), 1, fd);
556*9f988b79SJean-Baptiste Boric 	apm32 = htobe32(nsectors);
557*9f988b79SJean-Baptiste Boric 	fwrite(&apm32, sizeof(apm32), 1, fd);
558*9f988b79SJean-Baptiste Boric 
559*9f988b79SJean-Baptiste Boric 	fwrite(part_name, strlen(part_name) + 1, 1, fd);
560*9f988b79SJean-Baptiste Boric 	fseek(fd, 32 - strlen(part_name) - 1, SEEK_CUR);
561*9f988b79SJean-Baptiste Boric 	fwrite(part_type, strlen(part_type) + 1, 1, fd);
562*9f988b79SJean-Baptiste Boric 	fseek(fd, 32 - strlen(part_type) - 1, SEEK_CUR);
563*9f988b79SJean-Baptiste Boric 
564*9f988b79SJean-Baptiste Boric 	apm32 = 0;
565*9f988b79SJean-Baptiste Boric 	/* pmLgDataStart */
566*9f988b79SJean-Baptiste Boric 	fwrite(&apm32, sizeof(apm32), 1, fd);
567*9f988b79SJean-Baptiste Boric 	/* pmDataCnt */
568*9f988b79SJean-Baptiste Boric 	apm32 = htobe32(nsectors);
569*9f988b79SJean-Baptiste Boric 	fwrite(&apm32, sizeof(apm32), 1, fd);
570*9f988b79SJean-Baptiste Boric 	/* pmPartStatus */
571*9f988b79SJean-Baptiste Boric 	apm32 = htobe32(part_status);
572*9f988b79SJean-Baptiste Boric 	fwrite(&apm32, sizeof(apm32), 1, fd);
573*9f988b79SJean-Baptiste Boric 
574*9f988b79SJean-Baptiste Boric 	return 0;
575*9f988b79SJean-Baptiste Boric }
576*9f988b79SJean-Baptiste Boric 
577*9f988b79SJean-Baptiste Boric int
cd9660_write_boot(iso9660_disk * diskStructure,FILE * fd)578*9f988b79SJean-Baptiste Boric cd9660_write_boot(iso9660_disk *diskStructure, FILE *fd)
579*9f988b79SJean-Baptiste Boric {
580*9f988b79SJean-Baptiste Boric 	struct boot_catalog_entry *e;
581*9f988b79SJean-Baptiste Boric 	struct cd9660_boot_image *t;
582*9f988b79SJean-Baptiste Boric 	int apm_partitions = 0;
583*9f988b79SJean-Baptiste Boric 	int mbr_partitions = 0;
584*9f988b79SJean-Baptiste Boric 
585*9f988b79SJean-Baptiste Boric 	/* write boot catalog */
586*9f988b79SJean-Baptiste Boric 	if (fseeko(fd, (off_t)diskStructure->boot_catalog_sector *
587*9f988b79SJean-Baptiste Boric 	    diskStructure->sectorSize, SEEK_SET) == -1)
588*9f988b79SJean-Baptiste Boric 		err(1, "fseeko");
589*9f988b79SJean-Baptiste Boric 
590*9f988b79SJean-Baptiste Boric 	if (diskStructure->verbose_level > 0) {
591*9f988b79SJean-Baptiste Boric 		printf("Writing boot catalog to sector %" PRId64 "\n",
592*9f988b79SJean-Baptiste Boric 		    diskStructure->boot_catalog_sector);
593*9f988b79SJean-Baptiste Boric 	}
594*9f988b79SJean-Baptiste Boric 	LIST_FOREACH(e, &diskStructure->boot_entries, ll_struct) {
595*9f988b79SJean-Baptiste Boric 		if (diskStructure->verbose_level > 0) {
596*9f988b79SJean-Baptiste Boric 			printf("Writing catalog entry of type %d\n",
597*9f988b79SJean-Baptiste Boric 			    e->entry_type);
598*9f988b79SJean-Baptiste Boric 		}
599*9f988b79SJean-Baptiste Boric 		/*
600*9f988b79SJean-Baptiste Boric 		 * It doesnt matter which one gets written
601*9f988b79SJean-Baptiste Boric 		 * since they are the same size
602*9f988b79SJean-Baptiste Boric 		 */
603*9f988b79SJean-Baptiste Boric 		fwrite(&(e->entry_data.VE), 1, 32, fd);
604*9f988b79SJean-Baptiste Boric 	}
605*9f988b79SJean-Baptiste Boric 	if (diskStructure->verbose_level > 0)
606*9f988b79SJean-Baptiste Boric 		printf("Finished writing boot catalog\n");
607*9f988b79SJean-Baptiste Boric 
608*9f988b79SJean-Baptiste Boric 	/* copy boot images */
609*9f988b79SJean-Baptiste Boric 	TAILQ_FOREACH(t, &diskStructure->boot_images, image_list) {
610*9f988b79SJean-Baptiste Boric 		if (diskStructure->verbose_level > 0) {
611*9f988b79SJean-Baptiste Boric 			printf("Writing boot image from %s to sectors %d\n",
612*9f988b79SJean-Baptiste Boric 			    t->filename, t->sector);
613*9f988b79SJean-Baptiste Boric 		}
614*9f988b79SJean-Baptiste Boric 		cd9660_copy_file(diskStructure, fd, t->sector, t->filename);
615*9f988b79SJean-Baptiste Boric 
616*9f988b79SJean-Baptiste Boric 		if (t->system == ET_SYS_MAC)
617*9f988b79SJean-Baptiste Boric 			apm_partitions++;
618*9f988b79SJean-Baptiste Boric 		if (t->system == ET_SYS_PPC)
619*9f988b79SJean-Baptiste Boric 			mbr_partitions++;
620*9f988b79SJean-Baptiste Boric 	}
621*9f988b79SJean-Baptiste Boric 
622*9f988b79SJean-Baptiste Boric 	/* some systems need partition tables as well */
623*9f988b79SJean-Baptiste Boric 	if (mbr_partitions > 0 || diskStructure->chrp_boot) {
624*9f988b79SJean-Baptiste Boric 		uint16_t sig;
625*9f988b79SJean-Baptiste Boric 
626*9f988b79SJean-Baptiste Boric 		fseek(fd, 0x1fe, SEEK_SET);
627*9f988b79SJean-Baptiste Boric 		sig = htole16(0xaa55);
628*9f988b79SJean-Baptiste Boric 		fwrite(&sig, sizeof(sig), 1, fd);
629*9f988b79SJean-Baptiste Boric 
630*9f988b79SJean-Baptiste Boric 		mbr_partitions = 0;
631*9f988b79SJean-Baptiste Boric 
632*9f988b79SJean-Baptiste Boric 		/* Write ISO9660 descriptor, enclosing the whole disk */
633*9f988b79SJean-Baptiste Boric 		if (diskStructure->chrp_boot)
634*9f988b79SJean-Baptiste Boric 			cd9660_write_mbr_partition_entry(fd, mbr_partitions++,
635*9f988b79SJean-Baptiste Boric 			    0, diskStructure->totalSectors *
636*9f988b79SJean-Baptiste Boric 			    (diskStructure->sectorSize / 512), 0x96);
637*9f988b79SJean-Baptiste Boric 
638*9f988b79SJean-Baptiste Boric 		/* Write all partition entries */
639*9f988b79SJean-Baptiste Boric 		TAILQ_FOREACH(t, &diskStructure->boot_images, image_list) {
640*9f988b79SJean-Baptiste Boric 			if (t->system != ET_SYS_PPC)
641*9f988b79SJean-Baptiste Boric 				continue;
642*9f988b79SJean-Baptiste Boric 			cd9660_write_mbr_partition_entry(fd, mbr_partitions++,
643*9f988b79SJean-Baptiste Boric 			    t->sector * (diskStructure->sectorSize / 512),
644*9f988b79SJean-Baptiste Boric 			    t->num_sectors * (diskStructure->sectorSize / 512),
645*9f988b79SJean-Baptiste Boric 			    0x41 /* PReP Boot */);
646*9f988b79SJean-Baptiste Boric 		}
647*9f988b79SJean-Baptiste Boric 	}
648*9f988b79SJean-Baptiste Boric 
649*9f988b79SJean-Baptiste Boric 	if (apm_partitions > 0) {
650*9f988b79SJean-Baptiste Boric 		/* Write DDR and global APM info */
651*9f988b79SJean-Baptiste Boric 		uint32_t apm32;
652*9f988b79SJean-Baptiste Boric 		uint16_t apm16;
653*9f988b79SJean-Baptiste Boric 		int total_parts;
654*9f988b79SJean-Baptiste Boric 
655*9f988b79SJean-Baptiste Boric 		fseek(fd, 0, SEEK_SET);
656*9f988b79SJean-Baptiste Boric 		apm16 = htobe16(0x4552);
657*9f988b79SJean-Baptiste Boric 		fwrite(&apm16, sizeof(apm16), 1, fd);
658*9f988b79SJean-Baptiste Boric 		/* Device block size */
659*9f988b79SJean-Baptiste Boric 		apm16 = htobe16(512);
660*9f988b79SJean-Baptiste Boric 		fwrite(&apm16, sizeof(apm16), 1, fd);
661*9f988b79SJean-Baptiste Boric 		/* Device block count */
662*9f988b79SJean-Baptiste Boric 		apm32 = htobe32(diskStructure->totalSectors *
663*9f988b79SJean-Baptiste Boric 		    (diskStructure->sectorSize / 512));
664*9f988b79SJean-Baptiste Boric 		fwrite(&apm32, sizeof(apm32), 1, fd);
665*9f988b79SJean-Baptiste Boric 		/* Device type/id */
666*9f988b79SJean-Baptiste Boric 		apm16 = htobe16(1);
667*9f988b79SJean-Baptiste Boric 		fwrite(&apm16, sizeof(apm16), 1, fd);
668*9f988b79SJean-Baptiste Boric 		fwrite(&apm16, sizeof(apm16), 1, fd);
669*9f988b79SJean-Baptiste Boric 
670*9f988b79SJean-Baptiste Boric 		/* Count total needed entries */
671*9f988b79SJean-Baptiste Boric 		total_parts = 2 + apm_partitions; /* Self + ISO9660 */
672*9f988b79SJean-Baptiste Boric 
673*9f988b79SJean-Baptiste Boric 		/* Write self-descriptor */
674*9f988b79SJean-Baptiste Boric 		cd9660_write_apm_partition_entry(fd, 0, total_parts, 1,
675*9f988b79SJean-Baptiste Boric 		    total_parts, 512, "Apple", "Apple_partition_map");
676*9f988b79SJean-Baptiste Boric 
677*9f988b79SJean-Baptiste Boric 		/* Write all partition entries */
678*9f988b79SJean-Baptiste Boric 		apm_partitions = 0;
679*9f988b79SJean-Baptiste Boric 		TAILQ_FOREACH(t, &diskStructure->boot_images, image_list) {
680*9f988b79SJean-Baptiste Boric 			if (t->system != ET_SYS_MAC)
681*9f988b79SJean-Baptiste Boric 				continue;
682*9f988b79SJean-Baptiste Boric 
683*9f988b79SJean-Baptiste Boric 			cd9660_write_apm_partition_entry(fd,
684*9f988b79SJean-Baptiste Boric 			    1 + apm_partitions++, total_parts,
685*9f988b79SJean-Baptiste Boric 			    t->sector * (diskStructure->sectorSize / 512),
686*9f988b79SJean-Baptiste Boric 			    t->num_sectors * (diskStructure->sectorSize / 512),
687*9f988b79SJean-Baptiste Boric 			    512, "CD Boot", "Apple_Bootstrap");
688*9f988b79SJean-Baptiste Boric 		}
689*9f988b79SJean-Baptiste Boric 
690*9f988b79SJean-Baptiste Boric 		/* Write ISO9660 descriptor, enclosing the whole disk */
691*9f988b79SJean-Baptiste Boric 		cd9660_write_apm_partition_entry(fd, 2 + apm_partitions,
692*9f988b79SJean-Baptiste Boric 		    total_parts, 0, diskStructure->totalSectors *
693*9f988b79SJean-Baptiste Boric 		    (diskStructure->sectorSize / 512), 512, "ISO9660",
694*9f988b79SJean-Baptiste Boric 		    "CD_ROM_Mode_1");
695*9f988b79SJean-Baptiste Boric 	}
696*9f988b79SJean-Baptiste Boric 
697*9f988b79SJean-Baptiste Boric 	return 0;
698*9f988b79SJean-Baptiste Boric }
699