2 * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published
6 * by the Free Software Foundation.
13 #include <unistd.h> /* for unlink() */
15 #include <getopt.h> /* for getopt() */
22 #include <arpa/inet.h>
23 #include <netinet/in.h>
25 #define IH_MAGIC 0x27051956 /* Image Magic Number */
26 #define IH_NMLEN 32 /* Image Name Length */
28 #define UM_MAGIC 0x55525F46
29 #define UM_HEADER_LEN 12
32 * all data in network byte order (aka natural aka bigendian)
34 struct u_media_header
{
35 uint32_t ih_magic
; /* Image Header Magic Number */
36 uint32_t ih_hcrc
; /* Image Header CRC Checksum */
37 uint32_t ih_time
; /* Image Creation Timestamp */
38 uint32_t ih_size
; /* Image Data Size */
39 uint32_t ih_load
; /* Data Load Address */
40 uint32_t ih_ep
; /* Entry Point Address */
41 uint32_t ih_dcrc
; /* Image Data CRC Checksum */
42 uint8_t ih_os
; /* Operating System */
43 uint8_t ih_arch
; /* CPU architecture */
44 uint8_t ih_type
; /* Image Type */
45 uint8_t ih_comp
; /* Compression Type */
46 uint8_t ih_name
[IH_NMLEN
- UM_HEADER_LEN
]; /* Image Name */
48 uint32_t ih_UMedia_magic
; /* U-Media magic number */
49 uint32_t ih_UMedia_boardID
; /* U-Media board ID */
50 uint8_t ih_UMedia_imageType
; /* U-Media image type */
51 uint8_t ih_UMedia_LoadDefault
; /* U-Media load to factory default setting */
52 uint8_t ih_UMedia_temp1
; /* U-Media didn't use this tag */
53 uint8_t ih_UMedia_temp2
; /* U-Media didn't use this tag */
54 } __attribute__ ((packed
));
57 char *file_name
; /* name of the file */
58 uint32_t file_size
; /* length of the file */
61 static char *progname
;
63 static struct if_info if_info
;
64 static int factory_defaults
;
65 static uint32_t board_id
;
66 static uint8_t image_type
;
71 #define ERR(fmt, ...) do { \
73 fprintf(stderr, "[%s] *** error: " fmt "\n", \
74 progname, ## __VA_ARGS__ ); \
77 #define ERRS(fmt, ...) do { \
80 fprintf(stderr, "[%s] *** error: " fmt " (%s)\n", \
81 progname, ## __VA_ARGS__, strerror(save)); \
84 #define DBG(fmt, ...) do { \
85 fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
88 static void usage(int status
)
90 FILE *stream
= (status
!= EXIT_SUCCESS
) ? stderr
: stdout
;
92 fprintf(stream
, "Usage: %s [OPTIONS...]\n", progname
);
96 " -B <board_id> set board ID to <board_id>\n"
97 " -i <file> read input from the file <file>\n"
98 " -F load factory defaults\n"
99 " -o <file> write output to the file <file>\n"
100 " -T <type> set image type to <type>\n"
101 " -h show this screen\n"
107 static int str2u32(char *arg
, uint32_t *val
)
113 t
= strtoul(arg
, &err
, 0);
114 if (errno
|| (err
==arg
) || ((err
!= NULL
) && *err
)) {
122 static int str2u8(char *arg
, uint8_t *val
)
128 t
= strtoul(arg
, &err
, 0);
129 if (errno
|| (err
==arg
) || ((err
!= NULL
) && *err
)) {
140 static int get_file_stat(struct if_info
*fdata
)
145 if (fdata
->file_name
== NULL
)
148 res
= stat(fdata
->file_name
, &st
);
150 ERRS("stat failed on %s", fdata
->file_name
);
154 fdata
->file_size
= st
.st_size
;
158 static int read_to_buf(struct if_info
*fdata
, char *buf
)
161 int ret
= EXIT_FAILURE
;
163 f
= fopen(fdata
->file_name
, "r");
165 ERRS("could not open \"%s\" for reading", fdata
->file_name
);
170 fread(buf
, fdata
->file_size
, 1, f
);
172 ERRS("unable to read from file \"%s\"", fdata
->file_name
);
184 static int check_options(void)
188 if (ofname
== NULL
) {
189 ERR("no %s specified", "output file");
193 if (if_info
.file_name
== NULL
) {
194 ERR("no %s specified", "input file");
198 ret
= get_file_stat(&if_info
);
205 static int write_fw(char *data
, int len
)
208 int ret
= EXIT_FAILURE
;
210 f
= fopen(ofname
, "w");
212 ERRS("could not open \"%s\" for writing", ofname
);
217 fwrite(data
, len
, 1, f
);
219 ERRS("unable to write output file");
228 if (ret
!= EXIT_SUCCESS
) {
235 static int fix_header(void)
239 uint32_t crc
, crc_orig
;
240 struct u_media_header
*hdr
;
241 int ret
= EXIT_FAILURE
;
243 buflen
= if_info
.file_size
;
244 if (buflen
< sizeof(*hdr
)) {
245 ERR("invalid input file\n");
249 buf
= malloc(buflen
);
251 ERR("no memory for buffer\n");
255 ret
= read_to_buf(&if_info
, buf
);
259 hdr
= (struct u_media_header
*) buf
;
260 if (ntohl(hdr
->ih_magic
) != IH_MAGIC
) {
261 ERR("invalid input file, bad magic\n");
265 /* verify header CRC */
266 crc_orig
= ntohl(hdr
->ih_hcrc
);
268 crc
= cyg_ether_crc32((unsigned char *)hdr
, sizeof(*hdr
));
269 if (crc
!= crc_orig
) {
270 ERR("invalid input file, bad header CRC\n");
274 hdr
->ih_name
[IH_NMLEN
- UM_HEADER_LEN
- 1] = '\0';
276 /* set U-Media specific fields */
277 hdr
->ih_UMedia_magic
= htonl(UM_MAGIC
);
278 hdr
->ih_UMedia_boardID
= htonl(board_id
);
279 hdr
->ih_UMedia_imageType
= image_type
;
280 hdr
->ih_UMedia_LoadDefault
= (factory_defaults
) ? 1 : 0;
282 /* update header CRC */
283 crc
= cyg_ether_crc32((unsigned char *)hdr
, sizeof(*hdr
));
284 hdr
->ih_hcrc
= htonl(crc
);
286 ret
= write_fw(buf
, buflen
);
290 DBG("U-Media header fixed in \"%s\"", ofname
);
300 int main(int argc
, char *argv
[])
302 int ret
= EXIT_FAILURE
;
304 progname
= basename(argv
[0]);
309 c
= getopt(argc
, argv
, "B:Fi:o:T:h");
315 if (str2u32(optarg
, &board_id
)) {
316 ERR("%s is invalid '%s'",
322 if (str2u8(optarg
, &image_type
)) {
323 ERR("%s is invalid '%s'",
324 "image type", optarg
);
329 factory_defaults
= 1;
332 if_info
.file_name
= optarg
;
346 ret
= check_options();