先声明一下,图片太大,显示效果不佳,可以拖拽到新窗口中看。
     在做好下载前的准备后,开始正式下载镜像。DownloadImage函数定义在文件blcommon.c中,下面是的源代码:
三个参数都是输出参数,分别输出镜像的开始位置、镜像的大小以及启动镜像的地址。这里注意,镜像的开始处会有一些头信息,所以开始位置与启动镜像的地址是不一样的。
217到222行通过OEMReadData函数读取镜像的前面7个字节,这7个字节代表了镜像文件的格式。每一个镜像文件在文件数据的起始位置都有7个字节的特征码,与镜像文件的格式一一对应:
"N000FF\x0A"----- 该类型的镜像文件的数据是多区段的记录型镜像文件的区段信息 
"X000FF\x0A"----- 该类型只在WinCE5.0及以前的版本中用于多区段的镜像文件 
"B000FF\x0A"----- 最普通常用的记录型镜像文件格式,以.bin为文件名后缀 
"S000FF\x0A"----- 带有数字签名的镜像文件,以.bin为文件名后缀 
"R000FF\x0A"----- 带有数字签名的镜像文件,以.nk0为文件名后缀 
无特征码        ----- 这时当做原始镜像文件进行处理
OEMReadData函数在上面的源代码中使用了很多次,由OEM用户自己实现,其定义在文件main.c中,根据下载镜像的方式不同(以太网或USB),调用不同的接口读取镜像数据,实现的源码如下:
BOOL OEMReadData(DWORD dwData, PUCHAR pData) 

        BOOL ret; 
         OALMSG(OAL_FUNC, (TEXT("+OEMReadData.\r\n"))); 
        //OALMSG(TRUE, (TEXT("\r\nINFO: dwData = 0x%x, pData = 0x%x \r\n"), dwData, pData)); 
        if ( g_bUSBDownload == FALSE ) 
        { 
                ret = EbootEtherReadData(dwData, pData); 
        } 
        else if ( g_bUSBDownload == TRUE ) // jylee 
        { 
                ret = UbootReadData(dwData, pData); 
        }         
        return(ret); 
}
227到269行表示使用的是多区段的记录型镜像文件格式,多区段的镜像起始就是操作系统或者BootLoader的运行时二进制数据分散在不连续的物理存储区间。多区段意味着多文件,即需要下载多个文件,所以在267行中用nNumDownLoadFiles来记录下载的文件数量。该类型的镜像文件并不是真正的WinCE操作系统或者BootLoader的二进制运行时数据,只是供下载多区段型镜像所使用的头信息,称为Manifest前导数据。当操作系统的镜像只有一个区段,或者是使用自身包含有存储位置头信息的记录型镜像文件格式时,就可以不使用Manifest前导数据。这点要注意,否则下面的一些代码就看不明白了。该类型的镜像文件使用专门的DownloadManifest型的全局变量g_DownloadManifest来存放。下面看看这种类型的镜像文件的数据结构。紧随7字节的格式类型特征码后是4字节的校验码,然后是4字节的区段个数。接下来便是存放在g_DownloadManifest.Region数组各个元素中的数据。RegionInfo结构体有3个成员dwRegionStart、dwRegionLength、szFileName,分别为镜像区段在物理存储的起始地址、以字节为单位的区段长度和与镜像区段对应的镜像文件的文件名。
231行开始首先读取4字节的校验码,然后读取区段数量,存储到g_DownloadManifest.dwNumRegions中,然后把该镜像区段的数据都读取到g_DownloadManifest结构体中,最后调用VerifyChecksum函数对数据执行校验。
263行的OEMMultiBINNotify函数是当BootLoader要下载多区段的操作系统镜像时调用来向用户发出通知。
272到278行表示的是WinCE5.0及之前版本支持的多区段的镜像文件,由于分析的平台是以WinCE6.0为操作系统的,所以这里直接返回FALSE。
281到292行表示的是最常用最普通的记录型镜像文件格式,下面对这种.bin的镜像文件的内部结构进行描述。最初的7字节特征码之后是镜像文件在目标系统中的目的地的物理存储起始位置和以字节为单位的长度,各占4字节,对应RegionInfo结构体的dwRegionStart和dwRegionLength两个成员。再接下来便是具体存放操作系统二进制数据的拥有相同结构的多条Record记录,每条Record包括4字节的内存起始地址dwRecAddr、4字节的记录长度dwRecLen、4字节的校验码dwRecChk和dwRecLen个字节的记录数据组成。校验无误以后将去除头信息的记录数据存放到dwRecAddr指定地址的物理存储位置。如果记录的目的存储位置是Flash存储设备,则要先缓存到RAM内存中,待整个镜像文件下载完以后再一起写入Flash。在源代码中,281到292行只读出了dwRegionStart和dwRegionLength。
305到317行是当仅仅下载了单个的.bin文件时,没有填充g_DownloadManifest结构体,无法通知用户,所以此时要人工手动填充DownloadManifest结构体,只是没有镜像区段对应的文件名。
324到329行调用函数EMVerifyMemory检测当前下载的镜像对应的虚拟内存地址区域是否映射到了用户可以使用的物理存储区域。
332到338行表示当下载的镜像的目的存储地址是Flash时,擦除Flash。函数OEMIsFlashAddr和OEMStartEraseFlash的定义都在文件\WINCE600\PLATFORM\<BSP name>\SRC\BOOTLOADER\EBOOT\flash.h中。OEMIsFlashAddr用来判断一个给定的地址值是否落在系统的Flash存储设备范围内。OEMStartEraseFlash负责初始化并启动Flash存储器的擦除进程。本平台的源码中,这两个函数都是空的,没有任何操作。
342到356行是当g_bBINDownload为FALSE时进行的处理,即下载的镜像是最普通常用的原始型镜像文件,以.nb0为文件后缀的二进制文件。这里需要解释的是为何要调用OEMMapMemAddr函数之后才开始读取镜像文件?由于Flash操作速度比RAM慢,在片擦除的时候可能会使读写操作停滞,这样在每次下载操作系统镜像文件的时候可能是下载停滞。调用OEMMapMemAddr将Flash地址映射到RAM地址中,这样向Flash写数据实际上先写到RAM中,然后再写到Flash中,就不会感觉到下载停滞了。
      358到416行是用来下载.bin文件,按照一定的顺序依次下载镜像的所有记录。结合该类型镜像文件格式,相信大家很容易明白。同样这里也用到了OEMMapMemAddr函数进行Flash地址映射来防止下载停滞现象。391行到406行是用来寻找操作系统镜像文件中的全局变量数据信息TOC的,首先比较数据长度dwRecLen与sizeof(ROMHDR)的大小,以此来判断该条记录是否为TOC记录,dwTempOffset取得的是RAM内存的偏移地址,398到401行的if语句是进一步通过TOC的成员判断该条记录确实是TOC记录的。ROM_SIGNATURE_OFFSET和ROM_SIGNATURE两个宏定义都在头文件\WINCE600\PUBLIC\COMMOM\OAK\INC\romldr.c中。 
430到454行根据下载的bin文件是否包含有TOC和内核分别对三个输出参数进行设置。433行是判断bin文件是够有TOC数据,如果有调用IsKernelRegion函数判断文件中是否有内核(通过查找是否有nk.exe的文件名),如果有则返回NK.bin的起始地址,长度和跳转地址。447行表示bin镜像只含有一个区段,同样返回镜像的起始地址、大小和启动地址。这里需要注意的是启动地址赋值为dwRecLen,因为通常bin文件的最后一条记录是地址dwRecAddr和校验和dwRecChk都为0,而dwRecLen标示的其实是实际的入口点。
455到460行是当镜像文件为原始的二进制文件时,对三个输出参数进行赋值。
463到477行表示如果镜像文件的目的存储地址是Flash,则调用OEMFinishEraseFlash函数结束Flash存储器的擦除进程,而且即将进入写镜像文件到Flash的处理阶段。在写镜像到Flash之前,调用g_pOEMCheckSignature对镜像进行校验。该函数用于验证WinCE image中的署名并检查其有效性。pCurDownloadFile->dwRegionStart为被下载image的存储起始地址,g_dwROMOffset为config.bib文件中定义的ROMOFFSET的值,*pdwLaunchAddr为被加载的地址,最后一个参数为TURE表示是被下载的image文件。
482到493行,调用函数OEMWriteFlash将暂存在RAM内存缓冲区中的一个或者多个操作系统镜像区段的数据写入Flash存储设备。
本文转自jazka 51CTO博客,原文链接:http://blog.51cto.com/jazka/605776,如需转载请自行联系原作者

WinCE6.0 BootloaderMain源码分析之DownloadImage相关推荐

  1. Spark2.4.0 SparkEnv 源码分析

    Spark2.4.0 SparkEnv 源码分析 更多资源 github: https://github.com/opensourceteams/spark-scala-maven-2.4.0 时序图 ...

  2. 菜鸟读jQuery 2.0.3 源码分析系列(1)

    原文链接在这里,作为一个菜鸟,我就一边读一边写 jQuery 2.0.3 源码分析系列 前面看着差不多了,看到下面一条(我是真菜鸟),推荐木有入门或者刚刚JS入门摸不着边的看看,大大们手下留情,想一起 ...

  3. Android 11.0 Settings源码分析 - 主界面加载

    Android 11.0 Settings源码分析 - 主界面加载 本篇主要记录AndroidR Settings源码主界面加载流程,方便后续工作调试其流程. Settings代码路径: packag ...

  4. Android 8.0系统源码分析--Camera processCaptureResult结果回传源码分析

    相机,从上到下概览一下,真是太大了,上面的APP->Framework->CameraServer->CameraHAL,HAL进程中Pipeline.接各种算法的Node.再往下的 ...

  5. photoshop-v.1.0.1源码分析第三篇–FilterInterface.p

    photoshop-v.1.0.1源码分析第三篇–FilterInterface.p 总体预览 一.源码预览 二.语法解释 三.结构预览 四:语句分析 五:思维导图 六:疑留问题 一.源码预览 {Ph ...

  6. Spark2.0.2源码分析——RPC 通信机制(消息处理)

    RPC 是一种远程过程的调用,即两台节点之间的数据传输. 每个组件都有它自己的执行环境,RPC 的执行环境就是 RPCENV,RPCENV 是 Spark 2.x.x 新增加的,用于替代之前版本的 a ...

  7. Pushlet 2.0.3 源码分析

    转载地址:http://blog.csdn.net/yxw246/article/details/2418255 Pushlet 2.0.3 源码分析 ----服务器端 1 总体架构 Pushlet从 ...

  8. jQuery 2.0.3 源码分析 Deferred(最细的实现剖析,带图)

    Deferred的概念请看第一篇 http://www.cnblogs.com/aaronjs/p/3348569.html ******************构建Deferred对象时候的流程图* ...

  9. 最细的实现剖析:jQuery 2.0.3源码分析Deferred

    Deferred的概念请看第一篇 http://www.cnblogs.com/aaronjs/p/3348569.html **构建Deferred对象时候的流程图** **源码解析** 因为cal ...

  10. jQuery 2.0.3 源码分析 事件体系结构

    那么jQuery事件处理机制能帮我们处理那些问题? 毋容置疑首先要解决浏览器事件兼容问题 可以在一个事件类型上添加多个事件处理函数,可以一次添加多个事件类型的事件处理函数 提供了常用事件的便捷方法 支 ...

最新文章

  1. 引导修复_怎么使用bcdrepair引导修复系统【详细步骤】
  2. 谭永浩 c语言pdf,如何自学C++?
  3. Mac 安装 MySQL-python 问题解决
  4. python显示行数_jupyter notebook实现显示行号
  5. “〜”(波浪号/波浪形/旋转)CSS选择器是什么意思?
  6. 计算机主板用塑料做的好吗,太震惊!你的键盘是否用了黑心塑料?
  7. 宁波网络推广分享能让新站提升收录的技巧!
  8. C++标准输出流对象
  9. 深度学习核心技术精讲100篇(六十二)-DQN 的三种改进在运筹学中的应用
  10. [云炬创业基础笔记]第二章创业者测试7
  11. HDU 2289 Cup
  12. 企业shell面试题:获取51CTO博客列表按时间倒序排序
  13. RSA签名算法 - Java加密与安全
  14. Decision Tree学习笔记(基础篇)
  15. MySQL_(Java)分页查询MySQL中的数据
  16. mysql性能优化学习笔记
  17. php 两个单词 正则表达式字符前_PHP正则表达式核心技术完全详解 第3节
  18. Java操作mongoDB2.6的常见API使用方法
  19. 将勾选数据从dataset中筛选出来
  20. Maven使用 | 多模块下的打包问题

热门文章

  1. Spring properties dependency checking
  2. ADSL拨号网络环境下实时视频广播的完美实现
  3. sql server 2000里ldf损坏,只有mdf的恢复
  4. Android lowmemorykiller分析
  5. 关于连接参数-Ttext
  6. cgroup: Control Group 分析 转载
  7. python平均分计算器_招募:基于python的召唤师全时段全技能(含均值AI)计算器全程测试...
  8. 手动计算均值,方差,协方差,皮尔逊系数
  9. sublime实用快捷键 mac版
  10. KDevelop下如何选择不同的源文件进行执行