[openwrt/openwrt] ath79: add support for TP-Link Deco S4

LEDE Commits lede-commits at lists.infradead.org
Sun Sep 11 12:55:48 PDT 2022


hauke pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/20581ee8b590afc56cda013272861e1e614a078e

commit 20581ee8b590afc56cda013272861e1e614a078e
Author: Nick French <nickfrench at gmail.com>
AuthorDate: Sat Aug 13 12:09:50 2022 -0500

    ath79: add support for TP-Link Deco S4
    
    Add support for TP-Link Deco S4 wifi router
    
    The label refers to the device as S4R and the TP-Link firmware
    site calls it the Deco S4 v2. (There does not appear to be a v1)
    
    Hardware (and FCC id) are identical to the Deco M4R v2 but the
    flash layout is ordered differently and the OEM firmware encrypts
    some config parameters (including the label mac address) in flash
    
    In order to set the encrypted mac address, the wlan's caldata
    node is removed from the DTS so the mac can be decrypted with
    the help of the uencrypt tool and patched into the wlan fw
    via hotplug
    
    Specifications:
    SoC: QCA9563-AL3A
    RAM: Zentel A3R1GE40JBF
    Wireless 2.4GHz: QCA9563-AL3A (main SoC)
    Wireless 5GHz: QCA9886
    Ethernet Switch: QCA8337N-AL3C
    Flash: 16 MB SPI NOR
    
    UART serial access (115200N1) on board via solder pads:
    RX = TP1 pad
    TX = TP2 pad
    GND = C201 (pad nearest board edge)
    
    The device's bootloader and web gui will only accept images that
    were signed using TP-Link's RSA key, however a memory safety bug
    in the bootloader can be leveraged to install openwrt without
    accessing the serial console. See developer forum S4 support page
    for link to a "firmware" file that starts a tftp client, or you
    may generate one on your own like this:
    ```
    python - > deco_s4_faux_fw_tftp.bin <<EOF
    import sys
    from struct import pack
    
    b = pack('>I', 0x00008000) + b'X'*16 + b"fw-type:" \
      + b'x'*256 + b"S000S001S002" + pack('>I', 0x80060200) \
    
    b += b"\x00"*(0x200-len(b)) \
      + pack(">33I", *[0x3c0887fc, 0x35083ddc, 0xad000000, 0x24050000,
                       0x3c048006, 0x348402a0, 0x3c1987f9, 0x373947f4,
                       0x0320f809, 0x00000000, 0x24050000, 0x3c048006,
                       0x348402d0, 0x3c1987f9, 0x373947f4, 0x0320f809,
                       0x00000000, 0x24050000, 0x3c048006, 0x34840300,
                       0x3c1987f9, 0x373947f4, 0x0320f809, 0x00000000,
                       0x24050000, 0x3c048006, 0x34840400, 0x3c1987f9,
                       0x373947f4, 0x0320f809, 0x00000000, 0x1000fff1,
                       0x00000000])
    
    b += b"\xff"*(0x2A0-len(b)) + b"setenv serverip 192.168.0.2\x00"
    b += b"\xff"*(0x2D0-len(b)) + b"setenv ipaddr 192.168.0.1\x00"
    b += b"\xff"*(0x300-len(b)) + b"tftpboot 0x81000000 initramfs-kernel.bin\x00"
    b += b"\xff"*(0x400-len(b)) + b"bootm 0x81000000\x00"
    b += b"\xff"*(0x8000-len(b))
    
    sys.stdout.buffer.write(b)
    EOF
    ```
    
    Installation:
    1. Run tftp server on pc with static ip 192.168.0.2
    2. Place openwrt "initramfs-kernel.bin" image in tftp root dir
    3. Connect pc to router ethernet port1
    4. While holding in reset button on bottom of router, power on router
    5. From pc access router webgui at http://192.168.0.1
    6. Upload deco_s4_faux_fw_tftp.bin
    7. Router will load and execture in-memory openwrt
    8. Switch pc back to dhcp or static 192.168.1.x
    9. Flash openwrt sysupgrade image via luci/ssh at 192.168.1.1
    
    Revert to stock:
    Press and hold reset button while powering device to start the
    bootloader's recovery mode, where stock firmware can be uploaded
    via web gui at 192.168.0.1
    
    Please note that one additional non-github commits is also needed:
    firmware-utils: add tplink-safeloader support for Deco S4
    
    Signed-off-by: Nick French <nickfrench at gmail.com>
---
 package/base-files/files/lib/functions/system.sh   |  19 +++
 .../linux/ath79/dts/qca9563_tplink_deco-s4-v2.dts  | 131 +++++++++++++++++++++
 .../generic/base-files/etc/board.d/02_network      |   7 +-
 .../etc/hotplug.d/firmware/10-ath9k-eeprom         |   5 +
 .../etc/hotplug.d/firmware/11-ath10k-caldata       |   7 ++
 .../base-files/lib/preinit/10_fix_eth_mac.sh       |   6 +-
 target/linux/ath79/image/generic-tp-link.mk        |  12 ++
 7 files changed, 185 insertions(+), 2 deletions(-)

diff --git a/package/base-files/files/lib/functions/system.sh b/package/base-files/files/lib/functions/system.sh
index c17354d945..22eb00c515 100644
--- a/package/base-files/files/lib/functions/system.sh
+++ b/package/base-files/files/lib/functions/system.sh
@@ -110,6 +110,25 @@ mtd_get_mac_encrypted_arcadyan() {
 	[ -n "$mac_dirty" ] && macaddr_canonicalize "$mac_dirty"
 }
 
+mtd_get_mac_encrypted_deco() {
+	local mtdname="$1"
+
+	if ! [ -e "$mtdname" ]; then
+		echo "mtd_get_mac_encrypted_deco: file $mtdname not found!" >&2
+		return
+	fi
+
+	tplink_key="3336303032384339"
+
+	key=$(dd if=$mtdname bs=1 skip=16 count=8 2>/dev/null | \
+		uencrypt -n -d -k $tplink_key -c des-ecb | hexdump -v -n 8 -e '1/1 "%02x"')
+
+	macaddr=$(dd if=$mtdname bs=1 skip=32 count=8 2>/dev/null | \
+		uencrypt -n -d -k $key -c des-ecb | hexdump -v -n 6 -e '5/1 "%02x:" 1/1 "%02x"')
+
+	echo $macaddr
+}
+
 mtd_get_mac_text() {
 	local mtdname=$1
 	local offset=$(($2))
diff --git a/target/linux/ath79/dts/qca9563_tplink_deco-s4-v2.dts b/target/linux/ath79/dts/qca9563_tplink_deco-s4-v2.dts
new file mode 100644
index 0000000000..e4bb88807e
--- /dev/null
+++ b/target/linux/ath79/dts/qca9563_tplink_deco-s4-v2.dts
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+#include "qca956x.dtsi"
+
+/ {
+	compatible = "tplink,deco-s4-v2", "qca,qca9563";
+	model = "TP-Link Deco S4 v2";
+
+	aliases {
+		led-boot = &led_power;
+		led-failsafe = &led_power;
+		led-running = &led_power;
+		led-upgrade = &led_power;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		wlan2g {
+			label = "red:wlan2g";
+			gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "phy1tpt";
+		};
+
+		led_power: power {
+			label = "green:power";
+			gpios = <&gpio 7 GPIO_ACTIVE_LOW>;
+			default-state = "on";
+		};
+
+		wlan5g {
+			label = "blue:wlan5g";
+			gpios = <&gpio 9 GPIO_ACTIVE_LOW>;
+			linux,default-trigger = "phy0tpt";
+		};
+	};
+
+
+	keys {
+		compatible = "gpio-keys";
+
+		reset {
+			label = "Reset button";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
+			debounce-interval = <60>;
+		};
+	};
+};
+
+&pcie {
+	status = "okay";
+};
+
+&mdio0 {
+	status = "okay";
+
+	phy0: ethernet-phy at 0 {
+		reg = <0>;
+		phy-mode = "sgmii";
+		qca,mib-poll-interval = <500>;
+
+		qca,ar8327-initvals = <
+			0x04 0x00080080 /* PORT0 PAD MODE CTRL */
+			0x7c 0x0000007e /* PORT0_STATUS */
+			>;
+	};
+};
+
+&spi {
+	status = "okay";
+	num-cs = <1>;
+
+	flash at 0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <25000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			uboot: partition at 0 {
+				label = "u-boot";
+				reg = <0x000000 0x080000>;
+				read-only;
+			};
+
+			partition at 80000 {
+				label = "product-info";
+				reg = <0x80000 0x05000>;
+				read-only;
+			};
+
+			config: partition at 85000 {
+				label = "config";
+				reg = <0x85000 0x16b000>;
+				read-only;
+			};
+
+			art: partition at 1f0000 {
+				label = "art";
+				reg = <0x1f0000 0x10000>;
+				read-only;
+			};
+
+			partition at 200000 {
+				compatible = "denx,uimage";
+				label = "firmware";
+				reg = <0x200000 0xe00000>;
+			};
+		};
+	};
+};
+
+&eth0 {
+	status = "okay";
+
+	phy-mode = "sgmii";
+	phy-handle = <&phy0>;
+};
+
+&wmac {
+	status = "okay";
+
+	qca,no-eeprom;
+};
diff --git a/target/linux/ath79/generic/base-files/etc/board.d/02_network b/target/linux/ath79/generic/base-files/etc/board.d/02_network
index 3b69c2bded..a2ae5cb8de 100644
--- a/target/linux/ath79/generic/base-files/etc/board.d/02_network
+++ b/target/linux/ath79/generic/base-files/etc/board.d/02_network
@@ -519,7 +519,8 @@ ath79_setup_interfaces()
 		ucidef_add_switch "switch0" \
 			"0 at eth0" "1:lan" "2:lan"
 		;;
-	tplink,deco-m4r-v1)
+	tplink,deco-m4r-v1|\
+	tplink,deco-s4-v2)
 		ucidef_add_switch "switch0" \
 			"0 at eth0" "3:lan:1" "5:lan:2"
 		;;
@@ -677,6 +678,10 @@ ath79_setup_macs()
 		base_mac=$(mtd_get_mac_binary u-boot 0x1fc00)
 		wan_mac=$(macaddr_add "$base_mac" 1)
 		;;
+	tplink,deco-s4-v2)
+		lan_mac=$(mtd_get_mac_encrypted_deco $(find_mtd_part config))
+		label_mac=$lan_mac
+		;;
 	nec,wf1200cr|\
 	nec,wg1200cr)
 		lan_mac=$(mtd_get_mac_ascii devdata "lanmac")
diff --git a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom
index 9127aed36e..04705aadf8 100644
--- a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom
+++ b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom
@@ -71,6 +71,11 @@ case "$FIRMWARE" in
 		caldata_extract "radiocfg" 0x1000 0x440
 		ath9k_patch_mac $(mtd_get_mac_ascii devdata "wlan24mac")
 		;;
+	tplink,deco-s4-v2)
+		caldata_extract "art" 0x1000 0x440
+		base_mac=$(mtd_get_mac_encrypted_deco $(find_mtd_part config))
+		ath9k_patch_mac $(macaddr_add $base_mac 1)
+		;;
 	*)
 		caldata_die "board $board is not supported yet"
 		;;
diff --git a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
index a47b29e7c7..57e59a89d6 100644
--- a/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
+++ b/target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
@@ -263,6 +263,13 @@ case "$FIRMWARE" in
 		ln -sf /lib/firmware/ath10k/pre-cal-pci-0000\:00\:00.0.bin \
 			/lib/firmware/ath10k/QCA9888/hw2.0/board.bin
 		;;
+	tplink,deco-s4-v2)
+		caldata_extract "art" 0x5000 0x2f20
+		base_mac=$(mtd_get_mac_encrypted_deco $(find_mtd_part config))
+		ath10k_patch_mac $(macaddr_add $base_mac 2)
+		ln -sf /lib/firmware/ath10k/pre-cal-pci-0000\:00\:00.0.bin \
+			/lib/firmware/ath10k/QCA9888/hw2.0/board.bin
+		;;
 	esac
 	;;
 *)
diff --git a/target/linux/ath79/generic/base-files/lib/preinit/10_fix_eth_mac.sh b/target/linux/ath79/generic/base-files/lib/preinit/10_fix_eth_mac.sh
index d9cb8d2b82..d06f043ad4 100644
--- a/target/linux/ath79/generic/base-files/lib/preinit/10_fix_eth_mac.sh
+++ b/target/linux/ath79/generic/base-files/lib/preinit/10_fix_eth_mac.sh
@@ -1,4 +1,4 @@
-. /lib/functions.sh
+. /lib/functions/system.sh
 
 preinit_set_mac_address() {
 	case $(board_name) in
@@ -19,6 +19,10 @@ preinit_set_mac_address() {
 	siemens,ws-ap3610)
 		ip link set dev eth0 address $(mtd_get_mac_ascii cfg1 ethaddr)
 		;;
+	tplink,deco-s4-v2)
+		base_mac=$(mtd_get_mac_encrypted_deco $(find_mtd_part config))
+		ip link set dev eth0 address $base_mac
+		;;
 	zyxel,nbg6616)
 		ethaddr=$(mtd_get_mac_ascii u-boot-env ethaddr)
 		ip link set dev eth0 address $(macaddr_add $ethaddr 2)
diff --git a/target/linux/ath79/image/generic-tp-link.mk b/target/linux/ath79/image/generic-tp-link.mk
index ffe1d6e290..598085e50b 100644
--- a/target/linux/ath79/image/generic-tp-link.mk
+++ b/target/linux/ath79/image/generic-tp-link.mk
@@ -493,6 +493,18 @@ define Device/tplink_deco-m4r-v1
 endef
 TARGET_DEVICES += tplink_deco-m4r-v1
 
+define Device/tplink_deco-s4-v2
+  $(Device/tplink-safeloader-uimage)
+  SOC := qca9563
+  IMAGE_SIZE := 13824k
+  DEVICE_MODEL := Deco S4
+  DEVICE_VARIANT := v2
+  DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca9888-ct uencrypt
+  SUPPORTED_DEVICES += deco-s4-v2
+  TPLINK_BOARD_ID := DECO-S4-V2
+endef
+TARGET_DEVICES += tplink_deco-s4-v2
+
 define Device/tplink_re350k-v1
   $(Device/tplink-safeloader)
   SOC := qca9558




More information about the lede-commits mailing list