1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
9 #include <unistd.h> /* for unlink() */
11 #include <getopt.h> /* for getopt() */
18 #include <arpa/inet.h>
19 #include <netinet/in.h>
21 #define IH_MAGIC 0x27051956 /* Image Magic Number */
22 #define IH_NMLEN 32 /* Image Name Length */
24 #define UM_MAGIC 0x55525F46
25 #define UM_HEADER_LEN 12
28 * all data in network byte order (aka natural aka bigendian)
30 struct u_media_header
{
31 uint32_t ih_magic
; /* Image Header Magic Number */
32 uint32_t ih_hcrc
; /* Image Header CRC Checksum */
33 uint32_t ih_time
; /* Image Creation Timestamp */
34 uint32_t ih_size
; /* Image Data Size */
35 uint32_t ih_load
; /* Data Load Address */
36 uint32_t ih_ep
; /* Entry Point Address */
37 uint32_t ih_dcrc
; /* Image Data CRC Checksum */
38 uint8_t ih_os
; /* Operating System */
39 uint8_t ih_arch
; /* CPU architecture */
40 uint8_t ih_type
; /* Image Type */
41 uint8_t ih_comp
; /* Compression Type */
42 uint8_t ih_name
[IH_NMLEN
- UM_HEADER_LEN
]; /* Image Name */
44 uint32_t ih_UMedia_magic
; /* U-Media magic number */
45 uint32_t ih_UMedia_boardID
; /* U-Media board ID */
46 uint8_t ih_UMedia_imageType
; /* U-Media image type */
47 uint8_t ih_UMedia_LoadDefault
; /* U-Media load to factory default setting */
48 uint8_t ih_UMedia_temp1
; /* U-Media didn't use this tag */
49 uint8_t ih_UMedia_temp2
; /* U-Media didn't use this tag */
50 } __attribute__ ((packed
));
53 char *file_name
; /* name of the file */
54 uint32_t file_size
; /* length of the file */
57 static char *progname
;
59 static struct if_info if_info
;
60 static int factory_defaults
;
61 static uint32_t board_id
;
62 static uint8_t image_type
;
67 #define ERR(fmt, ...) do { \
69 fprintf(stderr, "[%s] *** error: " fmt "\n", \
70 progname, ## __VA_ARGS__ ); \
73 #define ERRS(fmt, ...) do { \
76 fprintf(stderr, "[%s] *** error: " fmt " (%s)\n", \
77 progname, ## __VA_ARGS__, strerror(save)); \
80 #define DBG(fmt, ...) do { \
81 fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
84 static void usage(int status
)
86 FILE *stream
= (status
!= EXIT_SUCCESS
) ? stderr
: stdout
;
88 fprintf(stream
, "Usage: %s [OPTIONS...]\n", progname
);
92 " -B <board_id> set board ID to <board_id>\n"
93 " -i <file> read input from the file <file>\n"
94 " -F load factory defaults\n"
95 " -o <file> write output to the file <file>\n"
96 " -T <type> set image type to <type>\n"
97 " -h show this screen\n"
103 static int str2u32(char *arg
, uint32_t *val
)
109 t
= strtoul(arg
, &err
, 0);
110 if (errno
|| (err
==arg
) || ((err
!= NULL
) && *err
)) {
118 static int str2u8(char *arg
, uint8_t *val
)
124 t
= strtoul(arg
, &err
, 0);
125 if (errno
|| (err
==arg
) || ((err
!= NULL
) && *err
)) {
136 static int get_file_stat(struct if_info
*fdata
)
141 if (fdata
->file_name
== NULL
)
144 res
= stat(fdata
->file_name
, &st
);
146 ERRS("stat failed on %s", fdata
->file_name
);
150 fdata
->file_size
= st
.st_size
;
154 static int read_to_buf(struct if_info
*fdata
, char *buf
)
157 int ret
= EXIT_FAILURE
;
159 f
= fopen(fdata
->file_name
, "r");
161 ERRS("could not open \"%s\" for reading", fdata
->file_name
);
166 fread(buf
, fdata
->file_size
, 1, f
);
168 ERRS("unable to read from file \"%s\"", fdata
->file_name
);
180 static int check_options(void)
184 if (ofname
== NULL
) {
185 ERR("no %s specified", "output file");
189 if (if_info
.file_name
== NULL
) {
190 ERR("no %s specified", "input file");
194 ret
= get_file_stat(&if_info
);
201 static int write_fw(char *data
, int len
)
204 int ret
= EXIT_FAILURE
;
206 f
= fopen(ofname
, "w");
208 ERRS("could not open \"%s\" for writing", ofname
);
213 fwrite(data
, len
, 1, f
);
215 ERRS("unable to write output file");
224 if (ret
!= EXIT_SUCCESS
) {
231 static int fix_header(void)
235 uint32_t crc
, crc_orig
;
236 struct u_media_header
*hdr
;
237 int ret
= EXIT_FAILURE
;
239 buflen
= if_info
.file_size
;
240 if (buflen
< sizeof(*hdr
)) {
241 ERR("invalid input file\n");
245 buf
= malloc(buflen
);
247 ERR("no memory for buffer\n");
251 ret
= read_to_buf(&if_info
, buf
);
255 hdr
= (struct u_media_header
*) buf
;
256 if (ntohl(hdr
->ih_magic
) != IH_MAGIC
) {
257 ERR("invalid input file, bad magic\n");
261 /* verify header CRC */
262 crc_orig
= ntohl(hdr
->ih_hcrc
);
264 crc
= cyg_ether_crc32((unsigned char *)hdr
, sizeof(*hdr
));
265 if (crc
!= crc_orig
) {
266 ERR("invalid input file, bad header CRC\n");
270 hdr
->ih_name
[IH_NMLEN
- UM_HEADER_LEN
- 1] = '\0';
272 /* set U-Media specific fields */
273 hdr
->ih_UMedia_magic
= htonl(UM_MAGIC
);
274 hdr
->ih_UMedia_boardID
= htonl(board_id
);
275 hdr
->ih_UMedia_imageType
= image_type
;
276 hdr
->ih_UMedia_LoadDefault
= (factory_defaults
) ? 1 : 0;
278 /* update header CRC */
279 crc
= cyg_ether_crc32((unsigned char *)hdr
, sizeof(*hdr
));
280 hdr
->ih_hcrc
= htonl(crc
);
282 ret
= write_fw(buf
, buflen
);
286 DBG("U-Media header fixed in \"%s\"", ofname
);
296 int main(int argc
, char *argv
[])
298 int ret
= EXIT_FAILURE
;
300 progname
= basename(argv
[0]);
305 c
= getopt(argc
, argv
, "B:Fi:o:T:h");
311 if (str2u32(optarg
, &board_id
)) {
312 ERR("%s is invalid '%s'",
318 if (str2u8(optarg
, &image_type
)) {
319 ERR("%s is invalid '%s'",
320 "image type", optarg
);
325 factory_defaults
= 1;
328 if_info
.file_name
= optarg
;
342 ret
= check_options();