aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Crispin <john@openwrt.org>2014-06-16 18:57:20 +0000
committerJohn Crispin <john@openwrt.org>2014-06-16 18:57:20 +0000
commitdc5fe5f73f7cef3282fb6f529f4d91b8cf764706 (patch)
treef30fd1791e6056989790ae89ac2a4df4e4fdd574
parent28277caccb1590f63e392dc90ffe7a2a83658878 (diff)
downloadupstream-dc5fe5f73f7cef3282fb6f529f4d91b8cf764706.tar.gz
upstream-dc5fe5f73f7cef3282fb6f529f4d91b8cf764706.tar.bz2
upstream-dc5fe5f73f7cef3282fb6f529f4d91b8cf764706.zip
ramips: RT-N56U support fixes and factory image creation
Signed-off-by: Mikko Hissa <mikko.hissa@werzek.com> SVN-Revision: 41224
-rw-r--r--target/linux/ramips/base-files/lib/preinit/04_handle_checksumming (renamed from target/linux/ramips/base-files/lib/preinit/04_disable_wnce2001_flash_checksumming)17
-rw-r--r--target/linux/ramips/dts/RTN56U.dts8
-rw-r--r--target/linux/ramips/image/Makefile8
-rw-r--r--target/linux/ramips/patches-3.10/0135-mtd-add-rtn56u-support.patch28
-rw-r--r--tools/firmware-utils/Makefile1
-rw-r--r--tools/firmware-utils/src/mkrtn56uimg.c294
6 files changed, 353 insertions, 3 deletions
diff --git a/target/linux/ramips/base-files/lib/preinit/04_disable_wnce2001_flash_checksumming b/target/linux/ramips/base-files/lib/preinit/04_handle_checksumming
index 67a1746f1d..fd06d20c99 100644
--- a/target/linux/ramips/base-files/lib/preinit/04_disable_wnce2001_flash_checksumming
+++ b/target/linux/ramips/base-files/lib/preinit/04_handle_checksumming
@@ -5,7 +5,7 @@
# this, so we make sure to zero checksum and size to be checksummed before
# that happens, so this needs to run very early during boot.
-do_wnce2001_checksumming_disable() {
+do_checksumming_disable() {
. /lib/ramips.sh
local board=$(ramips_board_name)
@@ -35,9 +35,22 @@ do_wnce2001_checksumming_disable() {
echo "Checksum is already zero, nothing to do."
fi
;;
+ rt-n56u)
+ echo "Board is ASUS RT-N56U, replacing uImage header..."
+ local firmware_mtd=$(find_mtd_part firmware)
+ local rootfs_mtd=$(find_mtd_part rootfs)
+ local rootfs_data_mtd=$(find_mtd_part rootfs_data)
+ local rootfs_len=$(grep \"rootfs\" /proc/mtd | awk -F' ' '{print "0x"$2}')
+ local rootfs_data_len=$(grep \"rootfs_data\" /proc/mtd | awk -F' ' '{print "0x"$2}')
+ local offset=$(echo "$rootfs_len $rootfs_data_len 0x40" | awk -F' ' '{printf "%i",$1-$2-$3}')
+ local signature=$(dd if=$rootfs_mtd skip=$offset bs=1 count=4 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"')
+ if [ "$signature" == "27051956" ]; then
+ dd conv=notrunc if=$rootfs_mtd skip=$offset of=$firmware_mtd bs=1 count=64 2>/dev/null
+ fi
+ ;;
esac
return 0
}
-boot_hook_add preinit_main do_wnce2001_checksumming_disable
+boot_hook_add preinit_main do_checksumming_disable
diff --git a/target/linux/ramips/dts/RTN56U.dts b/target/linux/ramips/dts/RTN56U.dts
index b962aa0d23..305e36e85b 100644
--- a/target/linux/ramips/dts/RTN56U.dts
+++ b/target/linux/ramips/dts/RTN56U.dts
@@ -43,12 +43,20 @@
host-bridge {
pci-bridge@1 {
status = "okay";
+ wmac@0,0 {
+ compatible = "ralink,rt2880-pci", "pciclass060400", "pciclass0604";
+ reg = < 0x10000 0 0 0 0 >;
+ ralink,eeprom = "rt2x00pci_1_0.eeprom";
+ };
+
};
};
};
wmac@10180000 {
+ status = "okay";
ralink,2ghz = <0>;
+ ralink,eeprom = "soc_wmac.eeprom";
};
ehci@101c0000 {
diff --git a/target/linux/ramips/image/Makefile b/target/linux/ramips/image/Makefile
index 58a54773c2..1b342deb7a 100644
--- a/target/linux/ramips/image/Makefile
+++ b/target/linux/ramips/image/Makefile
@@ -665,7 +665,13 @@ Image/Build/Profile/DIR645=$(call BuildFirmware/Seama/$(1),$(1),dir-645,DIR-645,
omniembhpm_mtd_size=16449536
Image/Build/Profile/OMNIEMBHPM=$(call BuildFirmware/CustomFlash/$(1),$(1),omni-emb-hpm,OMNI-EMB-HPM,$(omniembhpm_mtd_size))
-Image/Build/Profile/RTN56U=$(call BuildFirmware/Default8M/$(1),$(1),rt-n56u,RTN56U)
+define BuildFirmware/RTN56U/squashfs
+ $(call BuildFirmware/Default8M/$(1),$(1),rt-n56u,RTN56U)
+ -mkrtn56uimg -s $(call sysupname,$(1),rt-n56u)
+ -cp $(call sysupname,$(1),rt-n56u) $(call imgname,$(1),rt-n56u)-factory.bin
+ -mkrtn56uimg -f $(call imgname,$(1),rt-n56u)-factory.bin
+endef
+Image/Build/Profile/RTN56U=$(call BuildFirmware/RTN56U/$(1),$(1),rt-n56u,RTN56U)
Image/Build/Profile/TEW691GR=$(call BuildFirmware/UMedia/$(1),$(1),tew-691gr,TEW-691GR,0x026910)
diff --git a/target/linux/ramips/patches-3.10/0135-mtd-add-rtn56u-support.patch b/target/linux/ramips/patches-3.10/0135-mtd-add-rtn56u-support.patch
new file mode 100644
index 0000000000..52379916b9
--- /dev/null
+++ b/target/linux/ramips/patches-3.10/0135-mtd-add-rtn56u-support.patch
@@ -0,0 +1,28 @@
+--- a/drivers/mtd/mtdpart.c 2014-04-27 10:09:21.566294160 +0300
++++ b/drivers/mtd/mtdpart.c 2014-06-09 11:27:48.952211672 +0300
+@@ -793,8 +793,11 @@
+ {
+ struct {
+ __be32 magic;
+- __be32 pad[2];
++ __be32 pad0[2];
+ __be32 size;
++ __be32 pad1[4];
++ __be32 name[7];
++ __be32 kern_size;
+ } hdr;
+ size_t len;
+
+@@ -804,7 +807,11 @@
+ if (len != sizeof(hdr) || hdr.magic != cpu_to_be32(UBOOT_MAGIC))
+ return;
+
+- len = be32_to_cpu(hdr.size) + 0x40;
++ if (hdr.kern_size != 0 && hdr.name[0] == 0)
++ len = be32_to_cpu(hdr.kern_size);
++ else
++ len = be32_to_cpu(hdr.size) + 0x40;
++
+ __mtd_add_partition(master, "rootfs", part->offset + len,
+ part->mtd.size - len, false);
+ }
diff --git a/tools/firmware-utils/Makefile b/tools/firmware-utils/Makefile
index 3be80e77ab..8f17c3e923 100644
--- a/tools/firmware-utils/Makefile
+++ b/tools/firmware-utils/Makefile
@@ -67,6 +67,7 @@ define Host/Compile
#$(call cc,mkhilinkfw, -lcrypto)
$(call cc,mkdcs932, -Wall)
$(call cc,mkheader_gemtek,-lz)
+ $(call cc,mkrtn56uimg, -lz)
endef
define Host/Install
diff --git a/tools/firmware-utils/src/mkrtn56uimg.c b/tools/firmware-utils/src/mkrtn56uimg.c
new file mode 100644
index 0000000000..973ab28d06
--- /dev/null
+++ b/tools/firmware-utils/src/mkrtn56uimg.c
@@ -0,0 +1,294 @@
+/*
+ *
+ * Copyright (C) 2014 OpenWrt.org
+ * Copyright (C) 2014 Mikko Hissa <mikko.hissa@werzek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#define IH_MAGIC 0x27051956
+#define IH_NMLEN 32
+#define IH_PRODLEN 23
+
+#define IH_TYPE_INVALID 0
+#define IH_TYPE_STANDALONE 1
+#define IH_TYPE_KERNEL 2
+#define IH_TYPE_RAMDISK 3
+#define IH_TYPE_MULTI 4
+#define IH_TYPE_FIRMWARE 5
+#define IH_TYPE_SCRIPT 6
+#define IH_TYPE_FILESYSTEM 7
+
+/*
+ * Compression Types
+ */
+#define IH_COMP_NONE 0
+#define IH_COMP_GZIP 1
+#define IH_COMP_BZIP2 2
+#define IH_COMP_LZMA 3
+
+typedef struct {
+ uint8_t major;
+ uint8_t minor;
+} version_t;
+
+typedef struct {
+ version_t kernel;
+ version_t fs;
+ uint8_t productid[IH_PRODLEN];
+ uint8_t sub_fs;
+ uint32_t ih_ksz;
+} asus_t;
+
+typedef struct image_header {
+ uint32_t ih_magic;
+ uint32_t ih_hcrc;
+ uint32_t ih_time;
+ uint32_t ih_size;
+ uint32_t ih_load;
+ uint32_t ih_ep;
+ uint32_t ih_dcrc;
+ uint8_t ih_os;
+ uint8_t ih_arch;
+ uint8_t ih_type;
+ uint8_t ih_comp;
+ union {
+ uint8_t ih_name[IH_NMLEN];
+ asus_t asus;
+ } tail;
+} image_header_t;
+
+typedef struct squashfs_sb {
+ uint32_t s_magic;
+ uint32_t pad0[9];
+ uint64_t bytes_used;
+} squashfs_sb_t;
+
+typedef enum {
+ NONE, FACTORY, SYSUPGRADE,
+} op_mode_t;
+
+void
+calc_crc(image_header_t *hdr, void *data, uint32_t len)
+{
+ /*
+ * Calculate payload checksum
+ */
+ hdr->ih_dcrc = htonl(crc32(0, data, len));
+ hdr->ih_size = htonl(len);
+ /*
+ * Calculate header checksum
+ */
+ hdr->ih_hcrc = 0;
+ hdr->ih_hcrc = htonl(crc32(0, hdr, sizeof(image_header_t)));
+}
+
+
+static void
+usage(const char *progname, int status)
+{
+ FILE *stream = (status != EXIT_SUCCESS) ? stderr : stdout;
+ int i;
+
+ fprintf(stream, "Usage: %s [OPTIONS...]\n", progname);
+ fprintf(stream, "\n"
+ "Options:\n"
+ " -f <file> generate a factory flash image <file>\n"
+ " -s <file> generate a sysupgrade flash image <file>\n"
+ " -h show this screen\n");
+ exit(status);
+}
+
+int
+process_image(char *progname, char *filename, op_mode_t opmode)
+{
+ int fd, len;
+ void *data, *ptr;
+ char namebuf[IH_NMLEN];
+ struct stat sbuf;
+ uint32_t checksum, offset_kernel, offset_sqfs, offset_end,
+ offset_sec_header, offset_eb, offset_image_end;
+ squashfs_sb_t *sqs;
+ image_header_t *hdr;
+
+ if ((fd = open(filename, O_RDWR, 0666)) < 0) {
+ fprintf (stderr, "%s: Can't open %s: %s\n",
+ progname, filename, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+
+ if (fstat(fd, &sbuf) < 0) {
+ fprintf (stderr, "%s: Can't stat %s: %s\n",
+ progname, filename, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+
+ if ((unsigned)sbuf.st_size < sizeof(image_header_t)) {
+ fprintf (stderr,
+ "%s: Bad size: \"%s\" is no valid image\n",
+ progname, filename);
+ return (EXIT_FAILURE);
+ }
+
+ ptr = (void *)mmap(0, sbuf.st_size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ fd, 0);
+
+ if ((caddr_t)ptr == (caddr_t)-1) {
+ fprintf (stderr, "%s: Can't read %s: %s\n",
+ progname, filename, strerror(errno));
+ return (EXIT_FAILURE);
+ }
+
+ hdr = ptr;
+
+ if (ntohl(hdr->ih_magic) != IH_MAGIC) {
+ fprintf (stderr,
+ "%s: Bad Magic Number: \"%s\" is no valid image\n",
+ progname, filename);
+ return (EXIT_FAILURE);
+ }
+
+ if (opmode == FACTORY) {
+ strncpy(&namebuf, (char *)&hdr->tail.ih_name, IH_NMLEN);
+ hdr->tail.asus.kernel.major = 0;
+ hdr->tail.asus.kernel.minor = 0;
+ hdr->tail.asus.fs.major = 0;
+ hdr->tail.asus.fs.minor = 0;
+ strncpy((char *)&hdr->tail.asus.productid, "RT-N56U", IH_PRODLEN);
+ }
+
+ if (hdr->tail.asus.ih_ksz == 0)
+ hdr->tail.asus.ih_ksz = htonl(ntohl(hdr->ih_size) + sizeof(image_header_t));
+
+ offset_kernel = sizeof(image_header_t);
+ offset_sqfs = ntohl(hdr->tail.asus.ih_ksz);
+ sqs = ptr + offset_sqfs;
+ offset_sec_header = offset_sqfs + sqs->bytes_used;
+
+ /*
+ * Reserve space for the second header.
+ */
+ offset_end = offset_sec_header + sizeof(image_header_t);
+ offset_eb = ((offset_end>>16)+1)<<16;
+
+ if (opmode == FACTORY)
+ offset_image_end = offset_eb + 4;
+ else
+ offset_image_end = sbuf.st_size;
+ /*
+ * Move the second header at the end of the image.
+ */
+ offset_end = offset_sec_header;
+ offset_sec_header = offset_eb - sizeof(image_header_t);
+
+ /*
+ * Remove jffs2 markers between squashfs and eb boundary.
+ */
+ if (opmode == FACTORY)
+ memset(ptr+offset_end, 0xff ,offset_eb - offset_end);
+
+ /*
+ * Grow the image if needed.
+ */
+ if (offset_image_end > sbuf.st_size) {
+ (void) munmap((void *)ptr, sbuf.st_size);
+ ftruncate(fd, offset_image_end);
+ ptr = (void *)mmap(0, offset_image_end,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ fd, 0);
+ /*
+ * jffs2 marker
+ */
+ if (opmode == FACTORY) {
+ *(uint8_t *)(ptr+offset_image_end-4) = 0xde;
+ *(uint8_t *)(ptr+offset_image_end-3) = 0xad;
+ *(uint8_t *)(ptr+offset_image_end-2) = 0xc0;
+ *(uint8_t *)(ptr+offset_image_end-1) = 0xde;
+ }
+ }
+
+ /*
+ * Calculate checksums for the second header to be used after flashing.
+ */
+ if (opmode == FACTORY) {
+ hdr = ptr+offset_sec_header;
+ memcpy(hdr, ptr, sizeof(image_header_t));
+ strncpy((char *)&hdr->tail.ih_name, &namebuf, IH_NMLEN);
+ calc_crc(hdr, ptr+offset_kernel, offset_sqfs - offset_kernel);
+ calc_crc((image_header_t *)ptr, ptr+offset_kernel, offset_image_end - offset_kernel);
+ } else {
+ calc_crc((image_header_t *)ptr, ptr+offset_kernel, offset_sqfs - offset_kernel);
+ }
+
+ if (sbuf.st_size > offset_image_end)
+ (void) munmap((void *)ptr, sbuf.st_size);
+ else
+ (void) munmap((void *)ptr, offset_image_end);
+
+ ftruncate(fd, offset_image_end);
+ (void) close (fd);
+
+ return EXIT_SUCCESS;
+}
+
+int
+main(int argc, char **argv)
+{
+ int opt;
+ char *filename, *progname;
+ op_mode_t opmode = NONE;
+
+ progname = argv[0];
+
+ while ((opt = getopt(argc, argv,":s:f:h?")) != -1) {
+ switch (opt) {
+ case 's':
+ opmode = SYSUPGRADE;
+ filename = optarg;
+ break;
+ case 'f':
+ opmode = FACTORY;
+ filename = optarg;
+ break;
+ case 'h':
+ opmode = NONE;
+ default:
+ usage(progname, EXIT_FAILURE);
+ opmode = NONE;
+ }
+ }
+
+ if(filename == NULL)
+ opmode = NONE;
+
+ switch (opmode) {
+ case NONE:
+ usage(progname, EXIT_FAILURE);
+ break;
+ case FACTORY:
+ case SYSUPGRADE:
+ return process_image(progname, filename, opmode);
+ break;
+ }
+
+ return EXIT_SUCCESS;
+}
+