Adding support for Canadian TP-Link Archer C60 v2.0

I was trying to install the latest stable release 19.07.4 on a TP-Link Archer C60(CA) v2.0 running factory OEM firmware and I ran into an error. After asking on Reddit I was told that is because the special_id for the Canadian model is not in the official releases but I can easily add it and compile my own.

So I forked the master branch, added the new special_id line, and built my images. That worked fine and I ended up with a *-factory.bin file. Instead of installing this on my hardware I figured I'd rather work from the stable release branch and config.

I checked out the commit tagged v19.07.4, made my changes, and created a branch. I downloaded the official config.buildinfo file ( and made it my initial .config file. I used "make menuconfig" to set my target and then I ran the build. This only produced a *-sysupgrade.bin file and no factory file.

I've been searching around trying to figure out how to make the factory file and so far have come up empty.

What am I missing?

This happens to me too sometimes...but I don't know why exactly.

Don't bother with stable branch for development, master is not as "unstable" as you think it is. The worst thing that has happened to me flashing master is the wifi driver having a bug. As long as you have a serial cable with a reliable method to reflash then there's no issues.

Also no need to download the config.buildinfo, just run make menuconfig and it generates a default one if .config does not exist yet.

I don't have a reliable method to reflash or serial cable setup. To be honest all that stuff is way out of my comfort zone. I guess I could spend time becoming comfortable with that but I was trying to opt for the stable approach because it seems my router (at least the US version) is well supported by OpenWrt.

Something I just noticed is that the profiles.json file that gets output from the build (bin/targets/ath79/generic/profiles.json) only has a type:sysupgrade entry in the "profiles.tplink_archer-c60-v2.images" array of the JSON. I've been trying to work backwards from there to see how the configuration determines which images to build.

It should just be the makefile for all the config...and the build process creates the JSON file...

Have you tried editing the US variant instead of adding a CA variant?

BTW, even if you make a factory.bin on stable branch, you're assuming that everything about the board is identical to the US version. It probably is identical, but if there is a difference in partitions for example, you will have a lot of problems after flashing. I would recommend grabbing a serial cable anyway and have a look around on the OEM image.

I just added a new special_id to the TP-Link Archer C60 v2.0 model entry directly rather than adding a whole new model.

As far as I can tell I have to open the router and add a serial header to the board somehow. Still figuring this out....

Yeah soldering pins are best, but if you can't solder it is possible to have decent connections using paperclips, folding one of the tips so that its large enough to push into the through-hole for a friction fit.

You might not need serial access, read the commit message for the US variant. If you are able to TFTP flash then you can easily reflash if something goes wrong.;a=commit;h=974d6958a7c6332438ab4cda98e72156c8d944ed

Edit: Adrian says "UART header on PCB". probably this means the pins are there already

1 Like

OK now I'm really confused. It no longer seems to matter which branch I build or whether it has my patch in it or not. It never builds the factory.bin file anymore. Now I'm trying to find the combination of steps I used the first time that worked. I just started from scratch again and it didn't. Is there some step in the build process that could persist between different checkouts of the repo (in different folders)? Does the scripts/feeds update/install steps do anything outside of the individually checked out branch?

you have to resync the feeds whenever you switch between branches with large difference in time or commit number (like stable vs master). there is a make command that does both update and install together
make package/symlinks
You can also make sure your config is in sync with make clean defconfig. If .config file does not exist yet, do make menuconfig instead.

other than that, I'm not sure

Started from a new checkout again. Redid all steps a few times with different branches. I think I've confirmed that I can build a factory image on the stable and master official branches however if I add my change to either the build succeeds but I don't end up with a factory image. So I suspect there is something wrong with my changes.

All I changed is I added a new special_id line to the tplink-safeloader.c file here:

make sure you are on a local branch instead of "detached HEAD" state
git status

if you are in detached state make a local branch
git checkout -b C60-canada

if your changes show a modified file in git status, make it into a commit
git add -A
git commit --signoff

wipe the buildtree clean and redownload feeds, and configure
make distclean package/symlinks menuconfig

make sure your changes are still there (or that the commit is there with git log)

and build

I managed to get it to build correctly by replacing one of the existing special_id entries instead of adding a new one. The router accepted the firmware and upgraded. So one step forward.

The install I did must not have contained the web interface because AFAICT it isn't running. I can SSH into the router and poke around but no web interface. Looking back I can see that I reset my config file to the defaults then told it which device to build but I didn't specify any packages or anything. Whoops.

I'm now rebuilding again but starting from this config file:

As far as I understand I should be able to upgrade to the newly built sysupgrade firmware version by SFTPing it to the router and using the sysupgrade command directly.

Just waiting for my build to finish now.

1 Like

In case someone else comes across the same issue here is the answer:

Official firmware does not yet support the Canadian version but it can be added by adding the special_id 43410000 to the tplink-safeloader.c file entry for this model. Adding another line doesn't work and won't compile properly so you have to replace one of the existing special_id lines.

Use the official config file for the release branch you are building as a starting point if you want a version with all the packages and features that official firmware includes. In my case that was this file because I was building from release 19.07.4

I'm still going to try to figure out what it takes to get the Canadian special_id included in the official release so that this just works for others in the future.

@pandasuit your personal build issues is not stopping you from adding official support. I am pretty sure there is something else going on thats stopping factory.bin compile. BTW you can do the image recipe step again after a complete build with verbose output and hunt for the issue in the resulting txt.

using nohup
nohup make V=s target/linux/install &
or using tee
make V=s target/linux/install | tee -a output.txt

Make a PR with your commit that adds the line. Whoever reviews your PR will let you know if anything is wrong. If they accept it you can flash a snapshot image a few hours later.

Edit: Again, dowloading the config.buildinfo is a pointless step. The only difference is LuCI, simply select it in make menuconfig under LuCI --> Collections.

I've done this a few times and don't see anything obvious in the output. The build succeeds without errors or warnings. I see these lines at the bottom of the output and yet the file is not there:

dd if=/home/pandasuit/openwrt/openwrt/build_dir/target-mips_24kc_musl/linux-ath79_generic/root.squashfs >> /home/pandasuit/openwrt/openwrt/build_dir/target-mips_24kc_musl/linux-ath79_generic/tmp/openwrt-ath79-generic-tplink_archer-c60-v2-squashfs-factory.bin
/home/pandasuit/openwrt/openwrt/staging_dir/host/bin/tplink-safeloader -B ARCHER-C60-V2 -V r11208-ce6496d796 -k /home/pandasuit/openwrt/openwrt/build_dir/target-mips_24kc_musl/linux-ath79_generic/tplink_archer-c60-v2-kernel.bin -r /home/pandasuit/openwrt/openwrt/build_dir/target-mips_24kc_musl/linux-ath79_generic/tmp/openwrt-ath79-generic-tplink_archer-c60-v2-squashfs-factory.bin -o /home/pandasuit/openwrt/openwrt/build_dir/target-mips_24kc_musl/linux-ath79_generic/tmp/ -j   && mv /home/pandasuit/openwrt/openwrt/build_dir/target-mips_24kc_musl/linux-ath79_generic/tmp/ /home/pandasuit/openwrt/openwrt/build_dir/target-mips_24kc_musl/linux-ath79_generic/tmp/openwrt-ath79-generic-tplink_archer-c60-v2-squashfs-factory.bin || rm -f /home/pandasuit/openwrt/openwrt/build_dir/target-mips_24kc_musl/linux-ath79_generic/tmp/openwrt-ath79-generic-tplink_archer-c60-v2-squashfs-factory.bin
cp /home/pandasuit/openwrt/openwrt/build_dir/target-mips_24kc_musl/linux-ath79_generic/tmp/openwrt-ath79-generic-tplink_archer-c60-v2-squashfs-factory.bin /home/pandasuit/openwrt/openwrt/bin/targets/ath79/generic/openwrt-ath79-generic-tplink_archer-c60-v2-squashfs-factory.bin

In a conversation on Reddit I got the response

Great thinking, I forgot how adding an entry (instead of replacing) would probably mess the partitioning... Sucks that this means this won't be as easily upstream-able.

Just publish a PR anyway, like I said, maintainers will figure it out

Very timely info for me gents...thanks!! - I just bought the same router earlier this week and I'm a first-timer with OpenWRT.
I took the direct binary file modification approach - I opted to bypass a toolchain setup with code recompile and the related makefile mysteria. While official support for the CA version would be best going forward, at least I have my router up and running with the current version of OpenWRT.
Here is what I did:

  • download the 19.07.4 -factory.bin file
  • change the "4252" at offset 0x2079 to "4341" (the CA special_id)
  • recalculated the MD5 hash (using info in the tplink-safeloader.c file) to be
    61 9A BF 79 B8 79 08 B8 A4 EE F2 79 F9 76 33 FB
  • replace bytes at offset 4-19 in the .bin file to the hash values above
  • flashed the router using the TFTP tp_recovery.bin method (server at

BTW - I used to modify the .bin file - it's a great implementation.

@TedH Good to hear you figured it out that way. I highly recommend giving a try at building Openwrt locally if you have the time (maybe when official support is figured out here), I think you would find it very smooth and easy. Honestly it is a mystery to me why adding this one line is causing so many issues. I make custom images for about 10 different boards so when it is flashed it has the config and packages already and I only have issues when backporting. Here's the quick build guide and required packages