龚昌平,谯通旭,张福健
(中国电子科技集团公司第三十研究所,四川 成都 610041)
网络安全嵌入应用中的BOOTLOADER*
龚昌平,谯通旭,张福健
(中国电子科技集团公司第三十研究所,四川 成都 610041)
Bootloader是网络安全嵌入软件开发实现的第一步,也是最重要的一步,直接影响应用程序在设备加电后是否能够正常加载运行,也影响设备从加电到正常运行间的时间,影响用户的体验。因此,讨论Bootloader的基本属性,并通过一个简单的实例详细描述引导加载过程,同时就如何满足现场升级、在应用编程(IAP)等方面的应用需求进行阐述,以助于网络安全嵌入式系统开发人员尤其是初学者深刻理解Bootloader。
网络安全;嵌入式应用;引导加载器;现场升级;IAP
所谓Bootloader,即引导加载器,是网络安全嵌入式系统中最先被运行的一小段程序。通过这小段程序初始化硬件设备,建立内存空间映射图,从而将系统的软硬件环境带到一个合适状态,以便为最终调用应用程序准备好软硬件环境。
常言道,“万事开头难”。编写网络安全嵌入式应用软件也是如此。一些网络安全嵌入式应用开发者,尤其是初学者,常常对其中的Bootloader感到困惑不解,更不用说如何编写。因为网络安全嵌入系统的Bootloader涉及底层硬件操作细节,所以编写一个合适的Bootloader是一项具有挑战性的任务。本文将以TI公司的DSP芯片为例,介绍编写Bootloader的一些实现细节。
在具体阐述Bootloader的基本属性前,先了解系统的引导过程[1-2]。以TI公司的C6000 DSP的ROM Boot方式为例,如图1所示,DSP的引导过程如下:(1)上电复位后,CPU暂停运转,其他部分则开始工作,此时EMIF的CE1空间自动配置为8/16/32位异步存储器接口,并且CE1空间读/写时序自动配置为最大,然后通过DMA(或EDMA)方式将外部CE1空间的数据读入到内部程序空间地址0处,读入数据的多少因芯片而异(C641x,C671x读取1 kB,C620x读取64 kB)。(2)CPU开始运转,并执行内部程序空间地址0处的程序,先将外部应用程序数据读入到DSP程序空间相应地址,然后跳转到应用程序运行。
图1 TI DSP引导过程
第一步由芯片自动完成,第二步由用户完成。用户编写相应的C程序(C620x,容量64 kB,可以用C实现)或汇编程序(C641x,C671x,容量1 kB,只能用汇编实现),实现二级引导,即应用程序的装载。
第二步通常也就是Bootloader要实现的目标。
在一个典型的网络安全嵌入式开发环境中,目标硬件通过一个硬件仿真器与主机连接[3]。通常,还会有类似TI的CCS调试器,用于将程序加载到目标存储器并执行。用户还可根据需要设置断点,以及其他诸如跟踪、剖析等事务。这些都使得开发者很容易快速实现和调试新的应用案例。
如果一个应用由C实现,并在非嵌入式开发环境中运行,程序看起来像是从主函数main开始执行,程序的加载和初始化过程则隐藏在表象背后。可见,将把用户的注意力从底层的系统寄存器初始化、堆栈的初始化、数据的初始化转移到上层应用程序代码,向用户提供一个友好的用户界面,将仅仅是调试器而非开发者的事情。
而在一个网络安全嵌入应用开发环境中,程序通常从C环境的程序入口点开始执行。程序入口点,TI的文档通常称为c_int00,实现堆栈、系统寄存器和数据存储器的初始化后,跳转到main[4]。由于与特定处理器相关的复位入口点(复位矢量)将触发c_int00,故开发者通常会对c_int00作特殊处理。
Bootloader形式多样,图2展示了一个典型的网络安全嵌入式C应用中的Bootloader。在这个例子中,RESET矢量跳转到C环境入口函数c_int00,并在此进行堆栈和系统寄存器的初始化。此外,在运行前需初始化的C变量也从.cinit段复制到.bss段相应的位置[5]。最后,调用main()函数。在这个简单的例子中,Bootloader包括RESET复位矢量和c_int00,并假定Bootloader和应用程序都是从同一个非易失存储器开始执行。在一个稍微复杂的系统中,Bootloader在调用main()前或许还会将应用程序复制到快速易失存储器。
图2 一个简单的Bootloader
更复杂的Bootloader或许还会实现诸如系统诊断、调试功能、现场更新等。其中,系统诊断包括存储器测试、外设测试、程序完整性校验等。Bootloader也可能会包含简单的调试功能模块,它通常集成在用户监控程序模块中。Bootloader还可能会处理现场更新程序、从外部存储器下载应用程序等。如果担心自己的产品被逆向工程,为保护自己的知识产权,用户还可以在Bootloader中集成加密、解密代码的功能。为了节约宝贵的存储器资源,也可以选择在Bootloader中进行资源压缩、解压缩。甚至为了以后方便资源管理,还可以集成文件系统。
让我们来看看一个包含上述所有基本属性的Bootloader。这个例子同样也会将应用程序从慢速非易失性存储器复制到快速易失性存储器,以加快应用程序的执行速度。
这里以TI的DSP为例,目标处理器是TI的TMS320C6205 DSP。它使用分离的程序和数据存储器,即典型的哈佛结构[6-8]。在这个简单的系统中,外部存储器是位于CE1空间的慢速FLASH,内含Bootloader和应用程序的拷贝。引导方式选择C6205的ROM Boot方式,存储器映射选择Memory Map 1,即地址0处于片内空间,这也是网络安全嵌入式应用中的首选应用方式。实际上,TI在后续C6000芯片的设计中,完全摒弃了存储器映射方式的选择,直接将地址0x00000000定位于片内(例如C6416)。
应用程序代码用C语言编写。此例中,修改TI C6205 DSP的库函数c_int00,以此作为Bootloader,并完成以下功能:初始化堆栈;设置寄存器;从.cinit中初始化数据,将应用程序从慢速的外部FLASH复制到快速的程序RAM(片内或片外),然后跳转到main()函数[9]。
本例子的链接命令文件如下[10]:
开始两行分别定义堆、栈空间的大小为16 kB、32 kB。接下来,MEMORY伪指令分配存储空间。这里,把片内程序空间(共64 kB)分为4个部分:IPRAM_VECT(中断矢量),IPRAM_BOOT(RTS库中的boot代码),IPRAM_RTSL(本程序中用到的RTS库代码)和IPRAM(其余运行于片内的程序);把CE1空间分为FLASH0~FLASH5六部分:片内程序、保留、片外程序、.cinit段、.const段、.switch段;接下来,SRAM_P则定义了片外程序的运行空间,而IDRAM则是64 k字节的片内数据空间,所有的全局变量、局部变量、常数等均在此空间内。伪指令SECTIONS将程序中用到的各个段分配至MEMORY定义的相应区域内,从而完成所有段的映射。开始于CE1空间(FLASH0)的首0x200字节存放的是中断矢量表,上电时将被搬移至IPRAM_VECT区域。FLASH0的其余部分以及FLASH1~FLASH5则包含c_int00和C程序的拷贝,上电时将被搬移到IPRAM_BOOT、IPRAM_RTSL、IPRAM、SRAM_P,随后应用程序开始运行。最后,IDRAM中包含堆栈和C变量,存于C6000的片内RAM中。需要注意的是,这些变量和堆栈也是由c_int00负责初始化的。
在链接命令文件中,应特别注意LOAD和RUN的使用。当编译C或汇编源文件时,生成的目标文件总是可重定位的。因此,在链接前是不知道绝对地址的[11-14]。一个目标文件可以临时加载到存储器的任何区域,但在运行前必须拷贝到RUN运行时的绝对地址处,否则程序的运行不可预知。LOAD
用于说明程序存储在哪,但并不说明程序的运行地址。RUN
则说明程序的运行地址,也被链接器用于地址解析。如果程序的加载地址和运行地址不同,程序在运行前应从加载地址拷贝到运行地址。通常程序的运行地址和加载地址相同,但在这个特定的例子中,由于应用程序在运行前必须从慢速存储器搬移到快速存储器,因此这两个地址必定不同,而程序拷贝工作由Bootloader来完成。
对于中断矢量表,复位矢量只是简单跳转到c_int00入口函数,不处理其他中断:
这个修改后的c_int00函数必须首先初始化堆栈和需要初始化的DSP寄存器,然后把应用程序从FLASH拷贝到片外程序RAM,使用.cinit表初始化数据项,最后调用main()函数。
注意,应尽量把对速度要求较高的程序段放在片内,同时把堆栈、变量也放在片内,以加快程序的运行速度。
在编写链接命令文件时,要注意程序和数据的地址空间安排。通常,数据区域不能存放程序,反之亦然。正如本例的链接命令文件,C6205的数据空间和程序空间并不重叠。
几乎TI所有的DSP都内置有基于ROM的Bootloader,用于将程序代码从片外拷贝到DSP的程序空间。代码加载接口灵活多样,可使用McBSP、SPI、HPI、I/O、GPIO和并行存储器接口等[15]。使用GPIO非常方便、通用、灵活,但缺点是速度较慢且独占CPU。HPI和并行存储器接口的速度较快,但灵活性稍差。激活Bootloader的机制因器件而异,但所有的器件通常都会有“检测外部处理器引脚的数字状态”“外部并行数据接口”“I/O总线上某个特殊数字序列”等常规机制。
在大多数网络安全嵌入式环境中,Bootloader必须具备鲁棒性,在某些情况下甚至只许成功,不能失败。一个好的设计思路就是像图3那样,将Bootloader分成几个独立的扇区[10]。由于可块引导FLASH的每个扇区能够单独锁定,因此非常适合这种场合。
引导扇区包含中断矢量表和引导代码,出厂时被编程到非易失性存储器。加载器分为两个扇区:主加载器扇区和二级加载器扇区。每个扇区均有CRC校验值。出厂时,设备默认配置为主加载器。
图3 多级引导扇区(鲁棒性)
二级加载器扇区出厂时为保留空间,无初始化数据。如果设备需要新的加载器(即加载程序),将由主加载器写到二级加载器扇区。应用程序扇区包含应用程序代码,将由主加载器或二级加载器现场加载至非易失性存储空间(即现场更新)。
系统复位时,引导扇区进行冗余检测、硬件特定的系统初始化。引导扇区基于CRC完整性校验来确定激活哪个加载器,每个加载器扇区都存储有CRC校验值。首先检验主加载扇区的完整性校验,若校验通过,则使用主加载扇区;若校验未通过,转为校验二级加载扇区的校验值,若校验通过,使用二级加载扇区。然后,选择的加载器扇区负责应用程序的完整性校验,将应用程序加载到易失性存储器,并跳转到应用程序的入口点。
软件是否可在线更新成为衡量设备升级灵活性的重要指标。应用编程(IAP)是指当固件驻留在系统中时,可将固件写至非易失性存储器。常用的方法是,首先加载设备加载程序到非易失性目标存储器,随后就由设备加载程序负责下载外部应用程序,并将其编程到目标系统的非易失存储器。TI的许多DSP都内置有基于ROM的Bootloader,利用这个内置的Bootloader将很容易实现上述目标。通常的思路如下:(1)完成系统初始化;(2)选择检测程序更新条件。有四种方式对程序更新进行检测:
方式1:设置定时器。时限未到,可以进行程序更新;时限到,则检查应用程序标志,如果有应用程序且校验和正确,则跳转到应用程序执行;否则重置定时器,开始新一轮检测。(前提条件:有硬件定时器)
伊泰普水电站当时初步选定的单机容量为700 MW,对其向上取700的倍数,分别得到12 600 MW和14 000 MW。所以伊泰普水电站的初期(1991年)装机容量为12 600 MW,并预留了扩建2台700 MW机组的机坑。到2007年伊泰普水电站总装机容量从12 600 MW增加到14 000 MW,年发电量为900亿kW·h。该数据与表2中数据基本一致,验证了该方法的可靠性。
方式2:检测外部按键是否按下。如果按键按下,执行程序更新;否则,检查应用程序标志,如果有应用程序且校验和正确,则跳转到应用程序执行,否则重新检测按键,开始新一轮检测。(前提条件:有按键)
方式3:方式1和方式2的综合,设置定时器。时限未到,循环检测按键是否有效,并进行程序更新;时限到,则检查应用程序标志,如果有应用程序且校验和正确,则跳转到应用程序执行;否则重置定时器,开始新一轮检测。(前提条件:按键+定时器)
方式4:在主循环中设置一个变量进行计数。每循环一次变量加1,计数值未到,可进行程序更新;计数值到,则检查应用程序标志,如果有应用程序且校验和正确,则跳转到应用程序执行;否则计数值清0,开始新一轮检测。
上述过程结束后,如果有应用程序,Bootloader将把程序的控制权交给应用程序。考虑到片内RAM资源有限、用户习惯且程序编写方便,通常我们把Bootloader和应用程序的入口地址都安排在地址0处。因此,在任意时刻,有且仅有一个程序处于执行状态。
Bootloader如何将应用程序搬移到地址0并运行?需要搬移全部应用程序吗?以TI的C6000芯片为例,先使用芯片内置的DMA/EDMA完成固定长度的程序代码搬移(C641x,C671x:1KB,C620x:64KB-Len),随后由刚才搬移的程序将余下的程序代码搬移至合适地址。切记,完成DMA/EDMA程序搬移的这段程序(假设长度为Len)的地址空间,不能与被其搬移的程序地址空间重叠,否则程序的执行行为不可预知。
在一些网络安全嵌入式系统中,非易失存储器的容量可能比易失存储器的容量小得多。针对此种情况,可在Bootloader中集成信源编码(即压缩、解压缩):代码先经压缩,然后存放到FLASH上;使用前解压缩FLASH上的代码,再加载到程序RAM空间并运行。此外,如果用户希望保护自己的知识产权,防止竞争对手COPY技术成果,在Bootloader中可增加加密、解密功能。
本文概要介绍Bootloader的方方面面,并以TMS320C6205为例,对怎样为网络安全嵌入式应用写一个Bootloader进行详细阐述,希望对网络安全嵌入式系统开发人员尤其是初学者有所帮助。
[1] TI.TMS320C620x/C670x DSP Boot Modes and Configuration Reference Guide[J].Application Note,2003,1(01):1-23.
[2] TI.TMS320C6414,TMS320C6415,TMS320C6416 Fixed-point Digital Signal Processors[J].Application Note,2005,1(01):75.
[3] TI.TMS320C6000 Assembly Language Tools User's Guide[J].Application Note,2006,1(01):61-125.
[4] TI.TMS320C6000 Optimizing C Compiler User's Guide[J].Application Note,2011,1(01):183-243.
[5] TI.TMS320C6000 CPU and Instruction Set Reference Guide[J].Application Note,2000,1(01):644-670.
[6] TI.TMS320C6000 Peripherals Reference Guide [J]. Application Note,2006,1(01):1-11.
[7] TI.TMS320C62x/C67x Programmer's Guide [J]. Application Note,2011,1(01):421-432.
[8] TI.TMS320C6000 DSP Enhanced Direct Memory Access(EDMA) Controller Reference Guide[J].Application Note,2005,1(01):117-163.
[9] TI.TMS320C620x/C670x DSP Program and Data Memory Controller/Direct Memory Access (DMA) Controller Reference Guide[J].Application Note,2004,1(01):11-37.
[10] Stanford Hudson.Embedded Apps Need Boot-loaders Too[J].Embedded Edge,2002,3(02):20-26.
[11] TI.TMS320C54x DSP Reference Set Volume 1:CPU and Peripherals[J].Application Note,1999,1(01):60-89.
[12] TI.TMS320C54x DSP Reference Set,Volume 2:Mnemonic Instruction[J].Application Note,1998,2(01):45-116.
[13] TI.TMS320C54x DSP Reference Set Volume 3:Algebraic Instruction Set[J].Application Note,1998,3(01):332-344.
[14] TI.TMS320C54x DSP Reference Set Volume 4:Applications Guide[J].Application Note,1996,4(01):165-185.
[15] TI.TMS320C54x DSP Reference Set Volume 5:Enhanced Peripherals[J].Application Note,1999,5(01):125-181.
龚昌平(1972—),男,硕士,工程师,主要研究方向为信息安全与通信保密;
谯通旭(1963—),男,学士,高级工程师,主要研究方向为密码学;
张福健(1989—),男,硕士,工程师,主要研究方向为信息安全与通信保密。
Bootloader in Embedded Application of Network Security
GONG Chang-ping, QIAO Tong-xu, ZHANG Fu-jian
(No.30 Institute of China Electronics Technology Group Corporation, Chengdu Sichuan 610041, China)
The design and implementation of Bootloader is the first and most important step, in a embedded environment of network security, this directly influences program loading and running of the devices after power-on, and also affects boot time of the devices and thus the user's experiences. This article discusses some basic properties of Bootloader, describes in detail the Bootloader process via a simple example, and makes an elaborate interpretation of how to satisfy such application demands as field upgrade and IAP(In-Application Programming). All this could help the developer of network security embedded system, especially the beginner, deeply understand Bootloader.
network security; embedded application; Bootloader; field upgrade; IAP
TN918.1
A
1002-0802(2016)-10-1392-05
10.3969/j.issn.1002-0802.2016.10.024
2016-06-19;
2016-09-24
data:2016-06-19;Revised data:2016-09-24