Fixing a bricked Tagus: breaking the recovery loop over UART
My Tagus got stuck in an infinite loop trying to install a non-existent update. Here's how I recovered it without ADB, using just a USB-UART adapter.
One of my Tagus devices woke up in a coma. It booted, entered recovery, tried to install something that didn’t exist, failed, and rebooted. Over and over. No ADB access, since recovery doesn’t expose USB. No touchscreen, since this one’s digitizer is broken.
Here’s everything I did to bring it back using just a 3-euro UART adapter and BusyBox.
The symptoms
The device boots, shows the bootloader logo, and enters recovery directly. The UART log makes it clear:
got recovery cmd from misc.
...
Boot command: boot-recovery
list arg=2:
recovery
--update_package=/data/local/assets/update.zip
...
I/: Update location: /data/local/assets/update.zip
E/: failed to open /data/local/assets/update.zip (No such file or directory)
E:signature verification failed
Installation aborted.
Recovery has a command burned into the misc partition telling it to “install update.zip”. Since that file doesn’t exist (probably deleted by a previous update), signature verification fails and the process aborts. But the command is still there, so on the next boot it tries again. Infinite loop.
What you need
- A USB-UART TTL 3.3V adapter (any cheap CP2102, FT232 or PL2303 works)
- Wires to connect GND, TX and RX to the board
- A computer with a serial terminal (on Mac,
screenis built in) - Basic soldering skills or a JST connector for the UART pins on the board
Don’t connect VCC. Just GND, TX and RX.
Step 1: Connect via UART and watch the log
Locate the UART pins on the board. On the Tagus Gea/Gaia they’re labeled and accessible with barely any disassembly.
Connect:
- Adapter GND to Tagus GND
- Adapter TX to Tagus RX
- Adapter RX to Tagus TX
On Mac, find the port:
ls /dev/tty.*
Connect at 115200 baud (the standard speed for U-Boot and embedded Linux kernels):
screen /dev/tty.usbserial-XXXXX 115200
Power on the Tagus and you’ll see the full boot log. The system ends at a recovery # shell after it finishes failing.
Step 2: Explore with BusyBox
Regular Linux commands aren’t available in this device’s recovery. But BusyBox is, packing dozens of utilities:
busybox
This lists all available commands. Use them by prefixing with busybox:
busybox ls
busybox dd
busybox hexdump
busybox mount
busybox reboot
Step 3: Find the misc partition
On Android/RockChip, the misc partition stores the boot command. To find which block device it is:
busybox ls -l /dev/block/platform/1021c000.rksdmmc/by-name/misc
Result:
misc -> /dev/block/mmcblk0p3
Step 4: Read the cursed command
Use hexdump to view the binary content of the partition:
busybox hexdump -C /dev/block/mmcblk0p3 | busybox head
The recovery command starts at offset 0x4000 (16384 bytes):
00004000 62 6f 6f 74 2d 72 65 63 6f 76 65 72 79 00 00 00 |boot-recovery...|
00004040 72 65 63 6f 76 65 72 79 0a 2d 2d 75 70 64 61 74 |recovery.--updat|
00004050 65 5f 70 61 63 6b 61 67 65 3d 2f 64 61 74 61 2f |e_package=/data/|
00004060 6c 6f 63 61 6c 2f 61 73 73 65 74 73 2f 75 70 64 |local/assets/upd|
00004070 61 74 65 2e 7a 69 70 0a 00 00 00 00 00 00 00 00 |ate.zip.........|
Key insight: the command isn’t at the start of the partition. It’s at block 16 (offset 0x4000). If I had tried to wipe from the beginning, it wouldn’t have done anything.
Step 5: Wipe the command
Use dd to overwrite that exact area with zeros:
busybox dd if=/dev/zero of=/dev/block/mmcblk0p3 bs=1k seek=16 count=1
Parameters:
if=/dev/zero— source: zeros.of=/dev/block/mmcblk0p3— target: the misc partition.bs=1k— 1 KB blocks.seek=16— skip 16 blocks (16384 bytes) before writing.count=1— write only 1 block, enough to erase the command.
Step 6: Verify
busybox hexdump -C /dev/block/mmcblk0p3 | busybox head -20
The area at offset 0x4000 should now be all zeros.
Step 7: Reboot
busybox reboot
If the command doesn’t respond, alternative:
echo b > /proc/sysrq-trigger
The device no longer tries to install a phantom update. It boots normally.
Why this works
Android’s misc partition uses a format called bootloader message. The bootloader (U-Boot, in this case) reads it at boot time and, if it finds boot-recovery, loads the recovery partition instead of boot. Recovery then reads the rest of the message to know what to do.
By wiping the message, the bootloader finds no reason to enter recovery. It goes back to normal boot.
Notes and risks
- Back up before touching partitions:
busybox dd if=/dev/block/mmcblk0p3 of=/sdcard/misc-backup.img - The exact offset may vary by manufacturer. Always confirm with
hexdumpbefore writing. - Modifying system partitions carries brick risk. But when you’re already in an infinite loop, there’s not much left to lose.
Full boot log
For reference, the complete boot log from the Tagus in this state is available. It covers U-Boot, the Linux 3.10 kernel, Rockchip initialization, the e-ink panel (ED060XH7), the AXP223/TPS6518x PMIC, and Android 4.4.2 recovery with all relevant error messages.
It’s a useful reference if you’re debugging similar issues on any Rockchip RK3128 device with an Onyx e-ink display.
Drafted with AI, edited by hand. I publish it when it sounds like me.