Preface
之前也发表过关于《Bootloader启动过程分析》的文章,但是内容表达得比较抽象,大多是文字叙述,所以这里从系统和代码的角度来深入分析bootloader的启动过程。
工具:Source Insight
目标:U-Boot-1.1.6
仅留此分析过程,日后再作补充(纯手打也不容易啊,嘿嘿)。
U-Boot工程结构
学习一个软件,尤其是开源软件,首先应该从分析软件的工程结构开始。一个好的软件有良好的工程结构,对于读者学习和理解软件的架构以及工作流程都有很好的帮助。
U-Boot的源代码布局和Linux类似,使用了按照模块划分的结构,并且充分考虑了体系结构和跨平台问题。
U-Boot源代码目录结构
子目录名 |
作用 |
board | 开发板相关的定义和结构 |
common | 包含U-Boot用到的各种处理函数 |
cpu | 各种不同类型的处理器相关代码 |
doc | U-Boot文档 |
drivers | 常用外部设备驱动程序 |
examples | 存放U-Boot开发代码样例 |
fs | 文件系统有关的代码,包括cramfs、ext2、fat等常见文件系统 |
include | U-Boot用到的头文件 |
lib_arm | ARM体系结构有关的数据定义和操作 |
lib_generic | U-Boot通用的操作函数 |
net | 常用的网络协议,包括bootp、rarp、arp、tftp等 |
post | 上电自检相关代码 |
rtc | 实时钟有关操作 |
tools | U-Boot有关的数据代码 |
U-Boot总体工作流程
与大多数Bootloader类似,U-Boot的启动分成stage1和stage2两个阶段。
stage1使用汇编语言编写,通常与CPU体系紧密相关,如处理器初始化和设备初始化代码等,该阶段在start.S文件中实现。
上图是U-Boot中Stage1工作流程。Stage1的代码都是与平台相关的,使用汇编语言编写占用空间小而且执行速度快。
Stage1负责建立Stage1阶段使用堆栈和代码段,然后复制Stage2阶段的代码到内存。
Stage2阶段一般包括:初始化Flash器件、swim 系统内存映射、初始化网络设备、进入命令循环,接收用户从串口发送的命令然后进行相应的处理。
Stage2使用C语言编写,用于加载操作系统内核,该阶段主要是board.c中是start_armboot()函数实现。下图为U-Boot的Stage1和Stage2在Flash和RAM中的分配。
从上图中可以看出,U-Boot在加载到内存后,使用了操作系统空余的内存空间。
U-Boot启动流程分析
从图中可以看出U-Boot的启动代码分布在start.S、low_level_init.S、board.c和main.c文件中
Start.S是U-Boot整个程序的入口,该文件使用汇编语言编写,不同体系结构的启动代码不同
low_level_init.S是特定开发板的设置代码;
board.c包含开发板底层设备驱动;
main.c是一个与平台无关的代码,U-Boot应用程序的入口在此文件中。
①_start标号
在U-Boot工程中,每种处理器目录下都有一个start.S文件,该文件中有一个_start标号,是整个U-Boot代码的入口点。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|