1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include <errno.h> 5#include <getopt.h> 6#include <time.h> 7#include <stdint.h> 8#include <sys/stat.h> 9 10#define ROUNDUP(n, a) ((n + (a - 1)) & ~(a - 1)) 11 12#define TRX_MAGIC 0x30524448 13#define TRX_MAX_OFFSET 4 14#define TRX_MAX_LEN ((64 * 1024 * 1024) - ((256 + 128) * 1024)) // 64MB - (256K cfe + 128K cfg) 15 16typedef struct { 17 uint32_t magic; 18 uint32_t length; 19 uint32_t crc32; 20 uint32_t flag_version; 21 uint32_t offsets[TRX_MAX_OFFSET]; 22} trx_t; 23 24char trx_version = 1; 25int trx_max_offset = 3; 26 27uint32_t *crc_table = NULL; 28trx_t *trx = NULL; 29int trx_final = 0; 30time_t max_time = 0; 31 32inline size_t trx_header_size(void) 33{ 34 return sizeof(*trx) - sizeof(trx->offsets) + (trx_max_offset * sizeof(trx->offsets[0])); 35} 36 37int crc_init(void) 38{ 39 uint32_t c; 40 int i, j; 41 42 if (crc_table == NULL) { 43 if ((crc_table = malloc(sizeof(uint32_t) * 256)) == NULL) return 0; 44 for (i = 255; i >= 0; --i) { 45 c = i; 46 for (j = 8; j > 0; --j) { 47 if (c & 1) c = (c >> 1) ^ 0xEDB88320L; 48 else c >>= 1; 49 } 50 crc_table[i] = c; 51 } 52 } 53 return 1; 54} 55 56uint32_t crc_calc(uint32_t crc, uint8_t *buf, int len) 57{ 58 while (len-- > 0) { 59 crc = crc_table[(crc ^ *buf) & 0xFF] ^ (crc >> 8); 60 ++buf; 61 } 62 return crc; 63} 64 65void help(void) 66{ 67 fprintf(stderr, 68 "Usage: -i <input> {output}\n" 69 "Output:\n" 70 " ASUS: -r <id>,<v1>,<v2>,<v3>,<v4>,<output file>\n" 71 "\n" 72 ); 73 exit(1); 74} 75 76void load_image(const char *fname) 77{ 78 struct stat st; 79 FILE *f; 80 long rsize; 81 82 if (stat(fname, &st) != 0) { 83 perror(fname); 84 exit(1); 85 } 86 if (st.st_ctime > max_time) max_time = st.st_ctime; 87 88 rsize = ROUNDUP(st.st_size, 4); 89 if ((trx->length + rsize) > TRX_MAX_LEN) { 90 fprintf(stderr, "Total size %lu (%.1f KB) is too big. Maximum is %lu (%.1f KB).\n", 91 (trx->length + rsize), (trx->length + rsize) / 1024.0, 92 (long unsigned int) TRX_MAX_LEN, TRX_MAX_LEN / 1024.0); 93 exit(1); 94 } 95 96 if ((f = fopen(fname, "r")) == NULL) { 97 perror(fname); 98 exit(1); 99 } 100 101 if (fread((char *)trx, st.st_size, 1, f) != 1) { 102 perror(fname); 103 exit(1); 104 } 105 fclose(f); 106} 107 108void finalize_trx(void) 109{ 110 uint32_t len; 111 112 if (trx_final) return; 113 trx_final = 1; 114 115 len = trx->length; 116 117 trx->magic = TRX_MAGIC; 118 trx->flag_version = trx_version << 16; 119 trx->crc32 = crc_calc(0xFFFFFFFF, (void *)&trx->flag_version, 120 trx->length - (sizeof(*trx) - (sizeof(trx->flag_version) + sizeof(trx->offsets)))); 121} 122 123#define MAX_STRING 12 124#define MAX_VER 4 125 126typedef struct { 127 uint8_t major; 128 uint8_t minor; 129} version_t; 130 131typedef struct { 132 version_t kernel; 133 version_t fs; 134 char productid[MAX_STRING]; 135 version_t hw[MAX_VER*2]; 136#ifdef BCMWL6A 137 uint16_t sn; 138 uint16_t en; 139 char pad[28]; 140#else 141 char pad[32]; 142#endif 143} TAIL; 144 145/* usage: 146 * -r <productid>,<version>,<output file> 147 * 148 */ 149int create_asus(const char *optarg) 150{ 151 FILE *f; 152 char value[320]; 153 char *next, *pid, *ver, *fname, *p; 154 TAIL asus_tail; 155 uint32_t v1, v2, v3, v4; 156#ifdef BCMWL6A 157 char *sn, *en; 158 char tmp[10]; 159#endif 160 161 memset(&asus_tail, 0, sizeof(TAIL)); 162 163 strncpy(value, optarg, sizeof(value)); 164 next = value; 165 pid = strsep(&next, ","); 166 if(!pid) return 0; 167 168 strncpy(&asus_tail.productid[0], pid, MAX_STRING); 169 170 ver = strsep(&next, ","); 171 if(!ver) return 0; 172 173 sscanf(ver, "%d.%d.%d.%d", &v1, &v2, &v3, &v4); 174 asus_tail.kernel.major = (uint8_t)v1; 175 asus_tail.kernel.minor = (uint8_t)v2; 176 asus_tail.fs.major = (uint8_t)v3; 177 asus_tail.fs.minor = (uint8_t)v4; 178 179#ifdef BCMWL6A 180 sn = strsep(&next, ","); 181 if(!sn) return 0; 182 183 en = strsep(&next, ","); 184 if(!en) return 0; 185 186 sscanf(sn, "%d", &v1); 187 asus_tail.sn = (uint16_t)v1; 188 189 sscanf(en, "%d-%s", &v1, tmp); 190 asus_tail.en = (uint16_t)v1; 191#endif 192 193 fname = strsep(&next, ","); 194 if(!fname) return 0; 195 196 // append version information into the latest offset 197 p = (char *)trx+trx->length-sizeof(TAIL); 198 memcpy(p, &asus_tail, sizeof(TAIL)); 199 200 finalize_trx(); 201 202 printf("Creating ASUS %s firmware to %s\n", asus_tail.productid, fname); 203 204 if (((f = fopen(fname, "w")) == NULL) || 205 (fwrite(trx, trx->length, 1, f) != 1)) { 206 perror(fname); 207 exit(1); 208 } 209 fclose(f); 210 211 return 1; 212} 213 214int main(int argc, char **argv) 215{ 216 int o; 217 unsigned l; 218 219 printf("\n"); 220 221 if ((!crc_init()) || ((trx = calloc(1, TRX_MAX_LEN)) == NULL)) { 222 fprintf(stderr, "Not enough memory\n"); 223 exit(1); 224 } 225 trx->length = trx_header_size(); 226 227 while ((o = getopt(argc, argv, "v:i:a:t:l:m:r:")) != -1) { 228 switch (o) { 229 case 'i': 230 load_image(optarg); 231 break; 232 case 'r': 233 create_asus(optarg); 234 break; 235 default: 236 help(); 237 return 1; 238 } 239 } 240 241 finalize_trx(); 242 l = trx->length - trx_header_size(); 243 printf("\nTRX Image:\n"); 244 printf(" Total Size .... : %u (%.1f KB) (%.1f MB)\n", trx->length, trx->length / 1024.0, trx->length / 1024.0 / 1024.0); 245 printf(" CRC-32 ........ : %8X\n", trx->crc32); 246 printf("\n"); 247 248 return 0; 249} 250