由Windows CE的开发工具Platform Build编译生成的Windows CE操作系统及Bootloader的镜像文件主要由两种格式类型——以.bin为文件名后缀的记录型镜像文件和以.nb0为后缀的原始型(raw)镜像文件,前者以记录(Record)为单位组织镜像的数据,后者则是镜像在嵌入式系统中运行时的二进制数据快照。
DownloaderImage函数执行的第一步是调用GetImageType函数获知镜像文件的格式类型。每一个Windows CE镜像文件在文件数据的起始位置都有一个7字节的特征码(magic number),它与镜像文件的格式一一对应如下:
“N000FF\X0A”——BL_IMAGE_TYPE_MANIFEST
“X000FF\X0A”——BL_IMAGE_TYPE_MULTIXIP
“B000FF\X0A”——BL_IMAGE_TYPE_BIN
…
本文重点研究BL_IMAGE_TYPE_BIN类型的记录型镜像文件格式,该类型的镜像文件均以.bin为文件名后缀,DownloaderImage函数调用DownloadBin函数处理这种类型的镜像文件。在BL_IMAGE_TYPE_BIN类型的镜像文件中,紧随着最初的7字节特征码之后是该镜像文件在嵌入式系统中的目的物理存储起始地址和以字节为单位的长度,各占4字节,这两个数据的含义分别对应于RegionInfo结构体的dwRegionStart、dwRegionLength两成员。接下来的便是具体存放操作系统为二进制数据的拥有相同结构的多条记录(Record),每条记录由4字节的内存起始地址dwRecAddr、4字节的记录长度dwRecLen、4字节的校验码dwRecChk和dwRecLen个字节的记录数据组成。DownloaderImage函数依次从下载端口读出各条记录并且对它们执行校验,校验也是以记录为单位,待校验无误以后将去除头信息的记录数据存放到dwRecAddr指定地址的物理存储位置。如果记录的目的存储位置是Flash存储设备,则通常要先缓存在RAM内存中,待整个镜像文件全部下载完再一起写入Flash。
本文以项目中定制的操作系统NK.bin为例进行分析。使用UltraEdit将其打开如图1所示。
图1 使用UltraEdit打开系统镜像文件
从上图可以看出,文件头(head)由7个字节组成,内容是:42 30 30 30 46 46 0A,即“B000FF\x0A”,这是判断镜像文件是.bin类型的依据。镜像数据目的起始地址(ImageStart,00 00 10 80)由4个字节组成,它定义了镜像文件解析后装载在内存中的起始地址是0x80100000。镜像数据长度(ImageLength,D0 03 5D 02)也由4个字节组成,它表示.bin镜像文件解析后在内存中占用的总的存储空间大小为(0x025D03D0)。每条记录(record)由4字节的起始存储地址(RecordStart)、4字节的数据长度(RecordLength)、4字节的校验码 (RecordCheckSum)和RecordLength个字节的记录数据(RecordData)组成。以第一条记录为例,分别为0x80100000,0x00000004,0x000001AF和0XEA0018AD。
可以使用%_WINCEROOT%\PUBLIC\COMMON\OAK\BIN\I386目录下的viewin工具查看NK.bin文件的记录内容。Viewbin是一个用于查看Windows CE的操作系统镜像数据信息的小程序,它可以看到的镜像信息包括:镜像运行时准确的长度信息、包含在镜像中的文件和可执行的模块以及镜像中所包含的符号信息。使用下面命令查看NK.bin镜像文件中的记录内容,如图2所示。
Viewbin –r nk.bin
上图清晰的显示了NK.bin里面的所有记录条目(截图只显示了0-16条)。镜像数据目的起始地址(ImageStart)为0x80100000,镜像数据长度(ImageLength)为0x025D03D0。以第一条记录Record[0]为例,它由4字节的起始存储地址(0x80100000)、4字节的数据长度(0x00000004)、4字节的校验码 (0x000001AF)和0x00000004个字节的记录数据(0XEA0018AD)组成。这和之前使用UltraEdit打开NK.bin的内容是一致的。
由以上 .bin 的文件格式可知, .bin 文件不是内存程序空间的一个简单的拷贝。所以它不能直接用串口烧写进内存或 FLASH 空间来直接运行,必须通过 PB 下载,通过 EBOOT 按照 .bin 文件的格式解析出来具体的内容并重新装载后才能运行。