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