Eboot启动代码分析

news/2024/7/24 14:29:57 标签: 代码分析, 编译器, 存储, wince, 汇编, os

启动代码通常都是用处理器相应的汇编代码写成,比较晦涩,但是却包含了很多与平台相关的信息,对初始化代码进行分析有利于对平台的理解。本文将对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


http://www.niftyadmin.cn/n/1516553.html

相关文章

WinCE中中断的处理过程(驱动开发人员角度)

中断是硬件与软件打交道的重要方法,因此,大多数驱动程序都涉及到对中断的处理,本文就驱动程序的开发人员以及BSP的开发人员的角度,来谈谈Windows CE中中断的处理过程。 如果一个驱动程序要处理一个中断,那么驱动程序需…

WinCE资源链接

http://blog.csdn.net/constantine/------------不错的博客,一些原创值得借鉴。 http://blog.csdn.net/yeyueyeyue/archive/2006/12.aspx----------此人的博客虽然不在更新,但是也比较有价值。 http://yzcyn.blog.163.com/blog/----------2440跑wince6…

wince5.0中断分析--精辟

原帖地址http://topic.csdn.net/u/20071008/11/D54DF4A6-09EF-4D7F-AADB-2F60FF3824FC.html 1 WinCE中第一次对中断的处理是在OAL的OEMInit()中,该函数调用OALIntrInit()完成对中断的初始化. 2 OALIntrInit()对中断的初始化做了如下工作: 2.1 通过配置IPR0-IPR33设置中断优…

SQL数据库表连接图文详解

sql数据库表连接,主要分为:内连接、外连接(左连接、右连接 、全连接)、交叉连接,今天统一整合一下,看看他们的区别。 首先建表填充值。 学生表:student(id,姓名,年龄,性别…

wince5.0内核的启动流程(MIPS为例)

本文简单描述一下wince5.0内核的启动流程,以mips cpu为例。msdn有一篇文章叫做Microsoft Windows CE 5.0 Board support Package,Boot Loader,and Kernel Startup Sequence非常不错,可以参考。 1. startup.首先,内核最先执行的代码位于oal当…

超全 IntelliJ Idea 快捷键

CtrlShift Enter,语句完成 “!”,否定完成,输入表达式时按 “!”键 CtrlE,最近的文件 CtrlShiftE,最近更改的文件 ShiftClick,可以关闭文件 Ctrl[ OR ],可以跑到大括号的…

Hdu-1166 敌兵布阵【线段树(单点更新)】

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid1166 解题思路&#xff1a; 线段树的入门题&#xff0c;可以用谷歌搜索线段树或者segment tree&#xff0c;理解后就可以了。 我采用的是静态建树。 代码如下&#xff1a; #include<cstdio>#define ls…

CompletionService 创建多线程,并返回全部线程处理结束后的结果

创建多线程&#xff0c;并返回全部线程处理结束后的结果int cacheThreadCount10;//线程数ExecutorService cacheThreadPool Executors.newCachedThreadPool();//线程池 CompletionService<T> completionService new ExecutorCompletionService<T>(cacheThreadPoo…