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
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
39 get_722(char *p)
40 {
41 	return ((p[1] & 0xff)
42 	     | ((p[0] & 0xff) << 8));
43 }
44 
45 
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 
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