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