1 /* @(#)apple_driver.c	1.10 17/07/17 joerg */
2 #ifndef lint
3 static	char sccsid[] =
4 	"@(#)apple_driver.c	1.10 17/07/17 joerg";
5 #endif
6 /*
7  *	apple_driver.c: extract Mac partition label, maps and boot driver
8  *
9  *	Based on Apple_Driver.pl, part of "mkisofs 1.05 PLUS" by Andy Polyakov
10  *	<appro@fy.chalmers.se> (I don't know Perl, so I rewrote it C ...)
11  *	(see http://fy.chalmers.se/~appro/mkisofs_plus.html for details)
12  *
13  *	usage: apple_driver CDROM_device > HFS_driver_file
14  *
15  *	The format of the HFS driver file:
16  *
17  *	HFS CD Label Block				512 bytes
18  *	Driver Partition Map (for 2048 byte blocks)	512 bytes
19  *	Driver Partition Map (for 512 byte blocks)	512 bytes
20  *	Empty						512 bytes
21  *	Driver Partition				N x 2048 bytes
22  *	HFS Partition Boot Block			1024 bytes
23  *
24  *	By extracting a driver from an Apple CD, you become liable to obey
25  *	Apple Computer, Inc. Software License Agreements.
26  *
27  *	James Pearson 17/5/98
28  *	Copyright (c) 1998-2010,2017 J. Schilling
29  */
30 
31 #include <schily/mconfig.h>
32 #include "mkisofs.h"
33 #include "mac_label.h"
34 #include <schily/schily.h>
35 
36 EXPORT	UInt32_t	get_732	__PR((void *vp));
37 EXPORT	UInt32_t	get_722	__PR((void *vp));
38 EXPORT	int		main	__PR((int argc, char **argv));
39 
40 EXPORT UInt32_t
get_732(vp)41 get_732(vp)
42 	void	*vp;
43 {
44 	Uchar	*p = vp;
45 
46 	return ((p[3] & 0xff)
47 		| ((p[2] & 0xff) << 8)
48 		| ((p[1] & 0xff) << 16)
49 		| ((p[0] & 0xff) << 24));
50 }
51 
52 EXPORT UInt32_t
get_722(vp)53 get_722(vp)
54 	void	*vp;
55 {
56 	Uchar	*p = vp;
57 
58 	return ((p[1] & 0xff)
59 		| ((p[0] & 0xff) << 8));
60 }
61 
62 EXPORT int
main(argc,argv)63 main(argc, argv)
64 	int	argc;
65 	char	**argv;
66 {
67 	FILE		*fp;
68 	MacLabel	*mac_label;
69 	MacPart		*mac_part;
70 #if	defined(USE_NLS)
71 	char		*dir;
72 #endif
73 	unsigned char	Block0[HFS_BLOCKSZ];
74 	unsigned char	block[SECTOR_SIZE];
75 	unsigned char	bootb[2*HFS_BLOCKSZ];
76 	unsigned char	pmBlock512[HFS_BLOCKSZ];
77 	unsigned int	sbBlkSize;
78 	unsigned int	pmPyPartStart;
79 	unsigned int	pmPartStatus;
80 	unsigned int	pmMapBlkCnt;
81 	int		have_boot = 0, have_hfs = 0;
82 	int		hfs_start;
83 	int		i, j;
84 
85 
86 	save_args(argc, argv);
87 
88 	(void) setlocale(LC_ALL, "");
89 
90 #if	defined(USE_NLS)
91 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
92 #define	TEXT_DOMAIN "mkisofs"	/* Use this only if it weren't */
93 #endif
94 	dir = searchfileinpath("share/locale", F_OK,
95 					SIP_ANY_FILE|SIP_NO_PATH, NULL);
96 	if (dir)
97 		(void) bindtextdomain(TEXT_DOMAIN, dir);
98 	else
99 #ifdef	PROTOTYPES
100 	(void) bindtextdomain(TEXT_DOMAIN, INS_BASE "/share/locale");
101 #else
102 	(void) bindtextdomain(TEXT_DOMAIN, "/usr/share/locale");
103 #endif
104 	(void) textdomain(TEXT_DOMAIN);
105 #endif
106 
107 	if (argc != 2)
108 	    comerrno(EX_BAD, _("Usage: %s device-path\n"), argv[0]);
109 
110 	if ((fp = fopen(argv[1], "rb")) == NULL)
111 	    comerr(_("Can't open '%s'.\n"), argv[1]);
112 
113 	if (fread(Block0, 1, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ)
114 	    comerr(_("Can't read '%s'.\n"), argv[1]);
115 
116 	mac_label = (MacLabel *)Block0;
117 	mac_part = (MacPart *)block;
118 
119 	sbBlkSize = get_722(mac_label->sbBlkSize);
120 
121 	if (! IS_MAC_LABEL(mac_label) || sbBlkSize != SECTOR_SIZE)
122 	    comerrno(EX_BAD, _("%s is not a bootable Mac disk.\n"), argv[1]);
123 
124 	i = 1;
125 	do {
126 		if (fseek(fp, i * HFS_BLOCKSZ, SEEK_SET) != 0)
127 			comerr(_("Can't seek '%s'.\n"), argv[1]);
128 
129 		if (fread(block, 1, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ)
130 			comerr(_("Can't read '%s'.\n"), argv[1]);
131 
132 		pmMapBlkCnt = get_732(mac_part->pmMapBlkCnt);
133 
134 		if (!have_boot && strncmp((char *)mac_part->pmPartType, pmPartType_2, 12) == 0) {
135 			hfs_start = get_732(mac_part->pmPyPartStart);
136 
137 			fprintf(stderr, _("%s: found 512 driver partition (at block %d).\n"), argv[0], hfs_start);
138 			memcpy(pmBlock512, block, HFS_BLOCKSZ);
139 			have_boot = 1;
140 		}
141 
142 		if (!have_hfs && strncmp((char *)mac_part->pmPartType, pmPartType_4, 9) == 0) {
143 
144 			hfs_start = get_732(mac_part->pmPyPartStart);
145 
146 			if (fseek(fp, hfs_start*HFS_BLOCKSZ, SEEK_SET) != 0)
147 				comerr(_("Can't seek '%s'.\n"), argv[1]);
148 
149 			if (fread(bootb, 2, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ)
150 				comerr(_("Can't read '%s'.\n"), argv[1]);
151 
152 			if (get_722(bootb) == 0x4c4b) {
153 
154 				fprintf(stderr, _("%s: found HFS partition (at blk %d).\n"), argv[0], hfs_start);
155 				have_hfs = 1;
156 			}
157 		}
158 	} while (i++ < pmMapBlkCnt);
159 
160 	if (!have_hfs || !have_boot)
161 		comerrno(EX_BAD, _("%s is not a bootable Mac disk.\n"), argv[1]);
162 
163 	i = 1;
164 
165 	do {
166 		if (fseek(fp, i*sbBlkSize, SEEK_SET) != 0)
167 			comerr(_("Can't seek '%s'.\n"), argv[1]);
168 
169 		if (fread(block, 1, HFS_BLOCKSZ, fp) != HFS_BLOCKSZ)
170 			comerr(_("Can't read '%s'.\n"), argv[1]);
171 
172 		pmMapBlkCnt = get_732(mac_part->pmMapBlkCnt);
173 
174 		if (strncmp((char *)mac_part->pmPartType, pmPartType_2, 12) == 0) {
175 
176 			int	start, num;
177 
178 			fprintf(stderr, _("%s: extracting %s "), argv[0], mac_part->pmPartType);
179 			start = get_732(mac_part->pmPyPartStart);
180 			num = get_732(mac_part->pmPartBlkCnt);
181 			fwrite(Block0, 1, HFS_BLOCKSZ, stdout);
182 			fwrite(block, 1, HFS_BLOCKSZ, stdout);
183 			fwrite(pmBlock512, 1, HFS_BLOCKSZ, stdout);
184 			memset(block, 0, HFS_BLOCKSZ);
185 			fwrite(block, 1, HFS_BLOCKSZ, stdout);
186 
187 			if (fseek(fp, start*sbBlkSize, SEEK_SET) != 0)
188 				comerr(_("Can't seek '%s'.\n"), argv[1]);
189 
190 			for (j = 0; j < num; j++) {
191 				if (fread(block, 1, sbBlkSize, fp) != sbBlkSize)
192 					comerr(_("Can't read '%s'.\n"), argv[1]);
193 
194 				fwrite(block, 1, sbBlkSize, stdout);
195 				fprintf(stderr, ".");
196 			}
197 			fprintf(stderr, "\n");
198 
199 			fwrite(bootb, 2, HFS_BLOCKSZ, stdout);
200 			fclose(fp);
201 			exit(0);
202 		}
203 
204 		if (!IS_MAC_PART(mac_part))
205 			comerrno(EX_BAD, _("Unable to find boot partition.\n"));
206 
207 	} while (i++ < pmMapBlkCnt);
208 
209 	fclose(fp);
210 	return (0);
211 }
212