[OpenWrt-Devel] [PATCH 2/2] ramips: add support for Ubiquiti EdgeRouter X (UBNT-ERX)

Nikolay Martynov mar.kolya at gmail.com
Sat Dec 12 01:45:27 EST 2015


This router is based on MT7621 SoC, no wifi, no usb, nand.

Works:
* Boots.
* Ethernet.
* Switch.
* Button (reset).
* Flashing OpenWrt from stock firmware.
* Upgrading OpenWrt.

Doesn't work:
* No GPIO leds. All leds are controlled by switch,
  but stock firmware was able to control them.
* SoC has crypto engine but no open driver.
* SoC has nat acceleration, but no open driver.
* This router has 2MB spi flash soldered in but MT
  nand/spi drivers do not support pin sharing,
  so it is not accessable and disabled. Stock
  firmware could read it and it was empty.
* PoE out.

Router has serial pins populated. If looking at the top
of the router, then counting from Eth sockets pins go as:
'GND, RX, TX, GND'. 3.3v, 57600.

U-boot bootloader supports tftpboot, controlled from serial.
This router has two kernel partitions: 'live' and 'backup'.
They are swapped during flashing (on both stock and OpenWrt).
Active partition is controlled by a flag in a factory partition.
U-boot has custom command to switch active kernel partition.
Kernel partitions are 'bare flash' 3MB. Stock bootloader has
no UBI support. Stock rootfs is UBIFS.

Flashing procedure.
Stock firmware uses custom kernel patch to mount squashfs
from a file that is located on UBIFS volume. This makes wiping
out this volume from within stock firmware difficult.
Instead this patch builds image that is flashable by stock firmware
and contains initrams image (with minimal set of packages
to fit into kernel partition). Once this is flashed one can reboot
into initramfs OpenWrt and use sysupgrade to flash OpenWrt including
rootfs into nand.
Note: factory image is only built if initramfs image is enabled.

Signed-off-by: Nikolay Martynov <mar.kolya at gmail.com>
---
This patch has been updated from its original to include comments
from Yousong Zhou and Piotr Dymacz
---
 .../linux/ramips/base-files/etc/board.d/02_network |   1 +
 target/linux/ramips/base-files/lib/ramips.sh       |   5 +-
 .../ramips/base-files/lib/upgrade/platform.sh      |  24 +++++
 target/linux/ramips/base-files/lib/upgrade/ubnt.sh |  76 +++++++++++++
 target/linux/ramips/dts/UBNT-ERX.dts               | 119 +++++++++++++++++++++
 target/linux/ramips/image/Makefile                 |  61 ++++++++++-
 target/linux/ramips/mt7621/profiles/ubnt.mk        |  17 +++
 .../patches-4.3/0901-spansion_nand_id_fix.patch    |  43 ++++++++
 8 files changed, 344 insertions(+), 2 deletions(-)
 create mode 100644 target/linux/ramips/base-files/lib/upgrade/ubnt.sh
 create mode 100644 target/linux/ramips/dts/UBNT-ERX.dts
 create mode 100644 target/linux/ramips/mt7621/profiles/ubnt.mk
 create mode 100644 target/linux/ramips/patches-4.3/0901-spansion_nand_id_fix.patch

diff --git a/target/linux/ramips/base-files/etc/board.d/02_network b/target/linux/ramips/base-files/etc/board.d/02_network
index a55c9eb..719e968 100755
--- a/target/linux/ramips/base-files/etc/board.d/02_network
+++ b/target/linux/ramips/base-files/etc/board.d/02_network
@@ -114,6 +114,7 @@ ramips_setup_interfaces()
 	f5d8235-v2|\
 	hg255d|\
 	rt-n14u|\
+	ubnt-erx|\
 	ur-326n4g|\
 	wrtnode|\
 	wt3020|\
diff --git a/target/linux/ramips/base-files/lib/ramips.sh b/target/linux/ramips/base-files/lib/ramips.sh
index c002b97..62be045 100755
--- a/target/linux/ramips/base-files/lib/ramips.sh
+++ b/target/linux/ramips/base-files/lib/ramips.sh
@@ -349,6 +349,9 @@ ramips_board_detect() {
 	*"TEW-692GR")
 		name="tew-692gr"
 		;;
+	*"UBNT-ERX")
+		name="ubnt-erx"
+		;;
 	*"UR-326N4G")
 		name="ur-326n4g"
 		;;
@@ -399,7 +402,7 @@ ramips_board_detect() {
 		;;
 	*"WizFi630A")
 		name="wizfi630a"
-		;;                
+		;;
 	*"WL-330N")
 		name="wl-330n"
 		;;
diff --git a/target/linux/ramips/base-files/lib/upgrade/platform.sh b/target/linux/ramips/base-files/lib/upgrade/platform.sh
index 4ec3008..f8073d1 100755
--- a/target/linux/ramips/base-files/lib/upgrade/platform.sh
+++ b/target/linux/ramips/base-files/lib/upgrade/platform.sh
@@ -182,12 +182,36 @@ platform_check_image() {
 		}
 		return 0
 		;;
+	ubnt-erx)
+		nand_do_platform_check "$board" "$1"
+		return $?;
+		;;
 	esac
 
 	echo "Sysupgrade is not yet supported on $board."
 	return 1
 }
 
+platform_nand_pre_upgrade() {
+	local board=$(ramips_board_name)
+
+	case "$board" in
+	ubnt-erx)
+		platform_upgrade_ubnt_erx "$ARGV"
+		;;
+	esac
+}
+
+platform_pre_upgrade() {
+	local board=$(ramips_board_name)
+
+	case "$board" in
+    	ubnt-erx)
+		nand_do_upgrade "$ARGV"
+		;;
+	esac
+}
+
 platform_do_upgrade() {
 	local board=$(ramips_board_name)
 
diff --git a/target/linux/ramips/base-files/lib/upgrade/ubnt.sh b/target/linux/ramips/base-files/lib/upgrade/ubnt.sh
new file mode 100644
index 0000000..316a704
--- /dev/null
+++ b/target/linux/ramips/base-files/lib/upgrade/ubnt.sh
@@ -0,0 +1,76 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+
+. /lib/functions.sh
+#Note: this code also uses some functions from nand.sh, but it is expected to be run by nand.sh, so we are not
+#sourcing it explicitly here
+
+UBNT_ERX_KERNEL_INDEX_OFFSET=160
+
+ubnt_get_target_kernel() {
+	local factory_mtd=$1
+	local current_kernel_index=$(hexdump -s $UBNT_ERX_KERNEL_INDEX_OFFSET -n 1 -e '/1 "%X "' ${factory_mtd})
+
+	if [ $current_kernel_index == "0" ]; then
+		echo 'kernel2'
+	elif [ $current_kernel_index == "1" ]; then
+		echo 'kernel1'
+	fi
+}
+
+ubnt_update_target_kernel() {
+	local factory_mtd=$1
+	local kernel_part=$2
+
+	local new_kernel_index
+	if [ $kernel_part == "kernel1" ]; then
+		new_kernel_index="\x00"
+	elif [ $kernel_part == "kernel2" ]; then
+		new_kernel_index="\x01"
+	else
+		echo 'Unknown kernel image index' >&2
+		return 1
+	fi
+
+	if ! (echo -e $new_kernel_index | dd of=${factory_mtd} bs=1 count=1 seek=$UBNT_ERX_KERNEL_INDEX_OFFSET); then
+		echo 'Failed to update kernel bootup index' >&2
+		return 1
+	fi
+}
+
+platform_upgrade_ubnt_erx() {
+	local factory_mtd=$(find_mtd_part factory)
+	if [ -z "$factory_mtd" ]; then
+		echo "cannot find factory partition" >&2
+		exit 1
+	fi
+
+	local kernel_part="$(ubnt_get_target_kernel ${factory_mtd})"
+	if [ -z "$kernel_part" ]; then
+		echo "cannot find factory partition" >&2
+		exit 1
+	fi
+
+	# This is a global defined in nand.sh, sets partition kernel will be flashed into
+	CI_KERNPART=${kernel_part}
+
+	#Remove volume possibly left over from stock firmware
+	local ubidev="$( nand_find_ubi "$CI_UBIPART" )"
+	if [ -z "$ubidev" ]; then
+		local mtdnum="$( find_mtd_index "$CI_UBIPART" )"
+		if [ -z "$mtdnum" ]; then
+			echo "cannot find ubi mtd partition $CI_UBIPART" >&2
+			exit 1
+		fi
+		ubiattach -m "$mtdnum"
+		sync
+		ubidev="$( nand_find_ubi "$CI_UBIPART" )"
+	fi
+	if [ -n "$ubidev" ]; then
+		local troot_ubivol="$( nand_find_volume $ubidev troot )"
+		[ -n "$troot_ubivol" ] && ubirmvol /dev/$ubidev -N troot || true
+	fi
+
+	ubnt_update_target_kernel ${factory_mtd} ${kernel_part} || exit 1
+}
diff --git a/target/linux/ramips/dts/UBNT-ERX.dts b/target/linux/ramips/dts/UBNT-ERX.dts
new file mode 100644
index 0000000..0014ac7
--- /dev/null
+++ b/target/linux/ramips/dts/UBNT-ERX.dts
@@ -0,0 +1,119 @@
+#include <dt-bindings/input/input.h>
+
+/dts-v1/;
+
+#include "mt7621.dtsi"
+
+/ {
+	compatible = "mediatek,mt7621-eval-board", "mediatek,mt7621-soc";
+	model = "UBNT-ERX";
+
+	memory at 0 {
+		device_type = "memory";
+		reg = <0x0 0x10000000>;
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,57600";
+	};
+
+	palmbus at 1E000000 {
+		spi at b00 {
+			/* This board has 2Mb spi flash soldered in and visible
+			   from manufacturer's firmware.
+			   But this SoC shares spi and nand pins,
+			   and current driver does't handle this sharing well */
+			status = "disabled";
+			m25p80 at 0 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "m25p80";
+				reg = <1>;
+				linux,modalias = "m25p80";
+				spi-max-frequency = <10000000>;
+
+				partition at 0 {
+					label = "spi";
+					reg = <0x0 0x200000>;
+					read-only;
+				};
+			};
+		};
+	};
+
+	nand at 1e003000 {
+		compatible = "mtk,mt7621-nand";
+		bank-width = <2>;
+		reg = <0x1e003000 0x800
+		       0x1e003800 0x800>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partition at 0 {
+			label = "u-boot";
+			reg = <0x0 0x80000>;
+			read-only;
+		};
+
+		partition at 80000 {
+			label = "u-boot-env";
+			reg = <0x80000 0x60000>;
+			read-only;
+		};
+
+		factory: partition at e0000 {
+			label = "factory";
+			reg = <0xe0000 0x60000>;
+		};
+
+		partition at 140000 {
+			label = "kernel1";
+			reg = <0x140000 0x300000>;
+		};
+
+		partition at 440000 {
+			label = "kernel2";
+			reg = <0x440000 0x300000>;
+		};
+
+		partition at 740000 {
+			label = "ubi";
+			reg = <0x740000 0xf7c0000>;
+		};
+
+	};
+
+	ethernet at 1e100000 {
+		mtd-mac-address = <&factory 0x22>;
+	};
+
+	pinctrl {
+		state_default: pinctrl0 {
+			gpio {
+				ralink,group = "uart2", "uart3", "i2c", "pcie", "rgmii2", "jtag";
+				ralink,function = "gpio";
+			};
+		};
+	};
+
+	sdhci at 1E130000 {
+		status = "disabled";
+	};
+
+	pcie at 1e140000 {
+		status = "disabled";
+	};
+
+	gpio-keys-polled {
+		compatible = "gpio-keys-polled";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		poll-interval = <20>;
+
+		reset {
+			label = "reset";
+			gpios = <&gpio0 12 1>;
+			linux,code = <KEY_RESTART>;
+		};
+	};
+};
diff --git a/target/linux/ramips/image/Makefile b/target/linux/ramips/image/Makefile
index 63d6222..1b12249 100644
--- a/target/linux/ramips/image/Makefile
+++ b/target/linux/ramips/image/Makefile
@@ -69,6 +69,51 @@ define Build/relocate-kernel
 	mv $@.new $@
 endef
 
+define Build/ubnt-erx-factory-compat
+	echo '21001:6' > $@.compat
+	$(TAR) -cf $@ --transform='s/^.*/compat/' $@.compat
+	$(RM) $@.compat
+endef
+
+define Build/ubnt-erx-factory-kernel
+	if [ -e $(BIN_DIR)/$(KERNEL_INITRAMFS_IMAGE) ]; then \
+		$(TAR) -rf $@ --transform='s/^.*/vmlinux.tmp/' $(BIN_DIR)/$(KERNEL_INITRAMFS_IMAGE); \
+		\
+		md5sum --binary $(BIN_DIR)/$(KERNEL_INITRAMFS_IMAGE) | awk '{print $$1}'> $@.md5; \
+		$(TAR) -rf $@ --transform='s/^.*/vmlinux.tmp.md5/' $@.md5; \
+		$(RM) $@.md5; \
+	fi
+endef
+
+define Build/ubnt-erx-factory-rootfs
+	echo "dummy" > $@.rootfs
+	$(TAR) -rf $@ --transform='s/^.*/squashfs.tmp/' $@.rootfs
+
+	md5sum --binary $@.rootfs | awk '{print $$1}'> $@.md5
+	$(TAR) -rf $@ --transform='s/^.*/squashfs.tmp.md5/' $@.md5
+	$(RM) $@.md5
+	$(RM) $@.rootfs
+endef
+
+define Build/ubnt-erx-factory-version
+	echo '$(BOARD) $(VERSION_CODE) $(VERSION_NUMBER)' > $@.version
+	$(TAR) -rf $@ --transform='s/^.*/version.tmp/' $@.version
+	$(RM) $@.version
+endef
+
+#We need kernel+initrams fit into kernel partition
+define Build/ubnt-erx-factory-check-size
+	@[ $$(($(subst k,* 1024,$(subst m, * 1024k,$(1))))) -ge "$$($(TAR) -xf $@ vmlinux.tmp -O | wc -c)" ] || { \
+		echo "WARNING: Initramfs kernel for image $@ is too big (kernel size: $$($(TAR) -xf $@ vmlinux.tmp -O | wc -c), max size $(1))" >&2; \
+		$(RM) -f $@; \
+	}
+
+	@[ "$$($(TAR) -xf $@ vmlinux.tmp -O | wc -c)" -gt 0 ] || { \
+		echo "WARNING: Kernel for image $@ not found" >&2; \
+		$(RM) -f $@; \
+	}
+endef
+
 define MkCombineduImage
 	$(call PatchKernelLzma,$(2),$(3))
 	if [ `stat -c%s "$(KDIR)/vmlinux-$(2).bin.lzma"` -gt `expr $(4) - 64` ]; then \
@@ -954,7 +999,7 @@ endif
 #
 
 ifeq ($(SUBTARGET),mt7621)
-  TARGET_DEVICES += mt7621 wsr-600 wsr-1166 dir-860l-b1 firewrt pbr-m1 re6500 sap-g3200u3 witi wf-2881 zbt-wg2626
+  TARGET_DEVICES += mt7621 wsr-600 wsr-1166 dir-860l-b1 firewrt pbr-m1 re6500 sap-g3200u3 ubnt-erx witi wf-2881 zbt-wg2626
 endif
 
 define Device/mt7621
@@ -1023,6 +1068,20 @@ define Device/wf-2881
   IMAGE/sysupgrade.bin := append-kernel | pad-to $$(KERNEL_SIZE) | append-ubi | check-size $$$$(IMAGE_SIZE)
 endef
 
+define Device/ubnt-erx
+  DTS := UBNT-ERX
+  FILESYSTEMS := squashfs
+  KERNEL_SIZE := 3145728
+  KERNEL := $(KERNEL_DTB) | uImage lzma
+  IMAGES := sysupgrade.tar factory-initramfs.tar
+  IMAGE/factory-initramfs.tar := ubnt-erx-factory-compat | \
+				 ubnt-erx-factory-kernel | \
+				 ubnt-erx-factory-rootfs | \
+				 ubnt-erx-factory-version | \
+				 ubnt-erx-factory-check-size $$$$(KERNEL_SIZE)
+  IMAGE/sysupgrade.tar := sysupgrade-nand
+endef
+
 #
 # MT7628 Profiles
 #
diff --git a/target/linux/ramips/mt7621/profiles/ubnt.mk b/target/linux/ramips/mt7621/profiles/ubnt.mk
new file mode 100644
index 0000000..b66b206
--- /dev/null
+++ b/target/linux/ramips/mt7621/profiles/ubnt.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+define Profile/UBNT-ERX
+	NAME:=Ubiquiti EdgeRouter X
+	FEATURES+=nand -usb
+	PACKAGES:=-kmod-mt76 -wpad-mini -kmod-cfg80211
+endef
+
+define Profile/UBNT-ERX/Description
+	Package set compatible with the Ubiquiti EdgeRouter X
+endef
+$(eval $(call Profile,UBNT-ERX))
diff --git a/target/linux/ramips/patches-4.3/0901-spansion_nand_id_fix.patch b/target/linux/ramips/patches-4.3/0901-spansion_nand_id_fix.patch
new file mode 100644
index 0000000..bb95461
--- /dev/null
+++ b/target/linux/ramips/patches-4.3/0901-spansion_nand_id_fix.patch
@@ -0,0 +1,43 @@
+From 8b61a1a33e41456ebeafa0ebe7ec0fccf859861e Mon Sep 17 00:00:00 2001
+From: Nikolay Martynov <mar.kolya at gmail.com>
+Date: Wed, 25 Nov 2015 20:43:46 -0500
+Subject: [PATCH] mtd: nand: Fix Spansion sparearea size detection
+
+According to datasheet S34ML02G2 and S34ML04G2 have
+larger sparea area size than was detected.
+
+Signed-off-by: Nikolay Martynov <mar.kolya at gmail.com>
+---
+ drivers/mtd/nand/nand_base.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/mtd/nand/nand_base.c
++++ b/drivers/mtd/nand/nand_base.c
+@@ -3422,6 +3422,7 @@ static void nand_decode_ext_id(struct mt
+ 	/*
+ 	 * Field definitions are in the following datasheets:
+ 	 * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
++	 *                          Spansion S34ML02G2 (p.33)
+ 	 * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44)
+ 	 * Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22)
+ 	 *
+@@ -3519,6 +3520,19 @@ static void nand_decode_ext_id(struct mt
+ 		*busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
+ 
+ 		/*
++		 * Spansion S34ML0[24]G2 have oobsize twice as large
++		 * as S34ML01G2 encoded in the same bit. We
++		 * differinciate them by their ID length
++		 */
++		if (id_data[0] == NAND_MFR_AMD
++		    		&& (id_data[1] == 0xda
++				 || id_data[1] == 0xdc
++				 || id_data[1] == 0xca
++				 || id_data[1] == 0xcc)) {
++			mtd->oobsize *= 2;
++		}
++
++		/*
+ 		 * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
+ 		 * 512B page. For Toshiba SLC, we decode the 5th/6th byte as
+ 		 * follows:
-- 
2.6.4
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list