BootLoader的工作原理和使用方法 (以U-Boot为代表)
gerlengzi
2022年05月04日 21:41

一、  工作原理

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 都包含两种不同的操作模式:“启动加载”模式和“下载”模式:

启动加载(Boot loading)模式:

    启动模式也称为“自主”(Autonomous)模式。也即BootLoader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。这种模式是BootLoader的正常工作模式,因此在嵌入式产品发布的时候,BootLoader显然必须工作在这种模式下。

下载(Downloading)模式:

    在这种模式下,目标机上的BootLoader将通过串口连接或网络连接等通信手段从主机(Host)下载文件,从主机下载的文件通常首先被BootLoader保存到目标机的RAM中,然后再被BootLoader写到目标机上的FLASH类固态存储设备中。BootLoader的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用BootLoader的这种工作模式。工作于这种模式下的 BootLoader 通常都会向它的终端用户提供一个简单的命令行接口。

    U­Boot这样功能强大的BootLoader同时支持这两种工作模式,而且允许用户在这两种工作模式之间进行切换。大多数BootLoader都分为阶段一(stage1)和阶段二(stage2)两大部分,即启动过程可以分为stage1(汇编写的)和stage2(C语言写的):stage1完成初始化硬件,为stage2准备内存空间,并将stage2复制到内存中,设置堆栈,然后跳转到stage2U­boot 也不例外。依赖于 CPU 体系结构的代码(如 CPU 初始化代码等)通常都放在阶段一中且通常用汇编语言实现,而阶段二则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。其中BootLoader的启动过程可以如下所示:

3.  U-Boot的启动流程

Ø  阶段一主要步骤(stage1):

①   定义入口

②   设置异常向量

③   设置 CPU 的模式为 SVC 模式

④   关闭看门狗

⑤   禁用所有中断

⑥   设置以 CPU 的频率

⑦   设置 CP15

⑧   配置内存区控制寄存器

⑨   安装 U-BOOT 使的栈空间

⑩   BSS段清零

⑪   搬移 Nand Flash 代码

⑫   进入 C 代码部分

Ø  阶段二主要步骤(stage2):

①  调用一系列的初始化函数

指定初始函数表:

配置可用的 Flash 区

初始化内存分配函数

nand flash 初始化

初始化环境变量

外围设备初始化

I2C 总线初始化

LCD 初始化

VIDEO 初始化

键盘初始化

系统初始化

②  初始化网络设备,即初始化相关网络设备,填写 IP、MAC 地址等。

③  进入主U-BOOT命令行进入命令循环(即整个boot 的工作循环),接受用户从串口输入的命令,然后进行相应的工作。

二、使用方法

1.       U-Boot命令的使用

信息查询命令:

常用的信息查询命令有三个:bdinfo,print,version。

Ø  bdinfo查看板子信息;

Ø   print查看环境变量;

Ø  version查看uboot的版本号。

环境变量操作命令:

环境变量操作命令常用setenv和saveenv。

内存操作命令:

常用的内存操作命令有:md、nm、mm、mw、cp。

Ø  md 命令用于显示内存值;

Ø  nm 命令用于修改指定地址的内存值;

Ø  mm和nm一样,也是修改指定地址内存值的,但 mm 修改内存值的时候地址会自增;

Ø  mw 用于使用一个指定的数据填充一段内存,数据拷贝命令,将 DRAM 中的数据从一段内存拷贝到另一段内存。

网络操作命令:

主要有三个,ping  nfs  tftp。

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  可以查看分区情况。

FAT 格式文件系统操作命令:

FAT格式文件系统的命令主要有 fatls,fatload。

Ø  fatls 命令用于查询 FAT 格式设备的目录和文件信息;

Ø  fatload 命令将指定的文件读取到 DRAM 中。

boot相关操作:

主要有两个,bootz和boot。

Ø  bootz:启动linux内核和设备树;

Ø  boot:启动 Linux 系统的,并且 boot 会读取环境变量 bootcmd 来启动 Linux 系统;

其他命令:

Ø  reset:复位命令,重启uboot;

Ø  go命令:跳转到指定地址执行应用;

Ø  run 命令:run运行环境变量定义的命令;