uboot啓動zImage(go)和uImage(bootm)分析

1.之間差異。
bootm 加載linux鏡像是加載uIamge,uIamge是由mkimage製作而來,和zIamge的差異是uIamge是zIamge壓縮過的,bootm需要先對uIamge解壓,解壓地址爲內核入口地址。當解壓完成時uIamge和zIamge 幾乎是相同的,具體差異可以論述。uboot目前只能支持uImage啓動,不支持zImage啓動
2.bootm解壓過程
---------------------------------------------------------------------------
## Booting image at 08808000 ...
Image Name: Linux-2.6.14.7
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 989172 Bytes = 966 kB
Load Address: 08008000
Entry Point: 08008000
Verifying Checksum ... OK
OK uboot bootm命令對uIamge的解壓操作
---------------------------------------------------------------------------
Starting kernel ...
傳遞內核參數將控制權交給arch/arm/boot/compressed]head.S
----------------------------------------------------------------------------
如mx1ADS班子內存的起始地址爲0x0800_0000,通過tftp 下載到0x0800_8000 +offset ,offset大於0x80_0000,即tftp 0x0880_8000 然後bootm 0x0880_8000 即
將0x0880_8000處的uIamge解壓,解壓地址即爲mkimage 設置的kernel入口地址0x0800_8000。
2.bootm內核啓動分析
通過分析uboot把控制權交給kernel的瞬間,我們可以知道bootm啓動linux內核,它究竟做了哪些工作。
具體源碼在uboot1.16 lib_arm/Armlinux.c do_bootm_linux(),大家有興趣可以看下源碼,這裏不仔細分析了,網上資料超多。
void (*theKernel)(int zero, int arch, uint params) 通過對這個函數指針的操作實現控制權從uboot到linux的交接。
該函數可以等價於set pc=0x0800_8000 ,r0=0 ,r1=0xA0(mx1ads 芯片的id),r2=0x08000100(bootargs參數基址)。
我通過仿真器,設置了一個指令斷點在0x0800_8000,可以看到該瞬間uboot做的操作。

>BKM>dr //查看當前時刻通用寄存器值
R00 = 00000000 R01 = 000000A0 R02 = 08000100 R03 = 08008000
R04 = 00000000 R05 = 08000124 R06 = 083DC0A9 R07 = 0841BC9C
R08 = 083DBFDC R09 = 083E0260 R10(SL) = 00000000 R11(FP) = 00000002
R12(IP) = 083DBFC0 R13(SP) = 083DBD44 R14(LR) = 08413984 PC = 08008000
CPSR = 600000D3 SPSR = B00000FF

>BKM>di 0x08008000 // 反彙編該地址區域代碼
08008000: mov r0,r0
08008004: mov r0,r0
08008008: mov r0,r0
0800800c: mov r0,r0
08008010: mov r0,r0
08008014: mov r0,r0
08008018: mov r0,r0
0800801c: mov r0,r0
08008020: b 0x8008030
08008024: .long 0x16F2818
08008028: andeq r0,r0,r0
0800802c: streqd r1,[pc],-r4
08008030: mov r7,r1
08008034: mov r8,#0
08008038: mrs r2,cpsr
0800803c: tst r2,#3
08008040: bne 0x800804C
08008044: mov r0,#0x17
08008048: swi 0x123456
0800804c: mrs r2,cpsr
08008050: orr r2,r2,#0xC0
08008054: msr cpsr_c,r2
08008058: andeq r0,r0,r0
0800805c: andeq r0,r0,r0
08008060: add r0,pc,#0xC8
08008064: ldmia r0,{r1,r2,r3,r4,r5,r6,r12,r13}
08008068: sub r0,r0,r1
0800806c: beq 0x800809C

>BKM>dml 0x08000100 0x50 //uboot bootargs
08000100: 00000005 54410001 00000000 00000000 ....TA..........
08000110: 00000000 00000004 54410002 04000000 ........TA......
08000120: 08000000 0000000F 54410009 736E6F63 ........TA..snoc
08000130: 3D656C6F 53797474 2C30584D 32353131 =eloSytt,0XM2511
08000140: 386E3030 3D706920 746F6F62 6F722070 8n00=pi toobor p
08000150: 2F3D746F 2F766564 0073666E 00000000 /=to/ved.sfn....
08000160: 00000000 00000000 00000000 00000000 ................
通過仿真器可以很清晰的看到bootm先後完成了2部分工作。大家可以分析bootm源碼
1.set bootargs 傳遞參數
2.set pc=0x0800_8000 ,r0=0 ,r1=0xA0
3.對比zImage 分析
通過tftp 0x0800_8000 命令直接將zImage下載到0x0800_8000地址
此時對0x08008000 反彙編可以得到和arch/arm/boot/compressed/head.S一致的彙編代碼,說明這是kernel的入口
08008000: msr cpsr_c,#0xD3
08008004: bl 0x8008150
08008008: mov r10,r5
0800800c: beq 0x8008148
08008010: bl 0x80081B0
08008014: mov r8,r5
08008018: beq 0x8008148
0800801c: bl 0x80080D8
08008020: ldr r13,[pc,#+4]
08008024: add r14,pc,#0x68
08008028: add pc,r10,#0xC
0800802c: andgt r8,r0,r0,asr r0
08008030: andgt r2,r11,r0
08008034: andgt r2,r11,r0
08008038: andgt r2,r12,r0,lsl #1
0800803c: ldrgth r14,[r13],-r12
08008040: andgt r5,r12,r12,asr #1
08008044: mulgts r12,r12,r0
08008048: andgt r5,r11,r12,asr #0x13
0800804c: ldrgtsh r3,[r11],-r8
08008050: sub r3,pc,#0x28
08008054: ldmia r3!,{r4,r5,r6,r7}
08008058: cmp r4,r5
0800805c: cmpne r5,r6
08008060: ldrne r11,[r4],#+4
08008064: strne r11,[r5],#+4
08008068: bne 0x800805C
0800806c: mov r11,#0
08008070: cmp r6,r7
08008074: strcc r11,[r6],#+4
08008078: bcc 0x8008070
0800807c: ldmia r3,{r4,r5,r6,r13}
08008080: str r9,[r4,#+0]
此時用go命令 go 0x08008000,go命令本質就是改變當前pc值,即pc=go 0x08008000
斷點位置爲 0x08008000 ,使用go 會在 0x08008000處停下來
>BKM>dr //此時通用寄存器值爲
R00 = 00000000 R01 = 083E0264 R02 = 000F0000 R03 = 0000000C
R04 = 08008000 R05 = 08808000 R06 = 41129200 R07 = 083E0264
R08 = 08000000 R09 = 18000000 R10(SL) = 00000000 R11(FP) = 00000020
R12(IP) = 08808354 R13(SP) = 088E9464 R14(LR) = 08808298 PC = 08008000
CPSR = 400000D3 SPSR = B00000FF
//uboot bootargs
08000100: 00000000 00000000 00000000 00000000 ................
08000110: 00000000 00000000 00000000 00000000 ................
08000120: 00000000 00000000 00000000 00000000 ................
08000130: 00000000 00000000 00000000 00000000 ................
08000140: 00000000 00000000 00000000 00000000 ................
08000150: 00000000 00000000 00000000 00000000 ................
08000160: 00000000 00000000 00000000 00000000 ................
08000170: 00000000 00000000 00000000 00000000 ................
08000180: 00000000 00000000 00000000 00000000 ................
08000190: 00000000 00000000 00000000 00000000 ................
080001A0: 00000000 00000000 00000000 00000000 ................
這個時候發現kernel無法正確啓動zImage
4,通過仿真器對go命令加以改造
a.將通用寄存器值改成
R00 = 00000000 R01 = 000000A0 R02 = 08000100 R03 = 0000000C
R04 = 08008000 R05 = 08808000 R06 = 41129200 R07 = 083E0264
R08 = 08000000 R09 = 18000000 R10(SL) = 00000000 R11(FP) = 00000020
R12(IP) = 08808354 R13(SP) = 088E9464 R14(LR) = 08808298 PC = 08008000
CPSR = 400000D3 SPSR = B00000FF
b.通過仿真器修改 0x08000100 地址的值
sml 0x08000100 00000005 54410001 00000000 00000000 00000000 00000004 54410002 04000000 08000000 0000000F 54410009 736E6F63
sml 0x08000130 3D656C6F 53797474 2C30584D 32353131 386E3030 3D706920 746F6F62 6F722070 2F3D746F 2F766564 0073666E 00000000
>BKM>dml 0x08000100 0x50
08000100: 00000005 54410001 00000000 00000000 ....TA..........
08000110: 00000000 00000004 54410002 04000000 ........TA......
08000120: 08000000 0000000F 54410009 736E6F63 ........TA..snoc
08000130: 3D656C6F 53797474 2C30584D 32353131 =eloSytt,0XM2511
08000140: 386E3030 3D706920 746F6F62 6F722070 8n00=pi toobor p
08000150: 2F3D746F 2F766564 0073666E 00000000 /=to/ved.sfn....
08000160: 00000000 00000000 00000000 00000000 ................
然後讓程序執行,這樣通過uboot也可以讓zImage得以執行。

可見go和bootm差異就是 go只是改寫pc值,而bootm傳遞r0,r1,r2還有bootargs

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章