WindowsCE BootLoader启动流程

      首先通常都是汇编代码:启动时由系统复位导致PC为0为触发条件:以2440代码为例直接进入fw.s文件,在有一些bsp包中这个汇编代码的文件名为Startup.s。主要执行的操作为设置处理器频率(PLL)、初始化RTC、设置内存参数、为bootloader的第二个阶段准备申请ram并把第二阶段的bootloader读入到ram中,然后进入eboot中的c代码的main函数中,这个阶段一般被称为N Boot,是机子运行起来时第一次软件的启动运行,这个阶段一般都是通过读写寄存器以达到效果。须注意的是在该部分代码虽然在形式上实现了诸多中断向量,但是这些代码根本上不会得到执行。而在后面会有一些其他手段用于实现中断向量的功能。由于和hal复用该部分文件,所以调用的函数名称会与内核启动函数的相同(如:KernelStart),但是实现内容却是完全不同的。在该部分的最后还将保存一个OEMAddressTable的地址指针到下一格函数,进行应有的内存影射。下面还是以2440bsp为例说明。根据windowsCE系统的要求,需要把将会操作到的内存空间影射到0x8000 0000后的512M空间中,其中低256M为带缓冲的,高256M则是不带缓冲的。不带缓冲的区域通常是驱动访问设备必须的,这样可以保障对硬件的操作不受到缓冲的干扰。除了按照OEMAddressTable进行内存空间影射外,还可以要根据程序需求进行其他一系列影射,通常的做法都是将目前所有的设备/内存在原地址空间上再影射一次,以方便使用。另外就是在将0x0位置影射到内存,这样,就可以通过这个部分来进行中短向量的安装了,以实现中断服务程序。(以上内存影射并不是必须的,仅仅是为了方便程序的编写而已,使用和系统相同的影射表可以使得不必重新另外建一套头文件,同时如果需要的话可以一直在内存中保存eboot,这样内存空间的规划也会相对容易做一些)。 

以上的这些工作做完,就进入windowsCE提供的eboot入口函数main了。而main函数的主要工作都是在BootloaderMain中进行,这个函数位于WINCE420\PUBLIC\COMMON\OAK\DRIVERS\ETHDBG\BLCOMMON\blcommon.c文件中。该目录的文件就是微软提供的eboot框架,尽管这不是实现的部分,也一并分析了吧。这部分的内容一开始就很有意思,第一个执行的语句如下 
if (!KernelRelocate (pTOC)) {  HALT (BLERR_KERNELRELOCATE);   } 
而这个传入的参数却这样定义:ROMHDR * volatile const pTOC = (ROMHDR *)-1;  按照程序的内容来说,这个函数到这里一定是死循环了,可是事实上这个死循环不会得到执行,也就是pTOC = (ROMHDR *)-1并没有真正的起到作用。:) 在pTOC第一次使用前检查了一下pTOC的值,结果如下:pTOC=0x8C04D694。也就是说pTOC在没有被改变之前就已经不再是-1了,而且pTOC是被定义成const的,也没有办法去改变,看样子就只能是编译器的过程中这个指针就已经被动了手脚。而查看eboot.map中该地址所对应的内容居然是bootpart.obj的内容。感觉是无从下手了,这样子让人太费解了。仔细比较eboot.exe和eboot.nb0后发现,eboot.exe通过romimage处理后长度增加了,而且结构上改变了许多,在原.eboot.exe后增加了一系列原来没有内容,pTOC的内容就是属于这部分内容中的一部分。由于牵涉到windowsCE的Image Chain结构,所以无法继续往下分析,这部分的内容就先跳过。以后再回头来看。 

随后在 BootloaderMain中对调试界面进行初始化,由OEMDebugInit完成这个函数的实现是由具体的硬件决定的通常来说为串口的初始化,在此以后就通过该调试界面进行调试信息的发布。 

然后在OEMPlatformInit()中对eboot所要用到的硬件资源进行初始化设备,通常这些会包含:存储设备(FLASH、硬盘等)、传输界面(以太网卡、USB-RNDIS、无线网卡、CF—LAN等等)、系统时钟,为下面将会进行的os镜像传输、os镜像存储、读取等等一系列动作做好准备。 
做好准备以后就可以调用OEMPreDownload ()来进行传输OS的准备了,在这个函数中通常会实现一系列功能,诸如:设备的设置、存储设备的格式化、网卡IP的指定、等等。windowsCE所支持的标准操作则只是两个,一个是跳转、一个是下载、分别对应下载OS镜像和跳入OS的入口点,前面提到的那些功能都是自己的扩展实现。 

下面我们分别来看这两个标准操作的分支:首先是下载的分支,在下载的分支中首先通过OEMReadData来获取在最先收到的标示位也就是被称为魔法数的数据,用以比较确认该传输的内容是否为windowsCE的镜像数据,随后继续进一步获取将接收的数据的效验和,待接收的镜像的数量,镜像起始地址、长度等信息,有了这些个信息,很自然地就是接收镜像了, 

随后检查数据的效验和。下一个镜像的信息的接收,如此往复循环直至所有的镜像信息接收完毕。

简而言之,bootloader流程如下:

Boot Loader按照WinCE启动方式的不同可分为两大类:一类是下载模式,一类是本地启动模式。

下载模式的基本执行过程为:
重定位RAM---初始化调试端口---初始化平台基本设备---打印用户菜单---初始化网络参数---下载OS内核---启动OS

以Eboot为例,启动过程函数调用的顺序和功能如下:
Startup( )-----------------初始化CPU、内存控制器等
KernelRelocate( )-------代码重定位至RAM
OEMDebugInit( )-------初始化调试端口(一般为串口)
OEMPlatformInit( )----初始化板上设备(初始化显示、RTC、OAL与eboot共享参数、打印用户菜单、网卡等)
OEMPreDownload( )---下载前准备(设置设备名、初始化MAC/IP参数)
DownloadImage( )------下载映像文件
OEMLaunch( )-----------启动OS

一般来说,Eboot所涉及的文件主要有:

Startup.s:包括以上提到的Startup( )函数,源代码位于%WINCE\Platform\Common\Src\***...和%WINCE\Platform\***\Src\Bootloader\eboot目录

Main.c: 包括以上提到的OEMDebugInit( )、OEMPlatform( )、OEMPreDownload( )、OEMLaunch( ),源代码位于%WINCE\Platform\***\Src\Bootloader\eboot目录

Blcommon.c:包括以上提到的KernelRelocate( )、DownloadImage( ),源代码位于%WINCE\Public\Common\Oak\Drivers\Ethdbg\Blcommon目录

Eboot下载的过程主要包括:
(1)设备通过Bootme使开发机获取设备IP(DHCP或者指定IP);
(2)开发机通过TFTP协议下载映像到设备上;
(3)  根据需求把映像烧写到Flash中或直接从RAM中启动OS

这里附上一份文档,是在《计算机工程》期刊看到的,很不错。

WinCEBootloader的设计与实现.pdf

你可能感兴趣的:(windows)