Adding OpenWrt support for TP-Link EAP245

This is EAP245v3 hardware:

So I was able to get OpenWRT kernel booting. I still have a long way to go, but it's a start.

The TP-Link bootloader requires all images to be signed using their key, so I couldn't use the tftp recovery method :frowning:

On the underside of the board, there's a unpopulated R225 resistor that was able to connect to to get 115200 baud 8n1 UART output. I need to bridge solder it, but it at least works by holding a jumper wire against it.

I then created a custom U-Boot image with j-d-r's https://github.com/j-d-r/u-boot-QCA956x. Network doesn't seem to work, so I wasn't able to get a web recovery console, even though it was listening on 192.168.1.1. It detects when a cable is plugged in, but it won't bring up a network stack. It's something else for me to look at as well.

I switched the BOOTCOMMAND to "bootm 0x9f0c0000". It was set to "bootelf" before, which works with the existing TP-Link image (it's an ELF image). Because I'm booting an OpenWRT initramfs, I needed to change to "bootm 0x9f0c0000".

Then I overwrote the original image that I dumped from SPI (using dd) with the u-boot image I crafted and the Archer c7 v5 OpenWRT initramfs kernel image I compiled. Then I took this crafted image and flashed it onto my EAP245v3 with my SPI programmer.

Here's output from my UART console (ignore the versioning, I didn't get around to changing it):

***************************************
*     U-Boot 1.1.4-90b788c2-dirty     *
*          Build: 2020-05-28          *
***************************************

** Warning: bad env CRC, using default,
   use 'saveenv' to save it in FLASH

  BOARD: TP-Link EAP245 v1
    SOC: QCA956x rev. 0
    CPU: MIPS 74Kc
    RAM: 128 MB DDR2 16-bit CL6-5-5-13
  FLASH: 16 MB Winbond W25Q128
   PCIe: QCA99X0
    MAC: 00:DE:AD:BE:EF:00
   UART: 111607 bps   
 CLOCKS: CPU/RAM/AHB/SPI/REF
         775/650/258/ 18/ 25 MHz

Hit any key to stop booting:  0

Booting image from 0x9F0C0000...

   Image name:    MIPS OpenWrt Linux-4.14.171
   Build date:    2020-02-27 21:05:12 UTC
   Architecture:  MIPS
   OS/image type: Linux Kernel
   Compression:   LZMA
   Data size:     3.5 MB (3659176 bytes)
   Load address:  0x80060000
   Entry point:   0x80060000

   Header CRC...  OK!
   Data CRC...    skipped

Stopping network... OK!
Uncompressing Kernel... OK!
Starting kernel...

[    0.000000] Linux version 4.14.171 (root@edca4f546068) (gcc version 7.5.0 (OpenWrt GCC 7.5.0 r10947-65030d81f3)) #0 Thu Feb 27 21:05:12 2020
[    0.000000] bootconsole [early0] enabled
[    0.000000] CPU0 revision is: 00019750 (MIPS 74Kc)
[    0.000000] SoC: Qualcomm Atheros QCA956X ver 1 rev 0
[    0.000000] Determined physical RAM map:
[    0.000000]  memory: 08000000 @ 00000000 (usable)
[    0.000000] Initrd not found or empty - disabling initrd
[    0.000000] Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
[    0.000000] Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 32 bytes
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000000000000-0x0000000007ffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000000000000-0x0000000007ffffff]
...............

I do get some errors about network devices not being initialized, but I'll work on that.

So yeah.. progress :slight_smile:

5 Likes

I was looking at the GPL sources for the EAP245v3 yesterday to see just how different it is from the v1. It might actually no longer be necessary to replace the bootloader to get proper network initialization. In fact, there is now a platform specific architecture file mach-eap245v3.c. This is quite different from the mach-ap152.c file used by the v1. The main difference being that there is no longer any custom SERDES/ethernet initialization. I had a look at the entire diff for the included kernel tree (it's not that long), but didn't immediately see that code anywhere else. That means that it might be included in their u-boot version now.

Fun fact: The EAP245v3 sources also refer to an EAP245v2, whose code is more like the v1 than the v3. To my knowledge, the EAP245v2 never made it to the market (no FCC ID either).

It's true, but the factory bootloader does an RSA key check against the image before it will allow it to boot. If the signature doesn't match, then it fails.

There may be a way to bypass that, but I haven't tried that yet.

I saw that! I actually copied it over to my OpenWRT fork to see if I can get a build going of it. The EAP245v3 hardware seems very similar to the Archer C7 v5, so I'm starting with that as a starting point and merging in diffs from the GPL Sources provided by TP-Link for the EAP245v3 :slight_smile: I have no idea how far I'll get with this, but it's a start.

Sorry I missed that in your earlier reply! That doesn't sound too good though...

Doesn't the C7v5 have a QCA9880 like the EAP245v1? Although (I would think) the wireless hardware probably doesn't matter too much for u-boot. I have an EAP245v3 on the way, so I can also start poking at it.

It's a QCA9982 on the EAP245v3. I haven't started looking at the wireless stuff yet, but will once I get ethernet working.

I bridged my TX line and added a UART header to my board. Now I just need to solder up to the RX lines so I can actually interface and troubleshoot.

That's great. It'd be nice to have someone else to collaborate on this with. This is my first time using OpenWRT code, so having an extra set of eyes will be helpful!

Also got my v3. For reference, the J3 header is >[ TX | RX | GND | 3.3V ]. To use TX and RX, you have to bridge (or put in a tiny resistor) on R225 and R237. Make sure not to bridge R230 next to R237, or you'll connect RX to ground. R225 is inside the can on the bottom side of the PCB. Carefully lift the can lid to access it.

Turns out TP-Link realised running raw user input in a shell was a bad idea. The EAP245v3's firmware opens a file and writes the username to it, instead of just echoing it into a file. So my v1 method of getting a root shell doesn't work any more.

The v3 uclited programme does seem to have a sort of test mode where it downloads a shell script and some radio related kernel modules (via tftp) and runs that, but I have no idea (yet) how trigger this.

Booting actually happens in two steps. first u-boot on the 'factory-boot' partition runs, which loads u-boot on the 'u-boot' partition, which then loads the kernel. The second u-boot properly initialises the network port before checking if it can boot from flash. The (single) bootloader on the v1 only did this after it failed to boot from flash (at 0x9f040000).

Awesome news! I used the bridging method on my UART TX line, but I messed up the pads on my RX one :frowning: . I need to source some copper tape so I can repair the pads. For now I can only get UART serial output.

There's also a tftp failsafe on boot when you hold down the reset button when plugging in power. It will attempt to pull a firmware file off tftp, but it's fully checked for its RSA signature. I'm not entirely sure if it's the factory-boot or fs-uboot doing this though.

I'm trying to confirm if this is the type of firmware header for the EAP245v3 or not: https://github.com/xdarklight/mktplinkfw3. It seems to indicate that the RSA signature verification is only actually done when trying to update the firmware, and not checking it on boot. So I may, in fact, be able to splice in an OpenWRT image into the factory firmware and SPI flash it..

On my v1 I managed to lift a pad and part of the trace leading up to it. So I knew I had to be careful! I now use some fine copper wire salvaged from an old cable, works very well for bridging. Looking at my old picture below, I just realised that the v1 and v3 have the same UART pinout. The resistor names are also the same, which makes if it's based of the same ap152 reference design.

Looking at the (v3) boot log, I would think the RSA integrity check only happens after booting linux.

U-Boot 1.1.4--LSDK-10.2-00082-4 (Mar 19 2018 - 14:55:50)

board956x - Dragonfly 1.0DRAM:  
sri
ath_ddr_initial_config(287): (ddr2 init)
ath_ddr_initial_config: DDR_EMR2_ADDRESS=0x180000bc, EMR2 value=0x80
ath_sys_frequency: ref_clk 25000000
ath_sys_frequency: cpu 775 ddr 650 ahb 258
Tap values = (0xf, 0xf, 0xf, 0xf)
128 MB
Top of RAM usable for U-Boot at: 88000000
Reserving 454k for U-Boot at: 87f8c000
Reserving 192k for malloc() at: 87f5c000
Reserving 44 Bytes for Board Info at: 87f5bfd4
Reserving 36 Bytes for Global Data at: 87f5bfb0
Reserving 128k for boot params() at: 87f3bfb0
Stack Pointer at: 87f3bf98
Now running in RAM - U-Boot at: 87f8c000
Flash Manuf Id 0xef, DeviceId0 0x40, DeviceId1 0x18
flash size 16MB, sector count = 256
Flash: 16 MB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Setting 0x181162c0 to 0x40802100
Hit Ctrl+B to stop autoboot:  0 
factory boot check integer ok.
factory boot load fs uboot len 262144 to addr 0x81000000.
## Starting application at 0x81000000 ...


U-Boot 1.1.4--LSDK-10.2-00082-4 (Mar 19 2018 - 14:56:29)

board956x - Dragonfly 1.0DRAM:  
sri
ath_ddr_initial_config(287): (ddr2 init)
ath_ddr_initial_config: DDR_EMR2_ADDRESS=0x180000bc, EMR2 value=0x80
ath_sys_frequency: ref_clk 25000000
ath_sys_frequency: cpu 775 ddr 650 ahb 258
Tap values = (0x10, 0x10, 0x10, 0x10)
128 MB
Top of RAM usable for U-Boot at: 88000000
Reserving 163k for U-Boot at: 87fd4000
Reserving 192k for malloc() at: 87fa4000
Reserving 44 Bytes for Board Info at: 87fa3fd4
Reserving 36 Bytes for Global Data at: 87fa3fb0
Reserving 128k for boot params() at: 87f83fb0
Stack Pointer at: 87f83f98
Now running in RAM - U-Boot at: 87fd4000
Flash Manuf Id 0xef, DeviceId0 0x40, DeviceId1 0x18
flash size 16MB, sector count = 256
Flash: 16 MB
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Setting 0x181162c0 to 0x40802100
Hit Ctrl+B to stop autoboot:  0 
Net:   ath_gmac_enet_initialize...
No valid address in Flash. Using fixed address
ath_gmac_enet_initialize: reset mask:c02200 
athr_mgmt_init ::done
Dragonfly  ----> S17 PHY *
athrs17_reg_init: complete
SGMII in forced mode
athr_gmac_sgmii_setup SGMII done
: cfg1 0x80000000 cfg2 0x7114
eth0: 00:03:7f:09:0b:ad
eth0 up
eth0
Loading .text @ 0x802f9640 (12304 bytes)
Loading .text.startup @ 0x802fc650 (8 bytes)
Loading .rodata.str1.4 @ 0x802fc658 (720 bytes)
Loading .data @ 0x802fc930 (1292213 bytes)
Clearing .bss @ 0x804380f0 (4202512 bytes)
## Starting application at 0x802f9640 ...
BOOT CONFIG:     80208482
zimage at:     802FC930 804380E5
Uncompressing Linux at load address 80060000
Now, booting the kernel...
[    0.000000] Linux version 3.3.8 (jenkins@sohoiapbuild) (gcc version 4.6.3 20120201 (prerelease) (Linaro GCC 4.6-2012.02) ) #1 Wed Jul 31 14:05:23 CST 2019
[    0.000000] bootconsole [early0] enabled
[    0.000000] CPU revision is: 00019750 (MIPS 74Kc)
[    0.000000] SoC: Qualcomm Atheros QCA956X rev 0
[    0.000000] Clocks: CPU:775.000MHz, DDR:650.000MHz, AHB:258.333MHz, Ref:25.000MHz
[    0.000000] Determined physical RAM map:
[    0.000000]  memory: 08000000 @ 00000000 (usable)
[    0.000000] User-defined physical RAM map:
[    0.000000]  memory: 08000000 @ 00000000 (usable)
[    0.000000] Initrd not found or empty - disabling initrd
[    0.000000] Zone PFN ranges:
[    0.000000]   Normal   0x00000000 -> 0x00008000
[    0.000000] Movable zone start PFN for each node
[    0.000000] Early memory PFN ranges
[    0.000000]     0: 0x00000000 -> 0x00008000
[    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 32512
[    0.000000] Kernel command line:  0x9f0c0000 console=ttyS0,115200 root=31:07 rootfstype=squashfs init=/init mtdparts=spi0.0:256k(factory-boot),256k(u-boot),64k(pation-table),64k(product-info),64k(ART),64k(extra-para),1536k(kernel),13056k(rootfs),192k(config),512k(mutil-log),256k(oops) mem=128M board=AP152
[    0.000000] PID hash table entries: 512 (order: -1, 2048 bytes)
[    0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
[    0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
[    0.000000] Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
[    0.000000] Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 32 bytes
[    0.000000] Writing ErrCtl register=00000000
[    0.000000] Readback ErrCtl register=00000000
[    0.000000] Memory: 126652k/131072k available (1989k kernel code, 4420k reserved, 496k data, 176k init, 0k highmem)
[    0.000000] SLUB: Genslabs=9, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS:83
[    0.000000] Calibrating delay loop... 385.84 BogoMIPS (lpj=1929216)
[    0.060000] pid_max: default: 32768 minimum: 301
[    0.060000] Mount-cache hash table entries: 512
[    0.070000] NET: Registered protocol family 16
[    0.070000] gpiochip_add: registered GPIOs 0 to 22 on device: ath79
[    0.080000] MIPS: machine is Qualcomm Atheros AP152 based EAP245V3
[    0.090000] 
[    0.090000] WLAN firmware dump buffer allocation of 2097152 bytes @ address 0x87a00000- SUCCESS !!!
[    0.100000] registering PCI controller with io_map_base unset
[    0.310000] bio: create slab <bio-0> at 0
[    0.310000] PCI host bridge to bus 0000:00
[    0.310000] pci_bus 0000:00: root bus resource [mem 0x12000000-0x13ffffff]
[    0.320000] pci_bus 0000:00: root bus resource [io  0x0001]
[    0.320000] pci 0000:00:00.0: BAR 0: assigned [mem 0x12000000-0x121fffff 64bit]
[    0.330000] pci 0000:00:00.0: using irq 40 for pin 1
[    0.330000] Switching to clocksource MIPS
[    0.340000] NET: Registered protocol family 2
[    0.340000] IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.340000] TCP established hash table entries: 4096 (order: 3, 32768 bytes)
[    0.350000] TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
[    0.350000] TCP: Hash tables configured (established 4096 bind 4096)
[    0.360000] TCP reno registered
[    0.360000] UDP hash table entries: 256 (order: 0, 4096 bytes)
[    0.370000] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
[    0.370000] NET: Registered protocol family 1
[    0.390000] squashfs: version 4.0 (2009/01/31) Phillip Lougher
[    0.390000] msgmni has been set to 247
[    0.400000] io scheduler noop registered
[    0.400000] io scheduler deadline registered (default)
[    0.410000] Serial: 8250/16550 driver, 1 ports, IRQ sharing disabled
[    0.430000] serial8250.0: ttyS0 at MMIO 0x18020000 (irq = 11) is a 16550A
[    0.440000] console [ttyS0] enabled, bootconsole disabled
[    0.440000] console [ttyS0] enabled, bootconsole disabled
[    0.450000] m25p80 spi0.0: found w25q128, expected m25p80
[    0.460000] m25p80 spi0.0: w25q128 (16384 Kbytes)
[    0.460000] 11 cmdlinepart partitions found on MTD device spi0.0
[    0.470000] Creating 11 MTD partitions on "spi0.0":
[    0.480000] 0x000000000000-0x000000040000 : "factory-boot"
[    0.480000] 0x000000040000-0x000000080000 : "u-boot"
[    0.490000] 0x000000080000-0x000000090000 : "pation-table"
[    0.500000] 0x000000090000-0x0000000a0000 : "product-info"
[    0.500000] 0x0000000a0000-0x0000000b0000 : "ART"
[    0.510000] 0x0000000b0000-0x0000000c0000 : "extra-para"
[    0.510000] 0x0000000c0000-0x000000240000 : "kernel"
[    0.520000] 0x000000240000-0x000000f00000 : "rootfs"
[    0.530000] mtd: partition "rootfs" set to be root filesystem
[    0.530000] 0x000000f00000-0x000000f30000 : "config"
[    0.540000] 0x000000f30000-0x000000fb0000 : "mutil-log"
[    0.550000] 0x000000fb0000-0x000000ff0000 : "oops"
[    0.670000] ag71xx_mdio: probed
[    0.670000] eth0: Atheros AG71xx at 0xb9000000, irq 4
[    1.250000] eth0: Atheros AR8327 switch driver attached.
[    2.440000] ag71xx ag71xx.0: eth0: connected to PHY at ag71xx-mdio.0:00 [uid=004dd036, driver=Atheros AR8216/AR8236/AR8316]
[    2.450000] TCP cubic registered
[    2.450000] NET: Registered protocol family 17
[    2.450000] 8021q: 802.1Q VLAN Support v1.8
[    2.460000] ### of_selftest(): No testcase data in device tree; not running tests
[    2.470000] VFS: Mounted root (squashfs filesystem) readonly on device 31:7.
[    2.480000] Freeing unused kernel memory: 176k freed
init started: BusyBox v1.20.2 (2019-07-31 14:15:01 CST)
starting pid 264, tty '': '/etc/rc.d/rcS >/dev/console 2>&1'
This board use 3.3.8
[    3.230000] mtdoops: Attached to MTD device 10
[    3.500000] xt_time: kernel timezone is -0000
[    3.510000] nf_conntrack version 0.5.0 (1981 buckets, 15848 max)
[    3.660000] ip_tables: (C) 2000-2006 Netfilter Core Team
[    3.730000] Ebtables v2.0 registered
insmod: can't insert '/lib/modules/3.3.8/kernel/ts_kmp.ko': No such file or directory
insmod: can't insert '/lib/modules/3.3.8/kernel/br_filter.ko': No such file or directory
[    3.780000] ---portal module open ok
[    3.790000] Register vlan_manage hooks success.
insmod: can't insert '/lib/modules/3.3.8/kernel/statistics.ko': No such file or directory
[    3.810000] [Debug gpio_parse_conf:265] Open File /etc/gpio.conf SUCCESS!!
[    3.830000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 14, readCount 256
[    3.840000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 44, readCount 256
[    3.850000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 6 , readCount 256
[    3.860000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 7 , readCount 256
[    3.860000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 2 , readCount 256
[    3.870000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 7 , readCount 256
[    3.880000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 44, readCount 256
[    3.890000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 6 , readCount 256
[    3.900000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 7 , readCount 256
[    3.900000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 2 , readCount 256
[    3.910000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 7 , readCount 256
[    3.920000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 44, readCount 256
[    3.930000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 7 , readCount 249
[    3.930000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 6 , readCount 242
[    3.940000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 6 , readCount 236
[    3.950000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 6 , readCount 230
[    3.960000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 2 , readCount 224
[    3.970000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 51, readCount 222
[    3.970000] [Debug gpio_parse_conf:354] Ignore line (0), skipLen 44, readCount 171
[    3.980000] [Debug gpio_parse_conf:382] GPIO Parse OK:  led_green   led(1) high(1) high(1) 7
[    3.990000] [Debug gpio_parse_conf:382] GPIO Parse OK:  led_yellow  led(1) high(1) low (0) 9
[    4.000000] [Debug gpio_parse_conf:382] GPIO Parse OK:  btn_reset   btn(2) low (0) high(1) 2
[    4.010000] [Debug btn_netlink_init:177] btn: create netlink socket SUCCESS.
[    4.010000] [Debug wdt_module_init:221] Create watchdog proc dir SUCCESS.
[    4.020000] [Debug led_entry_handler:756] Create led_green   proc dir SUCCESS.
[    4.030000] [Debug led_entry_handler:756] Create led_yellow  proc dir SUCCESS.
[    4.040000] [Debug btn_entry_handler:590] Init button: btn_reset 2 2 0 success.
insmod: can't insert '/lib/modules/3.3.8/kernel/[    4.050000] rate_limit: module license 'BSD' taints kernel.
mesh.ko': No suc[    4.060000] Disabling lock debugging due to kernel taint
h file or directory
[    4.360000] [Debug btn_netlink_receive:72] BTN netlink with user space daemon 365 SUCCESS.
mesh is not supported
[NM_Debug](nm_lock_init) 00149: create semaphore...
[NM_Debug](parsePtnTableFromNvramToStruct) 00182: NM_PTN_TABLE_BASE = 0x80000
wlanmonitor is not supported.
ap_watchdog is not supported.
starting pid 381, tty '': '/sbin/getty ttyS0 115200'
[NM_Debug](parsePtnTableFromNvramToStruct) 00182: NM_PTN_TABLE_BASE = 0x80000

 (none) mips #1 Wed Jul 31 14:05:23 CST 2019 (none)
(none) login: Into util_dbg_setMod, pModName(all), enable(1)
[Debug checkLedParamValid:341] Param: mode off  , delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode off  , delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode repeat, delayon 200, delayoff 200, blinkCount 0.
[Debug checkLedParamValid:341] Param: mode repeat, delayon 200, delayoff 200, blinkCount 0.
[Debug checkLedParamValid:341] Param: mode off  , delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode off  , delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode repeat, delayon 500, delayoff 500, blinkCount 0.
[Debug checkLedParamValid:341] Param: mode repeat, delayon 500, delayoff 500, blinkCount 0.
[Debug checkLedParamValid:341] Param: mode off  , delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode off  , delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode off  , delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode repeat, delayon 200, delayoff 200, blinkCount 0.
[Debug checkLedParamValid:341] Param: mode off  , delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode on   , delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode off  , delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode blink, delayon 500, delayoff 500, blinkCount 4.
[Debug checkLedParamValid:341] Param: mode disable, delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode enable, delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode blink, delayon 200, delayoff 200, blinkCount 3000.
[Debug checkLedParamValid:341] Param: mode stop , delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode off  , delayon 0  , delayoff 0  , blinkCount 0.
[Debug checkLedParamValid:341] Param: mode repeat, delayon 4200, delayoff 800, blinkCount 0.
[Debug checkLedParamValid:341] Param: mode stop , delayon 0  , delayoff 0  , blinkCount 0.
LED_RESET
	{ led_green     off      1   0   0   0 }
	{ led_yellow    off      1   0   0   0 }
	{ led_yellow    repeat   1   200 200 0 }
	{ led_green     repeat   1   200 200 0 }
LED_UPDATE_START
	{ led_green     off      1   0   0   0 }
	{ led_yellow    off      1   0   0   0 }
	{ led_yellow    repeat   1   500 500 0 }
	{ led_green     repeat   1   500 500 0 }
LED_UPDATE_FINISH
	{ led_yellow    off      1   0   0   0 }
	{ led_green     off      1   0   0   0 }
LED_DUT_NO_CALDATA
	{ led_green     off      0   0   0   0 }
	{ led_yellow    repeat   4   200 200 0 }
LED_SYS_INIT_PROCESS
	{ led_yellow    off      0   0   0   0 }
	{ led_green     on       0   0   0   0 }
LE[    5.210000] [Debug led_proc_write:624] Write led_yellow.
D_SYS_INIT_OK
	[    5.210000] [Debug led_common_write_proc:471] Execute LED action: { led_yellow    	{ 1   0   0   0   0 }
off      0   0   0   0 }
	{ led_green     blink    0   500 500 4 }
LED_DISABLE_ALL
	{ led_green     disable  2   0   0   0 }
LED_ENABLE_ALL
	{ led_green     enable   0   0   0   0 }
LED_LOCATE
	{ led_green     blink    3   200 200 3000 }
LED_LOCATE_STOP
	{ led_green     stop     1   0   0   0 }
LED_ISOLATED_START
	{ led_yellow    off      0   0   0   0 }
	{ led_green     repeat   2   4200 800 0 }
LED_ISOLATED_FINISH
	{ led_green     stop     0   0   0   0 }
[NM_Debug](parsePtn[    5.270000] [Debug led_proc_write:624] Write led_green.
TableFromNvramTo[    5.280000] [Debug led_common_write_proc:471] Execute LED action: Struct) 00182: N	{ 2   0   0   0   0 }
M_PTN_TABLE_BASE = 0x80000
[Debug ledListenEventHandler:148] Accept a new client.
[Debug ledClientEventHandler:110] GPIOD received led rule: LED_SYS_INIT_PROCESS.
<debug>_radio_region_init(): 158  @ read next region flag, parse finish
<debug>_radio_region_init(): 187  @ region:276, parse channel num:13
<debug>_radio_region_init(): 158  @ read next region flag, parse finish
<debug>_radio_region_init(): 187  @ region:276, parse channel num:19
GBK essid(TP-Link_2.4GHz_CB4FE2)
UTF8 essid(TP-Link_2.4GHz_CB4FE2)
GBK essid(TP-Link_5GHz_CB4FE3)
UTF8 essid(TP-Link_5GHz_CB4FE3)
[Debug ledListenEventHandler:148] Accept a new client.
[Debug ledClientEventHandler:110] GPIOD received led rule: LED_ENABLE_ALL.
[    6.430000] [Debug led_proc_write:624] Write led_green.
[    6.440000] [Debug led_common_write_proc:471] Execute LED action: 	{ 5   0   0   0   0 }
[    6.440000] [NOTICE led_common_write_proc:508] pledconf->backup.mode 0 1
[    6.510000] 
[    6.510000] Disable VlanManage, data.enable(0), data.vid(1)
[    6.520000] ath_spi_uid_read 0xe4694c68 
[    6.530000] ath_spi_uid_read 0x5b5a4028 
[NM_Debug](readFlashPublicKey) 00175: rsaKey=: BgIAAACkAABSU0ExAAQAAAEAAQDzyeWCpUptcSIr3Wuk6j3wEyGLbCalB127Ge315dfiwAV8UfeMi9m34xauO62IMNPSSm5biNChqO+eDyLG2dSndRA+BYnh6xFYu9t6PkxiJRvaumwejQwork0ohtXuqBC8k4yd1HlXcsI/rzvgZ0eDon5mdUzQ6Ac0iLA3RXDAng==!

Rsa verify success
[    6.660000] 
[    6.660000] manage vlan set port: ssh (22), http (80), https (443)
[    6.660000] 
[    6.660000] manage vlan set port: ssh (22), http (80), https (443)
[    6.690000] ath_spi_uid_read 0xe4694c68 
[    6.690000] ath_spi_uid_read 0x5b5a4028 
[NM_Debug](readFlashPublicKey) 00175: rsaKey=: BgIAAACkAABSU0ExAAQAAAEAAQDzyeWCpUptcSIr3Wuk6j3wEyGLbCalB127Ge315dfiwAV8UfeMi9m34xauO62IMNPSSm5biNChqO+eDyLG2dSndRA+BYnh6xFYu9t6PkxiJRvaumwejQwork0ohtXuqBC8k4yd1HlXcsI/rzvgZ0eDon5mdUzQ6Ac0iLA3RXDAng==!

Rsa verify success
[    8.110000] ath_tx99: Version 2.0
[    8.110000] Copyright (c) 2010 Atheros Communications, Inc, All Rights Reserved
[    8.480000] 
[    8.480000] ART Version : -48.0.0
[    8.490000] SW Image Version : -48.0.0.0.0
[    8.490000] Board Revision :  
[    8.490000] ar9300_attach: nf_2_nom -110 nf_2_max -60 nf_2_min -125 
[    8.520000] dfs_attach: event log enabled by default
[    8.530000] ath_descdma_setup: tx DMA: 2700 buffers 1 desc/buf 128 desc_len
[    8.540000] ath_descdma_setup: beacon DMA: 17 buffers 1 desc/buf 128 desc_len
[    8.550000] ath_descdma_setup: tim DMA: 34 buffers 1 desc/buf 128 desc_len
[    8.560000] ath_descdma_setup: uapsd_qnull DMA: 64 buffers 1 desc/buf 128 desc_len
[    8.560000] ath_tx_paprd_init sc 873e8000 PAPRD disabled in HAL
[    9.120000] hif_pci_enable_bus: con_mode = 0x0, device_id = 0x40
[    9.130000] PCI: Enabling device 0000:00:00.0 (0000 -> 0002)
[    9.130000] hif_pci_enable_bus: hif_enable_pci done *********** AR900B *************hif_pci_enable_bus: hif_type = 0xb, target_type = 0x9hif_pci_enable_bus: hif_pci_probe_tgt_wakeup donehif_target_sync: Loop checking FW signalhif_target_sync: Got FW signal, retries = 0hif_config_ce: ce_init donehif_config_ce: X, ret = 0hif_set_hia: Ehif_set_hia_extnd: E
[    9.180000] hif_pci_bus_configure: hif_set_hia donehif_configure_irq: Ehif_pci_configure_legacy_irq: Ehif_pci_configure_legacy_irq: X, ret = 0hif_enable: X OKhif_napi_create: NAPI structures initializedhif_napi_create: NAPI id 6 created for pipe 5hif_napi_event: received evnt: CONF cmd; v = 1 (state=0x1)hif_napi_event: setting configuration to ONol_ath_attach interface_id 1
[    9.370000] 
[    9.370000]  [Flash] : Ignore Module param
[    9.490000] ol_swap_wlan_memory_expansion: length:195073 size_left:195093 dma_size_left:262144 fw_temp:c0758004 fw_entry_size:195097
[    9.500000] ol_swap_wlan_memory_expansion: dma_virt_addr :a6280000 fw_temp: c0758008 length: 195073
[    9.510000] ol_swap_wlan_memory_expansion: length:0 size_left:12 dma_size_left:67071 fw_temp:c0787a0d fw_entry_size:195097
[   10.980000] wmi_unified_register_event_handler: Event id 62 is unavailable
[   10.990000] +htc_create ..  HIF :865c4000-htc_create: (0x865c1800)
[   11.000000] hif_enable_fastpath, Enabling fastpath mode
[   11.000000] +HWT
[   11.010000] hif_completion_thread_startup: pipe_num:0 pipe_info:0x865c705chif_completion_thread_startup: pipe_num:3 pipe_info:0x865c711chif_completion_thread_startup: pipe_num:4 pipe_info:0x865c715c
[   11.030000] -HWT
[   11.030000] Startup Mode-0 set
[   11.040000] htt_peer_map_timer_init Enter pdev 85b10000 hrtimer 85b14960
[   11.040000] 
[   11.040000]  htt_alloc_peer_map_mem : Alloc Success : host q vaddr 85b90000 paddr 5b90000
[   11.050000] 
[   11.050000]  htt_alloc_peer_map_mem : Flush Interval Configured to 256 pkts
[   11.070000] FW wireless modes: 0x1f9001
[   11.070000] wmi_service_coex_gpio 0, wmi_service_4_wire_coex_support 0, coex_version 0
[   11.080000] 
[   11.080000] Sending Ext resource cfg: HOST PLATFORM as 1
[   11.080000] fw_feature_bitmap as 50 to TGT
[   11.090000] ol_ath_service_ready_event: sw_cal_support_check_flag: 1
[   11.100000] EXT NSS Supported
[   11.110000] Support not added yet for Service 91
[   11.120000] Support not added yet for Service 92
[   11.120000] chunk 0 len 13568 requested , ptr  0x57a8000
[   11.130000] chunk 1 len 54272 requested , ptr  0x57b0000
[   11.130000] chunk 2 len 217088 requested , ptr  0x5040000
[   11.140000] chunk 3 len 675432 requested , ptr  0x5100000
[   11.140000] chunk 4 len 107520 requested , ptr  0x5020000
[   11.150000] chunk 5 len 6144 requested , ptr  0x57ac000
[   11.160000] chunk 6 len 1023768 requested , ptr  0x5200000
[   11.160000] chunk 7 len 0 requested , ptr  0xffffffff
[   11.170000] smart_log_init: Smart logging Enabled buf=85080000 (size=65536)
[   11.240000] Version = 16777216 3  status = 0
[   11.240000] htt_h2t_frag_desc_bank_cfg_msg - HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG sent to FW for radio ID = 1
[   11.260000] dfs_attach: event log enabled by default
[   11.270000] >>>> CB Set   (null)
[   11.270000] ath_lowi_if_netlink_init LOWI Netlink successfully created
[   11.280000] ol_ath_thermal_mitigation_attach: --
[   11.290000] ol_ath_pci_probe num_radios=0, wifi_radios[0].sc = 863c0380 wifi_radio_type = 2
[   11.290000] ath_sysfs_diag_init: diag_fsattr 
[   11.330000] +hif_update_pipe_callback pipeid 8
[   11.330000] -hif_update_pipe_callback
[   11.630000] ath_net80211_dfs_clist_update: called, cmd=1, nollist=  (null), nentries=0
[   11.640000] dfs_attach: event log enabled by default
Interface doesn't accept private ioctl...
HALDbg (8BE0): Operation not permitted
[   11.770000] wlan_vap_create : enter. devhandle=0x873f0380, opmode=IEEE80211_M_HOSTAP, flags=0x1
[   11.780000] wlan_vap_create : exit. devhandle=0x873f0380, vap=0x872c0000, opmode=IEEE80211_M_HOSTAP, flags=0x1.
ath0
[   11.800000] ath_net80211_dfs_clist_update: called, cmd=1, nollist=  (null), nentries=0
[   11.820000] dfs_attach: event log enabled by default
Removing interface ath0 failed
FAIL
Configuration file: /tmp/ath0.ap_bss (phy ath0) --> new PHY
Line 6: DEPRECATED: 'dump_file' configuration variable is not used anymore
ath0: Could not connect to kernel driver
Using interface ath0 with hwaddr 74:da:88:cb:4f:e2 and ssid "TP-Link_2.4GHz_CB4FE2"
ath0: interface state UNINITIALIZED->ENABLED
ath0: AP-ENABLED 
OK
Invalid command : HALDbg
Invalid command : chainmasksel
Interface doesn't accept private ioctl...
AMPDU (8BE0): Operation not permitted
Interface doesn't accept private ioctl...
AMPDUFrames (8BE0): Operation not permitted
Interface doesn't accept private ioctl...
AMPDULim (8BE0): Operation not permitted
[   12.420000] wlan_vap_create : enter. devhandle=0x863c0380, opmode=IEEE80211_M_HOSTAP, flags=0x1
[   12.430000] send_vdev_create_cmd_non_tlv: ID = 0 Type = 1, Subtype = 0 VAP Addr = 74:da:88:cb:4f:e3:
[   12.440000] su bfee 0 mu bfee 0 su bfer 0 mu bfer 0 impl bf 1 sounding dim 0
[   12.450000] wlan_vap_create : exit. devhandle=0x863c0380, vap=0x85380000, opmode=IEEE80211_M_HOSTAP, flags=0x1.
ath10
[   12.510000] Enable MCAST_TO_UCAST
Error for wireless request "Set Fragmentation Threshold" (8B24) :
    SET failed on device ath10 ; Invalid argument.
Removing interface ath10 failed
FAIL
Configuration file: /tmp/ath10.ap_bss (phy ath10) --> new PHY
Line 6: DEPRECATED: 'dump_file' configuration variable is not used anymore
ath10: Could not connect to kernel driver
Using interface ath10 with hwaddr 74:da:88:cb:4f:e3 and ssid "TP-Link_5GHz_CB4FE3"
ath10: interface state UNINITIALIZED->ENABLED
ath10: AP-ENABLED 
OK
[   12.930000] 
[   12.930000] manage vlan set ssid vlan: idx (0), intfName (ath0), vlan (0)
[   12.940000] 
[   12.940000] manage vlan set ssid vlan: idx (1), intfName (ath10), vlan (0)
[   13.030000] [Debug led_proc_write:624] Write led_yellow.

[Debug ledClien[   13.040000] [Debug led_common_write_proc:471] Execute LED action: tEventHandler:11	{ 1   0   0   0   0 }
0] GPIOD received led rule: LED_SYS_INIT_OK.
[   13.060000] [Debug led_proc_write:624] Write led_green.
[   13.060000] [Debug led_common_write_proc:471] Execute LED action: 	{ 3   0   500 500 4 }
[   13.070000] ath_spi_uid_read 0xe4694c68 
[   13.080000] ath_spi_uid_read 0x5b5a4028 
[NM_Debug](readFlashPublicKey) 00175: rsaKey=: BgIAAACkAABSU0ExAAQAAAEAAQDzyeWCpUptcSIr3Wuk6j3wEyGLbCalB127Ge315dfiwAV8UfeMi9m34xauO62IMNPSSm5biNChqO+eDyLG2dSndRA+BYnh6xFYu9t6PkxiJRvaumwejQwork0ohtXuqBC8k4yd1HlXcsI/rzvgZ0eDon5mdUzQ6Ac0iLA3RXDAng==!

Rsa verify success
[   14.230000] Switching to Tx Mode-0
now ok to start tddp---------------------
uclite init ok, now startup eap-cs ---------------------
[NM_Debug](parsePtnTableFromNvramToStruct) 00182: NM_PTN_TABLE_BASE = 0x80000
[TDDP_DEBUG]<debug>[main:1213] tddp init---
httpMudCreate: MUD 0x483d40 was created
[utilities_debug: httpSystemFirmwareInit:269]register rpm
httpServerCreate------------------
httpMudCreate: MUD 0x483d40 was created
[utilities_debug: httpSystemFirmwareInit:269]register rpm
httpServerCreate------------------
httpServerCreate: try to add port 80
httpServerCreate: try to add port 22080
[   18.690000] send_vdev_down_cmd_non_tlv for vap 0
[   18.700000] VDEV START
[   18.970000] su bfee 1 mu bfee 0 su bfer 1 mu bfer 1 impl bf 1 sounding dim 2
[   18.980000] send_vdev_up_cmd_non_tlv for vap 0
route: SIOCDELRT: No such process
connect: No such file or directory
Into util_dbg_setMod, pModName(all), enable(1)
[NM_Debug](nm_region_getRegionName) 00192: Flash region info, code: 276, name: EU.

Nice, I tried flashing over the fs-uboot with my own crafted uboot (both vanilla ap152 and j-d-r's), but it would freeze at:

## Starting application at 0x81000000 ...

In case you wanted the flash layout, I've made it available here: https://docs.google.com/spreadsheets/d/1D4J92n_HxZy9VS_5numgLe4cKsr8sf140ixCTbdZdgs/edit?usp=sharing

If I can make a compatible OpenWRT zImage, which has an ELF header like the EAP245v3 firmware does (with a squashfs rootfs), then I should actually be able to boot this thing properly with the factory firmware.

I just can't seem to find out how to do that. I've tried adding a few different things in target/linux/ath79/image/generic-tp-link.mk but they don't make a compatible image with the needed ELF header to boot successfully:

+define Device/tplink_eap245v3
+  #$(Device/tplink)                     # won't build a proper image
+  #$(Device/tplink-safeloader)  # won't build a proper image
+  $(Device/tplink-nolzma)          # won't build a proper image
+  ATH_SOC := qca9563
+  IMAGE_SIZE := 15360k
+  DEVICE_TITLE := TP-Link EAP 245 v3
+  DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct
+  TPLINK_BOARD_ID := EAP245V3
+  BOARDNAME := EAP245V3
+  LOADER_TYPE := gz
+  SUPPORTED_DEVICES += eap245v3
+endef
+TARGET_DEVICES += tplink_eap245v3

It's like the EAP245v3 has a completely different type of kernel image type compared to other TP-Link devices.

For reference, this is a hex dump of the beginning of the os-image partition, which u-boot boots using bootelf 0x9f0c0000:

00000000  7f 45 4c 46 01 02 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  00 02 00 08 00 00 00 01  80 2f 96 40 00 00 00 34  |........./.@...4|
00000020  00 14 81 40 70 00 10 01  00 34 00 20 00 01 00 28  |...@p....4. ...(|
00000030  00 08 00 07 00 00 00 01  00 00 00 00 80 2f 00 00  |............./..|
00000040  80 2f 00 00 00 14 80 e5  00 54 a1 00 00 00 00 07  |./.......T......|
00000050  00 01 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00009640  00 80 80 21 00 a0 88 21  00 c0 90 21 00 e0 98 21  |...!...!...!...!|
00009650  3c 04 80 44 24 84 80 f0  3c 06 80 84 24 c6 a1 00  |<..D$...<...$...|
00009660  ac 80 00 00 14 c4 ff fe  24 84 00 04 3c 04 80 44  |........$...<..D|
00009670  24 84 81 00 3c 1d 80 84  27 bd a1 00 3c 1f 80 30  |$...<...'...<..0|

Running binwalk on the original kernel partition gives:

$ binwalk block/kernel.bin 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             ELF, 32-bit MSB MIPS64 executable, MIPS, version 1 (SYSV)
51504         0xC930          gzip compressed data, maximum compression, from Unix, last modified: 1970-01-01 00:00:00 (null date)

So I think the ELF that u-boot is starting, is more of a second stage bootloader. The gzip compressed data is the actual kernel. When I realised this, part of the boot log suddenly made more sense: after the second u-boot brings up eth0, it loads a bunch of ELF sections. It then fires up the application (.text section), which finds a 'zimage' at 0x802FC930; matching up with the binwalk result. It then declares to begin compressing the kernel to RAM, after which Linux begins to boot.

The level of bootloader inception is starting to get quite high at this point: u-boot 1, u-boot 2, and some form of gunzip.

The TP-Link CPE510-v1 might be interesting to have a look at. It also uses a kernel loader (and this okli thing I haven't quite figured out yet).

Thanks for that link, I'll check it out :slight_smile:

I put the ELF binary into Ghidra to see what I could find. It does seem very basic and appears to only decompress the kernel.

A few of the strings from the binary that I can see are:

FUN_802fbb08("Uncompressing Linux at load address ");
FUN_802f9738("Out of memory while allocating z_stream");

These strings also show up here, which seems to indicate it's standard Linux code at least :slight_smile:

Nice catch! Turns out this is indeed nothing special, and the kernel's .config in TP-Link source code does indeed contain CONFIG_KERNEL_GZIP=y. I don't know what was holding them back from using CONFIG_KERNEL_LZMA=y though :thinking:

I'm not sure.. haha.

I did notice something interesting with the factory-uboot using binwalk:

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
145308        0x2379C         Certificate in DER format (x509 v3), header length: 4, sequence length: 64
166928        0x28C10         U-Boot version string, "U-Boot 1.1.4--LSDK-10.2-00082-4 (Mar 19 2018 - 14:55:50)"
168224        0x29120         CRC32 polynomial table, big endian
194987        0x2F9AB         HTML document header
213843        0x34353         HTML document footer
213856        0x34360         PNG image, 16 x 16, 8-bit/color RGBA, non-interlaced
214754        0x346E2         Zlib compressed data, best compression

There are HTML files contained within it. It seems there's some HTTP failsafe method to update the firmware, which I can't seem to trigger. I can get the automatic tftpboot by holding down the reset button, but not this web form.

I ran dd to extract the html files:

dd if=extracted/factory-boot.bin  skip=$((0x2F9AB)) bs=1 count=$((213843-194987))

<body id="boot-body">
    <div class="top" id="boot-main">
        <div class="top-header">
            <div class="top-header-wrap">
                <p id="tp-tag">TP-Link</p>
                <p id="product-tag">EAP245v3</p>
            </div>
        </div>
        <div id="top-main">
            <div class="top-content">
                <div id="upgrade-container">
                    <div class="error-note-container">
                        <p id="error-note">System error. The router cannot start up normally.<br/>Please upgrade your router. You can download the firmware file from www.tp-link.com.</p>
                    </div>
                    <form action="f2.htm" method="post" id="upgrade-form" target="upgrade-iframe" enctype="multipart/form-data">
...

Which is strange, because even overwriting the fs-uboot bootloader partition with a bad bootloader, my device still won't present me this webpage.

I'm making progress. I used the openwrt-ar71xx-generic-cpe510-v2-initramfs-kernel.bin image, which does use an ELF header. And presto!

## Starting application at 0x80060000 ...


OpenWrt kernel loader for AR7XXX/AR9XXX
Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
Looking for OpenWrt image... not found!

System halted!

I need to copy this over to the EAP245v3 configuration that I'm using and I should be able to boot :slight_smile:

1 Like

I was able to get a kernel somewhat booting, without the need for that loader:

eth0 up
eth0
Loading .text @ 0x80060000 (3913336 bytes)
Loading __ex_table @ 0x8041b680 (6696 bytes)
Loading .rodata @ 0x8041e000 (792048 bytes)
Loading .pci_fixup @ 0x804df5f0 (2192 bytes)
Loading __ksymtab @ 0x804dfe80 (24928 bytes)
Loading __ksymtab_gpl @ 0x804e5fe0 (17608 bytes)
Loading __ksymtab_strings @ 0x804ea4a8 (99130 bytes)
Loading __param @ 0x805027e4 (940 bytes)
Clearing __modver @ 0x80502b90 (1136 bytes)
Loading .data @ 0x80503000 (143200 bytes)
Loading .data..page_aligned @ 0x80526000 (8192 bytes)
Loading .init.text @ 0x80528000 (124928 bytes)
Loading .init.data @ 0x80546800 (34716 bytes)
Clearing .bss @ 0x80650000 (209456 bytes)
## Starting application at 0x804147c0 ...
[    0.000000] Linux version 4.14.171 (root@edca4f546068) (gcc version 7.5.0 (OpenWrt GCC 7.5.0 r10947-65030d81f3)) #0 Thu Feb 27 21:05:12 2020
[    0.000000] bootconsole [early0] enabled
[    0.000000] CPU0 revision is: 00019750 (MIPS 74Kc)
[    0.000000] SoC: Qualcomm Atheros QCA956X ver 1 rev 0
[    0.000000] Determined physical RAM map:
[    0.000000]  memory: 08000000 @ 00000000 (usable)
[    0.000000] Initrd not found or empty - disabling initrd
[    0.000000] OF: fdt: No valid device tree found, continuing without
[    0.000000] Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
[    0.000000] Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 32 bytes
[    0.000000] Zone ranges:
[    0.000000]   Normal   [mem 0x0000000000000000-0x0000000007ffffff]
[    0.000000] Movable zone start for each node
[    0.000000] Early memory node ranges
[    0.000000]   node   0: [mem 0x0000000000000000-0x0000000007ffffff]
[    0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x0000000007ffffff]
[    0.000000] random: get_random_bytes called from start_kernel+0x90/0x478 with crng_init=0
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 32512
[    0.000000] Kernel command line: rootfstype=squashfs,jffs2
[    0.000000] PID hash table entries: 512 (order: -1, 2048 bytes)
[    0.000000] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
[    0.000000] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
[    0.000000] Writing ErrCtl register=00000000
[    0.000000] Readback ErrCtl register=00000000
[    0.000000] Memory: 123212K/131072K available (3820K kernel code, 151K rwdata, 916K rodata, 1184K init, 204K bss, 7860K reserved, 0K cma-reserved)
[    0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS: 51
[    0.000000] Failed to get CPU node
[    0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 21474836475000000ns

I used:

  KERNEL_NAME := vmlinux.elf
  KERNEL_INITRAMFS_NAME := vmlinux-initramfs.elf
  KERNEL := kernel-bin | patch-cmdline

Which got me to where I am now.

The HTTP recovery can be started from the first bootloader. Interrupt by holding CTRL+B on boot and then run httpd (so you need to solder to access the serial port). They messed up their units when calling usleep (both in the v1 and v3), so instead of waiting 2s, it only waits for 200ms...

There's also the fwrecon command. It's possible this can be called either directly, or is used by the httpd after uploading a firmware. This command's code seems to indicate that it does in fact perform a firmware validation, including RSA checks.

ath> fwrecov
Usage:
fwrecov - TP-Link Firmware Recovery Tools
ath> help fwrecov
fwrecov address filelen

Hello,

ELF is kernel or loader with kernel built in.

What you see here is lzma-loader from ar71xx loader. Kernel is not compressed before and this compressor offers better ratio than in-kernel. Take care that uncompression can take 30s when u-boot does not enable caches for old versions (before this commit)

This is obtained with something like KERNEL := kernel-bin | patch-cmdline | lzma | loader-kernel on ar71xx, I don't know on ath79.

I used ELF image format in older releases, but kernel becomes too big to fit in partition, automatic splitting of firmware partition was not working so I switched to uImage.

You can switch back to ELF format, like this device inheriting from $(Device/tplink-safeloader) this may need to setup partitions in tools/firmware-utils/src/tplink-safeloader.c

edit: Tested and not working

2 Likes

Using this, produce bootable ELF. You miss append-dtb, patch-cmdline is for ignoring bad values in in bootargs, from broken TP-Link u-boot.

define Device/tplink_eap245-v1
  SOC := qca9563
  DEVICE_MODEL := EAP245
  DEVICE_VARIANT := v1
  TPLINK_BOARD_ID := EAP245-V1
  IMAGE_SIZE := 15872k
  DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca988x-ct
  SUPPORTED_DEVICES += eap245-v1
  LOADER_TYPE := elf
  KERNEL := kernel-bin | append-dtb | lzma | loader-kernel
  IMAGE/sysupgrade.bin := append-kernel | append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE)
endef
TARGET_DEVICES += tplink_eap245-v1

Kernel is not booting due to bug #2899. I don't know if rootfs is detected.