• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/mkzcfw.c

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
  4  */
  5 
  6 #include <stdio.h>
  7 #include <stdlib.h>
  8 #include <stdint.h>
  9 #include <string.h>
 10 #include <byteswap.h>
 11 #include <unistd.h>     /* for unlink() */
 12 #include <libgen.h>
 13 #include <getopt.h>     /* for getopt() */
 14 #include <stdarg.h>
 15 #include <errno.h>
 16 #include <sys/stat.h>
 17 
 18 #include "cyg_crc.h"
 19 
 20 #if (__BYTE_ORDER == __BIG_ENDIAN)
 21 #  define HOST_TO_BE32(x)       (x)
 22 #  define BE32_TO_HOST(x)       (x)
 23 #  define HOST_TO_LE32(x)       bswap_32(x)
 24 #  define LE32_TO_HOST(x)       bswap_32(x)
 25 #else
 26 #  define HOST_TO_BE32(x)       bswap_32(x)
 27 #  define BE32_TO_HOST(x)       bswap_32(x)
 28 #  define HOST_TO_LE32(x)       (x)
 29 #  define LE32_TO_HOST(x)       (x)
 30 #endif
 31 
 32 #define MAGIC_FIRMWARE  0x6d726966      /* 'firm' */
 33 #define MAGIC_KERNEL    0x676d694b      /* 'Kimg' */
 34 #define MAGIC_ROOTFS    0x676d6952      /* 'Rimg' */
 35 
 36 struct file_info {
 37         char            *file_name;     /* name of the file */
 38         uint32_t        file_size;      /* length of the file */
 39 };
 40 
 41 struct fw_header {
 42         uint32_t        magic;
 43         uint32_t        length;
 44         uint32_t        unk1;
 45         uint32_t        unk2;
 46 } __attribute__ ((packed));
 47 
 48 struct fw_tail {
 49         uint32_t        hw_id;
 50         uint32_t        crc;
 51 } __attribute__ ((packed));
 52 
 53 struct board_info {
 54         char            *id;
 55         uint32_t        hw_id;
 56         uint32_t        kernel_len;
 57         uint32_t        rootfs_len;
 58 };
 59 
 60 /*
 61  * Globals
 62  */
 63 static char *ofname;
 64 static char *progname;
 65 
 66 static char *board_id;
 67 static struct board_info *board;
 68 static struct file_info kernel_info;
 69 static struct file_info rootfs_info;
 70 
 71 
 72 static struct board_info boards[] = {
 73         {
 74                 .id             = "ZCN-1523H-2-8",
 75                 .hw_id          = 0x66661523,
 76                 .kernel_len     = 0x170000,
 77                 .rootfs_len     = 0x610000,
 78         }, {
 79                 .id             = "ZCN-1523H-5-16",
 80                 .hw_id          = 0x6615235A,
 81                 .kernel_len     = 0x170000,
 82                 .rootfs_len     = 0x610000,
 83         }, {
 84                 /* terminating entry */
 85         }
 86 };
 87 
 88 /*
 89  * Message macros
 90  */
 91 #define ERR(fmt, ...) do { \
 92         fflush(0); \
 93         fprintf(stderr, "[%s] *** error: " fmt "\n", \
 94                         progname, ## __VA_ARGS__ ); \
 95 } while (0)
 96 
 97 #define ERRS(fmt, ...) do { \
 98         int save = errno; \
 99         fflush(0); \
100         fprintf(stderr, "[%s] *** error: " fmt ": %s\n", \
101                         progname, ## __VA_ARGS__, strerror(save)); \
102 } while (0)
103 
104 #define DBG(fmt, ...) do { \
105         fprintf(stderr, "[%s] " fmt "\n", progname, ## __VA_ARGS__ ); \
106 } while (0)
107 
108 static struct board_info *find_board(char *id)
109 {
110         struct board_info *ret;
111         struct board_info *board;
112 
113         ret = NULL;
114         for (board = boards; board->id != NULL; board++){
115                 if (strcasecmp(id, board->id) == 0) {
116                         ret = board;
117                         break;
118                 }
119         };
120 
121         return ret;
122 }
123 
124 static void usage(int status)
125 {
126         FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
127 
128         fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
129         fprintf(stream,
130 "\n"
131 "Options:\n"
132 "  -B <board>      create image for the board specified with <board>\n"
133 "  -k <file>       read kernel image from the file <file>\n"
134 "  -r <file>       read rootfs image from the file <file>\n"
135 "  -o <file>       write output to the file <file>\n"
136 "  -h              show this screen\n"
137         );
138 
139         exit(status);
140 }
141 
142 static int get_file_stat(struct file_info *fdata)
143 {
144         struct stat st;
145         int res;
146 
147         if (fdata->file_name == NULL)
148                 return 0;
149 
150         res = stat(fdata->file_name, &st);
151         if (res){
152                 ERRS("stat failed on %s", fdata->file_name);
153                 return res;
154         }
155 
156         fdata->file_size = st.st_size;
157         return 0;
158 }
159 
160 static int read_to_buf(struct file_info *fdata, char *buf)
161 {
162         FILE *f;
163         int ret = EXIT_FAILURE;
164 
165         f = fopen(fdata->file_name, "r");
166         if (f == NULL) {
167                 ERRS("could not open \"%s\" for reading", fdata->file_name);
168                 goto out;
169         }
170 
171         errno = 0;
172         fread(buf, fdata->file_size, 1, f);
173         if (errno != 0) {
174                 ERRS("unable to read from file \"%s\"", fdata->file_name);
175                 goto out_close;
176         }
177 
178         ret = EXIT_SUCCESS;
179 
180  out_close:
181         fclose(f);
182  out:
183         return ret;
184 }
185 
186 static int check_options(void)
187 {
188         int ret;
189 
190         if (board_id == NULL) {
191                 ERR("no board specified");
192                 return -1;
193         }
194 
195         board = find_board(board_id);
196         if (board == NULL) {
197                 ERR("unknown/unsupported board id \"%s\"", board_id);
198                 return -1;
199         }
200 
201         if (kernel_info.file_name == NULL) {
202                 ERR("no kernel image specified");
203                 return -1;
204         }
205 
206         ret = get_file_stat(&kernel_info);
207         if (ret)
208                 return ret;
209 
210         if (kernel_info.file_size > board->kernel_len) {
211                 ERR("kernel image is too big");
212                 return -1;
213         }
214 
215         if (rootfs_info.file_name == NULL) {
216                 ERR("no rootfs image specified");
217                 return -1;
218         }
219 
220         ret = get_file_stat(&rootfs_info);
221         if (ret)
222                 return ret;
223 
224         if (rootfs_info.file_size > board->rootfs_len) {
225                 ERR("rootfs image is too big");
226                 return -1;
227         }
228 
229         if (ofname == NULL) {
230                 ERR("no output file specified");
231                 return -1;
232         }
233 
234         return 0;
235 }
236 
237 static int write_fw(char *data, int len)
238 {
239         FILE *f;
240         int ret = EXIT_FAILURE;
241 
242         f = fopen(ofname, "w");
243         if (f == NULL) {
244                 ERRS("could not open \"%s\" for writing", ofname);
245                 goto out;
246         }
247 
248         errno = 0;
249         fwrite(data, len, 1, f);
250         if (errno) {
251                 ERRS("unable to write output file");
252                 goto out_flush;
253         }
254 
255         DBG("firmware file \"%s\" completed", ofname);
256 
257         ret = EXIT_SUCCESS;
258 
259  out_flush:
260         fflush(f);
261         fclose(f);
262         if (ret != EXIT_SUCCESS) {
263                 unlink(ofname);
264         }
265  out:
266         return ret;
267 }
268 
269 static int build_fw(void)
270 {
271         int buflen;
272         char *buf;
273         char *p;
274         int ret = EXIT_FAILURE;
275         struct fw_header *hdr;
276         struct fw_tail *tail;
277 
278         buflen = 3 * sizeof(struct fw_header) +
279                  kernel_info.file_size + rootfs_info.file_size +
280                  3 * sizeof(struct fw_tail);
281 
282         buf = malloc(buflen);
283         if (!buf) {
284                 ERR("no memory for buffer\n");
285                 goto out;
286         }
287 
288         p = buf;
289         memset(p, 0, buflen);
290 
291         /* fill firmware header */
292         hdr = (struct fw_header *) p;
293         hdr->magic = HOST_TO_LE32(MAGIC_FIRMWARE);
294         hdr->length = HOST_TO_LE32(buflen - sizeof(struct fw_header));
295         p += sizeof(struct fw_header);
296 
297         /* fill kernel block header */
298         hdr = (struct fw_header *) p;
299         hdr->magic = HOST_TO_LE32(MAGIC_KERNEL);
300         hdr->length = HOST_TO_LE32(kernel_info.file_size +
301                                    sizeof(struct fw_tail));
302         p += sizeof(struct fw_header);
303 
304         /* read kernel data */
305         ret = read_to_buf(&kernel_info, p);
306         if (ret)
307                 goto out_free_buf;
308 
309         /* fill firmware tail */
310         tail = (struct fw_tail *) (p + kernel_info.file_size);
311         tail->hw_id = HOST_TO_BE32(board->hw_id);
312         tail->crc = HOST_TO_BE32(cyg_crc32(p, kernel_info.file_size +
313                                            sizeof(struct fw_tail) - 4));
314 
315         p += kernel_info.file_size + sizeof(struct fw_tail);
316 
317         /* fill rootfs block header */
318         hdr = (struct fw_header *) p;
319         hdr->magic = HOST_TO_LE32(MAGIC_ROOTFS);
320         hdr->length = HOST_TO_LE32(rootfs_info.file_size +
321                                    sizeof(struct fw_tail));
322         p += sizeof(struct fw_header);
323 
324         /* read rootfs data */
325         ret = read_to_buf(&rootfs_info, p);
326         if (ret)
327                 goto out_free_buf;
328 
329         /* fill firmware tail */
330         tail = (struct fw_tail *) (p + rootfs_info.file_size);
331         tail->hw_id = HOST_TO_BE32(board->hw_id);
332         tail->crc = HOST_TO_BE32(cyg_crc32(p, rootfs_info.file_size +
333                                            sizeof(struct fw_tail) - 4));
334 
335         p += rootfs_info.file_size + sizeof(struct fw_tail);
336 
337         /* fill firmware tail */
338         tail = (struct fw_tail *) p;
339         tail->hw_id = HOST_TO_BE32(board->hw_id);
340         tail->crc = HOST_TO_BE32(cyg_crc32(buf + sizeof(struct fw_header),
341                                  buflen - sizeof(struct fw_header) - 4));
342 
343         ret = write_fw(buf, buflen);
344         if (ret)
345                 goto out_free_buf;
346 
347         ret = EXIT_SUCCESS;
348 
349  out_free_buf:
350         free(buf);
351  out:
352         return ret;
353 }
354 
355 int main(int argc, char *argv[])
356 {
357         int ret = EXIT_FAILURE;
358 
359         progname = basename(argv[0]);
360 
361         while ( 1 ) {
362                 int c;
363 
364                 c = getopt(argc, argv, "B:k:r:o:h");
365                 if (c == -1)
366                         break;
367 
368                 switch (c) {
369                 case 'B':
370                         board_id = optarg;
371                         break;
372                 case 'k':
373                         kernel_info.file_name = optarg;
374                         break;
375                 case 'r':
376                         rootfs_info.file_name = optarg;
377                         break;
378                 case 'o':
379                         ofname = optarg;
380                         break;
381                 case 'h':
382                         usage(EXIT_SUCCESS);
383                         break;
384                 default:
385                         usage(EXIT_FAILURE);
386                         break;
387                 }
388         }
389 
390         ret = check_options();
391         if (ret)
392                 goto out;
393 
394         ret = build_fw();
395 
396  out:
397         return ret;
398 }
399 
400 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt