Bootloader的结构和启动过程
CPU上电后,会在某个地址开始执行,比如MIPS结构的CPU会从0xBFC00000取第一条指令,而ARM结构的CPU则从0x00000000开始,嵌入式开发板中,需要把存储器件ROM或Flash等映射到这个地址。而Bootloader就存在这个地址的开始处,这样一上电后就会从这个地址处执行。Bootloader执行后从板子上的某个固态存储设备上将操作系统OS加载到RAM中运行。(一些功能强大的Bootloader,比如U-boot在正常启动加载后可以延时若干秒(也可以自己设置),等待终端用户按下任意键后便可进入到下载模式;如果在指定的时间内没有按键,U-boot则会启动Linux内核,内核的启动参数可以是默认的或是由U-boot传递给它的)。
**注意:有的CPU在运行Bootloader之前 先运行一段固件(firmware)中固化的boot代码,比如x86结构的CPU就是先运行BIOS中的 固件然后才开始运行硬盘第一个分区中的Bootloader。在大多数的嵌入式系统中并没有固件,Bootloader是上电后运行的第一个代码。**
下面便更细致得说明Bootloader的启动过程:
从固态存储器上启动的Bootloader大多数是分二个阶段来启动的。
**第一个阶段**使用汇编代码来实现,它主要完成一些依赖于CPU体系结构的初始化,比如关看门狗、关中断、初始化RAM、将第二阶段调用的C语言代码复制到RAM(非必须,例如对于NOR Flash等设备可以直接在上面执行,只不过比在RAM上执行效率低),设置CPU的速度和时钟频率(非必需,也可以放在第二阶段),设置好栈,跳转到第二阶段的C语言入口处等;
**第二个阶段**通常用C语言来实现,它主要用来:初始化本阶段要用到的硬件设备、检测系统内存映射(就是确定板上使用了多少内存,他们的地址空间是什么)、将内核映像和根文件系统映像从Flash上复制到内存RAM并且在内存中的某个固定位置为内核设置启动参数Boot parameters(Flash上的内核映像有可能是经过压缩的,那么读到RAM后还要进行解压。对于有自解压功能的内核不需要Bootloader来解压。另外将根文件系统映像复制到RAM是非必须的,这取决于是什么类型的根文件系统,以及内核访问它的方法)、调用内核(内核启动后会挂载根文件系统,所以典型的嵌入式Linux系统的分区结构为Botloader + Boot parameters + Kernel + Root filesystem)。
**从上面的分析可知将内核放到适当的位置后,直接跳到其入口点便可以启动内核,在内核之前需要满足那些条件呢,下面我们来具体分析:**
**CPU寄存器R0、R1和R2值的设置**
由于U-boot在设置完启动参数标记列表后最终是调用theKernel函数来跳转执行linux内核的,uboot调用这个函数(其实就是linux内核)时会直接传递给linux内核3个参数,而这3个参数就是通过寄存器来实现传参的。其中第1个参数固定为0,就放在r0寄存器中,第二个参数为机器类型ID也就是我们常说的机器码,就放在r1寄存器中,第3个参数就是启动参数标记列表在RAM中的首地址,就放在r2寄存器中。
**CPU工作模式的设置**
必须禁止中断(IRQs和FIQs),并且要将CPU设置为SVC模式。
这是因为uboot只是完成硬件初始化,环境参数设置,代码搬运等工作,用不到中断。屏蔽中断是为了避免因为意外中断使得boot失败,毕竟很多外设还没有初始化,对应中断代码也都没有准备好。
那么为什么要将CPU设置为SVC模式呢?我们先简单的来分析一下CPU的7种模式:
中止abt和未定义und模式:
首先可以排除的是,中止abt和未定义und模式,那都是不太正常的模式,此处程序是正常运行的,所以不应该设置CPU为其中任何一种模式,所以可以排除。
快中断fiq和中断irq模式:
其次,对于快中断fiq和中断irq来说,此处uboot初始化的时候,也还没啥中断要处理和能够处理,而且即使是注册了终端服务程序后,能够处理中断,那么这两种模式,也是自动切换过去的,所以,此处也不应该设置为其中任何一种模式。
用户usr模式:
虽然从理论上来说,可以设置CPU为用户usr模式,但是由于此模式无法直接访问很多的硬件资源,而uboot初始化,就必须要去访问这类资源,所以此处可以排除,不能设置为用户usr模式。
系统sys模式 vs 管理svc模式:
首先,sys模式和usr模式相比,所用的寄存器组,都是一样的,但是增加了一些访问一些在usr模式下不能访问的资源。
而svc模式本身就属于特权模式,本身就可以访问那些受控资源,而且,比sys模式还多了些自己模式下的影子寄存器,所以,相对sys模式来说,可以访问资源的能力相同,但是拥有更多的硬件资源。
所以,从理论上来说,虽然可以设置为sys和svc模式的任一种,但是从uboot方面考虑,其要做的事情是初始化系统相关硬件资源,需要获取尽量多的权限,以方便操作硬件,初始化硬件。
从uboot的目的是初始化硬件的角度来说,设置为svc模式,更有利于其工作。
因此,此处将CPU设置为SVC模式。
另外uboot作为一个bootloader来说,最终目的是为了启动Linux的kernel,在做好准备工作(即初始化硬件,准备好kernel和rootfs等)跳转到kernel之前,本身就要满足一些条件,其中一个条件,就是要求CPU处于SVC模式的。
所以,uboot在最初的初始化阶段,就将CPU设置为SVC模式,也是最合适的。
**Cache和MMU的设置**
MMU和数据Cache必须必须关闭,指令Cache可以打开也可以关闭。
由于MMU在上电之初是没有任何作用的,也就是说U-boo第一阶段的汇编代码以及第二阶段的源代码初始化相关外设时访问的都是都是实际地址,MMU起不到任何作用,为了启动之初不影响对程序的启动常关闭MMU。
Cache是位于RAM和CPU内部寄存器之间的一个存储设施,用来加速二者之间的数据传输速度,即用来加快CPU从内存中取出指令的速度。但是在上电后CPU的初始化要比内存RAM快一拍,当CPU初始化完成后需要读取来自内存的数据,若内存还没有准备好那势必会造成异常,系统就挂掉了,因此需要关闭数据Cache,而指令Cache关与不关影响不大。
Bootloader的结构和启动过程的更多相关文章
- Windows Phone-框架结构和启动过程
上一篇文章介绍了Windows Phone的开发环境和一个简单的Windows Phone程序的演示和结构,这一篇文章要深入一点,介绍Windows Phone的框架结构和程序启动的过程. 一 Win ...
- Tomcat服务器顶层结构和启动过程【转】
号外:2016 最流行的是哪一种 Java 应用服务器呢? 通过从部署的 1240 个 JVM 中得到的数据,我们能够确定出现了 862 个容器供应商,或者说是占到了运行环境的 70% 左右.这些容器 ...
- Tomcat结构、启动过程、关键组件简单分析
Tomcat 结构: Tomcat最顶层容器叫Server,代表整个服务器,Server中包含至少一个Service,用于具体提供服务,Serv ...
- Linux学习笔记之Linux目录结构、磁盘命名、启动过程
1.Linux磁盘命名规则 名称的起名规则——/dev/xxyN: 1.Linux下装所有硬件设备的一个目录叫 /dev(devices) 2.Linux没有C盘.D盘.Linux最根上的一个目录叫 ...
- (转)硬盘结构,主引导记录MBR,硬盘分区表DPT,主分区、扩展分区和逻辑分区,电脑启动过程
硬盘结构硬盘有很多盘片组成,每个盘片的每个面都有一个读写磁头.如果有N个盘片.就有2N个面,对应2N个磁头(Heads),从0.1.2开始编号.每个盘片的半径均为固定值R的同心圆再逻辑上形成了一个以电 ...
- Linux内核启动过程概述
版权声明:本文原创,转载需声明作者ID和原文链接地址. Hi!大家好,我是CrazyCatJack.今天给大家带来的是Linux内核启动过程概述.希望能够帮助大家更好的理解Linux内核的启动,并且创 ...
- Linux启动过程详述
http://www.ibm.com/developerworks/cn/linux/kernel/startup/index.html Linux启动第1步:引导内核 Linux启动第2步:内核部分 ...
- 【转载】简述Linux的启动过程
原文:简述Linux的启动过程 本文将简单介绍一下Linux的启动过程,希望对那些安装Linux的过程中遇到了问题的朋友有些帮助 声明:本人没用过UEFI模式和GPT分区格式,所有关于这两部分的内容都 ...
- 浅析嵌入式Linux系统的构成和启动过程
在我们的周围,大量的嵌入式设备都是基于Linux系统来构建的,嵌入式Linux与主机Linux相比有着自己的一些特点,本文就嵌入式Linux系统的构成和启动过程做一些总结. 一.嵌入式Linux系统构 ...
随机推荐
- aix系统下的websphere的静默安装
一:环境 aix5.3,websphere6(ND版本,WebSphereV6.1_for_AIX_64-bit_Support.tar),注意:aix和websphere的版本问题 二:安装 ...
- 解决PJA错误
现场有WAS5.6,均安装在AIX下,且都已经设置PJA,在WAS5上报表正常,但是在WAS6下报表会报错,两个应用下的配置均相同. 反馈的报错日志: [11-4-25 14:20:42:758 ...
- phpAdmin修改密码后拒绝访问
[phpMyadmin没配置正确] 解决方法: 1.打开 phpMyadmin 目录找到config.inc.php文件2.查找到$cfg['Servers'][$i]['password']=''3 ...
- for循环内嵌套finally使用的意外获得
在for循环中有continue和break,无论执行continue还是break finally的逻辑都会执行,原本以为是不执行的 格式 for (int i = 0; i < 3; i ...
- c 字符串替换字符
使用完释放记得内存free(str),防止内存泄露 char * replace (const char *str, const char *src, const char *dst){ const ...
- Centos 使用C++11 编译
今天编译代码,发现使用auto后无法编译,我的当前linux内核版本:(4.7之后即可支持C++11) 这时,在编译末尾加入 -std=c++11 就可以正常编译了.如:
- 机器学习数学知识中令人费解的notation符号注解
$argmin_xf(x), min(f(x))$ $min(f(x))$的意思是函数$f(x)$的最小值 $argmin$的意思是返回使得表达式取得最小值时对应的输入变量值.例如$argmin_xf ...
- 如何利用fiddler篡改发送请求和截取服务器信息
一.断点的两种方式 1.before response:在request请求未到达服务器之前打断 2.after response:在服务器响应之后打断 二.全局打断 1.全局打断就是中断fiddle ...
- ORACLE RAC节点意外重启Node Eviction诊断流程图(11.2+)
- python已写内容中可能的报错及解决办法
理论上我发的每个短文,直接复制放到py里面,python xx.py是可以执行的,不过因为版本,编码什么的问题会有报错,详见这里 报错: SyntaxError: Non-ASCII characte ...