OpenWrt support for TP-Link Deco M4R

Very nice description, thank you. I was only missing the TP1 TP2 locations (I made the pictures in poor lighting conditions and my eyes are not as good as they once were I'm afraid).

I bought my USB-Serial for use with ESP8266-es so they are definitely the 3.3V signal level type, but I never had to use it with a router, as luckily I never bricked one completely. Usually the TFTP recovery methods worked for me up until now.

In this case I plan to use the uboot web recovery first. If I fsck it up, i'll fall back to the serial method. Maybe I should dump the SPI flash just in case...?

The ttl usb dongle I got for my esp8266s is signaling with 5V, which is fine for the esp since it's pins are 5V tolerant, but I wouldn't be so sure about that with the Deco. Definitely test the voltage between TX and GND of the dongle with a multimeter before you use it.

And I'm not sure if I understand the last part correctly. You can't flash OpenWrt via the recovery.

Some updates:
mtd is present in the firmware but I'm stuck on step 1, I can't figure out how to chop up the firmware so I get a kernel and rootfs file. I've tried searching but couldn't figure out what tool I should use. If anyone knows what I should do, please let me know.

I've read multiple times now that you have to cut off some info at the start of the oem image if you want to flash that directly to revert to stock (for other routers of course).

They all use dd for that:

Here is an example where they cut away the first 0x20200 (that is 131,584 = 257*512) bytes from original firmware:

With that you should be able to cut out the two different partitions of the sysupgrade image.

You might also be able to just write the whole sysupgrade image to "kernel". But no clue if that works.

After some figuring out I managed to cut up the openwrt image file into one kernel and one rootfs file, tried using mtd to write the partitions but it seemingly bricked the router (recovered it using bootloader recovery).
I ran these commands:

cd tmp
curl -LJO -k
dd if=openwrt-ath79-generic-tplink_deco-m4r-v1v2-squashfs-sysupgrade.bin of=rootfs.bin skip=10240 count=49152 bs=256
dd if=openwrt-ath79-generic-tplink_deco-m4r-v1v2-squashfs-sysupgrade.bin of=kernel.bin skip=2048 count=8192 bs=256
mtd write kernel.bin kernel
mtd write rootfs.bin rootfs

It flashed successfully:

But this left the router bricked. I'm not sure what I did wrong or if the block size I used to calculate the sizes and used in my dd commands were correct or whether I should have outputted them as .bin files.

Here are the instructions to flash this without soldering:
Credit @bobthebuilder for helping with this and for porting OpenWrt to this router.


Step 1:
Download this firmware image file. Credit @origami for sharing this.
GitHub Mirror

Flashing the firmware with telnet unlocked:
Set a static IP of on your computer.

Turn your router upside down and get a toothpick or a SIM unlocking tool (or some long and thin object that fits in the hole where the reset button resides).

Unplug your router from the wall socket and using your toothpick/sim tool hold the reset button and plug in your router to the wall and keep holding until the router LED starts flashing.

In a web browser open and you should get the bootloader recovery page. Click "Browse" and select the firmware file you just downloaded (extract it somewhere) and then click "Upgrade". Wait until the router flashes and restarts itself.

After it flashes remove the static IP.
Flashing OpenWrt:
Open a console window and type "telnet". Type "open router's IP" (by default it should be for the main router and 192.168.10X for secondary routers).
We have to download OpenWrt and using dd, chop up the firmware into a kernel and rootfs file.
Type "cd tmp" and then:

curl -LJO -k

Replace the link with a newer version in the future from the downloads website.

After it's downloaded type (make sure the name for openwrt bin is correct):

dd if=openwrt.bin of=kernel.bin skip=0 count=8192 bs=256
dd if=openwrt.bin of=rootfs.bin skip=8192 bs=256

You will get 1 kernel.bin and 1 rootfs.bin file
Now we flash it using mtd, type:

mtd write kernel.bin kernel
mtd write rootfs.bin rootfs

Note: This process is only needed for flashing the device from stock firmware to OpenWrt, upgrading OpenWrt after that can be done with a simple sysupgrade.

Now just type reboot and enjoy Wireless Freedom :wink:


You do? You can't just use the sysupgrade function?

I tried it but nothing happened, the router restarted back to 19.07.

Your MAC addresses are likely wrong or not working.

In 11-ath10k-caldata you're taking the MAC for 5G wifi out of the "info" partition, which doesn't exist in your .dts.

And in the .dts itself you're using <&uboot 0x1fc00> for eth0, but that's just some MAC every deco bootloader uses and not the MAC on the label on the bottom of your device.

wmac in the .dts doesn't have a MAC address at all.

Could it be that all of them start like this: 12-34-56-...?

This is important because end devices differenciate between different APs (that use the same SSID) by BSSID and that's usually the MAC of the used interface. And I'm guessing that all Decos running your firmware are going to have the same SSIDs.

Also having multiple wired devices with the same MAC in the same network is also going to create problems.

Thank you for your concern, I got my USB dongle from Adafruit for this purpose. It's the blue one with the Profilic PL2303 (I think it's a TA variant), the datasheet states, that the signal levels are 3.3v (CMOS) level not TTL. I think it will not blow up the Deco :slight_smile:

Since last time I have seen your conversation with @KinteLiX and read up on the subject. Am I right to assume that U-Boot is RSA locked? Then for complete support the RSA lock has to be disabled first, before we can flash any unsigned images via U-Boot recovery. Right now flashing anything on the device requires using the "leaked" developer firmware from @origami as it has the required signature and gives access to the device.

Anyway I was away for chistmas and I just got around to get my iron and cables. I will solder the UART tomorrow and try to collect information from serial.

Hi, I have a 21.02 port but the dts file was pretty bad on it (plus some other files), over the last couple of days I've improved it thanks to help from @bobthebuilder.

I've just pushed my latest dts file which has the firmware partition, which should fix sysupgrades (not sure, the verbose option didn't show any info that would help in finding the cause but that may have been it).

I think you still need to do the mtd method if going from 19.07 to mine because 19.07 lacks firmware partition.

From what I read up here our only option would be to find the RSA key, soldering or the leaked fw method. I'm not sure if disabling the RSA check in the bootloader is even possible.

Having a passing familiarity with RSA I doubt we could get the necessary private key to sign our own image (I will check the GPL pack from TP-Link for it, but it would have been a stupid mistake to leave it in there). The different parts of the image (kernel, rootfs, etc.) are individually hashed and signed, and these signatures are checked by U-Boot according to the documentation.

Interesting info, I also doubt you will find it there. In the meantime, I fetched and merged upstream changes (bumped Linux kernel version). I'm gonna use it to compile it and test sysupgrade.

1 Like

I have found this: U-Boot: Verified RSA Boot on ARM target (, gives some insight...

1 Like

Interesting, because RSA uses public and private keys, I wonder if the private key could be extracted from the router because the router's bootloader must check the image somehow, but I could be wrong so don't quote me on that. I don't think it would be legal to share it though.

And if you are already opening the device up and soldering wires to it, you could just flash OpenWrt to it without dealing with extracting keys.

Sysupgrade worked! Seems like the lack of firmware partition defined in dts was the issue.

Only the web-interface that is loaded by the bootloader if you press and hold the reset button during bootup is checking the RSA signature. Once you are in the command line of the bootloader (just type tpl multiple times during bootup) you could flash a jpeg of a horse to the flash memory and the bootloader wouldn't care.

So if you are soldering anyway then you don't need to worry about any RSA checks.

I have found this: U-Boot: Verified RSA Boot on ARM target (, gives some insight...

The Deco M4R V1 and V2 don't have an ARM SoC. The bootloader isn't checking what is in the flash. It only checks whatever you upload via the web interface before it flashes it.

I wonder if the private key could be extracted from the router because the router's bootloader must check the image somehow, but I could be wrong so don't quote me on that.

Yes, you are. Whatever is encoded with the private key can only be decoded with the public key and whatever is encoded with the public key can only be decoded with the private key.

So you will never find the private key on the router. That's just not how that works.

That's also how your bank does it with your online banking or how almost all websites these days do it with https. The server is the only one who knows the private key but it will gladly tell you the public key so you can encode messages with it that only the server can decode with its private key.

Sysupgrade worked! Seems like the lack of firmware partition defined in dts was the issue.

I'm betting that the label = "firmware"; is the important part here.

Did you upgrade from your second to last build to your last build or did you upgrade from my image?

I upgraded from my second to last build to my last build so it could work with 19.07 but I haven't tested that.

The second to last build still had kernel and rootfs as separate partitions in the .dts, right? Sounds good either way that it worked for you.

Are the MACs of the eth0 interface and of the first 2.4GHz SSID now the same as the one on the label on the bottom of the Deco? Is the first 5GHz MAC one less?

For instance if the MAC on the Label is E1:AA:BB:CC:DD:E0 then the first 5GHz SSID should have E1:AA:BB:CC:DD:DF (in Hex DF + 1 = E0, E0 + 1 = E1 and so on).

(OpenWrt will add 2 to the first byte of every following SSID so the second 2.4GHz SSID should have E3:AA:BB:CC:DD:E0 and the second 5GHz SSID should have E3:AA:BB:CC:DD:DF)

Actually no, my second to last build had kernel 5.4.163 and I upgraded to 5.4.168, both had firmware partitions defined, also I just tested it on my main deco which didn't have the firmware partition (I experimented on my secondary one) and it didn't work so you have to use mtd method to go to the image with the firmware partition defined.

I'll check this in a minute.
Edit: Yes, they are exactly how you said.