嵌入式Linux的安全模式设计
在safe mode的设计中,对后续多个版本升级的支持也是一个需要仔细考虑的地方。因为后续版本会存在很多的不确定性,如果发出的版本不能很好地兼容后续版本,那么将会给产品带来巨大的风险。
后续版本的可能情况,主要分两种:结构分区变化不大,结构分区变化巨大。
对后续版本中变化不大的情况,也即类似master + safe mode的情况,当再次更新时,只需要操作/dev/mtdblock/3对应master,/dev/mtdblock/4对应safe mode,即可。
但如果后续版本变化非常大,那么就需要特别注意了。
可以考虑这样一个情况:如果后续的版本,需求发生了大的变化,比如需要将原来master所在的分区再分成多个分区:
后续版本需求变化
![后续版本需求变化](http://uphotos.eepw.com.cn/fetch/20130729/150779_4_0.jpg)
那么从老版本升级到新版本时,这些分区的内容如何保证烧写后能正常工作呢?
解决的办法就是在老版本中,将后续的rootfs部分作为一个整体来操作,也就是说烧写时,是将master + part1 + part2+ safe mode作为一个整体来对待。在老版本看来,新版本中的这15872K的内容,不管它其中有多少个不同的分区,还是master + safe mode。在烧写时,还是按/dev/mtdblock/3对应master,/dev/mtdblock/4对应safe mode的方式来烧写,完成将15872K的内容完整烧写进flash即可。
为了做到这一点,在烧写中,我们将全部的15872K的内容分成两段,第一段为15872-4*1024=11776K,需要将其write到/dev/mtdblock/3中,第二段为4M,需要将其write到/dev/mtdblock/4中。这样全部的15872K的内容就完整地烧写完,而再次启动后的kernel会分辨出 master + part1 + part2 + safe mode,它们的总大小依然保持15872K不变。这整个过程中,都不用去理会新版本中到底包括哪些内容,哪些分区,只要保证是将15872K的内容全部完整地烧写进去就可以了。
整体rootfs的设计思想在这里帮了一个大忙,简化了升级更新时所需要考虑的复杂度,使设计变得更加灵活与易于维护。
这样才新发布的firmware里,如果分为多个分区,那么就保证再次升级时,将15872K的内容分成多段,写到类似/dev/mtdblock/3、4、5、6这样的设备文件里就可以了,只要保证这些区域是连续的、并且烧写的内容是全部的那15872K内容即可。
Magic number:
值得注意的是,随着不同的版本的变化,magic number的位置还是应该保持在15872K的最后一个字节的位置。但这就出现一个问题,在不同的版本中,这个magic number的位置会是在不同的partition的最后一个字节。比如某个版本可能是在/dev/mtdblock/4的最后,但再后续的版本它会变成了/dev/mtdblock/7的最后面,这样就会存在很大的不确定性。所以在一个各个版本中,写magic number标记位时,需要一个统一的方法来做到这件事。最容易想到的办法当然就是magic number这个位置相对起始位置0是不变的。而前面提到过的/dev/mtdblock/0就刚好是代表了可以操作的整个flash分区。
有了/dev/mtdblock/0,这样我们就可以open 它,seek到magic number的位置,然后write下0x55或0xAA,这样就保持了写magic number的代码的一致性,不需要根据不同的分区,多次修改操作magic number的有关函数。
Booloader:
Bootloader的修改,也涉及到对magic number的读取,它的读取就相对简单一些,直接使用magic number在RAM中映射的绝对地址即可。
Bootloader检查完magic number后,需要将相对地址为0xBC0000的safe mode的kernel + rootfs读入到RAM,然后设置启动参数,调用内核,进入safe mode提示界面。
Linuxkernel:
与老的、不带safe mode的image相比,新的image里的Linuxkernel从总体的角度来说,并没有大的变化。在新做的master与safe mode的image中,它们各自需要包含一个Linuxkernel,这两个kernel唯一的不同就是启动时所需要的rootfs在RAM中的映射位置不同。它们都有着相同的partition分区设置,编译选项等。
Safe mode必须包含自己的Linux kernel,因为它是运行在master损坏的情况下,master kernel已经不能启动了。
总结
上面的内容是在实际开发中对safe mode的设计与实现的一个描述。从这个描述中,可以看到safe mode在嵌入式Linux产品扮演着重要的角色,对它的设计涉及到很多方面,要考虑系统的尺寸,与现有buidling环境的的兼容性,对后续版本的升级的兼容性等诸多方面。
从某种意义上来说,safe mode的设计关系到产品的成败,一个好的safe mode的设计将会给产品带来巨大的灵活性与可扩展性,大大地方便了客户与产品开发商。
linux操作系统文章专题:linux操作系统详解(linux不再难懂)
评论