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