source: src/router/rc/mtd.c @ 15197

Last change on this file since 15197 was 15197, checked in by eko, 3 years ago

belkin Play / Share support

File size: 20.7 KB
Line 
1
2#include <limits.h>
3#include <unistd.h>
4#include <stdlib.h>
5#include <stdio.h>
6#include <stdint.h>
7#include <fcntl.h>
8#include <errno.h>
9#include <error.h>
10#include <time.h>
11#include <sys/ioctl.h>
12#include <sys/types.h>
13#include <sys/param.h>
14#include <sys/mount.h>
15#include <sys/stat.h>
16#include <sys/reboot.h>
17#include <sys/sysinfo.h>
18
19#include <string.h>
20#include <linux/version.h>
21
22#if KERNEL_VERSION(2,6,0) <= LINUX_VERSION_CODE
23#define IS_KERNEL26 1
24#else
25#define IS_KERNEL26 0
26#endif
27
28#if IS_KERNEL26
29#include <linux/mtd/mtd-abi.h>
30#else
31#include <linux/mtd/mtd.h>
32#endif
33
34#include <trxhdr.h>
35#include <crc.h>
36#include <bcmutils.h>
37#include <bcmnvram.h>
38#include <shutils.h>
39
40#include <cy_conf.h>
41#include <utils.h>
42
43#include <endian.h>
44#include <byteswap.h>
45
46#if __BYTE_ORDER == __BIG_ENDIAN
47#define STORE32_LE(X)           bswap_32(X)
48#elif __BYTE_ORDER == __LITTLE_ENDIAN
49#define STORE32_LE(X)           (X)
50#else
51#error unkown endianness!
52#endif
53
54/* Netgear definitions */
55#define NETGEAR_CRC_FAKE 1      //we fake checksum only over 4 bytes (HDR0)
56
57#ifdef NETGEAR_CRC_FAKE
58#define NETGEAR_CRC_FAKE_LEN            0x00000004
59#define NETGEAR_CRC_FAKE_CHK            0x02C0010E
60#else
61static unsigned long calculate_checksum(int action, char *s, int size);
62#endif
63#define WGR614_LZMA_LOADER_SIZE         0x000919        //loader+400.lzma = 2329 bytes, please change if size changes!
64#define FLASH_SIZE_4M                           0x400000
65#define FLASH_SIZE_8M                           0x800000
66#define CFE_SIZE_128K                           0x020000
67#define CFE_SIZE_256K                           0x040000
68#define NETGEAR_LEN_CHK_ADDR_4M         0x3AFFF8
69#define NETGEAR_LEN_CHK_ADDR_8M         0x7AFFF8
70/* end */
71
72/* Belkin Share & Play series */
73#define TRX_MAGIC_F7D3301                       0x20100322      /* Belkin Share Max; router's birthday ? */
74#define TRX_MAGIC_F7D3302                       0x20090928      /* Belkin Share; router's birthday ? */
75#define TRX_MAGIC_F7D4302                       0x20091006      /* Belkin Play; router's birthday ? */
76#define TRX_MAGIC_QA                            0x12345678      /* Belkin: cfe: It's QA firmware */
77/* end */
78
79/*
80 * Open an MTD device
81 * @param       mtd     path to or partition name of MTD device
82 * @param       flags   open() flags
83 * @return      return value of open()
84 */
85int mtd_open(const char *mtd, int flags)
86{
87        FILE *fp;
88        char dev[PATH_MAX];
89        int i;
90
91        if ((fp = fopen("/proc/mtd", "r"))) {
92                while (fgets(dev, sizeof(dev), fp)) {
93                        if (sscanf(dev, "mtd%d:", &i) && strstr(dev, mtd)) {
94                                snprintf(dev, sizeof(dev), "/dev/mtd/%d", i);
95                                fclose(fp);
96                                return open(dev, flags);
97                        }
98                }
99                fclose(fp);
100        }
101
102        return open(mtd, flags);
103}
104
105/*
106 * Erase an MTD device
107 * @param       mtd     path to or partition name of MTD device
108 * @return      0 on success and errno on failure
109 */
110int mtd_erase(const char *mtd)
111{
112        int mtd_fd;
113        struct mtd_info_user mtd_info;
114        struct erase_info_user erase_info;
115
116        /*
117         * char *et0; char *et1;
118         *
119         * et0=nvram_safe_get("et0macaddr"); et1=nvram_safe_get("et1macaddr");
120         * et0=strdup(et0); et1=strdup(et1);
121         */
122        /*
123         * Open MTD device
124         */
125        if ((mtd_fd = mtd_open(mtd, O_RDWR)) < 0) {
126                perror(mtd);
127                return errno;
128        }
129
130        /*
131         * Get sector size
132         */
133        if (ioctl(mtd_fd, MEMGETINFO, &mtd_info) != 0) {
134                perror(mtd);
135                close(mtd_fd);
136                return errno;
137        }
138
139        erase_info.length = mtd_info.erasesize;
140
141        for (erase_info.start = 0;
142             erase_info.start < mtd_info.size;
143             erase_info.start += mtd_info.erasesize) {
144                fprintf(stderr, "erase[%d]\r", erase_info.start);
145                (void)ioctl(mtd_fd, MEMUNLOCK, &erase_info);
146                if (ioctl(mtd_fd, MEMERASE, &erase_info) != 0) {
147                        perror(mtd);
148                        close(mtd_fd);
149                        return errno;
150                }
151        }
152
153        close(mtd_fd);
154        fprintf(stderr, "erase[%d]\n", erase_info.start);
155        /*
156         * nvram_set("et0macaddr",et0); nvram_set("et1macaddr",et1);
157         * nvram_commit(); free(et0); free(et1);
158         */
159
160        return 0;
161}
162
163extern int http_get(const char *server, char *buf, size_t count, off_t offset);
164
165/*
166 * Write a file to an MTD device
167 * @param       path    file to write or a URL
168 * @param       mtd     path to or partition name of MTD device
169 * @return      0 on success and errno on failure
170 */
171
172struct img_info {
173        uint32_t lenght;
174        uint32_t CRC;
175};
176
177
178struct code_header {
179        char magic[4];
180        char res1[4];   // for extra magic
181        char fwdate[3];
182        char fwvern[3];
183        char id[4];     // U2ND
184        char hw_ver;    // 0) for 4702, 1) for 4712, 2) for 4712L, 3) for 4704
185        char res2;
186        unsigned short flags;
187        unsigned char res3[10];
188} __attribute__((packed));
189
190struct etrx_header {
191        struct code_header code;
192        struct trx_header trx;
193} __attribute__((packed));
194
195#define SQUASHFS_MAGIC                  0x74717368
196
197int mtd_write(const char *path, const char *mtd)
198{
199        int mtd_fd = -1;
200        struct mtd_info_user mtd_info;
201        struct erase_info_user erase_info;
202
203        struct sysinfo info;
204#ifdef HAVE_WRT160NL
205        struct etrx_header etrx;
206#endif
207        struct trx_header trx;
208        unsigned long crc;
209        int squashfound = 0;
210        unsigned int crc_data = 0;
211        unsigned int data_len = 0;
212        unsigned int cal_chksum = 0;
213        FILE *fp;
214        char *buf = NULL;
215        long count, len, off;
216        long sum = 0;           // for debug
217        int ret = -1;
218        int i;
219        unsigned char lzmaloader[4096];
220        int brand = getRouterBrand();
221
222        /*
223         * Netgear WGR614v8_L: Read, store and write back old lzma loader from 1st block
224         */
225        if (brand == ROUTER_NETGEAR_WGR614L) {
226                if ((fp = fopen("/dev/mtdblock/1", "rb")))
227                        count =
228                            safe_fread(&trx, 1, sizeof(struct trx_header), fp);
229                else
230                        return -1;
231
232                memset(lzmaloader, 0, 4096);
233                fseek(fp, trx.offsets[0], SEEK_SET);
234                fread(lzmaloader, WGR614_LZMA_LOADER_SIZE, 1, fp);
235                fclose(fp);
236        }
237
238#ifdef HAVE_BCMMODERN           
239        unsigned long trxhd = STORE32_LE(TRX_MAGIC);
240       
241        if (brand == ROUTER_BELKIN_F7D3301
242                || brand == ROUTER_BELKIN_F7D3302
243                || brand == ROUTER_BELKIN_F7D4302) {
244                        if ((fp = fopen("/dev/mtdblock/1", "rb"))) {
245                                fread(&trxhd, 4, 1, fp);
246                                fclose(fp);
247                        }
248        }
249#endif
250       
251        nvram_set("flash_active", "1");
252        sleep(1);
253
254        /*
255         * Examine TRX header
256         */
257#ifdef HAVE_WRT160NL
258        fprintf(stderr,"size of ETRX header = %d\n",sizeof(struct etrx_header));
259        if ((fp = fopen(path, "r")))
260                count = safe_fread(&etrx, 1, sizeof(struct etrx_header), fp);
261        else
262                return -1;
263        memcpy(&trx,&etrx.trx,sizeof(struct trx_header));
264#else
265        if ((fp = fopen(path, "r")))
266                count = safe_fread(&trx, 1, sizeof(struct trx_header), fp);
267        else
268                return -1;
269
270#endif
271        // count = http_get (path, (char *) &trx, sizeof (struct trx_header), 0);
272        if (count < sizeof(struct trx_header)) {
273                fprintf(stderr, "%s: File is too small (%ld bytes)\n", path,
274                        count);
275                goto fail;
276        }
277        sysinfo(&info);
278#ifndef HAVE_CAMBRIA
279        stop_service("sshd");
280        stop_service("snmp");
281        stop_service("zebra");
282        stop_service("pppoeserver");
283        stop_service("olsrd");
284        stop_service("openvpn");
285        stop_service("openvpnserver");
286        stop_service("pptpd");
287        stop_service("upnp");
288        stop_service("freeradius");
289        system("killall process_monitor");
290#endif
291#ifdef HAVE_MAGICBOX
292        trx.magic = STORE32_LE(trx.magic);
293        trx.len = STORE32_LE(trx.len);
294        trx.crc32 = STORE32_LE(trx.crc32);
295#elif HAVE_FONERA
296        trx.magic = STORE32_LE(trx.magic);
297        trx.len = STORE32_LE(trx.len);
298        trx.crc32 = STORE32_LE(trx.crc32);
299        // info.freeram = 64; //fix, must be flashed in erase blocks
300#elif HAVE_SOLO51
301        trx.magic = STORE32_LE(trx.magic);
302        trx.len = STORE32_LE(trx.len);
303        trx.crc32 = STORE32_LE(trx.crc32);
304        // info.freeram = 64; //fix, must be flashed in erase blocks
305#elif HAVE_MERAKI
306        trx.magic = STORE32_LE(trx.magic);
307        trx.len = STORE32_LE(trx.len);
308        trx.crc32 = STORE32_LE(trx.crc32);
309        // info.freeram = 64; //fix, must be flashed in erase blocks
310#elif HAVE_LS2
311        trx.magic = STORE32_LE(trx.magic);
312        trx.len = STORE32_LE(trx.len);
313        trx.crc32 = STORE32_LE(trx.crc32);
314        // info.freeram = 64; //fix, must be flashed in erase blocks
315#elif HAVE_LS5
316        trx.magic = STORE32_LE(trx.magic);
317        trx.len = STORE32_LE(trx.len);
318        trx.crc32 = STORE32_LE(trx.crc32);
319#elif HAVE_WHRAG108
320        trx.magic = STORE32_LE(trx.magic);
321        trx.len = STORE32_LE(trx.len);
322        trx.crc32 = STORE32_LE(trx.crc32);
323#elif HAVE_PB42
324        trx.magic = STORE32_LE(trx.magic);
325        trx.len = STORE32_LE(trx.len);
326        trx.crc32 = STORE32_LE(trx.crc32);
327        // info.freeram = 64; //fix, must be flashed in erase blocks
328#elif HAVE_LSX
329        trx.magic = STORE32_LE(trx.magic);
330        trx.len = STORE32_LE(trx.len);
331        trx.crc32 = STORE32_LE(trx.crc32);
332        // info.freeram = 64; //fix, must be flashed in erase blocks
333#elif HAVE_TW6600
334        trx.magic = STORE32_LE(trx.magic);
335        trx.len = STORE32_LE(trx.len);
336        trx.crc32 = STORE32_LE(trx.crc32);
337#elif HAVE_CA8
338        trx.magic = STORE32_LE(trx.magic);
339        trx.len = STORE32_LE(trx.len);
340        trx.crc32 = STORE32_LE(trx.crc32);
341#elif HAVE_XSCALE
342        trx.magic = STORE32_LE(trx.magic);
343        trx.len = STORE32_LE(trx.len);
344        trx.crc32 = STORE32_LE(trx.crc32);
345#endif
346
347        if (trx.magic != TRX_MAGIC || trx.len < sizeof(struct trx_header)) {
348                fprintf(stderr, "%s: Bad trx header\n", path);
349                goto fail;
350        }
351        /*
352         * Open MTD device and get sector size
353         */
354        if ((mtd_fd = mtd_open(mtd, O_RDWR)) < 0 ||
355            ioctl(mtd_fd, MEMGETINFO, &mtd_info) != 0 ||
356            mtd_info.erasesize < sizeof(struct trx_header)) {
357                perror(mtd);
358                goto fail;
359        }
360        if (STORE32_LE(trx.flag_version) & TRX_NO_HEADER)
361                trx.len -= sizeof(struct trx_header);
362
363        // #ifndef HAVE_WRK54G
364        if (mtd_info.size < trx.len) {
365                fprintf(stderr, "Image too big for partition: %s\n", mtd);
366                perror(mtd);
367                goto fail;
368        }
369        // #endif
370
371        /*
372         * See if we have enough memory to store the whole file
373         */
374        fprintf(stderr, "freeram=[%ld] bufferram=[%ld]\n", info.freeram,
375                info.bufferram);
376        int mul = 1;            // temporarily use 1 instead of 4 until we
377
378        // found a a solution
379        if ((info.freeram + info.bufferram) >= (trx.len + 1 * 1024 * 1024)) {
380                fprintf(stderr,
381                        "The free memory is enough, writing image once.\n");
382                /*
383                 * Begin to write image after all image be downloaded by web upgrade.
384                 * In order to avoid upgrade fail if user unplug the ethernet cable
385                 * during upgrading
386                 */
387                // if(check_action() == ACT_WEBS_UPGRADE || check_action() ==
388                // ACT_WEB_UPGRADE)
389                erase_info.length = ROUNDUP(trx.len, mtd_info.erasesize);
390        } else {
391                erase_info.length = mtd_info.erasesize * mul;
392                fprintf(stderr,
393                        "The free memory is not enough, writing image per %d bytes.\n",
394                        erase_info.length);
395        }
396
397        /*
398         * Allocate temporary buffer
399         */
400        if (!(buf = malloc(erase_info.length))) {
401                mul = 1;
402                erase_info.length = mtd_info.erasesize * mul;
403                fprintf(stderr,
404                        "The free memory is not enough, writing image per %d bytes.\n",
405                        erase_info.length);
406                if (!(buf = malloc(erase_info.length))) {
407                        perror("malloc");
408                        goto fail;
409                }
410        }
411
412        /*
413         * Calculate CRC over header
414         */
415        crc = crc32((uint8 *) & trx.flag_version,
416                    sizeof(struct trx_header) - OFFSETOF(struct trx_header,
417                                                         flag_version),
418                    CRC32_INIT_VALUE);
419        crc_data = 0;
420#ifndef NETGEAR_CRC_FAKE
421        calculate_checksum(0, NULL, 0); // init
422#endif
423        /*
424         * Write file or URL to MTD device
425         */
426        for (erase_info.start = 0; erase_info.start < trx.len;
427             erase_info.start += count) {
428                len = MIN(erase_info.length, trx.len - erase_info.start);
429                if ((STORE32_LE(trx.flag_version) & TRX_NO_HEADER)
430                    || erase_info.start)
431                        count = off = 0;
432                else {
433                #ifdef HAVE_WRT160NL
434                        count = off = sizeof(struct etrx_header);
435                        memcpy(buf, &etrx, sizeof(struct etrx_header));
436                #else
437                        count = off = sizeof(struct trx_header);
438                        memcpy(buf, &trx, sizeof(struct trx_header));
439                #endif
440                }
441                // if (fp)
442                count += safe_fread(&buf[off], 1, len - off, fp);
443                // else
444                // count +=
445                // http_get (path, &buf[off], len - off, erase_info.start + off);
446
447                /*
448                 * for debug
449                 */
450                sum = sum + count;
451                fprintf(stderr, "write=[%ld]         \n", sum);
452
453                if (((count < len)
454                     && (len - off) > (mtd_info.erasesize * mul))
455                    || (count == 0)) {
456                        fprintf(stderr,
457                                "%s: Truncated file (actual %ld expect %ld)\n",
458                                path, count - off, len - off);
459                        goto fail;
460                }
461                /*
462                 * Update CRC
463                 */
464                crc = crc32(&buf[off], count - off, crc);
465#ifndef NETGEAR_CRC_FAKE
466                calculate_checksum(1, buf, count);
467#endif
468
469                if (!squashfound) {
470                        for (i = 0; i < (count - off); i++) {
471                                unsigned int *sq =
472                                    (unsigned int *)&buf[off + i];
473
474                                if (*sq == SQUASHFS_MAGIC) {
475                                        squashfound = 1;
476                                        break;
477                                }
478                                crc_data += (unsigned char)buf[off + i];
479                        }
480                        data_len += i;
481                }
482                /*
483                 * Check CRC before writing if possible
484                 */
485                #ifdef HAVE_WRT160NL
486                if (count == trx.len + sizeof(struct code_header)) {
487                #else
488                if (count == trx.len) {         
489                #endif
490                        if (crc != trx.crc32) {
491                                fprintf(stderr, "%s: Bad CRC\n", path);
492                                goto fail;
493                        } else {
494                                fprintf(stderr, "%s: CRC OK\n", mtd);
495                                fprintf(stderr,
496                                        "Writing image to flash, waiting a moment...\n");
497                        }
498                }
499                erase_info.length = mtd_info.erasesize;
500
501                int length = ROUNDUP(count, mtd_info.erasesize);
502                int base = erase_info.start;
503                for (i = 0; i < (length / mtd_info.erasesize); i++) {
504                        fprintf(stderr,
505                                "write block [%ld] at [0x%08X]        \n",
506                                i * mtd_info.erasesize,
507                                base + (i * mtd_info.erasesize));
508                        erase_info.start = base + (i * mtd_info.erasesize);
509                        (void)ioctl(mtd_fd, MEMUNLOCK, &erase_info);
510                        if (ioctl(mtd_fd, MEMERASE, &erase_info) != 0
511                            || write(mtd_fd, buf + (i * mtd_info.erasesize),
512                                     mtd_info.erasesize) !=
513                            mtd_info.erasesize) {
514                                perror(mtd);
515                                goto fail;
516                        }
517                }
518        }
519        /*
520         * Netgear: Write len and checksum at the end of mtd1
521         */
522        int sector_start;
523        char *tmp;
524
525        if (brand == ROUTER_NETGEAR_WGR614L
526            || brand == ROUTER_NETGEAR_WNR834B
527            || brand == ROUTER_NETGEAR_WNR834BV2
528            || brand == ROUTER_NETGEAR_WNDR3300
529            || brand == ROUTER_NETGEAR_WNR3500L) {
530#ifndef NETGEAR_CRC_FAKE
531                cal_chksum = calculate_checksum(2, NULL, 0);
532#endif
533
534                char imageInfo[8];
535                unsigned long flash_len_chk_addr = NETGEAR_LEN_CHK_ADDR_4M;
536                unsigned long cfe_size = CFE_SIZE_128K;
537
538                if (brand == ROUTER_NETGEAR_WNR3500L) {
539                        cfe_size = CFE_SIZE_256K;
540                        if (mtd_info.size > FLASH_SIZE_4M) {
541                                flash_len_chk_addr = NETGEAR_LEN_CHK_ADDR_8M;
542                        }
543                }
544                                       
545#ifndef NETGEAR_CRC_FAKE
546                trx.len = STORE32_LE(trx.len);
547                cal_chksum = STORE32_LE(cal_chksum);
548#else
549                trx.len = STORE32_LE(NETGEAR_CRC_FAKE_LEN);
550                cal_chksum = STORE32_LE(NETGEAR_CRC_FAKE_CHK);
551#endif
552                memcpy(&imageInfo[0], (char *)&trx.len, 4);
553                memcpy(&imageInfo[4], (char *)&cal_chksum, 4);
554
555                sector_start =
556                    ((flash_len_chk_addr - cfe_size) / mtd_info.erasesize) *
557                    mtd_info.erasesize;
558
559                if (lseek(mtd_fd, sector_start, SEEK_SET) < 0) {
560                        //fprintf( stderr, "Error seeking the file descriptor\n" );
561                        goto fail;
562                }
563
564                free(buf);
565
566                if (!(buf = malloc(mtd_info.erasesize))) {
567                        //fprintf( stderr, "Error allocating image block\n");
568                        goto fail;
569                }
570
571                memset(buf, 0, mtd_info.erasesize);
572
573                if (read(mtd_fd, buf, mtd_info.erasesize) != mtd_info.erasesize) {
574                        //fprintf( stderr, "Error reading last block from MTD device\n" );
575                        goto fail;
576                }
577
578                if (lseek(mtd_fd, sector_start, SEEK_SET) < 0) {
579                        //fprintf( stderr, "Error seeking the file descriptor\n" );
580                        goto fail;
581                }
582
583                erase_info.start = sector_start;
584                erase_info.length = mtd_info.erasesize;
585                ioctl(mtd_fd, MEMUNLOCK, &erase_info);
586
587                if (ioctl(mtd_fd, MEMERASE, &erase_info) != 0) {
588                        //fprintf( stderr, "Error erasing MTD block\n" );
589                        goto fail;
590                }
591
592                tmp = buf + ((flash_len_chk_addr - cfe_size) % mtd_info.erasesize);
593                memcpy(tmp, imageInfo, sizeof(imageInfo));
594
595                if (write(mtd_fd, buf, mtd_info.erasesize) !=
596                    mtd_info.erasesize) {
597                        //fprintf( stderr, "Error writing chksum to MTD device\n" );
598                        goto fail;
599                }
600                //fprintf( stderr, "TRX LEN = %x , CHECKSUM = %x\n", trx.len, cal_chksum );
601#ifndef NETGEAR_CRC_FAKE
602                fprintf(stderr, "Write len/chksum @ 0x%X ...done.\n", flash_len_chk_addr);
603#else
604                fprintf(stderr, "Write fake len/chksum @ 0x%X ...done.\n", flash_len_chk_addr);
605#endif
606        }
607
608        /* Write old lzma loader */
609        if (brand == ROUTER_NETGEAR_WGR614L) {
610                int offset = trx.offsets[0];
611                sector_start =
612                    (offset / mtd_info.erasesize) * mtd_info.erasesize;
613
614                if (lseek(mtd_fd, sector_start, SEEK_SET) < 0) {
615                        //fprintf( stderr, "Error seeking the file descriptor\n" );
616                        goto fail;
617                }
618
619                free(buf);
620
621                if (!(buf = malloc(mtd_info.erasesize))) {
622                        //fprintf( stderr, "Error allocating image block\n");
623                        goto fail;
624                }
625
626                memset(buf, 0, mtd_info.erasesize);
627
628                if (read(mtd_fd, buf, mtd_info.erasesize) != mtd_info.erasesize) {
629                        //fprintf( stderr, "Error reading first block from MTD device\n" );
630                        goto fail;
631                }
632
633                if (lseek(mtd_fd, sector_start, SEEK_SET) < 0) {
634                        //fprintf( stderr, "Error seeking the file descriptor\n" );
635                        goto fail;
636                }
637
638                erase_info.start = sector_start;
639                erase_info.length = mtd_info.erasesize;
640                ioctl(mtd_fd, MEMUNLOCK, &erase_info);
641
642                if (ioctl(mtd_fd, MEMERASE, &erase_info) != 0) {
643                        //fprintf( stderr, "Error erasing MTD block\n" );
644                        goto fail;
645                }
646
647                tmp = buf + (offset % mtd_info.erasesize);
648                if (trx.offsets[1] - trx.offsets[0] >= WGR614_LZMA_LOADER_SIZE) {
649                        memcpy(tmp, lzmaloader, trx.offsets[1] - trx.offsets[0]);       //we asume lzma loader is shorter then gz loader
650                        //fprintf( stderr, "LZMA loader size OK, space=%d needed=%d\n", trx.offsets[1] - trx.offsets[0], WGR614_LZMA_LOADER_SIZE );
651                } else {
652                        memset(buf, 0, mtd_info.erasesize);     //destroy 1st block, which puts router into tftp mode to allow recover
653                        //fprintf( stderr, "LZMA loader size too large, space=%d needed=%d\n", trx.offsets[1] - trx.offsets[0], WGR614_LZMA_LOADER_SIZE );
654                }
655                if (write(mtd_fd, buf, mtd_info.erasesize) !=
656                    mtd_info.erasesize) {
657                        //fprintf( stderr, "Error writing LZMA loader to MTD device\n" );
658                        goto fail;
659                }
660
661                fprintf(stderr, "Write lzma loader...done.\n");
662
663        }                       // end
664       
665#ifdef HAVE_BCMMODERN
666        /* Write Belkin Play or Share magic */
667        if (brand == ROUTER_BELKIN_F7D3301
668                || brand == ROUTER_BELKIN_F7D3302
669                || brand == ROUTER_BELKIN_F7D4302) {
670
671                sector_start = 0;
672                unsigned long be_magic = STORE32_LE(trxhd);
673                char be_trx[4];
674
675                memcpy(&be_trx[0], (char *)&be_magic, 4);
676               
677
678                if (lseek(mtd_fd, sector_start, SEEK_SET) < 0) {
679                        //fprintf( stderr, "Error seeking the file descriptor\n" );
680                        goto fail;
681                }
682
683                free(buf);
684
685                if (!(buf = malloc(mtd_info.erasesize))) {
686                        //fprintf( stderr, "Error allocating image block\n");
687                        goto fail;
688                }
689
690                memset(buf, 0, mtd_info.erasesize);
691
692                if (read(mtd_fd, buf, mtd_info.erasesize) != mtd_info.erasesize) {
693                        //fprintf( stderr, "Error reading first block from MTD device\n" );
694                        goto fail;
695                }
696
697                if (lseek(mtd_fd, sector_start, SEEK_SET) < 0) {
698                        //fprintf( stderr, "Error seeking the file descriptor\n" );
699                        goto fail;
700                }
701
702                erase_info.start = sector_start;
703                erase_info.length = mtd_info.erasesize;
704                ioctl(mtd_fd, MEMUNLOCK, &erase_info);
705
706                if (ioctl(mtd_fd, MEMERASE, &erase_info) != 0) {
707                        //fprintf( stderr, "Error erasing MTD block\n" );
708                        goto fail;
709                }
710
711                memcpy(buf, be_trx, 4);
712
713                if (write(mtd_fd, buf, mtd_info.erasesize) !=
714                    mtd_info.erasesize) {
715                        //fprintf( stderr, "Error writing Belkin magic to MTD device\n" );
716                        goto fail;
717                }
718
719                fprintf(stderr, "Write Belkin magic...done.\n");
720
721        }               // end
722#endif
723
724        ret = 0;
725
726fail:
727        nvram_set("flash_active", "0");
728        if (buf) {
729                /*
730                 * Dummy read to ensure chip(s) are out of lock/suspend state
731                 */
732                (void)read(mtd_fd, buf, 2);
733                free(buf);
734        }
735
736        if (mtd_fd >= 0)
737                close(mtd_fd);
738
739        if (fp)
740                fclose(fp);
741#ifdef HAVE_CA8
742#ifndef HAVE_ALPHA
743#ifndef HAVE_USR5453
744        buf = malloc(65536);
745        FILE *in = fopen("/dev/mtdblock/2", "rb");
746
747        fread(buf, 65536, 1, in);
748        fclose(in);
749        struct img_info *image_info;
750
751        image_info = buf + 0x56;
752        image_info->lenght = data_len;
753        image_info->CRC = crc_data;
754        in = fopen("/tmp/bdata", "wb");
755        fwrite(buf, 65536, 1, in);
756        fclose(in);
757        fprintf(stderr, "fixup CRC %X and LEN %X\n", crc_data, data_len);
758        eval("mtd", "-f", "write", "/tmp/bdata", "bdata");
759#endif
760#endif
761#endif
762#ifdef HAVE_WZRHPAG300NH
763        // must delete checksum, otherwise device will not boot anymore. the checksum gets recreated by the bootloader
764        if (!ret)
765            sysprintf("ubootenv del buf_crc");
766#endif
767        // eval("fischecksum");
768
769        return ret;
770}
771
772/*
773 * Irving -  We need an unlock function in order to mount a r/w jffs2 partition
774 * Unlock an MTD device
775 * @param       mtd     path to or partition name of MTD device
776 * @return      0 on success and errno on failure
777 */
778int mtd_unlock(const char *mtd)
779{
780        int mtd_fd;
781        struct mtd_info_user mtd_info;
782        struct erase_info_user lock_info;
783
784        /*
785         * Open MTD device
786         */
787        if ((mtd_fd = mtd_open(mtd, O_RDWR)) < 0) {
788                perror(mtd);
789                return errno;
790        }
791
792        /*
793         * Get sector size
794         */
795        if (ioctl(mtd_fd, MEMGETINFO, &mtd_info) != 0) {
796                perror(mtd);
797                close(mtd_fd);
798                return errno;
799        }
800
801        lock_info.start = 0;
802        lock_info.length = mtd_info.size;
803
804        if (ioctl(mtd_fd, MEMUNLOCK, &lock_info)) {
805                fprintf(stderr, "Could not unlock MTD device: %s\n", mtd);
806                perror(mtd);
807                close(mtd_fd);
808                return errno;
809        }
810
811        close(mtd_fd);
812        return 0;
813}
814
815#ifndef NETGEAR_CRC_FAKE
816// Netgear image checksum
817static unsigned long calculate_checksum(int action, char *s, int size)
818{
819        static unsigned long c0, c1;
820        unsigned long checksum, b;
821        int i;
822
823        switch (action) {
824        case 0:
825                c0 = c1 = 0;
826                break;
827
828        case 1:
829                for (i = 0; i < size; i++) {
830                        c0 += s[i] & 0xff;
831                        c1 += c0;
832                }
833                break;
834
835        case 2:
836                b = (c0 & 65535) + ((c0 >> 16) & 65535);
837                c0 = ((b >> 16) + b) & 65535;
838
839                b = (c1 & 65535) + ((c1 >> 16) & 65535);
840                c1 = ((b >> 16) + b) & 65535;
841
842                checksum = ((c1 << 16) | c0);
843
844                return checksum;
845        }
846        return 0;
847}
848#endif
Note: See TracBrowser for help on using the repository browser.