dump_fw posted June 2007
[agere_fw_utils.git] / dump_fw.c
blobd0254ddd173534037da4ef28cd323a88673bd750
1 /*
2 * Program to link against Agere FW images, and dump contents to
3 * binary files for loading directly by linux drivers.
5 *
6 */
8 /* Output format (LE numbers)
10 * vers [6] The text HFW and 3 ASCII digits indicating version
11 * headersize [2] Size of header inc vers, headersize and length
12 * entry point [4] NIC address of entry point
13 * blocks [4] Number of blocks (n)
14 * blk_offset [4] Offset to block data
15 * pdr_offset [4] Offset to PDR data
16 * pri_offset [4] Offset to primary plug data
17 * cpt_offset [4] Offset to compatibility data
18 * signature [arb] firmware signature
19 * Block_1
20 * ..
21 * Block_n
22 * Block_term
23 * pda_1
24 * ..
25 * pda_n
26 * pda_term
28 * Where Block_n is:
29 * addr [4] NIC address to program data
30 * length [2] Number of bytes of data to program
31 * data [arbitrary] Data to program
33 * block term is:
34 * 0xFFFFFFFF [4] BLOCK_END identifier
35 * 0x0000 [2] zero length
37 * pda_n is:
38 * id [4] PDA identifier
39 * addr [4] Address to program PDA
40 * len [4] Number of bytes to program
42 * pda_term
43 * 0x00000000 [4] PDI_END
44 * 0x00000000 [4]
45 * 0x00000000 [4]
47 * There is more information available in the driver. In particular
48 * whether the block is supposed to be programmed to NV or volatile,
49 * and various flags.
51 * Apart from the header, the output format is compatible with the
52 * spectrum_cs image. The header is arbitrary.
54 * TODO: ensure the output is LE, rather than relying on x86 byte orderring
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include "dhf.h"
62 #define AP_SUFFIX "_ap.fw"
63 #define STA_SUFFIX "_sta.fw"
64 #define VERSION "HFW000"
67 size_t count_blocks(memimage *image)
69 CFG_PROG_STRCT *p = image->codep;
70 size_t count = 0;
71 while (p->len)
73 /* Ignore zero data segments which will not be written */
74 if (p->segment_size)
75 count++;
76 p++;
78 return count;
81 size_t count_pdr(plugrecord *r)
83 size_t count = 0;
84 if (r)
86 while (r->code)
88 count++;
89 r++;
92 return count;
95 size_t acc_block_size(memimage *image)
97 CFG_PROG_STRCT *p = image->codep;
98 size_t len = 0;
99 while (p->len)
101 if (p->segment_size)
102 len += p->segment_size;
103 p++;
105 return len;
108 typedef unsigned int u32;
109 typedef unsigned short u16;
111 void dump_blocks(FILE* f, memimage *image)
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)
118 if (p->segment_size)
120 /* 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);
125 /* else PROG_STOP, entry point command, or terminating block */
126 p++;
128 fwrite (&end_addr, 1, sizeof(end_addr), f);
129 fwrite (&end_size, 1, sizeof(end_size), f);
131 return;
134 void dump_pdr(FILE *f, plugrecord *r)
136 u32 end = 0u;
138 if (!r)
139 goto terminate;
141 while (r->code)
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);
146 r++;
148 terminate:
149 /* 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);
153 return;
156 void dump_image(FILE* f, memimage *image)
158 u32 blocks = count_blocks(image);
159 u32 blk_offset = 0; /* Immediately after header */
160 u32 pdr_offset = (acc_block_size(image) +
161 ((blocks + 1) * (sizeof(u32) + sizeof(u16))));
162 u32 pri_offset = pdr_offset +
163 ((count_pdr(image->pdaplug) + 1) * sizeof(u32) * 3);
164 u32 cpt_offset = pri_offset +
165 ((count_pdr(image->priplug) + 1) * sizeof(u32) * 3);
166 u16 headersize = ((sizeof(VERSION)-1) +
167 sizeof(u16) +
168 (sizeof(u32)*6) +
169 sizeof(image->signature));
171 fwrite (VERSION, 1, sizeof(VERSION)-1, f);
172 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);
179 fwrite (&image->signature, 1, sizeof(image->signature), f);
181 dump_blocks(f, image);
182 dump_pdr(f, image->pdaplug);
183 dump_pdr(f, image->priplug);
184 /* compat info not written */
186 return;
189 extern memimage ap;
190 extern memimage station;
192 int main (int argc, char** argv)
194 char *ap_filename;
195 char *sta_filename;
196 FILE *ap_file;
197 FILE *sta_file;
198 size_t len;
199 int rc = 0;
201 if (argc < 2)
203 printf("Please specify a root filename.\n"
204 "%s will be appended for primary firmware\n"
205 "%s will be appended for secondary firmaware\n",
206 AP_SUFFIX, STA_SUFFIX);
207 return 1;
210 len = strlen(argv[1]);
211 ap_filename = malloc(len + sizeof(AP_SUFFIX) + 1);
212 if (!ap_filename)
214 fprintf(stderr, "Out of memory\n");
215 return 1;
217 strncpy(ap_filename, argv[1], len);
218 ap_filename[len] = 0;
219 strcat(ap_filename, AP_SUFFIX);
221 ap_file = fopen(ap_filename, "w");
222 if (!ap_file)
224 fprintf(stderr, "Can't open %s for writing\n", ap_filename);
225 rc = 1;
227 else
229 dump_image(ap_file, &ap);
230 fclose(ap_file);
232 free(ap_filename);
234 sta_filename = malloc(len + sizeof(STA_SUFFIX) + 1);
235 if (!sta_filename)
237 fprintf(stderr, "Out of memory\n");
238 return 1;
240 strncpy(sta_filename, argv[1], len);
241 sta_filename[len] = 0;
242 strcat(sta_filename,STA_SUFFIX);
244 sta_file = fopen(sta_filename,"w");
245 if (!sta_file)
247 fprintf(stderr, "Can't open %s for writing\n", sta_filename);
248 rc = 1;
250 else
252 dump_image(sta_file, &station);
253 fclose(sta_file);
255 free(sta_filename);
257 return rc;