summaryrefslogtreecommitdiff
path: root/genisoimage/mac_label.c
diff options
context:
space:
mode:
Diffstat (limited to 'genisoimage/mac_label.c')
-rw-r--r--genisoimage/mac_label.c425
1 files changed, 425 insertions, 0 deletions
diff --git a/genisoimage/mac_label.c b/genisoimage/mac_label.c
new file mode 100644
index 0000000..f43aafc
--- /dev/null
+++ b/genisoimage/mac_label.c
@@ -0,0 +1,425 @@
+/*
+ * This file has been modified for the cdrkit suite.
+ *
+ * The behaviour and appearence of the program code below can differ to a major
+ * extent from the version distributed by the original author(s).
+ *
+ * For details, see Changelog file distributed with the cdrkit package. If you
+ * received this file from another source then ask the distributing person for
+ * a log of modifications.
+ *
+ */
+
+/* @(#)mac_label.c 1.9 04/03/05 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */
+/*
+ * Copyright (c) 1997, 1998, 1999, 2000 James Pearson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * mac_label.c: generate Mactintosh partition maps and label
+ *
+ * Taken from "mkisofs 1.05 PLUS" by Andy Polyakov <appro@fy.chalmers.se>
+ * (see http://fy.chalmers.se/~appro/mkisofs_plus.html for details)
+ *
+ * The format of the HFS driver file:
+ *
+ * HFS CD Label Block 512 bytes
+ * Driver Partition Map (for 2048 byte blocks) 512 bytes
+ * Driver Partition Map (for 512 byte blocks) 512 bytes
+ * Empty 512 bytes
+ * Driver Partition N x 2048 bytes
+ * HFS Partition Boot Block 1024 bytes
+ *
+ * File of the above format can be extracted from a CD using
+ * apple_driver.c
+ *
+ * James Pearson 16/5/98
+ */
+
+/* PREP_BOOT Troy Benjegerdes 2/4/99 */
+
+#include <mconfig.h>
+#include "genisoimage.h"
+#include "mac_label.h"
+#include "apple.h"
+
+#ifdef PREP_BOOT
+void gen_prepboot_label(unsigned char *ml);
+
+#endif /* PREP_BOOT */
+int gen_mac_label(defer * mac_boot);
+int autostart(void);
+
+#ifdef PREP_BOOT
+void
+gen_prepboot_label(unsigned char *ml)
+{
+ struct directory_entry *de;
+ int i = 0;
+ int block;
+ int size;
+ MacLabel *mac_label = (MacLabel *) ml;
+
+ if (verbose > 1) {
+ fprintf(stderr, "Creating %d PReP boot partition(s)\n",
+ use_prep_boot + use_chrp_boot);
+ }
+ mac_label->fdiskMagic[0] = fdiskMagic0;
+ mac_label->fdiskMagic[1] = fdiskMagic1;
+
+ if (use_chrp_boot) {
+ fprintf(stderr, "CHRP boot partition 1\n");
+
+ mac_label->image[i].boot = 0x80;
+
+ mac_label->image[i].CHSstart[0] = 0xff;
+ mac_label->image[i].CHSstart[1] = 0xff;
+ mac_label->image[i].CHSstart[2] = 0xff;
+
+ mac_label->image[i].type = chrpPartType; /* 0x96 */
+
+ mac_label->image[i].CHSend[0] = 0xff;
+ mac_label->image[i].CHSend[1] = 0xff;
+ mac_label->image[i].CHSend[2] = 0xff;
+
+ mac_label->image[i].startSect[0] = 0;
+ mac_label->image[i].startSect[1] = 0;
+ mac_label->image[i].startSect[2] = 0;
+ mac_label->image[i].startSect[3] = 0;
+
+ size = (last_extent - session_start) * 2048 / 512;
+ mac_label->image[i].size[0] = size & 0xff;
+ mac_label->image[i].size[1] = (size >> 8) & 0xff;
+ mac_label->image[i].size[2] = (size >> 16) & 0xff;
+ mac_label->image[i].size[3] = (size >> 24) & 0xff;
+
+ i++;
+ }
+
+ for (; i < use_prep_boot + use_chrp_boot; i++) {
+ de = search_tree_file(root, prep_boot_image[i - use_chrp_boot]);
+ if (!de) {
+ fprintf(stderr,
+ "Uh oh, I cant find the boot image \"%s\"!\n",
+ prep_boot_image[i - use_chrp_boot]);
+ exit(1);
+ }
+ /* get size and block in 512-byte blocks */
+ block = get_733(de->isorec.extent) * 2048 / 512;
+ size = get_733(de->isorec.size) / 512 + 1;
+ fprintf(stderr, "PReP boot partition %d is \"%s\"\n",
+ i + 1, prep_boot_image[i - use_chrp_boot]);
+
+ mac_label->image[i].boot = 0x80;
+
+ mac_label->image[i].CHSstart[0] = 0xff;
+ mac_label->image[i].CHSstart[1] = 0xff;
+ mac_label->image[i].CHSstart[2] = 0xff;
+
+ mac_label->image[i].type = prepPartType; /* 0x41 */
+
+ mac_label->image[i].CHSend[0] = 0xff;
+ mac_label->image[i].CHSend[1] = 0xff;
+ mac_label->image[i].CHSend[2] = 0xff;
+
+ /* deal with endianess */
+ mac_label->image[i].startSect[0] = block & 0xff;
+ mac_label->image[i].startSect[1] = (block >> 8) & 0xff;
+ mac_label->image[i].startSect[2] = (block >> 16) & 0xff;
+ mac_label->image[i].startSect[3] = (block >> 24) & 0xff;
+
+ mac_label->image[i].size[0] = size & 0xff;
+ mac_label->image[i].size[1] = (size >> 8) & 0xff;
+ mac_label->image[i].size[2] = (size >> 16) & 0xff;
+ mac_label->image[i].size[3] = (size >> 24) & 0xff;
+ }
+ for (; i < 4; i++) {
+ mac_label->image[i].CHSstart[0] = 0xff;
+ mac_label->image[i].CHSstart[1] = 0xff;
+ mac_label->image[i].CHSstart[2] = 0xff;
+
+ mac_label->image[i].CHSend[0] = 0xff;
+ mac_label->image[i].CHSend[1] = 0xff;
+ mac_label->image[i].CHSend[2] = 0xff;
+ }
+}
+
+#endif /* PREP_BOOT */
+
+int
+gen_mac_label(defer *mac_boot)
+{
+ FILE *fp;
+ MacLabel *mac_label;
+ MacPart *mac_part;
+ char *buffer = (char *) hce->hfs_map;
+ int block_size;
+ int have_hfs_boot = 0;
+ char tmp[SECTOR_SIZE];
+ struct stat stat_buf;
+ mac_partition_table mpm[2];
+ int mpc = 0;
+ int i;
+
+ /* If we have a boot file, then open and check it */
+ if (mac_boot->name) {
+ if (stat(mac_boot->name, &stat_buf) < 0) {
+ sprintf(hce->error, "unable to stat HFS boot file %s",
+ mac_boot->name);
+ return (-1);
+ }
+ if ((fp = fopen(mac_boot->name, "rb")) == NULL) {
+ sprintf(hce->error, "unable to open HFS boot file %s",
+ mac_boot->name);
+ return (-1);
+ }
+ if (fread(tmp, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) {
+ sprintf(hce->error, "unable to read HFS boot file %s",
+ mac_boot->name);
+ return (-1);
+ }
+ /* check we have a bootable partition */
+ mac_part = (MacPart *) (tmp + HFS_BLOCKSZ);
+
+ if (!(IS_MAC_PART(mac_part) &&
+ strncmp((char *) mac_part->pmPartType, pmPartType_2, 12) == 0)) {
+ sprintf(hce->error, "%s is not a HFS boot file",
+ mac_boot->name);
+ return (-1);
+ }
+ /* check we have a boot block as well - last 2 blocks of file */
+
+ if (fseek(fp, (off_t)-2 * HFS_BLOCKSZ, SEEK_END) != 0) {
+ sprintf(hce->error, "unable to seek HFS boot file %s",
+ mac_boot->name);
+ return (-1);
+ }
+ /* overwrite (empty) boot block for our HFS volume */
+ if (fread(hce->hfs_hdr, 2, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ) {
+ sprintf(hce->error, "unable to read HFS boot block %s",
+ mac_boot->name);
+ return (-1);
+ }
+ fclose(fp);
+
+ /* check boot block is valid */
+ if (d_getw((unsigned char *) hce->hfs_hdr) != HFS_BB_SIGWORD) {
+ sprintf(hce->error,
+ "%s does not contain a valid boot block",
+ mac_boot->name);
+ return (-1);
+ }
+ /*
+ * collect info about boot file for later user
+ * - skip over the bootfile header
+ */
+ mac_boot->size = stat_buf.st_size - SECTOR_SIZE - 2*HFS_BLOCKSZ;
+ mac_boot->off = SECTOR_SIZE;
+ mac_boot->pad = 0;
+
+ /*
+ * get size in SECTOR_SIZE blocks
+ * - shouldn't need to round up
+ */
+ mpm[mpc].size = ISO_BLOCKS(mac_boot->size);
+
+ mpm[mpc].ntype = PM2;
+ mpm[mpc].type = (char *) mac_part->pmPartType;
+ mpm[mpc].start = mac_boot->extent = last_extent;
+ mpm[mpc].name = 0;
+
+ /* flag that we have a boot file */
+ have_hfs_boot++;
+
+ /* add boot file size to the total size */
+ last_extent += mpm[mpc].size;
+ hfs_extra += mpm[mpc].size;
+
+ mpc++;
+ }
+ /* set info about our hybrid volume */
+ mpm[mpc].ntype = PM4;
+ mpm[mpc].type = pmPartType_4;
+ mpm[mpc].start = hce->hfs_map_size / HFS_BLK_CONV;
+ mpm[mpc].size = last_extent - mpm[mpc].start -
+ ISO_BLOCKS(mac_boot->size);
+ mpm[mpc].name = volume_id;
+
+ mpc++;
+
+ if (verbose > 1)
+ fprintf(stderr, "Creating HFS Label %s %s\n", mac_boot->name ?
+ "with boot file" : "",
+ mac_boot->name ? mac_boot->name : "");
+
+ /* for a bootable CD, block size is SECTOR_SIZE */
+ block_size = have_hfs_boot ? SECTOR_SIZE : HFS_BLOCKSZ;
+
+ /* create the CD label */
+ mac_label = (MacLabel *) buffer;
+ mac_label->sbSig[0] = 'E';
+ mac_label->sbSig[1] = 'R';
+ set_722((char *) mac_label->sbBlkSize, block_size);
+ set_732((char *) mac_label->sbBlkCount,
+ last_extent * (SECTOR_SIZE / block_size));
+ set_722((char *) mac_label->sbDevType, 1);
+ set_722((char *) mac_label->sbDevId, 1);
+
+ /* create the partition map entry */
+ mac_part = (MacPart *) (buffer + block_size);
+ mac_part->pmSig[0] = 'P';
+ mac_part->pmSig[1] = 'M';
+ set_732((char *) mac_part->pmMapBlkCnt, mpc + 1);
+ set_732((char *) mac_part->pmPyPartStart, 1);
+ set_732((char *) mac_part->pmPartBlkCnt, mpc + 1);
+ strncpy((char *) mac_part->pmPartName, "Apple",
+ sizeof (mac_part->pmPartName));
+ strncpy((char *) mac_part->pmPartType, "Apple_partition_map",
+ sizeof (mac_part->pmPartType));
+ set_732((char *) mac_part->pmLgDataStart, 0);
+ set_732((char *) mac_part->pmDataCnt, mpc + 1);
+ set_732((char *) mac_part->pmPartStatus, PM_STAT_DEFAULT);
+
+ /* create partition map entries for our partitions */
+ for (i = 0; i < mpc; i++) {
+ mac_part = (MacPart *) (buffer + (i + 2) * block_size);
+ if (mpm[i].ntype == PM2) {
+ /* get driver label and patch it */
+ memcpy((char *) mac_label, tmp, HFS_BLOCKSZ);
+ set_732((char *) mac_label->sbBlkCount,
+ last_extent * (SECTOR_SIZE / block_size));
+ set_732((char *) mac_label->ddBlock,
+ (mpm[i].start) * (SECTOR_SIZE / block_size));
+ memcpy((char *) mac_part, tmp + HFS_BLOCKSZ,
+ HFS_BLOCKSZ);
+ set_732((char *) mac_part->pmMapBlkCnt, mpc + 1);
+ set_732((char *) mac_part->pmPyPartStart,
+ (mpm[i].start) * (SECTOR_SIZE / block_size));
+ } else {
+ mac_part->pmSig[0] = 'P';
+ mac_part->pmSig[1] = 'M';
+ set_732((char *) mac_part->pmMapBlkCnt, mpc + 1);
+ set_732((char *) mac_part->pmPyPartStart,
+ mpm[i].start * (SECTOR_SIZE / HFS_BLOCKSZ));
+ set_732((char *) mac_part->pmPartBlkCnt,
+ mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ));
+ strncpy((char *) mac_part->pmPartName, mpm[i].name,
+ sizeof (mac_part->pmPartName));
+ strncpy((char *) mac_part->pmPartType, mpm[i].type,
+ sizeof (mac_part->pmPartType));
+ set_732((char *) mac_part->pmLgDataStart, 0);
+ set_732((char *) mac_part->pmDataCnt,
+ mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ));
+ set_732((char *) mac_part->pmPartStatus,
+ PM_STAT_DEFAULT);
+ }
+ }
+
+ if (have_hfs_boot) { /* generate 512 partition table as well */
+ mac_part = (MacPart *) (buffer + HFS_BLOCKSZ);
+ if (mpc < 3) { /* don't have to interleave with 2048 table */
+ mac_part->pmSig[0] = 'P';
+ mac_part->pmSig[1] = 'M';
+ set_732((char *) mac_part->pmMapBlkCnt, mpc + 1);
+ set_732((char *) mac_part->pmPyPartStart, 1);
+ set_732((char *) mac_part->pmPartBlkCnt, mpc + 1);
+ strncpy((char *) mac_part->pmPartName, "Apple",
+ sizeof (mac_part->pmPartName));
+ strncpy((char *) mac_part->pmPartType,
+ "Apple_partition_map",
+ sizeof (mac_part->pmPartType));
+ set_732((char *) mac_part->pmLgDataStart, 0);
+ set_732((char *) mac_part->pmDataCnt, mpc + 1);
+ set_732((char *) mac_part->pmPartStatus,
+ PM_STAT_DEFAULT);
+ mac_part++; /* +HFS_BLOCKSZ */
+ }
+ for (i = 0; i < mpc; i++, mac_part++) {
+ if (mac_part == (MacPart *) (buffer + SECTOR_SIZE))
+ mac_part++; /* jump over 2048 partition */
+ /* entry */
+ if (mpm[i].ntype == PM2) {
+ memcpy((char *) mac_part, tmp + HFS_BLOCKSZ * 2,
+ HFS_BLOCKSZ);
+ if (!IS_MAC_PART(mac_part)) {
+ mac_part--;
+ continue;
+ }
+ set_732((char *) mac_part->pmMapBlkCnt, mpc+1);
+ set_732((char *) mac_part->pmPyPartStart,
+ mpm[i].start * (SECTOR_SIZE / HFS_BLOCKSZ));
+ } else {
+ mac_part->pmSig[0] = 'P';
+ mac_part->pmSig[1] = 'M';
+ set_732((char *) mac_part->pmMapBlkCnt, mpc+1);
+ set_732((char *) mac_part->pmPyPartStart,
+ mpm[i].start * (SECTOR_SIZE / HFS_BLOCKSZ));
+ set_732((char *) mac_part->pmPartBlkCnt,
+ mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ));
+ strncpy((char *) mac_part->pmPartName,
+ mpm[i].name, sizeof (mac_part->pmPartName));
+ strncpy((char *) mac_part->pmPartType,
+ mpm[i].type, sizeof (mac_part->pmPartType));
+ set_732((char *) mac_part->pmLgDataStart, 0);
+ set_732((char *) mac_part->pmDataCnt,
+ mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ));
+ set_732((char *) mac_part->pmPartStatus,
+ PM_STAT_DEFAULT);
+ }
+ }
+ }
+ return (0);
+}
+
+/*
+ * autostart: make the HFS CD use the QuickTime 2.0 Autostart feature.
+ *
+ * based on information from Eric Eisenhart <eric@sonic.net> and
+ * http://developer.apple.com/qa/qtpc/qtpc12.html and
+ * http://developer.apple.com/dev/techsupport/develop/issue26/macqa.html
+ *
+ * The name of the AutoStart file is stored in the area allocated for
+ * the Clipboard name. This area begins 106 bytes into the sector of
+ * block 0, with the first four bytes at that offset containing the
+ * hex value 0x006A7068. This value indicates that an AutoStart
+ * filename follows. After this 4-byte tag, 12 bytes remain, starting
+ * at offset 110. In these 12 bytes, the name of the AutoStart file is
+ * stored as a Pascal string, giving you up to 11 characters to identify
+ * the file. The file must reside in the root directory of the HFS
+ * volume or partition.
+ */
+
+int
+autostart()
+{
+ int len;
+ int i;
+
+ if ((len = strlen(autoname)) > 11)
+ return (-1);
+
+ hce->hfs_hdr[106] = 0x00;
+ hce->hfs_hdr[107] = 0x6A;
+ hce->hfs_hdr[108] = 0x70;
+ hce->hfs_hdr[109] = 0x68;
+ hce->hfs_hdr[110] = len;
+
+ for (i = 0; i < len; i++)
+ hce->hfs_hdr[111 + i] = autoname[i];
+
+ return (0);
+}