Gm-aaa's blog.

不刷机获取甘肃电信烽火 HG6543C1 超级管理员密码

字数统计: 4.4k阅读时长: 19 min
2026/08/01
loading

本文记录一次对自有光猫的硬件调试。核心思路不是破解 Web 页面,也不是刷写 NAND,而是通过 3.3 V UART 进入 TcBoot,将临时 OpenWrt initramfs 加载到内存,随后只读挂载原厂配置分区,读取本机保存的超级管理员凭据。

请只操作自己拥有或明确获授权的设备。文中的命令示例使用脱敏占位符;实拍结果图按记录现场保留,仅隐藏了设备序列号。

设备信息

这次操作的设备是甘肃电信定制版烽火 HG6543C1:

  • 型号:FiberHome HG6543C1
  • 硬件版本:V3.0
  • 原厂软件版本:V3.00.M5002
  • SoC:EcoNet EN751221(Web 页面显示 EN7526 系列)
  • CPU:双核 MIPS 34Kc,900 MHz
  • 内存:256 MiB
  • Flash:Winbond W25N01G,128 MiB SPI NAND
  • 原厂内核:Linux 3.18.21
  • Bootloader:EN751221 TcBoot/Bootbase

不同地区、硬件版本或运营商批次的 PCB、分区表和配置路径可能不同,不要把本文地址直接套用到别的型号。

HG6543C1 背面隐私处理及拆机螺丝位置

前置条件

硬件

  • CH340G、CP2102 或 FT232 等 USB 转 TTL 模块
  • TTL 电平为 3.3 V
  • 杜邦线三根
  • 万用表
  • 小螺丝刀和绝缘工具
  • 光猫原装电源

所需 CH340G USB-TTL 工具及接线警告

不要使用主板 RS-232 串口,也不要给 UART 接口输入 5 V。USB-TTL 模块的 VCC 不接光猫,只接 TXD、RXD、GND。

Linux 软件

本文使用 Arch Linux:

sudo pacman -S picocom dtc

安装 uv 后,Python 依赖由脚本临时管理,不需要污染系统 Python。

临时 OpenWrt 镜像来自实验性的 EN751221 OpenWrt 构建;本文实际使用 v2026-06-03,不要用后续版本套用本文的固定偏移:

请理解:这是实验镜像,只用于 RAM 启动和只读检查,不应直接刷入运营商光猫。

第一步:确认 UART 引脚

HG6543C1 主板下缘附近有一组 JP1 排针。本机实测结果如下:

在本文照片的观察方向,JP1 编号是从右向左的;因此照片中从左到右依次为 JP1-5、JP1-4、JP1-3、JP1-2、JP1-1

光猫引脚 功能 接 USB-TTL
JP1-2 光猫 TX RXD
JP1-3 光猫 RX TXD
JP1-4 GND GND

其余引脚不要连接。

HG6543C1 JP1 UART 引脚定义

接线前断开光猫电源。用万用表确认 GND,并确认 USB-TTL 的 TXD 对 GND 空闲电压约为 3.3 V。接线规则是交叉连接:光猫 TX 到模块 RXD,光猫 RX 到模块 TXD。

最终接线:

HG6543C1 JP1-2 (TX)  ─── CH340G RXD
HG6543C1 JP1-3 (RX) ─── CH340G TXD
HG6543C1 JP1-4 (GND) ─── CH340G GND
CH340G VCC ─── 不接

第二步:读取启动日志并进入 Bootloader

插入 USB-TTL,确认设备节点:

ls -l /dev/ttyUSB*
dmesg | tail -n 30

打开串口:

sudo picocom -b 115200 --flow n /dev/ttyUSB0

参数为 115200 8N1,无硬件/软件流控。给光猫上电后,应看到类似内容:

EN751221 ... free bootbase
Memory size 256MB
Dected SPI NAND Flash : _SPI_NAND_DEVICE_ID_W25N01G
Press any key in 1.8 secs to enter boot command mode.

在倒计时内按任意键:

bldr>

查看命令:

bldr> help

本机 Bootloader 提供 godecompdumpjumpflashxmdm 等命令。本文只使用 xmdmjump,不要执行 flashspi nand rw testbdstore 或其他写入命令。

通过 CH340G 连接 UART 并进入 TcBoot 命令行的工作台全景

第三步:先把通用镜像识别的内存从 64 MiB 改成 256 MiB

3.1 这一修改解决什么问题

这里使用的是临时运行在内存中的 OpenWrt initramfs:

openwrt-econet-en751221-en751221_generic-initramfs-kernel.bin

可以把这个文件简单理解成三部分:Linux 内核、临时根文件系统,以及放在文件末尾的“硬件说明书” DTB。内核会根据 DTB 判断这块板子有多少内存、闪存怎样分区。

这份通用镜像的 DTB 把内存写成了 0x04000000 字节,也就是 64 MiB;HG6543C1 实际装有 256 MiB。直接启动原镜像虽然能够进入 OpenWrt,但系统只会使用 64 MiB,几十秒后便可能耗尽内存、触发 OOM,然后自动重启。

这一节只改电脑里的镜像文件,不会改动光猫的 NAND 闪存。目标是把 DTB 中的内存大小改成:

0x10000000 字节 = 256 MiB

3.2 准备 DTB 工具

本文是在 Arch Linux 上操作的。先确认三个命令是否存在:

command -v dtc
command -v fdtget
command -v fdtput

如果没有输出,安装 dtc

sudo pacman -S dtc

dtc 用于在二进制 DTB 与可读的 DTS 文本之间转换;fdtget 用于读取属性,fdtput 用于修改属性。

3.3 先核对原始镜像,不能跳过

下面的 DTB 偏移量只适用于本文使用的这个确切文件。先执行:

stat -c '%s bytes' \
~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel.bin

sha256sum \
~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel.bin

应得到:

6436792 bytes
aa021db3486e4cfd06d746742145d469edd96011a31dc3b9f021799325d81be9

大小或 SHA-256 只要有一个不同,就不要继续照抄本节的 skip=6430768。不同构建的 DTB 位置可能不同,用错误偏移覆盖文件会得到无法启动的镜像。

3.4 从镜像末尾取出 DTB

本文镜像中的 DTB 从十六进制偏移 0x622030 开始:

0x622030 = 6430768(十进制)

原 DTB 长度为 0x1788,即 6024 字节。用 dd 把它单独复制出来:

mkdir -p /tmp/hg6543-dtb

dd \
if=~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel.bin \
of=/tmp/hg6543-dtb/router.dtb \
bs=1 skip=6430768 count=6024 status=none

检查提取结果:

stat -c '%s bytes' /tmp/hg6543-dtb/router.dtb
od -An -tx1 -N4 /tmp/hg6543-dtb/router.dtb

应看到 6024 字节,并且开头四字节为 DTB 的固定文件头:

6024 bytes
d0 0d fe ed

若大小或文件头不对,说明原镜像不一致或偏移量输错了,不要继续。

3.5 读取原值,再改成 256 MiB

先读 /memory@0reg 属性:

fdtget -t x /tmp/hg6543-dtb/router.dtb /memory@0 reg

本文原文件输出:

0 4000000

前一个 0 是内存起始地址,后一个 4000000 是容量,即十六进制 0x04000000,等于 64 MiB。执行修改:

fdtput -t x \
/tmp/hg6543-dtb/router.dtb \
/memory@0 reg 0 0x10000000

再次读取,确认命令真的生效:

fdtget -t x /tmp/hg6543-dtb/router.dtb /memory@0 reg

现在必须输出:

0 10000000

它对应的 DTS 含义是:

memory@0 {
device_type = "memory";
reg = <0x00000000 0x10000000>;
};

3.6 把修改后的 DTB 放回镜像副本

不要直接覆盖下载的原文件。先复制一份,再把修改后的 DTB 写回原来的偏移位置:

cp \
~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel.bin \
~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel-256m.bin

dd \
if=/tmp/hg6543-dtb/router.dtb \
of=~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel-256m.bin \
bs=1 seek=6430768 conv=notrunc status=none

这里的 conv=notrunc 表示只替换指定位置的数据,不截掉镜像的其他内容。

最后核对结果:

stat -c '%s bytes' \
~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel-256m.bin

sha256sum \
~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel-256m.bin

本文得到:

6436792 bytes
5b82cb0811bd5019bc77304f25b84aad2a1253ecb84efa486925e0b47629be96

到这里仅解决了“系统错误地只识别 64 MiB 内存”的问题。还不能方便地访问 ConfigurationB,因为通用 DTB 不知道 HG6543C1 的原厂分区布局,这就是下一步要解决的事。

第四步:把 HG6543C1 的原厂分区表加入临时镜像

4.1 为什么还要加入分区表

光猫闪存里的数据本来就已经按原厂布局存放好了,我们并不是重新分区。所谓“加入分区表”,只是告诉临时 OpenWrt:每个区域从哪里开始、有多大、应该叫什么名字。

通用镜像默认只会列出 all_flashbootloaderrest_of_flash 三个粗略区域。这样虽然能看到整颗 NAND,却没有单独的 ConfigurationB 设备,后面就无法直接执行:

mount -t jffs2 -o ro /dev/mtdblock7 /mnt/factory-config

原厂启动日志给出的布局如下。reg 使用的是“起始地址 + 长度”,不是“起始地址 + 结束地址”。例如 ConfigurationB0x2d80000 开始,长度为 0x300000,所以结束位置是 0x3080000

启动地址 长度 结束地址 名称
0x0000000 0x080000 0x0080000 boot
0x0080000 0x300000 0x0380000 KernelA
0x0380000 0x1280000 0x1600000 RootfsA
0x1600000 0x300000 0x1900000 KernelB
0x1900000 0x1280000 0x2b80000 RootfsB
0x2b80000 0x200000 0x2d80000 ConfigurationA
0x2d80000 0x300000 0x3080000 ConfigurationB
0x3080000 0x800000 0x3880000 Framework1
0x3880000 0x800000 0x4080000 Framework2
0x4080000 0x3b80000 0x7c00000 Apps

所有分区都会在设备树中加上 read-only;。即使后续输错写入命令,内核也会多提供一层只读保护。

4.2 把二进制 DTB 转成可编辑文本

第三步已经修改了 /tmp/hg6543-dtb/router.dtb 的内存容量。现在把这同一个 DTB 反编译成 DTS 文本:

dtc -I dtb -O dts \
-o /tmp/hg6543-dtb/router.dts \
/tmp/hg6543-dtb/router.dtb

dtc 可能报告与网口节点有关的 warning;只要命令成功生成 router.dts,与本次分区修改无关的 warning 可以保留观察。

先找到原分区块:

grep -n -A25 -B5 'fixed-partitions' /tmp/hg6543-dtb/router.dts

在本文镜像中,它位于以下层级:

spi_controller@1fa10000
└── nand@0
└── partitions

原来只有 all_flashbootloaderrest_of_flash 三项。

4.3 在文本编辑器中替换分区块

nano 打开文件:

nano /tmp/hg6543-dtb/router.dts

在 nano 中按 Ctrl+W,输入 fixed-partitions 后回车。找到包含它的整个 partitions { ... };,从 partitions { 开始到与它配对的 }; 为止,整块替换为下面内容。不要删掉外层的 nand@0 { ... };

partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;

partition@0 { label = "all_flash"; reg = <0x0 0x8000000>; read-only; };
partition@boot { label = "boot"; reg = <0x0 0x80000>; read-only; };
partition@80000 { label = "KernelA"; reg = <0x80000 0x300000>; read-only; };
partition@380000 { label = "RootfsA"; reg = <0x380000 0x1280000>; read-only; };
partition@1600000 { label = "KernelB"; reg = <0x1600000 0x300000>; read-only; };
partition@1900000 { label = "RootfsB"; reg = <0x1900000 0x1280000>; read-only; };
partition@2b80000 { label = "ConfigurationA"; reg = <0x2b80000 0x200000>; read-only; };
partition@2d80000 { label = "ConfigurationB"; reg = <0x2d80000 0x300000>; read-only; };
partition@3080000 { label = "Framework1"; reg = <0x3080000 0x800000>; read-only; };
partition@3880000 { label = "Framework2"; reg = <0x3880000 0x800000>; read-only; };
partition@4080000 { label = "Apps"; reg = <0x4080000 0x3b80000>; read-only; };
};

Ctrl+O 保存,按回车确认文件名,再按 Ctrl+X 退出 nano。最常见的编辑错误是漏掉分号或花括号;下一条编译命令会指出出错行号。

4.4 重新编译,并在做镜像前检查关键分区

把 DTS 编译回 DTB:

dtc -I dts -O dtb \
-o /tmp/hg6543-dtb/router-factoryparts.dtb \
/tmp/hg6543-dtb/router.dts

如果这里出现 FATAL ERROR,不要继续制作镜像。根据提示的行号返回 nano,重点检查 {} 和每行末尾的 ;

先确认第三步的 256 MiB 设置没有丢失:

fdtget -t x \
/tmp/hg6543-dtb/router-factoryparts.dtb \
/memory@0 reg

应输出:

0 10000000

再检查我们最终要读取的 ConfigurationB

fdtget \
/tmp/hg6543-dtb/router-factoryparts.dtb \
/spi_controller@1fa10000/nand@0/partitions/partition@2d80000 \
label

fdtget -t x \
/tmp/hg6543-dtb/router-factoryparts.dtb \
/spi_controller@1fa10000/nand@0/partitions/partition@2d80000 \
reg

必须分别输出:

ConfigurationB
2d80000 300000

这一步通过,才说明分区名称、起始地址和长度都已经进入新 DTB。

4.5 生成最终的 RAM 启动镜像

修改分区表后,新的 DTB 比原来的 6024 字节稍大,不能简单地在旧 DTB 上覆盖。正确做法是:复制第三步的 256 MiB 镜像,把文件截到 DTB 起始位置,再从同一位置接上新 DTB。

cp \
~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel-256m.bin \
~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel-256m-factoryparts.bin

truncate -s 6430768 \
~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel-256m-factoryparts.bin

dd \
if=/tmp/hg6543-dtb/router-factoryparts.dtb \
of=~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel-256m-factoryparts.bin \
bs=1 seek=6430768 conv=notrunc status=none

这里的 truncate 只处理电脑里的镜像副本,不会接触光猫。它先移除文件末尾的旧 DTB;随后的 dd 再把新 DTB 接到偏移 6430768

检查最终文件:

stat -c '%s bytes' \
~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel-256m-factoryparts.bin

sha256sum \
~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel-256m-factoryparts.bin

本文使用 dtc 1.8.1 得到:

6437464 bytes
f3970c31cf8fed1df586fa6925890c4669f4f4daecb10ec60da2714da70d1850

不同 dtc 版本重新编译出的二进制排列可能不同,因此 SHA-256 可以作为本文环境的参考,不应取代前面的 fdtget 检查。只要内存输出为 0 10000000,且 ConfigurationB 输出为 2d80000 300000,关键修改就是正确的。

最终生成的 -256m-factoryparts.bin 仍然是 RAM 临时启动镜像。到这里没有执行 Bootloader 的 flash 命令,也没有向 NAND 写入任何内容。

第五步:用 XMODEM 上传到 RAM

TcBoot 的 xmdm 与 picocom/lrzsz 的组合在本机反复出现 NAK on sector,因此使用 pyserialxmodem 直接发送。

保存以下脚本为 ~/Downloads/tcboot_xmodem_send.py

# /// script
# requires-python = ">=3.11"
# dependencies = ["pyserial>=3.5", "xmodem>=0.4.7"]
# ///

import argparse
import logging
import pathlib
import sys
import time

import serial
from xmodem import XMODEM


def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("image", type=pathlib.Path)
parser.add_argument("--port", default="/dev/ttyUSB0")
parser.add_argument("--address", default="80020000")
args = parser.parse_args()

image = args.image.expanduser().resolve()
if not image.is_file():
parser.error(f"image not found: {image}")

address = int(args.address, 16)
if not 0x80000000 <= address < 0x90000000:
parser.error("address is outside MIPS KSEG0 RAM")

size = image.stat().st_size
command = f"xmdm {address:08X} {size:X}\r".encode("ascii")
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")

print(f"Opening {args.port} at 115200 8N1")
print(f"Sending TcBoot command: {command.decode().strip()}")
print("RAM only: this script never invokes flash.")

with serial.Serial(
args.port,
115200,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=1,
write_timeout=10,
xonxoff=False,
rtscts=False,
dsrdtr=False,
exclusive=True,
) as uart:
uart.reset_input_buffer()
uart.write(command)
uart.flush()

deadline = time.monotonic() + 20
preamble = bytearray()
pending = bytearray()
while time.monotonic() < deadline:
byte = uart.read(1)
if not byte:
continue
if byte in (b"C", b"\x15"):
pending.extend(byte)
break
preamble.extend(byte)
else:
print("No XMODEM handshake", file=sys.stderr)
return 1

print("Handshake received; starting transfer.")

def getc(count: int, timeout: int = 1):
uart.timeout = timeout
data = bytearray()
if pending:
take = min(count, len(pending))
data.extend(pending[:take])
del pending[:take]
data.extend(uart.read(count - len(data)))
return data or None

def putc(data: bytes, timeout: int = 1):
uart.write_timeout = timeout
written = uart.write(data)
uart.flush()
return written

modem = XMODEM(getc, putc, mode="xmodem")
with image.open("rb") as stream:
if not modem.send(stream, retry=32, timeout=10, quiet=False):
return 1

uart.timeout = 0.5
deadline = time.monotonic() + 3
output = bytearray()
while time.monotonic() < deadline:
output.extend(uart.read(4096))
print(output.decode("utf-8", errors="replace"))
return 0


if __name__ == "__main__":
raise SystemExit(main())

先从 picocom 退出:Ctrl+A,再按 Ctrl+X。随后执行:

sudo -E ~/.local/bin/uv run \
~/Downloads/tcboot_xmodem_send.py \
~/Downloads/openwrt-econet-en751221-en751221_generic-initramfs-kernel-256m-factoryparts.bin

成功时会看到:

Handshake received; starting transfer.
INFO: Transmission successful (ACK received).
received len=623A80
bldr>

received len 可能因为 XMODEM 的 128 字节补齐而略大于原文件,这是正常的。此过程只写 RAM。

重新打开 picocom:

sudo picocom -b 115200 --flow n /dev/ttyUSB0

启动内存中的 OpenWrt:

bldr> jump 80020000

第六步:确认内存与分区

进入 shell 后检查内存:

free -m

正确结果应接近 256 MiB,而不是 64 MiB:

Mem: 249344 ...

检查分区:

cat /proc/mtd

应看到:

mtd0: 08000000 "all_flash"
mtd1: 00080000 "boot"
mtd2: 00300000 "KernelA"
mtd3: 01280000 "RootfsA"
mtd4: 00300000 "KernelB"
mtd5: 01280000 "RootfsB"
mtd6: 00200000 "ConfigurationA"
mtd7: 00300000 "ConfigurationB"
mtd8: 00800000 "Framework1"
mtd9: 00800000 "Framework2"
mtd10: 03b80000 "Apps"

原厂启动日志显示设备从 B 槽启动,因此当前配置位于 ConfigurationB,即 mtd7

第七步:只读挂载配置分区

mkdir -p /mnt/factory-config
mount -t jffs2 -o ro /dev/mtdblock7 /mnt/factory-config
mount | grep factory-config

JFFS2 可能输出 CLEANMARKEREmpty flash,甚至少量旧节点 CRC 警告。本机原厂内核启动时也会出现相同 CRC 地址。这里必须保持只读,不要使用通用内核修复或写入该分区。

列出文件:

find /mnt/factory-config -maxdepth 4 -type f | sort

目标文件为:

/mnt/factory-config/cfg/agentconf/factory.conf

只筛选管理账号字段:

grep -niE 'telecom|admin|pass|passwd|pwd|account|user' \
/mnt/factory-config/cfg/agentconf/factory.conf

或者只查看文件开头:

sed -n '1,12p' \
/mnt/factory-config/cfg/agentconf/factory.conf

本机得到的结构如下,实际密码已脱敏:

TelecomAccount=telecomadmin
TelecomPasswd=<本机超级管理员密码>
UserAccount=useradmin
UserPasswd=<本机普通管理员密码>

同一文件中还可看到原厂 Telnet root 账号配置:

TelnetSuperAccount=root
TelnetSuperPassword=<本机 Telnet root 密码>

下面是本次从只读配置分区取得账号信息时的实拍,设备序列号已经隐藏:

从 factory.conf 中读取超级管理员凭据,设备序列号已隐藏

不要在文章、截图或命令记录中公开真实密码。

第八步:退出临时系统并登录原厂后台

先卸载:

umount /mnt/factory-config

然后重启:

reboot -f

因为整个 OpenWrt 都在 RAM 中,断电或重启后会自动回到原厂系统,没有刷机,也没有改变 NAND 内容。

原厂系统启动完成后,通过光猫 Wi-Fi 访问:

http://192.168.1.1/
http://192.168.1.1:8080/

使用刚刚从 factory.conf 中读出的 TelecomAccountTelecomPasswd 登录即可。

失败过程与排错

串口完全无输出

  • 确认是 115200 8N1
  • 光猫 TX 必须接模块 RXD;
  • GND 必须共地;
  • 不要连接 VCC;
  • 确认 USB-TTL 逻辑电平是 3.3 V;
  • 57600 下看到乱码并不表示正确波特率,本机最终确认是 115200。

picocom 调用 lrzsz 一直 NAK

本机的 lrzsz-sx --xmodem 与 TcBoot 不兼容,改用本文的 Python XMODEM 脚本。脚本会先消费 Bootloader 回显,再把握手字符交给 XMODEM 库。

OpenWrt 启动后 OOM 自动重启

通用设备树只声明了 64 MiB。必须将 /memory@0/reg 改为 0x10000000,即 256 MiB。

RootfsB 无法挂载

Filesystem uses "lzma" compression. This is not supported

临时 OpenWrt 内核未启用旧式 SquashFS-LZMA。获取超级管理员密码并不需要 Rootfs,只挂载 JFFS2 的 ConfigurationB 即可。

JFFS2 出现 CRC 警告

保持只读。不要在实验内核下执行:

mount -o remount,rw
flash_erase
nandwrite
dd of=/dev/mtd...

这套方法最大的价值在于可回退:从进入 Bootloader 到读取配置,所有关键操作都发生在 RAM 或只读挂载中。只要不执行 Flash 写入,断电后仍会回到原厂系统。

CATALOG
  1. 1. 设备信息
  2. 2. 前置条件
    1. 2.1. 硬件
    2. 2.2. Linux 软件
  3. 3. 第一步:确认 UART 引脚
  4. 4. 第二步:读取启动日志并进入 Bootloader
  5. 5. 第三步:先把通用镜像识别的内存从 64 MiB 改成 256 MiB
    1. 5.1. 3.1 这一修改解决什么问题
    2. 5.2. 3.2 准备 DTB 工具
    3. 5.3. 3.3 先核对原始镜像,不能跳过
    4. 5.4. 3.4 从镜像末尾取出 DTB
    5. 5.5. 3.5 读取原值,再改成 256 MiB
    6. 5.6. 3.6 把修改后的 DTB 放回镜像副本
  6. 6. 第四步:把 HG6543C1 的原厂分区表加入临时镜像
    1. 6.1. 4.1 为什么还要加入分区表
    2. 6.2. 4.2 把二进制 DTB 转成可编辑文本
    3. 6.3. 4.3 在文本编辑器中替换分区块
    4. 6.4. 4.4 重新编译,并在做镜像前检查关键分区
    5. 6.5. 4.5 生成最终的 RAM 启动镜像
  7. 7. 第五步:用 XMODEM 上传到 RAM
  8. 8. 第六步:确认内存与分区
  9. 9. 第七步:只读挂载配置分区
  10. 10. 第八步:退出临时系统并登录原厂后台
  11. 11. 失败过程与排错
    1. 11.1. 串口完全无输出
    2. 11.2. picocom 调用 lrzsz 一直 NAK
    3. 11.3. OpenWrt 启动后 OOM 自动重启
    4. 11.4. RootfsB 无法挂载
    5. 11.5. JFFS2 出现 CRC 警告