添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

小米路由器 MiWiFi R2D 它复活了!

2022-05-10

说好的焊接水平上升了呢?

接上文 记录一次失败的小米路由器 R2D 救砖之旅 ,更多技术信息请参见该文章。

通过仔细观察,测量了一些电压后发现是 3.3V 电源输出对地短路,再经过仔细观察后发现,是我的 NAND 芯片焊挂了...芯片的 VCC 与 VSS 的引脚是放在一起的,而这两个引脚都是连接了大铜皮,最后将烙铁温度升到了 410 度时,才成功从他们中间拖出了锡。

要来的密码

通过微信与原贴主询问到了压缩包的密码。压缩包内有完整的刷录镜像,其中也有设备的序列号等信息,为了设备主的隐私起见,我这里也不放上下载链接,如果有需要的人,可以通过 [email protected] 与我联系。

Ref: 小米R2D编程器固件 512M的nand芯片备份 完全好使加修改MAC和sn教程-恩山无线论坛

快要挂掉的芯片

任何刷入操作前一定要先备份!

这个小 NAND 在刷写的过程中,经常出现错误,导致编程器与电脑失去连接。经过测试发现其 0x00000000-0x01000000 区域(即前 128 个 block)可以写入数据,但是再往后就难写入了。

没有办法,只能刷入前面区域,对于一个系统来说,前面的区域包含了系统的内核,但是其他工具,软件包等数据都存储再后面的 rootfs 区域。这些写入信息不足以让系统正常启动

小米路由器的恢复系统

经过观察,小米编译的 CFE 正常情况下会启动 os0,若不成功会启动 os1,若再不成功,则会启动 os1,并且标志上两次启动不成功。

对于第三次启动,小米路由器在成功启动 os1 内核 的时候,进入恢复模式,表现为红灯闪烁。

这个恢复模式是在内核中实现的,换个角度来说,这个救砖机制主要是为了解决装了错误软件(即在 rootfs )导致的系统变砖头,而非内核编译错误导致的系统变砖头。刷机的时候,一定要往 os0 里刷入系统!刷入 os1 里,内核启动出现错误,砖头都救不动哇。

进入恢复模式后,系统会在串口输出一系列 . 等待 USB 装有新固件并且重命名为 miwifi.bin 文件的恢复 U 盘的插入。值得注意的是,小米路由器 R2D 会等待 /dev/sdb 插入,这是由于 R2D 本身有一个硬盘,即 /dev/sda 。故如果硬盘挪作他用,没有插上,同时只在 USB 口上插入一个 U 盘的话,R2D 检测不到恢复 U 盘(此时 U 盘为 /dev/sda )。这个时候我们需要一个 USB 分线器,在启动前先把一个 U 盘(作为 /dev/sda )插在分线器上,将分线器插在路由器上,等系统进入恢复模式等待恢复 U 盘插入的时候,我们再把恢复 U 盘插入(作为恢复系统需要的 /dev/sdb

之后小米系统会更新 os0 os1 rootfs0 rootfs1 重启后就可以进入系统啦。

更多关于小米编译的 CFE

在成功恢复系统之前,CFE 之后的每次重启都会进入 os1 系统。

如果 os1 安装了符合 CFE 格式(即 trx 格式)的系统,但是内核本身启动失败的话(比如给这个 arm 设备刷入了用于 mips 的内核镜像(我的情况) 除非你非常清楚这两个设备的情况,否则不同设备的镜像不能乱刷! ),CFE 会返回到其内置的 shell ,但是!

小米编译的 CFE 在 CFE 中的 nvram 里还增加了 uart_en 选项,如果这个选项不为 1 ,CFE 不会响应开机的 Ctrl-C 中断启动,且 shell 可能也无法使用(存疑,也有可能是我把芯片 UART 的 RX 搞坏了)

以上这些问题会导致如果 os1 本身错误的话无法启动的话,整个设备会卡住。

另外,如果 os0 和 os1 里都没有安装系统(为空白盘),CFE 会报两次 Wrong header 后,尝试向 192.168.1.2 (网线插入最靠近 USB 的那个网口)上的 tftp 请求两次 vmlinuz.trx ,并每次在请求成功后,将镜像刷入到 os0 或者 os1 中。

(以上每条结论的得出都意味着对 NAND 芯片的若干次拆装和对小米编译的 CFE 二进制代码的艰苦逆向 ;_; )

CFE 具体启动过程

小米编译的 CFE 除了一些小细节上外与官版的 CFE 大体一致。

可以参考 ASUS 开源的 CFE 代码,来辅助分析 CFE 的执行过程,这部分代码可以在 ASUSWRT 梅林代码仓库中找到: RMerl/asuswrt-merlin: Enhanced version of Asus's router firmware (Asuswrt) (legacy code base)

值得关注的代码分别为:

  • cfe\build\broadcom\bcm947xx\compressed\Makefile Makefile
  • shared\cfez_arm_shmoo.lds.in 链接文件
  • shared\startarm-ca9.S ARM 内核 Reset_Handler 所在汇编文件
  • shared\load.c 解压缩后半段代码的 c_main 函数所在文件
  • cfe\cfe\main\cfe_main.c 真正的 CFE 执行入口文件
  • cfe\cfe\arch\common\board\bcm947xx\src\bcm947xx_devs.c board_final_init 等设备相关初始化函数所在文
  • 小米编译的 CFE 启用了 CFE 自身压缩功能,系统会先启动一小段代码,解压由 LZMA 压缩的 CFE 内核,然后再执行 CFE 真正的内核。

    主芯片上电复位后,由芯片内的 BootROM 拷贝 NAND 中的数据到内存中,即从 NAND 的 0x00000000 位置后拷贝若干数据拷贝到内存中的 0xC0000000 下,并且从 0xC0000000 开始执行代码。(应该)

    这一行代码会直接跳转到 tr_rst tr_rst 为 ARM 内核芯片一般会由的 Reset_Handler ,CFE 的 tr_rst 会根据是否要解压缩去选择入口函数,对于代码运行在解压缩模式(即没有定义 __CFE__ 宏)时,调用 c_main ,若运行在正常模式(即定义有 __CFE__ 宏),会调用 cfe_main 。这个过程之前这段汇编也会执行 DDR 内存自检等操作。

    对于小米编译的 CFE,压缩后的镜像位于 NAND 的 0x0001C000 (对应内存编址 0xC001C000 )位置,前四个字节为小段序的镜像大小,后面会跟随该大小的压缩镜像。通过 WinHex 导出这一段数据后,可以使用开源的 7zip 程序直接解压。CFE 会把这些数据解压到内存的 0xF00000 位置,然后从这个位置再继续开始执行代码。

    CFE 在编译的过程中会把一些 section 的地址偏移信息,写入到特定的区域,这些信息会有助于我们分析小米编译的 CFE 的代码(如创建 bss section)。具体可以参见 cfez_arm_shmoo.lds.in 链接文件。

    flash_init 函数中,小米增加了判断进入工厂模式的代码,在检测到指定位置( 0x140000 )有特定字符的时候,重置 CFE 的 nvram(在 board_final_init 中执行逻辑),可以设置 uart_en 为 1。但是不知道为何,我自己在使用的时候,并不成功

    恩山论坛上也有坛友对 CFE 的启动进行了一些分析,对我很有帮助,在此谢谢这位坛友: 博通 CFE 数据压缩与解压-恩山无线论坛 CFE 编译、结构解析与二进制修改-恩山无线论坛

    IDA 真好用

    miwifi_ssh.bin 开启 ssh

    先刷到低版本系统,我刷的是 brcm4709_r2d_ec5d6_2.5.16.bin

    登录到后台,获取 url 上的 stok。

    访问该网址启动 telnet 服务,替换 <> 内参数:

    http://192.168.31.1/cgi-bin/luci/;stok=<stok>/api/xqnetwork/set_wifi_ap?ssid=whatever&encryption=NONE&enctype=NONE&channel=1%3B%2Fusr%2Fsbin%2Ftelnetd
    

    访问该网址修改 root 密码:

    http://192.168.31.1/cgi-bin/luci/;stok=<stok>/api/xqsystem/set_name_password?oldPwd=<old_admin_password>&newPwd=<new_admin_password>
    

    此外,软件编译工具链可以从 sdk_package.zip 获得。

    另外固件的解包可以使用 R2D 系统内的 mkxqimage 进行。

  • [OpenWrt Wiki] 小米米 WiFi Mini
  • 自己收藏的小米路由器2硬盘版(R2D)固件全集-恩山无线论坛
  • 小米路由器R2D官方固件解包打包-恩山无线论坛
  •