Support for Zyxel NWA90AX

I have a Zyxel NWA90AX (without "Pro" suffix) access point and would like to get OpenWrt running on it.

OpenWrt already has support for the NWA90AX Pro, which has the same hardware has the NWA50AX Pro - but the "Pro" versions have completely different hardware than the non-pro ones.

OpenWrt also has support for the NWA50AX, which has the exact same hardware as my NWA90AX. I confirmed this by a) inspecting the FCC ID I8811AXAP22A photos and b) finding an official Zyxel support page stating this:

NWA90AX: Identical hardware as in NWA50AX, but with added features like Captive portal for Guest access and WPA Enterprise for AD/Radius (Credential) authentication.

So the difference between 50 and 90 is only a feature unlocked in software.

(There is another thread about this device, but it's a different revision: mine has FCC ID I8811AXAP22A, Zyxel NWA90AX PoE AP has I8811AXAP22 (without the A at the end)


I updated the access point to the latest firmware version V7.10(3) dated 2025-06-29 03:25:20 to get the Current Image num to 1 as suggested by the wiki, and then tried flashing the OpenWrt NWA50AX firmware.

At first I got an error

errno: -25000
errmsg: Warning ULCGI unalbe to parse CGI query!

but the wiki told me to make the file name shorter, and that indeed helped getting around this problem.

But with a shorter name, I also get an error:

errno: -25007
errmsg: Firmware content error!

The firmware is not accepted; and this is where I am stuck at.


I looked at the commit that added NWA90AX Pro support and did the same for my NWA90AX in target/linux/ramips/image/mt7621.mk - simply adding DEVICE_ALT0_VENDOR + DEVICE_ALT0_MODEL.
This let me select the NWA90AX in make menuconfig, but the firmware I compiled did yield the same upload error.


Do the Zyxel devices need a certain flag set to discover that the firmware is indeed for them, and not some other model in the same line?

The commit that added support for the NWA50AX contains a call to a script mkits-zyxel-fit.sh that defines compat-models. It is called from mt7621.mk as follows:

define Build/zyxel-nwa-fit                  
        $(TOPDIR)/scripts/mkits-zyxel-fit.sh \
                $@.its $@ "6b e1 6f e1 ff ff ff ff ff ff"
        PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage -f $@.its $@.new
        @mv $@.new $@
endef

There is no explanation for the structure of 6b e1 6f e1 ff ff ff ff ff ff, though.
It looks to me as if 2 models are in there - 6b and 6f, with e1 being a separator and the ff could be the end-of-data marker. But this compat-models key seems to be unique to the Zyxel DTS file; I've found no other mentions of this on the internet.

I could flash an official NWA50AX 7.10(ACCV.3)C0 firmware on my NWA90AX without any problems, so there does not seem to be a check for whitelisted devices taking place - and the problem must be elsewhere.

When viewing official and OpenWRT firmware files in a hex editor, something sticks out:
The end contains a checksum, and something that looks like what the hash/checksum is built with:

|...*firmware....|
|.........../none|
|........hash....|
|....... ...J..;.|
|..$T.J......c<{.|
|..51.6..........|
|.......;sha256..|
|................|
|....description.|
|compat-models.fw|
|_version.data.ty|
|pe.compression.a|
|lgo.timestamp.va|
|lue.............|

The OpenWrt builds have a something off:

|............firm|
|ware............|
|...3none........|
|hash@1..........|
|...N6..ta.C.@l..|
|.....;9.........|
|...?sha1........|
|................|
|description.comp|
|at-models.#addre|
|ss-cells.data.ty|
|pe.compression.a|
|lgo.timestamp.va|
|lue.............|

This #address-cells looks suspicious. Does it have to be there?


Looks like this is just the dts.

I wonder if the files work at all, since all firmwares since 22.03.7 bring the same "-25007 / Firmware content error!":

  • openwrt-22.03.7-ramips-mt7621-zyxel_nwa50ax-squashfs-factory.bin
  • openwrt-23.05.6-ramips-mt7621-zyxel_nwa50ax-squashfs-factory.bin
  • openwrt-24.10.2-ramips-mt7621-zyxel_nwa50ax-squashfs-factory.bin

Could someone confirm that the factory images work on a NWA50AX?

I tried to downgrade to an earlier official firmware and got the "errno: -25007 / errmsg: Firmware content error!" with all lower firmware versions.

My current official firmware is V7.10(3), and downgrading to the following NWA50AX firmware versions gave me this error:

It looks to me as if the firmware has a downgrade protection in place, which prevents installing OpenWrt firmware - just as it prevents installing older firmware.

That downgrade protection does not seem to be in earlier firmware versions: A libe.net blog post reports a working upgrade from V6.29 (ABYW.1), which a github issue confirms.


Uploading NWA90AX_7.00(ACCV.2)C0 from https://download.zyxel.com/NWA90AX/firmware/NWA90AX_7.00(ACCV.2)C0.zip did work, and the web interface now shows Firmware Version: V7.00(2) / 2024-08-15 01:59:19

Downgrading to a NWA90AX firmware NWA90AX_6.29(ACCV.4)C0 (from https://download.zyxel.com/NWA90AX/firmware/NWA90AX_6.29(ACCV.4)C0.zip) works - so it's no downgrade protection, but a check if the firmware is for the right device.

When trying to flash firmware 7.10#3 for the NWA50AX on the currently installed NWA90AX firmware with the same version, I saw something in my browser's network inspector:

----- kernel cmdline -----
console=ttyS0,115200 loglevel=1 bootImage=1 bootVer=V1.03 rootfstype=squashfs,jffs2
------- FW version -------
FIRMWARE_VER=6.29(ACCV.4)
BUILD_DATE=2024-01-10 14:37:56
MODEL_ID=NWA90AX
COMPATIBLE_PRODUCT_MODEL_0=77E1
COMPATIBLE_PRODUCT_MODEL_1=FFFF
COMPATIBLE_PRODUCT_MODEL_2=FFFF
COMPATIBLE_PRODUCT_MODEL_3=FFFF
COMPATIBLE_PRODUCT_MODEL_4=FFFF

77E1 is the model number code!

After adding that to the scripts/mkits-zyxel-fit.sh call in target/linux/ramips/image/mt7621.mk and re-building the firmware, I could flash it!

I'll submit a patch: https://github.com/openwrt/openwrt/pull/20308

2 Likes