小米路由器3 U-Boot TTL 恢复及一些注意事项

TTL 连接路由器的方法大同小异,就直接略过。这里只讲一些注意事项。

默认情况下 TTL 是不可输入的

如果你不做任何设置,直接连上 TTL,会发现按什么都没反应。需要修改 nvram 开启。

官方固件下执行:

nvram set boot_wait=on
nvram set uart_en=1
nvram commit

OpenWRT 固件下执行:

fw_setenv boot_wait on
fw_setenv uart_en 1

uart_en 开启后才可以输入。

boot_wait 开启后会在 Please choose the operation: 这里等待 5 秒。

一般情况下刷其他固件前就会先设置这个选项,避免刷坏后无法恢复。

官方固件的闪存布局

0x000000000000-0x000000040000 : "Bootloader"
0x000000040000-0x000000080000 : "Config"
0x000000080000-0x0000000c0000 : "Bdata"
0x0000000c0000-0x000000100000 : "Factory"
0x000000100000-0x000000140000 : "crash"
0x000000140000-0x000000180000 : "crash_syslog"
0x000000180000-0x000000200000 : "reserved0"
0x000000200000-0x000000600000 : "kernel0"
0x000000600000-0x000000a00000 : "kernel1"
0x000000a00000-0x000002a00000 : "rootfs0"
0x000002a00000-0x000004a00000 : "rootfs1"
0x000004a00000-0x000008000000 : "overlay"

上面的十六进制数字都是对应闪存中的位置,单位为字节。

kernel0 kernel1 rootfs0 rootfs1 分别为两个系统,即使其中一个损坏了还可以从另一个系统启动。

官方 U-Boot 会根据 nvram 中几个变量来选择启动哪一个 kernel。具体规则可见 这里 (这里针对的是小米路由器 3G,不过实测是一样的)

TTL 恢复

和大多数路由器的操作相同,启动时 U-Boot 会提示选择操作:

Please choose the operation:
   1: Load system code to SDRAM via TFTP.
   2: Load system code then write to Flash via TFTP.
   3: Boot system code via Flash (default).
   4: Entr boot command line interface.
   9: Load Boot Loader code then write to Flash via TFTP.

选择 2 ,按提示操作即可

2: System Load Linux Kernel then write to Flash via TFTP.
 Warning!! Erase Linux in Flash then burn new one. Are you sure?(Y/N)
 Please Input new ones /or Ctrl-C to discard
        Input device IP (192.168.1.1) ==:192.168.1.1
        Input server IP (192.168.1.3) ==:192.168.1.3
        Input Linux Kernel filename () ==:

最后的 filename 为 TFTP 服务器上的文件名。

前面提到了闪存布局,在这里有用:U-Boot 会先把下载来的数据写到闪存的 0x200000 位置 (也就是 kernel0),再把数据写到 0x600000 位置 (kernel1)。

这样的话,就变成了 kernel0 和 kernel1 数据是相同的。不能实现 kernel0 和 kernel1 写入不同的数据。

另外,小米官网提供的固件不能通过 U-Boot 直接刷入,因为它是有特定格式的文件,要解包后才能得到实际能写入的文件。

构造一个可以通过 U-Boot 刷入的文件

OpenWRT

小米路由器 3 的 OpenWRT 固件一般为一个 kernel 文件,一个 rootfs 文件。

从上面的闪存布局可算出 kernel0 和 kernel1 的大小都是 4MB,所以把 kernel 文件补满 4MB,后面接上 rootfs 文件就可直接刷入。

假设有 kernel.bin 和 rootfs.bin,进行下列操作:

dd if=/dev/zero bs=4M count=1 | tr "\000" "\377" > padded_kernel.bin
dd if=kernel.bin of=padded_kernel.bin conv=notrunc
cat padded_kernel.bin rootfs.bin > kernel_rootfs.bin

刷入 kernel_rootfs.bin 即可。

Padavan

Prometheus (用来刷固件的虚拟机里的脚本) 这个脚本中可以看到,Padavan 是把固件写到 kernel1 的位置并往后覆盖的,所以可以直接刷入 Padavan 的固件文件。

小米官方固件的恢复模式

许多教程会讲到小米路由器的恢复模式。就是路由器红灯闪烁的时候,插入 U 盘按 Reset 键可以恢复官方固件。我以前曾认为这是 U-Boot 提供的功能,但是通过 TTL 输出的信息来看这是官方固件内核中 initramfs 的功能。

也就是说,如果没有官方固件的内核的话,就没有这个功能了。这也是为什么 OpenWRT 和 Padavan 都不修改 kernel0,因为这样可以直接进入官方固件的恢复模式,然后刷回官方固件。

同时也意味着,用上面 U-Boot 的方法刷入的话,不会包含官方内核,也就无法使用这个功能了。

也因为有这个功能,如果你一开始备份了官方固件中每个 mtd 的数据,那 U-Boot 刷入 mtd8 或 mtd9 就可以进入恢复模式了。

进入恢复模式还有个条件: nvram 中 flag_try_sys1_failed flag_try_sys2_failed 的值都为 1。

在前面提到的提示选择操作的时候,选择 4,然后执行:

setenv flag_try_sys1_failed 1
setenv flag_try_sys2_failed 1
saveenv

即可修改这两个变量。

本文章采用 CC BY-NC-SA 4.0 International 协议 进行许可。
本文链接:https://blog.ysc3839.com/archives/2018/03/miwifi-r3-ttl-recovery.html