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

Sources/firmware-utils/src/mkrtn56uimg.c

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  *
  4  *  Copyright (C) 2014 OpenWrt.org
  5  *  Copyright (C) 2014 Mikko Hissa <mikko.hissa@werzek.com>
  6  */
  7 
  8 #include <errno.h>
  9 #include <fcntl.h>
 10 #include <stdio.h>
 11 #include <stdlib.h>
 12 #include <string.h>
 13 #include <netinet/in.h>
 14 #include <sys/mman.h>
 15 #include <sys/stat.h>
 16 #include <unistd.h>
 17 #include <zlib.h>
 18 
 19 #define IH_MAGIC        0x27051956
 20 #define IH_NMLEN        32
 21 #define IH_PRODLEN      23
 22 
 23 #define IH_TYPE_INVALID         0
 24 #define IH_TYPE_STANDALONE      1
 25 #define IH_TYPE_KERNEL          2
 26 #define IH_TYPE_RAMDISK         3
 27 #define IH_TYPE_MULTI           4
 28 #define IH_TYPE_FIRMWARE        5
 29 #define IH_TYPE_SCRIPT          6
 30 #define IH_TYPE_FILESYSTEM      7
 31 
 32 /*
 33  * Compression Types
 34  */
 35 #define IH_COMP_NONE            0
 36 #define IH_COMP_GZIP            1
 37 #define IH_COMP_BZIP2           2
 38 #define IH_COMP_LZMA            3
 39 
 40 typedef struct {
 41         uint8_t major;
 42         uint8_t minor;
 43 } version_t;
 44 
 45 typedef struct {
 46         version_t       kernel;
 47         version_t       fs;
 48         uint8_t         productid[IH_PRODLEN];
 49         uint8_t         sub_fs;
 50         uint32_t        ih_ksz;
 51 } asus_t;
 52 
 53 typedef struct image_header {
 54         uint32_t        ih_magic;
 55         uint32_t        ih_hcrc;
 56         uint32_t        ih_time;
 57         uint32_t        ih_size;
 58         uint32_t        ih_load;
 59         uint32_t        ih_ep;
 60         uint32_t        ih_dcrc;
 61         uint8_t         ih_os;
 62         uint8_t         ih_arch;
 63         uint8_t         ih_type;
 64         uint8_t         ih_comp;
 65         union {
 66                 char    ih_name[IH_NMLEN];
 67                 asus_t  asus;
 68         } tail;
 69 } image_header_t;
 70 
 71 typedef struct squashfs_sb {
 72         uint32_t        s_magic;
 73         uint32_t        pad0[9];
 74         uint64_t        bytes_used;
 75 } squashfs_sb_t;
 76 
 77 typedef enum {
 78         NONE, FACTORY, SYSUPGRADE,
 79 } op_mode_t;
 80 
 81 void
 82 calc_crc(image_header_t *hdr, void *data, uint32_t len)
 83 {
 84         /*
 85          * Calculate payload checksum
 86          */
 87         hdr->ih_dcrc = htonl(crc32(0, (Bytef *)data, len));
 88         hdr->ih_size = htonl(len);
 89         /*
 90          * Calculate header checksum
 91          */
 92         hdr->ih_hcrc = 0;
 93         hdr->ih_hcrc = htonl(crc32(0, (Bytef *)hdr, sizeof(image_header_t)));
 94 }
 95 
 96 
 97 static void
 98 usage(const char *progname, int status)
 99 {
100         FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
101 
102         fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
103         fprintf(stream, "\n"
104                         "Options:\n"
105                         "  -f <file>            generate a factory flash image <file>\n"
106                         "  -s <file>            generate a sysupgrade flash image <file>\n"
107                         "  -h                   show this screen\n");
108         exit(status);
109 }
110 
111 int
112 process_image(char *progname, char *filename, op_mode_t opmode)
113 {
114         int             fd;
115         void            *ptr;
116         char            namebuf[IH_NMLEN];
117         struct          stat sbuf;
118         uint32_t        offset_kernel, offset_sqfs, offset_end,
119                         offset_sec_header, offset_eb, offset_image_end;
120         squashfs_sb_t *sqs;
121         image_header_t *hdr;
122 
123         if ((fd = open(filename, O_RDWR, 0666)) < 0) {
124                 fprintf (stderr, "%s: Can't open %s: %s\n",
125                         progname, filename, strerror(errno));
126                 return (EXIT_FAILURE);
127         }
128 
129         if (fstat(fd, &sbuf) < 0) {
130                 fprintf (stderr, "%s: Can't stat %s: %s\n",
131                         progname, filename, strerror(errno));
132                 return (EXIT_FAILURE);
133         }
134 
135         if ((unsigned)sbuf.st_size < sizeof(image_header_t)) {
136                 fprintf (stderr,
137                         "%s: Bad size: \"%s\" is no valid image\n",
138                         progname, filename);
139                 return (EXIT_FAILURE);
140         }
141 
142         ptr = (void *)mmap(0, sbuf.st_size,
143                                 PROT_READ | PROT_WRITE,
144                                 MAP_SHARED,
145                                 fd, 0);
146 
147         if ((caddr_t)ptr == (caddr_t)-1) {
148                 fprintf (stderr, "%s: Can't read %s: %s\n",
149                         progname, filename, strerror(errno));
150                 return (EXIT_FAILURE);
151         }
152 
153         hdr = ptr;
154 
155         if (ntohl(hdr->ih_magic) != IH_MAGIC) {
156                 fprintf (stderr,
157                         "%s: Bad Magic Number: \"%s\" is no valid image\n",
158                         progname, filename);
159                 return (EXIT_FAILURE);
160         }
161 
162         if (opmode == FACTORY) {
163                 strncpy(namebuf, hdr->tail.ih_name, IH_NMLEN);
164                 hdr->tail.asus.kernel.major = 0;
165                 hdr->tail.asus.kernel.minor = 0;
166                 hdr->tail.asus.fs.major = 0;
167                 hdr->tail.asus.fs.minor = 0;
168                 strncpy((char *)&hdr->tail.asus.productid, "RT-N56U", IH_PRODLEN);
169         }
170 
171         if (hdr->tail.asus.ih_ksz == 0)
172                 hdr->tail.asus.ih_ksz = htonl(ntohl(hdr->ih_size) + sizeof(image_header_t));
173 
174         offset_kernel = sizeof(image_header_t);
175         offset_sqfs = ntohl(hdr->tail.asus.ih_ksz);
176         sqs = ptr + offset_sqfs;
177         offset_sec_header = offset_sqfs + sqs->bytes_used;
178 
179         /*
180          * Reserve space for the second header.
181          */
182         offset_end = offset_sec_header + sizeof(image_header_t);
183         offset_eb = ((offset_end>>16)+1)<<16;
184 
185         if (opmode == FACTORY)
186                 offset_image_end = offset_eb + 4;
187         else
188                 offset_image_end = sbuf.st_size;
189         /*
190          * Move the second header at the end of the image.
191          */
192         offset_end = offset_sec_header;
193         offset_sec_header = offset_eb - sizeof(image_header_t);
194 
195         /*
196          * Remove jffs2 markers between squashfs and eb boundary.
197          */
198         if (opmode == FACTORY)
199                 memset(ptr+offset_end, 0xff ,offset_eb - offset_end);
200 
201         /*
202          * Grow the image if needed.
203          */
204         if (offset_image_end > sbuf.st_size) {
205                 (void) munmap((void *)ptr, sbuf.st_size);
206                 ftruncate(fd, offset_image_end);
207                 ptr = (void *)mmap(0, offset_image_end,
208                                                 PROT_READ | PROT_WRITE,
209                                                 MAP_SHARED,
210                                                 fd, 0);
211                 /*
212                  * jffs2 marker
213                  */
214                 if (opmode == FACTORY) {
215                         *(uint8_t *)(ptr+offset_image_end-4) = 0xde;
216                         *(uint8_t *)(ptr+offset_image_end-3) = 0xad;
217                         *(uint8_t *)(ptr+offset_image_end-2) = 0xc0;
218                         *(uint8_t *)(ptr+offset_image_end-1) = 0xde;
219                 }
220         }
221 
222         /*
223          * Calculate checksums for the second header to be used after flashing.
224          */
225         if (opmode == FACTORY) {
226                 hdr = ptr+offset_sec_header;
227                 memcpy(hdr, ptr, sizeof(image_header_t));
228                 strncpy(hdr->tail.ih_name, namebuf, IH_NMLEN);
229                 calc_crc(hdr, ptr+offset_kernel, offset_sqfs - offset_kernel);
230                 calc_crc((image_header_t *)ptr, ptr+offset_kernel, offset_image_end - offset_kernel);
231         } else {
232                 calc_crc((image_header_t *)ptr, ptr+offset_kernel, offset_sqfs - offset_kernel);
233         }
234 
235         if (sbuf.st_size > offset_image_end)
236                 (void) munmap((void *)ptr, sbuf.st_size);
237         else
238                 (void) munmap((void *)ptr, offset_image_end);
239 
240         ftruncate(fd, offset_image_end);
241         (void) close (fd);
242 
243         return EXIT_SUCCESS;
244 }
245 
246 int
247 main(int argc, char **argv)
248 {
249         int             opt;
250         char            *filename = NULL;
251         char            *progname;
252         op_mode_t       opmode = NONE;
253 
254         progname = argv[0];
255 
256         while ((opt = getopt(argc, argv,":s:f:h?")) != -1) {
257                 switch (opt) {
258                 case 's':
259                         opmode = SYSUPGRADE;
260                         filename = optarg;
261                         break;
262                 case 'f':
263                         opmode = FACTORY;
264                         filename = optarg;
265                         break;
266                 case 'h':
267                         opmode = NONE;
268                 default:
269                         usage(progname, EXIT_FAILURE);
270                         opmode = NONE;
271                 }
272         }
273 
274         if(filename == NULL)
275                 opmode = NONE;
276 
277         switch (opmode) {
278         case NONE:
279                 usage(progname, EXIT_FAILURE);
280                 break;
281         case FACTORY:
282         case SYSUPGRADE:
283                 return process_image(progname, filename, opmode);
284                 break;
285         }
286 
287         return EXIT_SUCCESS;
288 }
289 
290 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt