From 6fdeb48c1ec207e7952bfff1596b65626fb336fd Mon Sep 17 00:00:00 2001 From: Lech Perczak Date: Thu, 1 Sep 2022 23:00:02 +0200 Subject: [PATCH] ath79: support Ruckus ZoneFlex 7025 Ruckus ZoneFlex 7025 is a single 2.4GHz radio 802.11n 1x1 enterprise access point with built-in Ethernet switch, in an electrical outlet form factor. Hardware highligts: - CPU: Atheros AR7240 SoC at 400 MHz - RAM: 64MB DDR2 - Flash: 16MB SPI-NOR - Wi-Fi: AR9285 built-in 2.4GHz 1x1 radio - Ethernet: single Fast Ethernet port inside the electrical enclosure, coupled with internal LSA connector for direct wiring, four external Fast Ethernet ports on the lower side of the device. - PoE: 802.3af PD input inside the electrical box. 802.3af PSE output on the LAN4 port, capable of sourcing class 0 or class 2 devices, depending on power supply capacity. - External 8P8C pass-through connectors on the back and right side of the device - Standalone 48V power input on the side, through 2/1mm micro DC barrel jack Serial console: 115200-8-N-1 on internal JP1 header. Pinout: ---------- JP1 |5|4|3|2|1| ---------- Pin 1 is near the "H1" marking. 1 - RX 2 - n/c 3 - VCC (3.3V) 4 - GND 5 - TX Installation: There are two methods of installation: - Using serial console [1] - requires some disassembly, 3.3V USB-Serial adapter, TFTP server, and removing a single T10 screw, but with much less manual steps, and is generally recommended, being safer. - Using stock firmware root shell exploit, SSH and TFTP [2]. Does not work on some rare versions of stock firmware. A more involved, and requires installing `mkenvimage` from u-boot-tools package if you choose to rebuild your own environment, but can be used without disassembly or removal from installation point, if you have the credentials. If for some reason, size of your sysupgrade image exceeds 13312kB, proceed with method [1]. For official images this is not likely to happen ever. [1] Using serial console: 0. Connect serial console to H1 header. Ensure the serial converter does not back-power the board, otherwise it will fail to boot. 1. Power-on the board. Then quickly connect serial converter to PC and hit Ctrl+C in the terminal to break boot sequence. If you're lucky, you'll enter U-boot shell. Then skip to point 3. Connection parameters are 115200-8-N-1. 2. Allow the board to boot. Press the reset button, so the board reboots into U-boot again and go back to point 1. 3. Set the "bootcmd" variable to disable the dual-boot feature of the system and ensure that uImage is loaded. This is critical step, and needs to be done only on initial installation. > setenv bootcmd "bootm 0x9f040000" > saveenv 4. Boot the OpenWrt initramfs using TFTP. Replace IP addresses as needed: > setenv serverip 192.168.1.2 > setenv ipaddr 192.168.1.1 > tftpboot 0x81000000 openwrt-ath79-generic-ruckus_zf7025-initramfs-kernel.bin > bootm 0x81000000 5. Optional, but highly recommended: back up contents of "firmware" partition: $ ssh root@192.168.1.1 cat /dev/mtd1 > ruckus_zf7025_fw1_backup.bin 6. Copy over sysupgrade image, and perform actual installation. OpenWrt shall boot from flash afterwards: $ ssh root@192.168.1.1 # sysupgrade -n openwrt-ath79-generic-ruckus_zf7025-squashfs-sysupgrade.bin [2] Using stock root shell: 0. Reset the device to factory defaullts. Power-on the device and after it boots, hold the reset button near Ethernet connectors for 5 seconds. 1. Connect the device to the network. It will acquire address over DHCP, so either find its address using list of DHCP leases by looking for label MAC address, or try finding it by scanning for SSH port: $ nmap 10.42.0.0/24 -p22 From now on, we assume your computer has address 10.42.0.1 and the device has address 10.42.0.254. 2. Set up a TFTP server on your computer. We assume that TFTP server root is at /srv/tftp. 3. Obtain root shell. Connect to the device over SSH. The SSHD ond the frmware is pretty ancient and requires enabling HMAC-MD5. $ ssh 10.42.0.254 \ -o UserKnownHostsFile=/dev/null \ -o StrictHostKeyCheking=no \ -o MACs=hmac-md5 Login. User is "super", password is "sp-admin". Now execute a hidden command: Ruckus It is case-sensitive. Copy and paste the following string, including quotes. There will be no output on the console for that. ";/bin/sh;" Hit "enter". The AP will respond with: grrrr OK Now execute another hidden command: !v54! At "What's your chow?" prompt just hit "enter". Congratulations, you should now be dropped to Busybox shell with root permissions. 4. Optional, but highly recommended: backup the flash contents before installation. At your PC ensure the device can write the firmware over TFTP: $ sudo touch /srv/tftp/ruckus_zf7025_firmware{1,2}.bin $ sudo chmod 666 /srv/tftp/ruckus_zf7025_firmware{1,2}.bin Locate partitions for primary and secondary firmware image. NEVER blindly copy over MTD nodes, because MTD indices change depending on the currently active firmware, and all partitions are writable! # grep rcks_wlan /proc/mtd Copy over both images using TFTP, this will be useful in case you'd like to return to stock FW in future. Make sure to backup both, as OpenWrt uses bot firmwre partitions for storage! # tftp -l /dev/ -r ruckus_zf7025_firmware1.bin -p 10.42.0.1 # tftp -l /dev/ -r ruckus_zf7025_firmware2.bin -p 10.42.0.1 When the command finishes, copy over the dump to a safe place for storage. $ cp /srv/tftp/ruckus_zf7025_firmware{1,2}.bin ~/ 5. Ensure the system is running from the BACKUP image, i.e. from rcks_wlan.bkup partition or "image 2". Otherwise the installation WILL fail, and you will need to access mtd0 device to write image which risks overwriting the bootloader, and so is not covered here and not supported. Switching to backup firmware can be achieved by executing a few consecutive reboots of the device, or by updating the stock firmware. The system will boot from the image it was not running from previously. Stock firmware available to update was conveniently dumped in point 4 :-) 6. Prepare U-boot environment image. Install u-boot-tools package. Alternatively, if you build your own images, OpenWrt provides mkenvimage in host staging directory as well. It is recommended to extract environment from the device, and modify it, rather then relying on defaults: $ sudo touch /srv/tftp/u-boot-env.bin $ sudo chmod 666 /srv/tftp/u-boot-env.bin On the device, find the MTD partition on which environment resides. Beware, it may change depending on currently active firmware image! # grep u-boot-env /proc/mtd Now, copy over the partition # tftp -l /dev/mtd -r u-boot-env.bin -p 10.42.0.1 Store the stock environment in a safe place: $ cp /srv/tftp/u-boot-env.bin ~/ Extract the values from the dump: $ strings u-boot-env.bin | tee u-boot-env.txt Now clean up the debris at the end of output, you should end up with each variable defined once. After that, set the bootcmd variable like this: bootcmd=bootm 0x9f040000 You should end up with something like this: bootcmd=bootm 0x9f040000 bootargs=console=ttyS0,115200 rootfstype=squashfs init=/sbin/init baudrate=115200 ethaddr=0x00:0xaa:0xbb:0xcc:0xdd:0xee mtdparts=mtdparts=ar7100-nor0:256k(u-boot),7168k(rcks_wlan.main),7168k(rcks_wlan.bkup),1280k(datafs),256k(u-boot-env) mtdids=nor0=ar7100-nor0 bootdelay=2 filesize=52e000 fileaddr=81000000 ethact=eth0 stdin=serial stdout=serial stderr=serial partition=nor0,0 mtddevnum=0 mtddevname=u-boot ipaddr=192.168.0.1 serverip=192.168.0.2 stderr=serial ethact=eth0 These are the defaults, you can use most likely just this as input to mkenvimage. Now, create environment image and copy it over to TFTP root: $ mkenvimage -s 0x40000 -b -o u-boot-env.bin u-boot-env.txt $ sudo cp u-boot-env.bin /srv/tftp This is the same image, gzipped and base64-encoded: H4sICOLMEGMAA3UtYm9vdC1lbnYtbmV3LmJpbgDt0E1u00AUAGDfgm2XDUrTsUV/pTkFSxZoEk+o lcQJtlNaLsURwU4FikDiBN+3eDNvLL/3Zt5/+vFuud8Pq10dp3V3EV4e1uFDGBXTQeq+9HG1b/v9 NsdheP0Y5mV5U4Vw0Y1f1/3wesix/3pM/dO6v2jaZojX/bJpr6dtsUzHuktDjm//FHl4SnXdxfAS wmN4SWkMy+UYVqsx1PUYci52Q31I3dDHP5vU3ZUhXLX7LjxWN7eby+PVNNxsflfe3m8uu9Wm//xt m9rFLjXtv6fLzfEwm5fVfdhc1mlI6342Pytzldvn2dS1qfs49Tjvd3qFOm/Ta6yKdbPNffM9x5sq Ty805acL3Zfh5HTD1RDHJRT9WLGNfe6atJ2S/XE4y3LX/c6mSzZDs29P3edhmqXOz+1xF//s0y7H t3GL5nDqWT5Ui/Gii7Aoi7HQ81jrcHZY/dXkfLLiJwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8 xy8jb4zOAAAEAA== 7. Perform actual installation. Copy over OpenWrt sysupgrade image to TFTP root: $ sudo cp openwrt-ath79-generic-ruckus_zf7025-squashfs-sysupgrade.bin /srv/tftp Now load both to the device over TFTP: # tftp -l /tmp/u-boot-env.bin -r u-boot-env.bin -g 10.42.0.1 # tftp -l /tmp/openwrt.bin -r openwrt-ath79-generic-ruckus_zf7025-squashfs-sysupgrade.bin -g 10.42.0.1 Verify checksums of both images to ensure the transfer over TFTP was completed: # sha256sum /tmp/u-boot-env.bin /tmp/openwrt.bin And compare it against source images: $ sha256sum /srv/tftp/u-boot-env.bin /srv/tftp/openwrt-ath79-generic-ruckus_zf7025-squashfs-sysupgrade.bin Locate MTD partition of the primary image: # grep rcks_wlan.main /proc/mtd Now, write the images in place. Write U-boot environment last, so unit still can boot from backup image, should power failure occur during this. Replace MTD placeholders with real MTD nodes: # flashcp /tmp/openwrt.bin /dev/ # flashcp /tmp/u-boot-env.bin /dev/ Finally, reboot the device. The device should directly boot into OpenWrt. Look for the characteristic power LED blinking pattern. # reboot -f After unit boots, it should be available at the usual 192.168.1.1/24. Return to factory firmware: 1. Boot into OpenWrt initramfs as for initial installation. To do that without disassembly, you can write an initramfs image to the device using 'sysupgrade -F' first. 2. Unset the "bootcmd" variable: fw_setenv bootcmd "" 3. Concatenate the firmware backups, if you took them during installation using method 2: $ cat ruckus_zf7025_fw1_backup.bin ruckus_zf7025_fw2_backup.bin > ruckus_zf7025_backup.bin 3. Write factory images downloaded from manufacturer website into fwconcat0 and fwconcat1 MTD partitions, or restore backup you took before installation: # mtd write ruckus_zf7025_backup.bin /dev/mtd1 4. Reboot the system, it should load into factory firmware again. Quirks and known issues: - Flash layout is changed from the factory, to use both firmware image partitions for storage using mtd-concat, and uImage format is used to actually boot the system, which rules out the dual-boot capability. - The 2.4 GHz radio has its own EEPROM on board, not connected to CPU. - The stock firmware has dual-boot capability, which is not supported in OpenWrt by choice. It is controlled by data in the top 64kB of RAM which is unmapped, to avoid the interference in the boot process and accidental switch to the inactive image, although boot script presence in form of "bootcmd" variable should prevent this entirely. - On some versions of stock firmware, it is possible to obtain root shell, however not much is available in terms of debugging facitilies. 1. Login to the rkscli 2. Execute hidden command "Ruckus" 3. Copy and paste ";/bin/sh;" including quotes. This is required only once, the payload will be stored in writable filesystem. 4. Execute hidden command "!v54!". Press Enter leaving empty reply for "What's your chow?" prompt. 5. Busybox shell shall open. Source: https://alephsecurity.com/vulns/aleph-2019014 Signed-off-by: Lech Perczak --- package/boot/uboot-envtools/files/ath79 | 3 + .../linux/ath79/dts/ar7240_ruckus_zf7025.dts | 196 ++++++++++++++++++ .../generic/base-files/etc/board.d/01_leds | 7 + .../generic/base-files/etc/board.d/02_network | 6 + target/linux/ath79/image/generic.mk | 19 +- 5 files changed, 228 insertions(+), 3 deletions(-) create mode 100644 target/linux/ath79/dts/ar7240_ruckus_zf7025.dts diff --git a/package/boot/uboot-envtools/files/ath79 b/package/boot/uboot-envtools/files/ath79 index 89eb830575..60aa3c6ba4 100644 --- a/package/boot/uboot-envtools/files/ath79 +++ b/package/boot/uboot-envtools/files/ath79 @@ -138,6 +138,9 @@ plasmacloud,pa300e) qihoo,c301) ubootenv_add_uci_config "/dev/mtd9" "0x0" "0x10000" "0x10000" ;; +ruckus,zf7025) + ubootenv_add_uci_config "/dev/mtd5" "0x0" "0x40000" "0x40000" + ;; ruckus,zf7321|\ ruckus,zf7372) ubootenv_add_uci_config "/dev/mtd2" "0x0" "0x40000" "0x10000" diff --git a/target/linux/ath79/dts/ar7240_ruckus_zf7025.dts b/target/linux/ath79/dts/ar7240_ruckus_zf7025.dts new file mode 100644 index 0000000000..9e0671d638 --- /dev/null +++ b/target/linux/ath79/dts/ar7240_ruckus_zf7025.dts @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "ar7240.dtsi" + +#include +#include + + +/ { + model = "Ruckus ZoneFlex 7025"; + compatible = "ruckus,zf7025", "qca,ar7240"; + + aliases { + led-boot = &led_power_green; + led-failsafe = &led_power_red; + led-running = &led_power_green; + led-upgrade = &led_power_red; + label-mac-device = ð0; + }; + + keys { + compatible = "gpio-keys"; + + hard-reset { + label = "hard-reset"; + linux,code = ; + gpios = <&gpio 12 GPIO_ACTIVE_LOW>; + debounce-interval = <60>; + }; + }; + + leds: leds { + compatible = "gpio-leds"; + + pinctrl-names = "default"; + pinctrl-0 = <&jtag_disable_pins &switch_led_disable_pins &clks_disable_pins>; + + dir { + label = "green:dir"; + gpios = <&gpio 1 GPIO_ACTIVE_LOW>; + }; + + lan1 { + label = "green:lan1"; + gpios = <&gpio 16 GPIO_ACTIVE_LOW>; + }; + + lan2 { + label = "green:lan2"; + gpios = <&gpio 15 GPIO_ACTIVE_LOW>; + }; + + lan3 { + label = "green:lan3"; + gpios = <&gpio 14 GPIO_ACTIVE_LOW>; + }; + + lan4 { + label = "green:lan4"; + gpios = <&gpio 13 GPIO_ACTIVE_LOW>; + }; + + lan5 { + label = "green:lan5"; + gpios = <&gpio 17 GPIO_ACTIVE_LOW>; + }; + + opt { + label = "green:opt"; + gpios = <&gpio 8 GPIO_ACTIVE_LOW>; + }; + + led_power_red: power-red { + label = "red:power"; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + panic-indicator; + }; + + led_power_green: power-green { + label = "green:power"; + gpios = <&gpio 7 GPIO_ACTIVE_LOW>; + default-state = "on"; + }; + + wlan-green { + label = "green:wlan"; + gpios = <&gpio 0 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0assoc"; + }; + + wlan-yellow { + label = "yellow:wlan"; + gpios = <&gpio 6 GPIO_ACTIVE_LOW>; + linux,default-trigger = "phy0tpt"; + }; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + ruckus-himem@3ff0000 { + /* Ruckus Himem area used to control + * redundant boot image selection + */ + compatible = "nvmem-rmem"; + reg = <0x3ff0000 0x10000>; + no-map; + }; + }; +}; + +&spi { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <104000000>; + m25p,fast-read; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 0x40000>; + label = "u-boot"; + read-only; + }; + + /* On stock FW this encompasses rcks_wlan.main, + * rcks_wlan.bkup and datafs partitions + */ + partition@40000 { + compatible = "openwrt,uimage", "denx,uimage"; + reg = <0x40000 0xf40000>; + label = "firmware"; + }; + + partition@f80000 { + compatible = "u-boot,env"; + reg = <0xf80000 0x40000>; + label = "u-boot-env"; + }; + + board_data: partition@fc0000 { + reg = <0xfc0000 0x40000>; + label = "board-data"; + read-only; + }; + }; + }; +}; + +ð0 { + nvmem-cells = <&macaddr_board_data_66>; + nvmem-cell-names = "mac-address"; +}; + +ð1 { + status = "okay"; + nvmem-cells = <&macaddr_board_data_6c>; + nvmem-cell-names = "mac-address"; +}; + +&pcie { + status = "okay"; + + ath9k: wifi@0,0 { + compatible = "pci168c,002b"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&macaddr_board_data_60>; + nvmem-cell-names = "mac-address"; + }; +}; + +&board_data { + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_board_data_60: macaddr@60 { + reg = <0x60 0x6>; + }; + + macaddr_board_data_66: macaddr@66 { + reg = <0x66 0x6>; + }; + + macaddr_board_data_6c: macaddr@6c { + reg = <0x6c 0x6>; + }; +}; diff --git a/target/linux/ath79/generic/base-files/etc/board.d/01_leds b/target/linux/ath79/generic/base-files/etc/board.d/01_leds index 7fe9343876..cfcd2dfeda 100644 --- a/target/linux/ath79/generic/base-files/etc/board.d/01_leds +++ b/target/linux/ath79/generic/base-files/etc/board.d/01_leds @@ -327,6 +327,13 @@ qca,ap143-16m) qihoo,c301) ucidef_set_led_wlan "wlan" "WLAN" "green:wlan" "phy0tpt" ;; +ruckus,zf7025) + ucidef_set_led_netdev "lan" "LAN5" "green:lan5" "eth0" + ucidef_set_led_switch "lan1" "LAN1" "green:lan1" "switch0" "0x10" + ucidef_set_led_switch "lan2" "LAN2" "green:lan2" "switch0" "0x08" + ucidef_set_led_switch "lan3" "LAN3" "green:lan3" "switch0" "0x04" + ucidef_set_led_switch "lan4" "LAN4" "green:lan4" "switch0" "0x02" + ;; ruckus,zf7372) ucidef_set_led_switch "lan" "LAN" "green:eth1" "switch0" "0x02" ;; 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 339005f051..50576be9c5 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 @@ -434,6 +434,11 @@ ath79_setup_interfaces() ucidef_add_switch "switch0" \ "0@eth0" "1:lan" "2:lan" "3:wan" ;; + ruckus,zf7025) + ucidef_set_interface_lan "eth0 eth1" + ucidef_add_switch "switch0" \ + "0u@eth1" "4:lan:1" "3:lan:2" "2:lan:3" "1:lan:4" + ;; teltonika,rut955|\ teltonika,rut955-h7v3c0) ucidef_set_interface_wan "eth1" @@ -716,6 +721,7 @@ ath79_setup_macs() wan_mac=$(mtd_get_mac_binary factory 0x0) lan_mac=$(macaddr_setbit_la "$wan_mac") ;; + ruckus,zf7025|\ ruckus,zf7321|\ ruckus,zf7372) lan_mac=$(mtd_get_mac_binary board-data 0x807E) diff --git a/target/linux/ath79/image/generic.mk b/target/linux/ath79/image/generic.mk index e5bc73e5a6..c9bbb412b6 100644 --- a/target/linux/ath79/image/generic.mk +++ b/target/linux/ath79/image/generic.mk @@ -2402,15 +2402,28 @@ define Device/rosinson_wr818 endef TARGET_DEVICES += rosinson_wr818 -define Device/ruckus_zf73xx_common +define Device/ruckus_common DEVICE_VENDOR := Ruckus - DEVICE_PACKAGES := -swconfig kmod-usb2 kmod-usb-chipidea2 - IMAGE_SIZE := 31744k LOADER_TYPE := bin KERNEL := kernel-bin | append-dtb | lzma | loader-kernel | uImage none KERNEL_INITRAMFS := kernel-bin | append-dtb | lzma | loader-kernel | uImage none endef +define Device/ruckus_zf7025 + $(Device/ruckus_common) + SOC := ar7240 + DEVICE_MODEL := ZoneFlex 7025 + IMAGE_SIZE := 15616k + BLOCKSIZE := 256k +endef +TARGET_DEVICES += ruckus_zf7025 + +define Device/ruckus_zf73xx_common + $(Device/ruckus_common) + DEVICE_PACKAGES := -swconfig kmod-usb2 kmod-usb-chipidea2 + IMAGE_SIZE := 31744k +endef + define Device/ruckus_zf7321 $(Device/ruckus_zf73xx_common) SOC := ar9342 -- 2.30.2