微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Android arm linux kernel启动流程

Android arm linux kernel启动流程

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

拟地址都是相对的,没有绝对地址。这里的 vmlinx.lds可以对照着后面的head.s稍微看一下~得到压缩以后的vmlinx以后再将这个vmlinx经过objcopy以后就得到我们的 zImage了,然后拷贝到out目录下就是我们的kernel了~~

在这里要强调几个地址,这些地址定义在arch/arm/mach-msm/makefile.boot里面,被arch/arm/boot /Makefile调用,其中zreladdr-y就是我们的kernel被解压以后要释放的地址了,解压代码跑完以后就会跳到这个地址来执行 kernel的启动。不过这里还有其他两个PHYS,跟前面定义在boardconfig.h里面的值重复了,不知道这两个值在这里定义跟前面的值是一种什么关系???

好啦,讲到这里我们基本就知道boot.img的构成了,下面我们就从解压的代码开始看看arm linux kernel启动的一个过程,这个解压的source就是/arch/arm/boot/compressed/head.S。要看懂这个汇编需要了解 GNU ASM以及ARM汇编指令,ARM指令就不说了,ARM RVCT里面的文档有得下,至于GNU ASM,不需要消息了解的话主要是看一下一些伪指令的含义(http://sources.redhat.com/binutils/docs-2.12 /as.info/Pseudo-Ops.html#Pseudo%20Ops)

那么我们现在就开始分析这个解压的过程:

1)bootloader会传递2个参数过来,分别是r1=architecture ID, r2=atags pointer。head.S从哪部分开始执行呢,这个我们可以看看vmlinx.lds:

view plainprint?

  1. ENTRY(_start)
  2. SECTIONS
  3. {
  4. .=0;
  5. _text=.;
  6. .text:{
  7. _start=.;
  8. *(.start)
  9. *(.text)
  10. *(.text.*)
  11. *(.fixup)
  12. *(.gnu.warning)
  13. *(.rodata)
  14. *(.rodata.*)
  15. *(.glue_7)
  16. *(.glue_7t)
  17. *(.piggydata)
  18. .=ALIGN(4);
  19. }

ENTRY(_start) SECTIONS { . = 0; _text = .; .text : { _start = .; *(.start) *(.text) *(.text.*) *(.fixup) *(.gnu.warning) *(.rodata) *(.rodata.*) *(.glue_7) *(.glue_7t) *(.piggydata) . = ALIGN(4); }

可以看到我们最开始的section就是.start,所以我们是从start段开始执行的。ELF对程序的入口地址是有定义的,这可以参照*.lds 的语法规则里面有描述,分别是GNU LD的-E ---> *.lds里面的ENTRY定义 ---> start Symbol ---> .text section --->0。在这里是没有这些判断的,因为还没有操作系统,bootloader会直接跳到这个start的地址开始执行。

在这里稍微带一句,如果觉得head.S看的不太舒服的话,比如有些跳转并不知道意思,可以直接objdump vmlinx来看,dump出来的汇编的流程就比较清晰了。

view plainprint?

  1. 1:movr7,r1@savearchitectureID
  2. movr8,r2@saveatagspointer
  3. #ifndef__ARM_ARCH_2__
  4. /*
  5. *BootingfromAngel-needtoenterSVCmodeanddisable
  6. *FIQs/IRQs(numericdefinitionsfromangelarm.hsource).
  7. *Weonlydothisifwewereinusermodeonentry.
  8. */
  9. mrsr2,cpsr@getcurrentmode
  10. tstr2,#3@notuser?
  11. bnenot_angel@如果不是
  12. movr0,#0x17@angel_SWIreason_EnterSVC
  13. swi0x123456@angel_SWI_ARM
  14. not_angel:
  15. mrsr2,cpsr@turnoffinterruptsto
  16. orrr2,r2,#0xc0@preventangelfromrunning
  17. msrcpsr_c,r2

1: mov r7, r1 @ save architecture ID mov r8, r2 @ save atags pointer #ifndef __ARM_ARCH_2__ /* * Booting from Angel - need to enter SVC mode and disable * FIQs/IRQs (numeric definitions from angel arm.h source). * We only do this if we were in user mode on entry. */ mrs r2, cpsr @ get current mode tst r2, #3 @ not user? bne not_angel @ 如果不是 mov r0, #0x17 @ angel_SWIreason_EnterSVC swi 0x123456 @ angel_SWI_ARM not_angel: mrs r2, cpsr @ turn off interrupts to orr r2, r2, #0xc0 @ prevent angel from running msr cpsr_c, r2

上面首先保存r1和r2的值,然后进入超级用户模式,并关闭中断。

view plainprint?

  1. .text
  2. adrr0,LC0
  3. ldmiar0,{r1,r2,r3,r4,r5,r6,ip,sp}
  4. subsr0,r0,r1@calculatethedeltaoffset
  5. @ifdeltaiszero,weare
  6. beqnot_relocated@runningattheaddresswe
  7. @werelinkedat.

.text adr r0, LC0 ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} subs r0, r0, r1 @ calculate the delta offset @ if delta is zero, we are beq not_relocated @ running at the address we @ were linked at.

这里首先判断LC0当前的运行地址和链接地址是否一样,如果一样就不需要重定位,如果不一样则需要进行重定位。这里肯定是不相等的,因为我们可以通过 objdump看到LC0的地址是0x00000138,是一个相对地址,然后adr r0, LC0 实际上就是将LC0当前的运行地

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

网站地图

Top