Module Name:    src
Committed By:   christos
Date:           Sun May 22 21:51:40 UTC 2011

Modified Files:
        src/usr.sbin/makefs: cd9660.c cd9660.h makefs.8
        src/usr.sbin/makefs/cd9660: cd9660_eltorito.c

Log Message:
>From Nathan Whitehorn (nwhitehorn at freebsd dot org):
Add code to generate bootable ISOs on Powermac and CHRP systems.
Synthesize some partition maps (APM and MBR, respectively) pointing
to (a) the whole disk, and (b) relevant El Torito boot images that
have been added by other code. These partition maps are a little
bit funny looking, but they seem to work. FreeBSD has been using
this successfully in their release generation on powerpc, as well
as generating all non-SPARC install media. SPARC support could
probably be added as an extension of this patch.


To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.29 src/usr.sbin/makefs/cd9660.c
cvs rdiff -u -r1.15 -r1.16 src/usr.sbin/makefs/cd9660.h
cvs rdiff -u -r1.32 -r1.33 src/usr.sbin/makefs/makefs.8
cvs rdiff -u -r1.14 -r1.15 src/usr.sbin/makefs/cd9660/cd9660_eltorito.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/makefs/cd9660.c
diff -u src/usr.sbin/makefs/cd9660.c:1.28 src/usr.sbin/makefs/cd9660.c:1.29
--- src/usr.sbin/makefs/cd9660.c:1.28	Fri Nov 19 10:47:32 2010
+++ src/usr.sbin/makefs/cd9660.c	Sun May 22 17:51:39 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660.c,v 1.28 2010/11/19 15:47:32 tsutsui Exp $	*/
+/*	$NetBSD: cd9660.c,v 1.29 2011/05/22 21:51:39 christos Exp $	*/
 
 /*
  * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
@@ -103,7 +103,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(__lint)
-__RCSID("$NetBSD: cd9660.c,v 1.28 2010/11/19 15:47:32 tsutsui Exp $");
+__RCSID("$NetBSD: cd9660.c,v 1.29 2011/05/22 21:51:39 christos Exp $");
 #endif  /* !__lint */
 
 #include <string.h>
@@ -215,6 +215,7 @@
 	diskStructure.rr_moved_dir = 0;
 
 	diskStructure.archimedes_enabled = 0;
+	diskStructure.chrp_boot = 0;
 
 	diskStructure.include_padding_areas = 1;
 
@@ -399,6 +400,8 @@
 		diskStructure.rock_ridge_enabled = 1;
 	else if (CD9660_IS_COMMAND_ARG_DUAL(var, "A", "archimedes"))
 		diskStructure.archimedes_enabled = 1;
+	else if (CD9660_IS_COMMAND_ARG(var, "chrp-boot"))
+		diskStructure.chrp_boot = 1;
 	else if (CD9660_IS_COMMAND_ARG_DUAL(var, "K", "keep-bad-images"))
 		diskStructure.keep_bad_images = 1;
 	else if (CD9660_IS_COMMAND_ARG(var, "allow-deep-trees"))

Index: src/usr.sbin/makefs/cd9660.h
diff -u src/usr.sbin/makefs/cd9660.h:1.15 src/usr.sbin/makefs/cd9660.h:1.16
--- src/usr.sbin/makefs/cd9660.h:1.15	Wed Oct 27 14:51:34 2010
+++ src/usr.sbin/makefs/cd9660.h	Sun May 22 17:51:39 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660.h,v 1.15 2010/10/27 18:51:34 christos Exp $	*/
+/*	$NetBSD: cd9660.h,v 1.16 2011/05/22 21:51:39 christos Exp $	*/
 
 /*
  * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
@@ -286,6 +286,7 @@
 	cd9660node *rr_moved_dir;
 
 	int archimedes_enabled;
+	int chrp_boot;
 
 	/* Spec breaking options */
 	u_char allow_deep_trees;

Index: src/usr.sbin/makefs/makefs.8
diff -u src/usr.sbin/makefs/makefs.8:1.32 src/usr.sbin/makefs/makefs.8:1.33
--- src/usr.sbin/makefs/makefs.8:1.32	Tue Jan 20 15:47:25 2009
+++ src/usr.sbin/makefs/makefs.8	Sun May 22 17:51:39 2011
@@ -1,4 +1,4 @@
-.\"	$NetBSD: makefs.8,v 1.32 2009/01/20 20:47:25 bjh21 Exp $
+.\"	$NetBSD: makefs.8,v 1.33 2011/05/22 21:51:39 christos Exp $
 .\"
 .\" Copyright (c) 2001-2003 Wasabi Systems, Inc.
 .\" All rights reserved.
@@ -33,7 +33,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd January 10, 2009
+.Dd May 22, 2011
 .Dt MAKEFS 8
 .Os
 .Sh NAME
@@ -283,6 +283,9 @@
 extension to encode
 .Tn RISC OS
 metadata.
+.It Sy chrp-boot
+Write an MBR partition table to the image to allow older CHRP hardware to
+boot.
 .It Sy boot-load-segment
 Set load segment for the boot image.
 .It Sy bootimage

Index: src/usr.sbin/makefs/cd9660/cd9660_eltorito.c
diff -u src/usr.sbin/makefs/cd9660/cd9660_eltorito.c:1.14 src/usr.sbin/makefs/cd9660/cd9660_eltorito.c:1.15
--- src/usr.sbin/makefs/cd9660/cd9660_eltorito.c:1.14	Wed Oct 27 14:51:35 2010
+++ src/usr.sbin/makefs/cd9660/cd9660_eltorito.c	Sun May 22 17:51:39 2011
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_eltorito.c,v 1.14 2010/10/27 18:51:35 christos Exp $	*/
+/*	$NetBSD: cd9660_eltorito.c,v 1.15 2011/05/22 21:51:39 christos Exp $	*/
 
 /*
  * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
@@ -31,12 +31,15 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  * OF SUCH DAMAGE.
  */
+
+#include <sys/endian.h>
+
 #include "cd9660.h"
 #include "cd9660_eltorito.h"
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(__lint)
-__RCSID("$NetBSD: cd9660_eltorito.c,v 1.14 2010/10/27 18:51:35 christos Exp $");
+__RCSID("$NetBSD: cd9660_eltorito.c,v 1.15 2011/05/22 21:51:39 christos Exp $");
 #endif  /* !__lint */
 
 #ifdef DEBUG
@@ -499,11 +502,81 @@
 	return 1;
 }
 
+static int
+cd9660_write_mbr_partition_entry(FILE *fd, int idx, off_t sector_start,
+    off_t nsectors, int type)
+{
+	uint8_t val;
+	uint32_t lba;
+
+	if (fseeko(fd, (off_t)(idx) * 16 + 0x1be, SEEK_SET) == -1)
+		err(1, "fseeko");
+	
+	val = 0x80; /* Bootable */
+	fwrite(&val, sizeof(val), 1, fd);
+
+	val = 0xff; /* CHS begin */
+	fwrite(&val, sizeof(val), 1, fd);
+	fwrite(&val, sizeof(val), 1, fd);
+	fwrite(&val, sizeof(val), 1, fd);
+
+	val = type; /* Part type */
+	fwrite(&val, sizeof(val), 1, fd);
+
+	val = 0xff; /* CHS end */
+	fwrite(&val, sizeof(val), 1, fd);
+	fwrite(&val, sizeof(val), 1, fd);
+	fwrite(&val, sizeof(val), 1, fd);
+
+	/* LBA extent */
+	lba = htole32(sector_start);
+	fwrite(&lba, sizeof(lba), 1, fd);
+	lba = htole32(nsectors);
+	fwrite(&lba, sizeof(lba), 1, fd);
+
+	return 0;
+}
+
+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)
+{
+	uint32_t apm32;
+	uint16_t apm16;
+
+	if (fseeko(fd, (off_t)(idx + 1) * sector_size, SEEK_SET) == -1)
+		err(1, "fseeko");
+
+	/* Signature */
+	apm16 = htobe16(0x504d);
+	fwrite(&apm16, sizeof(apm16), 1, fd);
+	apm16 = 0;
+	fwrite(&apm16, sizeof(apm16), 1, fd);
+
+	/* Total number of partitions */
+	apm32 = htobe32(total_partitions);
+	fwrite(&apm32, sizeof(apm32), 1, fd);
+	/* Bounds */
+	apm32 = htobe32(sector_start);
+	fwrite(&apm32, sizeof(apm32), 1, fd);
+	apm32 = htobe32(nsectors);
+	fwrite(&apm32, sizeof(apm32), 1, fd);
+
+	fwrite(part_name, strlen(part_name) + 1, 1, fd);
+	fseek(fd, 32 - strlen(part_name) - 1, SEEK_CUR);
+	fwrite(part_type, strlen(part_type) + 1, 1, fd);
+
+	return 0;
+}
+
 int
 cd9660_write_boot(FILE *fd)
 {
 	struct boot_catalog_entry *e;
 	struct cd9660_boot_image *t;
+	int apm_partitions = 0;
+	int mbr_partitions = 0;
 
 	/* write boot catalog */
 	if (fseeko(fd, (off_t)diskStructure.boot_catalog_sector *
@@ -535,7 +608,88 @@
 			    t->filename, t->sector);
 		}
 		cd9660_copy_file(fd, t->sector, t->filename);
+
+		if (t->system == ET_SYS_MAC) 
+			apm_partitions++;
+		if (t->system == ET_SYS_PPC) 
+			mbr_partitions++;
+	}
+
+	/* some systems need partition tables as well */
+	if (mbr_partitions > 0 || diskStructure.chrp_boot) {
+		uint16_t sig;
+
+		fseek(fd, 0x1fe, SEEK_SET);
+		sig = htole16(0xaa55);
+		fwrite(&sig, sizeof(sig), 1, fd);
+
+		mbr_partitions = 0;
+
+		/* Write ISO9660 descriptor, enclosing the whole disk */
+		if (diskStructure.chrp_boot)
+			cd9660_write_mbr_partition_entry(fd, mbr_partitions++,
+			    0, diskStructure.totalSectors *
+			    (diskStructure.sectorSize / 512), 0x96);
+
+		/* Write all partition entries */
+		TAILQ_FOREACH(t, &diskStructure.boot_images, image_list) {
+			if (t->system != ET_SYS_PPC)
+				continue;
+			cd9660_write_mbr_partition_entry(fd, mbr_partitions++,
+			    t->sector * (diskStructure.sectorSize / 512),
+			    t->num_sectors * (diskStructure.sectorSize / 512),
+			    0x41 /* PReP Boot */);
+		}
+	}
+
+	if (apm_partitions > 0) {
+		/* Write DDR and global APM info */
+		uint32_t apm32;
+		uint16_t apm16;
+		int total_parts;
+
+		fseek(fd, 0, SEEK_SET);
+		apm16 = htobe16(0x4552);
+		fwrite(&apm16, sizeof(apm16), 1, fd);
+		/* Device block size */
+		apm16 = htobe16(512);
+		fwrite(&apm16, sizeof(apm16), 1, fd);
+		/* Device block count */
+		apm32 = htobe32(diskStructure.totalSectors *
+		    (diskStructure.sectorSize / 512));
+		fwrite(&apm32, sizeof(apm32), 1, fd);
+		/* Device type/id */
+		apm16 = htobe16(1);
+		fwrite(&apm16, sizeof(apm16), 1, fd);
+		fwrite(&apm16, sizeof(apm16), 1, fd);
+
+		/* Count total needed entries */
+		total_parts = 2 + apm_partitions; /* Self + ISO9660 */
+
+		/* Write self-descriptor */
+		cd9660_write_apm_partition_entry(fd, 0, total_parts, 1,
+		    total_parts, 512, "Apple", "Apple_partition_map");
+
+		/* Write ISO9660 descriptor, enclosing the whole disk */
+		cd9660_write_apm_partition_entry(fd, 1, total_parts, 0,
+		    diskStructure.totalSectors *
+		    (diskStructure.sectorSize / 512), 512, "ISO9660",
+		    "CD_ROM_Mode_1");
+
+		/* Write all partition entries */
+		apm_partitions = 0;
+		TAILQ_FOREACH(t, &diskStructure.boot_images, image_list) {
+			if (t->system != ET_SYS_MAC)
+				continue;
+
+			cd9660_write_apm_partition_entry(fd,
+			    2 + apm_partitions++, total_parts,
+			    t->sector * (diskStructure.sectorSize / 512),
+			    t->num_sectors * (diskStructure.sectorSize / 512),
+			    512, "CD Boot", "Apple_Bootstrap");
+		}
 	}
 
 	return 0;
 }
+

Reply via email to