tuxsavvy / agere_fw_utils (public) (License: Dual BSD 3-clause and GPLv2) (since 2021-02-07) (hash sha1)
Personal fork of https://repo.or.cz/agere_fw_utils.git
List of commits:
Subject Hash Author Date (UTC)
Further refactorring. Also pass through splint and indent. 29e550703e7ef9b083b22d11c3bb470ff54b6ab0 David Kilroy 2008-10-26 14:44:25
Convert primary plugdata properly 933f77d11ca6645df705c4b71c471aa670fccaf3 David Kilroy 2008-10-26 14:39:28
Convert AirPort firmware version 1f31f74c58179b099005ae939eff9bb467317b5b David Kilroy 2008-10-26 14:37:57
Mach-O parsing from Dan Williams 525f9168679392920da51d2487cc5fdba3c68e2c David Kilroy 2008-10-26 14:34:59
Check if we are in wl_lkm tree and build appropriately 4af298b374a1dea172b57acbd080773912d22087 David Kilroy 2008-10-26 14:30:33
Use C99 types 11362c209f9ec7369931b9a25a407c21476c48e4 David Kilroy 2008-10-26 14:30:03
hfwget refactorring posted as hfwget2 April 2008 9b77acdf3330592acda5261d282c579cc1497637 David Kilroy 2008-10-26 14:27:32
dump_fw and hfwget posted Sep 2007 77d205076542510222c6e8359bb2647b0d4e0873 David Kilroy 2008-10-26 14:22:02
Add hfwget.c from hermesap-0.2 9239c21487b524cf0f87b4ffa4828793713fbecd David Kilroy 2008-10-26 14:20:38
dump_fw posted June 2007 617a0ae960430d0d93a533ac5dffc7b9c07a777a David Kilroy 2008-10-26 14:19:45
Commit 29e550703e7ef9b083b22d11c3bb470ff54b6ab0 - Further refactorring. Also pass through splint and indent.
Author: David Kilroy
Author date (UTC): 2008-10-26 14:44
Committer name: David Kilroy
Committer date (UTC): 2008-10-26 14:44
Parent(s): 933f77d11ca6645df705c4b71c471aa670fccaf3
Signing key:
Tree: 93826492f0cc2038793f5b6a4d8a49b8e65bb36a
File Lines added Lines deleted
hfwget.c 547 439
File hfwget.c changed (mode: 100644) (index 54d1546..9b9f2fc)
3 3 * This may be distributed freely under the GPL v2 so long as this copyright * This may be distributed freely under the GPL v2 so long as this copyright
4 4 * notice is included. * notice is included.
5 5 * *
6 * Following modifications (c) 2007 David Kilroy
6 * Following modifications (c) 2008 David Kilroy
7 7 * primary plug data * primary plug data
8 8 * compatibility info * compatibility info
9 9 * firmware identification * firmware identification
 
22 22 #include <memory.h> #include <memory.h>
23 23 #include <string.h> #include <string.h>
24 24
25 #define false 0
26 #define true (!0)
25 #if __STDC_VERSION__>=199901L
26 # include <stdbool.h>
27 #else
28 typedef int bool;
29
30 # define false 0
31 # define true (!0)
32 #endif
27 33
28 34 /* Typedefs for little and big endian values */ /* Typedefs for little and big endian values */
29 35 typedef uint32_t __le32; typedef uint32_t __le32;
 
... ... typedef uint16_t __le16;
31 37 typedef uint32_t __be32; typedef uint32_t __be32;
32 38 typedef uint16_t __be16; typedef uint16_t __be16;
33 39
40 /* Driver endianness */
41 typedef uint32_t __de32;
42 typedef uint16_t __de16;
43
44
34 45 /* Typedefs for sized integers */ /* Typedefs for sized integers */
35 46 typedef uint32_t u32; typedef uint32_t u32;
36 47 typedef uint16_t u16; typedef uint16_t u16;
37 typedef uint8_t u8;
48 typedef uint8_t u8;
49
50 #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
38 51
39 52 /*** Macros to deal with different endianess ***/ /*** Macros to deal with different endianess ***/
40 53
 
... ... typedef uint8_t u8;
42 55 #define swap_bytes_16(value) \ #define swap_bytes_16(value) \
43 56 ((((value) >> 8) & 0xFF) | \ ((((value) >> 8) & 0xFF) | \
44 57 (((value) & 0xFF) << 8)) (((value) & 0xFF) << 8))
58
45 59 /* 0xAABBCCDD to 0xDDCCBBAA */ /* 0xAABBCCDD to 0xDDCCBBAA */
46 60 #define reverse_bytes_32(value) \ #define reverse_bytes_32(value) \
47 61 ((((value) >> 24) & 0x0000FF) | \ ((((value) >> 24) & 0x0000FF) | \
48 62 (((value) >> 8) & 0x00FF00) | \ (((value) >> 8) & 0x00FF00) | \
49 63 (((value) << 8) & 0xFF0000) | \ (((value) << 8) & 0xFF0000) | \
50 64 (((value) & 0xFF) << 24)) (((value) & 0xFF) << 24))
65
51 66 /* 0xAABBCCDD to 0xBBAADDCC */ /* 0xAABBCCDD to 0xBBAADDCC */
52 67 #define swap_bytes_32(value) \ #define swap_bytes_32(value) \
53 68 ((((value) >> 8) & 0x00FF00FF) | \ ((((value) >> 8) & 0x00FF00FF) | \
54 69 (((value) << 8) & 0xFF00FF00)) (((value) << 8) & 0xFF00FF00))
70
55 71 /* 0xAABBCCDD to 0xCCDDAABB */ /* 0xAABBCCDD to 0xCCDDAABB */
56 72 #define swap_words_32(value) \ #define swap_words_32(value) \
57 73 ((((value) >> 16) & 0x0000FFFF) | \ ((((value) >> 16) & 0x0000FFFF) | \
58 74 (((value) << 16) & 0xFFFF0000)) (((value) << 16) & 0xFFFF0000))
59 75
60 /* address 0 1 2 3 */
61 /* Pure LE stores 0x12345678 as 0x78 0x56 0x34 0x12 */
62 /* Pure BE stores 0x12345678 as 0x12 0x34 0x56 0x78 */
63 /* BEW+LEB stores 0x12345678 as 0x34 0x12 0x78 0x56 */
64 /* LEW+BEB stores 0x12345678 as 0x56 0x78 0x12 0x34 */
65 static int host_bytes_in_word_be = 0;
66 static int host_words_in_dword_be = 0;
67 static int driver_is_be = 0;
76 /* address -> 0 1 2 3
77 * Pure LE stores 0x12345678 as 0x78 0x56 0x34 0x12
78 * Pure BE stores 0x12345678 as 0x12 0x34 0x56 0x78
79 * BEW+LEB stores 0x12345678 as 0x34 0x12 0x78 0x56
80 * LEW+BEB stores 0x12345678 as 0x56 0x78 0x12 0x34
81 */
82 static bool host_bytes_in_word_be = false;
83 static bool host_words_in_dword_be = false;
84 static bool driver_is_be = false;
68 85
69 #define host_to_le16(value) \
86 #define host_to_le16(value) (__le16) \
70 87 (host_bytes_in_word_be ? swap_bytes_16(value) : (value)) (host_bytes_in_word_be ? swap_bytes_16(value) : (value))
71 #define host_to_le32(value) \
72 (host_words_in_dword_be ? \
88 #define host_to_le32(value) (__le32) \
89 (host_words_in_dword_be ? \
73 90 (host_bytes_in_word_be ? reverse_bytes_32(value) \ (host_bytes_in_word_be ? reverse_bytes_32(value) \
74 91 : swap_bytes_32(value)) : \ : swap_bytes_32(value)) : \
75 92 (host_bytes_in_word_be ? swap_words_32(value) : (value))) (host_bytes_in_word_be ? swap_words_32(value) : (value)))
76 93
77 #define le16_to_host(value) \
94 #define le16_to_host(value) (u16) \
78 95 (host_bytes_in_word_be ? swap_bytes_16(value) : (value)) (host_bytes_in_word_be ? swap_bytes_16(value) : (value))
79 #define le32_to_host(value) \
80 (host_words_in_dword_be ? \
96 #define le32_to_host(value) (u32) \
97 (host_words_in_dword_be ? \
81 98 (host_bytes_in_word_be ? reverse_bytes_32(value) \ (host_bytes_in_word_be ? reverse_bytes_32(value) \
82 99 : swap_bytes_32(value)) : \ : swap_bytes_32(value)) : \
83 100 (host_bytes_in_word_be ? swap_words_32(value) : (value))) (host_bytes_in_word_be ? swap_words_32(value) : (value)))
84 101
85 #define host_to_be16(value) \
102 #define host_to_be16(value) (__be16) \
86 103 (host_bytes_in_word_be ? (value) : swap_bytes_16(value)) (host_bytes_in_word_be ? (value) : swap_bytes_16(value))
87 #define host_to_be32(value) \
88 (host_words_in_dword_be ? \
104 #define host_to_be32(value) (__be32) \
105 (host_words_in_dword_be ? \
89 106 (host_bytes_in_word_be ? (value) : swap_bytes_32(value)) : \ (host_bytes_in_word_be ? (value) : swap_bytes_32(value)) : \
90 107 (host_bytes_in_word_be ? swap_words_32(value) \ (host_bytes_in_word_be ? swap_words_32(value) \
91 108 : reverse_bytes_32(value))) : reverse_bytes_32(value)))
92 109
93 #define be16_to_host(value) \
110 #define be16_to_host(value) (u16) \
94 111 (host_bytes_in_word_be ? (value) : swap_bytes_16(value)) (host_bytes_in_word_be ? (value) : swap_bytes_16(value))
95 #define be32_to_host(value) \
96 (host_words_in_dword_be ? \
112 #define be32_to_host(value) (u32) \
113 (host_words_in_dword_be ? \
97 114 (host_bytes_in_word_be ? (value) : swap_bytes_32(value)) : \ (host_bytes_in_word_be ? (value) : swap_bytes_32(value)) : \
98 115 (host_bytes_in_word_be ? swap_words_32(value) \ (host_bytes_in_word_be ? swap_words_32(value) \
99 116 : reverse_bytes_32(value))) : reverse_bytes_32(value)))
100 117
101 #define driver_to_host_16(value) \
118 #define driver_to_host_16(value) (u16) \
102 119 (driver_is_be ? be16_to_host(value) : le16_to_host(value)) (driver_is_be ? be16_to_host(value) : le16_to_host(value))
103 #define driver_to_host_32(value) \
120 #define driver_to_host_32(value) (u32) \
104 121 (driver_is_be ? be32_to_host(value) : le32_to_host(value)) (driver_is_be ? be32_to_host(value) : le32_to_host(value))
105 #define host_to_driver_16(value) \
122 #define host_to_driver_16(value) (__de16) \
106 123 (driver_is_be ? host_to_be16(value) : host_to_le16(value)) (driver_is_be ? host_to_be16(value) : host_to_le16(value))
107 #define host_to_driver_32(value) \
124 #define host_to_driver_32(value) (__de32) \
108 125 (driver_is_be ? host_to_be32(value) : host_to_le32(value)) (driver_is_be ? host_to_be32(value) : host_to_le32(value))
109 126
110 127 /**** Structures to read image data from driver ****/ /**** Structures to read image data from driver ****/
111 128
112 /* Decode the windows firmware blocks */
129 /* Decode Windows firmware blocks */
113 130 struct fwblock_wdrv { struct fwblock_wdrv {
114 131 __le32 offset; __le32 offset;
115 132 __le16 size; __le16 size;
 
... ... struct fwblock_wdrv {
117 134 __le32 data_p; __le32 data_p;
118 135 }; };
119 136
120 /* Decode the mac firmware blocks */
137 /* Decode Mac firmware blocks */
121 138 struct fwblock_mdrv { struct fwblock_mdrv {
122 139 __be16 len; __be16 len;
123 140 __be16 code; __be16 code;
 
... ... struct fwblock_mdrv {
128 145 __be32 data_p; __be32 data_p;
129 146 }; };
130 147
131 struct _plugarray {
132 __le32 code;
133 __le32 targ_off;
134 __le32 length;
148 union fwblock_drv {
149 struct fwblock_wdrv *w;
150 struct fwblock_mdrv *m;
135 151 }; };
136 152
137 struct _ident_info {
138 __le16 size;
139 __le16 code;
140 __le16 comp_id;
141 __le16 variant;
142 __le16 version_major;
143 __le16 version_minor;
153 struct plugarray_drv {
154 __de32 code;
155 __de32 targ_off;
156 __de32 length;
144 157 }; };
145 158
146 struct _compat_info {
147 __le16 size;
148 __le16 code;
149 __le16 role;
150 __le16 id;
151 struct
152 {
153 __le16 variant;
154 __le16 bottom;
155 __le16 top;
159 struct ident_info_drv {
160 __de16 size;
161 __de16 code;
162 __de16 comp_id;
163 __de16 variant;
164 __de16 version_major;
165 __de16 version_minor;
166 };
167
168 struct compat_info_drv {
169 __de16 size;
170 __de16 code;
171 __de16 role;
172 __de16 id;
173 struct {
174 __de16 variant;
175 __de16 bottom;
176 __de16 top;
156 177 } range[20]; } range[20];
157 178 }; };
158 179
159 180 struct fwtable_drv { struct fwtable_drv {
160 __le32 segarray_p;
161 __le32 halfentry;
162 __le32 plugarray_p;
163 __le32 pri_plugarray_p;
164 __le32 compat_p;
165 __le32 ident_p;
181 __de32 segarray_p;
182 __de32 halfentry;
183 __de32 plugarray_p;
184 __de32 pri_plugarray_p;
185 __de32 compat_p;
186 __de32 ident_p;
166 187 }; };
167 188
168 189 /*** Structures to use on host. ***/ /*** Structures to use on host. ***/
 
... ... struct fwblock {
173 194 uint8_t *data; uint8_t *data;
174 195 }; };
175 196
197 struct plugarray {
198 u32 code;
199 u32 targ_off;
200 u32 length;
201 };
202
203 struct ident_info {
204 u16 size;
205 u16 code;
206 u16 comp_id;
207 u16 variant;
208 u16 version_major;
209 u16 version_minor;
210 };
211
212 struct compat_info {
213 u16 size;
214 u16 code;
215 u16 role;
216 u16 id;
217 struct {
218 u16 variant;
219 u16 bottom;
220 u16 top;
221 } range[20];
222 };
223
176 224 struct fwtable { struct fwtable {
177 union {
178 struct fwblock_wdrv *w;
179 struct fwblock_mdrv *m;
180 } segarray_im;
181 struct fwblock segarray[4];
225 struct fwblock *segarray;
182 226 u32 halfentry; u32 halfentry;
183 struct _plugarray *plugarray;
184 struct _plugarray *pri_plugarray;
185 struct _compat_info *compat;
186 struct _ident_info *ident;
227 struct plugarray *plugarray;
228 struct plugarray *pri_plugarray;
229 struct compat_info *compat;
230 struct ident_info *ident;
187 231 }; };
188 232
189 /* Structure to map firmware identifiers to description strings */
190 static const struct
233 /* Structure detailing firmware differences between Windows and Mac */
234 struct fw_layout {
235 const int block_prefix; /* Bytes before the start of a firmware block */
236 const size_t lead_block_bytes; /* Bytes used by lead blocks */
237 const size_t datap_offset; /* Offset of data_p in fw_block struct */
238 size_t max_offset; /* No firmware after this offset */
239 ptrdiff_t addr_delta; /* Difference between addresses encoded in the
240 * driver and the file offset of the associated
241 * data */
242 bool mac; /* Use mac structures */
243 };
244
245 static struct fw_layout firmware_layout[] =
191 246 { {
247 { /* Windows */
248 4, 0 * sizeof(struct fwblock_wdrv),
249 offsetof(struct fwblock_wdrv, data_p)
250 },
251 { /* Mac */
252 0, 1 * sizeof(struct fwblock_mdrv),
253 offsetof(struct fwblock_mdrv, data_p)
254 }
255 };
256
257 /* Structure to map firmware identifiers to description strings */
258 static const struct {
192 259 u16 id; u16 id;
193 260 char *comp_string; char *comp_string;
194 261 } compat_table[] = } compat_table[] =
 
... ... static const struct
226 293
227 294 /* Checking endianess at runtime because performance isn't an issue, /* Checking endianess at runtime because performance isn't an issue,
228 295 * and I'd rather not add a configure step */ * and I'd rather not add a configure step */
229 static void check_endianess(void) {
296 static void check_endianess(void)
297 {
230 298 union { union {
231 299 u32 dword; u32 dword;
232 300 u16 word[2]; u16 word[2];
 
... ... static void check_endianess(void) {
234 302 } data; } data;
235 303
236 304 data.dword = 0x12345678; data.dword = 0x12345678;
237 if (data.word[0] == 0x1234) {
238 host_words_in_dword_be = 1;
305 if (data.word[0] == 0x1234)
306 {
307 host_words_in_dword_be = true;
239 308 } }
240 else if (data.word[0] == 0x5678) {
241 host_words_in_dword_be = 0;
242 } else {
309 else if (data.word[0] == 0x5678)
310 {
311 host_words_in_dword_be = false;
312 }
313 else
314 {
243 315 fprintf(stderr, "Can't determine endianess of host!\n"); fprintf(stderr, "Can't determine endianess of host!\n");
244 exit(1);
316 exit(EXIT_FAILURE);
245 317 } }
246 318
247 319 data.word[0] = 0x1234; data.word[0] = 0x1234;
248 if (data.byte[0] == 0x12) {
249 host_bytes_in_word_be = 1;
250 } else if (data.byte[0] == 0x34) {
251 host_bytes_in_word_be = 0;
252 } else {
320 if (data.byte[0] == 0x12)
321 {
322 host_bytes_in_word_be = true;
323 }
324 else if (data.byte[0] == 0x34)
325 {
326 host_bytes_in_word_be = false;
327 }
328 else
329 {
253 330 fprintf(stderr, "Can't determine endianess of host!\n"); fprintf(stderr, "Can't determine endianess of host!\n");
331 exit(EXIT_FAILURE);
254 332 } }
255 333
256 if (host_bytes_in_word_be == host_words_in_dword_be) {
257 fprintf (stdout, "Detected %s host\n",
258 host_bytes_in_word_be ? "big endian" : "little endian");
259 } else {
260 fprintf (stdout, "Detected host with mixed endianess\n");
334 if (host_bytes_in_word_be == host_words_in_dword_be)
335 {
336 fprintf(stdout, "Detected %s host\n",
337 host_bytes_in_word_be ? "big endian" : "little endian");
338 }
339 else
340 {
341 fprintf(stdout, "Detected host with mixed endianess\n");
261 342 } }
262 343 return; return;
263 344 } }
264 345
265 346 /* Locate firmware by looking for a T???????.HEX filename */ /* Locate firmware by looking for a T???????.HEX filename */
266 static char* find_fw_filename(const u8 *hostdriver,
267 unsigned int flen,
268 u8 hexchar)
347 static char* find_fw_filename(const u8 *hostdriver, size_t flen, char hexchar)
269 348 { {
270 349 const u8 *p, *end; const u8 *p, *end;
271 int found;
350 bool found;
272 351
273 352 /* Find the ?1XXYYZZ.HEX string */ /* Find the ?1XXYYZZ.HEX string */
274 353 p = hostdriver; p = hostdriver;
 
... ... static char* find_fw_filename(const u8 *hostdriver,
276 355
277 356 for (found = false; (found == false) && (p != NULL); ) for (found = false; (found == false) && (p != NULL); )
278 357 { {
279 p = memchr(p, hexchar, (unsigned int)(end - p));
358 p = memchr(p, hexchar, (end - p));
280 359
281 360 if (p != NULL) if (p != NULL)
282 361 { {
 
... ... static char* find_fw_filename(const u8 *hostdriver,
294 373 if (p != NULL) if (p != NULL)
295 374 { {
296 375 printf("Found firmware %s at file offset 0x%08x\n", printf("Found firmware %s at file offset 0x%08x\n",
297 p, p - hostdriver);
376 p, (p - hostdriver));
298 377 } }
299 378 else else
300 379 { {
 
... ... static char* find_fw_filename(const u8 *hostdriver,
307 386 /* Find the start of the firmware based on a hint as to where the end /* Find the start of the firmware based on a hint as to where the end
308 387 * of the firmware image is. The start of the firmware image is * of the firmware image is. The start of the firmware image is
309 388 * defined by a signature. */ * defined by a signature. */
310 static u8* find_fw(const u8* hostdriver,
311 unsigned int flen,
312 const u8* signature,
313 int slen,
314 const u8* hint)
389 static u8* find_fw(const u8 *hostdriver, size_t flen,
390 const u8 *signature, size_t slen,
391 const u8 *hint)
315 392 { {
316 393 const u8 *p = hint - slen; const u8 *p = hint - slen;
317 unsigned int i;
318 int found = false;
394 bool found = false;
395 size_t i;
319 396
320 397 printf("Searching for firmware from offset 0x%08x, start signature", printf("Searching for firmware from offset 0x%08x, start signature",
321 398 hint - hostdriver); hint - hostdriver);
 
... ... static u8* find_fw(const u8* hostdriver,
343 420 } }
344 421
345 422 /* Returns a pointer to the PE header */ /* Returns a pointer to the PE header */
346 static u8* peheader(const u8* data)
423 static void* pe_header(const void *data)
347 424 { {
348 __le32 *e_lfanew = (__le32*) (data + 0x3c);
425 __le32 *e_lfanew = (__le32 *) (data + 0x3c);
349 426
350 427 /* data + *e_lfanew gives us the NT SIGNATURE /* data + *e_lfanew gives us the NT SIGNATURE
351 428 * The NT signature is 4 bytes long. * The NT signature is 4 bytes long.
352 * The PE header follow immediately.
429 * The PE header follows immediately.
353 430 */ */
354 return (u8*) (data + (le32_to_host(*e_lfanew) + 4));
431 return (void *)(data + (le32_to_host(*e_lfanew) + 4));
355 432 } }
356 433
357 434 /* returns the expected imagebase */ /* returns the expected imagebase */
358 static unsigned int pe_imagebase(const u8* data)
435 static u32 pe_imagebase(const void *data)
359 436 { {
360 u8* pehdr = peheader(data);
361 return le32_to_host(*((u32*)(pehdr + 0x30)));
437 void *pe_hdr = pe_header(data);
438
439 return le32_to_host(*((u32 *) (pe_hdr + 0x30)));
362 440 } }
363 441
364 442 typedef __be32 mac_cpu_type_t; typedef __be32 mac_cpu_type_t;
 
... ... struct mach_header {
375 453 __be32 flags; __be32 flags;
376 454 }; };
377 455
378 struct mach_load_command
379 {
456 struct mach_load_command {
380 457 __be32 cmd; __be32 cmd;
381 458 __be32 cmdsize; __be32 cmdsize;
382 459 }; };
383 460
384 struct mach_segment_command
385 {
461 struct mach_segment_command {
386 462 __be32 cmd; __be32 cmd;
387 463 __be32 cmdsize; __be32 cmdsize;
388 464 char segname[16]; char segname[16];
 
... ... struct mach_segment_command
396 472 __be32 flags; __be32 flags;
397 473 }; };
398 474
399 struct mach_section
400 {
475 struct mach_section {
401 476 char sectname[16]; char sectname[16];
402 477 char segname[16]; char segname[16];
403 478 __be32 addr; __be32 addr;
 
... ... struct mach_section
416 491 * contains another second copy of our pointers later on (at about * contains another second copy of our pointers later on (at about
417 492 * offset 0x12330) which interfere with our search. * offset 0x12330) which interfere with our search.
418 493 */ */
419 static u32 macho_imagebase(const u8 *data, const u8 **section_end)
494 static const struct mach_section* macho_fw_section(const void *data)
420 495 { {
421 struct mach_header *hdr = (struct mach_header *) data;
422 int i, j;
423 const u8 *p = data + sizeof(struct mach_header);
496 const struct mach_header *hdr = data;
497 u32 i, j;
498 const void *p = data + sizeof(struct mach_header);
424 499
425 for (i = 0; i < be32_to_host(hdr->ncmds); i++) {
426 struct mach_load_command *load_cmd = (struct mach_load_command *) p;
500 for (i = 0; i < be32_to_host(hdr->ncmds); i++)
501 {
502 const struct mach_load_command *load_cmd = p;
427 503
428 if (be32_to_host(load_cmd->cmd) == 0x0001) { /* LC_SEGMENT */
429 struct mach_segment_command *seg_cmd = (struct mach_segment_command *) p;
504 if (be32_to_host(load_cmd->cmd) == 0x0001)
505 {
506 /* LC_SEGMENT */
430 507
431 p += sizeof(struct mach_segment_command);
432 for (j = 0; j < be32_to_host(seg_cmd->nsects); j++) {
433 struct mach_section *sect = (struct mach_section *) p;
508 const struct mach_segment_command *seg_cmd = p;
509 p += sizeof(struct mach_segment_command);
510 for (j = 0; j < be32_to_host(seg_cmd->nsects); j++)
511 {
512 const struct mach_section *sect = p;
434 513
435 if (!strcmp (sect->sectname, "__data") && !strcmp (sect->segname, "__DATA")) {
436 /*u32 *imgbase = (u32 *) (data + (be32_to_host(sect->addr) - be32_to_host(seg_cmd->vmaddr)));*/
437 *section_end = data + be32_to_host(sect->offset) + be32_to_host(sect->size);
438 return be32_to_host(sect->addr) - be32_to_host(sect->offset);
439 }
514 if ((strcmp(sect->sectname, "__data") == 0) &&
515 (strcmp(sect->segname, "__DATA") == 0))
516 {
517 return sect;
518 }
440 519
441 p += sizeof (struct mach_section);
442 }
443 }
520 p += sizeof(struct mach_section);
521 }
522 }
444 523
445 /* advance to past the load command */
446 p += sizeof (struct mach_load_command);
447 p += be32_to_host(load_cmd->cmdsize);
524 /* advance to past the load command */
525 p += sizeof(struct mach_load_command);
526 p += be32_to_host(load_cmd->cmdsize);
448 527 } }
449 528
450 529 printf("Couldn't find Mach-O __data/__DATA section\n"); printf("Couldn't find Mach-O __data/__DATA section\n");
451 return 0;
530 return NULL;
452 531 } }
453 532
454 533 #define MH_MAGIC 0xfeedface /* BE Mach-O magic number */ #define MH_MAGIC 0xfeedface /* BE Mach-O magic number */
 
... ... static u32 macho_imagebase(const u8 *data, const u8 **section_end)
465 544 * -1 = Not a 32-bit PPC Mach-O object file * -1 = Not a 32-bit PPC Mach-O object file
466 545 * -2 = Not a Mach-O object file * -2 = Not a Mach-O object file
467 546 */ */
468 static int macho_validate(const u8 *data)
547 static int macho_validate(const void *data)
469 548 { {
470 struct mach_header *hdr = (struct mach_header *) data;
471
472 printf("Header magic is 0x%x\n", be32_to_host(hdr->magic));
473 printf("CPU type is 0x%x\n", be32_to_host(hdr->cputype));
474 printf("File type is 0x%x\n", be32_to_host(hdr->filetype));
549 const struct mach_header *hdr = data;
475 550
476 switch (be32_to_host(hdr->magic)) {
551 switch (be32_to_host(hdr->magic))
552 {
477 553 case MH_MAGIC: case MH_MAGIC:
478 /* Yay, what we need */
479 break;
554 /* Yay, what we need */
555 break;
480 556 case MH_MAGIC_64: case MH_MAGIC_64:
481 557 case MH_CIGAM_64: case MH_CIGAM_64:
482 558 case MH_CIGAM: case MH_CIGAM:
483 /* 64-bit or LE 32-bit, can't use it */
484 return -1;
559 /* 64-bit or LE 32-bit, can't use it */
560 return -1;
485 561 default: default:
486 /* Not a Mach-O file at all */
487 return -2;
562 /* Not a Mach-O file at all */
563 return -2;
488 564 } }
489 565
490 if (be32_to_host(hdr->cputype) != 0x12) /* PPC */
491 return -1;
566 /* PPC */
567 if (be32_to_host(hdr->cputype) != 0x12)
568 return -1;
569
570 /* MH_OBJECT */
571 if (be32_to_host(hdr->filetype) != 0x0001)
572 return -1;
492 573
493 if (be32_to_host(hdr->filetype) != 0x0001) /* MH_OBJECT */
494 return -1;
495
496 574 return 0; return 0;
497 575 } }
498 576
499 577 /* Returns a pointer within data, to the fwblock pointing containing a /* Returns a pointer within data, to the fwblock pointing containing a
500 578 * pointer to addr (in driver address space)*/ * pointer to addr (in driver address space)*/
501 static u8* find_fwblock_entry(const u8* data,
502 unsigned int flen,
503 u32 addr,
504 int mac)
579 static u8* find_fwblock_entry(const u8 *data, const struct fw_layout *layout,
580 u32 addr)
505 581 { {
506 u32 *p = (u32*) ((unsigned int)(data + flen) & 0xFFFFFFFCu);
507 int found = false;
508
509 if (!mac) {
510 addr -= 4; /* kludge for driver firmware structure: one
511 * redundant dword at start. */
512 }
582 u32 *p = (u32*) ((unsigned int)(data + layout->max_offset) & 0xFFFFFFFCu);
583 bool found = false;
513 584
514 585 printf("Now searching for driver's firmware block entry (0x%08x)...\n", printf("Now searching for driver's firmware block entry (0x%08x)...\n",
515 586 addr); addr);
516 587
517 addr = host_to_driver_32(addr); /* convert to driver endianness to
518 * compare against file data */
588 /* Convert to driver endianness to compare against file data */
589 addr = host_to_driver_32(addr);
519 590
520 591 /* Note that we're not searching each byte position for a match. /* Note that we're not searching each byte position for a match.
521 592 * This should be fine because the data should have been placed on * This should be fine because the data should have been placed on
522 593 * a 4-byte boundary */ * a 4-byte boundary */
523 594
524 for (found = false;
525 ((u8*)p >= data);
526 p--)
595 for (found = false; ((u8*)p >= data); p--)
527 596 { {
528 597 if (*p == addr) if (*p == addr)
529 {
598 {
530 599 found = true; found = true;
531 break;
532 }
600 break;
601 }
533 602 } }
534 603
535 604 /* Compensate for the fields before the data_p pointer */ /* Compensate for the fields before the data_p pointer */
536 if (mac)
537 p -= offsetof(struct fwblock_mdrv, data_p) / sizeof(*p);
538 else
539 p -= offsetof(struct fwblock_wdrv, data_p) / sizeof(*p);
605 p -= layout->datap_offset / sizeof(*p);
540 606
541 607 return (u8*) p; return (u8*) p;
542 608 } }
543 609
544 static struct fwtable_drv* find_fwtable_entry(const u8* data,
545 unsigned int flen,
546 u32 fwblock)
610 static struct fwtable_drv* find_fwtable_entry(const u8 *data,
611 const struct fw_layout *layout,
612 u32 fwblock)
547 613 { {
548 u32 *p = (u32*) ((unsigned int)(data + flen) & 0xFFFFFFFCu);
549 int found = false;
614 u32 *p = (u32*) ((unsigned int)(data + layout->max_offset) & 0xFFFFFFFCu);
550 615 struct fwtable_drv *firmware; struct fwtable_drv *firmware;
616 bool found = false;
551 617
552 618 printf("Looking for main firmware table....\n"); printf("Looking for main firmware table....\n");
553 619
554 fwblock = host_to_driver_32(fwblock); /* convert to driver endianess to compare against file data */
555
556 printf("Looking for %x\n", fwblock);
620 /* Convert to driver endianess to compare against file data */
621 fwblock = host_to_driver_32(fwblock);
557 622
558 623 for (found = false; ((u8*)p >= data); p--) for (found = false; ((u8*)p >= data); p--)
559 624 { {
560 625 if (*p == fwblock) if (*p == fwblock)
561 {
626 {
562 627 found = true; found = true;
563 break;
564 }
628 break;
629 }
565 630 } }
566 631
567 632 firmware = (struct fwtable_drv *)p; firmware = (struct fwtable_drv *)p;
568 if (found == false) {
633 if (found == false)
634 {
569 635 printf("Main table not found - contact Mark!\n"); printf("Main table not found - contact Mark!\n");
570 } else {
636 }
637 else
638 {
571 639 printf("Found at file offset 0x%08x\n", (u8*)p - data); printf("Found at file offset 0x%08x\n", (u8*)p - data);
572 640 } }
573 641 return firmware; return firmware;
 
... ... static struct fwtable_drv* find_fwtable_entry(const u8* data,
580 648 * Some data will need to be converted back to LE when written out, * Some data will need to be converted back to LE when written out,
581 649 * but it will be easier than trying to kepp track of the endianness. * but it will be easier than trying to kepp track of the endianness.
582 650 */ */
583 static void copy_fw_data(struct fwtable* firmware,
584 struct fwtable_drv *fw_image,
585 const u8 *data,
586 int mac,
587 u32 ibase)
651 static void copy_fw_data(struct fwtable *firmware,
652 const struct fwtable_drv *driver_fw,
653 const void *data,
654 const struct fw_layout *layout)
588 655 { {
589 u32 delta = (u32)data - ibase;
590 unsigned int i;
591
592 /* Deal with pointers in fwtable */
593 firmware->segarray_im.w = (struct fwblock_wdrv *)
594 (driver_to_host_32(fw_image->segarray_p) + delta);
595 firmware->plugarray = (struct _plugarray *)
596 (driver_to_host_32(fw_image->plugarray_p) + delta);
597 firmware->pri_plugarray = (struct _plugarray *)
598 (driver_to_host_32(fw_image->pri_plugarray_p) + delta);
599 firmware->compat = (struct _compat_info *)
600 (driver_to_host_32(fw_image->compat_p) + delta);
601 firmware->ident = (struct _ident_info *)
602 (driver_to_host_32(fw_image->ident_p) + delta);
603 firmware->halfentry = driver_to_host_32(fw_image->halfentry);
604
605 for (i = 0; i < 4; i++)
656 union fwblock_drv block;
657 const struct plugarray_drv *pdr;
658 const struct plugarray_drv *pri;
659 const struct ident_info_drv *ident;
660 const struct compat_info_drv *compat;
661
662 /* Static data structures to write host endian data to */
663 static struct fwblock block_data[4] = {{ 0, 0, 0, 0 }};
664 static struct plugarray plug_data[64] = {{ 0, 0, 0 }};
665 static struct plugarray pri_plug_data[64] = {{ 0, 0, 0 }};
666 static struct ident_info ident_data = { 0, 0, 0, 0, 0, 0 };
667 static struct compat_info compat_data[16] = {{ 0 }};
668 u32 delta = (u32)data - layout->addr_delta;
669 size_t i;
670
671 /* Calculate valid pointers to driver data */
672 block.w = (struct fwblock_wdrv *)
673 (driver_to_host_32(driver_fw->segarray_p) + delta);
674 pdr = (struct plugarray_drv *)
675 (driver_to_host_32(driver_fw->plugarray_p) + delta);
676 pri = (struct plugarray_drv *)
677 (driver_to_host_32(driver_fw->pri_plugarray_p) + delta);
678 ident = (struct ident_info_drv *)
679 (driver_to_host_32(driver_fw->ident_p) + delta);
680 compat = (struct compat_info_drv *)
681 (driver_to_host_32(driver_fw->compat_p) + delta);
682
683 /* Setup pointers to host data */
684 firmware->segarray = &block_data[0];
685 firmware->plugarray = &plug_data[0];
686 firmware->pri_plugarray = &pri_plug_data[0];
687 firmware->compat = &compat_data[0];
688 firmware->ident = &ident_data;
689
690 firmware->halfentry = driver_to_host_32(driver_fw->halfentry);
691
692 for (i = 0; i < ARRAY_SIZE(block_data); i++)
606 693 { {
607 u32 offset = mac ?
608 driver_to_host_32(firmware->segarray_im.m[i].offset) :
609 driver_to_host_32(firmware->segarray_im.w[i].offset);
610 u32 data_p = mac ?
611 driver_to_host_32(firmware->segarray_im.m[i].data_p) :
612 driver_to_host_32(firmware->segarray_im.w[i].data_p) + 4; /* ?? offset for checksum? */
613 u16 size = mac ?
614 driver_to_host_16(firmware->segarray_im.m[i].size) :
615 driver_to_host_16(firmware->segarray_im.w[i].size);
616 u16 flags = mac ?
617 (u16) driver_to_host_32(firmware->segarray_im.m[i].flags) :
618 driver_to_host_16(firmware->segarray_im.w[i].flags);
619
620 if (offset != 0)
621 {
622 firmware->segarray[i].data = (unsigned char *) (data_p + delta);
623 firmware->segarray[i].offset = offset;
624 firmware->segarray[i].size = size;
625 firmware->segarray[i].flags = flags;
626 printf("Segment: %d File offs: 0x%08x Target mem: 0x%08x Length 0x%04x%s\n",
627 i,
628 firmware->segarray[i].data - data,
629 firmware->segarray[i].offset,
630 firmware->segarray[i].size,
631 (firmware->segarray[i].size == 0) ? " (ignored)" : "");
632 }
633 else
634 {
635 firmware->segarray[i].data = NULL;
636 firmware->segarray[i].offset = 0;
637 firmware->segarray[i].size = 0;
638 firmware->segarray[i].flags = 0;
639 break;
640 }
694 u32 offset = layout->mac ? driver_to_host_32(block.m[i].offset) :
695 driver_to_host_32(block.w[i].offset);
696 u32 data_p = ((layout->mac ? driver_to_host_32(block.m[i].data_p) :
697 driver_to_host_32(block.w[i].data_p)) +
698 layout->block_prefix);
699 u16 size = layout->mac ? driver_to_host_16(block.m[i].size) :
700 driver_to_host_16(block.w[i].size);
701 u16 flags = layout->mac ? (u16) driver_to_host_32(block.m[i].flags) :
702 driver_to_host_16(block.w[i].flags);
703
704 if (offset != 0)
705 {
706 firmware->segarray[i].data = (uint8_t *)(data_p + delta);
707 firmware->segarray[i].offset = offset;
708 firmware->segarray[i].size = size;
709 firmware->segarray[i].flags = flags;
710 printf("Segment: %d File offs: 0x%08x Target mem: 0x%08x "
711 "Length 0x%04x%s\n",
712 i,
713 (void *)block.w - data,
714 firmware->segarray[i].offset,
715 firmware->segarray[i].size,
716 (firmware->segarray[i].size == 0) ? " (ignored)" : "");
717 }
718 else
719 {
720 firmware->segarray[i].data = NULL;
721 firmware->segarray[i].offset = 0;
722 firmware->segarray[i].size = 0;
723 firmware->segarray[i].flags = 0;
724 break;
725 }
641 726 } }
642 727
643 728 printf("Production Data plugrecords at file offset 0x%08x\n", printf("Production Data plugrecords at file offset 0x%08x\n",
644 (u8*)firmware->plugarray - data);
729 (void *)pdr - data);
645 730 printf("Primary plugrecords at file offset 0x%08x\n", printf("Primary plugrecords at file offset 0x%08x\n",
646 (u8*)firmware->pri_plugarray - data);
731 (void *)pri - data);
647 732 printf("Compatibility info at file offset 0x%08x\n", printf("Compatibility info at file offset 0x%08x\n",
648 (u8*)firmware->compat - data);
733 (void *)compat - data);
649 734 printf("Identity info at file offset 0x%08x\n", printf("Identity info at file offset 0x%08x\n",
650 (u8*)firmware->ident - data);
735 (void *)ident - data);
651 736
652 /* Convert plugarray (in place in image) */
653 for (i = 0; firmware->plugarray[i].code != 0; i++)
737 /* Copy plugarray */
738 for (i = 0; (pdr[i].code != 0) && (i < ARRAY_SIZE(plug_data)); i++)
654 739 { {
655 firmware->plugarray[i].code = driver_to_host_32(firmware->plugarray[i].code);
656 firmware->plugarray[i].targ_off = driver_to_host_32(firmware->plugarray[i].targ_off);
657 firmware->plugarray[i].length = driver_to_host_32(firmware->plugarray[i].length);
740 firmware->plugarray[i].code = driver_to_host_32(pdr[i].code);
741 firmware->plugarray[i].targ_off = driver_to_host_32(pdr[i].targ_off);
742 firmware->plugarray[i].length = driver_to_host_32(pdr[i].length);
658 743 } }
659 744
660 /* Convert pri_array (in place in image) */
661 for (i = 0; firmware->pri_plugarray[i].code != 0; i++)
745 /* Copy pri_array */
746 for (i = 0; (pri[i].code != 0) && (i < ARRAY_SIZE(pri_plug_data)); i++)
662 747 { {
663 firmware->pri_plugarray[i].code = driver_to_host_32(firmware->pri_plugarray[i].code);
664 firmware->pri_plugarray[i].targ_off = driver_to_host_32(firmware->pri_plugarray[i].targ_off);
665 firmware->pri_plugarray[i].length = driver_to_host_32(firmware->pri_plugarray[i].length);
748 firmware->pri_plugarray[i].code = driver_to_host_32(pri[i].code);
749 firmware->pri_plugarray[i].targ_off =
750 driver_to_host_32(pri[i].targ_off);
751 firmware->pri_plugarray[i].length = driver_to_host_32(pri[i].length);
666 752 } }
667 753
668 /* Convert identifiers */
669 firmware->ident->size = driver_to_host_16(firmware->ident->size);
670 firmware->ident->code = driver_to_host_16(firmware->ident->code);
671 firmware->ident->comp_id = driver_to_host_16(firmware->ident->comp_id);
672 firmware->ident->variant = driver_to_host_16(firmware->ident->variant);
673 firmware->ident->version_major = driver_to_host_16(firmware->ident->version_major);
674 firmware->ident->version_minor = driver_to_host_16(firmware->ident->version_minor);
754 /* Copy identifiers */
755 firmware->ident->size = driver_to_host_16(ident->size);
756 firmware->ident->code = driver_to_host_16(ident->code);
757 firmware->ident->comp_id = driver_to_host_16(ident->comp_id);
758 firmware->ident->variant = driver_to_host_16(ident->variant);
759 firmware->ident->version_major = driver_to_host_16(ident->version_major);
760 firmware->ident->version_minor = driver_to_host_16(ident->version_minor);
675 761
676 /* Convert compat_info */
677 for (i = 0; firmware->compat[i].size != 0; i++)
762 /* Copy compat_info */
763 for (i = 0; (compat[i].size != 0) && (i < ARRAY_SIZE(compat_data)); i++)
678 764 { {
679 int j;
680 firmware->compat[i].size = driver_to_host_16(firmware->compat[i].size);
681 firmware->compat[i].code = driver_to_host_16(firmware->compat[i].code);
682 firmware->compat[i].role = driver_to_host_16(firmware->compat[i].role);
683 firmware->compat[i].id = driver_to_host_16(firmware->compat[i].id);
684 for (j = 0; j < 20; j++)
685 {
686 firmware->compat[i].range[j].variant = driver_to_host_16(firmware->compat[i].range[j].variant);
687 firmware->compat[i].range[j].bottom = driver_to_host_16(firmware->compat[i].range[j].bottom);
688 firmware->compat[i].range[j].top = driver_to_host_16(firmware->compat[i].range[j].top);
689 }
690 }
765 size_t j;
691 766
767 firmware->compat[i].size = driver_to_host_16(compat[i].size);
768 firmware->compat[i].code = driver_to_host_16(compat[i].code);
769 firmware->compat[i].role = driver_to_host_16(compat[i].role);
770 firmware->compat[i].id = driver_to_host_16(compat[i].id);
771 for (j = 0; j < ARRAY_SIZE(compat[i].range); j++)
772 {
773 firmware->compat[i].range[j].variant =
774 driver_to_host_16(compat[i].range[j].variant);
775 firmware->compat[i].range[j].bottom =
776 driver_to_host_16(compat[i].range[j].bottom);
777 firmware->compat[i].range[j].top =
778 driver_to_host_16(compat[i].range[j].top);
779 }
780 }
692 781 } }
693 782
694 783 static void print_fw_ident(const struct fwtable *firmware) static void print_fw_ident(const struct fwtable *firmware)
695 784 { {
696 int i;
785 size_t i;
697 786
698 787 if (firmware->ident->code == 0xFD20u) if (firmware->ident->code == 0xFD20u)
699 788 { {
700 for (i = 0;
701 i < sizeof(compat_table)/sizeof(compat_table[0]);
702 i++)
789 for (i = 0; i < ARRAY_SIZE(compat_table); i++)
703 790 { {
704 791 if (compat_table[i].id == firmware->ident->comp_id) if (compat_table[i].id == firmware->ident->comp_id)
705 792 break; break;
 
... ... static void print_fw_ident(const struct fwtable *firmware)
709 796 compat_table[i].comp_string, compat_table[i].comp_string,
710 797 firmware->ident->variant, firmware->ident->variant,
711 798 firmware->ident->version_major, firmware->ident->version_major,
712 firmware->ident->version_minor);
799 firmware->ident->version_minor);
713 800 } }
714 801 } }
715 802
716 static int write_hermesap_fw(FILE* output,
717 const struct fwtable *firmware)
803 static int write_hermesap_fw(FILE *output, const struct fwtable *firmware)
718 804 { {
719 805 unsigned int i; unsigned int i;
806
720 807 fprintf(output, "HFW1\nENTRY %08X\n", firmware->halfentry * 2); fprintf(output, "HFW1\nENTRY %08X\n", firmware->halfentry * 2);
721 808
722 809 for (i = 0; firmware->plugarray[i].code != 0; i++) for (i = 0; firmware->plugarray[i].code != 0; i++)
 
... ... static int write_hermesap_fw(FILE* output,
729 816
730 817 for (i = 0; firmware->segarray[i].offset != 0; i++) for (i = 0; firmware->segarray[i].offset != 0; i++)
731 818 { {
732 unsigned int j;
819 u16 j;
820
733 821 if (i != 0) if (i != 0)
734 822 fprintf(output, "\n"); fprintf(output, "\n");
735 823 fprintf(output, "SEG %08X %08X %08X", fprintf(output, "SEG %08X %08X %08X",
 
... ... static int write_hermesap_fw(FILE* output,
737 825 firmware->segarray[i].size, firmware->segarray[i].size,
738 826 0); 0);
739 827
740 for (j = 0; j < firmware->segarray[i].size; j += 2) {
828 for (j = 0; j < firmware->segarray[i].size; j += 2)
829 {
741 830 if ((j % 16) == 0) if ((j % 16) == 0)
742 831 fprintf(output, "\nDATA"); fprintf(output, "\nDATA");
743 832
 
... ... static size_t count_blocks(const struct fwblock *first_block)
756 845 { {
757 846 const struct fwblock *block = first_block; const struct fwblock *block = first_block;
758 847 size_t count = 0; size_t count = 0;
759 while(block->offset != 0)
848
849 while (block->offset != 0)
760 850 { {
761 851 if (block->size > 0) if (block->size > 0)
762 count++;
852 count++;
763 853 block++; block++;
764 854 } }
765 855 return count; return count;
 
... ... static size_t acc_block_size(const struct fwblock *first_block)
769 859 { {
770 860 const struct fwblock *block = first_block; const struct fwblock *block = first_block;
771 861 size_t len = 0; size_t len = 0;
772 while(block->offset != 0)
862
863 while (block->offset != 0)
773 864 { {
774 865 len += block->size; len += block->size;
775 866 block++; block++;
 
... ... static size_t acc_block_size(const struct fwblock *first_block)
777 868 return len; return len;
778 869 } }
779 870
780 static size_t count_pdr(const struct _plugarray *first_pdr)
871 static size_t count_pdr(const struct plugarray *first_pdr)
781 872 { {
782 const struct _plugarray *pdr = first_pdr;
873 const struct plugarray *pdr = first_pdr;
783 874 size_t count = 0; size_t count = 0;
784 while(pdr->code)
875
876 while (pdr->code)
785 877 { {
786 878 count++; count++;
787 879 pdr++; pdr++;
 
... ... static size_t count_pdr(const struct _plugarray *first_pdr)
789 881 return count; return count;
790 882 } }
791 883
792 static void dump_blocks(FILE* output,
793 const struct fwblock *first_block)
884 static void dump_blocks(FILE *output, const struct fwblock *first_block)
794 885 { {
795 886 const struct fwblock *block = first_block; const struct fwblock *block = first_block;
796 887 u8 block_hdr[sizeof(block->offset) + sizeof(block->size)]; u8 block_hdr[sizeof(block->offset) + sizeof(block->size)];
797 888 __le32 *addr = (__le32 *) &block_hdr[0]; __le32 *addr = (__le32 *) &block_hdr[0];
798 889 __le16 *size = (__le16 *) &block_hdr[sizeof(block->offset)]; __le16 *size = (__le16 *) &block_hdr[sizeof(block->offset)];
799 890
800 while(block->offset != 0)
891 while (block->offset != 0)
801 892 { {
802 893 if (block->size > 0) if (block->size > 0)
803 894 { {
804 895 *addr = host_to_le32(block->offset); *addr = host_to_le32(block->offset);
805 896 *size = host_to_le16(block->size); *size = host_to_le16(block->size);
806 897
807 fwrite(&block_hdr, 1, sizeof(block_hdr), output);
808 fwrite(block->data, 1, block->size, output); /* data */
898 (void)fwrite(&block_hdr, 1, sizeof(block_hdr), output);
899 (void)fwrite(block->data, 1, block->size, output); /* data */
809 900 } }
810 901 block++; block++;
811 902 } }
812 *addr = host_to_le32(0xFFFFFFFFu); /* set block end */
903 *addr = host_to_le32(0xFFFFFFFFu); /* set block end */
813 904 *size = host_to_le16(0); *size = host_to_le16(0);
814 fwrite(&block_hdr, 1, sizeof(block_hdr), output);
905 (void)fwrite(&block_hdr, 1, sizeof(block_hdr), output);
815 906 } }
816 907
817 static void dump_pdr(FILE* output,
818 const struct _plugarray *first_pdr)
908 static void dump_pdr(FILE *output, const struct plugarray *first_pdr)
819 909 { {
820 const struct _plugarray *r = first_pdr;
910 const struct plugarray *r = first_pdr;
821 911 u8 pdr[sizeof(r->code) + sizeof(r->targ_off) + sizeof(r->length)]; u8 pdr[sizeof(r->code) + sizeof(r->targ_off) + sizeof(r->length)];
822 912 __le32 *code = (__le32*) &pdr[0]; __le32 *code = (__le32*) &pdr[0];
823 913 __le32 *addr = (__le32*) &pdr[sizeof(r->code)]; __le32 *addr = (__le32*) &pdr[sizeof(r->code)];
824 __le32 *len = (__le32*) &pdr[sizeof(r->code) + sizeof(r->targ_off)];
914 __le32 *len = (__le32*) &pdr[sizeof(r->code) + sizeof(r->targ_off)];
825 915
826 916 if (r) if (r)
827 917 { {
828 while(r->code != 0)
918 while (r->code != 0)
829 919 { {
830 920 *code = host_to_le32(r->code); *code = host_to_le32(r->code);
831 921 *addr = host_to_le32(r->targ_off); *addr = host_to_le32(r->targ_off);
832 922 *len = host_to_le32(r->length); *len = host_to_le32(r->length);
833 fwrite(&pdr, 1, sizeof(pdr), output);
923 (void)fwrite(&pdr, 1, sizeof(pdr), output);
834 924 r++; r++;
835 925 } }
836 926 } }
837 *code = *addr = *len = host_to_le32(0); /* pdr end */
838 fwrite(&pdr, 1, sizeof(pdr), output);
927 *code = *addr = *len = host_to_le32(0); /* pdr end */
928 (void)fwrite(&pdr, 1, sizeof(pdr), output);
839 929 } }
840 930
841 static void dump_compat(FILE* output,
842 const struct _compat_info *compat)
931 static void dump_compat(FILE *output, const struct compat_info *compat)
843 932 { {
844 __le16 buf[sizeof(*compat)/sizeof(__le16)];
845
846 printf("buf is %d bytes\n", sizeof(buf));
847 printf("le16 is %d bytes\n", sizeof(__le16));
848 printf("*compat is %d bytes\n", sizeof(*compat));
933 __le16 buf[sizeof(*compat) / sizeof(__le16)];
849 934
850 935 /* Dump non-zero length blocks. /* Dump non-zero length blocks.
851 936 * No need to reformat. */ * No need to reformat. */
852 937 while (compat->size != 0) while (compat->size != 0)
853 938 { {
854 int i;
855
856 for (i = 0; i < (sizeof(buf)/sizeof(buf[0])); i++)
857 {
858 buf[i] = host_to_le16(((u16*)compat)[i]);
859 }
860 fwrite(buf, 1, sizeof(buf), output);
861 compat++;
862 printf("compat is at %x. size is %d\n", (int) compat, compat->size);
939 size_t i;
940
941 for (i = 0; i < ARRAY_SIZE(buf); i++)
942 {
943 buf[i] = host_to_le16(((u16 *) compat)[i]);
944 }
945 (void)fwrite(buf, 1, sizeof(buf), output);
946 compat++;
863 947 } }
864 948 /* sentinel */ /* sentinel */
865 949 memset(&buf, 0, sizeof(buf)); memset(&buf, 0, sizeof(buf));
866 fwrite(&buf, 1, sizeof(buf), output);
950 (void)fwrite(&buf, 1, sizeof(buf), output);
867 951 } }
868 952
869 953 #define VERSION "HFW000" #define VERSION "HFW000"
870 954 /* Returns zero, or a negative number to indicate an error */ /* Returns zero, or a negative number to indicate an error */
871 static int write_kernel_fw(FILE* output,
872 const struct fwtable *firmware)
955 static int write_kernel_fw(FILE *output, const struct fwtable *firmware)
873 956 { {
874 957 /* Note: does not deal with BE/LE issues */ /* Note: does not deal with BE/LE issues */
875 958 u32 image_header[6]; u32 image_header[6];
876 959 u32 *ptr; u32 *ptr;
877 u16 headersize = ((sizeof(VERSION)-1) +
878 sizeof(u16) +
879 (sizeof(u32)*6));
960 u16 headersize = ((sizeof(VERSION) - 1) + sizeof(u16) + (sizeof(u32) * 6));
880 961 u32 blocks = count_blocks(&firmware->segarray[0]); u32 blocks = count_blocks(&firmware->segarray[0]);
881 962 u32 blk_offset = 0; /* Immediately after header */ u32 blk_offset = 0; /* Immediately after header */
882 963 u32 pdr_offset = (acc_block_size(&firmware->segarray[0]) + u32 pdr_offset = (acc_block_size(&firmware->segarray[0]) +
 
... ... static int write_kernel_fw(FILE* output,
887 968 ((count_pdr(&firmware->pri_plugarray[0]) + 1) * sizeof(u32) * 3); ((count_pdr(&firmware->pri_plugarray[0]) + 1) * sizeof(u32) * 3);
888 969
889 970
890 fwrite (VERSION, 1, sizeof(VERSION)-1, output);
971 (void)fwrite(VERSION, 1, sizeof(VERSION) - 1, output);
891 972
892 973 headersize = host_to_le16(headersize); headersize = host_to_le16(headersize);
893 fwrite (&headersize, 1, sizeof(headersize), output);
974 (void)fwrite(&headersize, 1, sizeof(headersize), output);
894 975
895 976 ptr = &image_header[0]; ptr = &image_header[0];
896 *ptr = host_to_le32(firmware->halfentry); /* entrypoint */
977 *ptr = host_to_le32(firmware->halfentry); /* entrypoint */
897 978 ptr++; ptr++;
898 979 *ptr = host_to_le32(blocks); *ptr = host_to_le32(blocks);
899 980 ptr++; ptr++;
 
... ... static int write_kernel_fw(FILE* output,
905 986 ptr++; ptr++;
906 987 *ptr = host_to_le32(cpt_offset); *ptr = host_to_le32(cpt_offset);
907 988 ptr++; ptr++;
908 fwrite (&image_header, 1, sizeof(image_header), output);
989 (void)fwrite(&image_header, 1, sizeof(image_header), output);
909 990
910 991 dump_blocks(output, firmware->segarray); dump_blocks(output, firmware->segarray);
911 992 dump_pdr(output, firmware->plugarray); dump_pdr(output, firmware->plugarray);
912 993 dump_pdr(output, firmware->pri_plugarray); dump_pdr(output, firmware->pri_plugarray);
913 994 dump_compat(output, firmware->compat); dump_compat(output, firmware->compat);
914 return 0; /* success */
995 return 0;
915 996 } }
916 997
917 static int dump_fw(const char *basename, const char hexchar,
918 u8* data, size_t flen,
919 const u8* signature, size_t slen)
998 static int dump_fw(const char *basename, char hexchar,
999 const void *data,
1000 const struct fw_layout *layout,
1001 const u8 *signature, size_t slen)
920 1002 { {
1003 struct fwtable_drv *fw_image; /* structure all elements of a given firmware */
921 1004 struct fwtable firmware; struct fwtable firmware;
922 char* fwname;
923 char* filename;
924 u8* hint;
925 u8* fw; /* pointer to the actual blocks for programming */
926 u8* fwblock; /* location of structure listing blocks to program for a given firmware */
927 struct fwtable_drv *fw_image; /* structure all elements of a given firmware */
928 u32 ibase;
1005 char *fwname;
1006 char *filename;
1007 const void *hint;
1008 void *fw; /* pointer to the actual blocks for programming */
1009 void *fwblock; /* location of structure listing blocks to program for a given firmware */
929 1010 u32 vaddr; u32 vaddr;
930 FILE* output;
931 size_t len;
932 int macho = macho_validate(data);
933 int mac = 0;
934
935 if (macho == 0)
936 {
937 const u8* section_end;
938 printf ("Driver looks like Apple Mach-O format\n");
939 ibase = macho_imagebase(data, &section_end);
940
941 /* restrict search area */
942 flen = section_end - data;
943
944 driver_is_be = 1;
945 mac = 1;
946 }
947 else if (macho == -1)
948 {
949 printf ("Driver looks like Apple Mach-O format\n"
950 "But only a 32-bit PPC Mach-O format driver is supported.\n");
951 return -5;
952 }
953 else if (memcmp(data, "MZ", 2) == 0)
954 {
955 printf ("Driver looks like Microsoft PE format\n");
956 ibase = pe_imagebase(data);
957 driver_is_be = 0;
958 mac = 0;
959 }
960 else if (memcmp(data, "Joy!", 4) == 0)
961 {
962 printf ("Driver looks like Apple PEF format\n");
963 printf ("I don't know how to extract for this format.\n"
964 "I don't have a powerbook, and would need a copy of the driver to fix this\n");
965
966 /* Need to look at each of the section headers.
967 * Number of section headers if given at offset 0x20 (32) (__be16?)
968 * First section header starts at offset 0x28 (40)
969 * Each section header is 0x1C (28) bytes long
970 * Subsequent section headers follow immediately after.
971 * Each section header specifies its imagebase at offset 0x4 (__be32?)
972 * We need to use the imagebase of the section in which the firmware is found.
973 * The offset to the section data is at offset 0x14 (20) (__be32?).
974 * This offset is relative to the beginning of the file.
975 * The length of each sections data is at offset 0x10 (16) (__be32?)
976 */
977 /* ibase = pef_imagebase(data); */
978 return -5;
979 }
980 else
981 {
982 printf ("Unknown object file format\n");
983 return -5;
984 }
1011 FILE *output;
985 1012
986 1013 printf("\nAttempting to dump %c firmware:\n", hexchar); printf("\nAttempting to dump %c firmware:\n", hexchar);
987 fwname = find_fw_filename(data, flen, hexchar);
1014 fwname = find_fw_filename(data, layout->max_offset, hexchar);
988 1015 if (fwname) if (fwname)
989 1016 { {
990 1017 /* The filename is towards the end of the FW block, /* The filename is towards the end of the FW block,
 
... ... static int dump_fw(const char *basename, const char hexchar,
994 1021 } }
995 1022 else else
996 1023 { {
997 hint = data + flen; /* start from the end of file */
1024 hint = data + layout->max_offset;
998 1025 } }
999 1026
1000 1027 /* Now find the first firmware blob using the signature */ /* Now find the first firmware blob using the signature */
1001 fw = find_fw(data, flen, signature, slen, hint);
1028 fw = find_fw(data, layout->max_offset, signature, slen, hint);
1002 1029 if (!fw) if (!fw)
1003 1030 return -1; return -1;
1004 1031
1005 vaddr = (u32)(fw - data) + ibase;
1032 vaddr = (fw - data) + layout->addr_delta;
1033
1034 printf("Driver address of first firmware blob is 0x%08x\n", vaddr);
1006 1035
1007 printf("Image base is 0x%08x, therefore virtual offset of firmware is 0x%08x\n",
1008 ibase, vaddr);
1036 /* Some drivers fwtables point before the actual block start. */
1037 vaddr -= layout->block_prefix;
1009 1038
1010 fwblock = find_fwblock_entry(data,
1011 flen,
1012 vaddr,
1013 mac);
1039 fwblock = find_fwblock_entry(data, layout, vaddr);
1014 1040
1015 vaddr = (fwblock - data) + ibase;
1041 vaddr = (fwblock - data) + layout->addr_delta;
1016 1042
1017 if (!fwblock) {
1043 if (!fwblock)
1044 {
1018 1045 printf("Firmware block entry not found - contact Mark!\n"); printf("Firmware block entry not found - contact Mark!\n");
1019 1046 return -2; return -2;
1020 } else {
1021 printf("Found firmware block entry at virtual location 0x%08x, file offset 0x%08x\n",
1022 vaddr,
1023 fwblock - data);
1047 }
1048 else
1049 {
1050 printf("Found firmware block entry at virtual location 0x%08x, "
1051 "file offset 0x%08x\n", vaddr, fwblock - data);
1024 1052 } }
1025 1053
1026 /* The Mac firmware has a leading fwblock which we need to
1027 * compensate for */
1028 if (mac)
1029 fwblock -= sizeof(struct fwblock_mdrv);
1030 vaddr = (fwblock - data) + ibase;
1054 /* Got to the first fwblock. Static offset per arch */
1055 fwblock -= layout->lead_block_bytes;
1056 vaddr = (fwblock - data) + layout->addr_delta;
1031 1057
1032 fw_image = find_fwtable_entry(data,
1033 flen,
1034 vaddr);
1058 fw_image = find_fwtable_entry(data, layout, vaddr);
1035 1059 if (!fw_image) if (!fw_image)
1036 1060 return -3; return -3;
1037 1061
1038 copy_fw_data(&firmware, fw_image, data, mac, ibase);
1062 copy_fw_data(&firmware, fw_image, data, layout);
1039 1063
1040 1064 /* Print FW ident information */ /* Print FW ident information */
1041 1065 printf("Entry point at 0x%08x\n", firmware.halfentry * 2); printf("Entry point at 0x%08x\n", firmware.halfentry * 2);
1042 1066 print_fw_ident(&firmware); print_fw_ident(&firmware);
1043 1067
1044 filename = malloc(strlen(basename) + 5);
1068 filename = malloc(strlen(basename) + 12);
1045 1069 strcpy(filename, basename); strcpy(filename, basename);
1046 len = strlen(filename);
1047 filename[len] = hexchar;
1048 filename[len+1] = 0;
1049 strcat(filename, ".fw");
1070 strcat(filename,
1071 (firmware.ident->comp_id == 32) ? "_ap_fw.bin" : "_sta_fw.bin");
1050 1072
1051 1073 printf("Dumping to %s...\n", filename); printf("Dumping to %s...\n", filename);
1052 1074 if ((output = fopen(filename, "wb")) == NULL) if ((output = fopen(filename, "wb")) == NULL)
 
... ... static int dump_fw(const char *basename, const char hexchar,
1069 1091 return 0; return 0;
1070 1092 } }
1071 1093
1094 struct fw_layout* detect_fw_layout(const void *data, size_t flen)
1095 {
1096 int macho = macho_validate(data);
1097 struct fw_layout *layout;
1098 bool mac = false;
1099
1100 if (macho == 0)
1101 {
1102 const struct mach_section *fw_section;
1103
1104 printf("Driver looks like Apple Mach-O format\n");
1105
1106 mac = true;
1107 driver_is_be = true;
1108 layout = &firmware_layout[mac];
1109
1110 fw_section = macho_fw_section(data);
1111
1112 layout->addr_delta = (be32_to_host(fw_section->addr) -
1113 be32_to_host(fw_section->offset));
1114
1115 /* restrict search area */
1116 layout->max_offset = (size_t) (be32_to_host(fw_section->offset) +
1117 be32_to_host(fw_section->size));
1118 layout->mac = mac;
1119 }
1120 else if (macho == -1)
1121 {
1122 printf("Driver looks like Apple Mach-O format\n"
1123 "But only a 32-bit PPC Mach-O format driver is supported.\n");
1124 return NULL;
1125 }
1126 else if (memcmp(data, "MZ", 2) == 0)
1127 {
1128 printf("Driver looks like Microsoft PE format\n");
1129 driver_is_be = false;
1130 mac = false;
1131
1132 layout = &firmware_layout[mac];
1133
1134 layout->addr_delta = (ptrdiff_t) pe_imagebase(data);
1135 layout->max_offset = flen;
1136 layout->mac = mac;
1137 }
1138 else if (memcmp(data, "Joy!", 4) == 0)
1139 {
1140 printf("Driver looks like Apple PEF format\n");
1141 printf("I don't know how to extract for this format.\n");
1142
1143 /* Need to look at each of the section headers.
1144 * Number of section headers if given at offset 0x20 (32) (__be16?)
1145 * First section header starts at offset 0x28 (40)
1146 * Each section header is 0x1C (28) bytes long
1147 * Subsequent section headers follow immediately after.
1148 * Each section header specifies its imagebase at offset 0x4 (__be32?)
1149 * We need to use the imagebase of the section in which the firmware is found.
1150 * The offset to the section data is at offset 0x14 (20) (__be32?).
1151 * This offset is relative to the beginning of the file.
1152 * The length of each sections data is at offset 0x10 (16) (__be32?)
1153 */
1154 /* layout->addr_delta = pef_imagebase(data); */
1155 return NULL;
1156 }
1157 else
1158 {
1159 printf("Unknown object file format\n");
1160 return NULL;
1161 }
1162
1163 return layout;
1164 }
1165
1072 1166 /* /*
1073 1167 * Main * Main
1074 1168 */ */
1075 1169 int main(int argc, char *argv[]) int main(int argc, char *argv[])
1076 1170 { {
1077 1171 FILE *input; FILE *input;
1078 unsigned char *data;
1079 unsigned int flen;
1172 void *data;
1173 size_t read_bytes;
1174 size_t flen;
1080 1175
1081 1176 printf("Lucent Firmware Extractor v1.1\n" printf("Lucent Firmware Extractor v1.1\n"
1082 1177 "(c) 2003 Mark Smith (username 'Mark' on HermesAP board)\n" "(c) 2003 Mark Smith (username 'Mark' on HermesAP board)\n"
 
... ... int main(int argc, char *argv[])
1085 1180 check_endianess(); check_endianess();
1086 1181
1087 1182 /* Attempt to load file */ /* Attempt to load file */
1088 if (argc != 3) {
1183 if (argc != 3)
1184 {
1089 1185 printf("Usage: %s <driver> <output_base>\n", argv[0]); printf("Usage: %s <driver> <output_base>\n", argv[0]);
1090 1186 return -1; return -1;
1091 1187 } }
 
... ... int main(int argc, char *argv[])
1098 1194 * Others? * Others?
1099 1195 */ */
1100 1196
1101 if ((input = fopen(argv[1], "rb")) == NULL) {
1197 if ((input = fopen(argv[1], "rb")) == NULL)
1198 {
1102 1199 printf("Unable to open %s, aborting.\n", argv[1]); printf("Unable to open %s, aborting.\n", argv[1]);
1103 1200 return -1; return -1;
1104 1201 } }
 
... ... int main(int argc, char *argv[])
1113 1210
1114 1211 /* Allocate memory and load the file */ /* Allocate memory and load the file */
1115 1212 data = malloc(flen); data = malloc(flen);
1116 fread(data, 1, flen, input);
1117 printf("Memory allocated and file read OK\n");
1213 read_bytes = fread(data, 1, flen, input);
1118 1214 fclose(input); fclose(input);
1119 1215
1216 if (read_bytes == flen)
1120 1217 { {
1121 1218 u8 t_sig[4] = { 0x61, 0x44, 0xfe, 0xfb }; u8 t_sig[4] = { 0x61, 0x44, 0xfe, 0xfb };
1122 1219 u8 r_sig[4] = { 0x0f, 0x60, 0xfc, 0x63 }; u8 r_sig[4] = { 0x0f, 0x60, 0xfc, 0x63 };
1220 struct fw_layout *layout;
1221
1222 printf("Memory allocated and file read OK\n");
1123 1223
1124 dump_fw(argv[2], 'T', data, flen, t_sig, sizeof(t_sig));
1125 dump_fw(argv[2], 'R', data, flen, r_sig, sizeof(r_sig));
1224 layout = detect_fw_layout(data, flen);
1225 if (layout)
1226 {
1227 dump_fw(argv[2], 'T', data, layout, t_sig, sizeof(t_sig));
1228 dump_fw(argv[2], 'R', data, layout, r_sig, sizeof(r_sig));
1229 }
1230 }
1231 else
1232 {
1233 printf("Only read %d out of %d bytes\n", read_bytes, flen);
1126 1234 } }
1127 1235
1128 1236 free(data); free(data);
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/tuxsavvy/agere_fw_utils

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/tuxsavvy/agere_fw_utils

Clone this repository using git:
git clone git://git.rocketgit.com/user/tuxsavvy/agere_fw_utils

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main