从操作系统的角度看,Bootloader的总目标就是正确地调用内核来执行 。
Bootloader的实现依赖于CPU的架构,因此大多数Bootloader都分为Stage1和Stage2两大部分。依赖于CPU架构的代码,比如设备初始化代码等,通常放在Stage1中,并且大都用汇编语言来实现,以达到短小精悍的目的。而Stage2则一般用C语言实现,这样可以实现一些复杂的功能,而且代码会具有更好的可读性和可移植性。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。
由于Bootloader是严重依赖于硬件而实现的,特别是在嵌入式世界。因此,在嵌入式世界里建立一个通用的Bootloader几乎是不可能的。尽管如此,我们仍然可以对Bootloader归纳出一些通用的概念来,以指导用户特定的Bootloader设计与实现。
Bootloader Stage1通常包含以下几个步骤(以执行的先后为顺序):
1.硬件设备初始化
2.为Stage2准备RAM空间。
3.拷贝Stage2到RAM空间。
4.设置好堆栈。
5.跳转到Stage2的C入口。
主要代码如下:
.text
.extern _ld_text_start
.extern _ld_text_and_data_size
///
/// Vector Table ///
///
.globl _start
_start:
b reset
reset:
// Mask All interrupt
ldr r12, =INTERRUPT_CONTROL_BASE
ldr r0, =0x00000000
str r0, [r12, #ICMR]
str r0, [r12, #ICLR]
// Initialize GPIO
bl gpio_init
// Initialize SDRAM
bl init_sdram
// Copy Bootloader from Flash to SDRAM
bl copy_to_ram
// Loading kernel image
ldr r4, =KERNEL_SRAM_BASE
ldr r5, =KERNEL_DRAM_BASE
ldr r6, =KERNEL_MAX_SIZE
add r6, r6, r4
repeat:
ldmia r4!, {r0-r3, r7-r10}
stmia r5!, {r0-r3, r7-r10}
cmp r4, r6
blt repeat
ldr sp, =_ld_stack_address
// Jump to c_main
ldr r0, =c_main
mov pc, r0
die:
b die
================================================================================================================
Bootloader Stage2通常包含以下几个步骤(以执行的先后为顺序):
1.初始化本阶段需要用到的硬件设备。
2.检测系统的内存映射(memery map)。
3.将kernel和根文件系统从Flash上加载到RAM空间。
4.为kernel设置启动参数。
5.调用内核。