summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2006-02-12 06:00:38 +0000
committernbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73>2006-02-12 06:00:38 +0000
commitc11b0e50212bdd5a360cae8835ab42cd153a35d6 (patch)
tree59ba95c12665a7ab7ee8c9ff80efc22102da14ca
parent64544ce5225d04bcb62b6a10fe465ce560cb74a5 (diff)
add support for netgear dg834 and the almost identical sphairon jdr454wb: new images, automatic boot loader patcher, updated flash script (dlink.pl renamed to adam2flash.pl) - Thanks to Jonathan McDowell (Noodles)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@3221 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rwxr-xr-xopenwrt/scripts/adam2flash.pl (renamed from openwrt/scripts/dlink.pl)13
-rw-r--r--openwrt/target/linux/image/ar7/Makefile13
-rw-r--r--openwrt/target/linux/image/ar7/sercomm/adam2.binbin0 -> 131072 bytes
-rw-r--r--openwrt/target/linux/image/ar7/sercomm/dg834bin0 -> 80 bytes
-rw-r--r--openwrt/target/linux/image/ar7/sercomm/jdr454wbbin0 -> 80 bytes
-rw-r--r--openwrt/target/linux/package/base-files/Makefile15
-rwxr-xr-xopenwrt/target/linux/package/base-files/files/ar7-2.4/etc/init.d/S00adam28
-rw-r--r--openwrt/target/linux/package/base-files/src/adam2patcher.c59
-rw-r--r--openwrt/target/linux/package/base-files/src/jffs2root.c (renamed from openwrt/target/linux/package/base-files/jffs2root.c)0
-rw-r--r--openwrt/target/utils/Makefile2
-rw-r--r--openwrt/target/utils/src/dgfirmware.c376
11 files changed, 481 insertions, 5 deletions
diff --git a/openwrt/scripts/dlink.pl b/openwrt/scripts/adam2flash.pl
index ace6476e92..bd0fa69a61 100755
--- a/openwrt/scripts/dlink.pl
+++ b/openwrt/scripts/adam2flash.pl
@@ -39,20 +39,27 @@ my $probe = IO::Socket::INET->new(Proto => 'udp',
my $setip = unpack("N", inet_aton($ip));
$setip > 0 or usage();
+my @packets;
+foreach my $ver ([18, 1], [22, 2]) {
+ push @packets, pack("vCCVNV", 0, @$ver, 1, $setip, 0);
+}
print STDERR "Looking for device: ";
-my $packet = pack("vCCVNV", 0, 22, 2, 1, $setip, 0);
my $broadcast = sockaddr_in(5035, INADDR_BROADCAST);
my $scanning;
my $box;
$SIG{"ALRM"} = sub {
return if --$scanning <= 0;
- $probe->send($packet, 0, $broadcast);
+ foreach my $packet (@packets) {
+ $probe->send($packet, 0, $broadcast);
+ }
print STDERR ".";
};
$scanning = 10;
-$probe->send($packet, 0, $broadcast);
+foreach my $packet (@packets) {
+ $probe->send($packet, 0, $broadcast);
+}
print STDERR ".";
while($scanning) {
diff --git a/openwrt/target/linux/image/ar7/Makefile b/openwrt/target/linux/image/ar7/Makefile
index 38fce6bdfc..3a803cbd8b 100644
--- a/openwrt/target/linux/image/ar7/Makefile
+++ b/openwrt/target/linux/image/ar7/Makefile
@@ -83,6 +83,19 @@ $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FS)-$(1).bin: $(BIN_DIR)/openwrt-$(BOARD
install: $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FS)-$(1).bin
endef
+define sercomm_template
+$(BIN_DIR)/openwrt-$(1)-$(KERNEL)-$(FS).bin: $(BIN_DIR)/openwrt-$(BOARD)-$(KERNEL)-$(FS).bin
+ cat sercomm/adam2.bin "$$^" > "$$@.tmp"
+ dd if=sercomm/$(1) of="$$@.tmp" bs=$$$$((0x3e0000 - 80)) seek=1 conv=notrunc
+ $(STAGING_DIR)/bin/dgfirmware -f -w "$$@" "$$@.tmp"
+ rm -f "$$@.tmp"
+
+install: $(BIN_DIR)/openwrt-$(1)-$(KERNEL)-$(FS).bin
+endef
+
+$(eval $(call sercomm_template,dg834))
+$(eval $(call sercomm_template,jdr454wb))
+
$(eval $(call pattern_template,AG1B))
$(eval $(call pattern_template,WA22))
$(eval $(call pattern_template,WAG2))
diff --git a/openwrt/target/linux/image/ar7/sercomm/adam2.bin b/openwrt/target/linux/image/ar7/sercomm/adam2.bin
new file mode 100644
index 0000000000..d4aa0cd2d3
--- /dev/null
+++ b/openwrt/target/linux/image/ar7/sercomm/adam2.bin
Binary files differ
diff --git a/openwrt/target/linux/image/ar7/sercomm/dg834 b/openwrt/target/linux/image/ar7/sercomm/dg834
new file mode 100644
index 0000000000..61fe336e85
--- /dev/null
+++ b/openwrt/target/linux/image/ar7/sercomm/dg834
Binary files differ
diff --git a/openwrt/target/linux/image/ar7/sercomm/jdr454wb b/openwrt/target/linux/image/ar7/sercomm/jdr454wb
new file mode 100644
index 0000000000..821ff1c1af
--- /dev/null
+++ b/openwrt/target/linux/image/ar7/sercomm/jdr454wb
Binary files differ
diff --git a/openwrt/target/linux/package/base-files/Makefile b/openwrt/target/linux/package/base-files/Makefile
index 637904c2e8..cf72eabdac 100644
--- a/openwrt/target/linux/package/base-files/Makefile
+++ b/openwrt/target/linux/package/base-files/Makefile
@@ -15,8 +15,21 @@ $(PKG_BUILD_DIR)/.prepared:
mkdir -p $(PKG_BUILD_DIR)
touch $@
+ifeq ($(BOARD),ar7)
+$(PKG_BUILD_DIR)/adam2patcher: src/adam2patcher.c
+ $(TARGET_CC) -o $@ $<
+
+$(PKG_BUILD_DIR)/.built: $(PKG_BUILD_DIR)/adam2patcher
+
+$(IDIR_OPENWRT)/sbin/adam2patcher: $(PKG_BUILD_DIR)/adam2patcher
+ mkdir -p $(IDIR_OPENWRT)/sbin
+ $(CP) $(PKG_BUILD_DIR)/adam2patcher $(IDIR_OPENWRT)/sbin
+
+$(IPKG_OPENWRT): $(IDIR_OPENWRT)/sbin/adam2patcher
+endif
+
ifeq ($(BOARD),brcm)
-$(PKG_BUILD_DIR)/jffs2root: jffs2root.c
+$(PKG_BUILD_DIR)/jffs2root: src/jffs2root.c
$(TARGET_CC) -o $@ $<
$(PKG_BUILD_DIR)/.built: $(PKG_BUILD_DIR)/jffs2root
diff --git a/openwrt/target/linux/package/base-files/files/ar7-2.4/etc/init.d/S00adam2 b/openwrt/target/linux/package/base-files/files/ar7-2.4/etc/init.d/S00adam2
new file mode 100755
index 0000000000..0ca4c01453
--- /dev/null
+++ b/openwrt/target/linux/package/base-files/files/ar7-2.4/etc/init.d/S00adam2
@@ -0,0 +1,8 @@
+#!/bin/sh
+# ADAM2 patcher for Netgear DG834 and compatible
+MD5="$(md5sum /dev/mtdblock/0 | awk '{print $1}')"
+[ "$MD5" = "0530bfdf00ec155f4182afd70da028c1" ] && {
+ mtd unlock adam2
+ /sbin/adam2patcher /dev/mtdblock/0
+}
+rm -f /etc/init.d/S00adam2 /sbin/adam2patcher >&- 2>&-
diff --git a/openwrt/target/linux/package/base-files/src/adam2patcher.c b/openwrt/target/linux/package/base-files/src/adam2patcher.c
new file mode 100644
index 0000000000..25a78074a6
--- /dev/null
+++ b/openwrt/target/linux/package/base-files/src/adam2patcher.c
@@ -0,0 +1,59 @@
+/*
+ * patcher.c - ADAM2 patcher for Netgear DG834 (and compatible)
+ *
+ * Copyright (C) 2006 Felix Fietkau
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#include <sys/ioctl.h>
+
+int main(int argc, char **argv)
+{
+ int fd;
+ char *ptr;
+ uint32_t *i;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
+ exit(1);
+ }
+
+ if (((fd = open(argv[1], O_RDWR)) < 0)
+ || ((ptr = mmap(0, 128 * 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == (void *) (-1))) {
+ fprintf(stderr, "Can't open file\n");
+ exit(1);
+ }
+
+ i = (uint32_t *) &ptr[0x3944];
+ if (*i == 0x0c000944) {
+ fprintf(stderr, "Unpatched ADAM2 detected. Patching... ");
+ *i = 0x00000000;
+ msync(i, sizeof(*i), MS_SYNC|MS_INVALIDATE);
+ fprintf(stderr, "done!\n");
+ } else if (*i == 0x00000000) {
+ fprintf(stderr, "Patched ADAM2 detected.\n");
+ } else {
+ fprintf(stderr, "Unknown ADAM2 detected. Can't patch!\n");
+ }
+
+ close(fd);
+}
diff --git a/openwrt/target/linux/package/base-files/jffs2root.c b/openwrt/target/linux/package/base-files/src/jffs2root.c
index 14662fc945..14662fc945 100644
--- a/openwrt/target/linux/package/base-files/jffs2root.c
+++ b/openwrt/target/linux/package/base-files/src/jffs2root.c
diff --git a/openwrt/target/utils/Makefile b/openwrt/target/utils/Makefile
index 753db53deb..5b0f2470b4 100644
--- a/openwrt/target/utils/Makefile
+++ b/openwrt/target/utils/Makefile
@@ -1,6 +1,6 @@
include $(TOPDIR)/rules.mk
-TARGETS := addpattern trx motorola-bin
+TARGETS := addpattern trx motorola-bin dgfirmware
UTILS_BUILD_DIR:=$(BUILD_DIR)/target-utils
diff --git a/openwrt/target/utils/src/dgfirmware.c b/openwrt/target/utils/src/dgfirmware.c
new file mode 100644
index 0000000000..5ff3b69646
--- /dev/null
+++ b/openwrt/target/utils/src/dgfirmware.c
@@ -0,0 +1,376 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+
+#define IMG_SIZE 0x3e0000
+
+#define KERNEL_START 0x020000
+#define KERNEL_SIZE 0x0b0000
+
+#define ROOTFS_START 0x0d0000
+#define ROOTFS_SIZE 0x30ffb2
+
+char* app_name;
+
+
+
+
+void print_usage(void)
+{
+ fprintf(stderr, "usage: dgfirmware [<opts>] <img>\n");
+ fprintf(stderr, " <img> firmware image filename\n");
+ fprintf(stderr, " <opts> -h print this message\n");
+ fprintf(stderr, " -f fix the checksum\n");
+ fprintf(stderr, " -x <file> extract the rootfs file to <file>\n");
+ fprintf(stderr, " -xk <file> extract the kernel to <file>\n");
+ fprintf(stderr, " -m <file> merge in rootfs fil\e from <file>\n");
+ fprintf(stderr, " -k <file> merge in kernel from <file>\n");
+ fprintf(stderr, " -w <file> write back the modified firmware\n");
+}
+
+
+unsigned char* read_img(const char *fname)
+{
+ FILE *fp;
+ int size;
+ unsigned char *img;
+
+ fp = fopen(fname, "rb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+
+ if (size != IMG_SIZE) {
+ fprintf(stderr, "%s: image file has wrong size\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ rewind(fp);
+
+ img = malloc(IMG_SIZE);
+ if (img == NULL) {
+ perror(app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ if (fread(img, 1, IMG_SIZE, fp) != IMG_SIZE) {
+ fprintf(stderr, "%s: can't read image file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ fclose(fp);
+ return img;
+}
+
+
+void write_img(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+
+ fp = fopen(fname, "wb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ if (fwrite(img, 1, IMG_SIZE, fp) != IMG_SIZE) {
+ fprintf(stderr, "%s: can't write image file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+}
+
+
+void write_rootfs(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+
+ fp = fopen(fname, "wb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ if (fwrite(img+ROOTFS_START, 1, ROOTFS_SIZE, fp) != ROOTFS_SIZE) {
+ fprintf(stderr, "%s: can't write image file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+}
+
+
+void write_kernel(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+
+ fp = fopen(fname, "wb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ if (fwrite(img+KERNEL_START, 1, KERNEL_SIZE, fp) != KERNEL_SIZE) {
+ fprintf(stderr, "%s: can't write kernel file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+}
+
+
+unsigned char* read_rootfs(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+ int size;
+ int i;
+
+ for (i=ROOTFS_START; i<ROOTFS_START+ROOTFS_SIZE; i++)
+ img[i] = 0xff;
+
+ fp = fopen(fname, "rb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+
+ if (size > ROOTFS_SIZE) {
+ fprintf(stderr, "%s: rootfs image file is too big\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ rewind(fp);
+
+ if (fread(img+ROOTFS_START, 1, size, fp) != size) {
+ fprintf(stderr, "%s: can't read rootfs image file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ fclose(fp);
+ return img;
+}
+
+
+unsigned char* read_kernel(unsigned char* img, const char *fname)
+{
+ FILE *fp;
+ int size;
+ int i;
+
+ for (i=KERNEL_START; i<KERNEL_START+KERNEL_SIZE; i++)
+ img[i] = 0xff;
+
+ fp = fopen(fname, "rb");
+ if (fp == NULL) {
+ perror(app_name);
+ exit(-1);
+ }
+
+ fseek(fp, 0, SEEK_END);
+ size = ftell(fp);
+
+ if (size > KERNEL_SIZE) {
+ fprintf(stderr, "%s: kernel binary file is too big\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ rewind(fp);
+
+ if (fread(img+KERNEL_START, 1, size, fp) != size) {
+ fprintf(stderr, "%s: can't read kernel file\n", app_name);
+ fclose(fp);
+ exit(-1);
+ }
+
+ fclose(fp);
+ return img;
+}
+
+
+int get_checksum(unsigned char* img)
+{
+ short unsigned s;
+
+ s = img[0x3dfffc] + (img[0x3dfffd]<<8);
+
+ return s;
+}
+
+
+void set_checksum(unsigned char*img, unsigned short sum)
+{
+ img[0x3dfffc] = sum & 0xff;
+ img[0x3dfffd] = (sum>>8) & 0xff;
+}
+
+
+int compute_checksum(unsigned char* img)
+{
+ int i;
+ short s=0;
+
+ for (i=0; i<0x3dfffc; i++)
+ s += img[i];
+
+ return s;
+}
+
+
+int main(int argc, char* argv[])
+{
+ char *img_fname = NULL;
+ char *rootfs_fname = NULL;
+ char *kernel_fname = NULL;
+ char *new_img_fname = NULL;
+
+ int do_fix_checksum = 0;
+ int do_write = 0;
+ int do_write_rootfs = 0;
+ int do_read_rootfs = 0;
+ int do_write_kernel = 0;
+ int do_read_kernel = 0;
+
+ int i;
+ unsigned char *img;
+ unsigned short img_checksum;
+ unsigned short real_checksum;
+
+ app_name = argv[0];
+
+ for (i=1; i<argc; i++) {
+ if (!strcmp(argv[i], "-h")) {
+ print_usage();
+ return 0;
+ }
+ else if (!strcmp(argv[i], "-f")) {
+ do_fix_checksum = 1;
+ }
+ else if (!strcmp(argv[i], "-x")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_write_rootfs = 1;
+ rootfs_fname = argv[i+1];
+ i++;
+ }
+ else if (!strcmp(argv[i], "-xk")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_write_kernel = 1;
+ kernel_fname = argv[i+1];
+ i++;
+ }
+ else if (!strcmp(argv[i], "-m")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_read_rootfs = 1;
+ rootfs_fname = argv[i+1];
+ i++;
+ }
+ else if (!strcmp(argv[i], "-k")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_read_kernel = 1;
+ kernel_fname = argv[i+1];
+ i++;
+ }
+ else if (!strcmp(argv[i], "-w")) {
+ if (i+1 >= argc) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+ do_write = 1;
+ new_img_fname = argv[i+1];
+ i++;
+ }
+ else if (img_fname != 0) {
+ fprintf(stderr, "%s: too many arguments\n", app_name);
+ return -1;
+ }
+ else {
+ img_fname = argv[i];
+ }
+ }
+
+ if (img_fname == NULL) {
+ fprintf(stderr, "%s: missing argument\n", app_name);
+ return -1;
+ }
+
+ if ((do_read_rootfs && do_write_rootfs) ||
+ (do_read_kernel && do_write_kernel)) {
+ fprintf(stderr, "%s: conflictuous options\n", app_name);
+ return -1;
+ }
+
+ printf ("** Read firmware file\n");
+ img = read_img(img_fname);
+
+ printf ("Firmware product: %s\n", img+0x3dffbd);
+ printf ("Firmware version: 1.%02d.%02d\n", (img[0x3dffeb] & 0x7f), img[0x3dffec]);
+
+ if (do_write_rootfs) {
+ printf ("** Write rootfs file\n");
+ write_rootfs(img, rootfs_fname);
+ }
+
+ if (do_write_kernel) {
+ printf ("** Write kernel file\n");
+ write_kernel(img, kernel_fname);
+ }
+
+ if (do_read_rootfs) {
+ printf ("** Read rootfs file\n");
+ read_rootfs(img, rootfs_fname);
+ do_fix_checksum = 1;
+ }
+
+ if (do_read_kernel) {
+ printf ("** Read kernel file\n");
+ read_kernel(img, kernel_fname);
+ do_fix_checksum = 1;
+ }
+
+ img_checksum = get_checksum(img);
+ real_checksum = compute_checksum(img);
+
+ printf ("image checksum = %04x\n", img_checksum);
+ printf ("real checksum = %04x\n", real_checksum);
+
+ if (do_fix_checksum) {
+ if (img_checksum != real_checksum) {
+ printf ("** Bad Checksum, fix it\n");
+ set_checksum(img, real_checksum);
+ }
+ else {
+ printf ("** Checksum is correct, good\n");
+ }
+ }
+
+ if (do_write) {
+ printf ("** Write image file\n");
+ write_img(img, new_img_fname);
+ }
+
+ free(img);
+ return 0;
+}
+