嵌入式 arm平台kernel启动第一阶段汇编head.s分析
使用64MRAM时,通常的内存分布图:
下面我们的分析集中在arch/arm/boot/compressed/head.S,适当参考vmlinux.lds。
从linux/arch/arm/boot/compressed/vmlinux.lds文件可以看出head.S的入口地址为ENTRY(_start),也就是head.S汇编文件的_start标号开始的第一条指令。
下面从head.S中得_start标号开始分析。(有些指令不影响初始化,暂时略去不分析)
代码位置在/arch/arm/boot/compressed/head.S中:
start:
.typestart,#function/*uboot跳转到内核后执行的第一条代码*/
.rept8/*重复定义8次下面的指令,也就是空出中断向量表的位置*/
movr0,r0/*就是nop指令*/
.endr
b1f@跳转到后面的标号1处
.word0x016f2818@辅助引导程序的幻数,用来判断镜像是否是zImage
.wordstart@加载运行zImage的绝对地址,start表示赋的初值
.word_edata@zImage结尾地址,_edata是在vmlinux.lds.S中定义的,表示init,text,data三个段的结束位置
1:movr7,r1@savearchitectureID保存体系结构ID用r1保存
movr8,r2@saveatagspointer保存r2寄存器参数列表,r0始终为0
mrsr2,cpsr@getcurrentmode得到当前模式
tstr2,#3@notuser?,tst实际上是相与,判断是否处于用户模式
bnenot_angel@如果不是处于用户模式,就跳转到not_angel标号处
/*如果是普通用户模式,则通过软中断进入超级用户权限模式*/
movr0,#0x17@angel_SWIreason_EnterSVC,向SWI中传递参数
swi0x123456@angel_SWI_ARM这个是让用户空间进入SVC空间
not_angel:/*表示非用户模式,可以直接关闭中断*/
mrsr2,cpsr@turnoffinterruptsto读出cpsr寄存器的值放到r2中
orrr2,r2,#0xc0@preventangelfromrunning关闭中断
msrcpsr_c,r2@把r2的值从新写回到cpsr中
/*读入地址表。因为我们的代码可以在任何地址执行,也就是位置无关代码(PIC),所以我们需要加上一个偏移量。下面有每一个列表项的具体意义。
LC0是表的首项,它本身就是在此head.s中定义的
.typeLC0,#object
LC0:.wordLC0@r1LC0表的起始位置
.word__bss_start@r2bss段的起始地址在vmlinux.lds.S中定义
.word_end@r3zImage(bss)连接的结束地址在vmlinux.lds.S中定义
.wordzreladdr@r4zImage的连接地址,我们在arch/arm/mach-s3c2410/makefile.boot中定义的
.word_start@r5zImage的基地址,bootp/init.S中的_start函数,主要起传递参数作用
.word_got_start@r6GOT(全局偏移表)起始地址,_got_start是在compressed/vmlinux.lds.in中定义的
.word_got_end@ipGOT结束地址
.worduser_stack+4096@sp用户栈底user_stack是紧跟在bss段的后面的,在compressed/vmlinux.lds.in中定义的
@在本head.S的末尾定义了zImag的临时栈空间,在这里分配了4K的空间用来做堆栈。
.section".stack","w"
user_stack:.space4096
GOT表的初值是连接器指定的,当时程序并不知道代码在哪个地址执行。如果当前运行的地址已经和表上的地址不一样,还要修正GOT表。*/
.text
adrr0,LC0/*把地址表的起始地址放入r0中*/
ldmiar0,{r1,r2,r3,r4,r5,r6,ip,sp}/*加载地址表中的所有地址到相应的寄存器*/
@r0是运行时地址,而r1则是链接时地址,而它们两都是表示LC0表的起始位置,这样他们两的差则是运行和链接的偏移量,纠正了这个偏移量才可以运行与”地址相关的代码“
subsr0,r0,r1@calculatethedeltaoffset计算偏移量,并放入r0中
beqnot_relocated@ifdeltaiszero,wearerunningattheaddresswewerelinkedat.
@如果为0,则不用重定位了,直接跳转到标号not_relocated处执行
/*
*偏移量不为零,说明运行在不同的地址,那么需要修正几个指针
*r5–zImage基地址
*r6–GOT(全局偏移表)起始地址
*ip–GOT结束地址
*/
addr5,r5,r0/*加上偏移量修正zImage基地址*/
addr6,r6,r0/*加上偏移量修正GOT(全局偏移表)起始地址*/
addip,ip,r0/*加上偏移量修正GOT(全局偏移表)结束地址*/
/*
*这时需要修正BSS区域的指针,我们平台适用。
*r2–BSS起始地址
*r3–BSS结束地址
*sp–堆栈指针
*/
addr2,r2,r0/*加上偏移量修正BSS起始地址*/
addr3,r3,r0/*加上偏移量修正BSS结束地址*/
addsp,sp,r0/*加上偏移量修正堆栈指针*/
/*
*重新定位GOT表中所有的项.
*/
1:ldrr1,[r6,#0]@relocateentriesintheGOT
addr1,r1,r0@table.Thisfixesupthe
strr1,[r6],#4@Creferences.
cmpr6,ip
blo1b
not_relocated:movr0,#0
1:strr0,[r2],#4@clearbss清除bss段
strr0,[r2],#4
strr0,[r2],#4
strr0,[r2],#4
cmpr2,r3
blo1b
blcache_on/*开启指令和数据Cache,为了加快解压速度*/
@这里的r1,r2之间的空间为
嵌入式arm平台kernel启 相关文章:
- 嵌入式 arm平台kernel启动第二阶段分析(11-09)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)