2 * Program to link against Agere FW images, and dump contents to
3 * binary files for loading directly by linux drivers.
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
29 * addr [4] NIC address to program data
30 * length [2] Number of bytes of data to program
31 * data [arbitrary] Data to program
34 * 0xFFFFFFFF [4] BLOCK_END identifier
35 * 0x0000 [2] zero length
38 * id [4] PDA identifier
39 * addr [4] Address to program PDA
40 * len [4] Number of bytes to program
43 * 0x00000000 [4] PDI_END
47 * There is more information available in the driver. In particular
48 * whether the block is supposed to be programmed to NV or volatile,
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
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
;
73 /* Ignore zero data segments which will not be written */
81 size_t count_pdr(plugrecord
*r
)
95 size_t acc_block_size(memimage
*image
)
97 CFG_PROG_STRCT
*p
= image
->codep
;
102 len
+= p
->segment_size
;
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 */
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 */
128 fwrite (&end_addr
, 1, sizeof(end_addr
), f
);
129 fwrite (&end_size
, 1, sizeof(end_size
), f
);
134 void dump_pdr(FILE *f
, plugrecord
*r
)
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
);
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
);
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) +
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 */
190 extern memimage station
;
192 int main (int argc
, char** argv
)
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
);
210 len
= strlen(argv
[1]);
211 ap_filename
= malloc(len
+ sizeof(AP_SUFFIX
) + 1);
214 fprintf(stderr
, "Out of memory\n");
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");
224 fprintf(stderr
, "Can't open %s for writing\n", ap_filename
);
229 dump_image(ap_file
, &ap
);
234 sta_filename
= malloc(len
+ sizeof(STA_SUFFIX
) + 1);
237 fprintf(stderr
, "Out of memory\n");
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");
247 fprintf(stderr
, "Can't open %s for writing\n", sta_filename
);
252 dump_image(sta_file
, &station
);