diff --git a/usr.sbin/makefs/cd9660.c b/usr.sbin/makefs/cd9660.c index 696307bb71f6..78339f9dbf73 100644 --- a/usr.sbin/makefs/cd9660.c +++ b/usr.sbin/makefs/cd9660.c @@ -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 #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 @@ -215,6 +215,7 @@ cd9660_set_defaults(void) diskStructure.rr_moved_dir = 0; diskStructure.archimedes_enabled = 0; + diskStructure.chrp_boot = 0; diskStructure.include_padding_areas = 1; @@ -399,6 +400,8 @@ cd9660_parse_opts(const char *option, fsinfo_t *fsopts) 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")) diff --git a/usr.sbin/makefs/cd9660.h b/usr.sbin/makefs/cd9660.h index 9e96080f9c3a..22ddbd517e27 100644 --- a/usr.sbin/makefs/cd9660.h +++ b/usr.sbin/makefs/cd9660.h @@ -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 @@ typedef struct _iso9660_disk { cd9660node *rr_moved_dir; int archimedes_enabled; + int chrp_boot; /* Spec breaking options */ u_char allow_deep_trees; diff --git a/usr.sbin/makefs/cd9660/cd9660_eltorito.c b/usr.sbin/makefs/cd9660/cd9660_eltorito.c index e1167baaf37e..6b3867a840ce 100644 --- a/usr.sbin/makefs/cd9660/cd9660_eltorito.c +++ b/usr.sbin/makefs/cd9660/cd9660_eltorito.c @@ -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 + #include "cd9660.h" #include "cd9660_eltorito.h" #include #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 @@ cd9660_setup_boot_volume_descriptor(volume_descriptor *bvd) 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 @@ cd9660_write_boot(FILE *fd) 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; } + diff --git a/usr.sbin/makefs/makefs.8 b/usr.sbin/makefs/makefs.8 index 98bc181adc19..d4b2c4394c33 100644 --- a/usr.sbin/makefs/makefs.8 +++ b/usr.sbin/makefs/makefs.8 @@ -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 @@ Use the 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