1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <stdio.h> 3 #include <string.h> 4 #include <stdlib.h> 5 #include <sys/types.h> 6 #include <unistd.h> 7 #include <byteswap.h> 8 #include <endian.h> 9 #include <getopt.h> 10 11 #if !defined(__BYTE_ORDER) 12 #error "Unknown byte order" 13 #endif 14 15 #if __BYTE_ORDER == __BIG_ENDIAN 16 #define cpu_to_be32(x) (x) 17 #elif __BYTE_ORDER == __LITTLE_ENDIAN 18 #define cpu_to_be32(x) bswap_32(x) 19 #else 20 #error "Unsupported endianness" 21 #endif 22 23 /* #define DEBUG 1 */ 24 25 #ifdef DEBUG 26 #define DBG(...) {printf(__VA_ARGS__); } 27 #else 28 #define DBG(...) {} 29 #endif 30 31 #define ERR(...) {printf(__VA_ARGS__); } 32 33 /* 34 * Fw Header Layout for Netgear / Sercomm devices (bytes) 35 * 36 * Size : 512 bytes + zipped image size 37 * 38 * Locations: 39 * magic : 0-6 ASCII 40 * version: 7-11 fixed 41 * hwID : 11-44 ASCII 42 * hwVer : 45-54 ASCII 43 * swVer : 55-62 uint32_t in BE 44 * magic : 63-69 ASCII 45 * ChkSum : 511 Inverse value of the full image checksum while this location is 0x00 46 */ 47 static const char* magic = "sErCoMm"; /* 7 */ 48 static const unsigned char version[4] = { 0x00, 0x01, 0x00, 0x00 }; 49 static const int header_sz = 512; 50 static const int footer_sz = 71; 51 52 static int is_header = 1; 53 54 struct file_info { 55 char* file_name; /* name of the file */ 56 char* file_data; /* data of the file in memory */ 57 u_int32_t file_size; /* length of the file */ 58 }; 59 60 static u_int8_t getCheckSum(char* data, int len) { 61 u_int8_t new = 0; 62 int i; 63 64 if (!data) { 65 ERR("Invalid pointer provided!\n"); 66 return 0; 67 } 68 69 for (i = 0; i < len; i++) { 70 new += data[i]; 71 } 72 73 return new; 74 } 75 76 /* 77 * read file into buffer 78 * add space for header/footer 79 */ 80 static int copyToOutputBuf(struct file_info* finfo) { 81 FILE* fp = NULL; 82 83 int file_sz = 0; 84 int extra_sz; 85 int hdr_pos; 86 int img_pos; 87 88 if (!finfo || !finfo->file_name) { 89 ERR("Invalid pointer provided!\n"); 90 return -1; 91 } 92 93 DBG("Opening file: %s\n", finfo->file_name); 94 95 if (!(fp = fopen(finfo->file_name, "rb"))) { 96 ERR("Error opening file: %s\n", finfo->file_name); 97 return -1; 98 } 99 100 /* Get filesize */ 101 rewind(fp); 102 fseek(fp, 0L, SEEK_END); 103 file_sz = ftell(fp); 104 rewind(fp); 105 106 if (file_sz < 1) { 107 ERR("Error getting filesize: %s\n", finfo->file_name); 108 fclose(fp); 109 return -1; 110 } 111 112 if (is_header) { 113 extra_sz = header_sz; 114 hdr_pos = 0; 115 img_pos = header_sz; 116 } else { 117 extra_sz = footer_sz; 118 hdr_pos = file_sz; 119 img_pos = 0; 120 } 121 122 DBG("Filesize: %i\n", file_sz); 123 finfo->file_size = file_sz + extra_sz; 124 125 if (!(finfo->file_data = malloc(finfo->file_size))) { 126 ERR("Out of memory!\n"); 127 fclose(fp); 128 return -1; 129 } 130 131 /* init header/footer bytes */ 132 memset(finfo->file_data + hdr_pos, 0, extra_sz); 133 134 /* read file and take care of leading header if exists */ 135 if (fread(finfo->file_data + img_pos, 1, file_sz, fp) != file_sz) { 136 ERR("Error reading file %s\n", finfo->file_name); 137 fclose(fp); 138 return -1; 139 } 140 141 DBG("File: read successful\n"); 142 fclose(fp); 143 144 return hdr_pos; 145 } 146 147 static int writeFile(struct file_info* finfo) { 148 FILE* fp; 149 150 if (!finfo || !finfo->file_name) { 151 ERR("Invalid pointer provided!\n"); 152 return -1; 153 } 154 155 DBG("Opening file: %s\n", finfo->file_name); 156 157 if (!(fp = fopen(finfo->file_name, "w"))) { 158 ERR("Error opening file: %s\n", finfo->file_name); 159 return -1; 160 } 161 162 DBG("Writing file: %s\n", finfo->file_name); 163 164 if (fwrite(finfo->file_data, 1, finfo->file_size, fp) != finfo->file_size) { 165 ERR("Wanted to write, but something went wrong!\n"); 166 fclose(fp); 167 return -1; 168 } 169 170 fclose(fp); 171 return 0; 172 } 173 174 static void usage(char* argv[]) { 175 printf("Usage: %s [OPTIONS...]\n" 176 "\n" 177 "Options:\n" 178 " -f add sercom footer (if absent, header)\n" 179 " -b <hwid> use hardware id specified with <hwid> (ASCII)\n" 180 " -r <hwrev> use hardware revision specified with <hwrev> (ASCII)\n" 181 " -v <version> set image version to <version> (decimal, hex or octal notation)\n" 182 " -i <file> input file\n" 183 , argv[0]); 184 } 185 186 int main(int argc, char* argv[]) { 187 struct file_info image = { 0 }; 188 189 char* hwID = NULL; 190 char* hwVer = NULL; 191 u_int32_t swVer = 0; 192 u_int8_t chkSum; 193 int hdr_offset; 194 195 while ( 1 ) { 196 int c; 197 198 c = getopt(argc, argv, "b:i:r:v:f"); 199 if (c == -1) 200 break; 201 202 switch (c) { 203 case 'b': 204 hwID = optarg; 205 break; 206 case 'f': 207 is_header = 0; 208 break; 209 case 'i': 210 image.file_name = optarg; 211 break; 212 case 'r': 213 hwVer = optarg; 214 break; 215 case 'v': 216 swVer = (u_int32_t) strtol(optarg, NULL, 0); 217 swVer = cpu_to_be32(swVer); 218 break; 219 default: 220 usage(argv); 221 return EXIT_FAILURE; 222 } 223 } 224 225 if (!hwID || !hwVer || !image.file_name) { 226 usage(argv); 227 return EXIT_FAILURE; 228 } 229 230 /* 231 * copy input to buffer, add extra space for header/footer and return 232 * header position 233 */ 234 hdr_offset = copyToOutputBuf(&image); 235 if (hdr_offset < 0) 236 return EXIT_FAILURE; 237 238 DBG("Filling header: %s %s %2X %s\n", hwID, hwVer, swVer, magic); 239 240 strncpy(image.file_data + hdr_offset + 0, magic, 7); 241 memcpy(image.file_data + hdr_offset + 7, version, sizeof(version)); 242 strncpy(image.file_data + hdr_offset + 11, hwID, 34); 243 strncpy(image.file_data + hdr_offset + 45, hwVer, 10); 244 memcpy(image.file_data + hdr_offset + 55, &swVer, sizeof(swVer)); 245 strncpy(image.file_data + hdr_offset + 63, magic, 7); 246 247 /* calculate checksum and invert checksum */ 248 if (is_header) { 249 chkSum = getCheckSum(image.file_data, image.file_size); 250 chkSum = (chkSum ^ 0xFF) + 1; 251 DBG("Checksum for Image: %hhX\n", chkSum); 252 253 /* write checksum to header */ 254 image.file_data[511] = (char) chkSum; 255 } 256 257 /* overwrite input file */ 258 if (writeFile(&image)) 259 return EXIT_FAILURE; 260 261 return EXIT_SUCCESS; 262 } 263
This page was automatically generated by LXR 0.3.1. • OpenWrt