[Guide] Installing and Configuring OpenWrt 25.x on ZBT-Z800AX with Quectel RM520N-GL

Introduction
This guide details the complete installation and configuration of OpenWrt 25.12.0-rc5 on the ZBT-Z800AX router. It specifically focuses on the initial TFTP flashing process, fixing the U-Boot kernel panic bootloop encountered after a fresh flash, and configuring the internal M.2 Quectel RM520N-GL 5G modem. Firmware images for Z800AX are avaliable here firmware-selector.openwrt.org

In many IPQ807x devices, the stock bootloader cannot directly "understand" or correctly partition the NAND for a full OpenWrt sysupgrade image. By flashing the .itb (Image Tree Blob) file first, you are booting a temporary initramfs version of OpenWrt directly into the router's RAM. This provides a fully functional Linux environment with the necessary tools (like sysupgrade) to safely and correctly write the permanent firmware to the internal flash.
Z800AX have 8MB SPI flash + 256 MB NAND storage.

Currently, the default OpenWrt sysupgrade image for the Z800AX lacks automated U-Boot environment mapping, which results in a hard bootloop after flashing. Furthermore, the M.2 slot routes the modem over the USB 3.0 bus rather than the PCIe/MHI bus, requiring manual installation of the correct USB driver stacks.

You will need usb TTL adapter 3.3V and terminal program TeraTerm or putty with serial port settings 115200, 8N1. Z800AX have easy accessible UART port with 3 dupont pins (GND,TX,RX)

Part 0: Initial Flashing and TFTP Recovery

Before proceeding to the environment fixes, you must get the firmware onto the device. If you are recovering a "bricked" unit or performing the first install from the stock QSDK, use a TFTP server.

Part 0: The Two-Step Installation (Initramfs to Sysupgrade)

We use a two-step process to transition from the stock QSDK environment to vanilla OpenWrt. The U-Boot environment is too limited to handle complex NAND partitioning, so we first boot a temporary "helper" environment.

Step 0.1: Booting the Initramfs (.itb)

The .itb file is a Flattened Image Tree (FIT) that contains the kernel and a small RAM-based root filesystem. We load this into RAM to gain access to the sysupgrade utility. This file is named as kernel at firmware selector kernel.itb

  1. Connect your PC to a LAN port on the Z800AX and set your static IP to 192.168.1.10.
  2. Place the .itb and sysupgrade.bin files in your TFTP server's root directory.
  3. Interrupt the U-Boot process via UART (115200 8N1) and configure the network:

setenv serverip 192.168.1.10

setenv ipaddr 192.168.1.1

saveenv

Transfer the image from your PC to the router's RAM

tftpboot 0x44000000 openwrt-ipq807x-zbtlink_zbt-z800ax-initramfs-uImage.itb

Boot the image from RAM (does not flash to NAND yet)

bootm 0x44000000

The Permanent Flash (Sysupgrade)

Once the router boots into the temporary OpenWrt environment (accessible at 192.168.1.1), you must perform the permanent installation.

  1. Transfer the sysupgrade.bin to the router's /tmp directory using SCP or go directly to luci web interface and upload firmware from there:

scp openwrt-z800ax-sysupgrade.bin root@192.168.1.1:/tmp/.

  1. SSH into the router and run the final flash command:

sysupgrade -n /tmp/openwrt-z800ax-sysupgrade.bin.

Part 1: Fixing the U-Boot Environment (Resolving Kernel Panics)

The Problem: When the stock Qualcomm QSDK firmware boots, its proprietary bootloader script (bootipq) dynamically passes the partition boundaries and root filesystem location to the kernel. When you flash a vanilla OpenWrt sysupgrade image, this script is bypassed. The OpenWrt kernel starts blind, cannot find the rootfs block, throws a VFS: Cannot open root device "/dev/ubiblock0_1" panic, and enters an infinite reboot loop.

Here we must manually define the partition layout (mtdparts) and inject the OpenWrt kernel arguments (bootargs) directly into the U-Boot environment variables.

1. While at the IPQ807x# uboot prompt, execute the following commands :

To define the kernel boot arguments (tells VFS where to find the squashfs root)

setenv bootargs 'console=ttyMSM0,115200n8 ubi.mtd=rootfs root=mtd:ubi_rootfs rootfstype=squashfs rootwait'

2. Define the boot sequence (injects the partition map, mounts the UBI, reads the kernel to RAM, and boots)

setenv bootcmd 'setenv mtdids nand0=nand0; setenv mtdparts mtdparts=nand0:0x3400000@0x0(rootfs); ubi part rootfs && ubi read 0x44000000 kernel && bootm 0x44000000'

3. Commit the variables to the SPI flash environment

saveenv

4. Perform a cold reboot

reset

After this rotuer should boot normally and luci web should be avaliable at http://192.168.1.1

Part 2: Installing the Quectel RM520N-GL 5G Modem

The Z800AX routes the M.2 cellular module over the internal USB 3.0 bus, not the PCIe bus. A fresh OpenWrt 25 installation lacks the required USB drivers and the ModemManager daemon to operate it.

  1. Provide Temporary Internet: Connect the Z800AX to an existing network via the WAN Ethernet port (or configure a temporary Wi-Fi client connection, use wifi interface on router in client mode and connect it to your phone wifi hotspot or some other wifi network, don't forget to configure default route) so it can download packages.

  2. Install Drivers: Connect to the router via SSH and utilize the apk package manager (the new standard in OpenWrt 25+) to fetch the USB serial modules, QMI drivers, and ModemManager stack.

apk update

apk add usbutils usb-modeswitch kmod-usb-serial-option kmod-usb-net-qmi-wwan kmod-usb-net-cdc-mbim kmod-usb-net-cdc-mbim

apk add modemmanager luci-proto-modemmanager

  1. Reboot: The router must be restarted to allow the kernel to bind the new USB drivers to the M.2 hardware.

reboot

  1. Verify Hardware Detection: Reconnect via SSH and confirm the modem is recognized on the bus and claimed by the daemon:

lsusb
mmcli -L

Part 3: LuCI Network Configuration

With the backend fully operational, you can configure the connection through the web interface.

  1. Log into LuCI (192.168.1.1).
  2. Navigate to Network -> Interfaces and click Add new interface.
  3. Name the interface wwan5g and select ModemManager as the Protocol.
  4. Click Create interface. In the resulting configuration window:
  • Modem Device: Select the Quectel RM520N-GL.
  • APN: Enter your specific carrier APN (e.g., internet).
  • PIN: Leave blank unless your SIM has an active hardware lock.
  1. Click the Firewall Settings tab and assign the interface to the wan zone.
  2. Click Save, followed by Save & Apply on the main page.

1 Like

Here is output from mtdparts and other various commands and link to official stock vendor OpenWrt firmware.

IPQ807x# mtdparts



device nand0 <nand0>, # parts = 1

 #: name                size            offset          mask_flags

 0: fs                  0x07400000      0x00000000      0



active partition: nand0,0 - (fs) 0x07400000 @ 0x00000000



defaults:

mtdids  : none

mtdparts: none

IPQ807x# printenv

baudrate=115200

bootargs=console=ttyMSM0,115200n8 ubi.mtd=rootfs root=mtd:ubi_rootfs rootfstype=squashfs rootwait

bootcmd=bootipq

bootdelay=2

eth1addr=f8:5e:3c:6b:c9:41

eth2addr=f8:5e:3c:6b:c9:42

eth3addr=f8:5e:3c:6b:c9:43

eth4addr=f8:5e:3c:6b:c9:44

ethact=eth0

ethaddr=f8:5e:3c:6b:c9:40

fdt_high=0x4A400000

fdtcontroladdr=4a972770

flash_type=7

fsbootargs=ubi.mtd=rootfs root=mtd:ubi_rootfs rootfstype=squashfs

ipaddr=192.168.1.11

machid=8010008

mtddevname=fs

mtddevnum=0

mtdids=nand0=nand0

mtdparts=mtdparts=nand0:0x7400000@0x0(fs),

netmask=255.255.255.0

partition=nand0,0

serverip=192.168.1.10

soc_hw_version=200d0200

soc_version_major=2

soc_version_minor=0

stderr=serial@78B3000

stdin=serial@78B3000

stdout=serial@78B3000



Environment size: 784/65532 bytes
Format: Log Type - Time(microsec) - Message - Optional Info
Log Type: B - Since Boot(Power On Reset),  D - Delta,  S - Statistic
S - QC_IMAGE_VERSION_STRING=BOOT.BF.3.3.1-00163
S - IMAGE_VARIANT_STRING=HAABANAZA
S - OEM_IMAGE_VERSION_STRING=CRM
S - Boot Config, 0x000002e1
B -       203 - PBL, Start
B -      2739 - bootable_media_detect_entry, Start
B -      2886 - bootable_media_detect_success, Start
B -      2890 - elf_loader_entry, Start
B -     11380 - auth_hash_seg_entry, Start
B -     11623 - auth_hash_seg_exit, Start
B -    250722 - elf_segs_hash_verify_entry, Start
B -    311404 - PBL, End
B -    324001 - SBL1, Start
B -    376034 - GCC [RstStat:0x10, RstDbg:0x600000] WDog Stat : 0x4
B -    382531 - pm_device_init, Start
B -    504165 - PM_SET_VAL:Skip
D -    121146 - pm_device_init, Delta
B -    506574 - pm_driver_init, Start
D -      5337 - pm_driver_init, Delta
B -    512918 - clock_init, Start
D -      2104 - clock_init, Delta
B -    516914 - boot_flash_init, Start
D -      3873 - boot_flash_init, Delta
B -    524569 - boot_config_data_table_init, Start
D -      1006 - boot_config_data_table_init, Delta - (575 Bytes)
B -    534390 - Boot Setting :  0x00000618
B -    538203 - CDT version:2,Platform ID:8,Major ID:1,Minor ID:0,Subtype:8
B -    545126 - sbl1_ddr_set_params, Start
B -    548939 - CPR configuration: 0x30c
B -    552294 - cpr_init, Start
B -    555161 - Rail:0 Mode: 5 Voltage: 808000
B -    560285 - CL CPR settled at 760000mV
B -    563121 - Rail:1 Mode: 5 Voltage: 880000
B -    567391 - Rail:1 Mode: 7 Voltage: 920000
D -     16439 - cpr_init, Delta
B -    574193 - Pre_DDR_clock_init, Start
B -    578280 - Pre_DDR_clock_init, End
B -    581574 - DDR Type : PCDDR4
B -    588314 - do ddr sanity test, Start
D -      1037 - do ddr sanity test, Delta
B -    592127 - DDR: Start of HAL DDR Boot Training
B -    596763 - DDR: End of HAL DDR Boot Training
B -    602527 - DDR: Checksum to be stored on flash is 1632879862
B -    612867 - Image Load, Start
D -    335591 - QSEE Image Loaded, Delta - (1376536 Bytes)
B -    948550 - Image Load, Start
D -        30 - SEC Image Loaded, Delta - (0 Bytes)
B -    956236 - Image Load, Start
D -      9790 - DEVCFG Image Loaded, Delta - (26148 Bytes)
B -    966118 - Image Load, Start
D -     25986 - RPM Image Loaded, Delta - (86660 Bytes)
B -    992195 - Image Load, Start
D -    137250 - APPSBL Image Loaded, Delta - (559810 Bytes)
B -   1129537 - QSEE Execution, Start
D -        61 - QSEE Execution, Delta
B -   1135362 - USB D+ check, Start
D -         0 - USB D+ check, Delta
B -   1141737 - SBL1, End
D -    820054 - SBL1, Delta
S - Flash Throughput, 4426 KB/s  (2050401 Bytes,  463257 us)
S - DDR Frequency, 600 MHz
S - Core 0 Frequency, 1651 MHz


U-Boot 2016.01 (Nov 05 2021 - 12:37:30 +0800)

DRAM:  smem ram ptable found: ver: 1 len: 4
1 GiB
NAND:  Could not find nand_gpio in dts, using defaults
ONFI device found
ID = 1190aac2
Vendor = c2
Device = aa
qpic_nand: changing oobsize to 80 from 128 bytes
SPI_ADDR_LEN=3
SF: Detected MX25U6435F with page size 256 Bytes, erase size 64 KiB, total 8 MiB
ipq_spi: page_size: 0x100, sector_size: 0x10000, size: 0x800000
264 MiB
MMC:   sdhci: Node Not found, skipping initialization

PCI1 is not defined in the device tree
In:    serial@78B3000
Out:   serial@78B3000
Err:   serial@78B3000
machid: 8010008
MMC Device 0 not found
eth5 MAC Address from ART is not valid
Hit any key to stop autoboot:  0 

Net:   MAC0 addr:f8:5e:3c:6b:c9:40
PHY ID1: 0x4d
PHY ID2: 0xd0b1
EDMA ver 1 hw init
Num rings - TxDesc:1 (0-0) TxCmpl:1 (7-7)
RxDesc:1 (15-15) RxFill:1 (7-7)
ipq807x_edma_alloc_rings: successfull
ipq807x_edma_setup_ring_resources: successfull
ipq807x_edma_configure_rings: successfull
ipq807x_edma_hw_init: successfull
eth0
IPQ807x# help
?       - alias for 'help'
aes_256 - AES 256 CBC/ECB encryption/decryption
aq_load_fw- LOAD aq-fw-binary
aq_phy_restart- Restart Aquantia phy
base    - print or set address offset
bdinfo  - print Board Info structure
bootipq - bootipq from flash device
bootm   - boot application image from memory
bootp   - boot image via network using BOOTP/TFTP protocol
bootz   - boot Linux zImage image from memory
canary  - test stack canary
chpart  - change active partition
cmp     - memory compare
cp      - memory copy
crc32   - checksum calculation
dhcp    - boot image via network using DHCP/TFTP protocol
dm      - Driver model low level access
echo    - echo args to console
env     - environment handling commands
erase   - erase FLASH memory
exectzt - execute TZT

exit    - exit script
false   - do nothing, unsuccessfully
fdt     - flattened device tree utility commands
flash   - flash part_name 
        flash part_name load_addr file_size 

flasherase- flerase part_name 

flinfo  - print FLASH memory information
fuseipq - fuse QFPROM registers from memory

go      - start application at address 'addr'
help    - print command description/usage
i2c     - I2C sub-system
imxtract- extract a part of a multi-image
ipq_mdio- IPQ mdio utility commands
is_sec_boot_enabled- check secure boot fuse is enabled or not

itest   - return true/false on integer compare
loop    - infinite loop on address range
md      - memory display
mii     - MII utility commands
mm      - memory modify (auto-incrementing address)
mmc     - MMC sub system
mmcinfo - display MMC info
mtdparts- define flash/nand partitions
mtest   - simple RAM read/write test
mw      - memory write (fill)
nand    - NAND sub-system
nboot   - boot from NAND device
nm      - memory modify (constant address)
pci     - list and access PCI Configuration Space
ping    - send ICMP ECHO_REQUEST to network host
printenv- print environment variables
protect - enable or disable FLASH write protection
reset   - Perform RESET of the CPU
run     - run commands in an environment variable
runmulticore- Enable and schedule secondary cores
saveenv - save environment variables to persistent storage
secure_authenticate- authenticate the signed image

setenv  - set environment variables
sf      - SPI flash sub-system
showvar - print local hushshell variables
sleep   - delay execution for some time
smeminfo- print SMEM FLASH information
source  - run script from memory
test    - minimal test like /bin/sh
tftpboot- boot image via network using TFTP protocol
tftpput - TFTP put command, for uploading files to a server
true    - do nothing, successfully
uart    - UART sub-system
ubi     - ubi commands
usb     - USB sub-system
usbboot - boot from USB device
version - print monitor, compiler and linker version
IPQ807x# showvar
HUSH_VERSION=0.01
IPQ807x# setenv ipaddr 192.168.1.1
IPQ807x# setenv serverip 192.168.1.10 
IPQ807x# tftpboot 0x44000000 openwrt-25.12.0-rc5-qualcommax-ipq807x-zbtlink_zbt-z800ax-initramfs-uImage.itb
ipq807x_eth_halt: done
eth0 PHY0 up Speed :100 Full duplex
eth0 PHY1 Down Speed :10 Half duplex
eth0 PHY2 Down Speed :10 Half duplex
eth0 PHY3 Down Speed :10 Half duplex
eth0 PHY4 up Speed :10 Full duplex
eth0 PHY5 up Speed :10 Full duplex
ipq807x_eth_init: done
Using eth0 device
TFTP from server 192.168.1.10; our IP address is 192.168.1.1
Filename 'openwrt-25.12.0-rc5-qualcommax-ipq807x-zbtlink_zbt-z800ax-initramfs-uImage.itb'.
Load address: 0x44000000
Loading: *
Got TFTP_OACK: TFTP remote port: changes from 69 to 55551
#################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ###########################
         2 MiB/s
done
Bytes transferred = 13741368 (d1ad38 hex)
ipq807x_eth_halt: done
IPQ807x# bootm 0x44000000
## Loading kernel from FIT Image at 44000000 ...
   Using 'config@hk09' configuration
   Trying 'kernel-1' kernel subimage
     Description:  ARM64 OpenWrt Linux-6.12.71
     Type:         Kernel Image
     Compression:  gzip compressed
     Data Start:   0x440000e8
     Data Size:    13693527 Bytes = 13.1 MiB
     Architecture: AArch64
     OS:           Linux
     Load Address: 0x41000000
     Entry Point:  0x41000000
     Hash algo:    crc32
     Hash value:   af5b6e1e
     Hash algo:    sha1
     Hash value:   9e61214bb0e312495122a80a603a34a6c5d4af0c
   Verifying Hash Integrity ... crc32+ sha1+ OK
## Loading fdt from FIT Image at 44000000 ...
   Using 'config@hk09' configuration
   Trying 'fdt-1' fdt subimage
     Description:  ARM64 OpenWrt zbtlink_zbt-z800ax device tree blob
     Type:         Flat Device Tree
     Compression:  uncompressed
     Data Start:   0x44d0f484
     Data Size:    46444 Bytes = 45.4 KiB
     Architecture: AArch64
     Hash algo:    crc32
     Hash value:   366ef4dc
     Hash algo:    sha1
     Hash value:   26e0bb29363adfa99f9d14f5fafd3b1bc88c5619
   Verifying Hash Integrity ... crc32+ sha1+ OK
   Booting using the fdt blob at 0x44d0f484
   Uncompressing Kernel Image ... OK
   Loading Device Tree to 4a3f1000, end 4a3ff56b ... OK
fdt-fixup: unable to find compatible node
Could not find PCI in device tree
Using machid 0x8010008 from environment

Starting kernel ...

Jumping to AARCH64 kernel via monitor
[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] Linux version 6.12.71 (builder@buildhost) (aarch64-openwrt-linux-musl-gcc (OpenWrt GCC 14.3.0 r32673-482ba7230a) 14.3.0, GNU ld (GNU Binutils) 2.44) #0 SMP Tue Feb 17 21:30:37 2026
[    0.000000] Machine model: Zbtlink ZBT-Z800AX
[    0.000000] OF: reserved mem: 0x0000000040000000..0x0000000040ffffff (16384 KiB) nomap non-reusable nss@40000000

root@OpenWrt:~# lsusb

Bus 001 Device 001: ID 1d6b:0002 Linux 6.12.71 xhci-hcd xHCI Host Controller

Bus 002 Device 001: ID 1d6b:0003 Linux 6.12.71 xhci-hcd xHCI Host Controller

Bus 002 Device 002: ID 2c7c:0801 Quectel RM520N-GL

Bus 003 Device 001: ID 1d6b:0002 Linux 6.12.71 xhci-hcd xHCI Host Controller

Bus 004 Device 001: ID 1d6b:0003 Linux 6.12.71 xhci-hcd xHCI Host Controller

root@OpenWrt:~# mmcli -L

    /org/freedesktop/ModemManager1/Modem/0 [Quectel] RM520N-GL

root@OpenWrt:~# 

Vendor official firmware in case someone wants to go back to stock is avaliable at Google drive.