2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* @(#)mac_label.c 1.9 04/03/05 joerg, Copyright 1997, 1998, 1999, 2000 James Pearson */
15 * Copyright (c) 1997, 1998, 1999, 2000 James Pearson
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)
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.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; see the file COPYING. If not, write to
29 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
33 * mac_label.c: generate Mactintosh partition maps and label
35 * Taken from "mkisofs 1.05 PLUS" by Andy Polyakov <appro@fy.chalmers.se>
36 * (see http://fy.chalmers.se/~appro/mkisofs_plus.html for details)
38 * The format of the HFS driver file:
40 * HFS CD Label Block 512 bytes
41 * Driver Partition Map (for 2048 byte blocks) 512 bytes
42 * Driver Partition Map (for 512 byte blocks) 512 bytes
44 * Driver Partition N x 2048 bytes
45 * HFS Partition Boot Block 1024 bytes
47 * File of the above format can be extracted from a CD using
50 * James Pearson 16/5/98
53 /* PREP_BOOT Troy Benjegerdes 2/4/99 */
56 #include "genisoimage.h"
57 #include "mac_label.h"
61 void gen_prepboot_label(unsigned char *ml);
63 #endif /* PREP_BOOT */
64 int gen_mac_label(defer * mac_boot);
69 gen_prepboot_label(unsigned char *ml)
71 struct directory_entry *de;
75 MacLabel *mac_label = (MacLabel *) ml;
78 fprintf(stderr, "Creating %d PReP boot partition(s)\n",
79 use_prep_boot + use_chrp_boot);
81 mac_label->fdiskMagic[0] = fdiskMagic0;
82 mac_label->fdiskMagic[1] = fdiskMagic1;
85 fprintf(stderr, "CHRP boot partition 1\n");
87 mac_label->image[i].boot = 0x80;
89 mac_label->image[i].CHSstart[0] = 0xff;
90 mac_label->image[i].CHSstart[1] = 0xff;
91 mac_label->image[i].CHSstart[2] = 0xff;
93 mac_label->image[i].type = chrpPartType; /* 0x96 */
95 mac_label->image[i].CHSend[0] = 0xff;
96 mac_label->image[i].CHSend[1] = 0xff;
97 mac_label->image[i].CHSend[2] = 0xff;
99 mac_label->image[i].startSect[0] = 0;
100 mac_label->image[i].startSect[1] = 0;
101 mac_label->image[i].startSect[2] = 0;
102 mac_label->image[i].startSect[3] = 0;
104 size = (last_extent - session_start) * 2048 / 512;
105 mac_label->image[i].size[0] = size & 0xff;
106 mac_label->image[i].size[1] = (size >> 8) & 0xff;
107 mac_label->image[i].size[2] = (size >> 16) & 0xff;
108 mac_label->image[i].size[3] = (size >> 24) & 0xff;
113 for (; i < use_prep_boot + use_chrp_boot; i++) {
114 de = search_tree_file(root, prep_boot_image[i - use_chrp_boot]);
117 "Uh oh, I cant find the boot image \"%s\"!\n",
118 prep_boot_image[i - use_chrp_boot]);
121 /* get size and block in 512-byte blocks */
122 block = get_733(de->isorec.extent) * 2048 / 512;
123 size = get_733(de->isorec.size) / 512 + 1;
124 fprintf(stderr, "PReP boot partition %d is \"%s\"\n",
125 i + 1, prep_boot_image[i - use_chrp_boot]);
127 mac_label->image[i].boot = 0x80;
129 mac_label->image[i].CHSstart[0] = 0xff;
130 mac_label->image[i].CHSstart[1] = 0xff;
131 mac_label->image[i].CHSstart[2] = 0xff;
133 mac_label->image[i].type = prepPartType; /* 0x41 */
135 mac_label->image[i].CHSend[0] = 0xff;
136 mac_label->image[i].CHSend[1] = 0xff;
137 mac_label->image[i].CHSend[2] = 0xff;
139 /* deal with endianess */
140 mac_label->image[i].startSect[0] = block & 0xff;
141 mac_label->image[i].startSect[1] = (block >> 8) & 0xff;
142 mac_label->image[i].startSect[2] = (block >> 16) & 0xff;
143 mac_label->image[i].startSect[3] = (block >> 24) & 0xff;
145 mac_label->image[i].size[0] = size & 0xff;
146 mac_label->image[i].size[1] = (size >> 8) & 0xff;
147 mac_label->image[i].size[2] = (size >> 16) & 0xff;
148 mac_label->image[i].size[3] = (size >> 24) & 0xff;
151 mac_label->image[i].CHSstart[0] = 0xff;
152 mac_label->image[i].CHSstart[1] = 0xff;
153 mac_label->image[i].CHSstart[2] = 0xff;
155 mac_label->image[i].CHSend[0] = 0xff;
156 mac_label->image[i].CHSend[1] = 0xff;
157 mac_label->image[i].CHSend[2] = 0xff;
161 #endif /* PREP_BOOT */
164 gen_mac_label(defer *mac_boot)
169 char *buffer = (char *) hce->hfs_map;
171 int have_hfs_boot = 0;
172 char tmp[SECTOR_SIZE];
173 struct stat stat_buf;
174 mac_partition_table mpm[2];
178 /* If we have a boot file, then open and check it */
179 if (mac_boot->name) {
180 if (stat(mac_boot->name, &stat_buf) < 0) {
181 sprintf(hce->error, "unable to stat HFS boot file %s",
185 if ((fp = fopen(mac_boot->name, "rb")) == NULL) {
186 sprintf(hce->error, "unable to open HFS boot file %s",
190 if (fread(tmp, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) {
191 sprintf(hce->error, "unable to read HFS boot file %s",
195 /* check we have a bootable partition */
196 mac_part = (MacPart *) (tmp + HFS_BLOCKSZ);
198 if (!(IS_MAC_PART(mac_part) &&
199 strncmp((char *) mac_part->pmPartType, pmPartType_2, 12) == 0)) {
200 sprintf(hce->error, "%s is not a HFS boot file",
204 /* check we have a boot block as well - last 2 blocks of file */
206 if (fseek(fp, (off_t)-2 * HFS_BLOCKSZ, SEEK_END) != 0) {
207 sprintf(hce->error, "unable to seek HFS boot file %s",
211 /* overwrite (empty) boot block for our HFS volume */
212 if (fread(hce->hfs_hdr, 2, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ) {
213 sprintf(hce->error, "unable to read HFS boot block %s",
219 /* check boot block is valid */
220 if (d_getw((unsigned char *) hce->hfs_hdr) != HFS_BB_SIGWORD) {
222 "%s does not contain a valid boot block",
227 * collect info about boot file for later user
228 * - skip over the bootfile header
230 mac_boot->size = stat_buf.st_size - SECTOR_SIZE - 2*HFS_BLOCKSZ;
231 mac_boot->off = SECTOR_SIZE;
235 * get size in SECTOR_SIZE blocks
236 * - shouldn't need to round up
238 mpm[mpc].size = ISO_BLOCKS(mac_boot->size);
240 mpm[mpc].ntype = PM2;
241 mpm[mpc].type = (char *) mac_part->pmPartType;
242 mpm[mpc].start = mac_boot->extent = last_extent;
245 /* flag that we have a boot file */
248 /* add boot file size to the total size */
249 last_extent += mpm[mpc].size;
250 hfs_extra += mpm[mpc].size;
254 /* set info about our hybrid volume */
255 mpm[mpc].ntype = PM4;
256 mpm[mpc].type = pmPartType_4;
257 mpm[mpc].start = hce->hfs_map_size / HFS_BLK_CONV;
258 mpm[mpc].size = last_extent - mpm[mpc].start -
259 ISO_BLOCKS(mac_boot->size);
260 mpm[mpc].name = volume_id;
265 fprintf(stderr, "Creating HFS Label %s %s\n", mac_boot->name ?
266 "with boot file" : "",
267 mac_boot->name ? mac_boot->name : "");
269 /* for a bootable CD, block size is SECTOR_SIZE */
270 block_size = have_hfs_boot ? SECTOR_SIZE : HFS_BLOCKSZ;
272 /* create the CD label */
273 mac_label = (MacLabel *) buffer;
274 mac_label->sbSig[0] = 'E';
275 mac_label->sbSig[1] = 'R';
276 set_722((char *) mac_label->sbBlkSize, block_size);
277 set_732((char *) mac_label->sbBlkCount,
278 last_extent * (SECTOR_SIZE / block_size));
279 set_722((char *) mac_label->sbDevType, 1);
280 set_722((char *) mac_label->sbDevId, 1);
282 /* create the partition map entry */
283 mac_part = (MacPart *) (buffer + block_size);
284 mac_part->pmSig[0] = 'P';
285 mac_part->pmSig[1] = 'M';
286 set_732((char *) mac_part->pmMapBlkCnt, mpc + 1);
287 set_732((char *) mac_part->pmPyPartStart, 1);
288 set_732((char *) mac_part->pmPartBlkCnt, mpc + 1);
289 strncpy((char *) mac_part->pmPartName, "Apple",
290 sizeof (mac_part->pmPartName));
291 strncpy((char *) mac_part->pmPartType, "Apple_partition_map",
292 sizeof (mac_part->pmPartType));
293 set_732((char *) mac_part->pmLgDataStart, 0);
294 set_732((char *) mac_part->pmDataCnt, mpc + 1);
295 set_732((char *) mac_part->pmPartStatus, PM_STAT_DEFAULT);
297 /* create partition map entries for our partitions */
298 for (i = 0; i < mpc; i++) {
299 mac_part = (MacPart *) (buffer + (i + 2) * block_size);
300 if (mpm[i].ntype == PM2) {
301 /* get driver label and patch it */
302 memcpy((char *) mac_label, tmp, HFS_BLOCKSZ);
303 set_732((char *) mac_label->sbBlkCount,
304 last_extent * (SECTOR_SIZE / block_size));
305 set_732((char *) mac_label->ddBlock,
306 (mpm[i].start) * (SECTOR_SIZE / block_size));
307 memcpy((char *) mac_part, tmp + HFS_BLOCKSZ,
309 set_732((char *) mac_part->pmMapBlkCnt, mpc + 1);
310 set_732((char *) mac_part->pmPyPartStart,
311 (mpm[i].start) * (SECTOR_SIZE / block_size));
313 mac_part->pmSig[0] = 'P';
314 mac_part->pmSig[1] = 'M';
315 set_732((char *) mac_part->pmMapBlkCnt, mpc + 1);
316 set_732((char *) mac_part->pmPyPartStart,
317 mpm[i].start * (SECTOR_SIZE / HFS_BLOCKSZ));
318 set_732((char *) mac_part->pmPartBlkCnt,
319 mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ));
320 strncpy((char *) mac_part->pmPartName, mpm[i].name,
321 sizeof (mac_part->pmPartName));
322 strncpy((char *) mac_part->pmPartType, mpm[i].type,
323 sizeof (mac_part->pmPartType));
324 set_732((char *) mac_part->pmLgDataStart, 0);
325 set_732((char *) mac_part->pmDataCnt,
326 mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ));
327 set_732((char *) mac_part->pmPartStatus,
332 if (have_hfs_boot) { /* generate 512 partition table as well */
333 mac_part = (MacPart *) (buffer + HFS_BLOCKSZ);
334 if (mpc < 3) { /* don't have to interleave with 2048 table */
335 mac_part->pmSig[0] = 'P';
336 mac_part->pmSig[1] = 'M';
337 set_732((char *) mac_part->pmMapBlkCnt, mpc + 1);
338 set_732((char *) mac_part->pmPyPartStart, 1);
339 set_732((char *) mac_part->pmPartBlkCnt, mpc + 1);
340 strncpy((char *) mac_part->pmPartName, "Apple",
341 sizeof (mac_part->pmPartName));
342 strncpy((char *) mac_part->pmPartType,
343 "Apple_partition_map",
344 sizeof (mac_part->pmPartType));
345 set_732((char *) mac_part->pmLgDataStart, 0);
346 set_732((char *) mac_part->pmDataCnt, mpc + 1);
347 set_732((char *) mac_part->pmPartStatus,
349 mac_part++; /* +HFS_BLOCKSZ */
351 for (i = 0; i < mpc; i++, mac_part++) {
352 if (mac_part == (MacPart *) (buffer + SECTOR_SIZE))
353 mac_part++; /* jump over 2048 partition */
355 if (mpm[i].ntype == PM2) {
356 memcpy((char *) mac_part, tmp + HFS_BLOCKSZ * 2,
358 if (!IS_MAC_PART(mac_part)) {
362 set_732((char *) mac_part->pmMapBlkCnt, mpc+1);
363 set_732((char *) mac_part->pmPyPartStart,
364 mpm[i].start * (SECTOR_SIZE / HFS_BLOCKSZ));
366 mac_part->pmSig[0] = 'P';
367 mac_part->pmSig[1] = 'M';
368 set_732((char *) mac_part->pmMapBlkCnt, mpc+1);
369 set_732((char *) mac_part->pmPyPartStart,
370 mpm[i].start * (SECTOR_SIZE / HFS_BLOCKSZ));
371 set_732((char *) mac_part->pmPartBlkCnt,
372 mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ));
373 strncpy((char *) mac_part->pmPartName,
374 mpm[i].name, sizeof (mac_part->pmPartName));
375 strncpy((char *) mac_part->pmPartType,
376 mpm[i].type, sizeof (mac_part->pmPartType));
377 set_732((char *) mac_part->pmLgDataStart, 0);
378 set_732((char *) mac_part->pmDataCnt,
379 mpm[i].size * (SECTOR_SIZE / HFS_BLOCKSZ));
380 set_732((char *) mac_part->pmPartStatus,
389 * autostart: make the HFS CD use the QuickTime 2.0 Autostart feature.
391 * based on information from Eric Eisenhart <eric@sonic.net> and
392 * http://developer.apple.com/qa/qtpc/qtpc12.html and
393 * http://developer.apple.com/dev/techsupport/develop/issue26/macqa.html
395 * The name of the AutoStart file is stored in the area allocated for
396 * the Clipboard name. This area begins 106 bytes into the sector of
397 * block 0, with the first four bytes at that offset containing the
398 * hex value 0x006A7068. This value indicates that an AutoStart
399 * filename follows. After this 4-byte tag, 12 bytes remain, starting
400 * at offset 110. In these 12 bytes, the name of the AutoStart file is
401 * stored as a Pascal string, giving you up to 11 characters to identify
402 * the file. The file must reside in the root directory of the HFS
403 * volume or partition.
412 if ((len = strlen(autoname)) > 11)
415 hce->hfs_hdr[106] = 0x00;
416 hce->hfs_hdr[107] = 0x6A;
417 hce->hfs_hdr[108] = 0x70;
418 hce->hfs_hdr[109] = 0x68;
419 hce->hfs_hdr[110] = len;
421 for (i = 0; i < len; i++)
422 hce->hfs_hdr[111 + i] = autoname[i];