From bb83304182f1611a281ba6901a7c7df47f41ff56 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 9 Feb 2006 08:59:52 +0000 Subject: [PATCH] rewrite of the webif firmware upgrade process SVN-Revision: 3201 --- openwrt/package/webif/Makefile | 4 +- .../files/usr/lib/webif/lang/de/common.txt | 1 - .../files/usr/lib/webif/lang/es/common.txt | 1 - .../files/usr/lib/webif/lang/fr/common.txt | 1 - .../webif/files/usr/lib/webif/webif.sh | 2 + .../webif/files/www/cgi-bin/webif/upgrade.sh | 144 +++++++++++------- openwrt/package/webif/src/bstrip.c | 73 +++++++++ openwrt/package/webif/src/webif-page.c | 48 +++++- 8 files changed, 215 insertions(+), 59 deletions(-) create mode 100644 openwrt/package/webif/src/bstrip.c diff --git a/openwrt/package/webif/Makefile b/openwrt/package/webif/Makefile index cc6c26ac77..ae4419ab55 100644 --- a/openwrt/package/webif/Makefile +++ b/openwrt/package/webif/Makefile @@ -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) diff --git a/openwrt/package/webif/files/usr/lib/webif/lang/de/common.txt b/openwrt/package/webif/files/usr/lib/webif/lang/de/common.txt index b860b51562..85ab59d6e1 100644 --- a/openwrt/package/webif/files/usr/lib/webif/lang/de/common.txt +++ b/openwrt/package/webif/files/usr/lib/webif/lang/de/common.txt @@ -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ültig diff --git a/openwrt/package/webif/files/usr/lib/webif/lang/es/common.txt b/openwrt/package/webif/files/usr/lib/webif/lang/es/common.txt index a1715b6c45..323c62a9cf 100644 --- a/openwrt/package/webif/files/usr/lib/webif/lang/es/common.txt +++ b/openwrt/package/webif/files/usr/lib/webif/lang/es/common.txt @@ -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álido diff --git a/openwrt/package/webif/files/usr/lib/webif/lang/fr/common.txt b/openwrt/package/webif/files/usr/lib/webif/lang/fr/common.txt index 35482937ec..b86cd3b4c8 100644 --- a/openwrt/package/webif/files/usr/lib/webif/lang/fr/common.txt +++ b/openwrt/package/webif/files/usr/lib/webif/lang/fr/common.txt @@ -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 diff --git a/openwrt/package/webif/files/usr/lib/webif/webif.sh b/openwrt/package/webif/files/usr/lib/webif/webif.sh index f42ab17929..cdf235889d 100644 --- a/openwrt/package/webif/files/usr/lib/webif/webif.sh +++ b/openwrt/package/webif/files/usr/lib/webif/webif.sh @@ -135,6 +135,8 @@ EOF

@TR<>: @TR<Please enter one now (the user name in your browser will be 'root').>>



+EOF + empty "$NOINPUT" && cat < diff --git a/openwrt/package/webif/files/www/cgi-bin/webif/upgrade.sh b/openwrt/package/webif/files/www/cgi-bin/webif/upgrade.sh index c27be439b0..9d67e00805 100755 --- a/openwrt/package/webif/files/www/cgi-bin/webif/upgrade.sh +++ b/openwrt/package/webif/files/www/cgi-bin/webif/upgrade.sh @@ -1,45 +1,58 @@ -#!/usr/bin/webif-page -u ->" -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<>." } -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<>: TRX
" - mv $FORM_firmware /tmp/upgrade.bin - UPGRADE=1 - ;; - 57353447|57353453|57353473) # WRT54G(S) - echo "@TR<>: Cybertan BIN => @TR<> " - strip_cybertan - echo "@TR<>.
" - UPGRADE=1 - ;; - *) - rm $FORM_firmware - ERROR="

@TR<>: @TR<>

" - ;; - esac - } - } || { - ERROR="

@TR<>: @TR<>

" - } +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<>" + +equal "$REQUEST_METHOD" "GET" && { + cat < + +function statusupdate() { + document.getElementById("form_submit").style.display = "none"; + document.getElementById("status_text").style.display = "inline"; + document.getElementById("status_text").firstChild.nodeValue = "@TR<>"; + + return true; } -?> - -
+ +
@@ -55,25 +68,52 @@ empty "$FORM_submit" || empty "$FORM_firmware" || { + +
- + + +
- ->' - # 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<>." }' - exit -?> - +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
+	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
+}
+
+footer
 
-
-
diff --git a/openwrt/package/webif/src/bstrip.c b/openwrt/package/webif/src/bstrip.c
new file mode 100644
index 0000000000..ccd49af37a
--- /dev/null
+++ b/openwrt/package/webif/src/bstrip.c
@@ -0,0 +1,73 @@
+#include 
+
+#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 )\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);
+}
diff --git a/openwrt/package/webif/src/webif-page.c b/openwrt/package/webif/src/webif-page.c
index 9d0222f6fa..13e70937ec 100644
--- a/openwrt/package/webif/src/webif-page.c
+++ b/openwrt/package/webif/src/webif-page.c
@@ -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++]);
 	}
-- 
2.30.2