您的位置:首页 > 其它

u-boot第一阶段初始化流程(反汇编分析)

2014-10-07 15:35 489 查看
转自:http://www.embstudy.org/home/space.php?uid=66&do=blog&id=90

1.设置中断向量表

为了更清楚,彻底的理解u-boot,我会全部从反汇编的代码去分析

忘记的朋友先补下课啦,提示:arm-linux-objdump -D u-boot>u-boot.s

====================================================================================================

.globl _start

_start: b start_code

ldr pc, _undefined_instruction

ldr pc, _software_interrupt

ldr pc, _prefetch_abort

ldr pc, _data_abort

ldr pc, _not_used

ldr pc, _irq

ldr pc, _fiq

_undefined_instruction: .word undefined_instruction

_software_interrupt: .word software_interrupt

_prefetch_abort: .word prefetch_abort

_data_abort: .word data_abort

_not_used: .word not_used

_irq: .word irq

_fiq: .word fiq

.balignl 16,0xdeadbeef

====================================================================================================

33f80000 <_start>:

33f80000: ea000012 b 33f80050 <start_code>

33f80004: e59ff014 ldr pc, [pc, #20] ; 33f80020 <_undefined_instruction>

33f80008: e59ff014 ldr pc, [pc, #20] ; 33f80024 <_software_interrupt>

33f8000c: e59ff014 ldr pc, [pc, #20] ; 33f80028 <_prefetch_abort>

33f80010: e59ff014 ldr pc, [pc, #20] ; 33f8002c <_data_abort>

33f80014: e59ff014 ldr pc, [pc, #20] ; 33f80030 <_not_used>

33f80018: e59ff014 ldr pc, [pc, #20] ; 33f80034 <_irq>

33f8001c: e59ff014 ldr pc, [pc, #20] ; 33f80038 <_fiq>

33f80020 <_undefined_instruction>:

33f80020: 33f80140 mvnccs r0, #16 ; 0x10

33f80024 <_software_interrupt>:

33f80024: 33f801a0 mvnccs r0, #40 ; 0x28

33f80028 <_prefetch_abort>:

33f80028: 33f80200 mvnccs r0, #0 ; 0x0

33f8002c <_data_abort>:

33f8002c: 33f80260 mvnccs r0, #6 ; 0x6

33f80030 <_not_used>:

33f80030: 33f802c0 mvnccs r0, #12 ; 0xc

33f80034 <_irq>:

33f80034: 33f80320 mvnccs r0, #-2147483648 ; 0x80000000

33f80038 <_fiq>:

33f80038: 33f80380 mvnccs r0, #2 ; 0x2

33f8003c: deadbeef cdple 14, 10, cr11, cr13, cr15, {7}

====================================================================================================

这段比较好理解,先是在33f80000地址处定义了一个全局标号_start,这个地址是在board/smdk2410/config.mk中指定,他会被包含在Makefile文件中,链接时传递给GCC。当然,你还可以从System.map文件中找到他所标识的地址,如:33f80000 T _start,T标识他所在的段是text(code) section.

然后是一堆中断跳转指令,如:ldr pc, _undefined_instruction。他把_undefined_instruction标号处(即地址33f80020)的值(即33f80140)放入pc指针,就是跳转到相应的中断处理函数的地址处,从反汇编中(ldr pc, [pc, #20])我们可以看出,就是相对当前pc指针偏移20字节(计算时别忘了流水线哦!)。最后一句可能让人比较费解(.balignl 16,0xdeadbeef),他的定义是增加位置计数器(在当前子段)使它指向规定的存储边界。真是很拗口哦,不知所云。其实从反汇编中可以看出,他在这里做的事情很简单,就是在0x33f8003c地址处写入值0xdeadbeef。

有关.balignl 16,0xdeadbeef的详细解释请参考:http://haoyeren.blog.sohu.com/84511571.html

2设置特权模式

====================================================================================================

start_code:

/*

* set the cpu to SVC32 mode

*/

mrs r0,cpsr ;cpsr中的值放到人r0

bic r0,r0,#0x1f ;r0 的值与 0x1f的反码按位作逻辑与操作

orr r0,r0,#0xd3 ;r0的值与寄存器 0xd3的值按位作逻辑或操作

msr cpsr,r0 ;r0中的值放到cpsr

bl coloured_LED_init

bl red_LED_on

============================================================================

33f80050: e10f0000 mrs r0, CPSR

33f80054: e3c0001f bic r0, r0, #31 ; 0x1f

33f80058: e38000d3 orr r0, r0, #211 ; 0xd3

33f8005c: e129f000 msr CPSR_fc, r0

33f80060: eb000110 bl 33f804a8 <__coloured_LED_init>

33f80064: eb000110 bl 33f804ac <__red_LED_on>

============================================================================

执行结果:

禁止IRQ(bit7=1)

禁止FRQ(bit6=1)

ARM指令集(bit5=0)

特权模式(bit[4..0]=10010)

最后两句是有关LED处理的跳转指令,可用如下指令定位:

arm-linux-addr2line -e u-boot 33f804a8

在lib_arm/board.c文件中的第137行和139行:

void inline __coloured_LED_init (void) {}

void inline __red_LED_on (void) {}

其实都是空函数,可根据需要自己添加。

3关闭看门狗

====================================================================================================

/* turn off the watchdog */

# define pWTCON 0x53000000

ldr r0, =pWTCON ;把0x53000000放入r0

mov r1, #0x0 ;把0x00放入r1

str r1, [r0] ;把r1的值存入r0指向的地址处

====================================================================================================

33f80068: e3a00453 mov r0, #1392508928 ; 0x53000000

33f8006c: e3a01000 mov r1, #0 ; 0x0

33f80070: e5801000 str r1, [r0]

====================================================================================================

反汇编中#1392508928即是十六进制数0x53000000的十进制表示

4屏蔽所有中断

====================================================================================================

# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */

# define INTSUBMSK 0x4A00001C

/*

* mask all IRQs by setting all bits in the INTMR - default

*/

mov r1, #0xffffffff

ldr r0, =INTMSK

str r1, [r0]

# if defined(CONFIG_S3C2410)

ldr r1, =0x7ff

ldr r0, =INTSUBMSK

str r1, [r0]

# endif

====================================================================================================

33f80074: e3e01000 mvn r1, #0 ; 0x0

33f80078: e59f0358 ldr r0, [pc, #856] ; 33f803d8 <.text+0x3d8>

33f8007c: e5801000 str r1, [r0]

33f80080: e59f1354 ldr r1, [pc, #852] ; 33f803dc <.text+0x3dc>

33f80084: e59f0354 ldr r0, [pc, #852] ; 33f803e0 <.text+0x3e0>

33f80088: e5801000 str r1, [r0]

。。。。。

33f803d8: 4a000008 bmi 33f80400 <sbrk>

33f803dc: 000007ff streqd r0, [r0], -pc

33f803e0: 4a00001c bmi 33f80458 <strmhz+0x14>

====================================================================================================

注意这里的立即数无法循环右移偶数位得到,所以汇编器先把他存在了后面的地址空间中,见反汇编代码。

5设置时钟工作频率

====================================================================================================

# define CLKDIVN 0x4C000014 /* clock divisor register */

/* FCLK:HCLK:PCLK = 1:2:4 */

/* default FCLK is 120 MHz ! */

ldr r0, =CLKDIVN

mov r1, #3

str r1, [r0]

====================================================================================================

33f8008c: e59f0350 ldr r0, [pc, #848] ; 33f803e4 <.text+0x3e4>

33f80090: e3a01003 mov r1, #3 ; 0x3

33f80094: e5801000 str r1, [r0]

。。。。。

33f803e4: 4c000014 stcmi 0, cr0, [r0], {20}

6刷新数据和指令缓存

====================================================================================================

bl cpu_init_crit ;跳转到子程序入口处

。。。。。。。

cpu_init_crit:

/*

* flush v4 I/D caches

*/

mov r0, #0

mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */

mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */

====================================================================================================

33f80098: eb000018 bl 33f80100 <cpu_init_crit>

。。。。。

33f80100: e3a00000 mov r0, #0 ; 0x0

33f80104: ee070f17 mcr 15, 0, r0, cr7, cr7, {0}

33f80108: ee080f17 mcr 15, 0, r0, cr8, cr7, {0}

====================================================================================================

记住这里有个子程序入口,第8部分子程序会返回。

7禁止MMU和缓存

====================================================================================================

/*

* disable MMU stuff and caches

*/

mrc p15, 0, r0, c1, c0, 0

bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)

bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)

orr r0, r0, #0x00000002 @ set bit 2 (A) Align

orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache

mcr p15, 0, r0, c1, c0, 0

====================================================================================================

33f8010c: ee110f10 mrc 15, 0, r0, cr1, cr0, {0}

33f80110: e3c00c23 bic r0, r0, #8960 ; 0x2300

33f80114: e3c00087 bic r0, r0, #135 ; 0x87

33f80118: e3800002 orr r0, r0, #2 ; 0x2

33f8011c: e3800a01 orr r0, r0, #4096 ; 0x1000

33f80120: ee010f10 mcr 15, 0, r0, cr1, cr0, {0}

8配置存储控制相关寄存器

====================================================================================================

mov ip, lr ;保存lr到ip(r12)

bl lowlevel_init ;跳转到新的子程序入口处

mov lr, ip ;恢复lr

mov pc, lr ;子程序返回

。。。。。。。。

#define BWSCON 0x48000000

_TEXT_BASE:

.word TEXT_BASE

.globl lowlevel_init

lowlevel_init:

/* memory control configuration */

/* make r0 relative the current location so that it */

/* reads SMRDATA out of FLASH rather than memory ! */

ldr r0, =SMRDATA

ldr r1, _TEXT_BASE

sub r0, r0, r1

ldr r1, =BWSCON /* Bus Width Status Controller */

add r2, r0, #13*4

0:

ldr r3, [r0], #4

str r3, [r1], #4

cmp r2, r0

bne 0b

/* everything is fine now */

mov pc, lr

.ltorg

/* the literal pools origin */

SMRDATA:

.word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))

.word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))

.word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))

.word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))

.word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))

.word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))

.word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))

.word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))

.word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))

.word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)

.word 0x32

.word 0x30

.word 0x30

====================================================================================================

33f80124: e1a0c00e mov ip, lr

33f80128: eb005f76 bl 33f97f08 <lowlevel_init>

33f8012c: e1a0e00c mov lr, ip

33f80130: e1a0f00e mov pc, lr

。。。。。

33f97f04 <_TEXT_BASE>:

33f97f04: 33f80000 mvnccs r0, #0 ; 0x0

33f97f08 <lowlevel_init>:

33f97f08: e59f0020 ldr r0, [pc, #32] ; 33f97f30 <.text+0x17f30>

33f97f0c: e51f1010 ldr r1, [pc, #-16] ; 33f97f04 <_TEXT_BASE>

33f97f10: e0400001 sub r0, r0, r1

33f97f14: e3a01312 mov r1, #1207959552 ; 0x48000000

33f97f18: e2802034 add r2, r0, #52 ; 0x34

33f97f1c: e4903004 ldr r3, [r0], #4

33f97f20: e4813004 str r3, [r1], #4

33f97f24: e1520000 cmp r2, r0

33f97f28: 1afffffb bne 33f97f1c <lowlevel_init+0x14>

33f97f2c: e1a0f00e mov pc, lr

33f97f30: 33f97f34 mvnccs r7, #208 ; 0xd0

33f97f34 <SMRDATA>:

33f97f34: 2211d120 andcss sp, r1, #8 ; 0x8

33f97f38: 00000700 andeq r0, r0, r0, lsl #14

33f97f3c: 00000700 andeq r0, r0, r0, lsl #14

33f97f40: 00000700 andeq r0, r0, r0, lsl #14

33f97f44: 00001f4c andeq r1, r0, ip, asr #30

33f97f48: 00000700 andeq r0, r0, r0, lsl #14

33f97f4c: 00000700 andeq r0, r0, r0, lsl #14

33f97f50: 00018005 andeq r8, r1, r5

33f97f54: 00018005 andeq r8, r1, r5

33f97f58: 008e04f4 streqd r0, [lr], r4

33f97f5c: 00000032 andeq r0, r0, r2, lsr r0

33f97f60: 00000030 andeq r0, r0, r0, lsr r0

33f97f64: 00000030 andeq r0, r0, r0, lsr r0

====================================================================================================

注意由于前次子程序未返回,又用bl进入新的子程序,所以先要对lr进行保护。

本段主要完成的任务是,用一个循环把SMRDATA标号处定义的52字节数据依次存放到0x48000000以上的地址空间中 ,从而完成对存储控制相关寄存器的初始化工作。最后恢复lr,子程序返回。

然后来看下具体配置:(根据源代码中的宏定义)

/* BWSCON */

#define DW32 (0x2)

#define B1_BWSCON (DW32)

#define B6_BWSCON (DW32)

/* BANK0CON */

#define B0_Tacs 0x0 /* 0clk */

#define B0_Tcos 0x0 /* 0clk */

#define B0_Tacc 0x7 /* 14clk */

#define B0_Tcoh 0x0 /* 0clk */

#define B0_Tah 0x0 /* 0clk */

#define B0_Tacp 0x0

#define B0_PMC 0x0 /* normal */

/* BANK6CON */

#define B6_MT 0x3 /* SDRAM */

#define B6_Trcd 0x1

#define B6_SCAN 0x1 /* 9bit */

/* REFRESH parameter */

#define REFEN 0x1 /* Refresh enable */

#define TREFMD 0x0 /* CBR(CAS before RAS)/Auto refresh */

#define Trp 0x0 /* 2clk */

#define Trc 0x3 /* 7clk */

#define Tchr 0x2 /* 3clk */

#define REFCNT 1268 /* period=15.6us, HCLK=60Mhz, (2048+1-15.6*60)

BWSCON:配置总线宽度,等待状态控制寄存器

(0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))

配置结果:

BANK6设为32位数据总线,禁止WAIT,不用UB/LB

(BANK0通过外部引脚设定,其他BANK未使用,设置略。)

BANKCON0:BANK0控制寄存器

((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))

配置结果:

nGCS0之前的地址建立时间0clocks,

在nOE之前片选的建立时间0clocks,

访问周期14clocks,

在nOE之后的片选的保持时间0clocks,

nGCS0之后的地址保持时间0clocks,

页模式访问周期2clocks,

页模式配置为标准(1 date),

BANKCON6:BANK6控制寄存器

((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))

配置结果:

BANK6设为类型DRAM,

RAS到CAS延迟3clocks,

纵向地址数9bit

REFRESH:SDRAM刷新控制寄存器

((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)

配置结果:

使能刷新

刷新模式为自动刷新

SDRAM RAS预改变时间2clocks

SDRAM Semi Row 周期7clocks

刷新计数值1268(即设定SDRAM刷新频率)

BANKSIZE:BANK大小寄存器

0x32

配置结果:

使能SDRAM掉电模式

SCLK仅在访问期间才有效

BANK6/7按128M映射

MRSRB6:BANK6模式寄存器设置寄存器

0x30

配置结果:

CAS反应时间3clocks

顺序触发类型

触发长度1

9将程序搬移到RAM空间

====================================================================================================

relocate: /* relocate U-Boot to RAM */

adr r0, _start /* r0 <- current position of code */

ldr r1, _TEXT_BASE /* test if we run from flash or RAM */

cmp r0, r1 /* don't reloc during debug */

beq stack_setup

ldr r2, _armboot_start

ldr r3, _bss_start

sub r2, r3, r2 /* r2 <- size of armboot */

add r2, r0, r2 /* r2 <- source end address */

copy_loop:

ldmia r0!, {r3-r10} /* copy from source address [r0] */

stmia r1!, {r3-r10} /* copy to target address [r1] */

cmp r0, r2 /* until source end addreee [r2] */

ble copy_loop

====================================================================================================

33f8009c <relocate>:

33f8009c: e24f00a4 sub r0, pc, #164 ; 0xa4

33f800a0: e51f1068 ldr r1, [pc, #-104] ; 33f80040 <_TEXT_BASE>

33f800a4: e1500001 cmp r0, r1

33f800a8: 0a000007 beq 33f800cc <stack_setup>

33f800ac: e51f2070 ldr r2, [pc, #-112] ; 33f80044 <_armboot_start>

33f800b0: e51f3070 ldr r3, [pc, #-112] ; 33f80048 <_bss_start>

33f800b4: e0432002 sub r2, r3, r2

33f800b8: e0802002 add r2, r0, r2

33f800bc <copy_loop>:

33f800bc: e8b007f8 ldmia r0!, {r3, r4, r5, r6, r7, r8, r9, sl}

33f800c0: e8a107f8 stmia r1!, {r3, r4, r5, r6, r7, r8, r9, sl}

33f800c4: e1500002 cmp r0, r2

33f800c8: dafffffb ble 33f800bc <copy_loop>

====================================================================================================

先测试是否是Debug中(注意adr相对寻址,ldr绝对寻址的不同),是则跳转到下一部分,否则按8字节循环搬移程序到RAM空间,注意结合上面给出的uboot存储器映射图学习。

10设置堆栈指针

====================================================================================================

/* Set up the stack */

stack_setup:

ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */

sub r0, r0, #CFG_MALLOC_LEN /* malloc area */

sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */

#ifdef CONFIG_USE_IRQ

sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif

sub sp, r0, #12 /* leave 3 words for abort-stack */

====================================================================================================

33f800cc <stack_setup>:

33f800cc: e51f0094 ldr r0, [pc, #-148] ; 33f80040 <_TEXT_BASE>

33f800d0: e2400803 sub r0, r0, #196608 ; 0x30000

33f800d4: e2400080 sub r0, r0, #128 ; 0x80

33f800d8: e240d00c sub sp, r0, #12 ; 0xc

====================================================================================================

结合上面的映射图可以看出,_TEXT_BASE标号处地址(33f80000)以上就是上一步重定位的程序代码,他以下减去动态内存分配区大小,再减去bdinfo的大小(uboot第二段会有个结构体指向这个区域),从反汇编代码可以看出,我们未配置用户IRQ,所以再留12个字节给中断堆栈使用。现在指向的地址就是sp指针的位置了,从反汇编可以很容易的看出sp每次减去的数值。

11清零全局未初始化数据段,并跳转到第二阶段--C程序部分

====================================================================================================

clear_bss:

ldr r0, _bss_start /* find start of bss segment */

ldr r1, _bss_end /* stop here */

mov r2, #0x00000000 /* clear */

clbss_l:str r2, [r0] /* clear loop... */

add r0, r0, #4

cmp r0, r1

ble clbss_l

ldr pc, _start_armboot

_start_armboot: .word start_armboot

====================================================================================================

33f800dc <clear_bss>:

33f800dc: e51f009c ldr r0, [pc, #-156] ; 33f80048 <_bss_start>

33f800e0: e51f109c ldr r1, [pc, #-156] ; 33f8004c <_bss_end>

33f800e4: e3a02000 mov r2, #0 ; 0x0

33f800e8 <clbss_l>:

33f800e8: e5802000 str r2, [r0]

33f800ec: e2800004 add r0, r0, #4 ; 0x4

33f800f0: e1500001 cmp r0, r1

33f800f4: dafffffb ble 33f800e8 <clbss_l>

33f800f8: e51ff004 ldr pc, [pc, #-4] ; 33f800fc <_start_armboot>

33f800fc <_start_armboot>:

33f800fc: 33f80578 mvnccs r0, #503316480 ; 0x1e000000

====================================================================================================

从board/smdk2410/u-boot.lds文件中,我们看到bss段被链接到了u_boot_cmd段的后面,即地址0x33f80048以后,现在我们要做的就通过一个循环把这段清空。然后重新赋值PC指针,跳转到标号_start_armboot指向的地址处,即第二阶段,C程序部分。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: