1/* 2 * makeamitbin - create firmware binaries for MGB100 3 * 4 * Copyright (C) 2007 Volker Weiss <dev@tintuc.de> 5 * Christian Welzel <dev@welzel-online.ch> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * 21 */ 22 23 24#include <stdlib.h> 25#include <stdio.h> 26#include <string.h> 27 28 29/* defaults: Level One WAP-0007 */ 30static char *ascii1 = "DDC_RUS001"; 31static char *ascii2 = "Queen"; 32 33static struct hdrinfo { 34 char *name; 35 unsigned long unknown; /* can probably be any number, maybe version number */ 36 int topalign; 37 unsigned int addr; 38 unsigned int size; 39} hdrinfo[] = { 40 { "bios", 0xc76be111, 1, 0x3fa000, 0x006000 }, /* BIOS */ 41 { "recovery", 0xc76be222, 0, 0x3f0000, 0x004000 }, /* Recovery Loader */ 42 { "linux", 0xc76bee9d, 0, 0x000000, 0x100000 }, /* Linux */ 43 { "ramdisk", 0xc76bee9d, 0, 0x100000, 0x280000 }, /* ramdisk */ 44 { "amitconfig", 0xc76bee8b, 0, 0x380000, 0x060000 }, /* AMIT config */ 45 { "redboot", 0x00000000, 1, 0x3d0000, 0x030000 }, /* Redboot 128kB image */ 46 { "redbootlow", 0, 0, 0x3e0000, 0x18000 }, /* Redboot 1. part */ 47 { "redboothigh", 0, 0, 0x3fa000, 0x6000 }, /* Redboot 2. part */ 48 { "linux3g", 0xcb5f06b5, 0, 0x000000, 0x100000 }, /* Linux */ 49 { "ramdisk3g", 0xcb5f06b5, 0, 0x100000, 0x280000 }, /* ramdisk */ 50 { NULL } 51}; 52 53/* 54CHD2WLANU_R400b7 55 5611e1 6bc7 5722e2 6bc7 585dc3 47c8 595cc3 47c8 6021c3 47c8 61*/ 62 63/* 6420060106_DDC_WAP-0007_R400b4 65 6611e1 6bc7 6722e2 6bc7 689dee 6bc7 699dee 6bc7 708bee 6bc7 71*/ 72 73/* 74WMU-6000FS_R400b6 75 7611e1 6bc7 7722e2 6bc7 786d2d 0fc8 796c2d 0fc8 80542d 0fc8 81*/ 82 83/* 84WAP-0007(R4.00b8)_2006-10-02 85 869979 5fc8 8722e2 6bc7 88c46e cec8 89c36e cec8 90a76e cec8 91*/ 92 93 94 95#define HDRSIZE 80 96 97#define COPY_SHORT(d, o, v) d[o+0] = (unsigned char)((v) & 0xff); \ 98 d[o+1] = (unsigned char)(((v) >> 8) & 0xff) 99#define COPY_LONG(d, o, v) d[o+0] = (unsigned char)((v) & 0xff); \ 100 d[o+1] = (unsigned char)(((v) >> 8) & 0xff); \ 101 d[o+2] = (unsigned char)(((v) >> 16) & 0xff); \ 102 d[o+3] = (unsigned char)(((v) >> 24) & 0xff) 103#define READ_SHORT(d, o) ((unsigned short)(d[o+0]) + \ 104 (((unsigned short)(d[o+1])) << 8)) 105 106/* 10700..0d ASCII product ID 1080e..0f checksum of payload 10910..1b ASCII Queen 1101c..1f AMIT BIOS: 11e1 6bc7, Recovery Tool: 22e2 6bc7 111 Linux: 5dc3 47c8, ramdisk: 5cc3 47c8 112 AMIT FS: 21c3 47c8 VERSION NUMBER?????? 11320..23 offset in flash aligned to segment boundary 11424..27 length in flash aligned to segment boundary 11528..2b offset in flash (payload) 1162c..2f length (payload) 11730..3f always 0 11840..47 always 4248 0101 5000 0001 (last maybe .....0501) 11948..4b same as 20..23 1204c..4d always 0b00 1214e..4f inverted checksum of header 122*/ 123 124unsigned short checksum(unsigned char *data, long size) 125{ 126 long n; 127 unsigned short d, cs = 0; 128 for (n = 0; n < size; n += 2) 129 { 130 d = READ_SHORT(data, n); 131 cs += d; 132 if (cs < d) 133 cs++; 134 } 135 if (size & 1) 136 { 137 d = data[n]; 138 cs += d; 139 if (cs < d) 140 cs++; 141 } 142 return cs; 143} 144 145void showhdr(unsigned char *hdr) 146{ 147 int i, j; 148 for (j = 0; j < 5; j++) 149 { 150 for (i = 0; i < 16; i++) 151 { 152 printf("%02x ", (unsigned int)(hdr[j * 16 + i])); 153 } 154 printf(" "); 155 for (i = 0; i < 16; i++) 156 { 157 unsigned char d = hdr[j * 16 + i]; 158 printf("%c", (d >= ' ' && d < 127) ? d : '.'); 159 } 160 printf("\n"); 161 } 162} 163 164void makehdr(unsigned char *hdr, struct hdrinfo *info, 165 unsigned char *data, long size, int last) 166{ 167 unsigned int offset = info->addr + 0x10; 168 memset(hdr, 0, HDRSIZE); 169 if (info->topalign) 170 offset = info->addr + info->size - size; /* top align */ 171 strncpy((char *)hdr + 0x00, ascii1, 14); 172 strncpy((char *)hdr + 0x10, ascii2, 12); 173 COPY_LONG(hdr, 0x1c, info->unknown); 174 COPY_LONG(hdr, 0x20, info->addr); 175 COPY_LONG(hdr, 0x24, info->size); 176 COPY_LONG(hdr, 0x28, offset); 177 COPY_LONG(hdr, 0x2c, size); 178 COPY_LONG(hdr, 0x40, 0x01014842); 179 COPY_LONG(hdr, 0x44, last ? 0x01050050 : 0x01000050); 180 COPY_LONG(hdr, 0x48, info->addr); 181 COPY_SHORT(hdr, 0x4c, info->unknown == 0xcb5f06b5 ? 0x0016 : 0x000b); 182 COPY_SHORT(hdr, 0x0e, checksum(data, size)); 183 COPY_SHORT(hdr, 0x4e, ~checksum(hdr, HDRSIZE)); 184} 185 186unsigned char *read_file(const char *name, long *size) 187{ 188 FILE *f; 189 unsigned char *data = NULL; 190 *size = 0; 191 f = fopen(name, "r"); 192 if (f != NULL) 193 { 194 if (fseek(f, 0, SEEK_END) == 0) 195 { 196 *size = ftell(f); 197 if (*size != -1) 198 { 199 if (fseek(f, 0, SEEK_SET) == 0) 200 { 201 data = (unsigned char *)malloc(*size); 202 if (data != NULL) 203 { 204 if (fread(data, sizeof(char), *size, f) != *size) 205 { 206 free(data); 207 data = NULL; 208 } 209 } 210 } 211 } 212 } 213 fclose(f); 214 } 215 return data; 216} 217 218struct hdrinfo *find_hdrinfo(const char *name) 219{ 220 int n; 221 for (n = 0; hdrinfo[n].name != NULL; n++) 222 { 223 if (strcmp(name, hdrinfo[n].name) == 0) 224 return &hdrinfo[n]; 225 } 226 return NULL; 227} 228 229void oferror(FILE *f) 230{ 231 printf("file error\n"); 232 exit(2); 233} 234 235void showhelp(void) 236{ 237 printf("Syntax: makeamitbin [options]\n"); 238 printf("Options:\n"); 239 printf(" -1 ID1\tFirmware identifier 1, e.g. 'DDC_RUS001' for manufacturer LevelOne\n"); 240 printf(" -2 ID2\tFirmware identifier 2, 'Queen' in all known cases\n"); 241 printf(" -o FILE\tOutput file\n"); 242 printf(" -ids\t\tShow a list of known firmware identifiers.\n"); 243 exit(1); 244} 245 246void show_fwids(void) 247{ 248 printf("List of known firmware identifiers:\n"); 249 printf("Manufacturer\t\tProduct\t\tIdentifier\n"); 250 printf("=====================================================\n"); 251 printf("Conceptronic\t\tCHD2WLANU\tLLM_RUS001\n"); 252 printf("Pearl\t\t\tPE6643\t\tQueen\n"); 253 printf("Micronica\t\tMGB100\t\tQueen\n"); 254 printf("LevelOne\t\tWAP-0007\tDDC_RUS001\n"); 255 printf("SMC\t\t\tWAPS-G\t\tSMC_RUS001\n"); 256 printf("OvisLink (AirLive)\tWMU-6\t\tOVS_RUS001\n"); 257 printf("SafeCom SWSAPUR-5\tFMW\t\tSafeco_RPS001\n"); 258 exit(1); 259} 260 261int main(int argc, char *argv[]) 262{ 263 unsigned char hdr[HDRSIZE]; 264 unsigned char *data; 265 FILE *of; 266 char *outfile = NULL; 267 char *type; 268 struct hdrinfo *info; 269 long size; 270 int last = 0; 271 int n; 272 for (n = 1; n < argc; n++) 273 { 274 if (strcmp(argv[n], "-1") == 0) 275 ascii1 = argv[n+1]; 276 if (strcmp(argv[n], "-2") == 0) 277 ascii2 = argv[n+1]; 278 if (strcmp(argv[n], "-o") == 0) 279 outfile = argv[n+1]; 280 if (strcmp(argv[n], "-ids") == 0) 281 show_fwids(); 282 } 283 if (ascii1 == NULL || ascii2 == NULL || outfile == NULL) 284 showhelp(); 285 of = fopen(outfile, "w"); 286 if (of == NULL) 287 oferror(of); 288 for (n = 1; n < argc; n++) 289 { 290 if (strncmp(argv[n], "-", 1) != 0) 291 { 292 type = argv[n++]; 293 if (n >= argc) 294 showhelp(); 295 last = ((n + 1) >= argc); /* dirty, options first! */ 296 info = find_hdrinfo(type); 297 if (info == NULL) 298 showhelp(); 299 data = read_file(argv[n], &size); 300 if (data == NULL) 301 showhelp(); 302 makehdr(hdr, info, data, size, last); 303 /* showhdr(hdr); */ 304 if (fwrite(hdr, HDRSIZE, 1, of) != 1) 305 oferror(of); 306 if (fwrite(data, size, 1, of) != 1) 307 oferror(of); 308 free(data); 309 } 310 else 311 n++; 312 } 313 if (fclose(of) != 0) 314 oferror(NULL); 315 return 0; 316} 317