引导程序再认识
在32位以上的现代计算机里,bootloader,中文叫【引导程序】,是一支将计算机从【开机重置态】或者叫【物理裸机态】过渡到【逻辑虚拟机态】的程序。这个引导过程叫Booting。所谓【物理裸机态】指机器开机时最基本的功能状态,它是机器可用的基本保证,由厂商定义和提供实现。【物理裸机态】可以理解为物理态,而【逻辑虚拟机态】则是逻辑态,逻辑态有一些的标准,比如32位处理器的保护模式。计算机的逻辑态是现代计算机应用的客观需要,比如桌面GUI应用、多进程、互联网等,但由于成本、硬件局限等原因,目前的计算机还不能设计成开机就达到逻辑态的能力要求。bootloader在一段时间内仍在计算机应用中担当重要角色。
物理祼机态
【物理裸机态】(下称裸机态)的定义依赖于处理器的体系。虽然各体系会有差导,但Booting过程有一些共同点,例如引导的起点,引导的最小代码和最小数据,这些数据和代码是开机或重置时立即可用的。至于引导起点位于何处,最小代码和最小数据用途则根据体系设计而不同。比如很大一部分的机器的最小引导代码是用来引导【功能更强的引导程序】,而不是直接过渡到逻辑态。功能包括访问大容量RAM,支持读写闪存、支持其它访问高级输入输出设备(比如USB),支持访问逻辑文件系统等。
以下是【处理器体系结构】对boot suite 的影响的例子 To illustrate the effects of the processor family on the boot suite, consider the following: A bootloader for a device designed around the StrongARM processor has to know whether it's booting the system or waking it up from sleep, because the processor starts execution from the top of its address space (the bootloader) in both cases. The bootloader has to pass control to the kernel code that restores the system state if it's waking up from sleep or load the kernel from the boot device if the system is starting from reset. An x86 bootloader might need to switch to protected mode to load a kernel bigger than the 1MB real-mode limit. Embedded systems not based on x86 platforms cannot avail the services of a legacy BIOS. So, if you want your embedded device to boot, for example, from an external USB device, you have to build USB capabilities into your bootloader. Even when two platforms are based on similar processor cores, the bootloader architecture may differ based on the SoC. For example, consider two ARM-based devices, the Compaq iPAQ H3900 PDA and the Darwin Jukebox. The former is built around the Intel PXA250 controller chip, which has an XScale CPU based on an ARMv5 core, and the latter is designed using the Cirrus Logic EP7312 controller that uses an ARMv3 core. Whereas XScale supports JTAG (named after the Joint Test Action Group, which developed this hardware-assisted debugging standard) to load a bootloader onto flash, the EP7312 has a bootstrap mode to accomplish the same task.
逻辑虚拟机态
逻辑虚拟机态(下称虚拟机态)的定义更多的依赖于操作系统。系统的虚拟机态是硬件体系相关,比较处理器体系、载板以及系统输入输出模块等;更是操作系统体系相关的,不同的OS下的【虚拟机态】定义有出入。不过还是有一些通用的定义部分,比如前面提到的处理器保护模式的开启、虚拟内存功能的开启。
引导过程
bootloader
一般理解下的引导程序,比如NTLDR,GRUB,只工作到把操作系统内核镜像载入到RAM,如下的第④步,而操作系统还没有开始执行,此时的机器还没有进入这里所定义的【逻辑态】——开启处理器保护模式、开启虚拟内存功能等。所以bootloader具体指代什么取决于bootloader工作起点与终点。本文所指的【引导过程】指从裸机态到虚拟机态全程,包括了内核内对系统作进一步初始化的一段。而bootloader只是其中的第③步。
【引导过程】: ① 裸机态→ ② 固件载入bootloader→③ bootloader载入kernel → ④kernel→ ⑤虚拟机态
引导内容
Booting过程的具体内容可以理解为对【系统】各个部件进行初始化。这个过程一般不是一蹴而就的,由以上的【引导过程】可知,一般都分为若干子阶段,例如在PC里,有BIOS和NTLDR或GRUB两段,再加上kernel一段。
对booting过程划分阶段很重要,因为不同的软硬体系的计算机的booting过程区别很大,也就是booting过程中初始化的内容多种多样的,但是对booting过程划分阶段后可以找到一些规律性的东西,第一,后一阶段的【系统】比前一阶段的更复杂,更高级;第二,前一阶段的计算职责(初始化的内容)是对后一阶段计算搭建环境。所以要理解【booting过程中初始化的内容】必须划清子系统边界,对这些【子系统】有一个清楚的定义,并且需【厘清这些子系统的有机组成元素】。关于更多的有关【系统初始化】相关的系统论的内容看这里《程序及程序员的责任》。
bootloader其它功能职责
bootloader主要职责以外还会负责一些特殊的任务,比如硬件诊断。这类特殊任务在系统论称为【元运算】,它保证计算机可用性,而与之相对的,bootloader各阶段内的的任务称为【体运算】。
bootloader 的一些基本职责和特定功能职责 At the minimum, a bootloader is responsible for processor- and board-specific initializations, loading a kernel and an optional initial ramdisk into memory and passing control to the kernel. In addition, a bootloader might be in charge of providing BIOS services, performing POST, supporting firmware downloads to the target, and passing memory layout and configuration information to the kernel. On embedded devices that use encrypted firmware images for security reasons, bootloaders may have the task of decrypting firmware. Some bootloaders support a debug monitor to load and debug stand-alone code on to the target device. You may also decide to build a failure-recovery mechanism into your bootloader to recoup from kernel corruption on the field.
booting vs. bootstrap
我们要严格区分两个过程概念——引导(booting)与自举(bootstrap),这两个概念在很多场合是等同的,但在这里,bootstrap是指处于开发阶段的引导过程。在PC里,这个过程的例子是升级BIOS,在嵌入式系统是安装系统bootloader。
下面我们以使用【Cirrus Logic EP7211】控制器核心的嵌入系统为例子理解一下bootstrap。
EP7211被设计为两种工作模式——自举模式(bootstrap mode)和普通操作模式(normal operation mode)。在自举模式下,EP7211会读取它内置的128字节记忆体里的最小引导代码。这部分最小代码通过串口下载【下一阶段的引导代码镜像】——称为bootstraper,到容量为2K的板载RAM内,然后跳转到那里,由bootstraper进一步将bootloader下载入闪存。 因此,EP7211的bootstrap必须设计成三阶段的体系结构,每一阶段都位于不同的地址上:
- 第一阶段是处理器的固件部分,大小为128-byte;
- 第二阶段是【能读写闪存】的bootstaper,位于RAM内,大小可达2KB;
- 第三阶段是功能更强的真正bootloader,位于系统闪存内。
可以说,bootstrap 是一次性的。尔后开机时,位于闪存内的bootloader会在处理器工作在普通操作模式下第一时间控制着机器。
为什么分三段? 其实完全可以只做成两段,由处理器内置功能直接下载bootloader镜像到闪存中的,但那样设计会增加处理器开发成本,也降低处理器本身的灵活性。
很多嵌入式处理器并不支持【自举操作模式】,它们是通过一个称为JTAG接口把bootloader写入闪存的。也有一些嵌入式处理既支持自举操作模式,也支持JTAG,例如基于AMR9核心的Freescale i.MX21 。
当bootloader 被安装入闪存后,它不只可引导系统,还可带有升级自身和其它固件组件(内核和根文件系统)的功能,bootloader可以通过UART、USB或Ethernet与开发主机进行通信来执行这些操作。