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)
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 1f31f74c58179b099005ae939eff9bb467317b5b - Convert AirPort firmware version
Author: David Kilroy
Author date (UTC): 2008-10-26 14:37
Committer name: David Kilroy
Committer date (UTC): 2008-10-26 14:37
Parent(s): 525f9168679392920da51d2487cc5fdba3c68e2c
Signing key:
Tree: 4d673b1de821c0032e12c65bc734ea5d0d1e2c94
File Lines added Lines deleted
hfwget.c 346 233
File hfwget.c changed (mode: 100644) (index 6ccea31..792ef0e)
15 15 * These modifications may be distributed freely under the GPL v2 so * These modifications may be distributed freely under the GPL v2 so
16 16 * long as this copyright notice is included. * long as this copyright notice is included.
17 17 */ */
18 #include <stddef.h>
18 19 #include <stdio.h> #include <stdio.h>
19 20 #include <stdint.h> #include <stdint.h>
20 21 #include <stdlib.h> #include <stdlib.h>
 
24 25 #define false 0 #define false 0
25 26 #define true (!0) #define true (!0)
26 27
27 /* Typedefs for little endian values */
28 /* Typedefs for little and big endian values */
28 29 typedef uint32_t __le32; typedef uint32_t __le32;
29 30 typedef uint16_t __le16; typedef uint16_t __le16;
31 typedef uint32_t __be32;
32 typedef uint16_t __be16;
30 33
31 34 /* Typedefs for sized integers */ /* Typedefs for sized integers */
32 35 typedef uint32_t u32; typedef uint32_t u32;
 
... ... typedef uint8_t u8;
61 64 /* LEW+BEB stores 0x12345678 as 0x56 0x78 0x12 0x34 */ /* LEW+BEB stores 0x12345678 as 0x56 0x78 0x12 0x34 */
62 65 static int host_bytes_in_word_be = 0; static int host_bytes_in_word_be = 0;
63 66 static int host_words_in_dword_be = 0; static int host_words_in_dword_be = 0;
67 static int driver_is_be = 0;
64 68
65 69 #define host_to_le16(value) \ #define host_to_le16(value) \
66 host_bytes_in_word_be ? swap_bytes_16(value) : (value)
70 (host_bytes_in_word_be ? swap_bytes_16(value) : (value))
67 71 #define host_to_le32(value) \ #define host_to_le32(value) \
68 host_words_in_dword_be ? \
69 (host_bytes_in_word_be ? reverse_bytes_32(value) \
70 : swap_bytes_32(value)) : \
71 (host_bytes_in_word_be ? swap_words_32(value) : (value))
72 (host_words_in_dword_be ? \
73 (host_bytes_in_word_be ? reverse_bytes_32(value) \
74 : swap_bytes_32(value)) : \
75 (host_bytes_in_word_be ? swap_words_32(value) : (value)))
72 76
73 77 #define le16_to_host(value) \ #define le16_to_host(value) \
74 host_bytes_in_word_be ? swap_bytes_16(value) : (value)
78 (host_bytes_in_word_be ? swap_bytes_16(value) : (value))
75 79 #define le32_to_host(value) \ #define le32_to_host(value) \
76 host_words_in_dword_be ? \
77 (host_bytes_in_word_be ? reverse_bytes_32(value) \
78 : swap_bytes_32(value)) : \
79 (host_bytes_in_word_be ? swap_words_32(value) : (value))
80 (host_words_in_dword_be ? \
81 (host_bytes_in_word_be ? reverse_bytes_32(value) \
82 : swap_bytes_32(value)) : \
83 (host_bytes_in_word_be ? swap_words_32(value) : (value)))
84
85 #define host_to_be16(value) \
86 (host_bytes_in_word_be ? (value) : swap_bytes_16(value))
87 #define host_to_be32(value) \
88 (host_words_in_dword_be ? \
89 (host_bytes_in_word_be ? (value) : swap_bytes_32(value)) : \
90 (host_bytes_in_word_be ? swap_words_32(value) \
91 : reverse_bytes_32(value)))
80 92
81 93 #define be16_to_host(value) \ #define be16_to_host(value) \
82 host_bytes_in_word_be ? (value) : swap_bytes_16(value)
94 (host_bytes_in_word_be ? (value) : swap_bytes_16(value))
83 95 #define be32_to_host(value) \ #define be32_to_host(value) \
84 host_words_in_dword_be ? \
85 (host_bytes_in_word_be ? (value) : reverse_bytes_32(value)) : \
86 (host_bytes_in_word_be ? swap_words_32(value) : \
87 swap_bytes_32(value))
88
89 /* Structures to read image data */
90 struct _segarray {
96 (host_words_in_dword_be ? \
97 (host_bytes_in_word_be ? (value) : swap_bytes_32(value)) : \
98 (host_bytes_in_word_be ? swap_words_32(value) \
99 : reverse_bytes_32(value)))
100
101 #define driver_to_host_16(value) \
102 (driver_is_be ? be16_to_host(value) : le16_to_host(value))
103 #define driver_to_host_32(value) \
104 (driver_is_be ? be32_to_host(value) : le32_to_host(value))
105 #define host_to_driver_16(value) \
106 (driver_is_be ? host_to_be16(value) : host_to_le16(value))
107 #define host_to_driver_32(value) \
108 (driver_is_be ? host_to_be32(value) : host_to_le32(value))
109
110 /**** Structures to read image data from driver ****/
111
112 /* Decode the windows firmware blocks */
113 struct fwblock_wdrv {
91 114 __le32 offset; __le32 offset;
92 115 __le16 size; __le16 size;
93 116 __le16 flags; __le16 flags;
94 117 __le32 data_p; __le32 data_p;
95 118 }; };
96 119
120 /* Decode the mac firmware blocks */
121 struct fwblock_mdrv {
122 __be16 len;
123 __be16 code;
124 __be16 prg_mode;
125 __be16 size;
126 __be32 offset;
127 __be32 flags;
128 __be32 data_p;
129 };
130
97 131 struct _plugarray { struct _plugarray {
98 132 __le32 code; __le32 code;
99 133 __le32 targ_off; __le32 targ_off;
 
... ... struct _compat_info {
122 156 } range[20]; } range[20];
123 157 }; };
124 158
125 struct _firmwareblock {
159 struct fwtable_drv {
126 160 __le32 segarray_p; __le32 segarray_p;
127 161 __le32 halfentry; __le32 halfentry;
128 162 __le32 plugarray_p; __le32 plugarray_p;
 
... ... struct _firmwareblock {
131 165 __le32 ident_p; __le32 ident_p;
132 166 }; };
133 167
134 struct segarray {
168 /*** Structures to use on host. ***/
169 struct fwblock {
135 170 uint32_t offset; uint32_t offset;
136 171 uint16_t size; uint16_t size;
137 172 uint16_t flags; uint16_t flags;
138 173 uint8_t *data; uint8_t *data;
139 174 }; };
140 175
141 struct firmwareblock {
142 struct _segarray *segarray_im;
143 struct segarray segarray[4];
176 struct fwtable {
177 union {
178 struct fwblock_wdrv *w;
179 struct fwblock_mdrv *m;
180 } segarray_im;
181 struct fwblock segarray[4];
144 182 u32 halfentry; u32 halfentry;
145 183 struct _plugarray *plugarray; struct _plugarray *plugarray;
146 184 struct _plugarray *pri_plugarray; struct _plugarray *pri_plugarray;
 
... ... static u8* peheader(const u8* data)
317 355 } }
318 356
319 357 /* returns the expected imagebase */ /* returns the expected imagebase */
320 static unsigned int imagebase(const u8* data)
358 static unsigned int pe_imagebase(const u8* data)
321 359 { {
322 360 u8* pehdr = peheader(data); u8* pehdr = peheader(data);
323 361 return le32_to_host(*((u32*)(pehdr + 0x30))); return le32_to_host(*((u32*)(pehdr + 0x30)));
324 362 } }
325 363
364 typedef __be32 mac_cpu_type_t;
365 typedef __be32 mac_cpu_subtype_t;
366 typedef __be32 mac_vmprot_t;
367
326 368 struct mach_header { struct mach_header {
327 u32 magic;
328 int cputype;
329 int cpusubtype;
330 u32 filetype;
331 u32 ncmds;
332 u32 sizeofcmds;
333 u32 flags;
369 __be32 magic;
370 mac_cpu_type_t cputype;
371 mac_cpu_subtype_t cpusubtype;
372 __be32 filetype;
373 __be32 ncmds;
374 __be32 sizeofcmds;
375 __be32 flags;
334 376 }; };
335 377
336 378 struct mach_load_command struct mach_load_command
337 379 { {
338 u32 cmd;
339 u32 cmdsize;
380 __be32 cmd;
381 __be32 cmdsize;
340 382 }; };
341 383
342 384 struct mach_segment_command struct mach_segment_command
343 385 { {
344 u32 cmd;
345 u32 cmdsize;
386 __be32 cmd;
387 __be32 cmdsize;
346 388 char segname[16]; char segname[16];
347 u32 vmaddr;
348 u32 vmsize;
349 u32 fileoff;
350 u32 filesize;
351 int maxprot;
352 int initprot;
353 u32 nsects;
354 u32 flags;
389 __be32 vmaddr;
390 __be32 vmsize;
391 __be32 fileoff;
392 __be32 filesize;
393 mac_vmprot_t maxprot;
394 mac_vmprot_t initprot;
395 __be32 nsects;
396 __be32 flags;
355 397 }; };
356 398
357 399 struct mach_section struct mach_section
358 400 { {
359 401 char sectname[16]; char sectname[16];
360 402 char segname[16]; char segname[16];
361 u32 addr;
362 u32 size;
363 u32 offset;
364 u32 align;
365 u32 reloff;
366 u32 nreloc;
367 u32 flags;
368 u32 reserved1;
369 u32 reserved2;
403 __be32 addr;
404 __be32 size;
405 __be32 offset;
406 __be32 align;
407 __be32 reloff;
408 __be32 nreloc;
409 __be32 flags;
410 __be32 reserved1;
411 __be32 reserved2;
370 412 }; };
371 413
372 /* returns the start of the segment that contains the firmware */
373 static unsigned int macho_imagebase(const u8 *data)
414 /* Returns the start of the segment that contains the firmware. Also
415 * identifies the end of the section. It appears that the firmware
416 * contains another second copy of our pointers later on (at about
417 * offset 0x12330) which interfere with our search.
418 */
419 static u32 macho_imagebase(const u8 *data, const u8 **section_end)
374 420 { {
375 struct mach_header *hdr = (struct mach_header *) data;
421 struct mach_header *hdr = (struct mach_header *) data;
376 422 int i, j; int i, j;
377 423 const u8 *p = data + sizeof(struct mach_header); const u8 *p = data + sizeof(struct mach_header);
378 424
379 425 for (i = 0; i < be32_to_host(hdr->ncmds); i++) { for (i = 0; i < be32_to_host(hdr->ncmds); i++) {
380 struct mach_load_command *load_cmd = (struct mach_load_command *) p;
426 struct mach_load_command *load_cmd = (struct mach_load_command *) p;
381 427
382 if (be32_to_host(load_cmd->cmd) == 0x0001) { /* LC_SEGMENT */
383 struct mach_segment_command *seg_cmd = (struct mach_segment_command *) p;
428 if (be32_to_host(load_cmd->cmd) == 0x0001) { /* LC_SEGMENT */
429 struct mach_segment_command *seg_cmd = (struct mach_segment_command *) p;
384 430
385 p += sizeof(struct mach_segment_command);
386 for (j = 0; j < be32_to_host(seg_cmd->nsects); j++) {
387 struct mach_section *sect = (struct mach_section *) p;
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;
388 434
389 if (!strcmp (sect->sectname, "__data") && !strcmp (sect->segname, "__DATA")) {
390 u32 *imgbase = (u32 *) (data + (be32_to_host(sect->addr) - be32_to_host(seg_cmd->vmaddr)));
391 return *imgbase;
392 }
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 }
393 440
394 p += sizeof (struct mach_section);
395 }
396 }
441 p += sizeof (struct mach_section);
442 }
443 }
397 444
398 /* advance to past the load command */
399 p += sizeof (struct mach_load_command);
400 p += be32_to_host(load_cmd->cmdsize);
445 /* advance to past the load command */
446 p += sizeof (struct mach_load_command);
447 p += be32_to_host(load_cmd->cmdsize);
401 448 } }
402 449
403 450 printf("Couldn't find Mach-O __data/__DATA section\n"); printf("Couldn't find Mach-O __data/__DATA section\n");
 
... ... static unsigned int macho_imagebase(const u8 *data)
420 467 */ */
421 468 static int macho_validate(const u8 *data) static int macho_validate(const u8 *data)
422 469 { {
423 struct mach_header *hdr = (struct mach_header *) data;
424
425 switch (hdr->magic) {
426 case MH_MAGIC:
427 /* Yay, what we need */
428 break;
429 case MH_MAGIC_64:
430 case MH_CIGAM_64:
431 case MH_CIGAM:
432 /* 64-bit or LE 32-bit, can't use it */
433 return -1;
434 default:
435 /* Not a Mach-O file at all */
436 return -2;
437 }
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));
475
476 switch (be32_to_host(hdr->magic)) {
477 case MH_MAGIC:
478 /* Yay, what we need */
479 break;
480 case MH_MAGIC_64:
481 case MH_CIGAM_64:
482 case MH_CIGAM:
483 /* 64-bit or LE 32-bit, can't use it */
484 return -1;
485 default:
486 /* Not a Mach-O file at all */
487 return -2;
488 }
438 489
439 if (hdr->cputype != 0x12) /* PPC */
440 return -1;
490 if (be32_to_host(hdr->cputype) != 0x12) /* PPC */
491 return -1;
441 492
442 if (hdr->filetype != 0x0001) /* MH_OBJECT */
443 return -1;
493 if (be32_to_host(hdr->filetype) != 0x0001) /* MH_OBJECT */
494 return -1;
444 495
445 return 0;
496 return 0;
446 497 } }
447 498
448 /* Returns the virtual location of the firmware block */
449 static unsigned int find_fwblock_entry(const u8* data,
450 unsigned int flen,
451 u32 vfwoffs,
452 const u32 ibase)
499 /* Returns a pointer within data, to the fwblock pointing containing a
500 * 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)
453 505 { {
454 506 u32 *p = (u32*) ((unsigned int)(data + flen) & 0xFFFFFFFCu); u32 *p = (u32*) ((unsigned int)(data + flen) & 0xFFFFFFFCu);
455 u8 *q;
456 507 int found = false; int found = false;
457 unsigned int fwblock;
458 508
459 vfwoffs -= 4; /* kludge for driver firmware structure: one redundant dword at start. */
509 if (!mac) {
510 addr -= 4; /* kludge for driver firmware structure: one
511 * redundant dword at start. */
512 }
460 513
461 514 printf("Now searching for driver's firmware block entry (0x%08x)...\n", printf("Now searching for driver's firmware block entry (0x%08x)...\n",
462 vfwoffs);
515 addr);
463 516
464 vfwoffs = host_to_le32(vfwoffs); /* convert to little-endian to compare against file data */
517 addr = host_to_driver_32(addr); /* convert to driver endianness to
518 * compare against file data */
465 519
466 520 /* Note that we're not searching each byte position for a match. /* Note that we're not searching each byte position for a match.
467 521 * This should be fine because the data should have been placed on * This should be fine because the data should have been placed on
468 522 * a 4-byte boundary */ * a 4-byte boundary */
469 523
470 524 for (found = false; for (found = false;
471 ((u8*)p > data) && (found == false);
525 ((u8*)p >= data);
472 526 p--) p--)
473 527 { {
474 if (*p == vfwoffs)
528 if (*p == addr)
529 {
475 530 found = true; found = true;
531 break;
532 }
476 533 } }
477 534
478 /* Table entry is 8 bytes before vfwoffs,
479 * but don't forget we've decremented by 4 bytes already
480 */
481 q = (u8*)(p - 1);
535 /* 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);
482 540
483 fwblock = (unsigned int)(q - data) + ibase;
484 if (found == false) {
485 printf("Firmware block entry not found - contact Mark!\n");
486 return 0;
487 } else {
488 printf("Found firmware block entry at virtual location 0x%08x, file offset 0x%08x\n",
489 fwblock,
490 q - data);
491 }
492 return fwblock;
541 return (u8*) p;
493 542 } }
494 543
495 static struct _firmwareblock* find_fwtable_entry(const u8* data,
496 unsigned int flen,
497 u32 fwblock)
544 static struct fwtable_drv* find_fwtable_entry(const u8* data,
545 unsigned int flen,
546 u32 fwblock)
498 547 { {
499 548 u32 *p = (u32*) ((unsigned int)(data + flen) & 0xFFFFFFFCu); u32 *p = (u32*) ((unsigned int)(data + flen) & 0xFFFFFFFCu);
500 549 int found = false; int found = false;
501 struct _firmwareblock *firmware;
550 struct fwtable_drv *firmware;
502 551
503 552 printf("Looking for main firmware table....\n"); printf("Looking for main firmware table....\n");
504 553
505 fwblock = host_to_le32(fwblock); /* convert to little-endian to compare against file data */
506 for (found = false; ((u8*)p > data) && (found == false); p--)
554 fwblock = host_to_driver_32(fwblock); /* convert to driver endianess to compare against file data */
555
556 printf("Looking for %x\n", fwblock);
557
558 for (found = false; ((u8*)p >= data); p--)
559 {
507 560 if (*p == fwblock) if (*p == fwblock)
561 {
508 562 found = true; found = true;
563 break;
564 }
565 }
509 566
510 firmware = (struct _firmwareblock *)++p;
567 firmware = (struct fwtable_drv *)p;
511 568 if (found == false) { if (found == false) {
512 569 printf("Main table not found - contact Mark!\n"); printf("Main table not found - contact Mark!\n");
513 570 } else { } else {
 
... ... static struct _firmwareblock* find_fwtable_entry(const u8* data,
523 580 * 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,
524 581 * 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.
525 582 */ */
526 static void copy_fw_data(struct firmwareblock* firmware,
527 struct _firmwareblock *fw_image,
583 static void copy_fw_data(struct fwtable* firmware,
584 struct fwtable_drv *fw_image,
528 585 const u8 *data, const u8 *data,
529 const u32 ibase)
586 int mac,
587 u32 ibase)
530 588 { {
531 589 u32 delta = (u32)data - ibase; u32 delta = (u32)data - ibase;
532 590 unsigned int i; unsigned int i;
533 591
534 /* Deal with pointers in firmwareblock */
535 firmware->segarray_im = (struct _segarray *)
536 (le32_to_host(fw_image->segarray_p) + delta);
592 /* Deal with pointers in fwtable */
593 firmware->segarray_im.w = (struct fwblock_wdrv *)
594 (driver_to_host_32(fw_image->segarray_p) + delta);
537 595 firmware->plugarray = (struct _plugarray *) firmware->plugarray = (struct _plugarray *)
538 (le32_to_host(fw_image->plugarray_p) + delta);
596 (driver_to_host_32(fw_image->plugarray_p) + delta);
539 597 firmware->pri_plugarray = (struct _plugarray *) firmware->pri_plugarray = (struct _plugarray *)
540 (le32_to_host(fw_image->pri_plugarray_p) + delta);
598 (driver_to_host_32(fw_image->pri_plugarray_p) + delta);
541 599 firmware->compat = (struct _compat_info *) firmware->compat = (struct _compat_info *)
542 (le32_to_host(fw_image->compat_p) + delta);
600 (driver_to_host_32(fw_image->compat_p) + delta);
543 601 firmware->ident = (struct _ident_info *) firmware->ident = (struct _ident_info *)
544 (le32_to_host(fw_image->ident_p) + delta);
545 firmware->halfentry = le32_to_host(fw_image->halfentry);
602 (driver_to_host_32(fw_image->ident_p) + delta);
603 firmware->halfentry = driver_to_host_32(fw_image->halfentry);
546 604
547 605 for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
548 606 { {
549 if (le32_to_host(firmware->segarray_im[i].offset) != 0)
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)
550 621 { {
551 unsigned int temp =
552 (le32_to_host(firmware->segarray_im[i].data_p) + 4); /* ?? offset for checksum? */
553 firmware->segarray[i].data = (unsigned char *) (temp + delta);
554 firmware->segarray[i].offset = le32_to_host(firmware->segarray_im[i].offset);
555 firmware->segarray[i].size = le16_to_host(firmware->segarray_im[i].size);
556 firmware->segarray[i].flags = le16_to_host(firmware->segarray_im[i].flags);
557 printf("Segment: %d File offs: 0x%08x Target mem: 0x%08x Length 0x%04x\n",
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",
558 627 i, i,
559 628 firmware->segarray[i].data - data, firmware->segarray[i].data - data,
560 629 firmware->segarray[i].offset, firmware->segarray[i].offset,
561 firmware->segarray[i].size);
630 firmware->segarray[i].size,
631 (firmware->segarray[i].size == 0) ? " (ignored)" : "");
562 632 } }
563 633 else else
564 634 { {
 
... ... static void copy_fw_data(struct firmwareblock* firmware,
578 648 (u8*)firmware->compat - data); (u8*)firmware->compat - data);
579 649 printf("Identity info at file offset 0x%08x\n", printf("Identity info at file offset 0x%08x\n",
580 650 (u8*)firmware->ident - data); (u8*)firmware->ident - data);
581 #if 0
651
582 652 /* Convert plugarray (in place in image) */ /* Convert plugarray (in place in image) */
583 653 for (i = 0; firmware->plugarray[i].code != 0; i++) for (i = 0; firmware->plugarray[i].code != 0; i++)
584 654 { {
585 firmware->plugarray[i].code = le32_to_host(firmware->plugarray[i].code);
586 firmware->plugarray[i].targ_off = le32_to_host(firmware->plugarray[i].targ_off);
587 firmware->plugarray[i].length = le32_to_host(firmware->plugarray[i].length);
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);
588 658 } }
589 659
590 660 /* Convert pri_array (in place in image) */ /* Convert pri_array (in place in image) */
591 661 for (i = 0; firmware->pri_plugarray[i].code != 0; i++) for (i = 0; firmware->pri_plugarray[i].code != 0; i++)
592 662 { {
593 firmware->pri_plugarray[i].code = le32_to_host(firmware->plugarray[i].code);
594 firmware->pri_plugarray[i].targ_off = le32_to_host(firmware->plugarray[i].targ_off);
595 firmware->pri_plugarray[i].length = le32_to_host(firmware->plugarray[i].length);
663 firmware->pri_plugarray[i].code = driver_to_host_32(firmware->plugarray[i].code);
664 firmware->pri_plugarray[i].targ_off = driver_to_host_32(firmware->plugarray[i].targ_off);
665 firmware->pri_plugarray[i].length = driver_to_host_32(firmware->plugarray[i].length);
596 666 } }
597 667
598 668 /* Convert identifiers */ /* Convert identifiers */
599 firmware->ident->size = le16_to_host(fw_image->ident->size);
600 firmware->ident->code = le16_to_host(fw_image->ident->code);
601 firmware->ident->comp_id = le16_to_host(fw_image->ident->comp_id);
602 firmware->ident->variant = le16_to_host(fw_image->ident->variant);
603 firmware->ident->version_major = le16_to_host(fw_image->ident->version_major);
604 firmware->ident->version_minor = le16_to_host(fw_image->ident->version_minor);
605
606 /* TODO: Convert compat_info */
607 #endif
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);
675
676 /* Convert compat_info */
677 for (i = 0; firmware->compat[i].size != 0; i++)
678 {
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 }
691
608 692 } }
609 693
610 static void print_fw_ident(const struct firmwareblock *firmware)
694 static void print_fw_ident(const struct fwtable *firmware)
611 695 { {
612 696 int i; int i;
613 697
614 if (le16_to_host(firmware->ident->code) == 0xFD20u)
698 if (firmware->ident->code == 0xFD20u)
615 699 { {
616 700 for (i = 0; for (i = 0;
617 701 i < sizeof(compat_table)/sizeof(compat_table[0]); i < sizeof(compat_table)/sizeof(compat_table[0]);
618 702 i++) i++)
619 703 { {
620 if (compat_table[i].id == le16_to_host(firmware->ident->comp_id))
704 if (compat_table[i].id == firmware->ident->comp_id)
621 705 break; break;
622 706 } }
623 707
624 708 printf("Firmware identity: %s, Variant %d Version %d.%2d\n", printf("Firmware identity: %s, Variant %d Version %d.%2d\n",
625 709 compat_table[i].comp_string, compat_table[i].comp_string,
626 le16_to_host(firmware->ident->variant),
627 le16_to_host(firmware->ident->version_major),
628 le16_to_host(firmware->ident->version_minor));
710 firmware->ident->variant,
711 firmware->ident->version_major,
712 firmware->ident->version_minor);
629 713 } }
630 714 } }
631 715
632 716 static int write_hermesap_fw(FILE* output, static int write_hermesap_fw(FILE* output,
633 const struct firmwareblock *firmware)
717 const struct fwtable *firmware)
634 718 { {
635 719 unsigned int i; unsigned int i;
636 720 fprintf(output, "HFW1\nENTRY %08X\n", firmware->halfentry * 2); fprintf(output, "HFW1\nENTRY %08X\n", firmware->halfentry * 2);
 
... ... static int write_hermesap_fw(FILE* output,
638 722 for (i = 0; firmware->plugarray[i].code != 0; i++) for (i = 0; firmware->plugarray[i].code != 0; i++)
639 723 { {
640 724 fprintf(output, "PLUG %08X %08X %08X\n", fprintf(output, "PLUG %08X %08X %08X\n",
641 le32_to_host(firmware->plugarray[i].code),
642 le32_to_host(firmware->plugarray[i].targ_off),
643 le32_to_host(firmware->plugarray[i].length));
725 firmware->plugarray[i].code,
726 firmware->plugarray[i].targ_off,
727 firmware->plugarray[i].length);
644 728 } }
645 729
646 730 for (i = 0; firmware->segarray[i].offset != 0; i++) for (i = 0; firmware->segarray[i].offset != 0; i++)
 
... ... static int write_hermesap_fw(FILE* output,
668 752 return 0; return 0;
669 753 } }
670 754
671 static size_t count_blocks(const struct segarray *first_seg)
755 static size_t count_blocks(const struct fwblock *first_block)
672 756 { {
673 const struct segarray *seg = first_seg;
757 const struct fwblock *block = first_block;
674 758 size_t count = 0; size_t count = 0;
675 while(seg->offset != 0)
759 while(block->offset != 0)
676 760 { {
677 count++;
678 seg++;
761 if (block->size > 0)
762 count++;
763 block++;
679 764 } }
680 765 return count; return count;
681 766 } }
682 767
683 static size_t acc_block_size(const struct segarray *first_seg)
768 static size_t acc_block_size(const struct fwblock *first_block)
684 769 { {
685 const struct segarray *seg = first_seg;
770 const struct fwblock *block = first_block;
686 771 size_t len = 0; size_t len = 0;
687 while(seg->offset != 0)
772 while(block->offset != 0)
688 773 { {
689 len += seg->size;
690 seg++;
774 len += block->size;
775 block++;
691 776 } }
692 777 return len; return len;
693 778 } }
 
... ... static size_t count_pdr(const struct _plugarray *first_pdr)
705 790 } }
706 791
707 792 static void dump_blocks(FILE* output, static void dump_blocks(FILE* output,
708 const struct segarray *first_seg)
793 const struct fwblock *first_block)
709 794 { {
710 const struct segarray *seg = first_seg;
711 u8 block_hdr[sizeof(seg->offset) + sizeof(seg->size)];
795 const struct fwblock *block = first_block;
796 u8 block_hdr[sizeof(block->offset) + sizeof(block->size)];
712 797 __le32 *addr = (__le32 *) &block_hdr[0]; __le32 *addr = (__le32 *) &block_hdr[0];
713 __le16 *size = (__le16 *) &block_hdr[sizeof(seg->offset)];
798 __le16 *size = (__le16 *) &block_hdr[sizeof(block->offset)];
714 799
715 while(seg->offset != 0)
800 while(block->offset != 0)
716 801 { {
717 if (seg->size > 0)
802 if (block->size > 0)
718 803 { {
719 *addr = host_to_le32(seg->offset);
720 *size = host_to_le16(seg->size);
804 *addr = host_to_le32(block->offset);
805 *size = host_to_le16(block->size);
721 806
722 807 fwrite(&block_hdr, 1, sizeof(block_hdr), output); fwrite(&block_hdr, 1, sizeof(block_hdr), output);
723 fwrite(seg->data, 1, seg->size, output); /* data */
808 fwrite(block->data, 1, block->size, output); /* data */
724 809 } }
725 seg++;
810 block++;
726 811 } }
727 812 *addr = host_to_le32(0xFFFFFFFFu); /* set block end */ *addr = host_to_le32(0xFFFFFFFFu); /* set block end */
728 *size = host_to_le32(0);
813 *size = host_to_le16(0);
729 814 fwrite(&block_hdr, 1, sizeof(block_hdr), output); fwrite(&block_hdr, 1, sizeof(block_hdr), output);
730 815 } }
731 816
 
... ... static void dump_pdr(FILE* output,
756 841 static void dump_compat(FILE* output, static void dump_compat(FILE* output,
757 842 const struct _compat_info *compat) const struct _compat_info *compat)
758 843 { {
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));
849
759 850 /* Dump non-zero length blocks. /* Dump non-zero length blocks.
760 851 * No need to reformat. */ * No need to reformat. */
761 852 while (compat->size != 0) while (compat->size != 0)
762 853 { {
763 fwrite(compat, 1, sizeof(*compat), output);
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);
764 861 compat++; compat++;
862 printf("compat is at %x. size is %d\n", (int) compat, compat->size);
765 863 } }
766 864 /* sentinel */ /* sentinel */
767 fwrite(compat, 1, sizeof(*compat), output);
865 memset(&buf, 0, sizeof(buf));
866 fwrite(&buf, 1, sizeof(buf), output);
768 867 } }
769 868
770 869 #define VERSION "HFW000" #define VERSION "HFW000"
771 870 /* Returns zero, or a negative number to indicate an error */ /* Returns zero, or a negative number to indicate an error */
772 871 static int write_kernel_fw(FILE* output, static int write_kernel_fw(FILE* output,
773 const struct firmwareblock *firmware)
872 const struct fwtable *firmware)
774 873 { {
775 874 /* Note: does not deal with BE/LE issues */ /* Note: does not deal with BE/LE issues */
776 875 u32 image_header[6]; u32 image_header[6];
 
... ... static int dump_fw(const char *basename, const char hexchar,
819 918 u8* data, size_t flen, u8* data, size_t flen,
820 919 const u8* signature, size_t slen) const u8* signature, size_t slen)
821 920 { {
822 struct firmwareblock firmware;
921 struct fwtable firmware;
823 922 char* fwname; char* fwname;
824 923 char* filename; char* filename;
825 924 u8* hint; u8* hint;
826 925 u8* fw; /* pointer to the actual blocks for programming */ u8* fw; /* pointer to the actual blocks for programming */
827 unsigned int fwblock; /* virtual location of structure listing blocks to program for a given firmware */
828 struct _firmwareblock *fw_image; /* structure all elements of a given firmware */
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 */
829 928 u32 ibase; u32 ibase;
830 u32 vfwoffs;
929 u32 vaddr;
831 930 FILE* output; FILE* output;
832 931 size_t len; size_t len;
833 int found = 0;
932 int macho = macho_validate(data);
933 int mac = 0;
834 934
835 if (memcmp(data, "MZ", 2) == 0)
935 if (macho == 0)
836 936 { {
837 printf ("Driver looks like Microsoft PE format\n");
838 ibase = imagebase(data);
839 found = 1;
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;
840 946 } }
841
842 if (!found)
947 else if (macho == -1)
843 948 { {
844 int ret;
845
846 ret = macho_validate(data);
847 if (ret == 0)
848 {
849 printf ("Driver looks like Apple Mach-O format\n");
850 ibase = macho_imagebase(data);
851 found = 1;
852 }
853 else if (ret == -1)
854 {
855 printf ("Driver looks like Apple Mach-O format\n"
856 "But only a 32-bit PPC Mach-O format driver is supported.\n");
857 return -5;
858 }
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;
859 952 } }
860
861 if (!found && memcmp(data, "Joy!", 4) == 0)
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)
862 961 { {
863 962 printf ("Driver looks like Apple PEF format\n"); printf ("Driver looks like Apple PEF format\n");
864 963 printf ("I don't know how to extract for this format.\n" printf ("I don't know how to extract for this format.\n"
 
... ... static int dump_fw(const char *basename, const char hexchar,
878 977 /* ibase = pef_imagebase(data); */ /* ibase = pef_imagebase(data); */
879 978 return -5; return -5;
880 979 } }
881
882 if (!found)
980 else
883 981 { {
884 982 printf ("Unknown object file format\n"); printf ("Unknown object file format\n");
885 983 return -5; return -5;
 
... ... static int dump_fw(const char *basename, const char hexchar,
899 997 hint = data + flen; /* start from the end of file */ hint = data + flen; /* start from the end of file */
900 998 } }
901 999
902 /* Now find the block using the signature */
1000 /* Now find the first firmware blob using the signature */
903 1001 fw = find_fw(data, flen, signature, slen, hint); fw = find_fw(data, flen, signature, slen, hint);
904 1002 if (!fw) if (!fw)
905 1003 return -1; return -1;
906 1004
907 vfwoffs = (u32)(fw - data) + ibase;
1005 vaddr = (u32)(fw - data) + ibase;
908 1006
909 1007 printf("Image base is 0x%08x, therefore virtual offset of firmware is 0x%08x\n", printf("Image base is 0x%08x, therefore virtual offset of firmware is 0x%08x\n",
910 ibase, vfwoffs);
1008 ibase, vaddr);
911 1009
912 1010 fwblock = find_fwblock_entry(data, fwblock = find_fwblock_entry(data,
913 1011 flen, flen,
914 vfwoffs,
915 ibase);
916 if (!fwblock)
1012 vaddr,
1013 mac);
1014
1015 vaddr = (fwblock - data) + ibase;
1016
1017 if (!fwblock) {
1018 printf("Firmware block entry not found - contact Mark!\n");
917 1019 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);
1024 }
1025
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;
918 1031
919 1032 fw_image = find_fwtable_entry(data, fw_image = find_fwtable_entry(data,
920 1033 flen, flen,
921 fwblock);
1034 vaddr);
922 1035 if (!fw_image) if (!fw_image)
923 1036 return -3; return -3;
924 1037
925 copy_fw_data(&firmware, fw_image, data, ibase);
1038 copy_fw_data(&firmware, fw_image, data, mac, ibase);
926 1039
927 1040 /* Print FW ident information */ /* Print FW ident information */
928 1041 printf("Entry point at 0x%08x\n", firmware.halfentry * 2); printf("Entry point at 0x%08x\n", firmware.halfentry * 2);
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