19-Openwrt双固件升级

在上一章节《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=1

v "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 set

CONFIG_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);
#endif
    default:
        printf("Invalid image format\n");
        return 1;
    }

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

 image-fdt.c
 image-fit.c
 image-sig.c
 image.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      0x73717368

struct 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之后的某个脚本处,将标志位清零即可。后面再次启动的时候就不会重复烧录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容