内容发布更新时间 : 2024/12/26 20:21:18星期一 下面是文章的全部内容请认真阅读。
文档说明: 本文档简述了openwrt sdk的升级功能流程,从页面传入升级文件到升级文件检测,再到调用升级脚本进行升级,升级完成后,进行系统重启。最后简述了如何添加升级文件标识,标识包括自己定义的字段,以及升级软件的md5值。达到防止用户用其他openwrt sdk编译出来的固件刷新我们的系统,以及防止升级软件被破坏。
文档需要用到的文件及在sdk中的路径(某些文件路径可能随项目的不同而改动): ./package/ralink/ui/luci-mtk/src/modules/admin-full/luasrc/controller/admin/system.lua ./target/linux/ramips/image/ Makefile
./package/base-files/files/lib/upgrade/common.sh ./package/base-files/files/lib/functions.sh ./package/base-files/files/sbin/sysupgrade ./target/linux/ramips/base-files/lib/ramips.sh
./target/linux/ramips/base-files/lib/upgrade/platform.sh
文档正文:
1.从页面接受传过来的升级文件
作为整个流程的开始,功能实现在文件system.lua中。
这是一个lua文件,很容易在function index函数中找到系统升级功能的入口函数:action_flashops。在这个函数中首先通过fp = io.open(image_tmp, \打开升级临时文件:/tmp/firmware.img,打开后通过fp:write(chunk)写入页面传进来的升级文件。到这里,接受升级文件完成 。
2.检测升级文件的合法性
实现同样在文件system.lua中。
在函数image_supported()中进行检测,这个函数通过image magic number来检测升级文件是否合法。函数image_supported()会调用platform.sh脚本中的platform_check_image函数, platform_check_image函数调用ramips.sh脚本中的ramips_board_name函数,获取board name,ramips_board_name函数从文件 /tmp/sysinfo/board_name 中获取board name,若没有则为unknown,并返回给调用者,我用的板是ralink-soc。platform_check_image函数继续调用common.sh脚本中的get_magic_long函数,用以获取升级文件magic,就是升级文件前4位。get_magic_long函数调用common.sh脚本中的get_image函数用以获取文件/tmp/firmware.img内容,其实就是cat /tmp/firmware.img. 获取到的内容,通过dd bs=4 count=1,来获取前4位,最后通过hexdump -v -n 4 -e '1/1 \处理以十六进制编码返回调用者。获取到的升级文件magic,在platform_check_image函数中与27051956做对比,这个值是在固件编译的时候已经定好了的。如果相等,就是合法的升级文件,继续升级动作;不相等则为非法升级文件,做一些后续处理并终止升级动作。到这里检测升级文件合法性完成。
3.检测升级文件不合法后的处理 实现同样在文件system.lua中。 检测到不合法后,通过nixio.fs.unlink(image_tmp)来删除临时文件/tmp/firmware.img,并通过image_invalid = true,设置检测失败,用以通知页面显示提示信息。终止升级。处理完成。
4.检测升级文件合法后的处理 实现同样在文件system.lua中。
检测到升级文件合法后,会获取一些升级文件相关的信息,用以在页面显示:调用image_checksum(),获取checksum;调用storage_size(),获取可用空间大小;调用nixio.fs.stat(image_tmp).size,获取升级文件大小;以及页面传过来的是否保存配置的值;其中,image_checksum()函数用的是md5sum命令,storage_size()函数是在系统文件/proc/mtd中找到firmware分区大小。
接下来如果用户选择进行升级文件,则会现在页面上打印一些提示信息,用于提示用户:正在升级,不要断开电源等等。
文件system.lua最后的处理就是调用升级脚本:fork_exec(\dropbear uhttpd; sleep 1; /sbin/sysupgrade %s %q\。
这条语句,先清除dropbear 和uhttpd进程,再等待1秒,最后调用升级脚本sysupgrade,传过去的参数就是keep:是否要保存配置;image_tmp:升级文件/tmp/firmware.img。 OK,到这里system.lua文件中关于升级前的准备工作都完成了,视线请转到升级脚本sysupgrade上。
5.运行升级脚本
实现在文件sysupgrade中。
脚本开始,像所有的主体处理程序一样,会对传进来的参数进行处理。下面对这些参数的介绍:
-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 打印帮助信息
这些参数的使用在脚本中都有介绍,不再多讲。
接下来:[ -z \,意思是:如果没有升级文件参数,且没有命令行参数-b(create-backup),-r(restore-backup),或者带有-h(help)参数,则打印帮助信息。这个条件为真的话,会在终端打印帮助信息,退出脚本。
接下来:[ -n \,意思是:不要指定-b或-r(创建配置、恢复配置)的同时,指定升级文件。为真的话,打印提示信息,退出脚本。
接下来:[ \,意思是:选择备份配置但传进来的文件为“-”时,不打印备份文件时的过程。
下面展示一下-v选项的作用: 带-v时的升级过程:
root@OpenWrt:/# sysupgrade -i -v /tmp/firmware.img Keep config files over reflash (Y/n): y Edit config file list (y/N): n Saving config files... etc/config/dhcp etc/config/dropbear etc/config/firewall etc/config/fstab etc/config/luci etc/config/network etc/config/system etc/config/ucitrack etc/config/uhttpd etc/config/wireless
etc/dropbear/dropbear_dss_host_key etc/dropbear/dropbear_rsa_host_key etc/group etc/hosts etc/inittab etc/passwd etc/profile etc/rc.local etc/shells etc/sysctl.conf
Sending TERM to remaining processes ... dnsmasq ubusd btnd logd netifd uhttpd ntpd Sending KILL to remaining processes ... Switching to ramdisk...
Performing system upgrade... Unlocking firmware ...
Writing from
Appending jffs2 data from /tmp/sysupgrade.tgz to firmware... Writing from
不带-v时的升级过程:
root@OpenWrt:/# sysupgrade -i /tmp/firmware.img Keep config files over reflash (Y/n): y Edit config file list (y/N): n Saving config files...