linux下安全备份升级(网页)

2019-07-13 08:07发布

如果在大部分开发完成,并且已经交付完成软件之后,如果产品要可持续的发展,并且与客户有长久合作关系,不可避免的需要进行技术支持,同样的,只要是人写出来的代码,就一定会存在bug,问题严重的还会影响产品的产量。所以,升级的必须的,现在我所知道的升级方式有三种: 一。直接把产生的二进制bin文件通过烧录器烧写到flash里面,在嵌入式linux中一般有三种类型的bin文件,分别是bootloader,uImage,rootfs。 二。在uboot阶段,通过相应的flash读写操作(一般是裸驱动),将sd卡/u盘中指定的文件名,烧录到指定的flash地址去。 三。在系统正常起来之后,通过网页将相应的镜像烧写到flash中去(涉及到mtd子系统的框架)。 而最方便的便是第三种方案,但是在网页升级过程中,突然断电,那镜像可能只有一部分被烧写到flash中去,拼凑起来就成了一个错误的镜像,那么无论是内核还是根文件系统都不能再次正常启动系统,这样,嵌入式产品也就成为了一块砖,只有一些冷冰冰的电容电阻的组合,没有任何功能。 所谓安全备份升级,就是需要flash专门一块区域作为镜像的备份,那么即使在升级过程中断电了,备份镜像还是能够正常起来的,至少系统能够正常工作。 在讨论安全升级之前最需要做的一件事情就是flash空间的分配,因为嵌入式产品,所拥有的资源本来就稀缺,所以需要最大化的利用好当前的资源。 因为flash是以扇区为单元进行读写操作的,而且每次在写之前需要对flash进行擦除,所以flash是有寿命的,超过了一定的写的次数,flash就会出现坏块了。考虑到现在的rootfs比较大,原本使用的是8M的flash,现在使用16M大小的flash。根据flash的芯片手册,扇区大小为64K(0x10000)。  因为需要用到备份分区的,所以还需要对当前正常分区的状态是正在被写入还是已经写入完成,这样的一个标志位,这一类的标志位明显是不能够和镜像放在同一个分区的,因为一旦断电了,标志位的分区也就错误了,那么我们的 判断也就会有错误了。同样的还需要再考虑到这样一种情况,就是假如我们把镜像写入备份分区完成之后,要写标志位的时候断电了,那要怎么办,所以同理的我们对标志位分区也需要做一个备份分区,那么问题又来了,那要怎么样是判断哪一个标志位的分区才是正确的当前需要的标志呢,我的解决办法是在该分区设置一个独一无二的属于自己的魔数,并且对自己所需要用到的数据进行校验和,如果这两个条件同时成立了,那么就表示这个标志位的分区就是正确的,不是在写入时断电的那个错误分区,那么两个分区都是的那两个充分条件都成立,又如何去判断哪一个是最新的正确的标志呢,所以我还设置了一个计数值,每次写入之后,就会把该计数值增加一,那么之后再判断的话就是谁大谁就是正确的分区,实际上这些的实现方式很简单,也就是构造一个结构而已,而一个结构占用不了多少字节,所以使用最小的一个扇区,作为标志位分区的大小。 struct part_head_info { int magic; int len; int checksum; };在整个功能的实现过程中,我遇到了以下几个问题: 1.首先在linux内核中,注册spiflash设备,如果编写的驱动需要正常使用 spi_register_board_info(xxx_spi_board_info,ARRAY_SIZE(xxx_spi_board_info));
xxx_spi_board_info的moalias的名字需要和注册驱动时/driver/mtd/devices/xxx_flash.c的 spi_register_driver(&m25p80_driver);中的名字相同,不然probe函数就不匹配,无法分配正确的分区。 2. 一定要注意kernel和rootfs所在哪个分区,不同的分区意味着flash地址的不同,bootloader会到指定的flash地址将内核拷贝到内存中去。 3. roofs分区如果小于rootfs的大小,那么如果其他一切都正常操作,那么最后系统能够起来,但是在挂载根文件系统的时候,会出现kernel panic