3 Copyright 2003, CyberTAN Inc. All Rights Reserved
5 This is UNPUBLISHED PROPRIETARY SOURCE CODE of CyberTAN Inc.
6 the contents of this file may not be disclosed to third parties,
7 copied or duplicated in any form without the prior written
8 permission of CyberTAN Inc.
10 This software should be used as a reference only, and it not
11 intended for production use!
13 THIS SOFTWARE IS OFFERED "AS IS", AND CYBERTAN GRANTS NO WARRANTIES OF ANY
14 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. CYBERTAN
15 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
16 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE
21 Copyright 2005, Broadcom Corporation
24 THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
25 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
26 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
27 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
32 Modified for Tomato Firmware
33 Portions, Copyright (C) 2006-2009 Jonathan Zarate
40 #include <sys/sysmacros.h>
41 #include <sys/types.h>
46 #include <sys/ioctl.h>
47 #include <sys/sysinfo.h>
49 #include <linux/compiler.h>
50 #include <mtd/mtd-user.h>
52 #include <linux/mtd/mtd.h>
60 // #define DEBUG_SIMULATE
72 unsigned char res3
[10];
75 // -----------------------------------------------------------------------------
77 static uint32
*crc_table
= NULL
;
79 static void crc_done(void)
85 static int crc_init(void)
90 if (crc_table
== NULL
) {
91 if ((crc_table
= malloc(sizeof(uint32
) * 256)) == NULL
) return 0;
92 for (i
= 255; i
>= 0; --i
) {
94 for (j
= 8; j
> 0; --j
) {
95 if (c
& 1) c
= (c
>> 1) ^ 0xEDB88320L
;
104 static uint32
crc_calc(uint32 crc
, void *buf
, int len
)
107 crc
= crc_table
[(crc
^ *((char *)buf
)) & 0xFF] ^ (crc
>> 8);
113 // -----------------------------------------------------------------------------
116 int mtd_getinfo(const char *mtdname
, int *part
, int *size
)
124 if ((strlen(mtdname
) < 128) && (strcmp(mtdname
, "pmon") != 0)) {
125 sprintf(t
, "\"%s\"", mtdname
);
126 if ((f
= fopen("/proc/mtd", "r")) != NULL
) {
127 while (fgets(s
, sizeof(s
), f
) != NULL
) {
128 if ((sscanf(s
, "mtd%d: %x", part
, size
) == 2) && (strstr(s
, t
) != NULL
)) {
129 // don't accidentally mess with bl (0)
130 if (*part
> 0) r
= 1;
144 static int mtd_open(const char *mtdname
)
150 if (mtd_getinfo(mtdname
, &part
, &size
)) {
151 sprintf(path
, MTD_DEV(%d
), part
);
152 return open(path
, O_RDWR
|O_SYNC
);
157 static int _unlock_erase(const char *mtdname
, int erase
)
164 if (!wait_action_idle(5)) return 0;
165 set_action(ACT_ERASE_NVRAM
);
166 if (erase
) led(LED_DIAG
, 1);
169 if ((mf
= mtd_open(mtdname
)) >= 0) {
170 if (ioctl(mf
, MEMGETINFO
, &mi
) == 0) {
173 ei
.length
= mi
.erasesize
;
174 for (ei
.start
= 0; ei
.start
< mi
.size
; ei
.start
+= mi
.erasesize
) {
175 printf("%sing 0x%x - 0x%x\n", erase
? "Eras" : "Unlock", ei
.start
, (ei
.start
+ ei
.length
) - 1);
178 if (ioctl(mf
, MEMUNLOCK
, &ei
) != 0) {
179 // perror("MEMUNLOCK");
184 if (ioctl(mf
, MEMERASE
, &ei
) != 0) {
195 printf("%sing 0x%x - 0x%x\n", erase
? "Eras" : "Unlock", ei
.start
, ei
.length
- 1);
198 if (ioctl(mf
, MEMUNLOCK
, &ei
) != 0) {
203 if (ioctl(mf
, MEMERASE
, &ei
) != 0) {
212 read(mf
, &buf
, sizeof(buf
));
217 if (erase
) led(LED_DIAG
, 0);
218 set_action(ACT_IDLE
);
220 if (r
) printf("\"%s\" successfully %s.\n", mtdname
, erase
? "erased" : "unlocked");
221 else printf("\nError %sing MTD\n", erase
? "eras" : "unlock");
227 int mtd_unlock(const char *mtdname
)
229 return _unlock_erase(mtdname
, 0);
232 int mtd_erase(const char *mtdname
)
234 return _unlock_erase(mtdname
, 1);
237 int mtd_unlock_erase_main(int argc
, char *argv
[])
242 while ((c
= getopt(argc
, argv
, "d:")) != -1) {
251 usage_exit(argv
[0], "-d part");
254 return _unlock_erase(dev
, strstr(argv
[0], "erase") ? 1 : 0);
257 int mtd_write_main(int argc
, char *argv
[])
263 struct trx_header trx
;
264 struct code_header cth
;
278 while ((c
= getopt(argc
, argv
, "i:d:w")) != -1) {
292 if ((iname
== NULL
) || (dev
== NULL
)) {
293 usage_exit(argv
[0], "-i file -d part");
296 if (!wait_action_idle(10)) {
297 printf("System is busy\n");
300 set_action(ACT_WEB_UPGRADE
);
302 if ((f
= fopen(iname
, "r")) == NULL
) {
303 error
= "Error opening input file";
307 error
= "File contains an invalid header";
309 if (safe_fread(&sig
, 1, sizeof(sig
), f
) != sizeof(sig
)) {
313 case 0x47343557: // W54G G, GL
314 case 0x53343557: // W54S GS
315 case 0x73343557: // W54s GS v4
316 case 0x55343557: // W54U SL
317 case 0x31345257: // WR41 WRH54G
319 case 0x42435745: // EWCB WRT300N v1
320 // case 0x32435745: // EWC2 WRT300N?
321 case 0x3035314E: // N150 WRT150N
323 if (safe_fread(((char *)&cth
) + 4, 1, sizeof(cth
) - 4, f
) != (sizeof(cth
) - 4)) {
326 if (memcmp(cth
.id
, "U2ND", 4) != 0) {
330 // trx should be next...
331 if (safe_fread(&sig
, 1, sizeof(sig
), f
) != sizeof(sig
)) {
335 case 0x5E24232A: // Netgear
336 // header length is next
337 if (safe_fread(&n
, 1, sizeof(n
), f
) != sizeof(n
)) {
341 if (fseek(f
, ntohl(n
), SEEK_SET
) != 0) {
344 // trx should be next...
345 if (safe_fread(&sig
, 1, sizeof(sig
), f
) != sizeof(sig
)) {
353 if (safe_fread(&sig
, 1, sizeof(sig
), f
) != sizeof(sig
)) {
357 case 0x50705710: // WR850G
359 if (safe_fread(&sig
, 1, sizeof(sig
), f
) != sizeof(sig
)) {
369 if (sig
!= TRX_MAGIC
) {
372 if ((safe_fread(((char *)&trx
) + 4, 1, sizeof(trx
) - 4, f
) != (sizeof(trx
) - 4)) || (trx
.len
<= sizeof(trx
))) {
378 error
= "Not enough memory";
381 crc
= crc_calc(0xFFFFFFFF, (uint8
*)&trx
.flag_version
, sizeof(struct trx_header
) - OFFSETOF(struct trx_header
, flag_version
));
383 if (trx
.flag_version
& TRX_NO_HEADER
) {
384 trx
.len
-= sizeof(struct trx_header
);
385 _dprintf("don't write header\n");
388 _dprintf("trx len=%db 0x%x\n", trx
.len
, trx
.len
);
390 if ((mf
= mtd_open(dev
)) < 0) {
391 error
= "Error opening MTD device";
395 if ((ioctl(mf
, MEMGETINFO
, &mi
) != 0) || (mi
.erasesize
< sizeof(struct trx_header
))) {
396 error
= "Error obtaining MTD information";
400 _dprintf("mtd size=%6x, erasesize=%6x\n", mi
.size
, mi
.erasesize
);
402 total
= ROUNDUP(trx
.len
, mi
.erasesize
);
403 if (total
> mi
.size
) {
404 error
= "File is too big to fit in MTD";
409 if ((si
.freeram
* si
.mem_unit
) > (total
+ (256 * 1024))) {
413 // ei.length = ROUNDUP((si.freeram - (256 * 1024)), mi.erasesize);
414 ei
.length
= mi
.erasesize
;
416 _dprintf("freeram=%ld ei.length=%d total=%u\n", si
.freeram
, ei
.length
, total
);
418 if ((buf
= malloc(ei
.length
)) == NULL
) {
419 error
= "Not enough memory";
423 #ifdef DEBUG_SIMULATE
425 if ((of
= fopen("/mnt/out.bin", "w")) == NULL
) {
426 error
= "Error creating test file";
431 if (trx
.flag_version
& TRX_NO_HEADER
) {
435 memcpy(buf
, &trx
, sizeof(trx
));
438 _dprintf("trx.len=%ub 0x%x ofs=%ub 0x%x\n", trx
.len
, trx
.len
, ofs
, ofs
);
442 for (ei
.start
= 0; ei
.start
< total
; ei
.start
+= ei
.length
) {
443 n
= MIN(ei
.length
, trx
.len
) - ofs
;
444 if (safe_fread(buf
+ ofs
, 1, n
, f
) != n
) {
445 error
= "Error reading file";
448 trx
.len
-= (n
+ ofs
);
450 crc
= crc_calc(crc
, buf
+ ofs
, n
);
453 _dprintf("crc=%8x trx.crc=%8x\n", crc
, trx
.crc32
);
454 if (crc
!= trx
.crc32
) {
455 error
= "Image is corrupt";
461 printf("Writing %x-%x\r", ei
.start
, (ei
.start
+ ei
.length
) - 1);
464 _dprintf("ofs=%ub n=%ub 0x%x trx.len=%ub ei.start=0x%x ei.length=0x%x mi.erasesize=0x%x\n",
465 ofs
, n
, n
, trx
.len
, ei
.start
, ei
.length
, mi
.erasesize
);
469 _dprintf(" erase start=%x len=%x\n", ei
.start
, ei
.length
);
470 _dprintf(" write %x\n", n
);
472 #ifdef DEBUG_SIMULATE
473 if (fwrite(buf
, 1, n
, of
) != n
) {
475 error
= "Error writing to test file";
479 ioctl(mf
, MEMUNLOCK
, &ei
);
480 if (ioctl(mf
, MEMERASE
, &ei
) != 0) {
481 error
= "Error erasing MTD block";
484 if (write(mf
, buf
, n
) != n
) {
485 error
= "Error writing to MTD device";
492 #ifdef DEBUG_SIMULATE
499 read(mf
, &n
, sizeof(n
));
506 // set_action(ACT_IDLE);
508 printf("%s\n", error
? error
: "Image successfully flashed");
509 _dprintf("%s\n", error
? error
: "Image successfully flashed");
510 return (error
? 1 : 0);