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();