免责声明
⚠️ 警告:刷机有风险,操作需谨慎
刷写 Bootloader(BL2/FIP)、分区表(GPT)和固件系统涉及对硬件底层存储的直接操作。操作不当可能导致:
- 设备无法启动(变砖)
- 网络功能失效
- 分区表损坏导致数据全部丢失
- 硬件永久性损坏
本教程及配套固件仅供参考学习用途。 作者不对因遵循本教程进行操作所导致的任何直接或间接损失承担责任,包括但不限于:
- 设备变砖、无法恢复
- 数据丢失或损坏
- 硬件故障或损坏
- 保修失效
在操作前,请确保你:
- 已充分理解刷机原理和风险
- 已备份所有重要数据
- 具备基本的 Linux 命令行操作能力
- 阅读并理解了完整的教程内容
如无法接受以上条款,请勿进行任何刷机操作。 进行刷机即代表你已理解并承担全部风险。
本教程发布于 CSDN,仅为技术分享,并非官方指南。
背景
BPI-R3 Mini 出厂 NAND 里是 SinoVoip 的 U-Boot,没有 DHCP,刷机必须接 TTL 串口 + 搭 TFTP 服务器,非常麻烦。
本方案使用 webfailsafe U-Boot(基于 5.4 BSP 编译),刷入后 U-Boot 自带:
- ✅ Web 刷机界面 --- 浏览器上传固件
- ✅ 静态 IP 192.168.1.1
- ✅ 可直刷 sysupgrade.itb
⚠️ 该 U-Boot 不带 DHCP 服务器 ,电脑需手动设置 IP 为
192.168.1.x(如192.168.1.2),子网掩码255.255.255.0,才能访问 Web 界面。
所需文件
来自 R3mini-5.4-BSP-webfail safe bl2+fip/ 目录:
| 文件 | 目标 | 大小 | 说明 |
|---|---|---|---|
nand/mt7986_bpi_r3mini-snand-fip-fixed-parts-multi-layout.bin |
NAND mtd4 (FIP) | ~1MB | U-Boot 本体,含 webfailsafe |
nand/mt7986_bpi_r3mini_snand-bl2.bin |
NAND mtd1 (BL2) | ~218KB | BL2(可选,见下文) |
nand/nand-factory.bin |
NAND 整片 | ~70MB | 完整 NAND 固件(备用) |
刷机流程
前提
NAND 和 eMMC 至少有一个能正常启动系统。这里假设你从 eMMC 系统操作。
第 1 步:上传文件到设备
因为 OpenWrt/QWRT 的 Dropbear SSH 不支持 SFTP,需要用 base64 管道传文件。
方法 A:在设备上下载(如果有网络)
bash
# 在设备上直接 wget 下载(如果设备能联网)
cd /tmp
wget https://your-server/mt7986_bpi_r3mini-snand-fip-fixed-parts-multi-layout.bin
wget https://your-server/mt7986_bpi_r3mini_snand-bl2.bin
方法 B:通过 SSH 管道上传(Windows 用 Python)
python
import paramiko, base64
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.1.1', username='root', password='password')
def upload_file(client, local_path, remote_path):
with open(local_path, 'rb') as f:
data = f.read()
b64 = base64.b64encode(data).decode()
stdin, stdout, stderr = client.exec_command('cat > /tmp/tmp.b64', timeout=120)
stdin.write(b64)
stdin.channel.shutdown_write()
stdout.channel.recv_exit_status()
client.exec_command(f'cat /tmp/tmp.b64 | base64 -d > {remote_path} && rm /tmp/tmp.b64')
upload_file(client, 'mt7986_bpi_r3mini_snand-bl2.bin', '/tmp/mt7986_bpi_r3mini_snand-bl2.bin')
upload_file(client, 'mt7986_bpi_r3mini-snand-fip-fixed-parts-multi-layout.bin', '/tmp/mt7986_bpi_r3mini-snand-fip-fixed-parts-multi-layout.bin')
方法 C:通过 SCP(如果 SSH 支持)
bash
# 从电脑传到设备
scp mt7986_bpi_r3mini_snand-bl2.bin root@192.168.1.1:/tmp/
scp mt7986_bpi_r3mini-snand-fip-fixed-parts-multi-layout.bin root@192.168.1.1:/tmp/
第 2 步:刷写 FIP(U-Boot)
FIP 是 U-Boot 本体,webfailsafe 功能在这里。
bash
# 确认分区
cat /proc/mtd
# 应该看到:
# mtd0: 08000000 "spi0.1" (整片 NAND)
# mtd1: 00100000 "BL2"
# mtd4: 00200000 "FIP" ← 目标分区
# 刷写 FIP
mtd write /tmp/mt7986_bpi_r3mini-snand-fip-fixed-parts-multi-layout.bin /dev/mtd4
# 验证
dd if=/dev/mtdblock4 bs=1 count=1040321 2>/dev/null | md5sum
# 应与原始文件 MD5 一致
第 3 步:BL2 刷写(可选,通常不需要)
⚠️ 注意:BL2 通常受 SPI NAND 硬件写保护,从 Linux 系统内无法刷入。
mtd和dd命令会报告成功,但数据实际上不会写入- 这是因为 SPI NAND 状态寄存器的 BP(Block Protect)位被硬件锁定
如果确实需要刷 BL2,必须从 U-Boot 命令行操作:
bash
# 在 U-Boot 中(通过 TTL 串口进入):
nmbm unlock
nand erase 0x0 0x100000
tftp 0x40000000 mt7986_bpi_r3mini_snand-bl2.bin
nand write 0x40000000 0x0 $filesize
大多数情况下 BL2 无需更新------旧 BL2 照样能正常加载新 FIP,webfailsafe 功能不受影响。
第 4 步:进入 Webfailsafe 模式
#mermaid-svg-BWmFLXB9QLPxyWA5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BWmFLXB9QLPxyWA5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BWmFLXB9QLPxyWA5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BWmFLXB9QLPxyWA5 .error-icon{fill:#552222;}#mermaid-svg-BWmFLXB9QLPxyWA5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BWmFLXB9QLPxyWA5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BWmFLXB9QLPxyWA5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BWmFLXB9QLPxyWA5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BWmFLXB9QLPxyWA5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BWmFLXB9QLPxyWA5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BWmFLXB9QLPxyWA5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BWmFLXB9QLPxyWA5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BWmFLXB9QLPxyWA5 .marker.cross{stroke:#333333;}#mermaid-svg-BWmFLXB9QLPxyWA5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BWmFLXB9QLPxyWA5 p{margin:0;}#mermaid-svg-BWmFLXB9QLPxyWA5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BWmFLXB9QLPxyWA5 .cluster-label text{fill:#333;}#mermaid-svg-BWmFLXB9QLPxyWA5 .cluster-label span{color:#333;}#mermaid-svg-BWmFLXB9QLPxyWA5 .cluster-label span p{background-color:transparent;}#mermaid-svg-BWmFLXB9QLPxyWA5 .label text,#mermaid-svg-BWmFLXB9QLPxyWA5 span{fill:#333;color:#333;}#mermaid-svg-BWmFLXB9QLPxyWA5 .node rect,#mermaid-svg-BWmFLXB9QLPxyWA5 .node circle,#mermaid-svg-BWmFLXB9QLPxyWA5 .node ellipse,#mermaid-svg-BWmFLXB9QLPxyWA5 .node polygon,#mermaid-svg-BWmFLXB9QLPxyWA5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BWmFLXB9QLPxyWA5 .rough-node .label text,#mermaid-svg-BWmFLXB9QLPxyWA5 .node .label text,#mermaid-svg-BWmFLXB9QLPxyWA5 .image-shape .label,#mermaid-svg-BWmFLXB9QLPxyWA5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-BWmFLXB9QLPxyWA5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BWmFLXB9QLPxyWA5 .rough-node .label,#mermaid-svg-BWmFLXB9QLPxyWA5 .node .label,#mermaid-svg-BWmFLXB9QLPxyWA5 .image-shape .label,#mermaid-svg-BWmFLXB9QLPxyWA5 .icon-shape .label{text-align:center;}#mermaid-svg-BWmFLXB9QLPxyWA5 .node.clickable{cursor:pointer;}#mermaid-svg-BWmFLXB9QLPxyWA5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BWmFLXB9QLPxyWA5 .arrowheadPath{fill:#333333;}#mermaid-svg-BWmFLXB9QLPxyWA5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BWmFLXB9QLPxyWA5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BWmFLXB9QLPxyWA5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BWmFLXB9QLPxyWA5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BWmFLXB9QLPxyWA5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BWmFLXB9QLPxyWA5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BWmFLXB9QLPxyWA5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BWmFLXB9QLPxyWA5 .cluster text{fill:#333;}#mermaid-svg-BWmFLXB9QLPxyWA5 .cluster span{color:#333;}#mermaid-svg-BWmFLXB9QLPxyWA5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BWmFLXB9QLPxyWA5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BWmFLXB9QLPxyWA5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-BWmFLXB9QLPxyWA5 .icon-shape,#mermaid-svg-BWmFLXB9QLPxyWA5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BWmFLXB9QLPxyWA5 .icon-shape p,#mermaid-svg-BWmFLXB9QLPxyWA5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BWmFLXB9QLPxyWA5 .icon-shape .label rect,#mermaid-svg-BWmFLXB9QLPxyWA5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BWmFLXB9QLPxyWA5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BWmFLXB9QLPxyWA5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BWmFLXB9QLPxyWA5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 断电
将启动跳线切到 NAND
按住 RESET 键不放
上电
继续按住 RESET 5~7 秒
松开 RESET
电脑连 LAN 口
手动设 IP 192.168.1.x
浏览器打开 http://192.168.1.1
进入 U-Boot Web 界面
如果接 TTL 串口,启动时能看到菜单,选择 web failsafe 选项。
如果接 TTL 串口,启动时能看到菜单,选择 web failsafe 选项。
第 5 步:通过 Web 界面刷固件
- 浏览器打开 U-Boot 的 Web 页面
- 选择要刷写的固件文件:
- sysupgrade.itb --- 升级系统(保留配置)
- factory.bin / nand-factory.bin --- 完整刷写整机
- 点击上传,等待刷写完成
- 刷完后设备自动重启进入新系统
完成的 NAND 分区布局
刷机完成后,NAND 布局如下(以 128MB NAND + QWRT 为例):
#mermaid-svg-0QNhCDfptZrHHDeK{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0QNhCDfptZrHHDeK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0QNhCDfptZrHHDeK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0QNhCDfptZrHHDeK .error-icon{fill:#552222;}#mermaid-svg-0QNhCDfptZrHHDeK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0QNhCDfptZrHHDeK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0QNhCDfptZrHHDeK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0QNhCDfptZrHHDeK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0QNhCDfptZrHHDeK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0QNhCDfptZrHHDeK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0QNhCDfptZrHHDeK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0QNhCDfptZrHHDeK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0QNhCDfptZrHHDeK .marker.cross{stroke:#333333;}#mermaid-svg-0QNhCDfptZrHHDeK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0QNhCDfptZrHHDeK p{margin:0;}#mermaid-svg-0QNhCDfptZrHHDeK .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0QNhCDfptZrHHDeK .cluster-label text{fill:#333;}#mermaid-svg-0QNhCDfptZrHHDeK .cluster-label span{color:#333;}#mermaid-svg-0QNhCDfptZrHHDeK .cluster-label span p{background-color:transparent;}#mermaid-svg-0QNhCDfptZrHHDeK .label text,#mermaid-svg-0QNhCDfptZrHHDeK span{fill:#333;color:#333;}#mermaid-svg-0QNhCDfptZrHHDeK .node rect,#mermaid-svg-0QNhCDfptZrHHDeK .node circle,#mermaid-svg-0QNhCDfptZrHHDeK .node ellipse,#mermaid-svg-0QNhCDfptZrHHDeK .node polygon,#mermaid-svg-0QNhCDfptZrHHDeK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0QNhCDfptZrHHDeK .rough-node .label text,#mermaid-svg-0QNhCDfptZrHHDeK .node .label text,#mermaid-svg-0QNhCDfptZrHHDeK .image-shape .label,#mermaid-svg-0QNhCDfptZrHHDeK .icon-shape .label{text-anchor:middle;}#mermaid-svg-0QNhCDfptZrHHDeK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0QNhCDfptZrHHDeK .rough-node .label,#mermaid-svg-0QNhCDfptZrHHDeK .node .label,#mermaid-svg-0QNhCDfptZrHHDeK .image-shape .label,#mermaid-svg-0QNhCDfptZrHHDeK .icon-shape .label{text-align:center;}#mermaid-svg-0QNhCDfptZrHHDeK .node.clickable{cursor:pointer;}#mermaid-svg-0QNhCDfptZrHHDeK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0QNhCDfptZrHHDeK .arrowheadPath{fill:#333333;}#mermaid-svg-0QNhCDfptZrHHDeK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0QNhCDfptZrHHDeK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0QNhCDfptZrHHDeK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0QNhCDfptZrHHDeK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0QNhCDfptZrHHDeK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0QNhCDfptZrHHDeK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0QNhCDfptZrHHDeK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0QNhCDfptZrHHDeK .cluster text{fill:#333;}#mermaid-svg-0QNhCDfptZrHHDeK .cluster span{color:#333;}#mermaid-svg-0QNhCDfptZrHHDeK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0QNhCDfptZrHHDeK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0QNhCDfptZrHHDeK rect.text{fill:none;stroke-width:0;}#mermaid-svg-0QNhCDfptZrHHDeK .icon-shape,#mermaid-svg-0QNhCDfptZrHHDeK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0QNhCDfptZrHHDeK .icon-shape p,#mermaid-svg-0QNhCDfptZrHHDeK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0QNhCDfptZrHHDeK .icon-shape .label rect,#mermaid-svg-0QNhCDfptZrHHDeK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0QNhCDfptZrHHDeK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0QNhCDfptZrHHDeK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0QNhCDfptZrHHDeK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} NAND Flash 128MB 分区布局
mtd0: spi0.1
整片 NAND 128MB
mtd1: BL2
预加载器 1MB
mtd2: u-boot-env
U-Boot 环境变量 512KB
mtd3: Factory
硬件信息/校准 2MB
mtd4: FIP
U-Boot 本体 2MB ★ webfailsafe
mtd5: ubi
系统分区 64MB
├─ kernel 3.5MB
├─ rootfs 46MB
└─ rootfs_data 9.5MB
⚠️ 如果固件只分了 64MB UBI ,剩余约 58MB NAND 空间会被浪费。要利用全部 128MB,需编译固件时修改 DTS 中 mtd5 的 reg 为 <0x000000 0x08000000>,然后重新编译刷入。
常见问题
Q: FIP 刷成功了,但打不开 Web 界面?
A: 先确认电脑 IP 是否手动设为 192.168.1.x 网段。如果还不行,检查刷入的 FIP 文件是否正确,重新用 mtd write 刷一次并验证 MD5。
Q: BL2 刷不了怎么办?
A: 不影响使用。BL2 只负责硬件初始化和加载 FIP,webfailsafe 功能全在 FIP 里。如需刷 BL2,参考第 3 步从 U-Boot 命令行操作。
Q: 刷完系统后空间很小?
A: 检查 UBI 分区大小(cat /proc/mtd 看 mtd5 的 size),64MB 是固件编译时决定的,需要改 DTS 重新编译才能用满 128MB。
Q: 想刷回 eMMC 启动?
A: 切回 eMMC 启动跳线即可,两套系统互不影响(前提是 eMMC 系统还在)。