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