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