Eboot启动代码分析

启动代码通常都是用处理器相应的汇编代码写成,比较晦涩,但是却包含了很多与平台相关的信息,对初始化代码进行分析有利于对平台的理解。本文将对Eboot的初始化代码进行分析,主要包含从Reset到进入C的main开始。
mov     r0, #0x48000000         ; Memory controller base physical addr.
    add     r0, r0, #0x4            ; Add offset of MDREFR
 
    mov     r1, #0x03800000        
    orr     r1, r1, #0x000FF000     ; VALUE
 
str     r1, [r0]                ; STORE
对MDREFR初始化为0x38ff000,使得所有的SDCLK自由运行,禁止自我刷新,不允许自动掉电,SDCLK以时钟频率运行,允许SDCLK信号,允许SDCKE
    mov     r0, #0xA0000000         ; SDRAM ADDRESS
    ldr     r1, [r0]                ; CAUSES the first row refresh to all partitions
   
    ldr     r1, [r0]                ; CAUSES the second row refresh to all partitions
不大懂这是什么意思,哪位知道麻烦通知一声
 
    mov     r4, #0x40000000         ; Main address section
    orr     r4, r4, #0x00F00000     ; Rest of address
    ;
    ; set the immediate sleep mode on batt/vdd fault
    mov     r3, #3                       ; force Imprecise Data Abort on Fault
    str     r3, [r4]
 配置PMCR寄存器的IDEA位,使得电池不足时产生一个data abort中断而不是直接进入sleep模式。
    mov     r2, #0x2000             ; 8k loop
 
EARLY_REFRESH_LOOP
    ldr     r1, [r0]                ; CAUSES a row refresh to all partitions
   
    subs    r2, r2, #0x1           
    bpl     EARLY_REFRESH_LOOP      ; while >= 0
然后循环对存储器进行读操作,我也不知道为什么要这么做
 bl PREINIT
做一些初始化前的准备工作,主要是关闭MMU和CACHE,然后获得reset的原因
主要有三个,从sleep中唤醒,或者是被GPIO的RESET或者就是直接的RESET
然后,对于各种不同的情况,就有不同的初始化过程
这些步骤大同小异,但是最后,一定是b INITMMU

INITMMU是内核和EBoot公用的,如果是和内核链接,那么INITMMU仅仅是把OEMAddressTable地址装载到寄存器中,然后就调用NK的kernelstart了,如果是做EBOOT,则 INITMMU是将MMU启动,然后把boot代码搬运到内存当中。
INITMMU的最后通过bl     main 来跳转到C的main函数

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


以上的这些工作做完,就进入windowsCE提供的eboot入口函数了。 也就是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的镜像数据,随后继续进一步获取将接收的数据的效验和,待接收的镜像的数量,镜像起始地址、长度等信息,有了这些个信息,很自然地就是接收镜像了,


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

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yeyueyeyue/archive/2006/12/11/1438266.aspx

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值