我們已知u-boot的終極目的是啟動核心,那麼核心啟動的開始必定是u-boot傳入的引數。
開啟armlinux.c 發現有一行的**為:
thekernel (0, bd->bi_arch_number, bd->bi_boot_params);//帶入三個引數
第乙個引數是0,第二個引數是機器id,第三個引數是引數所存放的位址。
核心啟動時要做的幾個步驟
1.處理u-boot傳入的引數 //arch/arm/kernel/head.s
entry(stext)
msr cpsr_c, #psr_f_bit | psr_i_bit | svc_mode @ 確立cpu是處於svc模式。
@ and irqs disabled
mrc p15, 0, r9, c0, c0 @ get processor id //將c0暫存器的數值傳送到r9暫存器中,獲取cpu的id
bl __lookup_processor_type @ r5=procinfo r9=cpuid //判斷cpu型別,核心支援的cpu是固定的
movs r10, r5 @ invalid processor (r5=0)?
beq __error_p @ yes, error 'p'
bl __lookup_machine_type @ r5=machinfo//判斷單板的型別 如果不能支援 就跳到error裡死迴圈,這裡就處理u-boot傳入的arch_number
movs r8, r5 @ invalid machine (r5=0)?
beq __error_a @ yes, error 'a'
bl __create_page_tables @建立頁表
a.判斷是否支援這個cpu
b.判斷核心是否支援該單板,分析u-boot啟動核心時傳入的機器id
3: .long .
.long __arch_info_begin
.long __arch_info_end
__lookup_machine_type:
adr r3, 3b @r3 = 3b的 address address of r3 = "3: .long" real address
ldmia r3, @r4 = "." virtual address of 3b,r5="__arch_info_begin" r6 = "__arch_info_end"
/* __arch_info_begin = .;
*(.arch.info.init)
__arch_info_end = .;*/
sub r3, r3, r4 @ get offset between virt&phys r3 = r3 - r4
add r5, r5, r3 @ convert virt addresses to //r5 = r5 + r3
add r6, r6, r3 @ physical address space//r6 = r3 + r6
1: ldr r3, [r5, #machinfo_type] @ get machine type
teq r3, r1 @ matches loader number
beq 2f @ found
add r5, r5, #sizeof_machine_desc @ next machine_desc
cmp r5, r6
blo 1b
mov r5, #0 @ unknown machine
2: mov pc, lr
在這裡 出現了.arch.info.init 我們搜尋下 發現在arch.h處有定義
#define machine_start(_type,_name) \
static const struct machine_desc __mach_desc_##_type \
__used \
__attribute__((__section__(".arch.info.init"))) = ;
machine_start(s3c2440, "smdk2440")
/* maintainer: ben dooks */
.phys_io = s3c2410_pa_uart,
.io_pg_offst = (((u32)s3c24xx_va_uart) >> 18) & 0xfffc,
.boot_params = s3c2410_sdram_pa + 0x100, //0x30000100,儲存u-boot傳進的引數
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
machine_end
#define machine_start(_type,_name) \
//由上面兩段**整合後是這樣的
static const struct machine_desc __mach_desc_s3c2440 \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
.nr = mach_type_s3c2440, \
.name = smdk2440,
.phys_io = s3c2410_pa_uart,
.io_pg_offst = (((u32)s3c24xx_va_uart) >> 18) & 0xfffc,
.boot_params = s3c2410_sdram_pa + 0x100,
.init_irq = s3c24xx_init_irq,
.map_io = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
;c.建立頁表
d.使能mmu
e.跳轉到startkernel
//為什麼要建立頁表呢,我們觀察鏈結檔案得位址為(0xc0000000) + 0x00008000; //指定核心位址,但是這位址不對應真實存在的記憶體,所以需要開啟mmu對映位址
核心的啟動流程
/arch/arm/kernel/head.s
start_kernel
setup_arch //解析u-boot傳入的啟動引數
setup_command_line //解析u-boot傳入的啟動引數
parse_early_param
do_early_paramt
從_setup_start到_setup_end;呼叫early函式
unknown_bootoption
obsolete_checksetup
從_setup_start到_setup_end;呼叫非early函式
rest_init();
kernel_init
prepare_namespace();
mount_root();(掛接根檔案系統)
init_post(); //開啟/dev/console 執行應用程式run_init_professor
linux2 6核心啟動流程
計算機在啟動時都是先加電,然後進行硬體檢測並引導作業系統的初始化程式,然後作業系統的初始化程式程負責讀入系統核心並建產系統的執行環境.一這過程相對來說比較復而且與cpu體系結構相關,這裡我們通過linux並以i386的體系結構對這一過程進行較為詳細的說明.一 硬體檢測 當 機器加電後它首先執行bio...
Linux 2 6 核心引導過程分析
本文以x86為例,x86與嵌入式系統的區別在於多了乙個bios轉移到bootloader的過程。linux核心引導的過程包含多個階段,接下來將依次解讀 系統加電時,處理器會執行乙個位於已知位置處的 pc中即我們熟知的bios,它儲存在主機板的快閃儲存器中。bios從0xffff0處開始執行,首先執行...
Linux 2 6 核心引導過程分析
本文以x86為例,x86與嵌入式系統的區別在於多了乙個bios轉移到bootloader的過程。linux核心引導的過程包含多個階段,接下來將依次解讀 系統加電時,處理器會執行乙個位於已知位置處的 pc中即我們熟知的bios,它儲存在主機板的快閃儲存器中。bios從0xffff0處開始執行,首先執行...