目录
QCA Fail Safe Boot
MTK Dual Image Boot
嵌入式Linux系统从内部功能划分角度主要包含三个核心组成部分:BootLoader(多采用开源源码的U-Boot)、Kernel(Linux内核)、RootFS(根文件系统)。嵌入式Linux系统启动过程均是先从BootLoader引导,由BootLoader初始化CPU、DDR、Cache等硬件设备,再对Linux内核进行解压并拷贝到内存,随后转到内核地址执行;Linux内核在完成系统初始化之后将挂载RootFS根文件系统,并加载必要内核模块,启动应用程序。
正如我们所熟知的,嵌入式Linux设备在出厂前均会对固件进行首次烧录保证设备能正常启动且功能正常,而后续使用过程中大多都是通过在线升级的方式对设备进行固件更新以修正问题或迭代功能。然而固件在线升级时,可能会出现断电导致固件未完全更新从而引发设备无法正常启动的异常情况。因此,嵌入式Linux设备升级固件时应具备容错校验功能,如果升级失败,应能自动恢复并正常运行。
对于不同的硬件平台,升级失败之后自动恢复的方案也存在着些许差异,下面就对QCA、MTK平台的双Image备份方案进行分析总结与对比,期望帮助大家理解镜像备份原理,或者拓展其他可行方案。
QCA Fail Safe Boot
QCA Fail-safe boot机制正是为了避免设备固件升级异常断电而导致无法正常启动的问题。因Nor Flash售价高,而且相同成本容量比Nand Flash小,出于成本考虑,大多涉及双Image备份功能的嵌入式Linux系统均采用Nand Flash作为存储介质,QCA Fail-safe机制也是在Nand Flash存储介质下提供支持的。下面将对Fail-safe boot机制进行详细分析:
1、Fail-safe boot对嵌入式系统所有需要更新的Flash分区创建备选分区;
主要分区作用如下所示:
SBL1 :二级引导程序(secondary boot loader),根据系统状况决定设备是从主分区还是备选分区启动;
MIBIB :系统分区表信息;
BOOTCONFIG 、 BOOTCONFIG1 :故障保护分区信息(Failsafe partition information),存储主引导标志、分区名、开始/结束标志、备份分区数量等信息;
APPSBLENV :分区大小512KB,存储u-boot环境变量;
APPSBL 、 APPSBL_1 :分区大小1536KB,U-boot引导程序;
rootfs 、 rootfs_1 :Linux Kernel与RootFS分区;
2、Fail-safe boot使用BOOTCONFIG(1)分区记录各可选分区引导信息;
故障保护分区信息(BOOTCONFIG)主要由如下信息构成:
start magic、end magic:开始/结束标志;
age:使用年限;
numaltpart:备选分区数量;
per_part_info[numaltpart]:备选分区信息,包含name分区名和Primary_boot主引导标志,其中Primary_boot可取值0/1,当1时,表示使用备选分区启动;当0时,表示使用主分区启动;
3、Fail-safe boot固件升级写入备选分区并在升级成功之后更新BOOTCONFIG(1)已升级分区的引导信息;
固件升级之前,BOOTCONFIG(1)分区信息如上所示,APPSBL、rootfs等分区的Primary_boot值均为0,即表示系统启动时将从APPSBL、rootfs主分区引导;
rootfs升级成功之后,对BOOTCONFIG(1)存储的age(叠加)、rootfs分区Primary_boot(取反,即0变为1、1变为0)等内容进行更新。若升级失败(异常断电或手动中断),BOOTCONFIG(1)分区存储信息便不会更新,信息保持不变。
4、Fail-safe boot二级引导程序启动时会读取BOOTCONFIG与BOOTCONFIG1分区信息,并根据各分区Primary_boot值选择主分区还是备选分区启动;
系统启动时,会依次读取BOOTCONFIG和BOOTCONFIG1分区内容,并对存储信息进行校对,这块逻辑不作详细阐述,大家可参考下图进行理解。其实系统启动的关键在于根据Primary_boot值决定是否“swap offset of the partitions”,即选择主分区还是分选分区启动。
“swap offset of the partitions”主要是为了交换主分区名指向的分区地址,下面以rootfs升级前后启动对比进行阐述,当升级之前时,rootfs Primary_boot值为0,则系统从主分区启动,即rootfs指向根文件系统第一个分区地址处,从此地址启动;而升级成功之后,rootfs Primary_boot值变为1,则系统从备选分区启动,此时rootfs指向根文件系统第二个分区地址处,并从此地址启动。
rootfs primaryboot值为0:
0x000000000000-0x000000180000 : "0:SBL1" 0x000000180000-0x000000280000 : "0:MIBIB" 0x000000280000-0x000000300000 : "0:BOOTCONFIG" 0x000000300000-0x000000380000 : "0:BOOTCONFIG1" 0x000000d80000-0x000000e00000 : "0:APPSBLENV" 0x000000e00000-0x000000f80000 : "0:APPSBL" 0x000000f80000-0x000001100000 : "0:APPSBL_1" 0x000001100000-0x000001180000 : "0:ART" 0x000001180000-0x000003e20000 : "rootfs" mtd: device 17 (rootfs) set to be root filesystem mtdsplit: no squashfs found in "rootfs" 0x000003e20000-0x000006ac0000 : "rootfs_1" 0x000006ac0000-0x000006b40000 : "0:ETHPHYFW"
rootfs primaryboot值为1:
0x000000000000-0x000000180000 : "0:SBL1" 0x000000180000-0x000000280000 : "0:MIBIB" 0x000000280000-0x000000300000 : "0:BOOTCONFIG" 0x000000300000-0x000000380000 : "0:BOOTCONFIG1" 0x000000d80000-0x000000e00000 : "0:APPSBLENV" 0x000000e00000-0x000000f80000 : "0:APPSBL" 0x000000f80000-0x000001100000 : "0:APPSBL_1" 0x000001100000-0x000001180000 : "0:ART" 0x000001180000-0x000003e20000 : "rootfs_1" 0x000003e20000-0x000006ac0000 : "rootfs" mtd: device 18 (rootfs) set to be root filesystem mtdsplit: no squashfs found in "rootfs" 0x000006ac0000-0x000006b40000 : "0:ETHPHYFW"
如上,对QCA Fail-safe boot从备选分区划分、引导信息存储、升级失败或成功后引导信息的处理,以及系统如何根据引导信息选择主/备选分区启动的实现进行了详细分析。QCA Fail-safe boot可对任何场景下升级断电造成的异常进行自动恢复。
MTK Dual Image Boot
相对QCA Fail-safe boot方案而言,MTK Dual-image boot方案就比较简单,易理解。MTK Dual-image boot不存在二级引导程序,也不存在引导信息存储备份,其只是简单的对rootfs划分备选分区,启动时BootLoader会根据mkimage生成的CRC校验值对Image进行校验,当校验失败时会将备选分区的Image拷贝到主分区中启动。
1、MTK Dual-image boot只对rootfs镜像划分备选分区rootfs_1;
2、MTK Dual-image boot固件升级时统一写入rootfs镜像主分区;
3、MTK Dual-image boot系统启动时,会根据rootfs镜像的CRC校验值判断主分区是否损坏,若损坏则将rootfs_1镜像备选分区拷贝到rootfs主分区,后续从rootfs主分区启动;当主分区和备选分区均校验失败时,系统启动异常。
如上,对MTK Dual-image boot进行了简要分析,从整个方案可知,MTK Dual-image boot并不能对任何场景下升级断电造成的异常进行自动恢复。因为MTK Dual-image boot方案只对rootfs镜像(Linux内核+根文件系统)进行备份恢复,未对BootLoader进行备份,那当对BootLoader进行更新且碰巧异常断电导致该分区未正常写完时,BootLoader引导程序便遭到损坏,系统便不能正常引导。此时,Dual-image boot也就失去了效果。
当然,功能开发与更新角度考量,BootLoader相较于rootfs/kernel更新频率从是比较低的。因此,虽然MTK Dual-image boot不能保证任何场景下的自动恢复,但其还算简单但实用的双镜像备份恢复方案。