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

Sources/firmware-utils/src/zytrx.c

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * zytrx - add header to images for ZyXEL NR7101
  4  *
  5  * Based on add_header.c - partially based on OpenWrt's
  6  * motorola-bin.c
  7  *
  8  * Copyright (C) 2008 Imre Kaloz  <kaloz@openwrt.org>
  9  *                    Gabor Juhos <juhosg@openwrt.org>
 10  * Copyright (C) 2021 Bjørn Mork <bjorn@mork.no>
 11  */
 12 
 13 #include <stdio.h>
 14 #include <stdlib.h>
 15 #include <stddef.h>
 16 #include <unistd.h>
 17 #include <errno.h>
 18 #include <fcntl.h>
 19 #include <sys/mman.h>
 20 #include <sys/stat.h>
 21 #include <string.h>
 22 #include <netinet/in.h>
 23 #include <inttypes.h>
 24 
 25 #define BPB 8 /* bits/byte */
 26 
 27 static uint32_t crc32[1<<BPB];
 28 
 29 static void init_crc32(void)
 30 {
 31         const uint32_t poly = ntohl(0x2083b8ed);
 32         int n;
 33 
 34         for (n = 0; n < 1<<BPB; n++) {
 35                 uint32_t crc = n;
 36                 int bit;
 37 
 38                 for (bit = 0; bit < BPB; bit++)
 39                         crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1);
 40                 crc32[n] = crc;
 41         }
 42 }
 43 
 44 static uint32_t crc32buf(const unsigned char *buf, size_t len)
 45 {
 46         uint32_t crc = 0xFFFFFFFF;
 47 
 48         for (; len; len--, buf++)
 49                 crc = crc32[(uint8_t)crc ^ *buf] ^ (crc >> BPB);
 50         return ~crc;
 51 }
 52 
 53 /* HDR0 reversed, to be stored as BE */
 54 #define MAGIC           0x30524448  /* HDR0 reversed, to be stored as BE */
 55 
 56 /* All numbers are stored as BE */
 57 struct zytrx_t {
 58         uint32_t magic;
 59         uint32_t len_h;         /* Length of this header */
 60         uint32_t len_t;         /* Total length of file  */
 61         uint32_t crc32_p;       /* Bit inverted 32-bit CRC of image payload */
 62         uint8_t  verInt[32];    /* String "5.0.0.0\n" zero padded */
 63         uint8_t  verExt[32];    /* String "\n" zero padded */
 64         uint32_t len_p;         /* Length of image payload */
 65         uint8_t  pad1[12];      /* zero padding(?) */
 66         uint8_t  code[164];     /* string "3 6035 122 0\n" zero padded */
 67         uint8_t  chipid[8];     /* string "MT7621A" zero padded */
 68         uint8_t  boardid[16];   /* string "NR7101" zero padded */
 69         uint32_t modelid;       /* modelid as 4 BCD digits: 0x07010001 */
 70         uint8_t  pad2[8];       /* zero padding(?) */
 71         uint8_t  swVersionInt[32];      /* ZyXEL version string: "1.00(ABUV.0)D0" zero padded */
 72         uint8_t  swVersionExt[32];      /* identical to swVersionInt  */
 73         uint8_t  pad4[4];       /* zero padding(?) */
 74         uint32_t kernelChksum;  /* no idea how this is computed - reported but not validated */
 75         uint8_t  pad5[4];       /* zero padding(?) */
 76         uint32_t crc32_h;       /* Bit inverted 32-bit CRC of this header payload */
 77         uint8_t  pad6[4];       /* zero padding(?) */
 78 };
 79 
 80 /* static?() field values of unknown meaning - maybe ove to board
 81  * table when we know the significance
 82  */
 83 #define VER_INT         "5.0.0.0\n"
 84 #define VER_EXT         "\n"
 85 #define CODE            "3 6035 122 0\n"
 86 #define KERNELCHKSUM    0x12345678
 87 
 88 /* table of supported devices using this header format */
 89 static struct board_t {
 90         uint8_t  chipid[8];
 91         uint8_t  boardid[16];
 92         uint32_t modelid;
 93 } boards[] = {
 94         { "MT7621A", "NR7101", 0x07010001 },
 95         { "MT7621A", "LTE3301-PLUS", 0x03030001  },
 96         { "MT7621A", "LTE5398-M904", 0x05030908 },
 97         { "MT7621A", "LTE7490-M904", 0x07040900 },
 98         {}
 99 };
100 
101 static int find_board(struct zytrx_t *h, char *board)
102 {
103         struct board_t *p;
104 
105         for (p = boards; p->modelid; p++) {
106                 if (strncmp((const char *)p->boardid, board, sizeof(p->boardid)))
107                         continue;
108                 memcpy(h->chipid, p->chipid, sizeof(h->chipid));
109                 memcpy(h->boardid, p->boardid, sizeof(h->boardid));
110                 h->modelid = htonl(p->modelid);
111                 return 0;
112         }
113         return -1;
114 }
115 
116 static void usage(const char *name)
117 {
118         struct board_t *p;
119 
120         fprintf(stderr, "Usage:\n");
121         fprintf(stderr, " %s -B <board> -v <versionstr> -i <file> [-o <outputfile>]\n\n", name);
122         fprintf(stderr, "Supported <board> values:\n");
123         for (p = boards; p->modelid; p++)
124                 fprintf(stderr, "\t%-12s\n", p->boardid);
125         fprintf(stderr, "\nExample:\n");
126         fprintf(stderr, " %s -B %s -v foobar-1.0 -i my.img -o out.img\n\n", name,
127                 boards[0].boardid);
128         exit(EXIT_FAILURE);
129 }
130 
131 static void errexit(const char *msg)
132 {
133         fprintf(stderr, "ERR: %s: %s\n", msg, errno ? strerror(errno) : "unknown");
134         exit(EXIT_FAILURE);
135 }
136 
137 static void *map_input(const char *name, size_t *len)
138 {
139         struct stat stat;
140         void *mapped;
141         int fd;
142 
143         fd = open(name, O_RDONLY);
144         if (fd < 0)
145                 return NULL;
146         if (fstat(fd, &stat) < 0) {
147                 close(fd);
148                 return NULL;
149         }
150         *len = stat.st_size;
151         mapped = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);
152         if (close(fd) < 0) {
153                 (void) munmap(mapped, stat.st_size);
154                 return NULL;
155         }
156         return mapped;
157 }
158 
159 int main(int argc, char **argv)
160 {
161         int c, fdout = STDOUT_FILENO;
162         void *input_file = NULL;
163         size_t file_len, len;
164         uint32_t crc;
165         struct zytrx_t h = {
166                 .magic          = htonl(MAGIC),
167                 .len_h          = htonl(sizeof(h)),
168                 .verInt         = VER_INT,
169                 .verExt         = VER_EXT,
170                 .code           = CODE,
171                 .kernelChksum   = htonl(KERNELCHKSUM),
172         };
173 
174         while ((c = getopt(argc, argv, "B:v:i:o:")) != -1) {
175                 switch (c) {
176                 case 'B':
177                         if (find_board(&h, optarg) < 0)
178                                 errexit("unsupported board");
179                         break;
180                 case 'v':
181                         len = strlen(optarg);
182                         if (len > sizeof(h.swVersionInt))
183                                 errexit("version string too long");
184                         memcpy(h.swVersionInt, optarg, len);
185                         memcpy(h.swVersionExt, optarg, len);
186                         break;
187                 case 'i':
188                         input_file = map_input(optarg, &file_len);
189                         if (!input_file)
190                                 errexit(optarg);
191                         break;
192                 case 'o':
193                         fdout = open(optarg, O_WRONLY | O_CREAT, 0644);
194                         if (fdout < 0)
195                                 errexit(optarg);
196                         break;
197                 default:
198                         usage(argv[0]);
199                 }
200         }
201 
202         /* required paremeters */
203         if (!input_file || !h.modelid || !h.swVersionInt[0])
204                 usage(argv[0]);
205 
206         /* length fields */
207         h.len_t = htonl(sizeof(h) + file_len);
208         h.len_p = htonl(file_len);
209 
210         /* crc fields */
211         init_crc32();
212         crc = crc32buf(input_file, file_len);
213         h.crc32_p = htonl(~crc);
214         crc = crc32buf((unsigned char *)&h, sizeof(h));
215         h.crc32_h = htonl(~crc);
216 
217         /* dump new image */
218         write(fdout, &h, sizeof(h));
219         write(fdout, input_file, file_len);
220 
221         /* close files */
222         munmap(input_file, file_len);
223         if (fdout != STDOUT_FILENO)
224                 close(fdout);
225 
226         return EXIT_SUCCESS;
227 }
228 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt