一、 工作原理
1. BootLoader和U-boot的概述
在说BootLoader的工作原理和使用方法之前,我们先了解一些有关BootLoader和U-boot的一些概念和知识。对于计算机系统来说,从开机上电到操作系统启动需要一个引导过程。而在嵌入式linux操作系统中的引导程序,就叫做BootLoader。它是一段汇编代码,它的主要运行任务就是将内核映像从硬盘上读到RAM中,然后跳转到内核的入口点去运行,即开始启动操作系统。从功能上看,它就是在操作系统内核和用户应用程序运行之前运行的一段小程序。通过这段小程序可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核或用户应用程序准备好正确的环境。所以我们的linux系统一上电就要执行BootLoader来初始化系统。系统加电或复位后,所有CPU都会从某个地址开始执行,具体的地址值是由处理器设计决定的,比如,基于ARM7TDMI core的CPU在复位时通常都是从地址0x00000000取它的第一条指令。并且BootLoader的网络启动方式如下图所示:

U-boot(universal bootloader)是一种可以用于多种嵌入式CPU的BootLoader程序,也就是说,U-boot是bootloader的一个子集,U-boot的核心作用就是启动操作系统内核,U-boot的本质就是一段裸机程序。U-Boot支持的处理器架构包括PowerPC、ARM、MIPS、x86,它的功能强大,涵盖了绝大部分处理器架构,提供了大量的外设驱动,支持多个文件系统,附带调试、脚本和引导等工具。并且U-Boot的可配置性非常的强,它所支持的命令也可以通过配置来增减。U-Boot的命令主要包括以下几类:信息类命令、环境变量类命令、存储器命令、Flash专用命令、载类命令、启动命令和Cache命令。
U-Boot刚开始被放到flash中,板子上电后,会自动把其中的一部分代 码拷到内存中执行,这部分代码负责把剩余的U-Boot代码拷到内存中,然 后U-Boot代码再把kernel部分代码也拷到内存中,并且启动,内核启动后, 挂着根文件系统,执行应用程序。U-boot用来初始化最基础的硬件外设,如 系统时钟频率、FLASH、eMMC、DDR等,为LINUX kernel的运行提供一个基 础的硬件环境,然后经历“从外部存储中读取kerner→解压缩到内存→跳转 到kernel_start函数”的过程,从而完成LINUX内核的引导,类似于windows 系统安装光盘。U-Boot的功能如下图所示:

2. BootLoader 的两种不同的操作模式
大多数 BootLoader 都包含两种不同的操作模式:“启动加载”模式和“下载”模式:
l 启动加载(Boot loading)模式:
启动模式也称为“自主”(Autonomous)模式。也即BootLoader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。这种模式是BootLoader的正常工作模式,因此在嵌入式产品发布的时候,BootLoader显然必须工作在这种模式下。
l 下载(Downloading)模式:
在这种模式下,目标机上的BootLoader将通过串口连接或网络连接等通信手段从主机(Host)下载文件,从主机下载的文件通常首先被BootLoader保存到目标机的RAM中,然后再被BootLoader写到目标机上的FLASH类固态存储设备中。BootLoader的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用BootLoader的这种工作模式。工作于这种模式下的 BootLoader 通常都会向它的终端用户提供一个简单的命令行接口。
UBoot这样功能强大的BootLoader同时支持这两种工作模式,而且允许用户在这两种工作模式之间进行切换。大多数BootLoader都分为阶段一(stage1)和阶段二(stage2)两大部分,即启动过程可以分为stage1(汇编写的)和stage2(C语言写的):stage1完成初始化硬件,为stage2准备内存空间,并将stage2复制到内存中,设置堆栈,然后跳转到stage2。Uboot 也不例外。依赖于 CPU 体系结构的代码(如 CPU 初始化代码等)通常都放在阶段一中且通常用汇编语言实现,而阶段二则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。其中BootLoader的启动过程可以如下所示:

3. U-Boot的启动流程
Ø 阶段一主要步骤(stage1):
① 定义入口
② 设置异常向量
③ 设置 CPU 的模式为 SVC 模式
④ 关闭看门狗
⑤ 禁用所有中断
⑥ 设置以 CPU 的频率
⑦ 设置 CP15
⑧ 配置内存区控制寄存器
⑨ 安装 U-BOOT 使的栈空间
⑩ BSS段清零
⑪ 搬移 Nand Flash 代码
⑫ 进入 C 代码部分
Ø 阶段二主要步骤(stage2):
① 调用一系列的初始化函数
u 指定初始函数表:
u 配置可用的 Flash 区
u 初始化内存分配函数
u nand flash 初始化
u 初始化环境变量
u 外围设备初始化
u I2C 总线初始化
u LCD 初始化
u VIDEO 初始化
u 键盘初始化
u 系统初始化
② 初始化网络设备,即初始化相关网络设备,填写 IP、MAC 地址等。
③ 进入主U-BOOT命令行进入命令循环(即整个boot 的工作循环),接受用户从串口输入的命令,然后进行相应的工作。
二、使用方法
1. U-Boot命令的使用
l 信息查询命令:
常用的信息查询命令有三个:bdinfo,print,version。
Ø bdinfo查看板子信息;
Ø print查看环境变量;
Ø version查看uboot的版本号。
l 环境变量操作命令:
环境变量操作命令常用setenv和saveenv。
l 内存操作命令:
常用的内存操作命令有:md、nm、mm、mw、cp。
Ø md 命令用于显示内存值;
Ø nm 命令用于修改指定地址的内存值;
Ø mm和nm一样,也是修改指定地址内存值的,但 mm 修改内存值的时候地址会自增;
Ø mw 用于使用一个指定的数据填充一段内存,数据拷贝命令,将 DRAM 中的数据从一段内存拷贝到另一段内存。
l 网络操作命令:
主要有三个,ping nfs tftp。
l EMMC和SD卡命令:
U-Boot支持 EMMC 和 SD 卡,因此也要提供 EMMC 和 SD 卡的操作命令。主要有mmc info,mmc read,mmc write,mmc dev,mmc list,mmc rescan ,mmc part。
Ø mmc info用于查看当前mmc设备的信息;
Ø mmc rescan 用于扫描当前开发板上所有的MMC设备(在命令行里输入没有输出,猜测可以返回是否存在mmc设备);
Ø mmc list 查看总共有几个mmc设备;
Ø mmc dev 切换mmc设备和分区;
Ø mmc part 可以查看分区情况。
l FAT 格式文件系统操作命令:
FAT格式文件系统的命令主要有 fatls,fatload。
Ø fatls 命令用于查询 FAT 格式设备的目录和文件信息;
Ø fatload 命令将指定的文件读取到 DRAM 中。
l boot相关操作:
主要有两个,bootz和boot。
Ø bootz:启动linux内核和设备树;
Ø boot:启动 Linux 系统的,并且 boot 会读取环境变量 bootcmd 来启动 Linux 系统;
l 其他命令:
Ø reset:复位命令,重启uboot;
Ø go命令:跳转到指定地址执行应用;
Ø run 命令:run运行环境变量定义的命令;