One of my friends brought in a router (TL-WR841N v9) today, which was apparently bricked.
It had failed while installing openWRT.
My friend had already tried hooking up serial wires from the UART channel on the router to an Arduino Uno Board (a decent jugaad for an FTDI), but he said he was still stuck in a boot loop.

While checking it myself, I found that the serial was receiving everything dumped by the router, first, the initialisation and second, looping around this message:

## Booting image at 9e040000 ...
Uncompressing Kernel Image ... Too big uncompressed streamLZMA ERROR 1 - must RESET board to recover


Receiving data is easy, because most devices dump verbose output at 115200 bps, 9600 bps in some cases. The router was using 115200 bps.
The router boots after providing a 1 second window to go into bootloader mode.
According to openWRT forums, sending acl in this window should have resulted in this message:

uboot Commands

But what was happening instead was that anything I sent resulted in garbled bytes on the serial monitor
Since all the debug messages are expected to follow a Unicode encoding, I wrote a short python script to check the integrity of the transmission.

import serial

PORT = /dev/ttyACM0
BAUD = 115200

serialReceiver = serial.Serial(PORT, BAUD)
if serialReceiver.isOpen():
    while 1:
        try:
            x = (serialReceiver.read()).decode("utf-8")
        except UnicodeDecodeError as ude:
            print("UDE")


And the moment I sent any character over to the serial, it would collapse for about 3 seconds, flooding the terminal with UDE and then boot in normal mode, trying to uncompress the kernel image and obviously looping endlessly over it.
The message was pretty self-explanatory, I had a hint of what would have happened.
The router features a cFeon Q32B-104HIP , which is a 4MB flash storage device. Any kernel image that is uncompressed and run as an OS for the router must be limited to 4MB, but somehow, my friend had managed to forcibly flash an image greater than 4MB, and the kernel was not being properly setup. The board would then reset and encounter this issue again, looping around forever.

This meant that the problem could be easily solved, given the serial transmission worked flawlessly.
For that, I powered the router’s UART with an external 3V3 supply to eliminate the possibility of the serial not working due to limited power from Uno’s on-board AMS1117, and used two 10k-ohm pullup resistors to keep the serial lines to their default high state.
I tried typing acl and the serial worked flawlessly, at least my python script didn’t throw out UDE even once.

Now, all that was left was to use tftpboot to flash a new image.
In this mode, the router expects a TFTP Server running with some specific configurations, specifically the fixed IP and filename, which are displayed once tftpboot is entered, and then the device blindly starts copying that data and flashes itself. The stock images can be easily found on the router’s website.

Windows and Mac have applications that can setup TFTP servers in a click.
But for someone like me who uses Linux and is obsessed with CLI, this would help.