嵌入式Linux的safe mode设计与实现

发布者:cwk2003最新更新时间:2009-04-01 来源: 嵌入式在线关键字:安全模式  嵌入式Linux  Booloader 手机看文章 扫描二维码
随时随地手机看文章

  目前的各种嵌入式产品已经丰富多彩,它们正改变着我们的生活方式。随着嵌入式产品功能的增加,如何让用户对已购买的产品的升级能安全地、顺利地完成,避免升级过程中出现的意外掉电所引起的产品故障,这样的问题要求嵌入产品设计开发者在设计时就将产品的 safe mode 安全模式考虑进去。这里我们将以一个嵌入式Linux 网络播放器为例,来说明 safe mode 安全模式的设计与实现。通过本文,我们可以了解到针对一个实际的嵌入式系统,设计中需要注意的技术要点和实现细节。

  为什么需要 safe mode(安全模式)

  当用户购买一个产品后,在后续的服务中,可能还会发生一些费用,让产品开发商增加成本,如免费电话咨询,产品的维修、寄送。所以说将产品的卖出并不意味着最终的赢利。这样的情况下,产品的设计就需要更加合理,更加优化,来满足用户各种可能的需求。特别是在发生异常故障的时候,如果能引导客户自行完成诊断、修复,那么将大大降低后续的服务成本。正因为如此,产品故障时,就很需要safe mode安全模式来帮助用户完成恢复的工作。

  从节约产品的成本、产品所能提供的功能上来看,safe mode 是大有裨益的。

  大家所熟知的 windows 系统,也提供了 safe mode 安全模式,它就可以帮助用户解决系统不稳定,硬件冲突等诸多故障,让用户在自己可以操作的能力范围内先行对系统进行诊断与修复。在很大程度上, windows 的 safe mode 给用户与 Microsoft 都带来了很大的便利。

  嵌入式Linux产品与其他IT产品不同的地方,主要是使用flash来存贮运行时的系统。它没有大的内存,没有大的存储空间,但它却也是一个完整的系统。

  在通常情况下,嵌入式Linux产品的flash上的内容是不会被破坏的,也即它们会有着较好的稳定性,不会因为用户的常规使用而导致flash上的 firmware被破坏。但随着产品的更新升级,用户也需要在自己家中完成对已购买商品的更新换代。而用户大多属于非技术熟悉者,在更新升级中就可能出现种种意想不到的情况。

  比如在用户做firmware升级更新时,平时不会出现问题的firmware可能在这个过程中,就面临着巨大的风险,极有可能致使用户的系统无法启动,不能正常工作。这样的情况是我们不愿意看到的,而实际中却的的确确可能会发生。

  考虑这样一个场景:当用户对产品进行firmware升级时,如果在烧写flash的过程中,意外掉电,那么用户手中的产品就将无法再次启动,因为 rootfs系统已经被破坏了。用户所能做的,也只能将产品送回产商进行维修。这样来回的过程不仅耗费用户的精力,同样也会增加产品开发商的成本。在产品升级换代很快的当前市场情况下,这样的情况可能会经常发生。

  如何避免这样的情况的发生呢?如果我们可以提供一个机制,在进行升级前即往flash中写入一个标记,正常完成后,再写入另一个标记来表示整个过程的正常结束,否则的话,烧写时掉电不会写入第二个标记,只有第一个标记,那么就认为产品故障,这个时候,进入另一个新的提示界面,让用户自己选择从 USB或FTP来重新升级firmware。这样的话,整个过程用户就完全可以在界面的友好提示下自己完成,方便了用户与产品开发商。

  系统架构

  本文以一个实际的产品为例,来说明safe mode的设计。

  系统架构

  本系统为一个嵌入式Linux网络播放器,主要的功能为播放家庭网络中的多媒体文件,在家庭客厅等环境中有着大量的应用,它可以给用户提供更方便快捷的媒体文件的播放方式,并能充分利用家庭音响系统的巨大功能,而非PC环境下有限的外部设备,大大改善了媒体文件的播放体验。

  本系统的架构如下图:

  产品所使用的flash总大小为16M。

  系统包括三大部分,即Bootloader,config, kernel + rootfs:

  另外,/dev/mtdblock/0,在系统中对应整个flash block,即整个16M空间。

  系统启动时,bootloader将kernel和根文件映象从flash上读取到RAM空间中,为内核设置启动参数,调用内核,进入application,进行媒体文件的播放。

  这个通常意义上的嵌入式Linux系统,它是不带safe mode安全模式的。

  这样的系统,在做系统更新升级时,主要是对kernel+rootfs部分进行升级,以此来增加系统的功能。

  升级时,application主要是操作/dev/mtdblock/3设备文件:

  第一步:下载新的firmware到ramfs中,也即ram disk中,比如/tmp目录下,采用的更新方式可以是USB或FTP;

  第二步:read /tmp/firmware文件,并write到设备文件/dev/mtdblock/3上,即对已有的firmware进行了更新。

  在升级的过程中,我们会提供友好的界面给用户,来提示下载进度与烧写flash的进度,让用户可以看到正在发生的状况。

  最后烧写完成后,重新启动系统,即可进入到新的firmware中。

  在通常的更新中,用户的产品配置config一般不去修改,保持用户已经做的配置选项,不能破坏。Config内容对应为/dev/mtdblock/2设备文件。

  从USB/FTP 上更新时,所使用的firmware文件需要是一个更加完整的image文件,可以包括bootloader, default config, kernel+rootfs,并让application可以做到视image中的标记来决定是否需要更新bootloader、config等内容,这样会更加灵活。

  在更新firmware时,如果掉电,那么kernel + rootfs部分将会出现不完整的情况,也就是说只写入了部分内容,而中途中断了,这样的话,一个不完整的系统将无法正常工作。在这样的情况下就需要safe mode安全模式了。

  safe mode架构设计

  Safe mode的设计中,对原来的系统增加了两个部分的内容:

  kernel + rootfs,即简单的UI界面与功能;

  magic number,即烧写flash的标记。

  safe mode实际上也是一个kernel + rootfs部分,只是它所具有的功能只包括一些简单的界面,主要是提供网络设置,从USB/FTP下载firmware,完成对flash的烧写。

  为了区分,这里,将主功能部分的kernel + rootfs称为master。

  我们将safe mode存放在master的后部,预留的flash大小为4M。

  Magic number只占用一个字节的大小,是在这4M的最后的部分的一个字节,也即原始系统的15872K的最后一个字节位置处。

  在开始烧写flash前,将magic number设置为0x55,表示烧写的开始。烧写正常结束后,将magic number设置为0xAA,表示烧写正常结束。

  如果新产品中具备了safe mode模式,那么在以后再次更新升级时,开始烧写flash时,magic number的位置将会有0x55标记,如果烧写中途掉电,在重新启动后,将由Bootloader来检查magic number的值,如果内容为0x55,那么bootloader将从safemode部分读出kernel和根文件映象,再为内核设置启动参数,调用内核,进入safe mode application。

  如果bootloader读到magic number为0xAA,那么说明master firmware是正常的,就将直接进入master。

  所以涉及到safe mode的地方也包括了对bootloader的修改,需要在系统上电阶段也检查safe mode的magic number,这个过程是必不可少的,只有在启动阶段就检查magic number,才能跳过损坏的master系统,进入安全模式,达到恢复系统的目的。

  safe mode架构实现

  在safe mode的实现中,需要保持原有master部分的稳定,所以对master系统的building system不做大的改动,也就是保持safe mode的building system与master的building system共存。原则上来说,要避免对master系统带来大的冲突。

  Master building system主要涉及到的编译过程为:

  make

  make rootfs

  这个时候将得到master.bin

  safe mode building system和其类似,只是make rootfs部分有所区分:

  make

  make smrootfs

  这个时候将得到safemode.bin

  最后再将master与safe

  mode部分做一个合并,得到一个整的rootfs

  make dualrootfs

  make dist

  make

  dualrootfs将调用一个外部的程序make_dual.c,所做的事情是要得到一个15872K的rootfs。这个rootfs包含的内容为master.bin + safemode.bin。

[page]

  本系统中一般master.bin的大小约为10000K,再加上safemode.bin的4M,总大小并未达到15872K,那么中间多出的部分,我们需要将其补0填充好。需要补充的0的大小约为15872-4*1024-10000=1776K

  make_dual.c就是完成上面的合并,补0的工作。它read master.bin,write rootfs,然后write 1776K个零到rootfs中,接下来read safemode.bin,再继续write 到rootfs中。

  这样就得到了完整的、带master与safe mode的rootfs。

  safe mode实现中遇到的问题及其解决

  体积限制:

  在safe mode的开发中,首先遇到的一个问题就是如何从已有的系统中简化出一个safe mode的application环境。

  对master原有系统的裁剪来得到safe mode,将会比较容易,如果从头另写一套,将会花费较大精力,稳定性也无法得到确实的保障,所以最终采用的是精简master的系统来得到safe mode的大框架。

  在实现safe mode时,要做的工作的原则是做到safe mode的rootfs尽量小,低于4M,并且保持与master外围特性的一致,这样可以避免重复开发,同时代码的共用可以减少维护的不便,提高整个系统的灵活度、稳定度。

  就一个能运行的嵌入系统来说,最基本的内容应该包括Linux kernel,busybox工具包、图形驱动等内容。

  在本系统中,为了支持FTP下载,需要有network的支持,也即需要包括wired/wireless的支持。

  为了支持USB下载方式,就需要USB monitor管理进程的支持,这个主要是保持了与master系统的一致,而没有另外去写一个体积更小的USB管理模块。

  wireless模块:

  本来在设计时,可以考虑不加入wireless的支持,但为了更加方便用户,保持用户的使用习惯,我们还是加入了对wireless的支持,这样也保持了与master系统的一致,但支持的代价是,safe mode的体积增大了大约250K。

  在wireless module中,做了一个优化,master系统中wireless module在insmod时,是使用的rootfs中的/lib/module/wireless/XXX.o,这些未压缩的.o文件在rootfs系统中将占用较大空间,这样一来,对应的safe mode的内容将会超出4M的大小。为了解决这个问题,我们将这些wireless module压缩成wireless.tar.gz文件,放置到safemode.bin中,在Linux启动时,在/etc/rc脚本中将 wireless.tar.gz解压缩到ramfs中即/tmp/lib/module/wireless下,然后再从这里insmod安装 wireless模块。这样所做的努力,wireless module从原来的790K,缩减到了250K,而功能保持了一致。

  字体:

  master 系统的字体使用的是freetype2,字体文件arialbd.ttf大约为280K,这也将占用大量的空间。由于safe mode在显示界面方面没有过高的要求,能让用户看到基本的图形界面就已经达到目的了,所以在safe mode中需要将freetype去掉。但由于master模式与safe mode都使用相同的图形引擎,这样就导致了,如果在safe mode中去掉freetype,那么就需要再次重新build基础的图形库,这样在master与safe mode的单独编译过程中就需要反复去make clean这些库。这会给每次的编译带来很大的不便,每次make clean等操作会占用大量的时间,耗时耗力。

  基于这个考虑,我们决定master与safe mode在编译过程中都使用相同的图形库,即都编译生成freetype库。但在运行时,safe mode不去使用freetype。也就是说,freetype库会被编译进来,但字体文件不需要加到safe mode中,这样做的代价就是编译出来的safe mode的application比完全无freetype库的情况要大100K左右,但却保持了与master相同的库结构,而freetype字体就不再需要了,也就节约出了大约280K的空间。

  最终优化的结果,safe mode的4M,包括Linux kernel, buzybox, safe mode application等压缩后的大小:

  优化结果 

  后续版本的兼容:

  在safe mode的设计中,对后续多个版本升级的支持也是一个需要仔细考虑的地方。因为后续版本会存在很多的不确定性,如果发出的版本不能很好地兼容后续版本,那么将会给产品带来巨大的风险。

  后续版本的可能情况,主要分两种:结构分区变化不大,结构分区变化巨大。

  对后续版本中变化不大的情况,也即类似master + safe mode的情况,当再次更新时,只需要操作/dev/mtdblock/3对应master,/dev/mtdblock/4对应safe mode,即可。

  但如果后续版本变化非常大,那么就需要特别注意了。

  可以考虑这样一个情况:如果后续的版本,需求发生了大的变化,比如需要将原来master所在的分区再分成多个分区:

  后续版本需求变化

  那么从老版本升级到新版本时,这些分区的内容如何保证烧写后能正常工作呢?

  解决的办法就是在老版本中,将后续的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提示界面。

  Linux kernel:

  与老的、不带safe mode的image相比,新的image里的Linux kernel从总体的角度来说,并没有大的变化。在新做的master与safe mode的image中,它们各自需要包含一个Linux kernel,这两个kernel唯一的不同就是启动时所需要的rootfs在RAM中的映射位置不同。它们都有着相同的partition分区设置,编译选项等。

  Safe mode必须包含自己的Linux kernel,因为它是运行在master损坏的情况下,master kernel已经不能启动了。

  总结

  上面的内容是在实际开发中对safe mode的设计与实现的一个描述。从这个描述中,可以看到safe mode在嵌入式Linux产品扮演着重要的角色,对它的设计涉及到很多方面,要考虑系统的尺寸,与现有buidling环境的的兼容性,对后续版本的升级的兼容性等诸多方面。

  从某种意义上来说,safe mode的设计关系到产品的成败,一个好的safe mode的设计将会给产品带来巨大的灵活性与可扩展性,大大地方便了客户与产品开发商。

关键字:安全模式  嵌入式Linux  Booloader 引用地址:嵌入式Linux的safe mode设计与实现

上一篇:μCOSII在Cortex-M3核ARM处理器上的移植
下一篇:微软宣布将提供MSDN Embedded订阅服务

推荐阅读最新更新时间:2024-05-02 20:47

基于嵌入式Linux系统的导航软件设计思路
1 引言 随着汽车等各种车辆交通工具的普及,车辆导航设备的需求也变得日益旺盛。作为车载设备。不仅要有可靠的性能,而且需要具有便携、低功耗和低价格等特点。而采用基于ARM微处理器的嵌入式系统与GPS模块相配合的GPS导航终端机的设计方案,可以很好的满足这一系统需求。为此,本文介绍了一种利用 ARM9开发板和GPS模块实现GPS导航功能的终端机的软硬件结构和设计方法。 2 GPS导航系统结构 本文所介绍的GPS全球定位导航系统按功能可分为嵌入式主控模块、GPS模块、显示模块、扩展模块及供电模块等五大部分。 嵌入式主控模块基于S3C2440处理器,主要负责对GPS导航模块数据的响应、处理和控制。在硬件上,主控模块就是一个嵌入式
[嵌入式]
嵌入式Linux系统中使用的摄像头
1).目前越来越多的嵌入式系统采用摄像头应用,其中主要有下面几种方式 远程监控:如闭路电视系统,操作人员通过摄像头远程监控某个特定区域,小到一个小区,达到市政公共场所,都可能有这样的应用。 监控视频录制:另外一些监控系统不一定有操作人员一直监控,则会通过录制监控视频的方式在需要的时候调出相关视频进行查阅。 嵌入式视觉系统:嵌入式视觉系统会对视频图片进行处理并提取更多复杂信息,如雷达和城市智能交通应用。 视频传感器:如临床诊断设备会对采集的视频图像进行分析来诊断,智能购物设备通过采集视频图像分析使用者特征来定向推广销售等等。 2).环境配置 ./ ARM嵌入式模块系统:Toradex VF61以及 Colib
[单片机]
在<font color='red'>嵌入式Linux</font>系统中使用的摄像头
嵌入式Linux系统的设计与应用
摘要:随着嵌入式Linux系统的迅速发展,嵌入式Linux已发展成为嵌入式操作系统的一个重要分支。本文介绍了嵌入式Linux的设计和几种流行的嵌入式Linux系统。 关键词:嵌入式Linux 一、引言 嵌入式系统(Embedded Systems)是根据应用的要求,将操作系统和功能软件集成于计算机硬件系统之中,从而实现软件与硬件一体化的计算机系统。嵌入式系统出现于60年代晚期,它最初被用于控制机电电话交换机,如今已被广泛的应用于工业制造、过程控制、通讯、仪器、仪表、汽车、船舶、航空、航天、军事装备、消费类产品等众多领域。嵌入式系统在数量上远远超过了各种通用计算机系统:计算机系统核心CPU,每年在全球范围内的产量大概在二十亿
[嵌入式]
嵌入式Linux下USB驱动程序的设计
  一、引言   USB(Universal Serial Bus)即通用串行总线,是一种全新的双向同步传输的支持热插拔的数据传输总线,其目的是为了提供一种兼容不同速度的、可扩充的并且使用方便的外围设备接口,同时也是为了解决计算机接口的太多的弊端而设计的。一个USB系统主要有三部分组成:USB互连、USB主机、USB设备三部分组成的,其结构如图1所示。在编写USB设备驱动程序设计时,可以分为三部分编写:主机端设备驱动程序、主机控制器驱动程序设计和设备端驱动程序三部分,在本文中重点介绍主机端驱动程序的设计。   二、USB设备驱动程序的设计   USB设备驱动程序的设计包括主机端设备驱动程序设计、主机控制器驱动程序设计和
[嵌入式]
嵌入式Linux系统中的快速启动技术研究
       嵌入式Linux系统主要特点在于使用Bootloader替代了桌面系统的BIOS,同时对系统进行了规模上的裁剪,但硬件上的劣势往往导致系统启动速度较慢,而嵌入式产品使用者又对系统的开机速度比较敏感,样就产生了对于提高嵌入式Linux系统启动速度的需求。本文对系统启动时执行哪些阶段的操作,以及缩短这些操作时间的方法进行了探讨。    1 嵌入式Linux系统启动时序   目前,嵌入式系统的硬件平台和应用方向区别很大,但总体启动流程一致的。这里的系统启动是指从用户执行上电/复位操作,到系统开始提供用户可接收的服务水平所需要的过程。典型的上电/复位时序如表1所列。        表1 嵌入式Linux系
[嵌入式]
ARM与嵌入式linux入门建议
由于很多人总问这个问题,所以这里做一个总结文档供大家参考。这里必须先说明,以下的步骤都是针对Linux系统的,并不面向WinCE。也许你会注意到,现在做嵌入式的人中,做linux研究的人远比做WinCE的人多,很多产家提供的资料也是以linux为主。我一直很难理解,其实WinCE的界面比linux的界面好看多了,使用起来也很方便,更为重要的是,WinCE的开发和Windows下的开发基本一样,学起来简单得多,但是学linux或者使用linux做嵌入式的人就是远比WinCE多。在和很多工作的人交流时我了解到,他们公司从没考虑使用WinCE,因为成本高,都是使用linux进行开发。我读研究生的的实验室中也没有使用WinCE的,大都研究l
[单片机]
基于S3C2440嵌入式Linux的步进电机驱动程序
在嵌入式Linux开发过程中需要为指定设备编写和编译驱动程序,这与以往在PC机上的Linux驱动开发明显不同,本文设计了基于S3C2440嵌入式Linux下激光雕刻系统的步进电机驱动程序。 1 硬件系统的设计 步进电机开环控制系统主要由中央控制器、步进电机驱动器、传感器以及步进电机四大部分组成。本系统采用基于ARM920t内核的S3C244 0A微处理器作为控制系统的中央控制器,该芯片主频400MHz,最高可达到533MHz,内含多种设备接口,存储器使用64MB的Nand Flash和64MB的SDRAM。图1所示为控制系统框图。 2 系统的工作原理 本系统主要控制两个两相混合式步进电机,分别代表X轴和Y轴带动
[单片机]
基于S3C2440<font color='red'>嵌入式Linux</font>的步进电机驱动程序
基于嵌入式Linux系统的导航软件设计思路
1 引言 随着汽车等各种车辆交通工具的普及,车辆导航设备的需求也变得日益旺盛。作为车载设备。不仅要有可靠的性能,而且需要具有便携、低功耗和低价格等特点。而采用基于ARM微处理器的嵌入式系统与GPS模块相配合的GPS导航终端机的设计方案,可以很好的满足这一系统需求。为此,本文介绍了一种利用ARM9开发板和GPS模块实现GPS导航功能的终端机的软硬件结构和设计方法。 2 GPS导航系统结构 本文所介绍的GPS全球定位导航系统按功能可分为嵌入式主控模块、GPS模块、显示模块、扩展模块及供电模块等五大部分。 嵌入式主控模块基于S3C2440处理器,主要负责对GPS导航模块数据的响应、处理和控制。在硬件上,主控模块就是一个嵌入式开发板,包括
[电源管理]
基于<font color='red'>嵌入式Linux</font>系统的导航软件设计思路
小广播
最新嵌入式文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved