威联通QHora-322免拆无损刷机教程
前言
手头有一台 QHora-322,其串口没有消息输出,因此无法通过线刷方式刷机。一直想找到一份像针对 Qhora-301W 那样的免拆刷机教程,但全网都找不到现成的。不过,找到了开启 SSH 的方法,并成功完成了免拆无损刷机。同时,还解决了刷机后原厂系统配置丢失的问题,实现了原厂 QuRouterOS 和 OpenWrt双系统之间的完全的自由切换。
现将刷机过程归纳总结成本教程,并将关键动作脚本化,分享给需要的朋友。受篇幅所限,本教程只介绍刷机方法和步骤,不介绍相关工具、OpenWrt和QuRouterOS原厂系统的具体使用,相关内容请自行熟悉。
本教程介绍的刷机方法有如下独特优点:
免拆、无损
无需拆机,无需TTL刷写版,无需接TTL串口线,通过开启ssh即可刷机,有台电脑就能操作;不改变路由器硬件状态,软件可恢复成原厂状态。
双系统完全独立,可自由切换,互不影响
OpenWrt运行时不占用原厂系统存放配置的分区,原厂系统运行时也不破坏OpenWrt配置,双系统可自由切换,切换后无需重配系统、重配网络,切换即可用。
关键刷机动作和双系统切换脚本化,降低难度和出错概率(注:脚本在AI的协助下编写完成)
重要警示:
刷机有风险,稍有不慎就变砖;风险自担,请谨慎操作;
刷机后,原厂系统升级会覆盖OpenWrt,因此刷机后请勿升级原厂系统;
QHora-321的刷机思路类似,但手头没有QHora-321,故未适配QHora-321,刷机脚本请勿直接用于QHora-321刷机。
一、刷机工具与固件准备
1.1、必备软件&网络配件
7Zip解压工具:用于固件分层二次解压;
FinalShell:用于 SSH 远程连接、文件上传下载、命令行操作;
FinalShell工具也可以用Putty + WinSCP来替代,其中WinSCP登录时协议选SFTP,端口号填22200;
1.2、OpenWrt固件下载&预处理
前往 OpenWrt 官网,下载 iEi Puzzle-M902(QHora-322同款硬件) 对应的 SDCARD (SQUASHFS) 格式最新稳定版本固件,OpenWrt官网下载地址:https://downloads.openwrt.org/releases/25.12.4/targets/mvebu/cortexa72/openwrt-25.12.4-mvebu-cortexa72-iei_puzzle-m902-squashfs-sdcard.img.gz
使用 7Zip 对固件压缩包连续解压两次:第一次解压得到分包文件,第二次解压分包文件,第二次解压会报一个“文件末端错误:1.img”,此报错对1.img文件的完整性无影响,不影响刷机,请忽略;
解压完成后得到两个镜像文件:0.img、1.img,请将0.img 改名为 kernel.img,1.img 改名为 rootfs.img。
1.3、准备刷机脚本
本文后附两个刷机脚本和两个双系统切换脚本内容,请将两个刷机脚本pre_backup.sh、flash_write.sh的内容拷贝下来,用文本编辑器分别以pre_backup.sh、flash_write.sh文件名保存。
双系统切换脚本在要切换系统时再使用,第八、第九节有介绍。
二、备份原厂路由器配置(可选)
建议在刷机开始之前,先备份路由器原厂系统配置,具体方法是通过浏览器登录原厂QuRouterOS,进入 系统 > 系统设置 > 重置/备份/恢复 页面,点击“备份”按钮备份,按提示操作即可。
重要提示:记住这份配置中的admin用户密码,下次用此配置备份恢复的系统,密码也会恢复成此密码。
三、开启原厂 QuRouterOS SSH 权限
原厂QuRouterOS系统默认关闭 SSH 功能,可通过复位键快捷开启。
路由器正常通电、进入原厂系统正常运行状态,浏览器可登录;
连续短按 RESET 键 3 次(轻点即可,不要长按);
设备发出一长声“嘀”提示音,即代表 SSH 成功开启。
说明:
该开启方式在 QuRouterOS 2.6.x 版本测试通过,未测试过早期版本;若早期版本无法开启 SSH,建议升级路由器原厂固件至最新版;
长按 RESET 键会直接初始化 QuRouterOS,如果不小心重置了,初始密码为路由器MAC地址,见路由器背面标签。
四、实施刷机
4.1、FinalShell登录路由器ssh
电脑网线插入路由器第二网口,电脑设置自动获取 IP,打开 FinalShell 新建 SSH 连接,参数如下(原厂专属配置):
默认管理 IP:192.168.100.1(不通时以电脑以太网获取到的网关地址为准)
SSH 端口:22200
用户名:admin
密码:路由器登录密码
4.2、上传刷机文件
1. 检查并清理 /tmp 空间:
在FinalShell界面ssh shell命令行执行命令df -h /tmp 查看空间;
如果空闲空间不足800M,执行 sudo rm -rf /tmp/* 清除/tmp空间。
2. 上传文件:
在FinalShell界面右下角文件窗口中上传文件kernel.img、rootfs.img、pre_backup.sh、flash_write.sh四个文件上传到路由器/tmp目录下。
4.3、刷机文件预处理
在FinalShell界面右上角ssh shell窗口执行如下命令,转换windows换行符(finalshell上传的文件不会自动转换);
sed 's/r//g' /tmp/pre_backup.sh > /tmp/pre_backup.tmp && mv /tmp/pre_backup.tmp /tmp/pre_backup.sh
sed 's/r//g' /tmp/flash_write.sh > /tmp/flash_write.tmp && mv /tmp/flash_write.tmp /tmp/flash_write.sh
执行如下命令,给刷机脚本赋可执行权限:
chmod +x /tmp/pre_backup.sh
chmod +x /tmp/flash_write.sh

4.4、执行预刷机脚本pre_backup.sh
ssh shell窗口执行:/tmp/pre_backup.sh
pre_backup.sh只干两件事情:
o 确定当前系统运行的活动分区,以及待刷机的备用分区;
o 完整备份原厂系统备用分区,以备以后恢复使用。
说明:威联通路由器备用分区有小概率损坏无法启动,为降低变砖风险,此教程中,在刷机前不做分区切换,保留当前正成功运行的活动分区中的原厂系统,OpenWrt刷入备用分区,故要先确定活动分区和备用分区。

4.5、下载原厂备用分区备份
FinalShell 右侧文件目录进入路由器 /tmp 文件夹,找到生成的备份 img 文件,右键下载到电脑本地保存。
4.6、执行刷机脚本flash_write.sh
【风险提示】此脚本执行关键刷机动作,执行期间断电会导致路由器变砖,此脚本执行期间严禁断电。
ssh shell窗口执行:/tmp/flash_write.sh
flash_write.sh完成如下事项:
将上传的kernel.img、rootfs.img刷写入系统备用分区;
自定义环境变量boot_orig_entry、boot_owrt_entry标识原厂系统和新刷的openwrt系统所在的分区;
固化原厂QuRouterOS和新刷的OpenWrt系统的启动命令,简化后续的双系统切换操作,降低操作难度和出错机率;
切换系统启动环境变量,指向新刷的OpenWrt系统。

五、OpenWrt 首次登录和设置
执行sudo reboot,重启后即切换成OpwnWrt系统;若启动时间过长,请断电重启。
路由器重启完成后, 通过电脑浏览器登录路由器,OpenWrt 默认地址:192.168.1.1;
192.168.1.1为网络设备常用缺省ip,如果无法访问,可能是与网络上光猫或其他网络设备ip冲突,请尝试手动设置电脑IP为 192.168.1.2,子网掩码 255.255.255.0,并断开路由器和电脑上的其他网络连接(包括Wi-Fi),仅保留电脑通过网线连接路由器的这条唯一连接,然后重试;
首次登录无密码,用户名root,根据页面提示设置管理员密码(必须设置密码,第六节的OpenWrt ssh登录才能成功);
按自己需求配置上网方式,配置系统、配置网络。
说明: OpenWrt系统中网口顺序有变,对照表如下:

六、修复缺失的文件fw_env.config
OpenWrt 缺少 U-Boot 环境变量配置文件,导致fw_printenv和fw_setenv 命令执行失败,也就无法通过修改环境变量,实现双系统自由切换。修复方法:
FinalShell 连接 OpenWrt SSH:端口22,用户名root,密码为你刚设置的管理员密码;
在ssh shell命令行执行命令, echo "/dev/mtd3 0x0 0x10000 0x10000 1" > /etc/fw_env.config,生成环境变量配置文件;
ssh Shell窗口执行 fw_printenv 测试,能正常输出变量即修复成功。
注:有朋友刷的iStoreOS好像也缺此配置文件,亦可用此方法修复。

七、备份OpenWrt配置(可选)
在需要切换回原厂系统前请做配置备份。以防原厂系统被误升级破坏了OpenWrt系统。具体方法是通过浏览器登录OpenWrt,进入 System > Backup / Flash Firmware 页面,点击"Generate archive" 按钮备份,按提示操作即可。
重要提示:记住这份配置中的root用户密码,下次用此配置备份恢复的系统,密码也会恢复成此密码。
八、OpenWrt 切换回原厂QuRouterOS
FinalShell 连接 OpenWrt SSH:端口22,用户名root,密码为你设置的管理员密码
生成一键切换脚本(只需在第一次从OpenWrt切换到QuRouterOS时才生成一次):
从附件脚本三拷贝生成一键切换脚本的生成命令,粘贴到ssh shell命令行执行,生成切换脚本switch_to_origin.sh
ssh shell执行命令,chmod +x /root/switch_to_origin.sh,给切换脚本赋可执行权限
执行switch_to_origin.sh,完成系统切换的环境变量设置。
校验无误后执行 reboot,重启后即切换回原厂 QuRouterOS 系统。若启动时间过长,请断电重启。

九、原厂QuRouterOS切换回OpenWrt
按第三节的方法开启ssh,finalshell登录路由器ssh
生成一键切换脚本(只需在第一次从QuRouterOS切换到OpenWrt时生成一次):
从附件脚本四拷贝生成一键切换脚本的生成命令,粘贴到ssh shell命令行执行,生成切换脚本switch_to_openwrt.sh
ssh shell执行命令,chmod +x /home/admin/switch_to_openwrt.sh,给切换脚本赋可执行权限
执行switch_to_openwrt.sh,完成系统切换的环境变量设置。
校验无误后执行sudo reboot,重启后即切换成OpenWrt。若启动时间过长,请断电重启。

十、恢复成原厂系统(需要恢复原厂时执行)
如果不再需要OpenWrt,QHora-322在切换回原厂系统后,做一次升级,即可恢复成原厂状态,具体方法如下:
如果当前运行的是OpenWrt,按第八节的办法,切换回QuRouterOS原厂系统
浏览器登录到QuRouterOS系统
在“固件”页面,转到“QNAP 下载中心”下载最新固件版本(即使与当前运行版本一致,也可下载和更新)
在“固件”页面,上传下载的固件,并手动更新。更新完成,等待系统重启
重启完成后,按第三节的办法,开启ssh
FinalShell登录QuRouterOS的ssh,并在ssh shell命令行执行:
sudo fw_printenv current_entry
sudo fw_printenv boot_orig_entry
如果这两值不相同,且一个为1,一个为2,则表示OpenWrt分区已被原厂系统覆盖,继续下一步,如果两值相等,则回到第3步重新更新系统。
执行如下命令,消除刷机残留环境变量:
sudo fw_setenv boot_orig_entry
sudo fw_setenv boot_owrt_entry
sudo fw_setenv boot_OpenWrt
sudo fw_setenv boot_QuRouterOS
至此,已完全消除刷机痕迹,完全恢复成原厂状态。
附件:
脚本一:pre_backup.sh 【分区检测 + 备用分区备份】
#!/bin/sh
# QHora-322 免拆无损刷机 - 前置备份脚本
# 自动分区校验 + 备用分区备份
# 非法分区直接终止,杜绝未知分区变砖
# 读取当前启动项
current_entry=$(sudo fw_printenv current_entry | awk -F= '{print $2}')
# 合法分区校验
if [ "$current_entry" = "1" ];then
owrt_entry=2
orig_entry=1
part_kernel=p2
part_rootfs=p4
elif [ "$current_entry" = "2" ];then
owrt_entry=1
orig_entry=2
part_kernel=p1
part_rootfs=p3
else
echo "======================================"
echo "错误:未知 current_entry = $current_entry"
echo "仅支持 entry=1 / entry=2,刷机终止!"
echo "======================================"
exit 1
fi
echo "======================================"
echo "分区校验通过!"
echo "当前原厂运行活动分区 entry: $current_entry"
echo "待刷写备用分区 entry: $owrt_entry"
echo "内核分区: $part_kernel"
echo "根文件系统分区: $part_rootfs"
echo "======================================"
# 开始备份备用分区
echo "正在备份备用内核分区 $part_kernel ..."
sudo dd if=/dev/mmcblk0${part_kernel} of=/tmp/${part_kernel}-backup.img || { echo "内核分区备份失败!"; exit 1; }
echo "正在备份备用根文件系统分区 $part_rootfs ..."
sudo dd if=/dev/mmcblk0${part_rootfs} of=/tmp/${part_rootfs}-backup.img || { echo "根文件系统分区备份失败!"; exit 1; }
echo "======================================"
echo "分区备份完成!"
echo "请将/tmp目录中以下文件下载到电脑:"
echo "1. ${part_kernel}-backup.img"
echo "2. ${part_rootfs}-backup.img"
echo "======================================"
echo "【重要】备份保存完成后,执行第二阶段刷机脚本 flash_write.sh"
echo "======================================"
脚本二:flash_write.sh 【写入固件 + 配置双系统环境变量】
#!/bin/sh
# QHora-322 免拆无损刷机 - 正式刷机脚本
# 写入镜像 + 配置双系统变量 + 固化原厂系统和OpenWrt启动命令
# 读取当前启动项,二次校验防误刷
current_entry=$(sudo fw_printenv current_entry | awk -F= '{print $2}')
#分区固定映射规则(硬件固化:entry1=p1+p3 / entry2=p2+p4)
if [ "$current_entry" = "1" ];then
owrt_entry=2
orig_entry=1
part_kernel=p2
part_rootfs=p4
elif [ "$current_entry" = "2" ];then
owrt_entry=1
orig_entry=2
part_kernel=p1
part_rootfs=p3
else
echo "分区校验异常,终止刷机!"
exit 1
fi
# 确认备份文件已下载交互
read -p "确认已将${part_kernel}-backup.img、${part_rootfs}-backup.img备份镜像下载至电脑?输入y继续,其他退出:" ack
if [ "$ack" != "y" ];then
echo "刷机终止,请先下载备份文件!"
exit 1
fi
# 校验镜像文件是否存在
if [ ! -f "/tmp/kernel.img" ] || [ ! -f "/tmp/rootfs.img" ];then
echo "======================================"
echo "错误:未检测到 kernel.img / rootfs.img"
echo "请上传固件至 /tmp 后重试!"
echo "======================================"
exit 1
fi
echo "开始写入 OpenWrt 内核镜像 kernel.img ..."
sudo dd if=/tmp/kernel.img of="/dev/mmcblk0${part_kernel}" || { echo "内核镜像写入失败!终止刷机"; exit 1; }
echo "开始写入 OpenWrt 根文件系统镜像 rootfs.img ..."
sudo dd if=/tmp/rootfs.img of="/dev/mmcblk0${part_rootfs}" || { echo "根文件系统镜像写入失败!终止刷机"; exit 1; }
echo "镜像写入完成,开始配置双系统环境变量..."
# 双系统分区标记变量
sudo fw_setenv boot_orig_entry $orig_entry
sudo fw_setenv boot_owrt_entry $owrt_entry
# 固化原厂QuRouterOS启动命令
if [ "$orig_entry" = "1" ];then
sudo fw_setenv boot_QuRouterOS 'ext4load mmc 0:1 0x6500000 Image; ext4load mmc 0:1 0x6000000 cn9132-db-A.dtb; setenv bootargs $console cpuidle.off=1; booti 0x6500000 - 0x6000000'
elif [ "$orig_entry" = "2" ];then
sudo fw_setenv boot_QuRouterOS 'ext4load mmc 0:2 0x6500000 Image; ext4load mmc 0:2 0x6000000 cn9132-db-A.dtb; setenv bootargs $console cpuidle.off=1; booti 0x6500000 - 0x6000000'
else
echo "======================================"
echo "错误:检测到非法orig_entry值:$orig_entry"
echo "分区校验异常,终止配置!"
echo "======================================"
exit 1
fi
# 固化OpenWrt启动命令,启动命令中root=… fstools_ignore_partname=…是OpenWrt启动中比原厂系统启动中新增的必选项
# 严格校验owrt_entry合法值,非法值直接退出,避免错误分区挂载
if [ "$owrt_entry" = "2" ];then
sudo fw_setenv boot_OpenWrt 'ext4load mmc 0:2 0x6500000 Image; ext4load mmc 0:2 0x6000000 cn9132-puzzle-m902.dtb; setenv bootargs $console root=/dev/mmcblk0p4 fstools_ignore_partname=1 cpuidle.off=1; booti 0x6500000 - 0x6000000'
elif [ "$owrt_entry" = "1" ];then
sudo fw_setenv boot_OpenWrt 'ext4load mmc 0:1 0x6500000 Image; ext4load mmc 0:1 0x6000000 cn9132-puzzle-m902.dtb; setenv bootargs $console root=/dev/mmcblk0p3 fstools_ignore_partname=1 cpuidle.off=1; booti 0x6500000 - 0x6000000'
else
echo "======================================"
echo "错误:检测到非法owrt_entry值:$owrt_entry"
echo "无法匹配合法OpenWrt根分区,终止配置!"
echo "======================================"
exit 1
fi
# ====================== 设置启动关键环境变量 ======================
sudo fw_setenv bootcmd 'run boot_OpenWrt'
sudo fw_setenv current_entry 0
# 批量校验U-Boot环境变量写入结果
echo "校验U-Boot环境变量..."
sudo fw_printenv boot_orig_entry || { echo "环境变量 boot_orig_entry 读取失败!"; }
sudo fw_printenv boot_owrt_entry || { echo "环境变量 boot_owrt_entry 读取失败!"; }
sudo fw_printenv boot_QuRouterOS || { echo "环境变量 boot_QuRouterOS 读取失败!"; }
sudo fw_printenv boot_OpenWrt || { echo "环境变量 boot_OpenWrt 读取失败!"; }
sudo fw_printenv bootcmd || { echo "环境变量 bootcmd 读取失败!"; }
sudo fw_printenv current_entry || { echo "环境变量 current_entry 读取失败!"; }
echo "======================================"
echo "全部配置完成!即将重启进入 OpenWrt 25.12.4"
echo "检查环境变量无误后,请执行sudo reboot,重启系统"
echo "======================================"
脚本三:生成切换脚本switch_to_origin.sh,从OpenWrt到QuRoterOS
cat > /root/switch_to_origin.sh <<'EOF'
#!/bin/sh
set -e
# 兼容所有fw_printenv,完整截取=后全部内容
get_fw_val() {
local key="$1"
fw_printenv "$key" | sed 's/^[^=]*=//'
}
# 提取字符串内第一个 mmc 0:X 的数字
get_mmc_part() {
local cmd="$1"
echo "$cmd" | grep -oE 'mmc 0:[0-9]+' | head -n1 | cut -d: -f2
}
# 前置校验函数:1.四个变量存在;2.entry与对应启动命令分区号匹配
check_env_exist() {
local missing=""
# 检查四个核心变量是否存在
if ! fw_printenv boot_orig_entry >/dev/null 2>&1; then
missing="${missing} boot_orig_entry"
fi
if ! fw_printenv boot_owrt_entry >/dev/null 2>&1; then
missing="${missing} boot_owrt_entry"
fi
if ! fw_printenv boot_QuRouterOS >/dev/null 2>&1; then
missing="${missing} boot_QuRouterOS"
fi
if ! fw_printenv boot_OpenWrt >/dev/null 2>&1; then
missing="${missing} boot_OpenWrt"
fi
if [ -n "$missing" ]; then
echo "错误:以下U-Boot变量未定义,请手工修复后重试:$missing"
exit 1
fi
echo "✅ 全部4个必要环境变量校验存在:boot_orig_entry boot_owrt_entry boot_QuRouterOS boot_OpenWrt"
# 校验1:boot_orig_entry == boot_QuRouterOS 内 mmc 0:X
ORIG_ENTRY_VAL=$(get_fw_val boot_orig_entry)
QU_CMD=$(get_fw_val boot_QuRouterOS)
QU_MMC_PART=$(get_mmc_part "$QU_CMD")
if [ "$ORIG_ENTRY_VAL" != "$QU_MMC_PART" ]; then
echo "❌ 前置校验失败:"
echo "boot_orig_entry=$ORIG_ENTRY_VAL"
echo "boot_QuRouterOS 内 mmc 0:$QU_MMC_PART"
echo "两者分区号不一致,请修正U-Boot环境变量后重试"
exit 1
fi
# 校验2:boot_owrt_entry == boot_OpenWrt 内 mmc 0:X
OW_ENTRY_VAL=$(get_fw_val boot_owrt_entry)
OW_CMD=$(get_fw_val boot_OpenWrt)
OW_MMC_PART=$(get_mmc_part "$OW_CMD")
if [ "$OW_ENTRY_VAL" != "$OW_MMC_PART" ]; then
echo "❌ 前置校验失败:"
echo "boot_owrt_entry=$OW_ENTRY_VAL"
echo "boot_OpenWrt 内 mmc 0:$OW_MMC_PART"
echo "两者分区号不一致,请修正U-Boot环境变量后重试"
exit 1
fi
echo "✅ entry与对应启动命令mmc分区号全部匹配"
}
# 执行全部前置校验
check_env_exist
# ---------------- 切换原厂逻辑 ----------------
ORIG_ENTRY=$(get_fw_val boot_orig_entry)
echo "原厂分区标识 boot_orig_entry = $ORIG_ENTRY"
fw_setenv current_entry "$ORIG_ENTRY"
echo "已同步 current_entry = $ORIG_ENTRY"
ORIG_BOOT_CMD=$(get_fw_val boot_QuRouterOS)
echo "读取QuRouterOS完整启动命令完成"
fw_setenv bootcmd "$ORIG_BOOT_CMD"
echo "已替换bootcmd为原厂启动指令"
echo -e "n===== 后置校验1:boot_orig_entry / current_entry ====="
fw_printenv boot_orig_entry current_entry
echo -e "n===== 后置校验2:boot_QuRouterOS 与 bootcmd 全文比对 ====="
VAL_QU=$(get_fw_val boot_QuRouterOS)
VAL_BOOTCMD=$(get_fw_val bootcmd)
if [ "$VAL_QU" = "$VAL_BOOTCMD" ]; then
echo "✅ boot_QuRouterOS 与 bootcmd 内容完全一致"
else
echo "❌ boot_QuRouterOS 与 bootcmd 内容不匹配!"
exit 1
fi
echo -e "n===== 后置校验3:mmc分区号与current_entry匹配 ====="
MMC_NUM=$(get_mmc_part "$VAL_BOOTCMD")
CUR_ENTRY=$(get_fw_val current_entry)
echo "bootcmd 内 mmc 0:$MMC_NUM"
echo "current_entry = $CUR_ENTRY"
if [ "$MMC_NUM" = "$CUR_ENTRY" ]; then
echo "✅ 分区数字匹配,全部校验通过"
else
echo "❌ mmc分区号与current_entry不一致,配置异常"
exit 1
fi
echo -e "n操作完成,执行 reboot 重启进入原厂系统"
EOF
脚本四:生成切换脚本switch_to_openwrt.sh,从QuRoterOS到OpenWrt
cat > /home/admin/switch_to_openwrt.sh <<'EOF'
#!/bin/sh
set -e
# 兼容所有fw_printenv,完整截取=后全部内容
get_fw_val() {
local key="$1"
sudo fw_printenv "$key" | sed 's/^[^=]*=//'
}
# 提取字符串内第一个 mmc 0:X 的数字
get_mmc_part() {
local cmd="$1"
echo "$cmd" | grep -oE 'mmc 0:[0-9]+' | head -n1 | cut -d: -f2
}
# 前置校验函数:1.四个变量存在;2.entry与对应启动命令分区号匹配
check_env_exist() {
local missing=""
# 检查四个核心变量(boot_openwrt_entry → boot_owrt_entry)
if ! sudo fw_printenv boot_orig_entry >/dev/null 2>&1; then
missing="${missing} boot_orig_entry"
fi
if ! sudo fw_printenv boot_owrt_entry >/dev/null 2>&1; then
missing="${missing} boot_owrt_entry"
fi
if ! sudo fw_printenv boot_QuRouterOS >/dev/null 2>&1; then
missing="${missing} boot_QuRouterOS"
fi
if ! sudo fw_printenv boot_OpenWrt >/dev/null 2>&1; then
missing="${missing} boot_OpenWrt"
fi
if [ -n "$missing" ]; then
echo "错误:以下U-Boot变量未定义,请手工修复后重试:$missing"
exit 1
fi
echo "✅ 全部4个必要环境变量校验存在:boot_orig_entry boot_owrt_entry boot_QuRouterOS boot_OpenWrt"
# 校验1:boot_orig_entry == boot_QuRouterOS 内 mmc 0:X
ORIG_ENTRY_VAL=$(get_fw_val boot_orig_entry)
QU_CMD=$(get_fw_val boot_QuRouterOS)
QU_MMC_PART=$(get_mmc_part "$QU_CMD")
if [ "$ORIG_ENTRY_VAL" != "$QU_MMC_PART" ]; then
echo "❌ 前置校验失败:"
echo "boot_orig_entry=$ORIG_ENTRY_VAL"
echo "boot_QuRouterOS 内 mmc 0:$QU_MMC_PART"
echo "两者分区号不一致,请修正U-Boot环境变量后重试"
exit 1
fi
# 校验2:boot_owrt_entry == boot_OpenWrt 内 mmc 0:X
OW_ENTRY_VAL=$(get_fw_val boot_owrt_entry)
OW_CMD=$(get_fw_val boot_OpenWrt)
OW_MMC_PART=$(get_mmc_part "$OW_CMD")
if [ "$OW_ENTRY_VAL" != "$OW_MMC_PART" ]; then
echo "❌ 前置校验失败:"
echo "boot_owrt_entry=$OW_ENTRY_VAL"
echo "boot_OpenWrt 内 mmc 0:$OW_MMC_PART"
echo "两者分区号不一致,请修正U-Boot环境变量后重试"
exit 1
fi
echo "✅ entry与对应启动命令mmc分区号全部匹配"
}
# 执行全部前置校验
check_env_exist
# ---------------- 切换OpenWrt逻辑:先更新bootcmd,后设置current_entry=0 ----------------
OW_BOOT=$(get_fw_val boot_OpenWrt)
sudo fw_setenv bootcmd "$OW_BOOT"
sudo fw_setenv current_entry "0"
echo "===== 后置校验1:boot_owrt_entry / current_entry ====="
sudo fw_printenv boot_owrt_entry current_entry
# 新增校验current_entry必须等于0
CUR_ENTRY_CHECK=$(get_fw_val current_entry)
if [ "$CUR_ENTRY_CHECK" = "0" ]; then
echo "✅ current_entry = 0,符合设定"
else
echo "❌ current_entry 不为0,配置异常"
exit 1
fi
echo -e "n===== 后置校验2:boot_OpenWrt 与 bootcmd 全文比对 ====="
VAL_OW=$(get_fw_val boot_OpenWrt)
VAL_BOOT=$(get_fw_val bootcmd)
if [ "$VAL_OW" = "$VAL_BOOT" ]; then
echo "✅ 启动命令完整匹配"
else
echo "❌ 启动命令不匹配"
exit 1
fi
echo -e "n===== 后置校验3:mmc分区号与boot_owrt_entry匹配 ====="
MMC_NUM=$(get_mmc_part "$VAL_BOOT")
OW_ENTRY=$(get_fw_val boot_owrt_entry)
echo "mmc分区号:$MMC_NUM boot_owrt_entry:$OW_ENTRY"
if [ "$MMC_NUM" = "$OW_ENTRY" ]; then
echo "✅ 分区编号匹配"
else
echo "❌ 分区编号不匹配"
exit 1
fi
echo "操作完成,执行sudo reboot 重启进OpenWrt"
EOF

TheOneWalker
大佬的不死uboot有吗
校验提示文案
TheOneWalker
大佬的不死uboot有吗
校验提示文案