xref: /openbsd-src/gnu/usr.sbin/mkhybrid/src/apple_driver.c (revision f0d9efc08bdf8f314c206a5c81ebc300245394f8)
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