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

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