微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 嵌入式 arm平台kernel启动第一阶段汇编head.s分析

嵌入式 arm平台kernel启动第一阶段汇编head.s分析

时间:11-09 来源:互联网 点击:

使用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之间的空间为

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top