OpenWrt support for Zyxel PMG5617GA, first GPON support !?

So what is the point of using that if the PON port doesn't work at all, what are you using for the WAN uplink?

Waste utilization

You can always use the Ethernet ports as WAN but that defeats the purpose of a fiber router. Anyway, I've looked around and it seems that EcoNet changed the company name and website to Airoha, a subsidiary of Mediatek. There are some commits in the mainline kernel here and here, albeit for EN7523, mentioning this so we're on the right track.


Great, what is the next step. If this is supported in Linux mainline is the hard work complete already?

I now have to figure out the recovery procedure in case I screw up and how to flash different firmwares. So far I have 3 mediums of file transfer (USB flash, Ethernet tftp and Serial UART) but I think i can only use the Serial because I'm quite limited on what the bootloader can perform, granted it's a modified U-Boot bootloader. Only the following commands are available:

decomp                              Decompress kernel image to ram.
memrl <addr>                        Read a word from addr.
memwl <addr> <value>                Write a word to addr.
dump <addr> <len>                   Dump memory content.
jump <addr>                         Jump to addr.
flash <dst> <src> <len> <oob>       Write to flash from src to dst(oob: write nand oob if 1).
xmdm <addr> <len>                   Xmodem receive to addr.
ipaddr <ip addr>                    Change modem's IP.
ddrdrv <..>                         Change DDR driving length

I'm trying to research the XMODEM protocol and command set since it's the most promising. I'll deal with building a test firmware after.

I would say that TFTP would be the fastest. XMODEM over serial is quite slow, and I would only use that if you have bricked a unit, and that's your only option. USB many ONTs don't have a USB port.

For Z-Loader, there is an ATSW command. I'm a noob at this. But does it mean there are 2 firmware/linux partitions on this device?

I'm afraid XMODEM is only used for flashing, not dumping. USB doesn't have a working driver at boot time and TFTP isn't available as a command on the bootloader so in the end I'm stuck with painstakingly copy and paste the bytes the dump and nandrd commands spew out in the terminal. There is a nice Python script that automatises that for you in here but needs some tweaking for higher memory. Turns out that Ralink, Mediatek, Econet and Airoha SoCs all share the same core silicon and command set.

During this time, I found a Nokia G-240G-E modem that has the same exact SoC so I can afford to do more messy stuff and break the device since it's nothing but a spare. Details are available here with serial dumps and chip data.

One thing I don't understand is why the nand data is mirrored onto the ram at boot time. Is it to create a ramdisk? Wouldn't that be a waste of ram memory?
Secondly, I also don't understand the purpose of kernel/root/tclinux and kernel/root/tclinux-slave if it's already copied onto the ram.
And thirdly, which way should I backup the flash? Nand seems to be lzma compressed and ram seems to have Zyxel trx headers.

Hello Alex, this is an interesting project, thanks for pursuing it!

In the past, I have dumped other devices by using picocom -g so that it will log to a text file, then I read the flash into memory and use md.b to dump memory out to console, then close picocom and manipulate the file with sed and awk to convert it into a binary. Same idea as the python script.

Regarding why nand is read into memory, maybe I'm not understanding the question, but when it's the Linux kernel, the code needs to execute from memory. Generally squashfs will stay on the flash until the file is being read, but ramdisk based builds will load the FS into memory as well.

Looking at your MTD layout, my first instinct is:

  • bootloader -> u-boot binary code
  • romfile -> Likely to be u-boot environment, worth looking at this because you don't have printenv command
  • kernel -> main linux
  • rootfs -> main squashfs + jffs2 (or UBI, I'm not sure) partition
  • tclinux -> I have no idea what this might be
  • kernel_slave -> backup linux kernel in case main one is corrupted or for updating
  • rootfs_slave -> backup root fs
  • tclinux_slave -> backup mystery fs
  • wwan -> Don't know, potentially parameters for the laser, if it is this then you definitely do not want to delete them, they're unique to each unit
  • data -> Possible an FS containing some config stuff like wifi password, might also be laser parameters
  • rom-d -> Don't know
  • reservedarea -> Don't know, might be empty, check the hex dump

The best way to know what they are is to dump each one into a series of bins and then compare the first bytes to see what it is. UBIFS starts with 55 42 49 ("UBI"), squashfs starts with 68 73 71 73 (hsqs).

I would recommend running strings on the bootloader and the romfile, you might get lucky enough that it will print the env vars for u-boot and you'll see how it's booted and how it's updated.


Awesome stuff. Regarding tclinux, that's a toolchain TrendChip and its descendants SoC (Ralink, Econet, Mediatek, Airoha) use to build and decompose firmware as discussed in here. A variant of it named tcrevange (github page here) is used but from what i've heard it's mostly unmaintained. I've tried emailing Airoha if they can provide some SDKs/Toolchains to help but to no avail so far so we have to make use of what we have.

Thanks for the links re tclinux, I've ordered a sample of an EN7526 device because I'm interested in pursuing this as well.

  1. Someone wrote a shell script in owrt to build images for this zloader:
  2. I found a rather impressive amount of documentation about ZyXEL boot process here:

Hi, thanks for your effort. I'm very interested too. I have played many OpenWRT routers. However, I don't see any OpenWRT routers with GPON support. I want to know if there is firmware for GPON part like wireless chips . You know almost all wireless chips have own firmware since wifi5. If only driver in linux kernel side is needed, this should be easier to support.

1 Like

Bootloader(U-Boot) from keenetic runs on a device with the same processor (Sercomm FG824CD).

U-Boot log
DDR3 init.
DRAMC init done.
Calculate size.
DRAM size=256MB
Set new TRFC.

7512DRAMC V1.2.2 (0)

U-Boot 1.1.3 [] (Nov 29 2019 - 18:49:25)

Board: Ralink APSoC DRAM:  256 MB
relocate_code Pointer at: 8ff8c000

Software System Reset Occurred
Set SPI Clock to 50 Mhz
spi_nand_probe: mfr_id = 0xc2, dev_id = 0x12
Using Flash ECC.
Detected SPI NAND Flash: MXIC MX35LF1G, Flash Size: 128 MB
bmt pool size: 81
BBT found, bad block count: 0
BMT & BBT Init Success
*** Warning - bad CRC, using default environment

Ralink UBoot Version:
ASIC 7512_MP (Port5<->None)
SYS_CLK: 225 MHz
DRAM component: 2048 Mbits
DRAM bus: 16 bit
Total memory: 256 MBytes
Flash component: SPI NAND Flash
Date:Nov 29 2019  Time:18:49:25
icache: sets: 512, ways:4, linesz:32, total: 64kB
dcache: sets: 256, ways:4, linesz:32, total: 32kB

 ##### The CPU freq = 900 MHZ ####
 estimate memory size = 256 Mbytes

Detected internal switch MT7530

Detected external switch MT7530
Dual image:     on
Boot active:    1
Boot backup:    1
Boot fails:     0

Please choose the operation:
   1: Load system code to SDRAM via TFTP.
   2: Load system code then write to Flash via TFTP.
   3: Boot system code via Flash (default).
   4: Enter boot command line interface.
   7: Load Boot Loader code then write to Flash via Serial.
   9: Load Boot Loader code then write to Flash via TFTP.                                                                                                                                                    0

3: System Boot system code via Flash.
## Booting image at 00060000 ...
Bad Magic Number,FFFFFFFF

Load system code then write to Flash via TFTP.

System Boot log
3: System Boot system code via Flash.

## Booting image at 00060000 ...

   Image Name:   Keenetic DSL

   Created:      2018-10-23  16:55:17 UTC

   Image Type:   MIPS Linux Kernel Image (lzma compressed)

   Data Size:    1268528 Bytes =  1.2 MB

   Load Address: 80020000

   Entry Point:  802ef100

   Verifying Checksum ... OK

   Uncompressing Kernel Image ... OK

No initrd

## Transferring control to Linux (at address 802ef100) ...

## Giving linux memsize in MB, 256

Starting kernel ...

Linux version 3.4.113 ( (gcc version 7.3.0 (crosstool-NG crosstool-ng-1.23.0-ndm-4 - NDMS Toolkit 1.0.0) ) #1 SMP Tue Oct 16 18:48:53 MSK 2018
ISPRAM0: PA=00300000,Size=00010000,enabled
EcoNet SoC: RAM: DDR3 256MB
CPU/SYS frequency: 900/225 MHz
SoC power status: Hard reset occured
CPU revision is: 00019558 (MIPS 34Kc)
Determined physical RAM map:
 memory: 0ffe0000 @ 00020000 (usable)
Wasting 1024 bytes for tracking 32 unused pages
Zone PFN ranges:
0x00000020 -> 0x00010000
Movable zone start PFN for each node
Early memory PFN ranges
    0: 0x00000020 -> 0x00010000
Detected 1 available secondary CPU(s)
Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 32 bytes
PERCPU: Embedded 7 pages/cpu @81203000 s5984 r8192 d14496 u32768
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 64992
Kernel command line: console=ttyS0,57600n8 rdinit=/sbin/init es=1
PID hash table entries: 1024 (order: 0, 4096 bytes)
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Writing ErrCtl register=0003b800
Readback ErrCtl register=0003b800
NMI base is 8124c200
Memory: 255612k/262016k available (3008k kernel code, 6404k reserved, 618k data, 212k init, 0k highmem)
Hierarchical RCU implementation.
 Using 200.000 MHz high precision timer
console [ttyS0] enabled
Calibrating delay loop... 597.60 BogoMIPS (lpj=2988032)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
Config7: 0x80080500
ISPRAM0: PA=00300000,Size=00010000,enabled
Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 32 bytes
CPU revision is: 00019558 (MIPS 34Kc)
Synchronize counters for CPU 1: done.
Brought up 2 CPUs
NET: Registered protocol family 16
PCIe RC0 no card, disable PHY
bio: create slab <bio-0> at 0
NET: Registered protocol family 8
NET: Registered protocol family 20
Switching to clocksource TC HPT
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 4, 65536 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP: reno registered
UDP hash table entries: 128 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 128 (order: 0, 4096 bytes)
NET: Registered protocol family 1
squashfs: version 4.0 (2009/01/31) Phillip Lougher
msgmni has been set to 499
io scheduler noop registered (default)
tc3162_uart: UART driver for EN751x SoC, buffer size is 4096 bytes
ttyS0 at I/O 0xbfbf0003 (irq = 1) is a TC3162
Registering NDM partitions parser
EcoNET SPI NAND driver init
Detected SPI NAND Flash: MXIC35LF1G, Flash Size: 128MB
NAND device: Manufacturer ID: 0xc2, Chip ID: 0x12 (Macronix MXIC35LF1G), 128MiB, page size: 2048, OOB size: 64
BMT pool size: 81
BBT found, bad block count: 0
BMT & BBT init success
di: active = 1, backup = 1, current = 1
15 ndmpart partitions found on MTD device EN7512-SPI_NAND
Creating 15 MTD partitions on "EN7512-SPI_NAND":
0x000000000000-0x000000020000: "U-Boot"
0x000000020000-0x000000040000: "U-Config"
0x000000040000-0x000000060000: "RF-EEPROM"
0x000000060000-0x0000001c0000: "Kernel_1"
0x0000001c0000-0x000001da0000: "RootFS_1"
mtd: device 4 (RootFS_1) set to be root filesystem
0x000000060000-0x000001da0000: "Firmware_1"
0x000001da0000-0x000001dc0000: "Config_1"
0x000001dc0000-0x000001fc0000: "Storage"
0x000001fc0000-0x000002000000: "Dump"
0x000003ae0000-0x000003b00000: "U-State"
0x000003b00000-0x000003b20000: "U-Config_res"
0x000003b20000-0x000003b40000: "RF-EEPROM_res"
0x000003b40000-0x000005880000: "Firmware_2"
0x000005880000-0x0000058a0000: "Config_2"
0x000000000000-0x0000075e0000: "Full"
tun: Universal TUN/TAP device driver, 1.6
tun: (C) 1999-2004 Max Krasnyansky <>
PPP generic driver version 2.4.2
PPP MPPE Compression module registered
NET: Registered protocol family 24
PPTP driver version 0.8.5
Netfilter messages via NETLINK v0.30.
nfnl_dryrun: registering with nfnetlink.
nf_conntrack version 0.5.0 (16384 buckets, 32768 max)
ctnetlink v0.93: registering with nfnetlink.
xt_time: kernel timezone is -0000
ip_set: protocol 6
Bridge firewalling registered
ubridge: Tiny bridge driver, 1.1
IPv4 over IPv4 tunneling driver
gre: GRE over IPv4 demultiplexor driver
Fast NAT loaded
ip_tables: (C) 2000-2006 Netfilter Core Team
TCP: cubic registered
NET: Registered protocol family 10
ip6_tables: (C) 2000-2006 Netfilter Core Team
IPv6 over IPv4 tunneling driver
NET: Registered protocol family 17
8021q: 802.1Q VLAN Support v1.8
VFS: Mounted root (squashfs filesystem) readonly on device 31:4.
Freeing unused kernel memory: 212k freed
init: init process was started.

init: press Enter to activate this console.

Due to the lack of drivers, only the console and usb work. The network subsystem is not working.

An attempt at porting EcoNet/Mediatek EN7512 SoC to Linux 5.
The system from @minhng99 repository was also launched.

I received my unit and began doing some testing, it IS a different unit so YMMV but I was able to dump the mtdblock images and:

My MTD layout (with -- notes):

bldr> mtd
0x00000000-0x00040000 : "bootloader"
0x00040000-0x00080000 : "romfile" -- tar.gz
0x00080000-0x0022f39e : "kernel" -- TRX_MAGIC2
0x0022f39e-0x010df39e : "rootfs" -- squashfs
0x00080000-0x01480000 : "tclinux"
0x01480000-0x0162f39e : "kernel_slave" -- TRX_MAGIC2
0x0162f39e-0x0253f39e : "rootfs_slave" -- squashfs
0x01480000-0x02880000 : "tclinux_slave"
0x02880000-0x04880000 : "openjdk" -- squashfs
0x04880000-0x0d980000 : "ubifs" -- ubifs
0x0de40000-0x0e000000 : "reservearea" -- see below

Reserved Area

Initially I thought this was a backup of the romfile only because tar.gz happily unpacked it, but on closer inspection it contains a bit more...

This layout seems to match my board.

@reserve area table 7 BLOCK@
|sector		name				cover area				note
|1			backupromfile			0~0x3ffff					256k
|2			defaultromfile			0x40000~0x7ffff			256k
|3			syslog				0x80000~0xBffff			256k
|4			proline      			0xc0000~0xfffff			256k
|5			temp				0x100000~0x13ffff			256k
|5.1			cerm1				0x100000~0x100fff		4k
|5.2			cerm2				0x101000~0x101fff		4k
|5.3			cerm3				0x102000~0x102fff		4k
|5.4			cerm4				0x103000~0x103fff		4k
|6			block6				0x140000~0x17ffff			256k
|6.1			eeprom				0x140000~0x1403ff		1k(reserve 1k,no use 256 bytes)
|6.2			bob.conf				0x140400~0x14049f		160bytes
|7			block7				0x180000~0x1bffff			256k
|7.1			imgbootflag			0x180000~0x18003f		64bytes
|7.2			11ac					0x180040~0x18023f		512bytes
|7.3			11ac	 reserved			0x180240~0x18043f		512bytes

In my case:

  • backupromfile - identical to gzipped file contained in mtdblock2
  • defaultromfile - empty (ffff)
  • syslog - 00000000: 456e 644f 6654 4353 7973 4c6f 670d 0aff EndOfTCSysLog... followed by ffff
  • proline - contains structured data, seems to be this
  • temp - empty (ffff)
  • eeprom - contains RT30xxEEPROM.bin (eeprom for MT7592 2.4ghz wifi chip)
  • bob.conf - empty (ffff)
  • imgbootflag contains ascii 1 or 0 as it's first byte to decide if we will boot kernel_slave or kernel, this is used along with the crc32 check to ensure that in case of power loss during update, the device will still boot. It does not protect against "valid" kernels which are wrongly written and panic on boot.
  • 11ac - contains MT7610EEPROM.bin (eeprom for MT7612 5ghz wifi chip)
  • 11ac reserved - empty (ffff)

I know I'm on a different board so please let me know if I'm making too much noise in this thread. Thanks,

There is never too much noise on this thread, bro. If you want, I can send you my Nokia G-240G-E but I don't know how to get the "dynamic password" for accessing the extended command set in ssh.

I also have another board. But after a little rework, it became pmg5617ga.

For the convenience of working with SPI and CH341A programmer, use an adapter:


Install the adapter on the device board, securing the installation site with hot glue:



quick connector to second adapter:

Write the loader and the system into memory by the programmer.


@alexceltare2 The board I'm using doesn't have zyxel's zloader so when you press a key it drops directly into bldr>, which is rather convenient. Unfortunately I can't read flash into memory without entering linux. I think these devices are identical except for software and I'm sure I don't need another toy, but thanks for the offer.

@tower Being able to direct program the flash chip is kind of an attractive idea, I don't immediately see the 8 pad pattern on the board but I'll look on the bottom when I shut it down. I'm not so interested in flashing zloader on it, but it would be nice to be able to reliably unbrick it.

We don't really care about zloader much since it's just a ZyXeL secondary bootloader. The project has a wider aim which is "Having a fully functional Econet EN7526 SoC build". Once we have the base done, we can add the rest on top of it (LEDs, Wifi drivers, Telephony, PON and other interfaces...). Ideally the build will go under ramips/en7526/ target. From my differences between ZyXeL PMG5617GA and Nokia G-240G-E which i both dumped the serial output it looks like 2 things are obvious:

  • The PON driver isn't in the SoC but a separate kernel module and hardware since they both have different drivers (EN7571 for ZyXeL vs. GN25L98 for Nokia)
  • There are a set of partitions found on both routers which I guess they are Econet specific:

Yeah, that's kind of what I'm going for. From examining I've observed that the EN7526 is very similar to the EN7512 ( which is supported in ), so I'm thinking of trying to compile an openwrt-v19.x with kernel-49 and then see if I can xmodem just the raw kernel code into device memory, jump to it, and see if it will boot without panicking. I already confirmed that I can call decomp and then jump to 0x80002000 and it boots. So if I can do it with kernel-49 instead of the one in flash, then I might look at building a holistic kernel+squashfs with the TRX header and see if I can flash it. Also going to try to see how heavily that kernel-49 is patched so we can see how ugly it would be to try to port those patches to 5.15.

I managed to get a (relatively) clean patch from kernel-49, unfortunately:

  1. It's built on top of android-4.9-q, not mainline
  2. This kernel is for all of their products so there's a bunch of support for various MTK processors
  3. It's very diverged and there's a lot of trash in the patch


Exact diff:

git diff 41d9243e51a1c1cff4ce9b2e55d119ae94b49264 87ddbd109cc4cc70c68673818a3757810b2991f6

At first glance, it seems the parts we need to care about are the following:

  • arch/mips/include/asm/tc3162
  • arch/mips/tc3262
  • drivers/mtd/ralink/en75xx_nand
  • drivers/tty/serial/tc3162_uart.c

So in fact it might prove easier to manually copy the directories over and patch only the relevant makefiles.