1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * (C) Nicolò Veronese <nicveronese@gmail.com> 4 */ 5 6 #include <stdio.h> 7 #include <stdint.h> 8 #include <stdlib.h> 9 #include <unistd.h> 10 #include <libgen.h> 11 #include <stdarg.h> 12 #include <getopt.h> 13 #include <string.h> 14 #include <errno.h> 15 16 #include <netinet/in.h> // htonl 17 18 // Usage: mkdapimg2 -s signature [-v version] [-r region] 19 // [-k uImage block size] -i <input> -o <output> 20 // 21 // NOTE: The kernel block size is used to know the offset of the rootfs 22 // in the image file. 23 // 24 // The system writes in the uImage partition until the end of uImage 25 // is reached, after that, the system jumps to the offset specified with the -k 26 // parameter and begin writing at the beginning of the rootfs MTD partition. 27 // 28 // If the -k parameter is the size of the original uImage partition, the system 29 // continue writing in the rootfs partition starting from the last block 30 // that has been wrote. (This is useful if the new kernel size is 31 // different from the original one) 32 // 33 // Example: 34 // ------------------------------------------ 35 // Creating 7 MTD partitions on "ath-nor0": 36 // 0x000000000000-0x000000010000 : "u-boot" 37 // 0x000000010000-0x000000020000 : "ART" 38 // 0x000000020000-0x000000030000 : "MP" 39 // 0x000000030000-0x000000040000 : "config" 40 // 0x000000040000-0x000000120000 : "uImage" 41 // 0x000000120000-0x000000800000 : "rootfs" 42 // 0x000000040000-0x000000800000 : "firmware" 43 // ------------------------------------------ 44 // 45 // 0x000000120000-0x000000040000 = 0xE0000 -> 917504 46 // 47 // e.g.: mkdapimg2 -s HONEYBEE-FIRMWARE-DAP-1330 -v 1.00.21 -r Default 48 // -k 917504 -i sysupgrade.bin -o factory.bin 49 // 50 // 51 // The img_hdr_struct was taken from the D-Link SDK: 52 // DAP-1330_OSS-firmware_1.00b21/DAP-1330_OSS-firmware_1.00b21/uboot/uboot.patch 53 54 #define MAX_SIGN_LEN 32 55 #define MAX_FW_VER_LEN 16 56 #define MAX_REG_LEN 8 57 58 struct img_hdr_struct { 59 uint32_t hdr_len; 60 uint32_t checksum; 61 uint32_t total_size; 62 uint32_t kernel_size; 63 char signature[MAX_SIGN_LEN]; 64 char fw_ver[MAX_FW_VER_LEN]; 65 char fw_reg[MAX_REG_LEN]; 66 } imghdr ; 67 68 char *progname; 69 70 void 71 perrexit(int code, char *msg) 72 { 73 fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno)); 74 exit(code); 75 } 76 77 void 78 usage() 79 { 80 fprintf(stderr, "usage: %s -s signature [-v version] [-r region] [-k uImage part size] -i <input> -o <output>\n", progname); 81 exit(1); 82 } 83 84 int 85 main(int ac, char *av[]) 86 { 87 char signature[MAX_SIGN_LEN]; 88 char version[MAX_FW_VER_LEN]; 89 char region[MAX_REG_LEN]; 90 int kernel = 0; 91 92 FILE *ifile = NULL; 93 FILE *ofile = NULL; 94 int c; 95 96 uint32_t cksum; 97 uint32_t bcnt; 98 99 progname = basename(av[0]); 100 101 memset(signature, 0, sizeof(signature)); 102 memset(version, 0, sizeof(version)); 103 memset(region, 0, sizeof(region)); 104 105 while ( 1 ) { 106 char *ptr; 107 int c; 108 109 c = getopt(ac, av, "s:v:r:k:i:o:"); 110 if (c == -1) 111 break; 112 113 switch (c) { 114 case 's': 115 if (strlen(optarg) > MAX_SIGN_LEN + 1) { 116 fprintf(stderr, "%s: signature exceeds %d chars\n", 117 progname, MAX_SIGN_LEN); 118 exit(1); 119 } 120 strcpy(signature, optarg); 121 break; 122 case 'v': 123 if (strlen(optarg) > MAX_FW_VER_LEN + 1) { 124 fprintf(stderr, "%s: version exceeds %d chars\n", 125 progname, MAX_FW_VER_LEN); 126 exit(1); 127 } 128 strcpy(version, optarg); 129 break; 130 case 'r': 131 if (strlen(optarg) > MAX_REG_LEN + 1) { 132 fprintf(stderr, "%s: region exceeds %d chars\n", 133 progname, MAX_REG_LEN); 134 exit(1); 135 } 136 strcpy(region, optarg); 137 break; 138 case 'k': 139 kernel = strtoul(optarg, &ptr, 0); 140 if(ptr[0] == 'k'){ 141 kernel *= 1000; 142 } 143 break; 144 case 'i': 145 if ((ifile = fopen(optarg, "r")) == NULL) 146 perrexit(1, optarg); 147 break; 148 case 'o': 149 if ((ofile = fopen(optarg, "w")) == NULL) 150 perrexit(1, optarg); 151 break; 152 default: 153 usage(); 154 } 155 } 156 157 if (signature[0] == 0 || ifile == NULL || ofile == NULL) { 158 usage(); 159 exit(1); 160 } 161 162 for (bcnt = 0, cksum = 0 ; (c = fgetc(ifile)) != EOF ; bcnt++) 163 cksum += c & 0xff; 164 165 if (fseek(ifile, 0, SEEK_SET) < 0) 166 perrexit(2, "fseek on input"); 167 168 // Fill in the header 169 memset(&imghdr, 0, sizeof(imghdr)); 170 imghdr.hdr_len = sizeof(imghdr); 171 imghdr.checksum = htonl(cksum); 172 imghdr.total_size = htonl(bcnt); 173 imghdr.kernel_size = htonl(kernel); 174 175 strncpy(imghdr.signature, signature, MAX_SIGN_LEN); 176 strncpy(imghdr.fw_ver, version, MAX_FW_VER_LEN); 177 strncpy(imghdr.fw_reg, region, MAX_REG_LEN); 178 179 if (fwrite(&imghdr, sizeof(imghdr), 1, ofile) < 0) 180 perrexit(2, "fwrite header on output"); 181 182 while ((c = fgetc(ifile)) != EOF) { 183 if (fputc(c, ofile) == EOF) 184 perrexit(2, "fputc on output"); 185 } 186 187 if (ferror(ifile)) 188 perrexit(2, "fgetc on input"); 189 190 fclose(ofile); 191 fclose(ifile); 192 193 fprintf(stderr, "imgHdr.hdr_len = %lu\n", sizeof(imghdr)); 194 fprintf(stderr, "imgHdr.checksum = 0x%08x\n", cksum); 195 fprintf(stderr, "imgHdr.total_size = 0x%08x\n", bcnt); 196 fprintf(stderr, "imgHdr.kernel_size = 0x%08x\n", kernel); 197 fprintf(stderr, "imgHdr.header = %s\n", signature); 198 fprintf(stderr, "imgHdr.fw_ver = %s\n", version); 199 fprintf(stderr, "imgHdr.fw_reg = %s\n", region); 200 201 return 0; 202 } 203
This page was automatically generated by LXR 0.3.1. • OpenWrt