3 fpkg - Package a firmware
4 Copyright (C) 2007 Jonathan Zarate
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 #include <arpa/inet.h>
32 #define ROUNDUP(n, a) ((n + (a - 1)) & ~(a - 1))
34 #define TRX_MAGIC 0x30524448
36 #define TRX_MAX_OFFSET 3
37 #define TRX_MAX_LEN ((8 * 1024 * 1024) - ((256 + 128) * 1024)) // 8MB - (256K cfe + 128K cfg)
43 uint32_t flag_version
;
44 uint32_t offsets
[TRX_MAX_OFFSET
];
47 char names
[TRX_MAX_OFFSET
][80];
67 uint32_t *crc_table
= NULL
;
79 if (crc_table
== NULL
) {
80 if ((crc_table
= malloc(sizeof(uint32_t) * 256)) == NULL
) return 0;
81 for (i
= 255; i
>= 0; --i
) {
83 for (j
= 8; j
> 0; --j
) {
84 if (c
& 1) c
= (c
>> 1) ^ 0xEDB88320L
;
99 uint32_t crc_calc(uint32_t crc
, uint8_t *buf
, int len
)
102 crc
= crc_table
[(crc
^ *buf
) & 0xFF] ^ (crc
>> 8);
111 "fpkg - Package a firmware\n"
112 "Copyright (C) 2007 Jonathan Zarate\n"
114 "Usage: -i <input> [-i <input>] {output}\n"
116 " TRX: -t <output file>\n"
117 " Linksys: -l <id>,<output file>\n"
118 " W54G WRT54G / WRT54GL\n"
122 " Motorola: -m <id>,<output file>\n"
123 " 0x10577000 WE800\n"
124 " 0x10577040 WA840\n"
125 " 0x10577050 WR850\n"
131 void load_image(const char *fname
)
139 fprintf(stderr
, "Cannot load another image if an output has already been written.\n");
142 if (trx_count
>= TRX_MAX_OFFSET
) {
143 fprintf(stderr
, "Too many input files.\n");
147 if (stat(fname
, &st
) != 0) {
151 if (st
.st_ctime
> max_time
) max_time
= st
.st_ctime
;
153 rsize
= ROUNDUP(st
.st_size
, 4);
154 if ((trx
->length
+ rsize
) > TRX_MAX_LEN
) {
155 fprintf(stderr
, "Total size is too big.\n");
159 p
= (char *)trx
+ trx
->length
;
160 if ((f
= fopen(fname
, "r")) == NULL
) {
164 if (fread((char *)trx
+ trx
->length
, st
.st_size
, 1, f
) != 1) {
169 strncpy(names
[trx_count
], fname
, sizeof(names
[0]) -1);
170 trx
->offsets
[trx_count
++] = trx
->length
;
171 trx
->length
+= rsize
;
174 void finalize_trx(void)
178 if (trx_count
== 0) {
179 fprintf(stderr
, "No image was loaded.\n");
183 if (trx_final
) return;
188 trx
->length
= ROUNDUP(len
, 4096);
189 trx
->magic
= TRX_MAGIC
;
190 trx
->flag_version
= TRX_VERSION
<< 16;
191 trx
->crc32
= crc_calc(0xFFFFFFFF, (void *)&trx
->flag_version
,
192 trx
->length
- (sizeof(*trx
) - (sizeof(trx
->flag_version
) + sizeof(trx
->offsets
))));
194 trx_padding
= trx
->length
- len
;
197 void create_trx(const char *fname
)
203 printf("Creating TRX: %s\n", fname
);
205 if (((f
= fopen(fname
, "w")) == NULL
) ||
206 (fwrite(trx
, trx
->length
, 1, f
) != 1)) {
213 void create_cytan(const char *fname
, const char *pattern
)
217 char padding
[1024 - sizeof(h
)];
220 if (strlen(pattern
) != 4) {
221 fprintf(stderr
, "Linksys signature must be 4 characters. \"%s\" is invalid.\n", pattern
);
227 printf("Creating Linksys %s: %s\n", pattern
, fname
);
229 memset(&h
, 0, sizeof(h
));
230 memcpy(h
.magic
, pattern
, 4);
231 memcpy(h
.u2nd
, "U2ND", 4);
232 h
.version
[0] = 4; // 4.0.0 should be >= *_VERSION_FROM defined in code_pattern.h
234 tm
= localtime(&max_time
);
235 h
.date
[0] = tm
->tm_year
- 100;
236 h
.date
[1] = tm
->tm_mon
+ 1;
237 h
.date
[2] = tm
->tm_mday
;
239 memset(padding
, 0, sizeof(padding
));
241 if (((f
= fopen(fname
, "w")) == NULL
) ||
242 (fwrite(&h
, sizeof(h
), 1, f
) != 1) ||
243 (fwrite(trx
, trx
->length
, 1, f
) != 1) ||
244 (fwrite(padding
, sizeof(padding
), 1, f
) != 1)) {
251 void create_moto(const char *fname
, const char *signature
)
257 h
.magic
= strtoul(signature
, &p
, 0);
262 printf("Creating Motorola 0x%08X: %s\n", h
.magic
, fname
);
264 h
.magic
= htonl(h
.magic
);
265 h
.crc32
= crc_calc(0xFFFFFFFF, (void *)&h
.magic
, sizeof(h
.magic
));
266 h
.crc32
= htonl(crc_calc(h
.crc32
, (void *)trx
, trx
->length
));
268 if (((f
= fopen(fname
, "w")) == NULL
) ||
269 (fwrite(&h
, sizeof(h
), 1, f
) != 1) ||
270 (fwrite(trx
, trx
->length
, 1, f
) != 1)) {
277 int main(int argc
, char **argv
)
286 if ((!crc_init()) || ((trx
= calloc(1, TRX_MAX_LEN
)) == NULL
)) {
287 fprintf(stderr
, "Not enough memory\n");
290 trx
->length
= sizeof(*trx
);
292 while ((o
= getopt(argc
, argv
, "i:t:l:m:")) != -1) {
302 if (strlen(optarg
) >= sizeof(s
)) help();
304 if ((p
= strchr(s
, ',')) == NULL
) help();
307 if (o
== 'l') create_cytan(p
, s
);
308 else create_moto(p
, s
);
316 if (trx_count
== 0) {
321 l
= trx
->length
- trx_padding
- sizeof(*trx
);
322 printf("\nTRX Image:\n");
323 printf(" Total Size .... : %u (%.1f KB) (%.1f MB)\n", trx
->length
, trx
->length
/ 1024.0, trx
->length
/ 1024.0 / 1024.0);
324 printf(" Images ...... : %u (0x%08x)\n", l
, l
);
325 printf(" Padding ..... : %d\n", trx_padding
);
326 /* Reserved: 2 EBs for pmon, 1 EB for nvram. */
327 if (l
< (4 * 1024 * 1024) - (3 * 64 * 1024))
328 l
= (4 * 1024 * 1024) - (3 * 64 * 1024) - l
;
331 printf(" Avail for jffs. : %d EBs + %d\n", l
/ (64*1024), l
% (64*1024));
332 printf(" CRC-32 ........ : %8X\n", trx
->crc32
);
333 l
= (ROUNDUP(trx
->length
, (128 * 1024)) / (128 * 1024));
334 printf(" 128K Blocks ... : %u (0x%08X)\n", l
, l
);
335 l
= (ROUNDUP(trx
->length
, (64 * 1024)) / (64 * 1024));
336 printf(" 64K Blocks ... : %u (0x%08X)\n", l
, l
);
337 printf(" Offsets:\n");
338 for (o
= 0; o
< TRX_MAX_OFFSET
; ++o
) {
339 printf(" %d: 0x%08X %s\n", o
, trx
->offsets
[o
], names
[o
]);