uboot启动zImage(go)和uImage(bootm)分析

yazhouren 2016-07-17 20:56:50

origin: http://linux.chinaunix.net/techdoc/install/2009/03/15/1101440.shtml
http://www.linuxforum.net/forum/showthreaded.php?Cat=&Board=embedded&Number=700811&Search=true&Forum=embedded&Words=uboot%C6%F4%B6%AFzImage&Match=Entire%20Phrase&Searchpage=0&Limit=25&Old=allposts&Main=700811
我找了一块龙珠系列mx9328的板子和一个windriver ice,于是想把上面跑起来linux,不过内核启动遇到一些,调试了1个星期,有点收获,准备记录下来,先把之前不明白的zImage和uImage差异写出来。
做个记号
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

(0)

相关推荐