rewrite of the webif firmware upgrade process
authorFelix Fietkau <[email protected]>
Thu, 9 Feb 2006 08:59:52 +0000 (08:59 +0000)
committerFelix Fietkau <[email protected]>
Thu, 9 Feb 2006 08:59:52 +0000 (08:59 +0000)
SVN-Revision: 3201

openwrt/package/webif/Makefile
openwrt/package/webif/files/usr/lib/webif/lang/de/common.txt
openwrt/package/webif/files/usr/lib/webif/lang/es/common.txt
openwrt/package/webif/files/usr/lib/webif/lang/fr/common.txt
openwrt/package/webif/files/usr/lib/webif/webif.sh
openwrt/package/webif/files/www/cgi-bin/webif/upgrade.sh
openwrt/package/webif/src/bstrip.c [new file with mode: 0644]
openwrt/package/webif/src/webif-page.c

index cc6c26ac77e9afbfd214f869e405daf3c68f3700..ae4419ab552030b17b149b143fe795ff1a9220a3 100644 (file)
@@ -24,13 +24,15 @@ $(PKG_BUILD_DIR)/.configured:
 
 $(PKG_BUILD_DIR)/.built:
        $(TARGET_CC) $(TARGET_CFLAGS) $(NVRAM_OPTS) -o $(PKG_BUILD_DIR)/webif-page src/webif-page.c
-       $(STRIP) $(PKG_BUILD_DIR)/webif-page
+       $(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/bstrip src/bstrip.c
+       $(STRIP) $(PKG_BUILD_DIR)/webif-page $(PKG_BUILD_DIR)/bstrip
        touch $@
 
 $(IPKG_WEBIF): 
        cp -a ./files/* $(IDIR_WEBIF)/
        install -d $(IDIR_WEBIF)/usr/bin
        install -m0755 $(PKG_BUILD_DIR)/webif-page $(IDIR_WEBIF)/usr/bin/webif-page
+       install -m0755 $(PKG_BUILD_DIR)/bstrip $(IDIR_WEBIF)/usr/bin/bstrip
        find $(IDIR_WEBIF) -name CVS | xargs rm -rf
        find $(IDIR_WEBIF) -name .svn | xargs rm -rf
        $(IPKG_BUILD) $(IDIR_WEBIF) $(PACKAGE_DIR)
index b860b51562cd4f80e28ed6cf49221dd63338c500..85ab59d6e18acb547e702810920e651f1024d4bd 100644 (file)
@@ -99,7 +99,6 @@ Install => Installieren
 
 # 'Firmware Upgrade' page
 Firmware format => Firmware-Format
-converting... => konvertiere...
 Error => Fehler
 done => fertig
 Invalid_format => Das Dateiformat der Firmware ist ung&uuml;ltig
index a1715b6c452d5001d36cd5da4c59751bd5d0f46c..323c62a9cffede42311214c0320824106b7529d5 100644 (file)
@@ -99,7 +99,6 @@ Install => Instalar
 
 # 'Firmware Upgrade' page
 Firmware format => Formato del firmware
-converting... => convirtiendo...
 Error => Error
 done => hecho
 Invalid_formt => Formato del firmware inv&aacute;lido
index 35482937ec45ff95e632f7eda187fc0ef1d8d905..b86cd3b4c85427e329aa904f8c37255f0cd19fd1 100644 (file)
@@ -107,7 +107,6 @@ Install => Installer
 
 # 'Firmware Upgrade' page
 Firmware format => Format du firmware
-converting... => conversion en cours...
 Error => Erreur
 done => prĂȘt
 Invalid_formt => Le firmware n'a pas un format valide
index f42ab17929f1b77f5dd580635c4ca32ab4892152..cdf235889d37d53c6e42ef2fc23b5998f3364f5c 100644 (file)
@@ -135,6 +135,8 @@ EOF
 <h3>@TR<<Warning>>: @TR<<Password_warning|you haven't set a password for the Web interface and SSH access<br />Please enter one now (the user name in your browser will be 'root').>></h3>
 <br />
 <br />
+EOF
+                       empty "$NOINPUT" && cat <<EOF
 <form enctype="multipart/form-data" action="$SCRIPT_NAME" method="POST">
 <table>
        <tr>
index c27be439b05fa2fd85f2c4f57f8451d327aff6a7..9d67e00805e8c8aa1b6af353a88a9c6c2a8ad857 100755 (executable)
@@ -1,45 +1,58 @@
-#!/usr/bin/webif-page -u
-<? 
+#!/usr/bin/webif-page -p /bin/sh
 . /usr/lib/webif/webif.sh
-header "System" "Firmware Upgrade" "@TR<<Firmware Upgrade>>"
 
-strip_cybertan() {
-       (
-               dd of=/dev/null bs=32 count=1 2>/dev/null
-               cat > /tmp/upgrade.bin
-       ) < "$FORM_firmware"
-       rm "$FORM_firmware"
+do_upgrade() {
+       # free some memory :)
+       ps | grep -vE 'Command|init|\[[kbmj]|httpd|haserl|bin/sh|awk|kill|ps|webif' | awk '{ print $1 }' | xargs kill -KILL
+       MEMFREE="$(awk 'BEGIN{ mem = 0 } ($1 == "MemFree:") || ($1 == "Cached:") {mem += int($2)} END{print mem}' /proc/meminfo)"
+       empty "$ERASE_NVRAM" || {
+               mtd -q erase nvram
+       }
+       empty "$ERASE_FS" || MTD_OPT="-e linux"
+       if [ $(($MEMFREE)) -ge 4096 ]; then
+               bstrip "$BOUNDARY" > /tmp/firmware.bin
+               mtd $MTD_OPT -q -r write /tmp/firmware.bin linux
+       else
+               # Not enough memory for storing the firmware on tmpfs
+               bstrip "$BOUNDARY" | mtd $MTD_OPT -q -q -r write - linux
+       fi
+       echo "@TR<<done>>."
 }
 
-empty "$FORM_submit" || empty "$FORM_firmware" || {
-       exists $FORM_firmware && {
-               HEADER=$(head -c4 $FORM_firmware | hexdump -e "8/1 \"%x\"")
-               grep BCM947 /proc/cpuinfo > /dev/null && {
-                       case "$HEADER" in
-                               48445230) # TRX
-                                       echo "@TR<<Firmware format>>: TRX<br />"
-                                       mv $FORM_firmware /tmp/upgrade.bin
-                                       UPGRADE=1
-                               ;;
-                               57353447|57353453|57353473) # WRT54G(S)
-                                       echo "@TR<<Firmware format>>: Cybertan BIN =&gt; @TR<<converting...>> "
-                                       strip_cybertan
-                                       echo "@TR<<done>>. <br />"
-                                       UPGRADE=1
-                               ;;
-                               *)
-                                       rm $FORM_firmware
-                                       ERROR="<h2>@TR<<Error>>: @TR<<Invalid_format|Invalid firmware file format>></h2>"
-                               ;;
-                       esac
-               }
-       } || {
-               ERROR="<h2>@TR<<Error>>: @TR<<Open_failed|Couldn't open firmware file>></h2>"
-       }
+read_var() {
+       NAME=""
+       while :; do
+               read LINE
+               LINE="${LINE%%[^0-9A-Za-z]}"
+               equal "$LINE" "$BOUNDARY" && read LINE
+               empty "$NAME$LINE" && exit
+               case "${LINE%%:*}" in
+                       Content-Disposition)
+                               NAME="${LINE##*; name=\"}"
+                               NAME="${NAME%%\"*}"
+                       ;;
+               esac
+               empty "$LINE" && return
+       done
+}
+
+
+NOINPUT=1
+header "System" "Firmware Upgrade" "@TR<<Firmware Upgrade>>"
+
+equal "$REQUEST_METHOD" "GET" && {
+       cat <<EOF
+       <script type="text/javascript">
+       
+function statusupdate() {
+       document.getElementById("form_submit").style.display = "none";
+       document.getElementById("status_text").style.display = "inline";
+       document.getElementById("status_text").firstChild.nodeValue = "@TR<<Upgrading...>>";
+
+       return true;
 }
-?>
-<?if empty "$UPGRADE" ?>
-       <form method="POST" name="upgrade" action="<? echo -n $SCRIPT_NAME ?>" enctype="multipart/form-data">
+       </script>
+       <form method="POST" name="upgrade" action="$SCRIPT_NAME" enctype="multipart/form-data" onSubmit="statusupdate()">
        <table style="width: 90%; text-align: left;" border="0" cellpadding="2" cellspacing="2" align="center">
        <tbody>
                <tr>
@@ -55,25 +68,52 @@ empty "$FORM_submit" || empty "$FORM_firmware" || {
                                <input type="file" name="firmware" />
                        </td>
                </tr>
+               <tr>
                        <td />
-                       <td><input type="submit" name="submit" value="@TR<<Upgrade>>" /></td>
+                       <td>
+                               <div style="display: none; font-size: 14pt; font-weight: bold;" id="status_text" />&nbsp;</div>
+                               <input id="form_submit" type="submit" name="submit" value="@TR<<Upgrade>>" onClick="statusupdate()" />
+                       </td>
                </tr>
        </tbody>
        </table>
        </form>
-<?el?>
-<?
-       ERASE="${FORM_erase_fs:+-e linux }"
-       ERASE="$ERASE${FORM_erase_nvram:+-e nvram }"
-       cp /bin/busybox /tmp/
-       echo '@TR<<Upgrading...>>'
-       # FIXME: probably a race condition (with the reboot), but it seems to work
-       mtd -r $ERASE write /tmp/upgrade.bin linux 2>&- | awk 'END { print "@TR<<done>>." }'
-       exit
-?>
-<?fi?>
+EOF
+}
+equal "$REQUEST_METHOD" "POST" && {
+       equal "${CONTENT_TYPE%%;*}" "multipart/form-data" || ERR=1
+       BOUNDARY="${CONTENT_TYPE##*boundary=}"
+       empty "$BOUNDARY" && ERR=1
+
+       empty "$ERR" || {
+               echo "Wrong data format"
+               footer
+               exit
+       }
+cat <<EOF
+       <div style="margin: auto; text-align: left">
+<pre>
+EOF
+       while :; do
+               read_var
+               empty "$NAME" && exit
+               case "$NAME" in
+                       erase_fs)
+                               ERASE_FS=1
+                               bstrip "$BOUNDARY" > /dev/null
+                       ;;
+                       erase_nvram)
+                               ERASE_NVRAM=1
+                               bstrip "$BOUNDARY" > /dev/null
+                       ;;
+                       firmware) do_upgrade;;
+               esac
+       done
+cat <<EOF
+       </div>
+EOF
+}
+
+footer
 
-<? footer ?>
-<!--
 ##WEBIF:name:System:4:Firmware Upgrade
--->
diff --git a/openwrt/package/webif/src/bstrip.c b/openwrt/package/webif/src/bstrip.c
new file mode 100644 (file)
index 0000000..ccd49af
--- /dev/null
@@ -0,0 +1,73 @@
+#include <stdio.h>
+
+#define BUF_SIZE 1024
+#define READ_LEN 14
+
+static int read_len = READ_LEN;
+static char rbuf[32];
+static char rbuflen = 0;
+
+int do_gets(char *buf)
+{
+       int r = 0, c = 0;
+       char *m;
+       
+       if (rbuflen > 0)
+               memcpy(buf, rbuf, rbuflen);
+       c += rbuflen;
+
+       while ((c + read_len < BUF_SIZE) && ((r = read(0, &buf[c], read_len)) > 0)) {
+               m = NULL;
+               
+               if ((m = memchr(&buf[c], '\n', r)) != NULL) {
+                       rbuflen = r - (m - &buf[c] + 1);
+                       if (rbuflen > 0)
+                               memcpy(rbuf, m + 1, rbuflen);
+                       c += m - &buf[c] + 1;
+               } else {
+                       rbuflen = 0;
+                       c += r;
+               }
+               
+               if ((c > 3) && (memcmp(&buf[c - 3], "---", 3) == 0))
+                       read_len = 1;
+               
+               if (m != NULL)
+                       return c;
+       }
+
+       return c;
+}
+
+int main(int argc, char **argv)
+{
+       char buf[BUF_SIZE];
+       char buf1[BUF_SIZE];
+       char *tmp;
+       int len, r = 0, r1 = 0;
+
+       if (argc != 2) {
+               fprintf(stderr, "Syntax: %s (name|data <boundary>)\n", argv[0]);
+               exit(1);
+       }
+       while (tmp = strchr(argv[1], '\r'))
+               *tmp = 0;
+                                       
+       len = strlen(argv[1]);
+
+       *buf = 0;
+       while ((strncmp(buf, argv[1], len) != 0) && 
+               (strncmp(buf + 2, argv[1], len) != 0)) {
+               if (r > 0) {
+                       if (r1 > 0)
+                               write (1, buf1, r1);
+                       r1 = r;
+                       memcpy(buf1, buf, r);
+               }
+               if ((r = do_gets(buf)) <= 0)
+                       exit(1);
+       }
+
+       if (r1 > 2)
+               write(1, buf1, r1 - 2);
+}
index 9d0222f6fa16fd78efc1bdb43d218db7150a82ad..13e70937ec6c82ea53f7f8b4d526dfe968b637c4 100644 (file)
@@ -181,10 +181,11 @@ static void load_lang(char *file)
 int main (int argc, char **argv)
 {
        FILE *f;
-       int len, i;
-       char line[LINE_BUF];
+       int len, i, done;
+       char line[LINE_BUF], *tmp, *arg;
        glob_t langfiles;
        char *lang = NULL;
+       char *proc = "/usr/bin/haserl";
 
        memset(ltable, 0, HASH_MAX * sizeof(lstr *));
 #ifdef NVRAM
@@ -231,8 +232,49 @@ nomatch:
                }
        }
 
+       /*
+        * command line options for this parser are stored in argv[1] only.
+        * filename to be processed is in argv[2]
+        */
+       done = 0;
        i = 1;
-       strcpy(buf, "/usr/bin/haserl");
+       while (!done) {
+               if (argv[1] == NULL) {
+                       done = 1;
+               } else if (strncmp(argv[1], "-e", 2) == 0) {
+                       argv[1] = strchr(argv[1], ' ');
+                       argv[1]++;
+                       if (argv[1] != NULL) {
+                               arg = argv[1];
+                               if ((tmp = strchr(argv[1], ' ')) != NULL) {
+                                       *tmp = 0;
+                                       argv[1] = &tmp[1];
+                               } else {
+                                       argv[1] = NULL;
+                                       i++;
+                               }
+                               system(arg);
+                       }
+               } else if (strncmp(argv[1], "-p", 2) == 0) {
+                       argv[1] = strchr(argv[1], ' ');
+                       argv[1]++;
+                       if (argv[1] != NULL) {
+                               arg = argv[1];
+                               if ((tmp = strchr(argv[1], ' ')) != NULL) {
+                                       *tmp = 0;
+                                       argv[1] = &tmp[1];
+                               } else {
+                                       argv[1] = NULL;
+                                       i++;
+                               }
+                               proc = strdup(arg);
+                       }
+               } else {
+                       done = 1;
+               }
+       }
+
+       strcpy(buf, proc);
        while (argv[i]) {
                sprintf(buf + strlen(buf), " %s", argv[i++]);
        }