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)
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 77d205076542510222c6e8359bb2647b0d4e0873 - dump_fw and hfwget posted Sep 2007
Author: David Kilroy
Author date (UTC): 2008-10-26 14:22
Committer name: David Kilroy
Committer date (UTC): 2008-10-26 14:22
Parent(s): 9239c21487b524cf0f87b4ffa4828793713fbecd
Signing key:
Tree: 268b299155eeea2e7b341bc7a8adead9b071b593
File Lines added Lines deleted
README.dump_fw 37 5
dump_fw.c 191 38
dump_fw.mk 23 8
hfwget.c 246 32
File README.dump_fw changed (mode: 100644) (index f752eb0..8778f6f)
... ... To use the programs just do:
19 19 Which will produce root_ap.fw and root_sta.fw, with root replaced by Which will produce root_ap.fw and root_sta.fw, with root replaced by
20 20 whatever you specified. whatever you specified.
21 21
22 Enjoy,
22 If you want to use the wl_lkm_714 source tree instead, you can. See
23 instructions in dump_fw.mk
23 24
24 Dave Kilroy
25 June 2007.
25 KNOWN BUGS
26 ----------
27
28 1. Compatibility information offset present, but data not output.
29
30
31 hfwget
32 ------
33
34 Program to dump Lucent tertiary and Variant 2 FW images from windows
35 drivers (WLLUC48.SYS, WLLUC48B.SYS). Should work with Agere
36 (WLAGS48B.SYS) and Dell (WLDEL48B.SYS) drivers, and probably
37 others. The firmware images are intended to be used with the
38 orinoco_cs and hermes_dld Linux driver.
39
40 Compiled when building dump_fw above. Alternatively, extract into any
41 directory and run:
26 42
43 make -f dump_fw.mk hfwget
44
45 This will generate hfwget which will dump the firmware images it can
46 locate in the specified file. Just do:
47
48 ./hfwget <path to driver>
49
50 Which will output any of:
51 R02xxxxx.hfw Variant 2 firmware for RAM download
52 T02xxxxx.hfw Tertiary firmware
53 guess000.hfw Variant 2 firmware from Dell/old Lucent drivers.
27 54
28 55 KNOWN BUGS KNOWN BUGS
29 56 ---------- ----------
57 1. Will only work on a little endian machine.
30 58
31 1. Will only work on a little endian machine. Various numbers come out
32 backwards on a big endian machine.
33 59 2. Compatibility information offset present, but data not output. 2. Compatibility information offset present, but data not output.
60
61
62 Enjoy,
63
64 Dave Kilroy
65 September 2007.
File dump_fw.c changed (mode: 100644) (index d0254dd..65c74a4)
51 51 * Apart from the header, the output format is compatible with the * Apart from the header, the output format is compatible with the
52 52 * spectrum_cs image. The header is arbitrary. * spectrum_cs image. The header is arbitrary.
53 53 * *
54 * TODO: ensure the output is LE, rather than relying on x86 byte orderring
55 54 */ */
56 55
57 56 #include <stdio.h> #include <stdio.h>
 
63 62 #define STA_SUFFIX "_sta.fw" #define STA_SUFFIX "_sta.fw"
64 63 #define VERSION "HFW000" #define VERSION "HFW000"
65 64
65 /* 0xAABB to 0xBBAA */
66 #define swap_bytes_16(value) \
67 ((((value) >> 8) & 0xFF) | \
68 (((value) & 0xFF) << 8))
69 /* 0xAABBCCDD to 0xDDCCBBAA */
70 #define reverse_bytes_32(value) \
71 ((((value) >> 24) & 0x0000FF) | \
72 (((value) >> 8) & 0x00FF00) | \
73 (((value) << 8) & 0xFF0000) | \
74 (((value) & 0xFF) << 24))
75 /* 0xAABBCCDD to 0xBBAADDCC */
76 #define swap_bytes_32(value) \
77 ((((value) >> 8) & 0x00FF00FF) | \
78 (((value) << 8) & 0xFF00FF00))
79 /* 0xAABBCCDD to 0xCCDDAABB */
80 #define swap_words_32(value) \
81 ((((value) >> 16) & 0x0000FFFF) | \
82 (((value) << 16) & 0xFFFF0000))
83
84 /* address 0 1 2 3 */
85 /* Pure LE stores 0x12345678 as 0x78 0x56 0x34 0x12 */
86 /* Pure BE stores 0x12345678 as 0x12 0x34 0x56 0x78 */
87 /* BEW+LEB stores 0x12345678 as 0x34 0x12 0x78 0x56 */
88 /* LEW+BEB stores 0x12345678 as 0x56 0x78 0x12 0x34 */
89 int host_bytes_in_word_be = 0;
90 int host_words_in_dword_be = 0;
91
92 #define host_to_le16(value) \
93 host_bytes_in_word_be ? swap_bytes_16(value) : (value);
94 #define host_to_le32(value) \
95 host_words_in_dword_be ? \
96 (host_bytes_in_word_be ? reverse_bytes_32(value) \
97 : swap_bytes_32(value)) : \
98 (host_bytes_in_word_be ? swap_words_32(value) : (value));
99
100 #define le16_to_host(value) \
101 host_bytes_in_word_be ? swap_bytes_16(value) : (value);
102 #define le32_to_host(value) \
103 host_words_in_dword_be ? \
104 (host_bytes_in_word_be ? reverse_bytes_32(value) \
105 : swap_bytes_32(value)) : \
106 (host_bytes_in_word_be ? swap_words_32(value) : (value));
107
108 typedef unsigned int u32;
109 typedef unsigned short u16;
110 typedef unsigned char u8;
111
112 /* Checking endianess at runtime because performance isn't an issue,
113 * and I'd rather not add a configure step since this is slotting into the
114 * Agere source code. */
115 void check_endianess(void) {
116 union {
117 u32 dword;
118 u16 word[2];
119 u8 byte[4];
120 } data;
121
122 data.dword = 0x12345678;
123 if (data.word[0] == 0x1234) {
124 host_words_in_dword_be = 1;
125 }
126 else if (data.word[0] == 0x5678) {
127 host_words_in_dword_be = 0;
128 } else {
129 fprintf(stderr, "Can't determine endianess of host!\n");
130 exit(1);
131 }
132
133 data.word[0] = 0x1234;
134 if (data.byte[0] == 0x12) {
135 host_bytes_in_word_be = 1;
136 } else if (data.byte[0] == 0x34) {
137 host_bytes_in_word_be = 0;
138 } else {
139 fprintf(stderr, "Can't determine endianess of host!\n");
140 }
141
142 if (host_bytes_in_word_be == host_words_in_dword_be) {
143 fprintf (stdout, "Detected %s host\n",
144 host_bytes_in_word_be ? "big endian" : "little endian");
145 } else {
146 fprintf (stdout, "Detected host with mixed endianess\n");
147 }
148 return;
149 }
66 150
67 151 size_t count_blocks(memimage *image) size_t count_blocks(memimage *image)
68 152 { {
69 CFG_PROG_STRCT *p = image->codep;
153 #if __wl_lkm < 718
154 # define MEMBLOCK memblock
155 # define BLKSIZE p->size
156 # define IF_HAVE_SEGMENT
157 #else
158 # define MEMBLOCK CFG_PROG_STRCT
159 # define BLKSIZE p->len
160 # define IF_HAVE_SEGMENT if (p->segment_size)
161 #endif
162
163 MEMBLOCK *p = image->codep;
70 164 size_t count = 0; size_t count = 0;
71 while (p->len)
165 while (BLKSIZE)
72 166 { {
73 167 /* Ignore zero data segments which will not be written */ /* Ignore zero data segments which will not be written */
74 if (p->segment_size)
168 IF_HAVE_SEGMENT
169 {
75 170 count++; count++;
171 }
76 172 p++; p++;
77 173 } }
78 174 return count; return count;
79 175 } }
80 176
177
81 178 size_t count_pdr(plugrecord *r) size_t count_pdr(plugrecord *r)
82 179 { {
83 180 size_t count = 0; size_t count = 0;
 
... ... size_t count_pdr(plugrecord *r)
94 191
95 192 size_t acc_block_size(memimage *image) size_t acc_block_size(memimage *image)
96 193 { {
97 CFG_PROG_STRCT *p = image->codep;
194 #if __wl_lkm < 718
195 # define MEMBLOCK memblock
196 # define BLKSIZE p->size
197 # define SEGSIZE p->size
198 # define IF_HAVE_SEGMENT
199 #else
200 # define MEMBLOCK CFG_PROG_STRCT
201 # define BLKSIZE p->len
202 # define SEGSIZE p->segment_size
203 # define IF_HAVE_SEGMENT if (p->segment_size)
204 #endif
205
206 MEMBLOCK *p = image->codep;
98 207 size_t len = 0; size_t len = 0;
99 while (p->len)
208 while (BLKSIZE)
100 209 { {
101 if (p->segment_size)
102 len += p->segment_size;
210 /* Ignore zero data segments which will not be written */
211 IF_HAVE_SEGMENT
212 {
213 len += SEGSIZE;
214 }
103 215 p++; p++;
104 216 } }
105 217 return len; return len;
106 218 } }
107 219
108 typedef unsigned int u32;
109 typedef unsigned short u16;
110
111 220 void dump_blocks(FILE* f, memimage *image) void dump_blocks(FILE* f, memimage *image)
112 221 { {
113 CFG_PROG_STRCT *p = image->codep;
114 u32 end_addr = 0xFFFFFFFFu; /* Agree with spectrum BLOCK_END */
115 u16 end_size = 0u; /* a sensible size that won't screw the reader */
116 while (p->len)
222 #if __wl_lkm < 718
223 # define MEMBLOCK memblock
224 # define BLKSIZE p->size
225 # define SEGSIZE p->size
226 # define NICADDR p->addr
227 # define SEGDATA &(p->data[4]) /* Avoid initial CRC */
228 # define IF_HAVE_SEGMENT
229 #else
230 # define MEMBLOCK CFG_PROG_STRCT
231 # define BLKSIZE p->len
232 # define SEGSIZE p->segment_size
233 # define NICADDR p->nic_addr
234 # define SEGDATA p->host_addr
235 # define IF_HAVE_SEGMENT if (p->segment_size)
236 #endif
237
238 MEMBLOCK *p = image->codep;
239 u8 block_hdr[sizeof(NICADDR) + sizeof(SEGSIZE)];
240 u32 *addr = (u32 *) &block_hdr[0];
241 u16 *size = (u16 *) &block_hdr[sizeof(NICADDR)];
242
243 while (BLKSIZE)
117 244 { {
118 if (p->segment_size)
245 IF_HAVE_SEGMENT
119 246 { {
120 247 /* There is data to program in this block */ /* There is data to program in this block */
121 fwrite (&p->nic_addr, 1, sizeof(p->nic_addr), f);
122 fwrite (&p->segment_size, 1, sizeof(p->segment_size), f);
123 fwrite (p->host_addr, 1, p->segment_size, f);
248 *addr = host_to_le32(NICADDR);
249 *size = host_to_le16(SEGSIZE);
250 fwrite (&block_hdr, 1, sizeof(block_hdr), f);
251 fwrite (SEGDATA, 1, SEGSIZE, f);
124 252 } }
125 /* else PROG_STOP, entry point command, or terminating block */
126 253 p++; p++;
127 254 } }
128 fwrite (&end_addr, 1, sizeof(end_addr), f);
129 fwrite (&end_size, 1, sizeof(end_size), f);
255 *addr = host_to_le32(0xFFFFFFFFu); /* Agree with spectrum BLOCK_END */
256 *size = host_to_le16(0u);
257
258 fwrite (&block_hdr, 1, sizeof(block_hdr), f);
130 259
131 260 return; return;
132 261 } }
133 262
134 263 void dump_pdr(FILE *f, plugrecord *r) void dump_pdr(FILE *f, plugrecord *r)
135 264 { {
136 u32 end = 0u;
265 u8 pdr[sizeof(r->code) + sizeof(r->addr) + sizeof(r->len)];
266 u32 *code = (u32*) &pdr[0];
267 u32 *addr = (u32*) &pdr[sizeof(r->code)];
268 u32 *len = (u32*) &pdr[sizeof(r->code) + sizeof(r->addr)];
137 269
138 270 if (!r) if (!r)
139 271 goto terminate; goto terminate;
140 272
141 273 while (r->code) while (r->code)
142 274 { {
143 fwrite(&r->code, 1, sizeof(r->code), f);
144 fwrite(&r->addr, 1, sizeof(r->addr), f);
145 fwrite(&r->len, 1, sizeof(r->len), f);
275 *code = host_to_le32(r->code);
276 *addr = host_to_le32(r->addr);
277 *len = host_to_le32(r->len);
278 fwrite(&pdr, 1, sizeof(pdr), f);
146 279 r++; r++;
147 280 } }
148 281 terminate: terminate:
149 282 /* Terminate the PDR list */ /* Terminate the PDR list */
150 fwrite(&end, 1, sizeof(end), f);
151 fwrite(&end, 1, sizeof(end), f);
152 fwrite(&end, 1, sizeof(end), f);
283 *code = 0;
284 *addr = 0;
285 *len = 0;
286 fwrite(&pdr, 1, sizeof(pdr), f);
153 287 return; return;
154 288 } }
155 289
156 290 void dump_image(FILE* f, memimage *image) void dump_image(FILE* f, memimage *image)
157 291 { {
292 u32 image_header[6];
158 293 u32 blocks = count_blocks(image); u32 blocks = count_blocks(image);
159 294 u32 blk_offset = 0; /* Immediately after header */ u32 blk_offset = 0; /* Immediately after header */
160 295 u32 pdr_offset = (acc_block_size(image) + u32 pdr_offset = (acc_block_size(image) +
 
... ... void dump_image(FILE* f, memimage *image)
165 300 ((count_pdr(image->priplug) + 1) * sizeof(u32) * 3); ((count_pdr(image->priplug) + 1) * sizeof(u32) * 3);
166 301 u16 headersize = ((sizeof(VERSION)-1) + u16 headersize = ((sizeof(VERSION)-1) +
167 302 sizeof(u16) + sizeof(u16) +
168 (sizeof(u32)*6) +
169 sizeof(image->signature));
170
303 (sizeof(u32)*6)
304 #if __wl_lkm >= 718
305 + sizeof(image->signature)
306 #endif
307 );
308 u32 *ptr = &image_header[0];
171 309 fwrite (VERSION, 1, sizeof(VERSION)-1, f); fwrite (VERSION, 1, sizeof(VERSION)-1, f);
310 headersize = host_to_le16(headersize);
172 311 fwrite (&headersize, 1, sizeof(headersize), f); fwrite (&headersize, 1, sizeof(headersize), f);
173 fwrite (&image->execution, 1, sizeof(image->execution), f);
174 fwrite (&blocks, 1, sizeof(blocks), f);
175 fwrite (&blk_offset, 1, sizeof(blk_offset), f);
176 fwrite (&pdr_offset, 1, sizeof(pdr_offset), f);
177 fwrite (&pri_offset, 1, sizeof(pri_offset), f);
178 fwrite (&cpt_offset, 1, sizeof(cpt_offset), f);
312
313 *ptr = host_to_le32(image->execution);
314 ptr++;
315 *ptr = host_to_le32(blocks);
316 ptr++;
317 *ptr = host_to_le32(blk_offset);
318 ptr++;
319 *ptr = host_to_le32(pdr_offset);
320 ptr++;
321 *ptr = host_to_le32(pri_offset);
322 ptr++;
323 *ptr = host_to_le32(cpt_offset);
324 ptr++;
325 fwrite (&image_header, 1, sizeof(image_header), f);
326 #if __wl_lkm >= 718
179 327 fwrite (&image->signature, 1, sizeof(image->signature), f); fwrite (&image->signature, 1, sizeof(image->signature), f);
328 #endif
180 329
181 330 dump_blocks(f, image); dump_blocks(f, image);
182 331 dump_pdr(f, image->pdaplug); dump_pdr(f, image->pdaplug);
 
... ... int main (int argc, char** argv)
207 356 return 1; return 1;
208 357 } }
209 358
359 check_endianess();
360
210 361 len = strlen(argv[1]); len = strlen(argv[1]);
211 362 ap_filename = malloc(len + sizeof(AP_SUFFIX) + 1); ap_filename = malloc(len + sizeof(AP_SUFFIX) + 1);
212 363 if (!ap_filename) if (!ap_filename)
 
... ... int main (int argc, char** argv)
228 379 { {
229 380 dump_image(ap_file, &ap); dump_image(ap_file, &ap);
230 381 fclose(ap_file); fclose(ap_file);
382 fprintf (stdout, "Written %s\n", ap_filename);
231 383 } }
232 384 free(ap_filename); free(ap_filename);
233 385
 
... ... int main (int argc, char** argv)
251 403 { {
252 404 dump_image(sta_file, &station); dump_image(sta_file, &station);
253 405 fclose(sta_file); fclose(sta_file);
406 fprintf (stdout, "Written %s\n", sta_filename);
254 407 } }
255 408 free(sta_filename); free(sta_filename);
256 409
File dump_fw.mk changed (mode: 100644) (index 83c9587..03da4a8)
2 2 # Makefile for wlags49_cs_xxx # Makefile for wlags49_cs_xxx
3 3 # #
4 4
5 # NOTE if compiling wl_lkm_714:
6 # - the firmware files need to be modified to include "mmd.h" instead of "..\hcf\mmd.h"
7 # - include/hcf/hcfcfg.h line 775 should be commented out
8 # - select the appropriate DIR_FW and LKM_CFLAGS values below
9
5 10 LIB := ../lib LIB := ../lib
6 11
7 12 DIR_HCF = hcf DIR_HCF = hcf
8 13 DIR_DHF = dhf DIR_DHF = dhf
9 DIR_FW = dhf
14 # 714 firmware is in
15 #DIR_FW = dhf
16 # 718 firmware is in
17 DIR_FW = firmware
10 18 DIR_CONFIG = include/hcf DIR_CONFIG = include/hcf
11 19 DIR_WIRELESS = include/wireless DIR_WIRELESS = include/wireless
12 20
 
... ... WIRELESS_HEADERS = $(DIR_WIRELESS)/wl_enc.h $(DIR_WIRELESS)/wl_if.h $(DIR_WIR
17 25
18 26 OBJS = dump_fw.o OBJS = dump_fw.o
19 27
20 CFLAGS += -O3 -Wall -Wstrict-prototypes -pipe -DHCF_DLV
21 CPPFLAGS +=
28 CFLAGS = -O3 -Wall -Wstrict-prototypes -pipe
29 # CFLAGS for wl_lkm_714
30 #LKM_CFLAGS = -D__wl_lkm=714
31 # CFLAGS for wl_lkm_718
32 LKM_CFLAGS = -DHCF_DLV -D__wl_lkm=718
33 CPPFLAGS =
22 34 CC = gcc -I$(DIR_CONFIG) -I$(DIR_HCF) -I$(DIR_DHF) CC = gcc -I$(DIR_CONFIG) -I$(DIR_HCF) -I$(DIR_DHF)
23 35
24 H2_OBJS = firmware/ap_h2.o firmware/sta_h2.o
36 H2_OBJS = $(DIR_FW)/ap_h2.o $(DIR_FW)/sta_h2.o
25 37 H2_CFLAGS = -DHCF_TYPE=4 H2_CFLAGS = -DHCF_TYPE=4
26 38
27 H1_OBJS = firmware/ap_h1.o firmware/sta_h1.o
39 H1_OBJS = $(DIR_FW)/ap_h1.o $(DIR_FW)/sta_h1.o
28 40 H1_CFLAGS = -DHCF_TYPE=0 H1_CFLAGS = -DHCF_TYPE=0
29 41
30 42
31 43
32 44 # H1-STAP and H2-STAP are the default targets # H1-STAP and H2-STAP are the default targets
33 all: dump_h1_fw dump_h2_fw
45 all: dump_h1_fw dump_h2_fw hfwget
34 46
35 dump_h1_fw : CFLAGS+=$(H1_CFLAGS)
47 dump_h1_fw : CFLAGS+= $(LKM_CFLAGS) $(H1_CFLAGS)
36 48 dump_h1_fw : $(OBJS) $(H1_OBJS) dump_h1_fw : $(OBJS) $(H1_OBJS)
37 49 gcc $(CFLAGS) $^ -o $@ gcc $(CFLAGS) $^ -o $@
38 50
39 dump_h2_fw : CFLAGS+=$(H2_CFLAGS)
51 dump_h2_fw : CFLAGS+= $(LKM_CFLAGS) $(H2_CFLAGS)
40 52 dump_h2_fw : $(OBJS) $(H2_OBJS) dump_h2_fw : $(OBJS) $(H2_OBJS)
41 53 gcc $(CFLAGS) $^ -o $@ gcc $(CFLAGS) $^ -o $@
42 54
55 hfwget : hfwget.c
56 gcc $(CFLAGS) $^ -o $@
57
43 58 clean : clean :
44 59 rm $(OBJS) $(H1_OBJS) $(H2_OBJS) dump_h1_fw dump_h2_fw rm $(OBJS) $(H1_OBJS) $(H2_OBJS) dump_h1_fw dump_h2_fw
File hfwget.c changed (mode: 100644) (index c3f0952..a7a3b4c)
2 2 * Hermes AP firmware extractor for Windows drivers (c) 2003 by Mark Smith * Hermes AP firmware extractor for Windows drivers (c) 2003 by Mark Smith
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 *
6 * Following modifications (c) 2007 David Kilroy
7 * primary plug data
8 * compatibility info
9 * firmware identification
10 * unidentified drivers (guesswork for wldel48b, and old wlluc48)
11 * binary output format for linux kernel driver
12 *
13 * These modifications may be distributed freely under the GPL v2 so
14 * long as this copyright notice is included.
5 15 */ */
6 16 #include <stdio.h> #include <stdio.h>
7 17 #include <stdlib.h> #include <stdlib.h>
 
... ... struct _plugarray {
23 33 unsigned int length; unsigned int length;
24 34 }; };
25 35
36 struct _ident_info {
37 unsigned short int size;
38 unsigned short int code;
39 unsigned short int comp_id;
40 unsigned short int variant;
41 unsigned short int version_major;
42 unsigned short int version_minor;
43 };
44
45 struct _compat_info {
46 unsigned short int size;
47 unsigned short int code;
48 unsigned short int role;
49 unsigned short int id;
50 struct
51 {
52 unsigned short int variant;
53 unsigned short int bottom;
54 unsigned short int top;
55 } range[20];
56 };
57
26 58 struct firmwareblock { struct firmwareblock {
27 struct _segarray *segarray;
28 unsigned int halfentry;
29 struct _plugarray *plugarray;
59 struct _segarray *segarray;
60 unsigned int halfentry;
61 struct _plugarray *plugarray;
62 struct _plugarray *pri_plugarray;
63 struct _compat_info *compat;
64 struct _ident_info *ident;
30 65 } *firmware; } *firmware;
31 66
67 static const struct
68 {
69 unsigned short int id;
70 char *comp_string;
71 } compat_table[] =
72 {
73 /* Firmware type */
74 { 21, "Primary firmware" },
75 { 22, "Intermediate firmware" },
76 { 31, "Station firmware" },
77 { 32, "AP firmware" },
78
79 /* Driver type */
80 { 41, "Windows 9x/NT Miniport NDIS 3.1" },
81 { 42, "Packet" },
82 { 43, "DOS ODI" },
83 { 44, "32 bit ODI" },
84 { 45, "Mac OS" },
85 { 46, "Windows CE Miniport" },
86 { 47, "Linux HCF-light based (public domain)" },
87 { 48, "Windows 9x/NT Miniport NDIS 5.0" },
88 { 49, "Linux HCF-library based" },
89 { 50, "QNX" },
90 { 51, "Windows 9x/NT Miniport NDIS 5.0 USB" },
91 { 52, "Windows 9x/NT Miniport NDIS 4.0" },
92 { 53, "VxWorks END Station driver" },
93 { 54, "VxWorks END Access Point driver" },
94 { 55, "Mac OS?" },
95 { 56, "VxWorks END Station/AP driver" },
32 96
33 void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature, unsigned char hexchar);
97 /* Others */
98 { 63, "WaveLAN Station FW update utility" },
99 { 81, "WaveLAN/IEEE AP" },
100 { 83, "WaveLAN/IEEE Ethernet Converter" },
101 { 87, "USB Boot Loader" },
102 };
103
104 static int savefirmware(unsigned char *data,
105 unsigned int flen,
106 unsigned int signature,
107 unsigned char hexchar);
34 108
35 109 /* /*
36 110 * Main * Main
37 111 */ */
38 112 int main(int argc, char *argv[]) int main(int argc, char *argv[])
39 113 { {
40 FILE *input, *output;
41 unsigned char *data, *offset, *end, *hexstringoffs, *page1start, *peheader;
42 unsigned char hexstring[16];
43 unsigned int i, j, flen, found, imagebase, vfwoffs, fwblock;
114 FILE *input;
115 unsigned char *data;
116 unsigned int flen;
44 117
45 118 printf("Lucent Firmware Extractor v1.0 alpha\n(c) 2003 Mark Smith (username 'Mark' on HermesAP board)\n"); printf("Lucent Firmware Extractor v1.0 alpha\n(c) 2003 Mark Smith (username 'Mark' on HermesAP board)\n");
46 119
 
... ... int main(int argc, char *argv[])
70 143 fclose(input); fclose(input);
71 144
72 145 // Dump Tertiary firmware // Dump Tertiary firmware
73 printf("\nAttempting to dump tertiary firmware:\n");
74 savefirmware(data, flen, 0xfbfe4461, 'T');
146 printf("\nAttempting to dump tertiary (AP) firmware:\n");
147 (void) savefirmware(data, flen, 0xfbfe4461, 'T');
75 148 printf("\nAttempting to dump station firmware:\n"); printf("\nAttempting to dump station firmware:\n");
76 savefirmware(data, flen, 0x63fc600f, 'R');
149 (void) savefirmware(data, flen, 0x63fc600f, 'R');
77 150
78 151 free(data); free(data);
79 152 printf("\nAll dumps complete.\n\n"); printf("\nAll dumps complete.\n\n");
80 153 return 0; return 0;
81 154 } }
82 155
83 void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature, unsigned char hexchar)
156 #define GUESS_OFFSET 0xC000
157 #define GUESS_FILENAME "guess000.hex"
158
159 /* Returns zero, or a negative number to indicate an error */
160 static int savefirmware(unsigned char *data,
161 unsigned int flen,
162 unsigned int signature,
163 unsigned char hexchar)
84 164 { {
85 165 FILE *output; FILE *output;
86 166 unsigned char *offset, *end, *hexstringoffs, *page1start, *peheader; unsigned char *offset, *end, *hexstringoffs, *page1start, *peheader;
87 167 unsigned char hexstring[16]; unsigned char hexstring[16];
88 unsigned int i, j, found, imagebase, vfwoffs, fwblock;
168 unsigned int i, found, imagebase, vfwoffs, fwblock;
89 169
90 170 // Find the ?1XXYYZZ.HEX string // Find the ?1XXYYZZ.HEX string
91 171 offset = data; offset = data;
92 172 end = (unsigned char *)((unsigned int)data + flen); end = (unsigned char *)((unsigned int)data + flen);
173
93 174 for (found = false; found == false && offset != NULL; ) { for (found = false; found == false && offset != NULL; ) {
94 175 offset = memchr(offset, hexchar, (unsigned int)(end - offset)); offset = memchr(offset, hexchar, (unsigned int)(end - offset));
95 176
 
... ... void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature
102 183 } }
103 184 } }
104 185
105 if (offset == NULL) {
106 printf("%c-firmware not found!\n", hexchar);
107 exit(-1);
108 }
186 if (offset != NULL)
187 {
188 strncpy(hexstring, offset, 13);
189 hexstring[13] = 0;
109 190
110 strncpy(hexstring, offset, 13);
111 hexstring[13] = 0;
191 printf("Found firmware %s at file offset 0x%08x\n",
192 hexstring, offset-data);
193 }
194 else
195 {
196 printf("%c-firmware not found!\n", hexchar);
197 printf("searching for signature from 0x%x\n", GUESS_OFFSET);
198
199 strncpy(hexstring, GUESS_FILENAME,13);
200 hexstring[13] = 0;
201 offset = data + GUESS_OFFSET;
202 }
112 203
113 printf("Found firmware %s at file offset 0x%08x\n", hexstring, offset-data);
114 204 printf("Searching for firmware start signature 0x%08x...\n", signature); printf("Searching for firmware start signature 0x%08x...\n", signature);
115 205
116 206 // Really should use a mask here, but its not necessary for the moment. // Really should use a mask here, but its not necessary for the moment.
 
... ... void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature
121 211
122 212 if (found == false) { if (found == false) {
123 213 printf("Signature not found!\n"); printf("Signature not found!\n");
124 exit(-2);
214 return -2;
125 215 } else { } else {
126 216 page1start = offset; page1start = offset;
127 217
 
... ... void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature
129 219 } }
130 220
131 221 peheader = (unsigned char *)(*(unsigned int *)(data + 0x3c)); peheader = (unsigned char *)(*(unsigned int *)(data + 0x3c));
132 printf("Reading DOS driver header...\nPE header located at file offset 0x%08x\n", peheader);
222 printf("Reading DOS driver header...\nPE header located at file offset 0x%p\n", peheader);
133 223 imagebase = (unsigned int)(*(unsigned int *)((unsigned int)peheader + (unsigned int)data + 0x34)); imagebase = (unsigned int)(*(unsigned int *)((unsigned int)peheader + (unsigned int)data + 0x34));
134 224 vfwoffs = (unsigned int)((unsigned int)page1start - (unsigned int)data + imagebase); vfwoffs = (unsigned int)((unsigned int)page1start - (unsigned int)data + imagebase);
135 225 printf("PE imagebase is 0x%08x, therefore virtual offset of firmware is 0x%08x\n", printf("PE imagebase is 0x%08x, therefore virtual offset of firmware is 0x%08x\n",
 
... ... void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature
145 235 fwblock = (unsigned int)offset - 7 + imagebase - (unsigned int)data; fwblock = (unsigned int)offset - 7 + imagebase - (unsigned int)data;
146 236 if (found == false) { if (found == false) {
147 237 printf("Tertiary table not found - contact Mark!\n"); printf("Tertiary table not found - contact Mark!\n");
148 exit(-3);
238 return -3;
149 239 } else { } else {
150 240 printf("Found at virtual offset 0x%08x\n", fwblock); printf("Found at virtual offset 0x%08x\n", fwblock);
151 241 } }
 
... ... void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature
159 249 firmware = (struct firmwareblock *)++offset; firmware = (struct firmwareblock *)++offset;
160 250 if (found == false) { if (found == false) {
161 251 printf("Main table not found - contact Mark!\n"); printf("Main table not found - contact Mark!\n");
162 exit(-4);
252 return -4;
163 253 } else { } else {
164 254 printf("Found at file offset 0x%08x\n", offset - data); printf("Found at file offset 0x%08x\n", offset - data);
165 255 } }
166 256
167 257
168 258 printf("Entry point at 0x%08x\n", firmware->halfentry * 2); printf("Entry point at 0x%08x\n", firmware->halfentry * 2);
169 (unsigned int)firmware->segarray += (unsigned int)data - imagebase;
259 firmware->segarray = (struct _segarray *)
260 ((unsigned int)firmware->segarray +
261 (unsigned int)data - imagebase);
170 262 for (i = 0; i < 4 && firmware->segarray[i].offset != 0; i++) { for (i = 0; i < 4 && firmware->segarray[i].offset != 0; i++) {
171 (unsigned int)firmware->segarray[i].data -= imagebase - 4;
263 unsigned int temp =
264 ((unsigned int)firmware->segarray[i].data - (imagebase - 4));
265 firmware->segarray[i].data = (unsigned char *) (temp + data);
172 266 printf("Segment: %d File offs: 0x%08x Target mem: 0x%08x Length 0x%08x\n", printf("Segment: %d File offs: 0x%08x Target mem: 0x%08x Length 0x%08x\n",
173 267 i, i,
174 firmware->segarray[i].data,
268 temp,
175 269 firmware->segarray[i].offset, firmware->segarray[i].offset,
176 270 firmware->segarray[i].size); firmware->segarray[i].size);
177 271 } }
178 printf("Plugrecords at file offset 0x%08x\n", (unsigned int)firmware->plugarray - imagebase);
272 printf("Production Data plugrecords at file offset 0x%08x\n", (unsigned int)firmware->plugarray - imagebase);
179 273
180 274 hexstring[9] = 0; hexstring[9] = 0;
181 275 strcat(hexstring, "hfw"); strcat(hexstring, "hfw");
 
... ... void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature
183 277 printf("Dumping to %s...\n", hexstring); printf("Dumping to %s...\n", hexstring);
184 278 if ((output = fopen(hexstring, "wb")) == NULL) { if ((output = fopen(hexstring, "wb")) == NULL) {
185 279 printf("Unable to open %s, aborting.\n", hexstring); printf("Unable to open %s, aborting.\n", hexstring);
186 exit(-5);
280 return -5;
187 281 } }
188 282
189 (unsigned int)firmware->plugarray += (unsigned int)data - imagebase;
283 firmware->plugarray = (struct _plugarray *)
284 ((unsigned int)firmware->plugarray +
285 (unsigned int)data - imagebase);
190 286
287
288 printf("Primary plugrecords at file offset 0x%08x\n", (unsigned int)firmware->pri_plugarray - imagebase);
289 printf("Compatibility info at file offset 0x%08x\n", (unsigned int)firmware->compat - imagebase);
290 printf("Identity info at file offset 0x%08x\n", (unsigned int)firmware->ident - imagebase);
291
292 firmware->pri_plugarray = (struct _plugarray *)
293 ((unsigned int) firmware->pri_plugarray +
294 (unsigned int)data - imagebase);
295 firmware->compat = (struct _compat_info *)
296 ((unsigned int)firmware->compat +
297 (unsigned int)data - imagebase);
298 firmware->ident = (struct _ident_info *)
299 ((unsigned int)firmware->ident +
300 (unsigned int)data - imagebase);
301
302 if (firmware->ident->code == 0xFD20u)
303 {
304 for (i = 0;
305 i < sizeof(compat_table)/sizeof(compat_table[0]);
306 i++)
307 {
308 if (compat_table[i].id == firmware->ident->comp_id)
309 break;
310 }
311 /* Print FW ident information */
312 printf("Firmware identity: %s, Variant %d Version %d.%2d\n",
313 compat_table[i].comp_string,
314 firmware->ident->variant,
315 firmware->ident->version_major,
316 firmware->ident->version_minor);
317 }
318
319 #if 0 /* original hermesap format */
191 320 fprintf(output, "HFW1\nENTRY %08X\n", firmware->halfentry * 2); fprintf(output, "HFW1\nENTRY %08X\n", firmware->halfentry * 2);
192 321 for (i = 0; firmware->plugarray[i].code != 0; i++) { for (i = 0; firmware->plugarray[i].code != 0; i++) {
193 322 fprintf(output, "PLUG %08X %08X %08X\n", fprintf(output, "PLUG %08X %08X %08X\n",
 
... ... void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature
196 325 firmware->plugarray[i].length); firmware->plugarray[i].length);
197 326 } }
198 327
199 for (i = 0; firmware->segarray[i].offset != 0; i++) {
200 (unsigned int)firmware->segarray[i].data += (unsigned int)data;
328 for (i = 0; firmware->segarray[i].offset != 0; i++)
329 {
330 unsigned int j;
201 331 if (i != 0) if (i != 0)
202 332 fprintf(output, "\n"); fprintf(output, "\n");
203 333 fprintf(output, "SEG %08X %08X %08X", fprintf(output, "SEG %08X %08X %08X",
 
... ... void savefirmware(unsigned char *data, unsigned int flen, unsigned int signature
216 346 } }
217 347
218 348 fputc('\n', output); fputc('\n', output);
349 #else /* binary kernel format */
350 /* Note: does not deal with BE/LE issues */
351 {
352 unsigned long int l = 0;
353 unsigned short int s = 0;
354 unsigned long int prev_offset = 0;
355 fwrite ("HFW000", 1, 6, output);
356 s = 6 + 2 + (6*4) + 16; // headersize
357 fwrite (&s, 1, sizeof(s), output);
358 l = firmware->halfentry; // entrypoint
359 fwrite (&l, 1, sizeof(l), output);
360 l = 2; // number of blocks, hardcoded for now
361 fwrite (&l, 1, sizeof(l), output);
362 l = 0; // offset to block data
363 fwrite (&l, 1, sizeof(l), output);
364
365 // pdr offset
366 l = 0;
367 for (s = 0; firmware->segarray[s].offset != 0; s++)
368 {
369 l += firmware->segarray[s].size;
370 }
371 l = l + (s + 1) * (4 + 2);
372 fwrite (&l, 1, sizeof(l), output);
373
374 // pri offset
375 prev_offset = l;
376 for (l = 0; firmware->plugarray[l].code != 0; l++);
377 l = prev_offset + (l+1) * 4 * 3;
378 fwrite (&l, 1, sizeof(l), output);
379
380 // cpt offset
381 prev_offset = l;
382 for (l = 0; firmware->pri_plugarray[l].code != 0; l++);
383 l = prev_offset + (l+1) * 4 * 3;
384 fwrite (&l, 1, sizeof(l), output);
385 fwrite ("1234567890123456",1,16,output); // fw sig
386
387 for (i = 0; firmware->segarray[i].offset != 0; i++)
388 {
389 l = firmware->segarray[i].offset; // addr
390 s = firmware->segarray[i].size; // size
391
392 if (s > 0)
393 {
394 fwrite(&l, 1, sizeof(l), output);
395 fwrite(&s, 1, sizeof(s), output);
396 fwrite(firmware->segarray[i].data,1,s,output); // data
397 }
398 }
399 l = 0xFFFFFFFFu; // set block end
400 s = 0;
401 fwrite(&l, 1, sizeof(l), output);
402 fwrite(&s, 1, sizeof(s), output);
403
404 for (i = 0; firmware->plugarray[i].code != 0; i++) {
405 l = firmware->plugarray[i].code;
406 fwrite(&l, 1, sizeof(l), output);
407 l = firmware->plugarray[i].targ_off;
408 fwrite(&l, 1, sizeof(l), output);
409 l = firmware->plugarray[i].length;
410 fwrite(&l, 1, sizeof(l), output);
411 }
412 l = 0; // pdr end
413 fwrite(&l, 1, sizeof(l), output);
414 fwrite(&l, 1, sizeof(l), output);
415 fwrite(&l, 1, sizeof(l), output);
416
417 for (i = 0; firmware->pri_plugarray[i].code != 0; i++) {
418 l = firmware->pri_plugarray[i].code;
419 fwrite(&l, 1, sizeof(l), output);
420 l = firmware->pri_plugarray[i].targ_off;
421 fwrite(&l, 1, sizeof(l), output);
422 l = firmware->pri_plugarray[i].length;
423 fwrite(&l, 1, sizeof(l), output);
424 }
425 l = 0; // pdr end
426 fwrite(&l, 1, sizeof(l), output);
427 fwrite(&l, 1, sizeof(l), output);
428 fwrite(&l, 1, sizeof(l), output);
429 }
430 #endif
219 431 fclose(output); fclose(output);
220 432 printf("Dump of %s complete.\n", hexstring); printf("Dump of %s complete.\n", hexstring);
433
434 return 0; /* success */
221 435 } }
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