Adding OpenWrt support for Zyxel EX5601-T0

If I understand correctly, this is basically the same as the VMG8825, except the signature is calculated with only the root file inside the firmware instead of the whole firmware image. I tried this by extracting root, calculating a signature and adding it to zyfwinfo. Sadly, this didn't work. I found the code you sent in 'image.mk'. There are two more files that seem interesting: image-zycommands.mk and zyfwinfo.h, but that's a bit beyond my knowledge. I hope you can make sense of it. Thanks for your effort!

Ok, thank you for clarification. Im glad we have way to flash locked devices now.

from my experience the zyfwinfo is simply a volume that is written inside the ubi/ubi2 MTD which contains metadata on the firmware version.
If you get for example the acdz.2 sysupgrade and you open it with any archive manager you will see the following inside:
image
that zyfwinfo contains only metadata about the firmware version.
The zyfwinfo volume is checked by zloader at boot in both the ubi/ubi2 mtds.

If you look at the ./scripts/sysupgrade-zytar.sh you will see that it literally copies that file side by side with rootfs, kernel, CONTROL, and zydefault (not needed as it is only a volume that contains default router configuration overlay).

mkdir -p "${tmpdir}/sysupgrade-${board}"
echo "BOARD=${board}" > "${tmpdir}/sysupgrade-${board}/CONTROL"

[ -z "${zyfwinfo}" ] || cp "${zyfwinfo}" "${tmpdir}/sysupgrade-${board}/zyfwinfo"
[ -z "${zydefault}" ] || cp "${zydefault}" "${tmpdir}/sysupgrade-${board}/zydefault"

if [ -n "${rootfs}" ]; then
	case "$( get_fs_type ${rootfs} )" in
	"squashfs")
		dd if="${rootfs}" of="${tmpdir}/sysupgrade-${board}/root" bs=1024 conv=sync
		;;
	*)
		cp "${rootfs}" "${tmpdir}/sysupgrade-${board}/root"
		;;
	esac
fi
[ -z "${kernel}" ] || cp "${kernel}" "${tmpdir}/sysupgrade-${board}/kernel"

mtime=""
if [ -n "$SOURCE_DATE_EPOCH" ]; then
	mtime="--mtime=@${SOURCE_DATE_EPOCH}"
fi

(cd "$tmpdir"; tar --sort=name --owner=0 --group=0 --numeric-owner -cvf sysupgrade.tar sysupgrade-${board} ${mtime})
err="$?"
if [ -e "$tmpdir/sysupgrade.tar" ]; then
	cp "$tmpdir/sysupgrade.tar" "$outfile"
else
	err=2
fi
rm -rf "$tmpdir"

exit $err

The answer regarding the signature is inside the include/image-zycommands.mk file.
Here is where all the packaging process runs from the zyfwinfo, zydefault and signature stuff... indeed:

# reference Build/append-metadata
define Build/append-zymetadata
	if [ "$(SUPPORTED_DEVICES)" != "" ]; then \
		if [ "$(CONFIG_ZYXEL_FW_DIGITAL_SIGNATURE_V1)" = "y" ]; then \
			sh $(TOPDIR)/scripts/signature.sh $(zymetadata_json) $(KDIR)/rsa.sign $@; \
		else \
			echo $(call zymetadata_json) | fwtool -I - $@; \
		fi; \
	fi;
	[ ! -s "$(BUILD_KEY)" -o ! -s "$(BUILD_KEY).ucert" -o ! -s "$@" ] || { \
		cp "$(BUILD_KEY).ucert" "$@.ucert" ;\
		usign -S -m "$@" -s "$(BUILD_KEY)" -x "$@.sig" ;\
		ucert -A -c "$@.ucert" -x "$@.sig" ;\
		fwtool -S "$@.ucert" "$@" ;\
	}
endef

After that all the volumes are created here the sign process starts by calling sysupgrade-zytar and if CONFIG_ZYXEL_FW_DIGITAL_SIGNATURE is true than a special binary "zyimagesign" kicks in:

# reference Build/sysupgrade-tar
define Build/sysupgrade-zytar
	$(call check-files)
	echo zyfwinfo=$(KDIR)/tmp/$(IMG_PREFIX)-$(DEVICE_NAME)-$(FILESYSTEM)-zyfwinfo.bin
	echo zydefault=$(KDIR)/tmp/$(IMG_PREFIX)-$(DEVICE_NAME)-$(FILESYSTEM)-zydefault.bin
	sh $(TOPDIR)/scripts/sysupgrade-zytar.sh \
		--board $(if $(BOARD_NAME),$(BOARD_NAME),$(DEVICE_NAME)) \
		--kernel $(call param_get_default,kernel,$(1),$(IMAGE_KERNEL)) \
		--rootfs $(call param_get_default,rootfs,$(1),$(IMAGE_ROOTFS)) \
		--zyfwinfo $(KDIR)/tmp/$(IMG_PREFIX)-$(DEVICE_NAME)-$(FILESYSTEM)-zyfwinfo.bin \
		--zydefault $(KDIR)/tmp/$(IMG_PREFIX)-$(DEVICE_NAME)-$(FILESYSTEM)-zydefault.bin \
		$@
	$(if $(CONFIG_ZYXEL_FW_DIGITAL_SIGNATURE_V1), $(STAGING_DIR_HOST)/bin/zyimagesign -s $(KDIR)/rsa.sign -i $@)
endef

but to be honest I don't understand why we are still talking about the signature process for this router... with mtk_uartboot you can simply change everything...

Too the source code that zyxel provided for the acdz.2 version is missing libraries to complete a full compile process making it unuseful.

WARNING: Makefile 'package/utils/busybox/Makefile' has a build dependency on 'zcfg', which does not exist
WARNING: Makefile 'package/utils/busybox/Makefile' has a build dependency on 'libzcfg_msg', which does not exist
WARNING: Makefile 'package/utils/busybox/Makefile' has a build dependency on 'libjson', which does not exist
WARNING: Makefile 'package/utils/busybox/Makefile' has a build dependency on 'libzcfg_fe_rdm_access', which does not exist
WARNING: Makefile 'package/utils/busybox/Makefile' has a build dependency on 'libzcmd_tool', which does not exist
WARNING: Makefile 'package/utils/busybox/Makefile' has a build dependency on 'libzcfg_fe_rdm_struct', which does not exist
WARNING: Makefile 'package/utils/busybox/Makefile' has a build dependency on 'libzyutil', which does not exist

I'll try the steps with mtk_uartboot. To be clear: my goal is not to have OpenWRT or a different bootloader but the original Zyxel firmware on my EX5601. If it works, is there a way to make it persistent (i.e. do I only need to do this once and not again after a reboot/reset?) or is that already the case?
Just to be sure I'll upload the relevant files from the source code I mentioned earlier.

So you want a flashable firmware for your model built from the zyxel provided source code.

Yes. Ideally, I'd like to find a way to add the signature to the pre-compiled firmware by Zyxel. I know it's a bit off-topic, but I thought the process might be similar and there is a lot of knowledge on Zyxel firmware here. I looked at several forums, mostly Italian ones, but none of them mention signature verification. It seems to be a unique TMNL feature.

Can you share how you did the tftp of the image?

  • Manual set IP to 192.168.1.254/24 on host
  • UTP cable between host and router -on one of the 1GBit ports-
  • Run a tftp server on host and offer the file you wish to upload to the device
1 Like

When i try to flash it it returns a error;
Any one know what im doing wrong :sweat_smile:
All the files are in the same place as the exe

C:\Users\xx\Downloads\mtk_uartboot-v0.1.1-x86_64-pc-windows-msvc>mtk_uartboot.exe -s COM3  --aarch64 -p bl2-mt7986-ddr4-ram.bin -f openwrt-mediatek-filogic-zyxel_ex5601-t0-ubootmod-bl31-uboot.fip
mtk_uartboot - 0.1.1
Using serial port: COM3
Handshake...
hw code: 0x7986
hw sub code: 0x8a00
hw ver: 0xca01
sw ver: 0x1
Baud rate set to 460800
sending payload to 0x201000...
Checksum: 0xeefd
Setting baudrate back to 115200
Jumping to 0x201000 in aarch64...
Waiting for BL2. Message below:
==================================
NOTICE:  BL2: v2.10.0   (release):v2.10.0-mtk
NOTICE:  BL2: Built : 13:17:14, Mar  1 2024
NOTICE:  WDT: Cold boot
NOTICE:  WDT: disabled
NOTICE:  CPU: MT7986 (2000MHz)
NOTICE:  EMI: Using DDR4 settings
NOTICE:  EMI: Detected DRAM size: 1024MB
NOTICE:  EMI: complex R/W mem test passed
NOTICE:  Starting UART download handshake ...
==================================
BL2 UART DL version: 0x10
Baudrate set to: 921600
thread 'main' panicked at src\bl2.rs:46:13:
returned data isn't the same. Tx: [0, 15, 242, 241] Rx: [0, 14, 224, 241]
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

try without -f openwrt-mediatek-filogic-zyxel_ex5601-t0-ubootmod-bl31-uboot.fip

Looks a bit better atleast no error;

C:\Users\xx\Downloads\mtk_uartboot-v0.1.1-x86_64-pc-windows-msvc>mtk_uartboot.exe -s COM3  --aarch64 -p bl2-mt7986-ddr4-ram.bin
mtk_uartboot - 0.1.1
Using serial port: COM3
Handshake...
hw code: 0x7986
hw sub code: 0x8a00
hw ver: 0xca01
sw ver: 0x1
Baud rate set to 460800
sending payload to 0x201000...
Checksum: 0xeefd
Setting baudrate back to 115200
Jumping to 0x201000 in aarch64...

Your first command is good. You need to load the fip (uboot). Try hard setting the baudrate to 115200 and check your cable.

1 Like

Got it running in the RAM now.
Lets see how to install the image to have to permantly running

update installed Luci to have a webgui.

One question;
Is it just a matter of installing one of these to make to startup by default with OpenWRT

image

Don't install LuCI to the initial image. You have to format, partition and rewrite your flash-memory. After you are booted into OpenWRT, you have to get the mtd-device writeable. You can do it by downloading and loading mtd-rw.ko. After that, you have to format /dev/mtd5 as UBI, re-attach, and make a two seperate volumes for uboot. Ex.: 128KiB in size. Create a third partition that needs to contain the openwrt-recovery-image (ex: zyxel_ex5601-t0-ubootmod-initramfs-recovery.itb) and can fit in this partition (ex.: 10MB). Download preloader and uboot and flash them respectively to the bl2- and fip-partition. After that, write the firmware. You can use the sysupgrade-file and use the sysupgrade command.

So, you need to wget/scp/ftp/... to /tmp :

  • openwrt-mediatek-filogic-zyxel_ex5601-t0-ubootmod-preloader-preloader.bin
  • openwrt-mediatek-filogic-zyxel_ex5601-t0-ubootmod-preloader-bl31-uboot.fip
  • openwrt-mediatek-filogic-zyxel_ex5601-t0-ubootmod-preloader-squashfs-sysupgrade.itb
  • openwrt-mediatek-filogic-zyxel_ex5601-t0-ubootmod-initramfs-recovery.itb

Creating partitions can be done with ubimkvol, flashing to partition you can use ubiupdatevol.

I got it working on mine now as well :slight_smile:

Only problem I have is that the 5G wireless doesn’t seem to work.

After adding a SSID it doesn’t turn on the led and there is network visible in scans. It keep saying it’s disabled

EDIT: When setting a fixed channel instead of auto and the bandwidth to 80Mhz instead of 160Mhz. It does also work for the 5G

Tue Mar 19 16:26:48 2024 daemon.notice hostapd: Set new config for phy phy1: /var/run/hostapd-phy1.conf
Tue Mar 19 16:26:48 2024 daemon.notice hostapd: Restart interface for phy phy1
Tue Mar 19 16:26:48 2024 daemon.notice hostapd: Configuration file: data: driver=nl80211 logger_syslog=127 logger_syslog_level=2 logger_stdout=127 logger_stdout_level=2 hw_mode=a beacon_int=100 tx_queue_data2_burst=2.0 #num_global_macaddr=1 ieee80211n=1 ht_coex=0 ht_capab=[HT40+][LDPC][SHORT-GI-20][SHORT-GI-40][TX-STBC][RX-STBC1][MAX-AMSDU-7935] ieee80211ac=1 vht_oper_chwidth=2 vht_oper_centr_freq_seg0_idx=acs_survey vht_capab=[RXLDPC][SHORT-GI-80][SHORT-GI-160][TX-STBC-2BY1][SU-BEAMFORMER][SU-BEAMFORMEE][MU-BEAMFORMER][MU-BEAMFORMEE][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN][RX-STBC-1][SOUNDING-DIMENSION-4][BF-ANTENNA-4][VHT160][MAX-MPDU-11454][MAX-A-MPDU-LEN-EXP7] ieee80211ax=1 he_oper_chwidth=2 he_oper_centr_freq_seg0_idx=acs_survey he_su_beamformee=1 he_bss_color=128 he_spr_sr_control=3 he_default_pe_duration=4 he_rts_threshold=1023 he_mu_edca_qos_info_param_count=0 he_mu_edca_qos_info_q_ack=0 he_mu_edca_qos_info_queue_request=0 he_mu_edca_qos_info_txop_request=0 he_mu_edca_ac_be_aifsn=8 he_mu_edca_ac_be_aci=0 he_mu_edca_ac_
Tue Mar 19 16:26:48 2024 daemon.notice netifd: Wireless device 'radio1' is now up
Tue Mar 19 16:26:48 2024 daemon.notice hostapd: ACS: Automatic channel selection started, this may take a bit
Tue Mar 19 16:26:48 2024 daemon.notice hostapd: phy1-ap0: interface state UNINITIALIZED->ACS
Tue Mar 19 16:26:48 2024 daemon.notice hostapd: phy1-ap0: ACS-STARTED
Tue Mar 19 16:26:50 2024 daemon.info dnsmasq[1]: read /etc/hosts - 12 names
Tue Mar 19 16:26:50 2024 daemon.info dnsmasq[1]: read /tmp/hosts/dhcp.cfg01411c - 4 names
Tue Mar 19 16:26:50 2024 daemon.info dnsmasq-dhcp[1]: read /etc/ethers - 0 addresses
Tue Mar 19 16:26:51 2024 daemon.warn odhcpd[1730]: No default route present, overriding ra_lifetime!
Tue Mar 19 16:26:52 2024 daemon.err hostapd: ACS: Failed to compute ideal channel
Tue Mar 19 16:26:52 2024 daemon.err hostapd: Interface initialization failed
Tue Mar 19 16:26:52 2024 daemon.notice hostapd: phy1-ap0: interface state ACS->DISABLED
Tue Mar 19 16:26:52 2024 daemon.notice hostapd: phy1-ap0: AP-DISABLED
Tue Mar 19 16:26:52 2024 daemon.err hostapd: ACS: Possibly channel configuration is invalid, please report this along with your config file.
Tue Mar 19 16:26:52 2024 daemon.err hostapd: ACS: Failed to start
Tue Mar 19 16:26:52 2024 daemon.notice hostapd: phy1-ap0: AP-DISABLED

160mhz channel width runs always on DFS mode. It can take while to router bring up 5g interface. 160mhz works fine here.

I confirm, it works for me too

I was to inpatient, works for me now to.

One last question, sorry for all the questions as OpenWRT is new for me as a OS.

It now runs a snapshot version; OpenWrt SNAPSHOT (r25580-85ad6b9569)

according to the firmware selector there is newer version; openwrt-23.05.2-mediatek-filogic-zyxel_ex5601-t0-stock-squashfs-sysupgrade.

When I upload the file its fives an error that its not supported. Is this a false positive and can I force the upgrade or not.

Snapshots are newer than 23.05.2

Too you are running the uboot-mod .. so you have to stick with that. Don't mix or flash the stock version which requires stock partitioning.