source: src/router/httpd/modules/upgrade_x86.c @ 17205

Last change on this file since 17205 was 17205, checked in by BrainSlayer, 2 years ago

new x86 code

File size: 8.8 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
29#define MIN_BUF_SIZE    4096
30#define CODE_PATTERN_ERROR 9999
31static int upgrade_ret;
32
33#ifdef HAVE_X86
34static char *getdisc(void)      // works only for squashfs
35{
36        int i;
37        unsigned char *disks[]={"/dev/sda2","/dev/sdb2","/dev/sdc2","/dev/sdd2","/dev/sde2","/dev/sdf2","/dev/sdg2","/dev/sdh2","/dev/sdi2"};
38        for (i = 0; i < 9; i++) {
39                char dev[64];
40
41                strcpy(dev, disks[i]);
42                FILE *in = fopen(dev, "rb");
43
44                if (in == NULL)
45                        continue;       // no second partition or disc does not
46                // exist, skipping
47                char buf[4];
48
49                fread(buf, 4, 1, in);
50                if (buf[0] == 'h' && buf[1] == 's' && buf[2] == 'q'
51                    && buf[3] == 't') {
52                        fclose(in);
53                        // filesystem detected
54                        return disks[i];
55                }
56                fclose(in);
57        }
58        return NULL;
59}
60#endif
61void
62// do_upgrade_cgi(char *url, FILE *stream)
63do_upgrade_cgi(struct mime_handler *handler, char *url, webs_t stream, char *query)     // jimmy, https,
64                                                        // 8/6/2003
65{
66#ifndef ANTI_FLASH
67        fprintf(stderr, "do post\n");
68        if (upgrade_ret)
69                do_ej(handler, "Fail_u_s.asp", stream, NULL);
70        else
71                do_ej(handler, "Success_u_s.asp", stream, NULL);
72        fprintf(stderr, "websdone\n");
73
74        websDone(stream, 200);
75        fprintf(stderr, "reboot\n");
76
77        /*
78         * Reboot if successful
79         */
80        if (upgrade_ret == 0) {
81                sleep(4);
82                eval("umount", "/usr/local");
83                sys_reboot();
84        }
85#else
86        do_ej(handler, "Fail_u_s.asp", stream, NULL);
87        websDone(stream, 200);
88#endif
89}
90
91#ifdef HAVE_RB600
92#define swap(x) \
93        ((unsigned int )( \
94                        (((unsigned int )(x) & (unsigned int )0x000000ffUL) << 24) | \
95                        (((unsigned int )(x) & (unsigned int )0x0000ff00UL) <<  8) | \
96                        (((unsigned int )(x) & (unsigned int )0x00ff0000UL) >>  8) | \
97                        (((unsigned int )(x) & (unsigned int )0xff000000UL) >> 24) ))
98
99
100#endif
101
102int
103// sys_upgrade(char *url, FILE *stream, int *total)
104sys_upgrade(char *url, webs_t stream, int *total, int type)     // jimmy,
105                                                                // https,
106                                                                // 8/6/2003
107{
108        lcdmessage("System Upgrade");
109#ifndef ANTI_FLASH
110        char upload_fifo[] = "/tmp/uploadXXXXXX";
111        FILE *fifo = NULL;
112        char *write_argv[4];
113        pid_t pid;
114        char *buf = NULL;
115        int count, ret = 0;
116        long flags = -1;
117        int size = BUFSIZ;
118        int i = 0;
119
120        {
121                write_argv[0] = "write";
122                write_argv[1] = upload_fifo;
123                write_argv[2] = "linux";
124                write_argv[3] = NULL;
125        }
126
127        // diag_led(DIAG, START_LED); // blink the diag led
128        C_led(1);
129#ifdef HAVE_HTTPS
130        if (do_ssl)
131                ACTION("ACT_WEBS_UPGRADE");
132        else
133#endif
134                ACTION("ACT_WEB_UPGRADE");
135
136        /*
137         * Feed write from a temporary FIFO
138         */
139        if (!mktemp(upload_fifo) || !(fifo = fopen(upload_fifo, "w"))) {
140                if (!ret)
141                        ret = errno;
142                goto err;
143        }
144
145        /*
146         * Set nonblock on the socket so we can timeout
147         */
148
149        /*
150         ** The buffer must be at least as big as what the stream file is
151         ** using so that it can read all the data that has been buffered
152         ** in the stream file. Otherwise it would be out of sync with fn
153         ** select specially at the end of the data stream in which case
154         ** the select tells there is no more data available but there in
155         ** fact is data buffered in the stream file's buffer. Since no
156         ** one has changed the default stream file's buffer size, let's
157         ** use the constant BUFSIZ until someone changes it.
158         **/
159
160        if (size < MIN_BUF_SIZE)
161                size = MIN_BUF_SIZE;
162        if ((buf = safe_malloc(size)) == NULL) {
163                ret = ENOMEM;
164                goto err;
165        }
166
167        /*
168         * Pipe the rest to the FIFO
169         */
170        cprintf("Upgrading\n");
171        // while (total && *total)
172        {
173                wfread(&buf[0], 1, 5, stream);
174                *total -= 5;
175                if (buf[0] != 'W' || buf[1] != 'R' || buf[2] != 'A'
176                    || buf[3] != 'P' || buf[4] != '1') {
177                        ret = -1;
178                        goto err;
179                }
180                int linuxsize;
181
182                wfread(&linuxsize, 1, 4, stream);
183                *total -= 4;
184                safe_fwrite(&linuxsize, 1, 4, fifo);
185#ifdef HAVE_RB600
186                linuxsize=swap(linuxsize);
187#endif
188                for (i = 0; i < linuxsize / MIN_BUF_SIZE; i++) {
189                        wfread(&buf[0], 1, MIN_BUF_SIZE, stream);
190                        fwrite(&buf[0], 1, MIN_BUF_SIZE, fifo);
191                }
192
193                wfread(&buf[0], 1, linuxsize % MIN_BUF_SIZE, stream);
194                fwrite(&buf[0], 1, linuxsize % MIN_BUF_SIZE, fifo);
195                *total -= linuxsize;
196
197        }
198        fclose(fifo);
199        fifo = NULL;
200        fifo = fopen(upload_fifo, "rb");
201        unsigned long linuxsize;
202
203        linuxsize = 0;
204        linuxsize += getc(fifo);
205        linuxsize += getc(fifo) * 256;
206        linuxsize += getc(fifo) * 256 * 256;
207        linuxsize += getc(fifo) * 256 * 256 * 256;
208        char dev[128];
209
210        char drive[64];
211#ifdef HAVE_RB600
212        sprintf(drive, "/dev/sda");
213#else
214        strcpy(drive, getdisc());
215#endif
216        fprintf (stderr, "Write Linux %d to %s\n", linuxsize,dev);
217        //backup nvram
218        fprintf(stderr, "backup nvram\n");
219        FILE *in = fopen("/usr/local/nvram/nvram.bin", "rb");
220        if (in) {
221                char *mem = malloc(65536);
222                fread(mem, 65536, 1, in);
223                fclose(in);
224                in = fopen(drive, "r+b");
225                fseeko(in, 0, SEEK_END);
226                off_t mtdlen = ftello(in);
227                fseeko(in, mtdlen - (65536 * 2), SEEK_SET);
228                fwrite(mem, 65536, 1, in);
229                fclose(in);
230                eval("sync");
231                in = fopen(drive, "rb");
232                fseeko(in, mtdlen - (65536 * 2), SEEK_SET);
233                fread(mem, 65536, 1, in);
234                fclose(in);
235                free(mem);
236        }
237        fprintf(stderr, "write system\n");
238        FILE *out = fopen(drive, "r+b");
239        char *flashbuf = (char *)malloc(linuxsize);
240        if (!flashbuf)          // not enough memory, use direct way
241        {
242                for (i = 0; i < linuxsize; i++)
243                        putc(getc(fifo), out);
244        } else {
245                //read into temp buffer
246                fread(flashbuf, linuxsize, 1, fifo);
247                fwrite(flashbuf, linuxsize, 1, out);
248                free(flashbuf);
249        }
250        fclose(out);
251        fprintf(stderr, "sync system\n");
252        sysprintf("sync");
253        sysprintf("sync");
254        sysprintf("echo 1 > /proc/sys/vm/drop_caches"); // flush fs cache
255        //reread for validation
256        fprintf(stderr, "check system for validation\n");
257        in = fopen(drive, "rb");
258        for (i = 0; i < linuxsize; i++)
259                getc(in);
260        fclose(in);
261        sysprintf("sync");
262        /*
263         * Wait for write to terminate
264         */
265        // waitpid (pid, &ret, 0);
266        cprintf("done\n");
267        ret = 0;
268err:
269        if (buf)
270                free(buf);
271        if (fifo)
272                fclose(fifo);
273        unlink(upload_fifo);
274
275        // diag_led(DIAG, STOP_LED);
276        // C_led (0);
277        fprintf(stderr, "Idle\n");
278        ACTION("ACT_IDLE");
279
280        return ret;
281#else
282        return 0;
283#endif
284}
285
286void
287// do_upgrade_post(char *url, FILE *stream, int len, char *boundary)
288do_upgrade_post(char *url, webs_t stream, int len, char *boundary)      // jimmy,
289                                                                        // https,
290                                                                        // 8/6/2003
291{
292
293        killall("udhcpc", SIGKILL);
294#ifndef ANTI_FLASH
295        char buf[1024];
296        int type = 0;
297
298        upgrade_ret = EINVAL;
299
300        // Let below files loaded to memory
301        // To avoid the successful screen is blank after web upgrade.
302
303        /*
304         * Look for our part
305         */
306        while (len > 0) {
307                if (!wfgets(buf, MIN(len + 1, sizeof(buf)), stream))
308                        return;
309                len -= strlen(buf);
310                if (!strncasecmp(buf, "Content-Disposition:", 20)) {
311                        if (strstr(buf, "name=\"erase\"")) {
312                                while (len > 0 && strcmp(buf, "\n")
313                                       && strcmp(buf, "\r\n")) {
314                                        if (!wfgets
315                                            (buf, MIN(len + 1, sizeof(buf)),
316                                             stream))
317                                                return;
318                                        len -= strlen(buf);
319                                }
320                                if (!wfgets
321                                    (buf, MIN(len + 1, sizeof(buf)), stream))
322                                        return;
323                                len -= strlen(buf);
324                                buf[1] = '\0';  // we only want the 1st digit
325                                nvram_set("sv_restore_defaults", buf);
326                                nvram_commit();
327                        } else if (strstr(buf, "name=\"file\""))        // upgrade image
328                        {
329                                type = 0;
330                                break;
331                        }
332                }
333        }
334
335        /*
336         * Skip boundary and headers
337         */
338        while (len > 0) {
339                if (!wfgets(buf, MIN(len + 1, sizeof(buf)), stream))
340                        return;
341                len -= strlen(buf);
342                if (!strcmp(buf, "\n") || !strcmp(buf, "\r\n"))
343                        break;
344        }
345        upgrade_ret = sys_upgrade(NULL, stream, &len, type);
346        fprintf(stderr, "core upgrade done() %d\n", len);
347        /*
348         * Restore factory original settings if told to. This will also cause a
349         * restore defaults on reboot of a Sveasoft firmware.
350         */
351        if (nvram_match("sv_restore_defaults", "1")) {
352                system2("rm -f /usr/local/nvram/nvram.bin");
353                char drive[64];
354#ifdef HAVE_RB600
355        sprintf(drive, "/dev/sda");
356#else
357        strcpy(drive, getdisc());
358#endif
359                FILE *in = fopen(drive, "r+b");
360                fseeko(in, 0, SEEK_END);
361                off_t mtdlen = ftell(in);
362                fseeko(in, mtdlen - (65536 * 2), SEEK_SET);
363                int i;
364                for (i = 0; i < 65536; i++)
365                        putc(0, in);    // erase backup area
366                fclose(in);
367        }
368        /*
369         * Slurp anything remaining in the request
370         */
371        while (len--) {
372#ifdef HAVE_HTTPS
373                if (do_ssl) {
374                        wfgets(buf, 1, stream);
375                } else {
376                        (void)fgetc(stream);
377                }
378#else
379                (void)fgetc(stream);
380#endif
381
382        }
383#endif
384        fprintf(stderr, "upgrade done()\n");
385
386}
Note: See TracBrowser for help on using the repository browser.