BootLoader
bootloader 的主要任务: 调用内核加载操作系统
bootloader 称为引导加载程序,是嵌入式系统加电启动后执行的第一段代码, 相当于PC机的BIOS;
通过bootloader 这段代码,我们可以初始化硬件设备,建立内存空间映射图,为调用操作系统内核做好准备工作;
系统加电启动流程:
基于arm的嵌入式系统中,系统复位加电后,cpu的程序计数器pc 一般都是从0x0地址处开始 取指令执行,
而在这个地址处安排的通常就是系统的bootloader程序;bootloader严重的依赖于硬件而实现;不同体系结构
的处理器都有不同的bootloader程序;
U-Boot(Universal Bootloader)是一款目前功能较为强大的开源Bootloader程序,它支持多种处理器平台,
包括ARM、MIPS等。
bootloader的操作模式
“启动加载”模式和“下载”模式; 但这两种模式只对程序开发人员有意义;
启动加载模式: 称为“自举”(Autonomous)模式,即bootloader从某个固态存储器中将操作系统加载到RAM中,整个过程没有用户
的介入;它是bootloader的正常工作模式,在嵌入式产品发布后,bootloader必须工作在这个模式下;
在下载模式下,目标机上的Bootloader将通过串口连接或网络连接等通信手段从主机上下载文件。
比如下载内核映像文件和根文件系统映像等;从主机下载的文件通常被bootloader保存到RAM中,然后再被bootloader保存到目标机
的flash类固态存储设备中;这种模式通常在第一次安装内核和根文件系统时被使用,此外以后系统更新也会使用这种工作模式;
工作于下载模式中的bootloader通常都会给它的终端用户提供一个命令行接口,
bootloader的启动步骤(通常可分为两个阶段):
第一阶段: 主要包含依赖于cpu的体系结构;其主要任务是基本硬件设备初始化;这是bootloader一开始就执行的操作,目的是位第二
阶段的执行,以及随后kernel的执行准备好一些基本的硬件环境;
包括以下步骤:屏蔽所有中断,设置cpu的速度和时钟频率,关闭处理器内部指令,数据cache等;
第二阶段:准备包括RAM空间; 为了获得快的执行速度,通常把第二阶段加载到ram中来执行;因此必须为加载bootloader第二阶段
准备好一段可用的RAM空间范围;由于第二阶段通常是C语言执行代码,因此在考虑空间大小时,除了映像文件大小外,还要考虑堆栈
空间,此外空间大小最好是内存页的整数倍;一般而言1M的RAM空间已经足够;最后要确保安排的RAM空间时可读可写的。
第三阶段:拷贝第二阶段到RAM空间中。
第四阶段:设置好堆栈。(堆栈指针的设置时为了执行C语言代码做好准备,这里注意栈顶在高地址,栈时向下生长的)
第五阶段:跳转到第二阶段C代码的入口点;
第2阶段的主要任务:
(1)要使用到的硬件通常包括初始化至少一个串口,以便和终端用户进行I/O输出信息等。
(2)检测系统内存映像,它必须知道 CPU 预留的全部 RAM 地址空间中的哪些 被真正映射到 RAM 地址单元,哪些是处于 "unused" 状态;
(3)将kernel和根文件系统映像从flash上读到RAM空间中;
像 ARM 这样的嵌入式 CPU 通常都是在统一的内存地址空间中寻址 Flash 等固态存储设备的; 从 Flash 上读取数据与从 RAM 单元中
读取数据并没有什么不同。 这一步骤包括两部分内容:规划kernel和根文件系统所占用的内存范围和将它们从flash上进行拷贝。
(4)为kernel设置启动参数。
(5)调用内核。
Bootloader调用Linux kernel的方法是直接跳转到内核的第一条指令处。
在跳转时必须满足下列条件。
• (1)、CPU寄存器的设置:R0为0;R1为机器类型ID(机器类型参见 linux/arch/arm/tools/mach-types目录);R2为启动参数,标记列表在 RAM中的起始基地址。
• (2)、CPU模式:必须禁止中断(IRQs和FIQs);CPU必须设置为SVC模式。
• (3)、Cache 和 MMU 的设置:MMU 必须关闭;指令Cache 可以打开也可以关闭; 数据 Cache 必须关闭。