TFTP download from TP-Link Archer C2 does not work properly

Use 81000000 instead. The kernel uncompresses and moves itself to the area of 80060000 before starting. 81000000 is 16 MB from the start of RAM, leaving 16 MB space for the kernel to relocate to.

An 80100000 address (1 MB from the start of RAM) is in the destination range, so it ends up overwriting itself and crashing.

Thank you, I was unaware of how exactly this works. I have used the 0x80100000 address because that is the default address that the bootm command is configured to boot from.

I do not have the device readily available for experiments right now to verify whether using a different address further from the beginning would help. But I might try it in the future.

Thank you once again.

Heeey i finally got OpenWRT installed on my Archer C2, and this without a serial connection :partying_face:

In the beginning i flashed the TP link firmware version "Archer_C2(EU)_V1_160512" on my device, just to try something new.

I wasn't sure about the corresponding parameters to Use anticipation window ofโ€ with 1000 bytes for the linux tftp-hpa server and didn't know how to configure it, so i fired up my old windows machine and installed tftpd64 on it.
There i could easily set the anitcipation window and finally the transmission completed without any error.

TBH I'm not sure if the older firmware version or the Windows TFTP server did the trick, but if anyone else stumbles across this, definitely try both before opening up your case.

Thanks to everyone here who helped me :heart:

1 Like

I have tried booting the initramfs OpenWrt image from memory address 0x81000000 on an Archer C2 device which does not experience the TFTP transfer issues (serial number 2161373008976) and I can confirm that it works:

MT7620 # tftpboot 0x81000000

 netboot_common, argc= 2

 NetTxPacket = 0x83FE5800

 KSEG1ADDR(NetTxPacket) = 0xA3FE5800

 NetLoop,call eth_halt !

 NetLoop,call eth_init !
Trying Eth0 (10/100-M)

 Waitting for RX_DMA_BUSY status Start... done


 ETH_STATE_ACTIVE!!
*** Warning: no boot file name; using 'test.bin'
TFTP from server 192.168.0.100; our IP address is 192.168.0.1
Filename 'test.bin'.

 TIMEOUT_COUNT=10,Load address: 0x81000000
Loading: Got ARP REPLY, set server/gtwy eth addr (74:d4:35:e7:5d:9e)
Got it
#################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #############################################################
done
Bytes transferred = 4635481 (46bb59 hex)
NetBootFileXferSize= 0046bb59
MT7620 # bootm 0x81000000
do_bootm:argc=2, addr=0x81000000
## Booting image at 81000000 ...
   Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80000000) ...
## Giving linux memsize in MB, 64

Starting kernel ...

[    0.000000] Linux version 5.4.86 (builder@buildhost) (gcc version 8.4.0 (OpenWrt GCC 8.4.0 r15448-980dca6b7f)) #0 Thu Jan 7 01:38:57 2021

I have also tried booting the initramfs OpenWrt image from memory address 0x81000000 on an Archer C2 device which does experience the TFTP transfer issues (serial number 2161374002651) and I can confirm that it also works:

MT7620 # loadb 0x81000000
## Ready for binary (kermit) download to 0x81000000 at 115200 bps...
## Total Size      = 0x0046bb59 = 4635481 Bytes
## Start Addr      = 0x81000000
MT7620 # bootm 0x81000000
do_bootm:argc=2, addr=0x81000000
## Booting image at 81000000 ...
   Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80000000) ...
## Giving linux memsize in MB, 64

Starting kernel ...

[    0.000000] Linux version 5.4.86 (builder@buildhost) (gcc version 8.4.0 (OpenWrt GCC 8.4.0 r15448-980dca6b7f)) #0 Thu Jan 7 01:38:57 2021

I have tried to visually compare the boards of the two Archer C2 devices that I have, one without TFTP flashing issues and the other one with TFTP flashing issues. They look very similar:

Board 1 of Archer C2 with serial number 2161373008976 (without TFTP flashing issues):

Board 2 of Archer C2 with serial number 2161374002651 (with TFTP flashing issues):

I have noticed several differences between these two boards:

  1. The label on the switch part reads 3FC2-03 on Board 1 and 3FC2-05 on Board 2.
  2. White text in the upper-left corner reads 1601 on Board 1 and 1551 on Board 2.
  3. The label on the GROUP-TEK HST-24002SAR chip reads 1534 on Board 1 and 1546 on Board 2.
  4. The label on the GROUP-TEK HST-48002SAR chips reads 1544 on Board 1 and 1543 on Board 2.

There are more differences in serial numbers but I suppose that those are insignificant. In general, I do not see into the details of how could minor differences like these potentially influence the behavior of the bootloader and its ability to configure the ethernet interface so that it is able to successfully perform the TFTP download.

1 Like

The four digit numbers are date codes (year-week). So board 2 was made the second to the last week in 2015, two weeks before board 1 being made the first week in 2016. The chips were made at various times during 2015.

The difference is going to be in the bootloader code itself. Running OpenWrt you can compute the MD5 of the bootloader partitions.
md5sum /dev/mtd0ro

The part number of the flash chip may be different. The flash chip is 8 pins, it should be the one near the center of the board, unless it is on the bottom. The flash chip is also identified in the OpenWrt kernel boot log.

Thank you, it did not occur to me that these numbers could relate to dates. What you suggest makes sense.

As mentioned above, these two devices use the same bootloader:

Consequently, the binary images of the bootloaders extracted from the /dev/mtd0ro mtd devices on either of the routers are also exactly the same. They contain the following U-Boot version string: "U-Boot 1.1.3 (Aug 31 2015 - 16:32:16)".

I have also extracted the bootloaders from all 3 vendor-provided firmware versions that are currently available on the TP-Link's website. They are all exactly the same and they are also exactly the same as the bootloader which is currently present on the mentioned two devices.

I am not aware of any other publicly available bootloader for this device.

I had exactly the same issue. The device kept failing when TFTP'ing from a Linux box. Slowed down the server interface to 10Mb, still wouldn't work. Finally spun up a virtual Windows10 machine with tftpd32 with the anticipation window set to 1000 bytes. First time failed at 6% but this was further than tftpd-hpa got me. Second time succeeded. I have flashed a LOT of devices but this is the first time it nearly drove me insane.

I have tried to look into why the TFTP servers that are typically available on Linux (namely tftp-hpa and atftp) would behave differently than Tftpd32 or Tftpd64 which is configured to use the "anticipation window" option.

The "anticipation window" behavior

On the Tftpd32's website, there is a FAQ section which contains the question "How do i tune the anticipation window ?". The answer mentions that:

Tftpd32 will send data packets without waiting for acknowledgements

I assume that it refers to the data packets within the anticipation window.

Also, on the Tftpd64's Wiki, there is a Settings section which contains the following note next to the description of the "anticipation window" option:

Tftpd32 is able to send packets before receiving acknowledgements.

Since the default size of the TFTP data packet is 512 bytes, when setting the anticipation window to 1000 bytes, it instructs Tftpd32/Tftpd64 to extend the number of 512 byte data packets that are sent to clients without waiting for their acknowledgement by 1 (1000 / 512 is ~1.95). So, in effect, instead of a typical operation where only one data packet is sent to a client and then the server waits for its acknowledgement, Tftpd32/Tftpd64 would send two data packets and then wait for the client's acknowledgements. The code of Tftpd64 seems to confirm that the anticipation window's size is used to determine the number of extra data packets to send before waiting for their acknowledgement.

Such a behavior of the TFTP server resembles the behavior introduced in RFC 7440: TFTP Windowsize Option. However, if I understand correctly, RFC 7440 specifies that a larger window size needs to be asked for by the client. The TFTP download procedure implemented within the U-Boot bootloader of the TP-Link Archer C2 devices does not specify the windowsize option when performing the TFTP Read Request. It only specifies the timeout option, as captured by tcpdump:

192.168.0.1.2439 > 192.168.0.100.69: [no cksum] TFTP, length 27, RRQ "test.bin" octet timeout 1

According to the RFC 1350: THE TFTP PROTOCOL (REVISION 2), the data packets must be acknowledged by the client before the server can send more data packets:

Each data packet contains one block of data, and must be acknowledged by an acknowledgment packet before the next packet can be sent.

So, the behavior of Tftpd32/Tftpd64 with the "anticipation window" of at least 512 bytes does not follow the original TFTP specification. It resembles the newer RFC 7440 specification with the windowsize option but it only implements a part of it while omitting e.g. the support for clients specifying the desired TFTP window size.

That being said, such a behavior is able to work-around the apparent issues with some TP-Link Archer C2 devices where their U-Boot bootloader is unable to successfully download the firmware update over TFTP. I have tried using Tftpd64 with "anticipation window" of 1000 that was running in a Windows virtual machine. I can confirm that the TP-Link Archer C2 device that has TFTP flashing issues when used with a regular TFTP server (serial number 2161374002651) was able to use Tftpd64 configured as described above to successfully download the firmware.

However, the speed was rather low, only around 10 kB/s. I have tried experimenting with different values of the "anticipation window" option but I was unable to find a value which would significantly improve the speed, i.e. by more than ~30 %. Larger "anticipation window" typically caused speed to decrease and the number of timeouts to increase. Without the "anticipation window" option enabled, the behavior was the same as with any other regular TFTP server, i.e. the transfer would typically end after a few hundred data packets because of the timeouts.

Linux alternatives

I have also looked into the options of using a Linux TFTP server that would be capable of sending multiple data packets without acknowledgement. The two most commonly used TFTP servers on Linux, namely tftp-hpa and atftp, do not support the RFC 7440 windowsize option. The author of tftp-hpa has been asked to add support for it but there does not seem to be any activity since then. However, there are forks of tftp-hpa, namely ClausKlein/tftp-hpa and mellowcandle/tftp-hpa-rfc7440. which support RFC 7440. There are also several TFTP servers written in Python that claim to support RFC 7440 windowsize option, in particular: matkaczmarek/TFTP-RFC7440_1350, sirMackk/py3tftp and apardyl/PyTFTPd.

While there are multiple implementations of TFTP servers with RFC 7440 support available for Linux, that alone is insufficient for the purpose of sending a firmware to a TP-Link Archer C2 device with TFTP flashing issues. The reason is that, as mentioned above, the TFTP client within the U-Boot bootloader of the TP-Link Archer C2 device does not specify the windowsize option. As a result, even the TFTP servers with full support of RFC 7440 would keep using the window size of 1.

In order to make the TFTP download work even on the TP-Link Archer C2 devices with TFTP flashing issues, it is necessary to instruct the TFTP server with RFC 7440 windowsize support to always use a window of size at least 2, regardless of the client's requirement. Since the above mentioned TFTP servers do not offer an option to customize the window size manually, it is necessary to update their code.

I have tried to do that with apardyl/PyTFTPd because it is written in Python, has no dependencies on external packages and its code seems reasonably short and simple. I have made the following two changes:

--- a/tftp_common.py
+++ b/tftp_common.py
@@ -190,7 +190,7 @@ class RQPacket(TFTPPacket):
     @staticmethod
     def parse_rq(packet: bytes, constructor):
         block_size = 512
-        window_size = 1
+        window_size = 2  # temporarily changed
         bad_opts = False
         packet = packet[2:].split(b'\0')
         for i in range(2, len(packet), 2):
@@ -198,6 +198,8 @@ class RQPacket(TFTPPacket):
                 block_size = int(packet[i + 1])
             elif packet[i].lower() == b'windowsize':
                 window_size = int(packet[i + 1])
+            elif packet[i].lower() == b'timeout':
+                pass  # not implemented, temporarily ignoring
             elif packet[i] != b'':
                 bad_opts = True
         return constructor(packet[0], TransferModes.get_mode(packet[1]), block_size, window_size, bad_opts)

The first change adjusts the TFTP window size to 2. The second change skips the timeout option, which is not implemented by PyTFTPd but is part of the TFTP Read Request packet sent by the TFTP client within the U-Boot bootloader of TP-Link Archer C2.

I have then tried to run the PyTFTPd TFTP server with the above mentioned updates:

# ./tftpd.py 69 /srv/tftp

and initiate the TFTP download from the device's bootloader. There were no timeouts, the transfer was successful and it was also reasonably fast. The transfer speed was about 200 kB/s, i.e. roughly 20 times faster than with Tftpd64 during my experiments.

Summary

I can confirm that a customized TFTP server that sends two data packets at once before waiting for acknowledgements regardless of whether the client specifies the RFC 7440 windowsize option or not, can successfully be used to send firmware to a TP-Link Archer C2 device that experiences TFTP flashing issues with standards-compliant TFTP servers.

I think that it would be interesting to know why this kind of work-around in particular helps. It might also be interesting to investigate the root cause of why some devices are able to download firmware correctly from standards-compliant TFTP servers while some others are not.

1 Like

Like @pbasista I also have two C2s. One could easy be flashed (unknown serial number) via tftp, the other one error out with the same symptoms and u-boot logs (serial: 215C458003087).

Finally got it working by transfering an initramfs image via kermit over serial into memory, booting that and then sysupgradeing to a complete openwrt install (normal sysupgrade image without an integrated bootloader) (thanks @pbasista ! :slight_smile: ). The initramfs is missing something so the LAN/WAN ports are not useable (one of the switching chips is not recognised) so I had to enable wifi to transfer the complete sysupgrade image.

I would like to edit the wiki to include a link to this thread.
The remaining question is which method is the easiest to perform.

This would be my list:

no additional hardware or serial connection required

  1. Using Tftpd32 or Tftpd64 with an anticipation window (windows only)
  2. Patching PyTFTPd (*nix)

serial connection required

  1. transfering an image via serial onto the device (either boot from memory and then sysupgrade or directly write it into flash via u-boot)
  2. transfering an image via a thumb drive onto the device (did anybody try that ?)

What do you think ?

1 Like

I've edited the wiki to include more information regarding the tftp issue and also added a link to this thread.

1 Like

Just flashed a Archer C2 V1(US) with the provided 19.01 pre-prepared firmware using TFTP (Windows Tftpd64.exe) and it always timed out. So I clicked on settings in Tftpd.exe and set the default timeout and retries to a multiple of 10, so timeout 30 and Max retransmit 60. The flash succeeded.

2 posts were split to a new topic: Archer C2 dumb AP configuration

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.