Add support for ASUS RT-AX89X AX6000

Each time command sysupgrade is called, volumes linux (kernel), rootfs, rootfs_data are completely reinitialized.
On this device this process is not scary, since a huge partition UBI_DEV is used.

Booting to initramfs; I've tried to flash with the trx file - but this doesn't work, which makes sense as it doesn't contain a root_fs:

root@OpenWrt:/tmp# sysupgrade -v openwrt-24_rt-ax89x-initramfs.trx
ERROR: Incorrect TRX image! Part 'rootfs-1' not found!.
Image check failed.

How do you assemble the trx with the initramfs with the rootfs partition?

Also - I thought I'd bricked it for a bit; just had to do an

mtd erase /dev/mtd9 

to revert to stock fortunately.

TRX-image is needed for flash firmware via AsusWRT!

Do not do this)

Read the instructions carefully!

Yes, upgrading from stock with the trx was the first thing I tried. Sorry if I didn't make that clear. The UI gave an unsuccessful error; UART showed:

Slurp remaining -1 bytes
not support CAP or RE, don't start_amas_lanctrl
[Mastiff]exit.
clean_mode(1) clean_time(5) threshold(17742)
free_caches: memfree=528888.
free_caches: memfree > threshold.
read from stream: 4096
header crc: EE777C03
org header crc: EE777C03
image len: 1153584
header crc: EE777C03
org header crc: EE777C03
image len: 1153584
##### hdr2.tail.sn = 0184
##### hdr2.tail.en = bf68
##### hdr2.tail.key = ff
##### Key = c4
/tmp/linux.trx doesn't support HE20!
check trx fail!!

at least on the older 386 code. The newer 388 code gives the same error on the console, but reboots the router instead.

1 Like

@crajohnson , Thanks for testing!

Everything worked fine here. The image passed the test because there is no message version check fail! in the log.

But this message most likely indicates that the unsquashfs utility was unable to unpack the rootfs part of the image.

disasm
  data_ptr = img + 0x40;
  data_size = bswap32(*((_DWORD *)img + 3));
  LOBYTE(xx) = 0;
  v8 = img;
  do
  {
    v9 = *(_DWORD *)v8;
    v10 = *((_DWORD *)v8 + 1);
    v8 += 8;
    *v2 = v9;
    v2[1] = v10;
    v2 += 2;
  }
  while ( v8 != data_ptr );
  hdr2_tail_sn = *((unsigned __int16 *)img + 0x18);
  hdr2_tail_en = *((unsigned __int16 *)img + 0x19);
  j_cprintf("##### hdr2.tail.sn = %04x\n", hdr2_tail_sn);
  j_cprintf("##### hdr2.tail.en = %04x\n", hdr2_tail_en);
  j_cprintf("##### hdr2.tail.key = %02x\n", (unsigned __int8)img[0x35]);
  enc_sp_extendno = j_nvram_get_int("enc_sp_extendno");
  v14 = hdr2_tail_sn == 0;
  if ( hdr2_tail_sn )
    v14 = hdr2_tail_en == 0;
  if ( v14 || hdr2_tail_sn <= 381 || hdr2_tail_sn == 382 && hdr2_tail_en < enc_sp_extendno )
  {
    j_cprintf("version check fail!\n");
    return 0;
  }
  buf = (unsigned __int8 *)(img + 0x36);
  i = 5;
  xoffset = 0;
  do
  {
    if ( *buf == 0xA9 )
    {
      x3 = buf[3];
      if ( (x3 & 3) == 0 )
      {
        x1 = (unsigned __int8)xx | (buf[1] << 8);
        x2 = buf[2];
        buf += 2;
        xx = x1 | (x2 << 16) & 0xFFFFFF | (x3 << 24);
        xoffset = bswap32(xx);
      }
    }
    --i;
    buf += 2;
  }
  while ( i );
  k1 = img[xoffset + ((data_size + 0x40 - xoffset) >> 1)];
  if ( k1 )
    k2 = (unsigned __int8)(img[xoffset >> 1] + ~k1);
  else
    k2 = (unsigned __int8)((unsigned __int8)img[xoffset >> 1] % 3u - 3);
  if ( j_get_soc_version_major() != 2 || !j_f_exists((int)"/usr/sbin/unsquashfs") )
    return (unsigned __int8)img[0x35] == k2;
  if ( j_d_exists("/tmp/.squashfs-root") )
  {
    j__eval("rm -rf /tmp/.squashfs-root");
  }
  v24 = "/usr/sbin/unsquashfs";
  v25 = "-d";
  v29 = 0;
  v26 = "/tmp/.squashfs-root";
  v27 = img_name;
  v28 = "lib/firmware/IPQ8074A/fw_version.txt";
  j__eval((int)&v24, 0, 0, 0);
  system("ls -al /tmp/.squashfs-root/lib/firmware");
  if ( j_f_exists((int)"/tmp/.squashfs-root/lib/firmware/IPQ8074A/fw_version.txt") )
  {
    unlink("/tmp/.squashfs-root/lib/firmware/IPQ8074A/fw_version.txt");
    return (unsigned __int8)img[0x35] == k2;
  }
  j_dbg("%s doesn't support HE20!\n", img_name);
  j_logmessage_normal("CHKTRX", "%s doesn't support HE20!\n", img_name);
  return 0;

Need to come up with something....

UPD:
Alternatively, you can try to manually create file : /tmp/.squashfs-root/lib/firmware/IPQ8074A/fw_version.txt

UPD2:
You can try rename the file /usr/sbin/unsquashfs to /usr/sbin/unsquashfs_orig

That's just read only though, right?

admin@RT-AX89U-DDE0:/usr/sbin# mv unsquashfs unsquashfs_orig
mv: can't rename 'unsquashfs': Read-only file system

I might be able to initramfs boot the openwrt image and edit the squashfs image to rename that file. I'll give that a try.

Do not do this! This will definitely do harm!
I'm still having a hard time coming up with a simple solution.
But it seems that when assembling the TRX-image, I will have to create an additional squashfs image and implement it into TRX....

@crajohnson ,
When creating the TRX-image, I completely forgot to take into account that its maximum size should not exceed 16MB. And due to the huge size of Wi-Fi drivers, the image always turns out to be huge.
I had to change the assembly script a little so that it would remove all packages that relate to Wi-Fi drivers from the config.

After that, using various utilities, I added an additional squashfs image to the TRX-image, which contains 1 file (fw_version.txt).
The result is a new TRX-image: https://drive.google.com/drive/folders/1LYw8HTP1F5JAReigio33bxYEsBSQnJw9

So please try again.

script for generating corrected TRX-image
sudo apt-get install build-essential
sudo apt-get install squashfs-tools

mkdir -p ~/trx
cd ~/trx

wget http://github.com/openwrt-xiaomi/firmware-utils/raw/master/src/mkasustrx.c
gcc mkasustrx.c -o mkasustrx
chmod +x ./mkasustrx

wget -O fw.trx https://drive.usercontent.google.com/download?id=1VqTBDpYqxOkqnCFTniqn9KDVaAWTvHuU&export=download&authuser=0&confirm=t

mkdir -p ./root/lib/firmware/IPQ8074A/
echo "WLAN.HK.2.2-02237-QCAHKSWPL_SILICONZ-1.557369.2.577880.1 v2" > ./root/lib/firmware/IPQ8074A/fw_version.txt

mksquashfs ./root rootfs.hsqs -comp xz -b 4096 -no-exports -no-sparse -no-xattrs -noI -noD -noF -noX -all-root -noappend

cat fw.trx > fw2.trx
cat rootfs.hsqs >> fw2.trx
./mkasustrx -i fw2.trx -v 2 -n RT-AX89U -b 388 -e 49000 -o fw3.trx

Is there a need for this to be an initramfs image in it's final form? I.e. assume all filesystem of the OS just sits in RAM in such case.

I.e. I'd also feel like in the ideal situation you'd do it like the stock firmware itself, with OS fs living in the nand storage. Or that's not a desirable thing?

For example, how can things like changed settings be persistent if it's all in RAM anyway?

1 Like

AFAIK, every router I have messed around with has had custom firmware installed in the nand chip.

I recall robimarko saying that he is still making an effort to put the firmware on the nand chip.

It's cool that the OpenWRT firmware can be running from ram, but it would be nice to have it sitting in nand on this model of router.

1 Like

So this does flash! However, on reset this image is unable to boot:

RT-AX89U bootloader version: 2.1.2.2
MAC Address: 00:AA:BB:CC:DD:E0
Read 40 bytes from volume linux offset 0 to 4b000000
Read ee65c0 bytes from volume linux offset 40 to 4b000040
## Booting kernel from Legacy Image at 4b000000 ...
   Image Name:
   Image Type:   AArch64 Linux Kernel Image (uncompressed)
   Data Size:    15623616 Bytes = 14.9 MiB
   Load Address: 41000000
   Entry Point:  41000000
   Verifying Checksum ... OK
## Booting kernel from Legacy Image at 4b000000 ...
   Image Name:
   Image Type:   AArch64 Linux Kernel Image (uncompressed)
   Data Size:    15623616 Bytes = 14.9 MiB
   Load Address: 41000000
   Entry Point:  41000000
   Loading Kernel Image ... OK
Using machid 0x8010000 from environment

Starting kernel ...

undefined instruction
pc : [<41000004>]          lr : [<4a90247c>]
reloc pc : [<41000004>]    lr : [<4a90247c>]
sp : 4a0df710  ip : 0000001c     fp : 00000000
r10: 00000000  r9 : 4a0dfea0     r8 : 4a124400
r7 : 4a99f520  r6 : 00000000     r5 : 41000000  r4 : 4a99f520
r3 : 644d5241  r2 : 40000100     r1 : 08010000  r0 : 00000000
Flags: nZCv  IRQs off  FIQs off  Mode SVC_32
Resetting CPU ...

resetting ...

@crajohnson , Thanks for testing. It's pleasure to work with you!

This means that in this router the Asus developers did not implement the removal of
uImage header from FDT-images (UbiFit).
Therefore, to create a correct trx-image, I must change these 2 lines:
link_to_commit

Wait my new version of trx....

Apparently you didn't read the instructions well.
Flashing of Asus devices takes place in 2 stages. Only at the first stage you need an initramfs image.

1 Like

As it turned out, the ASUS developers assembled the linux kernel for this router under armv7 (32-bit). And everything else is collected under armv7.

And to create an trx-compatible image, I must somehow build an image of type zImage. But such an image is not available when building kernel for the ipq807x platforms.

Need to come up with something....

1 Like

Thanks so much for working on this!

zImage doesnt exist for 64 bit kernels

It's probably worth trying to collect an uImage of type IH_TYPE_MULTI.
The stock bootloader should be able to load the legacy-multi-images into memory:

The most effective way to solve the above problem is:
Add a patch to the Linux kernel that will allow you to add DTB directly to the image of the kernel itself.
Now you need to find actual patch that do this on versions 5.x or 6.x of the Linux kernel...

Please test latest version of TRX-image.

Looking good! I haven't tried doing the sysupgrade yet, and it doesn't seem to save any user settings yet (i.e. password, editing any config files), but it does boot successfully!

RT-AX89U bootloader version: 2.1.2.2
MAC Address: 00:AA:BB:CC:DD:E0
Read 40 bytes from volume linux offset 0 to 4b000000
Read f14b69 bytes from volume linux offset 40 to 4b000040
## Booting kernel from Legacy Image at 4b000000 ...
   Image Name:
   Image Type:   AArch64 Linux Multi-File Image (gzip compressed)
   Data Size:    15813481 Bytes = 15.1 MiB
   Load Address: 41000000
   Entry Point:  41000000
   Contents:
      Image 0: 15760536 Bytes = 15 MiB
      Image 1: 4096 Bytes = 4 KiB
      Image 2: 48833 Bytes = 47.7 KiB
   Verifying Checksum ... OK
## Booting kernel from Legacy Image at 4b000000 ...
   Image Name:
   Image Type:   AArch64 Linux Multi-File Image (gzip compressed)
   Data Size:    15813481 Bytes = 15.1 MiB
   Load Address: 41000000
   Entry Point:  41000000
   Contents:
      Image 0: 15760536 Bytes = 15 MiB
      Image 1: 4096 Bytes = 4 KiB
      Image 2: 48833 Bytes = 47.7 KiB
## Loading init Ramdisk from multi component Legacy Image at 4b000000 ...
## Flattened Device Tree from multi component Image at 4B000000
   Booting using the fdt at 0x4bf08ce8
   Uncompressing Multi-File Image ... OK
   Loading Ramdisk to 4a0dd000, end 4a0de000 ... OK
   Loading Device Tree to 4a0ce000, end 4a0dcec0 ... OK
del /soc/dp6 okay
Remove AQR107 settings
Using machid 0x8010000 from environment

Starting kernel ...

Jumping to AARCH64 kernel via monitor
[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
[    0.000000] Linux version 6.1.70 (user@debian) (aarch64-openwrt-linux-musl-gcc (OpenWrt GCC 12.3.0 r24736-c7fbf09950) 12.3.0, GNU ld (GNU Binutils) 2.40.0) #0 SMP Tue Jan 23 09:24:31 2024
[    0.000000] Machine model: Asus RT-AX89X
[    0.000000] Zone ranges:
[    0.000000]   DMA      [mem 0x0000000040000000-0x000000007fffffff]
[    0.000000]   DMA32    empty
[    0.000000]   Normal   empty
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges

A couple of times it does this on startup, but it seems stable for right now:

[   12.768188] Unable to handle kernel paging request at virtual address 0064060013000113
[   12.768236] Mem abort info:
[   12.775008]   ESR = 0x0000000096000004
[   12.777691]   EC = 0x25: DABT (current EL), IL = 32 bits
[   12.781529]   SET = 0, FnV = 0
[   12.786979]   EA = 0, S1PTW = 0
[   12.789852]   FSC = 0x04: level 0 translation fault
[   12.792886] Data abort info:
[   12.797742]   ISV = 0, ISS = 0x00000004
[   12.800878]   CM = 0, WnR = 0
[   12.804428] [0064060013000113] address between user and kernel address ranges
[   12.807563] Internal error: Oops: 0000000096000004 [#1] SMP
[   12.814676] Modules linked in: pppoe ppp_async nft_fib_inet nf_flow_table_inet ath11k_ahb ath11k pppox ppp_generic nft_reject_ipv6 nft_reject_ipv4 nft_reject_inet nft_reject nft_redir nft_quota nft_objref nft_numgen nft_nat nft_masq nft_log nft_limit nft_hash nft_flow_offload nft_fib_ipv6 nft_fib_ipv4 nft_fib nft_ct nft_chain_nat nf_tables nf_nat nf_flow_table nf_conntrack_netlink nf_conntrack mac80211 cfg80211 slhc qrtr_smd qrtr qmi_helpers nfnetlink nf_reject_ipv6 nf_reject_ipv4 nf_log_syslog nf_defrag_ipv6 nf_defrag_ipv4 libcrc32c compat gpio_fan sha512_generic seqiv jitterentropy_rng drbg michael_mic hmac cmac leds_gpio xhci_plat_hcd xhci_pci xhci_hcd dwc3 dwc3_qcom qca_nss_dp qca_ssdk ramoops reed_solomon pstore gpio_button_hotplug ext4 mbcache jbd2 aquantia hwmon crc_ccitt crc32c_generic
[   12.868309] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.1.70 #0
[   12.890545] Hardware name: Asus RT-AX89X (DT)
[   12.896184] pstate: 20400005 (nzCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[   12.900702] pc : 0xffffffc0009c3f70 [qca_nss_dp@0000000063271163+0xa000]
[   12.907474] lr : 0xffffffc0009c3f40 [qca_nss_dp@0000000063271163+0xa000]
[   12.914417] sp : ffffffc008003e00
[   12.921094] x29: ffffffc008003e00 x28: ffffffc008003f50 x27: ffffffc009546000
[   12.924314] x26: ffffffc03694c000 x25: ffffffc009452008 x24: ffffffc008003f40
[   12.931432] x23: ffffffc0009c8ca0 x22: ffffffc008003f3f x21: 0000000000000000
[   12.938549] x20: 0000000000000000 x19: 0000000000000001 x18: 0000000000000000
[   12.945668] x17: ffffffc03694c000 x16: ffffffc008000000 x15: 0000000000000000
[   12.952786] x14: 00000000000001ad x13: 0000000000000000 x12: 0000000000000000
[   12.959905] x11: 0000000000000000 x10: 00000000000008c0 x9 : ffffffc009543ce0
[   12.967022] x8 : ffffff803fda3028 x7 : 0000000000000000 x6 : 0000000000000000
[   12.974140] x5 : 000000000000043b x4 : ffffffc0009c8e60 x3 : 0000000000000000
[   12.981258] x2 : 6564060013000083 x1 : ffffff8003fc0000 x0 : ffffffc0009c8e58
[   12.988377] Call trace:
[   12.995485]  0xffffffc0009c3f70 [qca_nss_dp@0000000063271163+0xa000]
[   12.997751]  0xffffffc008601448
[   13.004339]  0xffffffc008601a94
[   13.007204]  0xffffffc00801010c
[   13.010330]  0xffffffc0080159f0
[   13.013455]  0xffffffc0080159b4
[   13.016579]  0xffffffc008015a1c
[   13.019704]  0xffffffc008038bbc
[   13.022829]  0xffffffc008038e34
[   13.025955]  0xffffffc00880e26c
[   13.029079]  0xffffffc00880e8dc
[   13.032204]  0xffffffc008011304
[   13.035329]  0xffffffc0080605f8
[   13.038455]  0xffffffc008810500
[   13.041579]  0xffffffc008810c28
[   13.044704]  0xffffffc008076918
[   13.047829]  0xffffffc008076b98
[   13.050955]  0xffffffc00880f660
[   13.054079]  0xffffffc0089b076c
[   13.057205]  0xffffffc0089b0e1c
[   13.060331]  0xffffffc0089b5358
[   13.063460] Code: 54000280 f9400001 b4ffff81 f9420022 (f9404843)
[   13.066588] ---[ end trace 0000000000000000 ]---
[   13.072834] Kernel panic - not syncing: Oops: Fatal exception in interrupt
[   13.077525] SMP: stopping secondary CPUs
[   13.084209] Kernel Offset: disabled
[   13.088282] CPU features: 0x00000,00000000,0000400b
[   13.091498] Memory Limit: none
[   13.096357] Rebooting in 3 seconds..

1 Like