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

Sources/firmware-utils/src/zynsig.c

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  *  Copyright (C) 2024-2025 Andreas Boehler <dev@aboehler.at>
  4  *  Copyright (C) 2007-2008 OpenWrt.org
  5  *  Copyright (C) 2007-2008 Gabor Juhos <juhosg at openwrt.org>
  6  *
  7  *  zynsig.c is basically a stripped-down version of mkzynfw.c,
  8  *  it just adds the required "SIG" header to the given file.
  9  *  This file is then accepted as a valid BootExt block by BootBase, to mask
 10  *  rt-loader as BootExt.
 11  */
 12 
 13 #include <stdio.h>
 14 #include <stdlib.h>
 15 #include <stdint.h>
 16 #include <string.h>
 17 #include <byteswap.h>
 18 #include <unistd.h>
 19 #include <libgen.h>
 20 #include <getopt.h>
 21 #include <sys/stat.h>
 22 #include <fcntl.h>
 23 #include <sys/mman.h>
 24 
 25 #include "zynos.h"
 26 
 27 #if (__BYTE_ORDER == __LITTLE_ENDIAN)
 28 #  define HOST_TO_LE16(x)       (x)
 29 #  define HOST_TO_LE32(x)       (x)
 30 #  define LE16_TO_HOST(x)       (x)
 31 #  define LE32_TO_HOST(x)       (x)
 32 #  define HOST_TO_BE16(x)       bswap_16(x)
 33 #  define HOST_TO_BE32(x)       bswap_32(x)
 34 #  define BE16_TO_HOST(x)       bswap_16(x)
 35 #  define BE32_TO_HOST(x)       bswap_32(x)
 36 #else
 37 #  define HOST_TO_BE16(x)       (x)
 38 #  define HOST_TO_BE32(x)       (x)
 39 #  define BE16_TO_HOST(x)       (x)
 40 #  define BE32_TO_HOST(x)       (x)
 41 #  define HOST_TO_LE16(x)       bswap_16(x)
 42 #  define HOST_TO_LE32(x)       bswap_32(x)
 43 #  define LE16_TO_HOST(x)       bswap_16(x)
 44 #  define LE32_TO_HOST(x)       bswap_32(x)
 45 #endif
 46 
 47 #define ALIGN(x,y)      (((x)+((y)-1)) & ~((y)-1))
 48 
 49 /*
 50  * Message macros
 51  */
 52 #define ERR(fmt, ...) do { \
 53         fflush(0); \
 54         fprintf(stderr, "[%s] *** error: " fmt "\n", \
 55                         progname, ## __VA_ARGS__ ); \
 56 } while (0)
 57 
 58 
 59 #define MAX_ARG_COUNT   32
 60 #define MAX_ARG_LEN     1024
 61 
 62 struct csum_state{
 63         int             odd;
 64         uint32_t        sum;
 65         uint32_t        tmp;
 66 };
 67 
 68 char *ofname = NULL;
 69 char *ifname = NULL;
 70 
 71 void *input_file = NULL;
 72 char *progname;
 73 uint32_t load_addr = 0x80100000;
 74 uint32_t mmap_addr = 0xb40e0000;
 75 
 76 /*
 77  * Helper routines
 78  */
 79 void
 80 usage(int status)
 81 {
 82         FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
 83 
 84         fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
 85         fprintf(stream, "\nOptions:\n");
 86         fprintf(stream,
 87 "  -i <file>\n"
 88 "                  input file, e.g. rt-loader image\n"
 89 "  -o <file>\n"
 90 "                  write output to the file <file>\n"
 91 "  -h              show this screen\n"
 92         );
 93 
 94         exit(status);
 95 }
 96 
 97 void
 98 csum_init(struct csum_state *css)
 99 {
100         css->odd = 0;
101         css->sum = 0;
102         css->tmp = 0;
103 }
104 
105 void
106 csum_update(void *data, uint32_t len, struct csum_state *css)
107 {
108         uint8_t *p = data;
109 
110         if (len == 0)
111                 return;
112 
113         if (css->odd) {
114                 css->sum += (css->tmp << 8) + p[0];
115                 if (css->sum > 0xFFFF) {
116                         css->sum += 1;
117                         css->sum &= 0xFFFF;
118                 }
119                 css->odd = 0;
120                 len--;
121                 p++;
122         }
123 
124         for ( ; len > 1; len -= 2, p +=2 ) {
125                 css->sum  += (p[0] << 8) + p[1];
126                 if (css->sum > 0xFFFF) {
127                         css->sum += 1;
128                         css->sum &= 0xFFFF;
129                 }
130         }
131 
132         if (len == 1){
133                 css->tmp = p[0];
134                 css->odd = 1;
135         }
136 }
137 
138 uint16_t
139 csum_get(struct csum_state *css)
140 {
141         char pad = 0;
142 
143         csum_update(&pad, 1, css);
144         return css->sum;
145 }
146 
147 uint16_t
148 csum_buf(uint8_t *p, uint32_t len)
149 {
150         struct csum_state css;
151 
152         csum_init(&css);
153         csum_update(p, len, &css);
154         return csum_get(&css);
155 
156 }
157 
158 static void
159 *map_input(const char *name, size_t *len)
160 {
161         struct stat stat;
162         void *mapped;
163         int fd;
164 
165         fd = open(name, O_RDONLY);
166         if (fd < 0)
167                 return NULL;
168         if (fstat(fd, &stat) < 0) {
169                 close(fd);
170                 return NULL;
171         }
172         *len = stat.st_size;
173         mapped = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);
174         if (close(fd) < 0) {
175                 (void) munmap(mapped, stat.st_size);
176                 return NULL;
177         }
178         return mapped;
179 }
180 
181 int
182 parse_arg(char *arg, char *buf, char *argv[])
183 {
184         int res = 0;
185         size_t argl;
186         char *tok;
187         char **ap = &buf;
188         int i;
189 
190         memset(argv, 0, MAX_ARG_COUNT * sizeof(void *));
191 
192         if ((arg == NULL)) {
193                 /* no arguments */
194                 return 0;
195         }
196 
197         argl = strlen(arg);
198         if (argl == 0) {
199                 /* no arguments */
200                 return 0;
201         }
202 
203         if (argl >= MAX_ARG_LEN) {
204                 /* argument is too long */
205                 argl = MAX_ARG_LEN-1;
206         }
207 
208         memcpy(buf, arg, argl);
209         buf[argl] = '\0';
210 
211         for (i = 0; i < MAX_ARG_COUNT; i++) {
212                 tok = strsep(ap, ":");
213                 if (tok == NULL) {
214                         break;
215                 }
216                 argv[i] = tok;
217                 res++;
218         }
219 
220         return res;
221 }
222 
223 int
224 required_arg(char c, char *arg)
225 {
226         if (arg == NULL || *arg != '-')
227                 return 0;
228 
229         ERR("option -%c requires an argument\n", c);
230         return -1;
231 }
232 
233 int
234 parse_opt_name(char ch, char *arg, char **dest)
235 {
236 
237         if (*dest != NULL) {
238                 ERR("only one input/output file allowed");
239                 return -1;
240         }
241 
242         if (required_arg(ch, arg))
243                 return -1;
244 
245         *dest = arg;
246 
247         return 0;
248 }
249 
250 int
251 is_empty_arg(char *arg)
252 {
253         int ret = 1;
254         if (arg != NULL) {
255                 if (*arg) ret = 0;
256         };
257         return ret;
258 }
259 
260 int main(int argc, char *argv[]) {
261         uint16_t csum;
262         size_t file_len = 0;
263         int optinvalid = 0;   /* flag for invalid option */
264         int res = EXIT_FAILURE;
265         int c;
266 
267         struct zyn_rombin_hdr bootext_hdr;
268 
269         FILE *outfile;
270 
271         progname=basename(argv[0]);
272 
273         opterr = 0;  /* could not print standard getopt error messages */
274         while ( 1 ) {
275                 optinvalid = 0;
276 
277                 c = getopt(argc, argv, "i:o:h");
278                 if (c == -1)
279                         break;
280 
281                 switch (c) {
282                 case 'i':
283                         optinvalid = parse_opt_name(c,optarg,&ifname);
284                         break;
285                 case 'o':
286                         optinvalid = parse_opt_name(c,optarg,&ofname);
287                         break;
288                 case 'h':
289                         usage(EXIT_SUCCESS);
290                         break;
291                 default:
292                         optinvalid = 1;
293                         break;
294                 }
295                 if (optinvalid != 0 ) {
296                         ERR("invalid option: -%c", optopt);
297                         goto out;
298                 }
299         }
300 
301         if(!ifname) {
302                 ERR("input file is mandatory");
303                 goto out;
304         }
305 
306         if(!ofname) {
307                 ERR("output file is mandatory");
308                 goto out;
309         }
310 
311         input_file = map_input(ifname, &file_len);
312         if(!input_file) {
313                 ERR("input file not found.");
314                 goto out;
315         }
316         csum = csum_buf((uint8_t*)input_file, file_len);
317 
318         memset(&bootext_hdr, 0, sizeof(bootext_hdr));
319         bootext_hdr.addr = HOST_TO_BE32(load_addr);
320         bootext_hdr.type = OBJECT_TYPE_BOOTEXT;
321 
322         memcpy(&bootext_hdr.sig, ROMBIN_SIGNATURE, ROMBIN_SIG_LEN);
323         bootext_hdr.osize = HOST_TO_BE32(file_len);
324         bootext_hdr.ocsum = HOST_TO_BE16(csum);
325         bootext_hdr.mmap_addr = HOST_TO_BE32(mmap_addr);
326 
327         bootext_hdr.flags = ROMBIN_FLAG_OCSUM;
328         bootext_hdr.csize = HOST_TO_BE32(0);
329         bootext_hdr.ccsum = HOST_TO_BE16(0);
330 
331         outfile = fopen(ofname, "w");
332         fwrite(&bootext_hdr, sizeof(bootext_hdr), 1, outfile);
333         fwrite(input_file, file_len, 1, outfile);
334         fflush(outfile);
335         fclose(outfile);
336 
337         res = EXIT_SUCCESS;
338 out:
339         if (res != EXIT_SUCCESS) {
340                 unlink(ofname);
341         }
342         if(input_file)
343                 munmap(input_file, file_len);
344         return res;
345 }
346 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt