uboot启动linux分析,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

有疑问加站长微信联系(非本文作者)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值