在上一章节《Openwrt sysupgrade系统升级》中,我们描述了sysupgrade升级系统的过程,这种升级过程会直接firmware分区进行写入,无法保证系统的安全性,只要在写入过程突然断电就会出现系统写入失败,升级失败无法启动系统的问题。

为了解决该问题一般会使用双固件升级的方式,有一个主分区firmware和一个备份分区firmware_backup,常见的有双固件升级方式有很多种,这边只介绍一种通用方式

1.升级流程

  • 1.根据sysupgrade的过程,将固件进行校验写入,不过写入的时候将升级文件写入到备份分区firmware_backup,不直接写主分区firmware。
  • 2.写完备份分区后,设置备份分区写入完成标志位(一般会开辟一块很小的分区用来写标志位),然后重启系统
  • 3.uboot启动的时候,检测到备份分区标志位被置位,则读取备份分区firmware_backup的固件内容。
  • 4.对firmware_backup的内容进行校验,校验一切正常后,将firmware_backup的内容写入到firmware分区。
  • 5.firmware写入完成后,启动系统,系统启动完成后将备份分区标志位清零,这样下次启动后就不会再次升级系统。

通过双固件的方式就不会出现升级失败系统启动不了的问题。

  • 如果步骤1写入过程被断电也不会出问题,因为主分区正常启动,只是没有升级到最新的分区而已。
  • 如果是步骤4升级过程被断电也不会出问题,再次启动的时候会检测到主分区有问题会被再次写入。

2.修改内容

2.1 sysupgrade写入备份分区

PART_NAME修改位备份分区

PART_NAME=firmware_backup

写入固件完成重启前,设置备份分区标志位

//set backup_flg=1v "Upgrade completed"[ -n "$DELAY" ] && sleep "$DELAY"
v "Rebooting system..."
upgrade_log_end
reboot -f
sleep 2
force_reboot   

2.2 uboot对双系统的支持

双固件最主要的工作都在uboot下面进行,一些mtk提供的新版本uboot一般会有支持部分双固件功能,位于dual_image.c文件中。

uboot添加双固件支持的配置


CONFIG_MTK_DUAL_IMAGE_SUPPORT=y
CONFIG_MTK_DUAL_IMAGE_PARTNAME_MAIN="firmware"
CONFIG_MTK_DUAL_IMAGE_PARTNAME_BACKUP="firmware_backup"
CONFIG_MTK_DUAL_IMAGE_SQUASHFS_DATA_CHECK=y
# CONFIG_MTK_DUAL_IMAGE_RESTORE_KERNEL_ONLY is not setCONFIG_MTDPARTS_DEFAULT="mtdparts=raspi:576k(u-boot),7360k(firmware),7360k(firmware_backup)"

dual_image_check()函数里面就是校验firmware合法性的内容。

firmware为kernel+rootfs,所以校验的时候两块都会进行验证

printf("Verifying main image at 0x%llx...\n", image1_off);
ret = verify_image(flash, image1_off, image1_partsize, &image1_size);
if (ret < 0) {printf("Dual image checking is bypassed\n");return 0;
}if (ret == 0) {ret = verify_rootfs(flash, image1_off + image1_size,image1_partsize - image1_size,&image1_padding_bytes, &rootfs1_size);
}image1_ok = ret == 0;
2.2.1 kernel校验

kernel的校验有两种格式

  • 一种是老版本的kernel,我们会把它称作LEGACY
  • 另一种是支持最新设备树的Flattened uImage Tree,会把它称作FIT

校验函数位于verify_image

 case IMAGE_FORMAT_LEGACY:return verify_legacy_image(flash, offset, maxsize, load_addr,image_size);
#if defined(CONFIG_FIT)case IMAGE_FORMAT_FIT:return verify_fit_image(flash, offset, maxsize, load_addr,image_size);
#endifdefault:printf("Invalid image format\n");return 1;}

里面的具体校验内容,查看代码细究,里面对于几种类型的image都有对于的校验函数。

 image-fdt.cimage-fit.cimage-sig.cimage.c
2.2.2 rootfs校验

现在一般使用的都是squashfs文件系统,校验函数为verify_squashfs

static int verify_rootfs(void *flash, uint64_t offset, uint64_t maxsize,size_t *header_prefix_bytes, size_t *rootfs_size)
{uint64_t end = offset + maxsize, leading, extra_bytes, tmp;int ret;ret = verify_squashfs(flash, offset, end, rootfs_size);if (!ret) {if (header_prefix_bytes)*header_prefix_bytes = 0;return 0;}tmp = offset;leading = do_div(tmp, mtk_board_get_flash_erase_size(flash));if (!leading)return 1;extra_bytes = mtk_board_get_flash_erase_size(flash) - leading;offset += extra_bytes;ret = verify_squashfs(flash, offset, end, rootfs_size);if (!ret) {if (header_prefix_bytes)*header_prefix_bytes = extra_bytes;return 0;}printf("No SquashFS found\n");return 1;
}

squashfs文件系统头部有专门的结构信息,如下

#define SQUASHFS_MAGIC       0x73717368struct squashfs_super_block {__le32 s_magic;__le32 pad0[9];__le64 bytes_used;
};

校验内容

if (le32_to_cpu(sb.s_magic) != SQUASHFS_MAGIC)return 1;size = le64_to_cpu(sb.bytes_used);
if (offset + size >= end) {printf("RootFS is truncated\n");return 1;
}
2.2.3 根据校验结果进行操作
  • 如果两个分区的固件都有问题,则报错
  • 如果主分区和备份分区都没有问题,判断备份分区是否有置位,置位则将备份分区拷贝到主分区;
  • 如果主分区正常,备份分区异常,则将主分区拷贝到备份分区
  • 如果主分区异常,备份分区正常,则将备份分区拷贝到主分区
2.2.4 注意事项

spi flash的块大小为64K,有时候为了节省空间把设置标志位的分区设置成4k,它不是64k的倍数,这样mtd 读写的时候也会报错

Detected w25q128bv with page size 256 Bytes, erase size 64 KiB, total 16 MiB

另外mount的时候,一般要大于64k的5倍,不然也会出现一直挂载不上

2.3 系统标志位清零

系统启动成功后,在init之后的某个脚本处,将标志位清零即可。后面再次启动的时候就不会重复烧录

19-Openwrt双固件升级相关推荐

  1. 【双网线网速叠加】新三 (Newifi D2) OpenWRT 双WAN 双拨号 (多线多拨) 网速叠加 (负载均衡)

    [双网线网速叠加]新三 (Newifi D2) OpenWRT 双WAN 双拨号 (多线多拨) 网速叠加 (负载均衡) 固件  链接:https://share.weiyun.com/ic7hOHZZ ...

  2. RouterOS(ROS)+OpenWRT双软路由配置方法及DNS缓存|UPnP等常用功能拓展

    在本次的方案中,我通过PVE虚拟化安装了RouterOS(ROS)与OpenWRT双软路由,其中ROS将作为主路由负责拨号上网等路由器基本功能以及DNS缓存.UPnP等常见ROS拓展功能.OpenWR ...

  3. Win10 + Ubuntu 19.10 双系统自动连接相同蓝牙设备

    原文地址:Win10 + Ubuntu 19.10 双系统自动连接相同蓝牙设备 0x00 环境 OS 1: Windows 10 专业版 1909 OS 2: Ubuntu 19.10 蓝牙设备: 小 ...

  4. Pandorabox(Openwrt) 双宽带(WAN) 叠加网络实战

    准备 一台已经刷好Pandorabox(Openwrt)的路由器.两条宽带 实战环境 固件:PandoraBox R8.1.12 By Lean 硬件:K2P A1版 过程 配置VLAN 为了将一个L ...

  5. openwrt双wan环境搭建以及适配UPnP

    最基本双wan环境搭建 1.修改网络配置文件network 2.修改防火墙配置文件firwall 3.添加策略路由 UPnP适配 修改UPnP配置文件以适配双wan环境

  6. Linux fedora 19 x86_64 双显卡 关闭独显

    1. 操作系统:fedora19 x86_64 双显卡:HD4000 &  GT640M 测试结果:使用命令关闭独显成功!增加启动项没有测试,传说中会出问题,没敢尝试! 2.使用命令: (0) ...

  7. LeetCode 第 19 场双周赛(231 / 1120,前20.6%)

    文章目录 1. 比赛结果 2. 题目 LeetCode 5311. 将数字变成 0 的操作次数 easy LeetCode 5312. 大小为 K 且平均值大于等于阈值的子数组数目 medium Le ...

  8. Linux Mint 19 / Win10 双系统安装全记录

    制作引导盘 Linux Mint官网下载系统镜像文件,Cinnamon.Mate.Xfce三种桌面环境可选. 使用软碟通UltraISO或者Win32DiskImager将镜像写入U盘中,我使用前者时 ...

  9. OpenWRT 学习笔记 -- 用户自定义添加app的开机自启动

    参考自:OpenWRT编译 – 用户自定义添加app的开机自启动 OpenWRT 学习笔记-19 OpenWRT开机自启动服务 文章目录 一.概述 二.自启动实现方式一 三.自启动实现方式二 四.自启 ...

最新文章

  1. scala while循环中断
  2. OSChina 周日乱弹 —— 表白的终极境界!
  3. 直接拿来用!最火的Android开源项目(一)
  4. win2008 mysql_mysql5.7.17在win2008R2的64位系统安装与配置实例
  5. Linux使用技巧9--用dpkg管理你的软件
  6. JAVAWEB项目如何实现验证码
  7. 支持pygame的python有哪些版本_完整构建文件支持PYGAME
  8. python正则表达式之match,search,findall区别
  9. 容器的六大误区和八大正确场景(颠覆你的认知)
  10. 德银病危:心比天高,却落下黄粱一梦
  11. 如何将eclipse的英文设置成中文?
  12. H3C交换机常用配置命令大全
  13. css标题样式_CSS的标题集样式
  14. linux文件夹压缩与分卷压缩
  15. 闲聊历史上的配角之赵高
  16. 4k纸是几厘米乘几厘米_4K纸是多少尺寸
  17. CF1427E Xum
  18. 硬件设计23之三极管开关原理与场效应管开关原理
  19. 【源码】广义逻辑分布(GLO)库
  20. java数字格式化为货币字符串_Java把数字格式化为货币字符串实例代码

热门文章

  1. GitHub 上受欢迎的 Android UI Library 整理二
  2. Java 不可变类的整洁之道
  3. c# 将数据库中值一次赋给MODEL
  4. Linux下两个工具convmv和iconv
  5. 阿里云主机如何安装护卫神镜像
  6. 读-《c++设计新思维-泛型编程与设计模式之应用》经典记录(英文书名:《modern c++ design》)
  7. php泥浆配比,中卫护壁剂用法用量信誉高性能稳定
  8. JAVA缓存规范 —— 虽迟但到的JCache API与天生不俗的Spring Cache
  9. 产业互联网,让互联网由「上层建筑」变成「基础设施」
  10. Spring Boot+高德地图热力图静态数据展示