source: src/router/httpd/modules/upgrade.c @ 18882

Last change on this file since 18882 was 18882, checked in by BrainSlayer, 14 months ago

small adjustment for factory defaults

File size: 12.9 KB
Line 
1
2/*
3 * Broadcom Home Gateway Reference Design
4 * Web Page Configuration Support Routines
5 *
6 * Copyright 2001-2003, Broadcom Corporation
7 * All Rights Reserved.
8 *
9 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
10 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
11 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
12 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
13 * $Id: upgrade.c,v 1.4 2005/11/30 11:53:42 seg Exp $
14 */
15
16#include <stdio.h>
17#include <string.h>
18#include <fcntl.h>
19#include <errno.h>
20#include <signal.h>
21#include <sys/stat.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include <sys/wait.h>
25
26#include <broadcom.h>
27#include <cyutils.h>
28#include <shutils.h>
29
30#define MIN_BUF_SIZE    4096
31#define CODE_PATTERN_ERROR 9999
32static int upgrade_ret;
33
34void set_upgrade_ret(int result)
35{
36        if (result != 0) {
37                upgrade_ret = result;
38        } else {
39                upgrade_ret = NULL;
40        }
41}
42
43void
44// do_upgrade_cgi(char *url, FILE *stream)
45do_upgrade_cgi(struct mime_handler *handler, char *url, webs_t stream, char *query)     // jimmy, https,
46                                                        // 8/6/2003
47{
48#ifndef ANTI_FLASH
49
50        fprintf(stderr, "[UPGRADE] ret: %d\n", upgrade_ret);
51        if (upgrade_ret) {
52                do_ej(handler, "Fail_u_s.asp", stream, NULL);
53                killall("ledtool", SIGTERM);
54                led_control(LED_DIAG, LED_OFF);
55        } else {
56                do_ej(handler, "Success_u_s.asp", stream, NULL);
57        }
58        websDone(stream, 200);
59
60        /*
61         * Reboot if successful
62         */
63        if (upgrade_ret == 0) {
64                // sleep (10);
65                sys_reboot();
66        }
67#else
68
69        do_ej(handler, "Fail_u_s.asp", stream, NULL);
70        websDone(stream, 200);
71
72#endif
73}
74
75int
76// sys_upgrade(char *url, FILE *stream, int *total)
77sys_upgrade(char *url, webs_t stream, int *total, int type)     // jimmy,
78                                                                // https,
79                                                                // 8/6/2003
80{
81
82        int brand = getRouterBrand();
83
84#ifndef ANTI_FLASH
85        char upload_fifo[] = "/tmp/uploadXXXXXX";
86        FILE *fifo = NULL;
87        char *write_argv[4];
88        pid_t pid;
89        char *buf = NULL;
90        int count, ret = 0;
91        long flags = -1;
92        int size = BUFSIZ;
93        int i = 0;
94#if (defined(HAVE_FONERA) || defined(HAVE_WHRAG108) || defined(HAVE_MERAKI) || defined(HAVE_TW6600) || defined(HAVE_PB42) || defined(HAVE_LS5) || defined(HAVE_USR5453)) && \
95(!defined(HAVE_DIR400) && !defined(HAVE_WRT54G2) && !defined(HAVE_GWMF54G2) && !defined(HAVE_FONERA2200) && !defined(HAVE_MR3202A) && !defined(HAVE_CA8PRO) &&  \
96!defined(HAVE_CA8) && !defined(HAVE_RT2880) && !defined(HAVE_LS2) && !defined(HAVE_WRK54G) && !defined(HAVE_ADM5120) && !defined(HAVE_DIR300) && !defined(HAVE_DLM101) && \
97!defined(HAVE_MERAKI) && !defined(HAVE_SOLO51) && !defined(HAVE_RTG32) && !defined(HAVE_EOC5610))
98#define WRITEPART "rootfs"
99#else
100#define WRITEPART "linux"
101#endif
102
103        write_argv[0] = "write";
104        write_argv[1] = upload_fifo;
105        write_argv[2] = WRITEPART;
106        write_argv[3] = NULL;
107        eval("fischecksum");
108        if (url)
109                return eval("write", url, WRITEPART);
110        // diag_led(DIAG, START_LED); // blink the diag led
111        C_led(1);
112#ifdef HAVE_HTTPS
113        if (do_ssl)
114                ACTION("ACT_WEBS_UPGRADE");
115        else
116#endif
117                ACTION("ACT_WEB_UPGRADE");
118        int uploadcount = 0;
119
120        /*
121         * Set nonblock on the socket so we can timeout
122         */
123#ifdef HAVE_HTTPS
124        if (!do_ssl) {
125#endif
126                if ((flags = fcntl(fileno(stream->fp), F_GETFL)) < 0 ||
127                    fcntl(fileno(stream->fp), F_SETFL, flags | O_NONBLOCK) < 0)
128                {
129                        ret = errno;
130                        goto err;
131                }
132#ifdef HAVE_HTTPS
133        }
134#endif
135
136        /*
137         ** The buffer must be at least as big as what the stream file is
138         ** using so that it can read all the data that has been buffered
139         ** in the stream file. Otherwise it would be out of sync with fn
140         ** select specially at the end of the data stream in which case
141         ** the select tells there is no more data available but there in
142         ** fact is data buffered in the stream file's buffer. Since no
143         ** one has changed the default stream file's buffer size, let's
144         ** use the constant BUFSIZ until someone changes it.
145         **/
146
147        if (size < MIN_BUF_SIZE)
148                size = MIN_BUF_SIZE;
149        if ((buf = safe_malloc(size)) == NULL) {
150                ret = ENOMEM;
151                goto err;
152        }
153        system("ledtool 500");
154        /*
155         * Pipe the rest to the FIFO
156         */
157        cprintf("Upgrading\n");
158        while (total && *total) {
159#ifdef HAVE_HTTPS
160                if (do_ssl) {
161                        if (size > *total)
162                                size = *total;
163                        count = wfread(buf, 1, size, stream);
164                } else
165#endif
166                {
167                        if (waitfor(fileno(stream->fp), 5) <= 0) {
168                                cprintf("waitfor timeout 5 secs\n");
169                                break;
170                        }
171                        count = safe_fread(buf, 1, size, stream->fp);
172                        if (!count && (ferror(stream->fp) || feof(stream->fp)))
173                                break;
174                }
175
176                if (i == 0) {   // check code pattern, the first data must
177#ifdef HAVE_BUFFALO
178                        if (!strncmp(buf, "bgn", 3) || !strncmp(buf, "WZR", 3)
179                            || !strncmp(buf, "WHR", 3)
180                            || !strncmp(buf, "WLA", 3)) {
181                                char *write_argv_buf[4];
182                                write_argv_buf[0] = "buffalo_flash";
183                                write_argv_buf[1] = upload_fifo;
184                                write_argv_buf[2] = NULL;
185
186                                if (!mktemp(upload_fifo) ||
187                                    mkfifo(upload_fifo, S_IRWXU) < 0 ||
188                                    (ret =
189                                     _evalpid(write_argv_buf, NULL, 0, &pid))
190                                    || !(fifo = fopen(upload_fifo, "w"))) {
191                                        if (!ret)
192                                                ret = errno;
193                                        goto err;
194                                }
195                                goto write_data;
196                        } else {
197                                if (!mktemp(upload_fifo) ||
198                                    mkfifo(upload_fifo, S_IRWXU) < 0 ||
199                                    (ret = _evalpid(write_argv, NULL, 0, &pid))
200                                    || !(fifo = fopen(upload_fifo, "w"))) {
201                                        if (!ret)
202                                                ret = errno;
203                                        goto err;
204                                }
205
206                        }
207
208#else
209                        /*
210                         * Feed write from a temporary FIFO
211                         */
212                        if (!mktemp(upload_fifo) ||
213                            mkfifo(upload_fifo, S_IRWXU) < 0 ||
214                            (ret = _evalpid(write_argv, NULL, 0, &pid)) ||
215                            !(fifo = fopen(upload_fifo, "w"))) {
216                                if (!ret)
217                                        ret = errno;
218                                goto err;
219                        }
220#endif
221                        // have code pattern
222                        char ver[40];
223                        long ver1, ver2, ver3;
224
225                        snprintf(ver, sizeof(ver), "v%d.%d.%d", buf[11],
226                                 buf[12], buf[13]);
227                        ver1 = convert_ver(ver);
228                        ver2 = convert_ver(INTEL_FLASH_SUPPORT_VERSION_FROM);
229                        ver3 = convert_ver(BCM4712_CHIP_SUPPORT_VERSION_FROM);
230
231                        fprintf(stderr,
232                                "upgrade_ver[%s] upgrade_ver[%ld] intel_ver[%ld] 4712_ver[%ld]\n",
233                                ver, ver1, ver2, ver3);
234#if defined(HAVE_WIKINGS) || defined(HAVE_ESPOD)
235
236#ifdef HAVE_WIKINGS
237#ifdef HAVE_SUB3
238#define V "XMED"
239#elif HAVE_SUB6
240#define V "XMIN"
241#else
242#define V "XMAX"
243#endif
244#endif
245
246#ifdef HAVE_ESPOD
247#ifdef HAVE_SUB3
248#define V "EPMN"
249#elif HAVE_SUB6
250#define V "EPMD"
251#else
252#define V "EPMX"
253#endif
254#endif
255                        if (memcmp(&buf[0], V, 4)) {
256                                fprintf(stderr, "code pattern error!\n");
257                                goto write_data;        // must be there, otherwise fail here
258                                //goto err;     // must be there, otherwise fail here
259                        }
260#undef V
261#endif
262
263#if defined(HAVE_WIKINGS) || defined(HAVE_ESPOD)
264#else
265#ifdef HAVE_WRT160NL
266                        if (memcmp(&buf[0], &CODE_PATTERN_WRT160NL, 4)
267                            && memcmp(&buf[0], &CODE_PATTERN_E2100L, 4)) {
268                                cprintf("code pattern error!\n");
269                                goto err;       // must be there, otherwise fail here
270                        }
271#else
272
273                        if ((brand == ROUTER_WRT320N && nvram_match("boardrev", "0x1307"))      //E2000
274                            || brand == ROUTER_LINKSYS_E2500
275                            || (brand == ROUTER_WRT610NV2 && nvram_match("boot_hw_model", "E300"))      //E3000
276                            || brand == ROUTER_LINKSYS_E3200
277                            || brand == ROUTER_LINKSYS_E4200) {
278                                if (memcmp(&buf[0], &CODE_PATTERN_E2000, 4)
279                                    && memcmp(&buf[0], &CODE_PATTERN_E2500, 4)
280                                    && memcmp(&buf[0], &CODE_PATTERN_E3000, 4)
281                                    && memcmp(&buf[0], &CODE_PATTERN_E3200, 4)
282                                    && memcmp(&buf[0], &CODE_PATTERN_E4200, 4)
283                                    && memcmp(&buf[0], &CODE_PATTERN_NV60K, 4)) {
284                                        cprintf
285                                            ("image not compatible with nv60k router!\n");
286                                        goto err;       // must be there, otherwise fail here
287                                }
288                        } else if (brand == ROUTER_NETGEAR_WNDR4000
289                                   || brand == ROUTER_NETGEAR_WNDR3400
290                                   || brand == ROUTER_LINKSYS_E900
291                                   || brand == ROUTER_LINKSYS_E1500) {
292                                if (memcmp(&buf[0], &CODE_PATTERN_E900, 4)
293                                        && memcmp(&buf[0], &CODE_PATTERN_E1500, 4)
294                                        && memcmp(&buf[0], &CODE_PATTERN_NV64K, 4)) {
295                                        cprintf
296                                            ("image not compatible with nv64k router!\n");
297                                        goto err;       // must be there, otherwise fail here
298                                }
299                        } else {
300                                if (memcmp(&buf[0], &CODE_PATTERN_NV60K, 4) == 0
301                                        || memcmp(&buf[0], &CODE_PATTERN_NV64K, 4) == 0) {
302                                        cprintf
303                                            ("image not compatible with your router!\n");
304                                        goto err;       // fail here                           
305                                }
306                        }
307
308                        if (memcmp(&buf[0], &CODE_PATTERN_WRT54G, 4)
309                            && memcmp(&buf[0], &CODE_PATTERN_WRT54GS, 4)
310                            && memcmp(&buf[0], &CODE_PATTERN_WRH54G, 4)
311                            && memcmp(&buf[0], &CODE_PATTERN_WRT150N, 4)
312                            && memcmp(&buf[0], &CODE_PATTERN_WRT160N, 4)
313                            && memcmp(&buf[0], &CODE_PATTERN_WRT300N, 4)
314                            && memcmp(&buf[0], &CODE_PATTERN_WRT300NV11, 4)
315                            && memcmp(&buf[0], &CODE_PATTERN_WRT310N, 4)
316                            && memcmp(&buf[0], &CODE_PATTERN_WRT350N, 4)
317                            && memcmp(&buf[0], &CODE_PATTERN_WRTSL54GS, 4)
318                            && memcmp(&buf[0], &CODE_PATTERN_WRT54G3G, 4)
319                            && memcmp(&buf[0], &CODE_PATTERN_WRT54G3GV, 4)
320                            && memcmp(&buf[0], &CODE_PATTERN_WRT610N, 4)
321                            && memcmp(&buf[0], &CODE_PATTERN_WRT54GSV4, 4)
322                            && memcmp(&buf[0], &CODE_PATTERN_WRT320N, 4)
323                            && memcmp(&buf[0], &CODE_PATTERN_VALET_M10, 4)
324                            && memcmp(&buf[0], &CODE_PATTERN_VALET_M20, 4)
325                            && memcmp(&buf[0], &CODE_PATTERN_E900, 4)
326                            && memcmp(&buf[0], &CODE_PATTERN_E1000, 4)
327                            && memcmp(&buf[0], &CODE_PATTERN_E1500, 4)
328                            && memcmp(&buf[0], &CODE_PATTERN_E2000, 4)
329                            && memcmp(&buf[0], &CODE_PATTERN_E2500, 4)
330                            && memcmp(&buf[0], &CODE_PATTERN_E3000, 4)
331                            && memcmp(&buf[0], &CODE_PATTERN_E3200, 4)
332                            && memcmp(&buf[0], &CODE_PATTERN_E4200, 4)
333                            && memcmp(&buf[0], &CODE_PATTERN_NV60K, 4)
334                            && memcmp(&buf[0], &CODE_PATTERN_NV64K, 4)) {
335                                cprintf("code pattern error!\n");
336                                goto write_data;
337                        }
338#endif
339#endif
340
341                        if (check_hw_type() == BCM4712_CHIP && ver1 < ver3) {
342                                fprintf(stderr,
343                                        "The old firmware version can't support bcm4712 chipset\n");
344                                fprintf(stderr,
345                                        "Can't downgrade to this old firmware version (%s), must be above %s(included)\n",
346                                        ver, BCM4712_CHIP_SUPPORT_VERSION_FROM);
347                                goto write_data;
348                        }
349
350                        fprintf(stderr, "code pattern correct!\n");
351                        *total -= count;
352#ifdef HAVE_WRT160NL
353                        safe_fwrite(buf, 1, count, fifo);       // we have to write the whole header to flash too
354#else
355                        safe_fwrite(&buf[sizeof(struct code_header)], 1,
356                                    count - sizeof(struct code_header), fifo);
357#endif
358                        i++;
359                        continue;
360                }
361
362              write_data:
363                *total -= count;
364                safe_fwrite(buf, 1, count, fifo);
365                // safe_fwrite(buf, 1, size, fifo);
366                uploadcount += count;
367                fprintf(stderr, "uploading [%d]\r", uploadcount);
368                i++;
369        }
370        fclose(fifo);
371        fifo = NULL;
372
373        /*
374         * Wait for write to terminate
375         */
376        waitpid(pid, &ret, 0);
377        fprintf(stderr, "uploading [%d]\n", uploadcount);
378        cprintf("done\n");
379#ifdef HAVE_HTTPS
380        if (!do_ssl) {
381#endif
382                /*
383                 * Reset nonblock on the socket
384                 */
385                if (fcntl(fileno(stream->fp), F_SETFL, flags) < 0) {
386                        ret = errno;
387                        goto err;
388                }
389#ifdef HAVE_HTTPS
390        }
391#endif
392
393err:
394        if (buf)
395                free(buf);
396        if (fifo)
397                fclose(fifo);
398        unlink(upload_fifo);
399
400        // diag_led(DIAG, STOP_LED);
401        C_led(0);
402        ACTION("ACT_IDLE");
403
404        return ret;
405#else
406        return 0;
407#endif
408}
409
410void
411// do_upgrade_post(char *url, FILE *stream, int len, char *boundary)
412do_upgrade_post(char *url, webs_t stream, int len, char *boundary)      // jimmy,
413                                                                        // https,
414                                                                        // 8/6/2003
415{
416        killall("udhcpc", SIGKILL);
417
418#ifndef ANTI_FLASH
419        char buf[1024];
420        int type = 0;
421
422        upgrade_ret = EINVAL;
423
424        /*
425         * Look for our part
426         */
427        while (len > 0) {
428                if (!wfgets(buf, MIN(len + 1, sizeof(buf)), stream))
429                        return;
430
431                len -= strlen(buf);
432                if (!strncasecmp(buf, "Content-Disposition:", 20)) {
433                        if (strstr(buf, "name=\"erase\"")) {
434                                while (len > 0 && strcmp(buf, "\n")
435                                       && strcmp(buf, "\r\n")) {
436                                        if (!wfgets
437                                            (buf, MIN(len + 1, sizeof(buf)),
438                                             stream))
439                                                return;
440
441                                        len -= strlen(buf);
442                                }
443                                if (!wfgets
444                                    (buf, MIN(len + 1, sizeof(buf)), stream))
445                                        return;
446                                len -= strlen(buf);
447                                buf[1] = '\0';  // we only want the 1st digit
448                                nvram_set("sv_restore_defaults", buf);
449                                nvram_commit();
450                        } else if (strstr(buf, "name=\"file\"")) {      // upgrade image
451                                type = 0;
452                                break;
453                        }
454                }
455        }
456
457        /*
458         * Skip boundary and headers
459         */
460        while (len > 0) {
461                if (!wfgets(buf, MIN(len + 1, sizeof(buf)), stream))
462                        return;
463
464                len -= strlen(buf);
465                if (!strcmp(buf, "\n") || !strcmp(buf, "\r\n"))
466                        break;
467        }
468
469        upgrade_ret = sys_upgrade(NULL, stream, &len, type);
470
471        /*
472         * Restore factory original settings if told to. This will also cause a
473         * restore defaults on reboot of a Sveasoft firmware.
474         */
475#ifdef HAVE_BUFFALO_SA
476        int region_sa = 0;
477        if(nvram_default_match("region", "SA", ""))
478                region_sa = 1;
479#endif
480        if (nvram_match("sv_restore_defaults", "1")) {
481                eval("erase", "nvram");
482#ifdef HAVE_BUFFALO_SA
483                nvram_set("sv_restore_defaults", "1");
484                if(region_sa)
485                        nvram_set("region", "SA");
486#endif
487        }
488        sys_commit();
489       
490        // #ifdef HAVE_WRK54G
491        // sys_reboot();
492        // #endif
493        /*
494         * Slurp anything remaining in the request
495         */
496
497        while ((len--) > 0) {
498#ifdef HAVE_HTTPS
499                if (do_ssl) {
500                        wfgets(buf, 1, stream);
501                } else {
502                        (void)fgetc(stream->fp);
503                }
504#else
505                (void)fgetc(stream->fp);
506#endif
507        }
508#endif
509}
Note: See TracBrowser for help on using the repository browser.