18-Openwrt sysupgrade系统升级
openwrt的升级是使用sysupgrade工具来升级的,该工具为sbin下面的一个脚本,可以附带很多参数,但是我们一般就直接sysupgrade openwrt-ramips-mt7621-device-squashfs-sysupgrade.
bin升级
参数 | 说明 |
---|---|
-i | 开启交互模式 |
-d | 重启前延迟,延迟秒数是传进来的 |
-v | 会打印sysupgrade脚本中的一些信息,脚本中默认打印 |
-q | 与-v相反 |
-n | 升级后不保存配置,默认保存配置 |
-c | 保存所有的改动配置文件到/etc/ |
-b | 用sysupgrade.conf中指定的文件,创建.tar.gz格式备份文件 |
-r | 用上步创建的.tar.gz文件,恢复配置 |
-l | 列出将会备份的文件列表 |
-f | 从.tar.gz恢复配置 |
-F | 即使升级文件检测失败,也要升级,这个参数是危险的,慎用 |
-T | 验证升级文件和.tar.gz配置文件,但不升级 |
-h | 打印帮助信息 |
sysupgrade的升级流程查看/sbin/sysupgrade脚本可以比较直观.
1、check校验固件合法性
sysupgrade的第一步就是校验固件合法性,如下判断platform_check_image
函数存在则开始执行。
type platform_check_image >/dev/null 2>/dev/null || {
echo "Firmware upgrade is not implemented for this platform."
exit 1
}
for check in $sysupgrade_image_check; do
( eval "$check \"\$1\"" ) || {
echo "Image check '$check' $1 failed."
return 1
}
done
该函数位于lib/upgrade/platform.sh
中,根据产品的型号来判断各自的magic值。
platform_check_image() {
local board=$(ramips_board_name)
local magic="$(get_magic_long "$1")"
[ "$#" -gt 1 ] && return 1
case "$board" in
br-6475nd)
[ "$magic" != "43535953" ] && {
echo "Invalid image type."
return 1
}
return 0
;;
ubnt-erx)
nand_do_platform_check "$board" "$1"
return $?;
;;
mt7621-*)
[ "$magic" != "d00dfeed" ] && {
echo "Invalid image type."
return 1
}
return 0;
;;
esac
echo "Sysupgrade is not yet supported on $board."
return 1
}
我们一般会在该check函数下面添加私有的校验方式,如固件的验签等功能。
2、保存config配置文件
export SAVE_CONFIG=1
默认的SAVE_CONFIG标志为为1,所以默认要保存uci配置文件
if [ -n "$CONF_IMAGE" ]; then
case "$(get_magic_word $CONF_IMAGE cat)" in
# .gz files
1f8b) ;;
*)
echo "Invalid config file. Please use only .tar.gz files"
exit 1
;;
esac
get_image "$CONF_IMAGE" "cat" > "$CONF_TAR"
export SAVE_CONFIG=1
elif ask_bool $SAVE_CONFIG "Keep config files over reflash"; then
[ $TEST -eq 1 ] || do_save_conffiles
export SAVE_CONFIG=1
else
export SAVE_CONFIG=0
fi
保存config文件函数如下:
do_save_conffiles() {
local conf_tar="${1:-$CONF_TAR}"
[ -z "$(rootfs_type)" ] && {
echo "Cannot save config while running from ramdisk."
ask_bool 0 "Abort" && exit
return 0
}
run_hooks "$CONFFILES" $sysupgrade_init_conffiles
ask_bool 0 "Edit config file list" && vi "$CONFFILES"
v "Saving config files..."
[ "$VERBOSE" -gt 1 ] && TAR_V="v" || TAR_V=""
tar c${TAR_V}zf "$conf_tar" -T "$CONFFILES" 2>/dev/null
rm -f "$CONFFILES"
}
如果sysupgrade的时候带参数-n,sysupgrade -n openwrt-ramips-mt7621-device-squashfs-sysupgrade. bin
,则会将SAVE_CONFIG=0.
3、run_hooks "" $sysupgrade_pre_upgrade
这句的意思是:运行函数sysupgrade_pre_upgrade。先介绍下run_hooks函数,定义在文件common.sh中。
run_hooks() {
localarg="$1"; shift
forfunc in "$@"; do
eval"$func $arg"
done
}
run_hooks函数是钩子函数,其中传过来的第一个参数是函数运行的参数,其余参数为要运行的函数。
disable_watchdog() {
killall watchdog
( ps | grep -v 'grep' | grep '/dev/watchdog' ) && {
echo 'Could not disable watchdog'
return 1
}
}
append sysupgrade_pre_upgrade disable_watchdog
就是在升级前,去清除watchdog进程
4、 ubus call system upgrade
调用注册到ubus进程的system路径下的update方法,update方法设置了upgrade_running变量值为1,使得在ubus上注册的服务退出时无需等待。
root@zihome:/usr/sbin# ubus list system -v
'system' @3b46ff0c
"board":{}
"info":{}
"upgrade":{}
"watchdog":{"frequency":"Integer","timeout":"Integer","stop":"Boolean"}
"signal":{"pid":"Integer","signum":"Integer"}
"nandupgrade":{"path":"String"}
5、do_upgrade升级
vim /sbin/sysupgrade
if [ -n "$(rootfs_type)" ]; then
v "Switching to ramdisk..."
(run_ramfs '. /lib/functions.sh; include /lib/upgrade; do_upgrade') &
else
(do_upgrade) &
fi
vim /lib/upgrade/common.sh
do_upgrade() {
clear_caches
v "Performing system upgrade..."
if type 'platform_do_upgrade' >/dev/null 2>/dev/null; then
platform_do_upgrade "$ARGV"
else
default_do_upgrade "$ARGV"
fi
}
image升级,保存到对应的mtd分区,这边的PART_NAME在头部会定义为fireware
default_do_upgrade() {
sync
if [ "$SAVE_CONFIG" -eq 1 ]; then
get_image "$1" "$2" | mtd $MTD_CONFIG_ARGS -j "$CONF_TAR" write - "${PART_NAME:-image}"
else
get_image "$1" "$2" | mtd write - "${PART_NAME:-image}"
fi
}
6、config保存/删除
保存完固件之后,就开始处理config配置文件
if [ "$SAVE_CONFIG" -eq 1 ] && type 'platform_copy_config' >/dev/null 2>/dev/null; then
platform_copy_config
fi
if [ "$SAVE_CONFIG" -eq 0 ] && type 'platform_remove_config' >/dev/null 2>/dev/null; then
platform_remove_config
fi
如果需要保存配置文件,则将config拷贝到/overlay下,`这边的$CONF_TAR压缩包就是上面第二步保存的配置文件
platform_copy_config() {
local board_flash=$(mtk_board_flash)
case "$board_flash" in
"nand"|"spi")
upgrade_log "Save config"
rm -rf $1/*
cp -af "$CONF_TAR" $1/
sync
;;
esac
}
如果不需要保存则删除/overlay下的config
platform_remove_config() {
local board_flash=$(mtk_board_flash)
case "$board_flash" in
"nand"|"spi")
upgrade_log "Drop config"
rm -rf $1/*
;;
esac
}
7、重启
v "Upgrade completed"
[ -n "$DELAY" ] && sleep "$DELAY"
v "Rebooting system..."
upgrade_log_end
reboot -f
sleep 2
force_reboot