1*f0d9efc0Sbeck /*
2*f0d9efc0Sbeck ** apple_driver.c: extract Mac partition label, maps and boot driver
3*f0d9efc0Sbeck **
4*f0d9efc0Sbeck ** Based on Apple_Driver.pl, part of "mkisofs 1.05 PLUS" by Andy Polyakov
5*f0d9efc0Sbeck ** <appro@fy.chalmers.se> (I don't know Perl, so I rewrote it C ...)
6*f0d9efc0Sbeck ** (see http://fy.chalmers.se/~appro/mkisofs_plus.html for details)
7*f0d9efc0Sbeck **
8*f0d9efc0Sbeck ** usage: apple_driver CDROM_device > HFS_driver_file
9*f0d9efc0Sbeck **
10*f0d9efc0Sbeck ** The format of the HFS driver file:
11*f0d9efc0Sbeck **
12*f0d9efc0Sbeck ** HFS CD Label Block 512 bytes
13*f0d9efc0Sbeck ** Driver Partition Map (for 2048 byte blocks) 512 bytes
14*f0d9efc0Sbeck ** Driver Partition Map (for 512 byte blocks) 512 bytes
15*f0d9efc0Sbeck ** Empty 512 bytes
16*f0d9efc0Sbeck ** Driver Partition N x 2048 bytes
17*f0d9efc0Sbeck ** HFS Partition Boot Block 1024 bytes
18*f0d9efc0Sbeck **
19*f0d9efc0Sbeck ** By extracting a driver from an Apple CD, you become liable to obey
20*f0d9efc0Sbeck ** Apple Computer, Inc. Software License Agreements.
21*f0d9efc0Sbeck **
22*f0d9efc0Sbeck ** James Pearson 17/5/98
23*f0d9efc0Sbeck */
24*f0d9efc0Sbeck
25*f0d9efc0Sbeck #include <config.h>
26*f0d9efc0Sbeck #include <mkisofs.h>
27*f0d9efc0Sbeck #include <mac_label.h>
28*f0d9efc0Sbeck
29*f0d9efc0Sbeck int
get_732(char * p)30*f0d9efc0Sbeck get_732(char *p)
31*f0d9efc0Sbeck {
32*f0d9efc0Sbeck return ((p[3] & 0xff)
33*f0d9efc0Sbeck | ((p[2] & 0xff) << 8)
34*f0d9efc0Sbeck | ((p[1] & 0xff) << 16)
35*f0d9efc0Sbeck | ((p[0] & 0xff) << 24));
36*f0d9efc0Sbeck }
37*f0d9efc0Sbeck
38*f0d9efc0Sbeck int
get_722(char * p)39*f0d9efc0Sbeck get_722(char *p)
40*f0d9efc0Sbeck {
41*f0d9efc0Sbeck return ((p[1] & 0xff)
42*f0d9efc0Sbeck | ((p[0] & 0xff) << 8));
43*f0d9efc0Sbeck }
44*f0d9efc0Sbeck
45*f0d9efc0Sbeck
main(int argc,char ** argv)46*f0d9efc0Sbeck main(int argc, char **argv)
47*f0d9efc0Sbeck {
48*f0d9efc0Sbeck FILE *fp;
49*f0d9efc0Sbeck MacLabel *mac_label;
50*f0d9efc0Sbeck MacPart *mac_part;
51*f0d9efc0Sbeck unsigned char Block0[HFS_BLOCKSZ];
52*f0d9efc0Sbeck unsigned char block[SECTOR_SIZE];
53*f0d9efc0Sbeck unsigned char bootb[2*HFS_BLOCKSZ];
54*f0d9efc0Sbeck unsigned char pmBlock512[HFS_BLOCKSZ];
55*f0d9efc0Sbeck unsigned int sbBlkSize;
56*f0d9efc0Sbeck unsigned int pmPyPartStart;
57*f0d9efc0Sbeck unsigned int pmPartStatus;
58*f0d9efc0Sbeck unsigned int pmMapBlkCnt;
59*f0d9efc0Sbeck int have_boot = 0, have_hfs = 0;
60*f0d9efc0Sbeck int hfs_start;
61*f0d9efc0Sbeck int i, j;
62*f0d9efc0Sbeck
63*f0d9efc0Sbeck
64*f0d9efc0Sbeck if (argc != 2)
65*f0d9efc0Sbeck perr(argv[0], "Usage: %s device-path", argv[0]);
66*f0d9efc0Sbeck
67*f0d9efc0Sbeck if ((fp = fopen(argv[1], "rb")) == NULL)
68*f0d9efc0Sbeck perr(argv[0], "can't open %s", argv[1]);
69*f0d9efc0Sbeck
70*f0d9efc0Sbeck if (fread(Block0, 1, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ)
71*f0d9efc0Sbeck perr(argv[0], "can't read %s", argv[1]);
72*f0d9efc0Sbeck
73*f0d9efc0Sbeck mac_label = (MacLabel *)Block0;
74*f0d9efc0Sbeck mac_part = (MacPart *)block;
75*f0d9efc0Sbeck
76*f0d9efc0Sbeck sbBlkSize = get_722(mac_label->sbBlkSize);
77*f0d9efc0Sbeck
78*f0d9efc0Sbeck if (! IS_MAC_LABEL(mac_label) || sbBlkSize != SECTOR_SIZE)
79*f0d9efc0Sbeck perr(argv[0], "%s is not a bootable Mac disk", argv[1]);
80*f0d9efc0Sbeck
81*f0d9efc0Sbeck i = 1;
82*f0d9efc0Sbeck do {
83*f0d9efc0Sbeck if (fseek(fp, i * HFS_BLOCKSZ, 0) != 0)
84*f0d9efc0Sbeck perr(argv[0], "can't seek %s", argv[1]);
85*f0d9efc0Sbeck
86*f0d9efc0Sbeck if (fread(block, 1, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ)
87*f0d9efc0Sbeck perr(argv[0], "can't read %s", argv[1]);
88*f0d9efc0Sbeck
89*f0d9efc0Sbeck pmMapBlkCnt = get_732(mac_part->pmMapBlkCnt);
90*f0d9efc0Sbeck
91*f0d9efc0Sbeck if (!have_boot && !strncmp(mac_part->pmPartType, pmPartType_2, 12)) {
92*f0d9efc0Sbeck hfs_start = get_732(mac_part->pmPyPartStart);
93*f0d9efc0Sbeck
94*f0d9efc0Sbeck fprintf(stderr, "%s: found 512 driver partition (at block %d)\n", argv[0], hfs_start);
95*f0d9efc0Sbeck memcpy(pmBlock512, block, HFS_BLOCKSZ);
96*f0d9efc0Sbeck have_boot = 1;
97*f0d9efc0Sbeck }
98*f0d9efc0Sbeck
99*f0d9efc0Sbeck if (!have_hfs && !strncmp(mac_part->pmPartType, pmPartType_4, 9)) {
100*f0d9efc0Sbeck
101*f0d9efc0Sbeck hfs_start = get_732(mac_part->pmPyPartStart);
102*f0d9efc0Sbeck
103*f0d9efc0Sbeck if (fseek(fp, hfs_start*HFS_BLOCKSZ, 0) != 0)
104*f0d9efc0Sbeck perr(argv[0], "can't seek %s", argv[1]);
105*f0d9efc0Sbeck
106*f0d9efc0Sbeck if (fread(bootb, 2, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ)
107*f0d9efc0Sbeck perr(argv[0], "can't read %s", argv[1]);
108*f0d9efc0Sbeck
109*f0d9efc0Sbeck if (get_722(bootb) == 0x4c4b) {
110*f0d9efc0Sbeck
111*f0d9efc0Sbeck fprintf(stderr, "%s: found HFS partition (at blk %d)\n", argv[0], hfs_start);
112*f0d9efc0Sbeck have_hfs = 1;
113*f0d9efc0Sbeck }
114*f0d9efc0Sbeck }
115*f0d9efc0Sbeck } while (i++ < pmMapBlkCnt);
116*f0d9efc0Sbeck
117*f0d9efc0Sbeck if (!have_hfs || !have_boot)
118*f0d9efc0Sbeck perr(argv[0], "%s is not a bootable Mac disk", argv[1]);
119*f0d9efc0Sbeck
120*f0d9efc0Sbeck i = 1;
121*f0d9efc0Sbeck
122*f0d9efc0Sbeck do {
123*f0d9efc0Sbeck if (fseek(fp, i*sbBlkSize, 0) != 0)
124*f0d9efc0Sbeck perr(argv[0], "can't seek %s", argv[1]);
125*f0d9efc0Sbeck
126*f0d9efc0Sbeck if (fread(block, 1, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ)
127*f0d9efc0Sbeck perr(argv[0], "can't read %s", argv[1]);
128*f0d9efc0Sbeck
129*f0d9efc0Sbeck pmMapBlkCnt = get_732(mac_part->pmMapBlkCnt);
130*f0d9efc0Sbeck
131*f0d9efc0Sbeck if (!strncmp(mac_part->pmPartType, pmPartType_2, 12)) {
132*f0d9efc0Sbeck
133*f0d9efc0Sbeck int start, num;
134*f0d9efc0Sbeck
135*f0d9efc0Sbeck fprintf(stderr, "%s: extracting %s ", argv[0], mac_part->pmPartType);
136*f0d9efc0Sbeck start = get_732(mac_part->pmPyPartStart);
137*f0d9efc0Sbeck num = get_732(mac_part->pmPartBlkCnt);
138*f0d9efc0Sbeck fwrite(Block0, 1, HFS_BLOCKSZ, stdout);
139*f0d9efc0Sbeck fwrite(block, 1, HFS_BLOCKSZ, stdout);
140*f0d9efc0Sbeck fwrite(pmBlock512, 1, HFS_BLOCKSZ, stdout);
141*f0d9efc0Sbeck memset(block, 0, HFS_BLOCKSZ);
142*f0d9efc0Sbeck fwrite(block, 1, HFS_BLOCKSZ, stdout);
143*f0d9efc0Sbeck
144*f0d9efc0Sbeck if (fseek(fp, start*sbBlkSize, 0) != 0)
145*f0d9efc0Sbeck perr(argv[0], "can't seek %s", argv[1]);
146*f0d9efc0Sbeck
147*f0d9efc0Sbeck for (j=0;j<num;j++) {
148*f0d9efc0Sbeck if (fread(block, 1, sbBlkSize, fp) != sbBlkSize)
149*f0d9efc0Sbeck perr(argv[0], "can't read %s", argv[1]);
150*f0d9efc0Sbeck
151*f0d9efc0Sbeck fwrite(block, 1, sbBlkSize, stdout);
152*f0d9efc0Sbeck fprintf(stderr, ".");
153*f0d9efc0Sbeck }
154*f0d9efc0Sbeck fprintf(stderr, "\n");
155*f0d9efc0Sbeck
156*f0d9efc0Sbeck fwrite(bootb, 2, HFS_BLOCKSZ, stdout);
157*f0d9efc0Sbeck fclose(fp);
158*f0d9efc0Sbeck exit (0);
159*f0d9efc0Sbeck }
160*f0d9efc0Sbeck
161*f0d9efc0Sbeck if (! IS_MAC_PART(mac_part) )
162*f0d9efc0Sbeck perr(argv[0], "unable to find boot partition", 0);
163*f0d9efc0Sbeck
164*f0d9efc0Sbeck } while (i++ < pmMapBlkCnt);
165*f0d9efc0Sbeck
166*f0d9efc0Sbeck
167*f0d9efc0Sbeck }
168*f0d9efc0Sbeck
perr(char * a,char * b,char * c)169*f0d9efc0Sbeck perr(char *a, char *b, char *c)
170*f0d9efc0Sbeck {
171*f0d9efc0Sbeck fprintf(stderr, "%s: ", a);
172*f0d9efc0Sbeck fprintf(stderr, b, c);
173*f0d9efc0Sbeck fprintf(stderr, "\n");
174*f0d9efc0Sbeck exit (1);
175*f0d9efc0Sbeck }
176