• 【转】uboot 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

    ——————
    无论在哪里做什么,只要坚持服务、创新、创造价值,其他的东西自然都会来的。
  • 相关阅读:
    给花花看的链接
    Arguments Optional闭包
    对闭包最好的解释
    Everything Be True判断对象是否存在指定的属性且有值
    Binary Agents将二进制句子翻译成英文
    伤情鉴定和伤残鉴定
    Steamroller 数组扁平化处理
    Drop it
    2021年flag-300+道算法~~~
    微服务之玉麟宝典,呕心沥血的日常
  • 原文地址:https://www.cnblogs.com/pied/p/1755592.html
Copyright © 2020-2023  润新知