针对pxa芯片的blob分析
Blob 编译后的代码定义最大为64Kb,并且这64Kb又分成两个阶段来执行。
第一阶段的代码在start.S 中定义,大小为1KB,它包括从系统上电后在0x00000000 地址开始执行的部分。这部分代码运行在Flash 中,它包括对一些寄存器的初始化和将Blob第二阶段代码从Flash 拷贝到 sdram 中。
第二阶段的起始文件为trampoline.S,被复制到sdram后,就从第一阶段跳转到这个文件开始执行剩余部分代码。
blob对各种板子和cpu的支持在configure.in中有介绍。
从blob/src/blob/start.S开始
.text
/* Jump vector table as in table 3.1 in [1] */
.globl _start
_start:
breset 跳转到reset
//以下是异常中断向量表
b
undefined_instruction //未定义指令
b
software_interrupt //软件中断
b
prefetch_abort //预取指令终止
b
data_abort //数据访问终止
b
not_used
b
irq //外部中断
b
fiq //快速中断
一开始就跳转到reset,查找到start_pxa.S中
reset:
/* First, mask **ALL** interrupts */
ldr
r0, =ICMR
mov
r1, #0x00
str
r1, [r0]
关闭所有中断,下面继续real_reset
real_reset:
blgpiosetup 跳转到gpiosetup
bl
ledsetup
bl
memsetup
bl
normal_boot
blink
#1
在gpio_pxa.S中找到gpiosetup,对gpio进行初始化
如此类推,分别在当前初始化led,在memsetup_pxa.S中初始化存储器,回到start.S中执行normal_boot
.globl normal_boot
normal_boot:
/* check the first 1MB of BLOB_START in increments of 4k */
mov
r7, #0x1000
mov
r6, r7, lsl #6 /* 4KB << 5 = 256KB */
ldr
r5, BLOB_START
在这里会检测blob在ram中起始地址后的1M空间,并调用testram,检测blob,如果出错就进入死循环
mem_test_loop:
mov
r0, r5
bl
testram 跳转到testmem.S中
teq
r0, #1
beq
endless_loop /* oops, something went wrong :( */
add
r5, r5, r7
subs
r6, r6, r7
bne
mem_test_loop
其中:
BLOB_START: .wordBLOB_ABS_BASE_ADDR
piggy_start: .word__piggy_start //后面有解释在blob-rest-piggy.o
piggy_end: .word__piggy_end
针对BLOB_ABS_BASE_ADDR 的值,以及各种地址
查看头文件,并在相应的文件中寻找
#ifdef HAVE_CONFIG_H
# include <blob/config.h>
#endif
#include <blob/arch.h>
copy_loop:
ldmia
r0!, {r3-r10} //ldmia:采用多寄存器寻址方式,一条指令可以完成多个寄存器值的传送,最多16个通用寄存器的值
stmia
r1!, {r3-r10}
cmp
r0, r2
ble
copy_loop
/* blob is copied to ram, so jump to it */
ldr
r0, BLOB_START
mov pc, r0
copy完成就跳转到ram中blob运行的第二阶段
开始于src/blob/start-ld-script
__piggy_start = .;
blob-rest-piggy.o
表明__piggy_start地址是blob-rest-piggy.o,也就是执行它。
而blob-rest-piggy.o依靠如下(Makefile中寻找)
blob-rest-piggy.o->blob-rest->blob-rest-elf32->blob_rest_elf32_OBJECTS->am_blob_rest_elf32_OBJECTS->trampoline
详情如下:
am_blob_rest_elf32_OBJECTS = trampoline.$(OBJEXT) flashasm.$(OBJEXT) \
testmem2.$(OBJEXT) bootldrpart.$(OBJEXT) commands.$(OBJEXT) \
initcalls.$(OBJEXT) lcd.$(OBJEXT) pxafb.$(OBJEXT) linux.$(OBJEXT) main.$(OBJEXT) \
memory.$(OBJEXT) reboot.$(OBJEXT)
我们在trampoline.S中很容易找到
/* setup the stack pointer */
ldr
r0, stack_end //堆栈设置
sub
sp, r0, #4
/* jump to C code */
bl
main //跳转到C代码的main函数中
/* if main ever returns we just call it again */
b
_trampoline
失败了,重新执行_trampoline