嵌入式linux系統主要有兩部分組成:linux內核和linux根文件系統。
而linux內核鏡像不具備自啓動,因爲內核鏡像的起始地址沒有異常向量表,還有內核鏡像的起始函數需要r0,r1,r3這3個寄存器初始化相應的值。所以,linux內核鏡像需要被動加載,而完成此任務的就是bootloader。
bootloader起始可以分爲boot和loader兩部分:
在boot階段完成的任務有:1.初始化CPU、內存
2爲加載bootloader的stage2準備RAM空間
3.拷貝bootloader的stage2代碼到RAM空間
4.設置好堆棧
5.跳轉到stage2的C入口點
在loader階段的任務有:1.初始化本階段要使用的硬件設備
2.將內核映像和根文件系統映像從flash上讀到RAM中,爲內核設置啓動參數
3.加載內核
Uboot啓動分析:
# cd /u-boot-2010.06
#vim arch/arm/cpu/arm920t/u-boot.lds
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
//規定輸出的數據格式: elf 32位的arm指令、小端
OUTPUT_ARCH(arm) //CPU的構架
ENTRY(_start) //入口地址
/*見cpu/srm920t/starts
.global_start
_start:
b reset */
SECTIONS
{
. = 0x00000000; //起始地址,鏈接時被_TEXT_BASE替換
. = ALIGN(4); //四字對齊方式
.text : //指定代碼段
{
arch/arm/cpu/arm920t/start.o (.text) //第一個代碼部分
*(.text) //其他代碼部分
}
. = ALIGN(4);
.rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } //指定只讀數據段
. = ALIGN(4);
.data : { *(.data) } //指定讀寫數據段
. = ALIGN(4);
.got : { *(.got) } //指定got段,got段式是boot自定義的一個段,非標準段
. = .;
__u_boot_cmd_start = .; //把_u_boot_cmd_start賦值爲當前位置,即起始位置
.u_boot_cmd : { *(.u_boot_cmd) } //指定u_boot_cmd段,uboot把所有的uboot命令放在該段
__u_boot_cmd_end = .; //把__u_boot_cmd_end賦值爲當前位置,即結束位置
. = ALIGN(4);
__bss_start = .; //把__bss_start賦值爲當前位置,即bss段的開始位置
.bss (NOLOAD) : { *(.bss) . = ALIGN(4); } //指定bss段
_end = .; //把_end賦值爲當前位置,即bss段的結束位置
}
下一步,找到入口函數arch/arm/cpu/arm920t/start.S,進行CPU的配置。