基于嵌入式Linux 的完整系统软件由三个部分组成:系统引导程序、Linux 操作系统内核和文件系统。
系统引导程序 Boot Loader 是系统加电后运行的第一段软件代码,它的作用是加载操作系统或者其他程序到内存中,并将控制权交给它们。
Boot Loader的启动过程
Boot Loader分为单阶段和多阶段两类
多阶段的Boot Loader能提供更为复杂的功能,以及更好的移植性。从固态存储器上启动的Boot Loader大多是两阶段的启动过程。具体分为stage1和stage2。
系统引导程序通常分为两个阶段:
- 由 BIOS 或者 UEFI 完成,它负责检测硬件设备,读取硬盘的主引导记录(MBR)或者 GUID 分区表(GPT),并执行其中的引导代码;
- 由操作系统的引导加载程序完成,它负责读取操作系统的核心文件,设置启动参数,创建启动菜单,或者链载另一个引导加载程序。
换一个说法:
Boot Loader首先完成系统硬件的初始化,包括时钟的设置、存储区的映射等,设置堆栈指针等;
然后把操作系统内核从flash区拷贝到RAM区,并跳转到内核的入口,将系统控制权交给操作系统,在此之后系统的运行和Boot Loader 再无任何关系。
Linux的发行包中不包含Boot Loader,Boot Loader必须由用户自己设计,但用户可以直接使用或参考一些开源的Boot Loader软件工程。
Boot Loader的大小由其设计功能所决定,最小只有几K字节,功能复杂的一般也不超过100K字节。
Linux
系统的开机过程是这样的:从BIOS
开始,进入Boot Loader
,再加载内核系统,进行内核初始化,最后启动初始化进程。以前Linux
的启动一直是采用init
进程的。
Boot Loader的特点
- Boot Loader的实现高度依赖于硬件,包括处理器的体系结构、具体型号、硬件电路板的设计。 Boot Loader中有一部分代码是使用汇编语言设计的,汇编语言是直接和硬件相关的。
- 不存在通用的Boot Loader,但是存在设计Boot Loader的通用的概念和规则,以指导用户对特定的Boot Loader进行设计与实现。
- 宿主主机和目标机之间一般通过串口连接,Boot Loader软件在执行时通常会通过串口来进行I/O操作。
例如:输出打印信息到串口,从串口读取用户控制字符等。
因为不同的硬件不同,和不同硬件一一对应的Boot Loader也不同,所以不存在通用的Boot Loader
Boot Loader的操作模式
大多Boot Loader都有两个操作模式:
- 启动加载(正常使用):即Boot Loader从目标机上的某个固态存储器上将操作系统加载到ram中运行,整个过程没有用户的介入。这是Boot Loader的正常工作模式。
- 下载模式(开发人员用):目标机上的Boot Loader将通过串口或网络连接从主机(host)上下载文件,例如内核映象和根文件系统等。下载的文件首先放在ram中,然后被Boot Loader写到固态存储器中。 Boot Loader的这种模式通常在第一次安装内核与根文件系统时使用。
重点Boot Loader介绍
- LILO:LInux LOader,linux草创时期提出的Boot Loader,现在由John Coffman维护,有详细的文档。在lilo.go.dyndns.org可以获得最新版本。
- GRUB:GRand Unified Boot Loader,是GNU计划的主要Boot Loader。(用的多)
- blob:LART硬件计划采用的Boot Loader。因为它的采用,blob被移植到许多使用arm的系统,使用非常广泛。blob不提供监控程序的能力。
- U-Boot:公认的功能最多、最具弹性以及开发最积极的开放源码Boot Loader,受到各种支持者的支持。U-Boot以PPCBoot和ARMBoot为基础,大约支持100种PPC电路和十几种ARM电路
vivi是由mizi公司为ARM处理器系列设计的一个Boot Loader,目前只支持使用串口和主机通信,所以必须使用一条串口电缆来连接目标板和主机。作用如下:
- 把内核(kernel)从flash复制到RAM,然后启动它
- 初始化硬件
- 下载程序并写入flash(一般通过串口或者网口先把内核下载到RAM中,然后写入到flash)
- 检测目标板(Boot Loader会有一些简单的代码用以测试目标板硬件的好坏)
例:Boot Loader的简单实现
/* Boot Loader, boot.S
上面这5行主要是对不同寄存器的地址进行了命名
*/
.equ WTCON, 0x01d30000
.equ PCONE, 0x01d20028
.equ LOCKTIME, 0x01d8000c
.equ PLLCON, 0x01d80000
.equ CLKCON, 0x01d80004
.globl _start
_start: //程序启动
b reset //程序跳转到标号为reset的地方执行
add pc, pc, #0x0c000000 //这些都是中断向量表
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
add pc, pc, #0x0c000000
//存放在标号MEMORY_CONFIG之下的用于配置内存的13个配置字
MEMORY_CONFIG:
.long 0x11110102
.long 0x600
.long 0x7ffc
.long 0x7ffc
.long 0x7ffc
.long 0x7ffc
.long 0x7ffc
.long 0x18000
.long 0x18000
.long 0x860459
.long 0x10
.long 0x20
.long 0x20
/* 复位地址 */
reset:
/* 关看门狗 */
ldr r0, =WTCON
ldr r1, =0x0
str r1, [r0]
/* 设置端口控制寄存器 Port E ,打开RxD0和TxD0(串口输入输出)功能*/
ldr r1, =PCONE //把PCONE这个寄存器的地址交给r1这个寄存器
ldr r0, =0x25529 // 0x25529就是对Port E寄存器 的配置字
str r0, [r1]
/* 设置系统时钟控制寄存器 */
ldr r1, =LOCKTIME
ldrb r0, =0xfff
strb r0, [r1]
ldr r1, =PLLCON
ldr r0, =0x78061
str r0, [r1]
ldr r1,=CLKCON
ldr r0, =0x7ff8
str r0, [r1]
/* 设置存储器 */
memsetup:
ldr r0, =MEMORY_CONFIG
ldmia r0, {r1-r13}
ldr r0, =0x01c80000
stmia r0, {r1-r13}
/* 拷贝Flash地址0x10000内核到RAM地址0xc300000中 */
ldr r0, =0x10000
ldr r1, =0xc300000
add r2, r0, #(704 * 1024)
copy_kernel:
ldmia r0!, {r3-r10}
stmia r1!, {r3-r10}
cmp r0, r2
ble copy_kernel
/* 跳转到RAM中执行内核 */
ldr r0, =0xc300000
mov pc, r0
常见的操作系统引导加载程序有 LILO,GRUB,SYSLINUX,Windows Boot Manager 等。
它们各有优缺点,可以根据不同的需求和场景选择合适的引导加载程序。一般来说,引导加载程序需要支持多种文件系统,能够识别不同的操作系统,提供友好的用户界面,支持安全启动等功能。
如果您想了解更多关于系统引导程序 Boot Loader 的信息,您可以参考以下的网页:
(1) 8.8. 配置引导加载器(Bootloader) - Debian. https://www.debian.org/doc/manuals/debian-handbook/sect.config-bootloader.zh-cn.html.
(2) 超详细分析Bootloader到内核的启动流程(万字长文) - 知乎. https://zhuanlan.zhihu.com/p/337507908.
超详细分析Bootloader到内核的启动流程(万字长文) - 知乎 (zhihu.com)
(3) 引导加载程序(BootLoader)_引导程序-CSDN博客. https://bing.com/search?q=%e7%b3%bb%e7%bb%9f%e5%bc%95%e5%af%bc%e7%a8%8b%e5%ba%8f+Boot+Loader.
(4) 引导加载程序(BootLoader)_引导程序-CSDN博客. https://blog.csdn.net/sinat_31608641/article/details/109981978.
(5) Bootloader开发:初识Bootloader - 知乎 - 知乎专栏. https://zhuanlan.zhihu.com/p/556181275.
(6) [小知识]Linux启动加载器介绍 – 深度科技社区 - Deepin. https://www.deepin.org/zh/linux-bootloaders/.