您的位置:首页 > 其它

Bootloader分析

2011-07-03 23:12 225 查看
Bootloader 是引导程序,在PC上用于引导Linux的是LILO、GRUB,在嵌入式系统中,Bootloader就是在操作系统内核运行之前运行的一段小程序。
通过这段小程序,可以初始化硬件设备、建立内存空间的映射图,使系统的软硬件环境处于合适的状态,为最终调用系统内核做好准备

Bootloader依赖于硬件而实现,每种不同的CPU体系结构都有不同的Bootloader,有些Bootloader也支持多种体系结构的CPU,如U-Boot
<1>Bootloader下载安装
一般来说CPU复位后都会从固定地址开始执行程序,不过都需要把Bootloader下载到系统最初开始执行的地址对应的固态存储器内。这个往往利用到JTAG接口
<2>Bootloader控制方法
Bootloader在目标机运行起来后,需要与Bootloader进行交互控制,此时一般会利用串口来进行I/O
<3>Bootloader的操作模式
大多数Bootloader包含两种不同的操作模式:“启动加载”模式 和“下载”模式
启动加载模式: 该模式下Bootloader自动加载操作系统并将控制权交给操作系统,整个过程没有人工干预
下载模式:该模式下药提供存储器分析管理、固态存储器擦除和写入、能下载内核、文件系统映像到存储器

Bootloader主要任务
由于系统在Flash中的访问速度大大慢于RAM,因此大部分系统都是加载到RAM中来执行的,从操作系统的角度来看,Bootloader的目标是正确地调用内核来执行
大多数Bootloader分为stage1 和 stage2两大部分,依赖于CPU体系结构的代码,如设备初始化代码等,通常都放在stage1中,通常是汇编语言实现
stage2通常用C语言来实现,这样既可以实现复杂的功能,代码又具有良好的可读性和可移植性

Bootloader的 stage1:
1、硬件设备初始化
2、为加载Bootloader的stage2准备RAM空间
3、拷贝Bootloader的stage2到RAM空间中
4、设置好堆栈
5、跳转到stage2的C入口处

Bootloader的stage2:
1、初始化本阶段要使用到的硬件设备
2、检测系统内存映射
3、将kernel 和根文件系统映像从flash上读到RAM空间中
4、为内核设置启动参数
5、调用内核

Blob源码文件结构:



根目录下有一个Configure.in文件, configure文件是由 命令autoconf 根据 configure.in文件自动生成
分析Blob实现原理,整个Blob的编译肯定需要在Makefile控制下进行,而Makefile是由 automake命令根据Makefile.am来生成 Makefile.in
最终由 configure 把 makefile.in变成最终的Makefile

终上分析,我们应该要先从Makefile.am开始入手,在源码的所有目录下都有一个Makefile.am文件,最重要的是src/Blob目录下的Makefile.am

<1>打开 src/Blob下的Makefile.am,可以清楚发现Blob分为了两个阶段:
# --- Blob frist stage loader ------------------------------
. . .
Blob_elf32_SOURCES = \
start.S \
testmem.S

从上面可以看出,src/Blob目录下的start.S是整个Blob的入口,从start.S开始跟踪程序
<2> start.S的分析
. . .
.globl _start
_start:
b reset
. . . . . .
该程序中出现指令 b reset, reset标号在 src/Blob/xlli/mainstone 的 start.s 文件中找到
<3> start.s文件分析
.include "xlli_Bulverde_defs.inc" @ Bulverde specific include file
.include "xlli_Mainstone_defs.inc" @ Mainstone specific include file
. . .
.globl reset
reset:
. . .
bl normal_boot
. . .
程序在 start.s 中开始 调用 src/Blog/xlli/mainstone目录里的xlli_LowLev_Init.s里的各个功能模块对系统进行初始化,start.s的执行顺序如下
1、检查状态信息
2、调用xlli_LowLev_Init.s模块进行以下几部分操作
【1】读取板载配置信息
【2】初始化GPIO
【3】初始化时钟系统
【4】初始化电源及内部SRAM
【5】初始化Memory控制器
【6】初始化Memory时钟速率
【7】初始化实时时钟
3、跳回到 start.S的normal_boot标号处
<4>start.S从normal_boot标号后,调用testmem.s的testram模块,对Blob起始地址1MRAM空间进行检查(写入0xaa,0x55,然后读出检查),
检查结束后就把blob第二阶段代码复制进内存空间,接下来跳转到RAM中Blob的其实地址BLOB_START处,执行第二阶段的任务

<5> 分析第二阶段前,先说明连接程序入口点的概念,设置该入口点有以下几种方法,优先级从高到低,高优先级覆盖低优先级
【1】用命令行ld选项 -e指定
【2】脚本语言中使用ENTRY(_start)指定
【3】程序中出现的start符号指定
【4】.text段的起始地址指定
【5】物理地址0x0

链接器是如何进行程序链接的,在src/Blob下的 rest-ld-script.in文件中有介绍,具体的看该源代码,以下是部分代码
. . .
OUTPUT_ARCH(arm)
ENTRY(_trampoline)
. . .
从上面可以看出 _trampoline是 Blob stage2的入口,可以从同一目录下的trampoline.S找到该标号
<6>trampoline.S的分析
.text
.globl _trampoline
_trampoline:
. . .
bl main
b _trampoline
. . .
该程序首先清除BSS段(该段存放着未初始化变量),然后CPU跳转到main()函数中执行,trampoline(弹簧床的意思),会一直执行main()函数
<7> main函数的分析
main函数主要功能有 初始化串口和网络,加载内核镜像文件,在BLOB命令行模式下实现用户交互,具体包括:
【1】初始化Flash
【2】设置网络IP
【3】初始化串口
【4】初始化icache
【5】初始化LED
【6】初始化网络设备
【7】准备BLOB命令
【8】初始化Flash Block Table;
【9】初始化 Flash Partition Table
【10】装载内核镜像文件
【11】打印基本的欢迎信息,等待用户终端,进入BLOB命令行或直接启动Linux kernel

其中main中要进行说明的是 init_subsystems()函数,该函数实际上是通过.initlist段来调用所有的初始化程序,具体的函数可查阅资料。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: