ath79: Add support for MOXA AWK-1137C
authorMaximilian Martin <mm@simonwunderlich.de>
Tue, 13 Jun 2023 10:55:59 +0000 (12:55 +0200)
committerHauke Mehrtens <hauke@hauke-m.de>
Sun, 25 Jun 2023 10:59:26 +0000 (12:59 +0200)
Device specifications:
======================

* Qualcomm/Atheros AR9344
* 128 MB of RAM
* 16 MB of SPI NOR flash
* 2x 10/100 Mbps Ethernet
* 2T2R 2.4/5 GHz Wi-Fi
* 4x GPIO-LEDs (1x wifi, 2x ethernet, 1x power)
* 1x GPIO-button (reset)
* 2x fast ethernet
  - lan1
    + builtin switch port 1
    + used as WAN interface
  - lan2
    + builtin switch port 2
    + used as LAN interface
* 9-30V DC
* external antennas

Flashing instructions:
======================

Log in to https://192.168.127.253/
   Username: admin
   Password: moxa

Open Maintenance > Firmware Upgrade and install the factory image.

Serial console access:
======================

Connect a RS232-USB converter to the maintenance port.
   Pinout: (reset button left) [GND] [NC] [RX] [TX]

Firmware Recovery:
==================

When the WLAN and SYS LEDs are flashing, the device is in recovery mode.

Serial console access is required to proceed with recovery.

Download the original image from MOXA and rename it to 'awk-1137c.rom'.
Set up a TFTP server at 192.168.127.1 and connect to a lan port.

Follow the instructions on the serial console to start the recovery.

Signed-off-by: Maximilian Martin <mm@simonwunderlich.de>
include/image-commands.mk
package/boot/uboot-envtools/files/ath79
scripts/moxa-encode-fw.py [new file with mode: 0755]
target/linux/ath79/dts/ar9344_moxa_awk-1137c.dts [new file with mode: 0644]
target/linux/ath79/generic/base-files/etc/board.d/01_leds
target/linux/ath79/generic/base-files/etc/board.d/02_network
target/linux/ath79/generic/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom
target/linux/ath79/generic/base-files/etc/init.d/bootcount
target/linux/ath79/generic/base-files/lib/preinit/10_fix_eth_mac.sh
target/linux/ath79/image/generic.mk

index 1d694850195457f826a975044a43a2674d6c1af2..9220b8dec0069abef9c98b27b7d7ba04242d7c98 100644 (file)
@@ -399,6 +399,15 @@ define Build/lzma-no-dict
        @mv $@.new $@
 endef
 
+define Build/moxa-encode-fw
+       $(TOPDIR)/scripts/moxa-encode-fw.py \
+               --input $@ \
+               --output $@ \
+               --magic $(MOXA_MAGIC) \
+               --hwid $(MOXA_HWID) \
+               --buildid 00000000
+endef
+
 define Build/netgear-chk
        $(STAGING_DIR_HOST)/bin/mkchkimg \
                -o $@.new \
index 5201b8b27a3ad7cb96cecd99d5cc4aa1283c0f53..e83703b03556b42669e8a22eace290825c5bfc33 100644 (file)
@@ -47,6 +47,7 @@ etactica,eg200|\
 glinet,gl-ar750s-nor|\
 glinet,gl-ar750s-nor-nand|\
 librerouter,librerouter-v1|\
+moxa,awk-1137c|\
 netgear,ex7300|\
 netgear,ex7300-v2|\
 netgear,wndr4300-v2|\
diff --git a/scripts/moxa-encode-fw.py b/scripts/moxa-encode-fw.py
new file mode 100755 (executable)
index 0000000..48d139b
--- /dev/null
@@ -0,0 +1,109 @@
+#! /usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import argparse
+import struct
+
+from binascii import crc32
+from dataclasses import dataclass
+from itertools import cycle
+from typing import List
+
+
+def xor(data: bytes) -> bytes:
+    passphrase = "Seek AGREEMENT for the date of completion.\0"
+    pw = cycle(bytearray(passphrase.encode('ascii')))
+    return bytearray(b ^ next(pw) for b in data)
+
+
+def add_fw_header(data: bytes, magic: int, hwid: int, build_id: int,
+                  offsets: List[int]) -> bytes:
+    unknown_1 = 0x01
+    unknown_2 = 0x0000
+    unknown_3 = 0x00000000
+    unknown_4 = 0x01000000
+    file_crc = crc(data, 0)
+
+    header_struct = struct.Struct('>QIBBHIIIIII' + 'I' * len(offsets))
+    header_size = header_struct.size
+    file_size = header_size + len(data)
+
+    header_offsets = map(lambda x: x + header_size, offsets)
+
+    header_data = header_struct.pack(magic, file_size, unknown_1, len(offsets),
+                                     unknown_2, hwid, build_id, unknown_3,
+                                     build_id, unknown_4, *header_offsets,
+                                     file_crc)
+    return header_data + data
+
+
+def add_file_header(data: bytes, filename: str, build_id: int) -> bytes:
+    unknown1 = 0x01000000
+    unknown2 = 0x00000000
+    file_crc = crc(data, 0)
+
+    header_struct = struct.Struct(">16sIIIII")
+    file_size = header_struct.size + len(data)
+
+    header_data = header_struct.pack(filename.encode('ascii'), file_size,
+                                     unknown1, build_id, unknown2, file_crc)
+    return header_data + data
+
+
+def crc(data: bytes, init_val: int) -> int:
+    return 0xffffffff ^ (crc32(data, 0xffffffff ^ init_val))
+
+
+@dataclass
+class Partition:
+    name: str
+    size: int
+
+
+def main():
+    partitions = [
+        Partition(name='kernel', size=2048 * 1024),
+        Partition(name='root', size=9216 * 1024),
+        Partition(name='userdisk', size=3076 * 1024),
+    ]
+
+    parser = argparse.ArgumentParser(prog='moxa-encode-fw',
+                                     description='MOXA IW firmware encoder')
+    parser.add_argument('-i', '--input', required=True, type=str, help='Firmware file')
+    parser.add_argument('-o', '--output', required=True, type=str, help="Output path for encoded firmware file")
+    parser.add_argument('-m', '--magic', required=True, type=lambda x: int(x,0), help="Magic for firmware header")
+    parser.add_argument('-d', '--hwid', required=True, type=lambda x: int(x,0), help="Hardware id of device")
+    parser.add_argument('-b', '--buildid', required=True, type=lambda x: int(x,0), help="Build id of firmware")
+    args = parser.parse_args()
+
+    with open(args.input, 'rb') as input_file:
+        firmware = bytearray(input_file.read())
+
+    offsets = []
+    pos_input = 0
+    pos_output = 0
+    firmware_seg = bytearray()
+
+    for partition in partitions:
+        part_data = firmware[pos_input:pos_input + partition.size]
+
+        # just to make sure that no partition is empty
+        if len(part_data) == 0:
+            part_data = bytearray([0x00])
+
+        header = add_file_header(part_data, partition.name, args.buildid)
+        firmware_seg += header
+
+        offsets.append(pos_output)
+        pos_input += partition.size
+        pos_output += len(header)
+
+    moxa_firmware = add_fw_header(firmware_seg, args.magic, args.hwid, args.buildid, offsets)
+
+    encrypted = xor(moxa_firmware)
+    with open(args.output, 'wb') as output_file:
+        output_file.write(encrypted)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/target/linux/ath79/dts/ar9344_moxa_awk-1137c.dts b/target/linux/ath79/dts/ar9344_moxa_awk-1137c.dts
new file mode 100644 (file)
index 0000000..d2c5171
--- /dev/null
@@ -0,0 +1,184 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+
+#include "ar9344.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+       compatible = "moxa,awk-1137c", "qca,ar9344";
+       model = "MOXA AWK-1137C";
+
+       aliases {
+               led-boot = &led_status_red;
+               led-failsafe = &led_status_red;
+               led-running = &led_status_green;
+               led-upgrade = &led_status_red;
+               label-mac-device = &eth1;
+       };
+
+       keys {
+               compatible = "gpio-keys";
+
+               reset {
+                       label = "reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               pinctrl-names = "default";
+
+               led_status_green: led-0 {
+                       label = "green:status";
+                       color = <LED_COLOR_ID_GREEN>;
+                       function = LED_FUNCTION_STATUS;
+                       function-enumerator = <0>;
+                       gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
+               };
+
+               led_status_red: led-1 {
+                       label = "red:status";
+                       color = <LED_COLOR_ID_RED>;
+                       function = LED_FUNCTION_STATUS;
+                       function-enumerator = <1>;
+                       gpios = <&gpio 3 GPIO_ACTIVE_LOW>;
+               };
+
+               led-2 {
+                       label = "green:wifi";
+                       color = <LED_COLOR_ID_GREEN>;
+                       function = LED_FUNCTION_WLAN;
+                       function-enumerator = <0>;
+                       gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "phy0tpt";
+               };
+
+               led-3 {
+                       label = "green:lan1";
+                       color = <LED_COLOR_ID_GREEN>;
+                       function = LED_FUNCTION_WAN;
+                       gpios = <&gpio 14 GPIO_ACTIVE_LOW>;
+               };
+
+               led-4 {
+                       label = "green:lan2";
+                       color = <LED_COLOR_ID_GREEN>;
+                       function = LED_FUNCTION_LAN;
+                       gpios = <&gpio 15 GPIO_ACTIVE_LOW>;
+               };
+
+               led-5 {
+                       label = "yellow:wifi";
+                       color = <LED_COLOR_ID_YELLOW>;
+                       function = LED_FUNCTION_WLAN;
+                       function-enumerator = <1>;
+                       gpios = <&gpio 21 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "phy0assoc";
+               };
+       };
+};
+
+&ref {
+       clock-frequency = <40000000>;
+};
+
+&spi {
+       status = "okay";
+
+       flash@0 {
+               compatible = "jedec,spi-nor";
+               reg = <0>;
+               spi-max-frequency = <40000000>;
+
+               partitions {
+                       compatible = "fixed-partitions";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       partition@0 {
+                               label = "u-boot";
+                               reg = <0x000000 0x040000>;
+                               read-only;
+                       };
+
+                       partition@40000 {
+                               label = "u-boot-env";
+                               reg = <0x040000 0x010000>;
+                       };
+
+                       partition@50000 {
+                               label = "firmware";
+                               reg = <0x050000 0xe00000>;
+                               compatible = "denx,uimage";
+                       };
+
+                       partition@e50000 {
+                               label = "log1";
+                               reg = <0xe50000 0x020000>;
+                               read-only;
+                       };
+
+                       partition@e70000 {
+                               label = "log2";
+                               reg = <0xe70000 0x020000>;
+                               read-only;
+                       };
+
+                       partition@e90000 {
+                               label = "version";
+                               reg = <0xe90000 0x020000>;
+                               read-only;
+                       };
+
+                       partition@eb0000 {
+                               label = "config1";
+                               reg = <0xeb0000 0x020000>;
+                               read-only;
+                       };
+
+                       partition@ed0000 {
+                               label = "config2";
+                               reg = <0xed0000 0x020000>;
+                               read-only;
+                       };
+
+                       partition@ef0000 {
+                               label = "config-data";
+                               reg = <0xef0000 0x0c0000>;
+                               read-only;
+                       };
+
+                       partition@fb0000 {
+                               label = "mib0";
+                               reg = <0xfb0000 0x030000>;
+                               read-only;
+                       };
+
+                       art: partition@fe0000 {
+                               label = "art";
+                               reg = <0xfe0000 0x010000>;
+                               read-only;
+                       };
+
+                       partition@ff0000 {
+                               label = "fis";
+                               reg = <0xff0000 0x010000>;
+                               read-only;
+                       };
+               };
+       };
+};
+
+&eth1 {
+       status = "okay";
+};
+
+&wmac {
+       status = "okay";
+       qca,no-eeprom;
+};
index 10c67991fd29ab4ca7adb1a98cde1c2f838649cd..65cf7b329231e1a91cc785024319ae1c5c34153a 100644 (file)
@@ -302,6 +302,10 @@ tplink,cpe210-v3)
 meraki,mr16)
        ucidef_set_led_netdev "wan" "WAN" "green:wan" "eth0"
        ;;
+moxa,awk-1137c)
+       ucidef_set_led_switch "wan" "LAN1" "green:lan1" "switch0" "0x02"
+       ucidef_set_led_switch "lan" "LAN2" "green:lan2" "switch0" "0x04"
+       ;;
 netgear,wnr2200-8m|\
 netgear,wnr2200-16m)
        ucidef_set_led_netdev "wan-amber" "WAN (amber)" "amber:wan" "eth0"
index d18eddf5b74ef0b8b25e5d62311ee3c65a79fe5b..64869701c6686d9caf37ac9658854963226f05aa 100644 (file)
@@ -240,7 +240,8 @@ ath79_setup_interfaces()
        ubnt,routerstation)
                ucidef_set_interfaces_lan_wan "eth1" "eth0"
                ;;
-       comfast,cf-e375ac)
+       comfast,cf-e375ac|\
+       moxa,awk-1137c)
                ucidef_add_switch "switch0" \
                        "0@eth0" "1:wan" "2:lan"
                ;;
@@ -731,6 +732,11 @@ ath79_setup_macs()
                lan_mac=$(mtd_get_mac_encrypted_deco $(find_mtd_part config))
                label_mac=$lan_mac
                ;;
+       moxa,awk-1137c)
+               lan_mac=$(mtd_get_mac_ascii u-boot-env mac_addr)
+               wan_mac=$(mtd_get_mac_ascii u-boot-env mac_addr)
+               label_mac=$lan_mac
+               ;;
        nec,wf1200cr|\
        nec,wg1200cr)
                lan_mac=$(mtd_get_mac_ascii devdata "lanmac")
index c46573ece5448ea6758cd0177e5adfc813dff9e2..3b089885b31414d28cb9a102f0092393a30b66c2 100644 (file)
@@ -62,6 +62,10 @@ case "$FIRMWARE" in
                caldata_extract "art" 0x1000 0x440
                ath9k_patch_mac $(mtd_get_mac_ascii u-boot-env ethaddr)
                ;;
+       moxa,awk-1137c)
+               caldata_extract "art" 0x1000 0x440
+               ath9k_patch_mac $(mtd_get_mac_ascii u-boot-env mac_addr)
+               ;;
        nec,wg800hp)
                caldata_extract "art" 0x1000 0x440
                ath9k_patch_mac $(mtd_get_mac_text board_data 0x680)
index 7807559d81033368d73fdfe2a4f1277054b47742..01c446b1bb47caee76dc0838a530941529e587a4 100755 (executable)
@@ -8,6 +8,9 @@ boot() {
        adtran,bsap1840)
                fconfig -s -w -d $(find_mtd_part "RedBoot config") -n boot_cntb -x 0
                ;;
+       moxa,awk-1137c)
+               fw_setenv fwr_verify 0
+               ;;
        qihoo,c301)
                local n=$(fw_printenv activeregion | cut -d = -f 2)
                fw_setenv "image${n}trynum" 0
index 5fa23e8eb68c3ebcad0fe528e4bdc031b824dc7d..8b39a17eb0cd9dfcb5893067efdbe40fc002bbfd 100644 (file)
@@ -28,6 +28,9 @@ preinit_set_mac_address() {
        fortinet,fap-221-b)
                ip link set dev eth0 address $(mtd_get_mac_text u-boot 0x3ff80 12)
                ;;
+       moxa,awk-1137c)
+               ip link set dev eth0 address $(mtd_get_mac_ascii u-boot-env mac_addr)
+               ;;
        tplink,deco-s4-v2)
                base_mac=$(mtd_get_mac_encrypted_deco $(find_mtd_part config))
                ip link set dev eth0 address $base_mac
index 1a558c30a05433c585cdf81967e265b1f7711af7..6a2131f5ae0cdebe56bc157a57dfcfb565f059dd 100644 (file)
@@ -9,6 +9,7 @@ DEVICE_VARS += ADDPATTERN_ID ADDPATTERN_VERSION
 DEVICE_VARS += SEAMA_SIGNATURE SEAMA_MTDBLOCK
 DEVICE_VARS += KERNEL_INITRAMFS_PREFIX DAP_SIGNATURE
 DEVICE_VARS += EDIMAX_HEADER_MAGIC EDIMAX_HEADER_MODEL
+DEVICE_VARS += MOXA_MAGIC MOXA_HWID
 DEVICE_VARS += OPENMESH_CE_TYPE ZYXEL_MODEL_STRING
 DEVICE_VARS += SUPPORTED_TELTONIKA_DEVICES
 
@@ -1819,6 +1820,19 @@ define Device/mercury_mw4530r-v1
 endef
 TARGET_DEVICES += mercury_mw4530r-v1
 
+define Device/moxa_awk-1137c
+  SOC := ar9344
+  DEVICE_MODEL := AWK-1137C
+  DEVICE_VENDOR := MOXA
+  MOXA_MAGIC := 0x8919123028877702
+  MOXA_HWID := 0x01080000
+  IMAGE_SIZE := 14336k
+  DEVICE_PACKAGES := uboot-envtools
+  IMAGES += factory.rom
+  IMAGE/factory.rom := $$(IMAGE/sysupgrade.bin) | moxa-encode-fw
+endef
+TARGET_DEVICES += moxa_awk-1137c
+
 define Device/nec_wx1200cr
   DEVICE_VENDOR := NEC
   IMAGE/default := append-kernel | pad-offset $$$$(BLOCKSIZE) 64 | append-rootfs