Custom U-Boot for TP-Link routers based on ath79 platform

Have You tried flash 'factory' image? through tftp? And remember:
ALWAYS USE -factory.img instead of sysupgrade one, because factory.img apply new DTS(partition tables) while sysupgrade won't.
(link to some tutorial for Netgear R7800, but idea is the same).

1 Like

this is not true on newer devices, i had boot failures on both qca9531 and qca9558 with missing art

1 Like

it won't work that way, you need to modify sources, in this case tools/firmware-utils/src/tplink-safeloader.c i think.

change

{"radio", 0x7f0000, 0x10000},

to

{"radio", 0xff0000, 0x10000},

other variables in that safeloader section might need to be adjusted as well

1 Like

Yes, I also did it using tftp didn't worked, back to the previous firmware and normally boots.

OK, I will look into this...

Yes, finally I found the reasons why the custom 16MB firmware bricks the router. I need to do lots of modifications in "tplink-safeloader.c" and also in "qca9563_tplink_archer-x6-v2.dtsi". Previously I just modified the "qca9563_tplink_archer-x6-v2.dtsi" as follows:

partition@30000 {
	compatible = "denx,uimage";
	label = "firmware";
	reg = <0x030000 0x7a0000>;
};

to

partition@30000 {
	compatible = "denx,uimage";
	label = "firmware";
	reg = <0x030000 0xfa0000>;
};

also the firmware image is not the last image "tplink" and "art" comes after that. Also I need to modify their starting offset as well as size offset.

partition@7d0000 {
	label = "tplink";
	reg = <0x7d0000 0x020000>;
	read-only;
};

art: partition@7f0000 {
	label = "art";
	reg = <0x7f0000 0x010000>;
	read-only;
};

and also modified "generic-tp-link.mk" as follows:

define Device/tplink_archer-c6-v2
  $(Device/tplink-safeloader-uimage)
  ATH_SOC := qca9563
  IMAGE_SIZE := 7808k
  DEVICE_TITLE := TP-Link Archer C6 v2
  TPLINK_BOARD_ID := ARCHER-C6-V2
  DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca9888-ct
endef
TARGET_DEVICES += tplink_archer-c6-v2

to

define Device/tplink_archer-c6-v2
  $(Device/tplink-safeloader-uimage)
  ATH_SOC := qca9563
  IMAGE_SIZE := 16000k
  DEVICE_TITLE := TP-Link Archer C6 v2
  TPLINK_BOARD_ID := ARCHER-C6-V2
  DEVICE_PACKAGES := kmod-ath10k-ct ath10k-firmware-qca9888-ct
endef
TARGET_DEVICES += tplink_archer-c6-v2

I didn't know about the "tplink-safeloader.c" has to be modified, thanks psyborg for pointing out me. I think I have found the code that I need to change in "tplink-safeloader.c". Here is the code section:

/** Firmware layout for the C6v2 */
{
	.id	= "ARCHER-C6-V2",
	.vendor	= "",
	.support_list =
		"SupportList:\r\n"
		"{product_name:Archer C6,product_ver:2.0.0,special_id:45550000}\r\n"
		"{product_name:Archer C6,product_ver:2.0.0,special_id:52550000}\r\n"
		"{product_name:Archer C6,product_ver:2.0.0,special_id:4A500000}\r\n",
	.support_trail = '\x00',
	.soft_ver = "soft_ver:1.0.0\n",

	.partitions = {
		{"fs-uboot", 0x00000, 0x20000},
		{"default-mac", 0x20000, 0x00200},
		{"pin", 0x20200, 0x00100},
		{"product-info", 0x20300, 0x00200},
		{"device-id", 0x20500, 0x0fb00},
		{"firmware", 0x30000, 0x7a9400},
		{"soft-version", 0x7d9400, 0x00100},
		{"extra-para", 0x7d9500, 0x00100},
		{"support-list", 0x7d9600, 0x00200},
		{"profile", 0x7d9800, 0x03000},
		{"default-config", 0x7dc800, 0x03000},
		{"partition-table", 0x7df800, 0x00800},
		{"user-config", 0x7e0000, 0x0c000},
		{"certificate", 0x7ec000, 0x04000},
		{"radio", 0x7f0000, 0x10000},
		{NULL, 0, 0}
	},

	.first_sysupgrade_partition = "os-image",
	.last_sysupgrade_partition = "file-system",
}

I rebuilt the openwrt firmware with all proper modification and all the partition offsets replaced with proper calculation in the source code of openwrt, compiled and flashed successfully. Running with >8MB free space, everything is ok until I reboot the router!!! Then I found the same problem, u-boot is culprit here it checks for the partition offsets and if it's found any tweaking then it prevent the loading of kernel to the memory and goes to the recovery mood. Sets router ip address to 192.168.0.1 then when I open the ip from web browser it shows a tplink firmware recovery page insisting browse and upload a firmware. All the modifications are not enough it definitely needs a custom u-boot.

This doesn't make a lot of sense since the partition changes are in the OpenWrt code that the bootloader would not be aware of. Perhaps the bootloader is looking for some piece of data in the tplink or ART partitions which no longer exist in their expected places. Have you looked at the bootloader serial log?

1 Like

Absolutely, the bootloader will search for tplink and art in their original places. This router doesn't have serial header, though I found a dot trace on the board saying uart rx but did not found the tx.

I searched on the net about tp_uart, what I found is tp_uart is a proprietary 1wire protocol which then father translate into uart. Also I've found in a datasheet of microchip that there is a 1wire half duplex uart protocol and interface also. Tp-link makes difficult things these days so that no one can easily do a mod.

I don't think this is the same as Siemens TP-UART aka KNX. That is a standard for building HVAC control involving long cable runs and multi-drop taps.

More likely it is a simple wired-or connection of 3.3 volt TX and RX. If you connect only the RX wire of your converter it may work in a receive-only manner.

1 Like

I think so... No output then how I will get the u-boot logs?

i'd help you but fccid photos are shit as usual. try looking on the board and find tp_uart out. if there is no any you'll need to discover it. probably is pulled out and left unmarked.

1 Like

I did not found either. I've another idea in my mind, Archar-C6 v2.0 US version has same hardware only the difference in some LED GPIOs and the 16MB flash, if I get a raw backup of stock firmware taken directly from the flash rom then with some tweaking with serial number in tplink partition that might work on Archar-C6 v2.0 EU/RU version. Previously I restored the RU version of firmware upgrade image from tplink website and then I flashed using openwrt firmware upgrade, it worked!

Can you trace it to a CPU pin# ? I guess Tx will be somewhere around.

1 Like

You also looked at the bottom side of the board, right?

1 Like

Nope, there is a huge heatsink attached to the circuit board.

I am successfully able to boot custom compiled moded 16MB OpenWrt just replacing u-boot with breed bootloader and moved art,tplink partitions to <8mb-flash-original-offset> + 0x80000 according to newly compiled OpenWrt. Also modified the proper offsets of firmware, tplink, art partitions in OpenWrt source code.

Now the problem is, every time turned off the router need to manually boot to the openwrt firmware via breed telnet issuing command "boot flash 0x030000". Breed autoboot is not working because this breed bootloader works like 8MB flash layout.

Here are the console-input/output:

C:\Users\Rupam>

C:\Users\Rupam>ping 192.168.1.1 /t

Pinging 192.168.1.1 with 32 bytes of data:
Reply from 192.168.1.1: bytes=32 time<1ms TTL=64
Reply from 192.168.1.1: bytes=32 time<1ms TTL=64
Reply from 192.168.1.1: bytes=32 time<1ms TTL=64
Reply from 192.168.1.1: bytes=32 time<1ms TTL=64
Reply from 192.168.1.1: bytes=32 time<1ms TTL=64

Ping statistics for 192.168.1.1:
    Packets: Sent = 5, Received = 5, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms
Control-C
^C

telnet 192.168.1.1

Boot and Recovery Environment for Embedded Devices
Copyright (C) 2018 HackPascal <hackpascal@gmail.com>
Build date 2018-12-29 [git-135bed9]
Version 1.1 (r1266)

Starting breed built-in shell

breed> help
Available commands:
about    - About this bootloader
abstatus - Interrupt status of autoboot
arp      - Display ARP table
autoboot - Detect firmware type and boot automatically
boot     - Boot firmware
btntst   - Test GPIO of buttons
dhcp     - Display DHCP leases
env      - Environment variables utility
envconf  - Configure environment variable block
exit     - Exit from telnet
flash    - Flash utility
gpio     - GPIO utilities
help     - Show available commands
mdio     - MDIO utility
mem      - Memory operation utilities
net      - Network control
netstat  - Display network state
reset    - Restart device
setbrg   - Set baudrate
spi      - SPI utility
sysinfo  - Display system information
thread   - Display all threads
wget     - Retrieval file through HTTP

breed> boot help
Usage:
  boot mem <addr>   - Boot from memory address or memory-mapped address
  boot flash [bank <n>] <addr>   - Boot from flash
  boot linux <addr> - Boot linux kernel at <addr>
  boot raw <addr>   - Disable interrupts and jump to <addr>
  boot breed <addr> - Boot given breed file at <addr>

breed> boot flash 0x030000
Trying to boot firmware from 0x00030000 in flash bank 0 ...
Reading data into memory ...
U-Boot firmware image header detected.
    Image Name:   MIPS OpenWrt Linux-4.14.133
    Data Size:    1699542 Bytes
    Load Address: 80060000
    Entry Point:  80060000
Uncompressing data (LZMA) ...

Connection to host lost.
C:\Users\Rupam>

Modified qca9563_tplink_archer-x6-v2.dtsi :

// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/dts-v1/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>

#include "qca956x.dtsi"

/ {
   chosen {
   	bootargs = "console=ttyS0,115200n8";
   };

   aliases {
   	led-boot = &power;
   	led-failsafe = &power;
   	led-running = &power;
   	led-upgrade = &power;
   };

   leds {
   	compatible = "gpio-leds";

   	power: power {
   		label = "tp-link:green:power";
   		gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
   		default-state = "on";
   	};

   	wlan2g {
   		label = "tp-link:green:wlan2g";
   		gpios = <&gpio 15 GPIO_ACTIVE_LOW>;
   		linux,default-trigger = "phy1tpt";
   	};

   	wlan5g {
   		label = "tp-link:green:wlan5g";
   		gpios = <&gpio 19 GPIO_ACTIVE_LOW>;
   		linux,default-trigger = "phy0tpt";
   	};

   	lan {
   		label = "tp-link:green:lan";
   		gpios = <&gpio 20 GPIO_ACTIVE_LOW>;
   	};

   	wan {
   		label = "tp-link:green:wan";
   		gpios = <&gpio 7 GPIO_ACTIVE_LOW>;
   	};

   	wan_fail {
   		label = "tp-link:amber:wan";
   		gpios = <&gpio 8 GPIO_ACTIVE_LOW>;
   	};

   	wps {
   		label = "tp-link:green:wps";
   		gpios = <&gpio 9 GPIO_ACTIVE_LOW>;
   	};
   };

   keys {
   	compatible = "gpio-keys";

   	reset {
   		label = "Reset button";
   		linux,code = <KEY_RESTART>;
   		gpios = <&gpio 5 GPIO_ACTIVE_LOW>;
   		debounce-interval = <60>;
   	};

   	wps {
   		label = "WPS button";
   		linux,code = <KEY_WPS_BUTTON>;
   		gpios = <&gpio 6 GPIO_ACTIVE_LOW>;
   		debounce-interval = <60>;
   	};
   };
};

&pcie {
   status = "okay";
};

&uart {
   status = "okay";
};

&gpio {
   status = "okay";
};

&spi {
   status = "okay";
   num-cs = <1>;

   flash@0 {
   	compatible = "jedec,spi-nor";
   	reg = <0>;
   	spi-max-frequency = <25000000>;

   	partitions {
   		compatible = "fixed-partitions";
   		#address-cells = <1>;
   		#size-cells = <1>;

   		partition@0 {
   			label = "u-boot";
   			reg = <0x000000 0x020000>;
   			read-only;
   		};

   		mac: partition@20000 {
   			label = "mac";
   			reg = <0x020000 0x010000>;
   			read-only;
   		};

   		partition@30000 {
   			compatible = "denx,uimage";
   			label = "firmware";
   			reg = <0x030000 0xfa0000>;
   		};

   		partition@fd0000 {
   			label = "tplink";
   			reg = <0xfd0000 0x020000>;
   			read-only;
   		};

   		art: partition@ff0000 {
   			label = "art";
   			reg = <0xff0000 0x010000>;
   			read-only;
   		};
   	};
   };
};

&mdio0 {
   status = "okay";

   phy-mask = <0>;

   phy0: ethernet-phy@0 {
   	reg = <0>;
   	phy-mode = "sgmii";
   	qca,mib-poll-interval = <500>;

   	qca,ar8327-initvals = <
   		0x04 0x00080080 /* PORT0 PAD MODE CTRL */
   		0x7c 0x0000007e /* PORT0_STATUS */
   		>;
   };
};

&eth0 {
   status = "okay";

   phy-mode = "sgmii";
   mtd-mac-address = <&mac 0x8>;
   phy-handle = <&phy0>;
};

&wmac {
   status = "okay";

   mtd-cal-data = <&art 0x1000>;
   mtd-mac-address = <&mac 0x8>;
};

Modified portion of tplink-safeloader.c :

/** Firmware layout for the C6v2 */
{
	.id	= "ARCHER-C6-V2",
	.vendor	= "",
	.support_list =
		"SupportList:\r\n"
		"{product_name:Archer C6,product_ver:2.0.0,special_id:45550000}\r\n"
		"{product_name:Archer C6,product_ver:2.0.0,special_id:52550000}\r\n"
		"{product_name:Archer C6,product_ver:2.0.0,special_id:4A500000}\r\n",
	.support_trail = '\x00',
	.soft_ver = "soft_ver:1.0.0\n",

	.partitions = {
		{"fs-uboot", 0x00000, 0x20000},
		{"default-mac", 0x20000, 0x00200},
		{"pin", 0x20200, 0x00100},
		{"product-info", 0x20300, 0x00200},
		{"device-id", 0x20500, 0x0fb00},
		{"firmware", 0x30000, 0xfa9400},
		{"soft-version", 0xfd9400, 0x00100},
		{"extra-para", 0xfd9500, 0x00100},
		{"support-list", 0xfd9600, 0x00200},
		{"profile", 0xfd9800, 0x03000},
		{"default-config", 0xfdc800, 0x03000},
		{"partition-table", 0xfdf800, 0x00800},
		{"user-config", 0xfe0000, 0x0c000},
		{"certificate", 0xfec000, 0x04000},
		{"radio", 0xff0000, 0x10000},
		{NULL, 0, 0}
	},

	.first_sysupgrade_partition = "os-image",
	.last_sysupgrade_partition = "file-system",
}

Modified partition offsets defined in tplink partition:
From:

partition fs-uboot base 0x00000 size 0x20000
partition default-mac base 0x20000 size 0x00200
partition pin base 0x20200 size 0x00100
partition product-info base 0x20300 size 0x00200
partition device-id base 0x20500 size 0x0fb00
partition os-image base 0x30000 size 0x1b649d
partition file-system base 0x1f0000 size 0x5b9400
partition soft-version base 0x7d9400 size 0x00100
partition extra-para base 0x7d9500 size 0x00100
partition support-list base 0x7d9600 size 0x00200
partition profile base 0x7d9800 size 0x03000
partition default-config base 0x7dc800 size 0x03000
partition partition-table base 0x7df800 size 0x00800
partition user-config base 0x7e0000 size 0x0c000
partition certificate base 0x7ec000 size 0x04000
partition radio base 0x7f0000 size 0x10000

To:

partition fs-uboot base 0x00000 size 0x20000
partition default-mac base 0x20000 size 0x00200
partition pin base 0x20200 size 0x00100
partition product-info base 0x20300 size 0x00200
partition device-id base 0x20500 size 0x0fb00
partition os-image base 0x30000 size 0x1b649d
partition file-system base 0x1f0000 size 0xdb9400
partition soft-version base 0xfd9400 size 0x00100
partition extra-para base 0xfd9500 size 0x00100
partition support-list base 0xfd9600 size 0x00200
partition profile base 0xfd9800 size 0x03000
partition default-config base 0xfdc800 size 0x03000
partition partition-table base 0xfdf800 size 0x00800
partition user-config base 0xfe0000 size 0x0c000
partition certificate base 0xfec000 size 0x04000
partition radio base 0xff0000 size 0x10000

Breed Web-Recovery: (built for 8MB layout, recovering from it, replacing firmware,art,tplink partitions to wrong offsets.)

OpenWrt Boot Successful

More Flash Available

EVERYTHING IS WORKING FINE BUT THE BREED AUTOBOOT, I SEARCHED ON THE NET CAN'T FOUND BREED SOURCE-CODE!
Maintainer of Breed Bootloader Weijie Gao (aka: hackpascal) did not open-sourced it's source code. i only found precompiled binaries in his website.

IF ANYONE KNOWS HOW TO COMPILE CUSTOM U-BOOT FROM SOURCE OR MODIFY BREED TO BOOT LINUX KERNEL FROM OFFSET 0x030000, PLEASE HELP ME!!!

since you are able to reflash chip using ch341a, as i've said your best option is to build image from this repo https://github.com/j-d-r/u-boot-QCA956x, once you verify that compiling works, run make clean and add your device profile. if you screw something and image doesn not boot you can easily reflash it. i can assist you with this, but not with breed as the guy who publish it doesnt provide source code, errors are unknown and hard to debug or even fix and there is no device specific support but generic only for the whole soc series. such a bootloader cannot work reliably, so get rid of the breed

1 Like

Thanks Dude, I'm looking into it. Which file do I need to add my device profile?