1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <stdio.h> 3 #include <stdint.h> 4 #include <stdlib.h> 5 #include <unistd.h> 6 #include <libgen.h> 7 #include <stdarg.h> 8 #include <getopt.h> 9 #include <string.h> 10 #include <errno.h> 11 12 #include <netinet/in.h> // htonl 13 14 // Usage: mkdapimg [-p] [-m <model>] -s <sig> -i <input> -o <output> 15 // 16 // e.g.: mkdapimg -s RT3052-AP-DAP1350-3 -i sysupgrade.bin -o factory.bin 17 // 18 // If the model string <model> is not given, we will assume that 19 // the leading characters upto the first "-" is the model. 20 // 21 // The "-p" (patch) option is used to patch the exisiting image with the 22 // specified model and signature. 23 // The "-x" (fix) option will recalculate the payload size and checksum 24 // during the patch mode operation. 25 26 // The img_hdr_struct was taken from the D-Link SDK: 27 // DAP-1350_A1_FW1.11NA_GPL/GPL_Source_Code/Uboot/DAP-1350/httpd/header.h 28 29 #define MAX_MODEL_NAME_LEN 20 30 #define MAX_SIG_LEN 30 31 #define MAX_REGION_LEN 4 32 #define MAX_VERSION_LEN 12 33 34 struct img_hdr_struct { 35 uint32_t checksum; 36 char model[MAX_MODEL_NAME_LEN]; 37 char sig[MAX_SIG_LEN]; 38 uint8_t partition; 39 uint8_t hdr_len; 40 uint8_t rsv1; 41 uint8_t rsv2; 42 uint32_t flash_byte_cnt; 43 } imghdr ; 44 45 char *progname; 46 47 void 48 perrexit(int code, char *msg) 49 { 50 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno)); 51 exit(code); 52 } 53 54 void 55 usage() 56 { 57 fprintf(stderr, "usage: %s [-p] [-m model] [-r region] [-v version] -s signature -i input -o output\n", progname); 58 exit(1); 59 } 60 61 int 62 main(int ac, char *av[]) 63 { 64 char model[MAX_MODEL_NAME_LEN+1]; 65 char signature[MAX_SIG_LEN+1]; 66 char region[MAX_REGION_LEN+1]; 67 char version[MAX_VERSION_LEN+1]; 68 int patchmode = 0; 69 int fixmode = 0; 70 int have_regionversion = 0; 71 72 FILE *ifile = NULL; 73 FILE *ofile = NULL; 74 int c; 75 uint32_t cksum; 76 uint32_t bcnt; 77 78 progname = basename(av[0]); 79 memset(model, 0, sizeof(model)); 80 memset(signature, 0, sizeof(signature)); 81 memset(region, 0, sizeof(region)); 82 memset(version, 0, sizeof(version)); 83 84 while ( 1 ) { 85 int c; 86 87 c = getopt(ac, av, "pxm:r:v:s:i:o:"); 88 if (c == -1) 89 break; 90 91 switch (c) { 92 case 'p': 93 patchmode = 1; 94 break; 95 case 'x': 96 fixmode = 1; 97 break; 98 case 'm': 99 if (strlen(optarg) > MAX_MODEL_NAME_LEN) { 100 fprintf(stderr, "%s: model name exceeds %d chars\n", 101 progname, MAX_MODEL_NAME_LEN); 102 exit(1); 103 } 104 strcpy(model, optarg); 105 break; 106 case 'r': 107 if (strlen(optarg) > MAX_REGION_LEN) { 108 fprintf(stderr, "%s: region exceeds %d chars\n", 109 progname, MAX_REGION_LEN); 110 exit(1); 111 } 112 have_regionversion = 1; 113 strcpy(region, optarg); 114 break; 115 case 'v': 116 if (strlen(optarg) > MAX_VERSION_LEN) { 117 fprintf(stderr, "%s: version exceeds %d chars\n", 118 progname, MAX_VERSION_LEN); 119 exit(1); 120 } 121 have_regionversion = 1; 122 strcpy(version, optarg); 123 break; 124 case 's': 125 if (strlen(optarg) > MAX_SIG_LEN) { 126 fprintf(stderr, "%s: signature exceeds %d chars\n", 127 progname, MAX_SIG_LEN); 128 exit(1); 129 } 130 strcpy(signature, optarg); 131 break; 132 case 'i': 133 if ((ifile = fopen(optarg, "r")) == NULL) 134 perrexit(1, optarg); 135 break; 136 case 'o': 137 if ((ofile = fopen(optarg, "w")) == NULL) 138 perrexit(1, optarg); 139 break; 140 default: 141 usage(); 142 } 143 } 144 145 if (signature[0] == 0 || ifile == NULL || ofile == NULL) { 146 usage(); 147 } 148 149 if (model[0] == 0) { 150 char *p = strchr(signature, '-'); 151 if (p == NULL) { 152 fprintf(stderr, "%s: model name unknown\n", progname); 153 exit(1); 154 } 155 if (p - signature > MAX_MODEL_NAME_LEN) { 156 *p = 0; 157 fprintf(stderr, "%s: auto model name failed, string %s too long\n", progname, signature); 158 exit(1); 159 } 160 strncpy(model, signature, p - signature); 161 } 162 163 if (patchmode) { 164 if (fread(&imghdr, sizeof(imghdr), 1, ifile) < 0) 165 perrexit(2, "fread on input"); 166 } 167 168 for (bcnt = 0, cksum = 0 ; (c = fgetc(ifile)) != EOF ; bcnt++) 169 cksum += c & 0xff; 170 171 if (fseek(ifile, patchmode ? sizeof(imghdr) : 0, SEEK_SET) < 0) 172 perrexit(2, "fseek on input"); 173 174 if (patchmode == 0) { 175 // Fill in the header 176 memset(&imghdr, 0, sizeof(imghdr)); 177 imghdr.checksum = htonl(cksum); 178 imghdr.partition = 0 ; // don't care? 179 imghdr.hdr_len = sizeof(imghdr); 180 if (have_regionversion) { 181 imghdr.hdr_len += MAX_REGION_LEN; 182 imghdr.hdr_len += MAX_VERSION_LEN; 183 } 184 imghdr.flash_byte_cnt = htonl(bcnt); 185 } else { 186 if (ntohl(imghdr.checksum) != cksum) { 187 fprintf(stderr, "%s: patch mode, checksum mismatch\n", 188 progname); 189 if (fixmode) { 190 fprintf(stderr, "%s: fixing\n", progname); 191 imghdr.checksum = htonl(cksum); 192 } else 193 exit(3); 194 } else if (ntohl(imghdr.flash_byte_cnt) != bcnt) { 195 fprintf(stderr, "%s: patch mode, size mismatch\n", 196 progname); 197 if (fixmode) { 198 fprintf(stderr, "%s: fixing\n", progname); 199 imghdr.flash_byte_cnt = htonl(bcnt); 200 } else 201 exit(3); 202 } 203 } 204 205 strncpy(imghdr.model, model, MAX_MODEL_NAME_LEN); 206 strncpy(imghdr.sig, signature, MAX_SIG_LEN); 207 208 if (fwrite(&imghdr, sizeof(imghdr), 1, ofile) < 0) 209 perrexit(2, "fwrite header on output"); 210 if (have_regionversion) { 211 if (fwrite(®ion, MAX_REGION_LEN, 1, ofile) < 0) 212 perrexit(2, "fwrite header on output"); 213 if (fwrite(&version, MAX_VERSION_LEN, 1, ofile) < 0) 214 perrexit(2, "fwrite header on output"); 215 } 216 217 while ((c = fgetc(ifile)) != EOF) { 218 if (fputc(c, ofile) == EOF) 219 perrexit(2, "fputc on output"); 220 } 221 222 if (ferror(ifile)) 223 perrexit(2, "fgetc on input"); 224 225 226 fclose(ofile); 227 fclose(ifile); 228 } 229
This page was automatically generated by LXR 0.3.1. • OpenWrt