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)
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 525f9168679392920da51d2487cc5fdba3c68e2c - Mach-O parsing from Dan Williams
Author: David Kilroy
Author date (UTC): 2008-10-26 14:34
Committer name: David Kilroy
Committer date (UTC): 2008-10-26 14:34
Parent(s): 4af298b374a1dea172b57acbd080773912d22087
Signing key:
Tree: a1af62854e6a5179af5e4b0bace917292e7ba9d1
File Lines added Lines deleted
hfwget.c 165 9
File hfwget.c changed (mode: 100644) (index 1c3a95b..6ccea31)
... ... static int host_words_in_dword_be = 0;
78 78 : swap_bytes_32(value)) : \ : swap_bytes_32(value)) : \
79 79 (host_bytes_in_word_be ? swap_words_32(value) : (value)) (host_bytes_in_word_be ? swap_words_32(value) : (value))
80 80
81 #define be16_to_host(value) \
82 host_bytes_in_word_be ? (value) : swap_bytes_16(value)
83 #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
81 89 /* Structures to read image data */ /* Structures to read image data */
82 90 struct _segarray { struct _segarray {
83 91 __le32 offset; __le32 offset;
 
... ... static unsigned int imagebase(const u8* data)
315 323 return le32_to_host(*((u32*)(pehdr + 0x30))); return le32_to_host(*((u32*)(pehdr + 0x30)));
316 324 } }
317 325
326 struct mach_header {
327 u32 magic;
328 int cputype;
329 int cpusubtype;
330 u32 filetype;
331 u32 ncmds;
332 u32 sizeofcmds;
333 u32 flags;
334 };
335
336 struct mach_load_command
337 {
338 u32 cmd;
339 u32 cmdsize;
340 };
341
342 struct mach_segment_command
343 {
344 u32 cmd;
345 u32 cmdsize;
346 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;
355 };
356
357 struct mach_section
358 {
359 char sectname[16];
360 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;
370 };
371
372 /* returns the start of the segment that contains the firmware */
373 static unsigned int macho_imagebase(const u8 *data)
374 {
375 struct mach_header *hdr = (struct mach_header *) data;
376 int i, j;
377 const u8 *p = data + sizeof(struct mach_header);
378
379 for (i = 0; i < be32_to_host(hdr->ncmds); i++) {
380 struct mach_load_command *load_cmd = (struct mach_load_command *) p;
381
382 if (be32_to_host(load_cmd->cmd) == 0x0001) { /* LC_SEGMENT */
383 struct mach_segment_command *seg_cmd = (struct mach_segment_command *) p;
384
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;
388
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 }
393
394 p += sizeof (struct mach_section);
395 }
396 }
397
398 /* advance to past the load command */
399 p += sizeof (struct mach_load_command);
400 p += be32_to_host(load_cmd->cmdsize);
401 }
402
403 printf("Couldn't find Mach-O __data/__DATA section\n");
404 return 0;
405 }
406
407 #define MH_MAGIC 0xfeedface /* BE Mach-O magic number */
408 #define MH_CIGAM 0xcefaedfe /* LE Mach-O magic number */
409 #define MH_MAGIC_64 0xfeedfacf /* BE Mach-O 64-bit magic number */
410 #define MH_CIGAM_64 0xcffaedfe /* LE Mach-O 64-bit magic number */
411
412 /* Validates the Mach-O object file; only accepts 32-bit BE
413 * PPC Mach-O object files because classic AirPort was only
414 * ever used on 32-bit PPC machines.
415 *
416 * Returns:
417 * 0 = success
418 * -1 = Not a 32-bit PPC Mach-O object file
419 * -2 = Not a Mach-O object file
420 */
421 static int macho_validate(const u8 *data)
422 {
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 }
438
439 if (hdr->cputype != 0x12) /* PPC */
440 return -1;
441
442 if (hdr->filetype != 0x0001) /* MH_OBJECT */
443 return -1;
444
445 return 0;
446 }
447
318 448 /* Returns the virtual location of the firmware block */ /* Returns the virtual location of the firmware block */
319 449 static unsigned int find_fwblock_entry(const u8* data, static unsigned int find_fwblock_entry(const u8* data,
320 450 unsigned int flen, unsigned int flen,
321 u32 vfwoffs)
451 u32 vfwoffs,
452 const u32 ibase)
322 453 { {
323 454 u32 *p = (u32*) ((unsigned int)(data + flen) & 0xFFFFFFFCu); u32 *p = (u32*) ((unsigned int)(data + flen) & 0xFFFFFFFCu);
324 455 u8 *q; u8 *q;
 
... ... static unsigned int find_fwblock_entry(const u8* data,
349 480 */ */
350 481 q = (u8*)(p - 1); q = (u8*)(p - 1);
351 482
352 fwblock = (unsigned int)(q - data) + imagebase(data);
483 fwblock = (unsigned int)(q - data) + ibase;
353 484 if (found == false) { if (found == false) {
354 485 printf("Firmware block entry not found - contact Mark!\n"); printf("Firmware block entry not found - contact Mark!\n");
355 486 return 0; return 0;
 
... ... static struct _firmwareblock* find_fwtable_entry(const u8* data,
394 525 */ */
395 526 static void copy_fw_data(struct firmwareblock* firmware, static void copy_fw_data(struct firmwareblock* firmware,
396 527 struct _firmwareblock *fw_image, struct _firmwareblock *fw_image,
397 u8 *data)
528 const u8 *data,
529 const u32 ibase)
398 530 { {
399 u32 delta = (u32)data - imagebase(data);
531 u32 delta = (u32)data - ibase;
400 532 unsigned int i; unsigned int i;
401 533
402 534 /* Deal with pointers in firmwareblock */ /* Deal with pointers in firmwareblock */
 
... ... static int dump_fw(const char *basename, const char hexchar,
698 830 u32 vfwoffs; u32 vfwoffs;
699 831 FILE* output; FILE* output;
700 832 size_t len; size_t len;
833 int found = 0;
701 834
702 835 if (memcmp(data, "MZ", 2) == 0) if (memcmp(data, "MZ", 2) == 0)
703 836 { {
704 837 printf ("Driver looks like Microsoft PE format\n"); printf ("Driver looks like Microsoft PE format\n");
705 838 ibase = imagebase(data); ibase = imagebase(data);
839 found = 1;
840 }
841
842 if (!found)
843 {
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 }
706 859 } }
707 else if (memcmp(data, "Joy!", 4) == 0)
860
861 if (!found && memcmp(data, "Joy!", 4) == 0)
708 862 { {
709 863 printf ("Driver looks like Apple PEF format\n"); printf ("Driver looks like Apple PEF format\n");
710 864 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,
724 878 /* ibase = pef_imagebase(data); */ /* ibase = pef_imagebase(data); */
725 879 return -5; return -5;
726 880 } }
727 else
881
882 if (!found)
728 883 { {
729 884 printf ("Unknown object file format\n"); printf ("Unknown object file format\n");
730 885 return -5; return -5;
 
... ... static int dump_fw(const char *basename, const char hexchar,
751 906
752 907 vfwoffs = (u32)(fw - data) + ibase; vfwoffs = (u32)(fw - data) + ibase;
753 908
754 printf("PE imagebase is 0x%08x, therefore virtual offset of firmware is 0x%08x\n",
909 printf("Image base is 0x%08x, therefore virtual offset of firmware is 0x%08x\n",
755 910 ibase, vfwoffs); ibase, vfwoffs);
756 911
757 912 fwblock = find_fwblock_entry(data, fwblock = find_fwblock_entry(data,
758 913 flen, flen,
759 vfwoffs);
914 vfwoffs,
915 ibase);
760 916 if (!fwblock) if (!fwblock)
761 917 return -2; return -2;
762 918
 
... ... static int dump_fw(const char *basename, const char hexchar,
766 922 if (!fw_image) if (!fw_image)
767 923 return -3; return -3;
768 924
769 copy_fw_data(&firmware, fw_image, data);
925 copy_fw_data(&firmware, fw_image, data, ibase);
770 926
771 927 /* Print FW ident information */ /* Print FW ident information */
772 928 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