TTL 连接路由器的方法大同小异,就直接略过。这里只讲一些注意事项。
默认情况下 TTL 是不可输入的
如果你不做任何设置,直接连上 TTL,会发现按什么都没反应。需要修改 nvram 开启。
官方固件下执行:
nvram set boot_wait=on |
OpenWRT 固件下执行:
fw_setenv boot_wait on |
uart_en 开启后才可以输入。
boot_wait 开启后会在 Please choose the operation:
这里等待 5 秒。
一般情况下刷其他固件前就会先设置这个选项,避免刷坏后无法恢复。
官方固件的闪存布局
0x000000000000-0x000000040000 : "Bootloader" |
上面的十六进制数字都是对应闪存中的位置,单位为字节。
kernel0 kernel1 rootfs0 rootfs1 分别为两个系统,即使其中一个损坏了还可以从另一个系统启动。
官方 U-Boot 会根据 nvram 中几个变量来选择启动哪一个 kernel。具体规则可见 这里 (这里针对的是小米路由器 3G,不过实测是一样的)
TTL 恢复
和大多数路由器的操作相同,启动时 U-Boot 会提示选择操作:
Please choose the operation: |
选择 2 ,按提示操作即可
2: System Load Linux Kernel then write to Flash via TFTP. |
最后的 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 |
刷入 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 |
即可修改这两个变量。