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

Android arm linux kernel启动流程

时间:11-09 来源:互联网 点击:
d r3, r2, r3 1: ldmia r2!, {r9 - r14} @ copy relocation code stmia r1!, {r9 - r14} ldmia r2!, {r9 - r14} stmia r1!, {r9 - r14} cmp r2, r3 blo 1b add sp, r1, #128 @ relocate the stack bl cache_clean_flush add pc, r5, r0 @ call relocation code

因为没有将kernel解压在要求的地址,所以必须重定向,说穿了就是要将解压的kernel拷贝到正确的地址,因为正确的地址与zImage的地址是重合的,而要拷贝我们又要执行zImage的重定位代码,所以这里首先将重定位代码reloc_start拷贝到vmlinx上面,然后再将vmlinx 拷贝到正确的地址并覆盖掉zImage。这里首先计算出解压后的vmlinux的高地址放在r1里面,r2存放着重定位代码的首地址,r3存放着重定位代码的size,这样通过拷贝就将reloc_start移动到vmlinx后面去了,然后跳转到重定位代码开始执行。

view plainprint?

  1. /*
  2. *Allcodefollowingthislineisrelocatable.Itisrelocatedby
  3. *theabovecodetotheendofthedecompressedkernelimageand
  4. *executedthere.Duringthistime,wehavenostacks.
  5. *
  6. *r0=decompressedkernellength
  7. *r1-r3=unused
  8. *r4=kernelexecutionaddress
  9. *r5=decompressedkernelstart
  10. *r6=processorID
  11. *r7=architectureID
  12. *r8=atagspointer
  13. *r9-r14=corrupted
  14. */
  15. .align5
  16. reloc_start:addr9,r5,r0
  17. subr9,r9,#128@donotcopythestack
  18. debug_reloc_start
  19. movr1,r4
  20. 1:
  21. .rept4
  22. ldmiar5!,{r0,r2,r3,r10-r14}@relocatekernel
  23. stmiar1!,{r0,r2,r3,r10-r14}
  24. .endr
  25. cmpr5,r9
  26. blo1b
  27. addsp,r1,#128@relocatethestack
  28. debug_reloc_end
  29. call_kernel:blcache_clean_flush
  30. blcache_off
  31. movr0,#0@mustbezero
  32. movr1,r7@restorearchitecturenumber
  33. movr2,r8@restoreatagspointer
  34. movpc,r4@callkernel

/* * All code following this line is relocatable. It is relocated by * the above code to the end of the decompressed kernel image and * executed there. During this time, we have no stacks. * * r0 = decompressed kernel length * r1-r3 = unused * r4 = kernel execution address * r5 = decompressed kernel start * r6 = processor ID * r7 = architecture ID * r8 = atags pointer * r9-r14 = corrupted */ .align 5 reloc_start: add r9, r5, r0 sub r9, r9, #128 @ do not copy the stack debug_reloc_start mov r1, r4 1: .rept 4 ldmia r5!, {r0, r2, r3, r10 - r14} @ relocate kernel stmia r1!, {r0, r2, r3, r10 - r14} .endr cmp r5, r9 blo 1b add sp, r1, #128 @ relocate the stack debug_reloc_end call_kernel: bl cache_clean_flush bl cache_off mov r0, #0 @ must be zero mov r1, r7 @ restore architecture number mov r2, r8 @ restore atags pointer mov pc, r4 @ call kernel

这里就是将vmlinx拷贝到正确的地址了,拷贝到正确的位置以后,就将kernel的首地址赋给PC,然后就跳转到真正kernel启动的过程~~

最后我们来总结一下一个基本的过程:

1)当bootloader要从分区中数据读到内存中来的时候,这里涉及最重要的两个地址,一个就是ZTEXTADDR还有一个是 INITRD_PHYS。不管用什么方式来生成IMG都要让bootloader有方法知道这些参数,不然就不知道应该将数据从FLASH读入以后放在什么地方,下一步也不知道从哪个地方开始执行了;

2)bootloader将IMG载入RAM以后,并跳到zImage的地址开始解压的时候,这里就涉及到另外一个重要的参数,那就是 ZRELADDR,就是解压后的kernel应该放在哪。这个参数一般都是arch/arm/mach-xxx下面的Makefile.boot来提供的;

3)另外现在解压的代码head.S和misc.c一般都会以PIC的方式来编译,这样载入RAM在任何地方都可以运行,这里涉及到两次冲定位的过程,基本上这个重定位的过程在ARM上都是差不多一样的。

写这个总结的时候咱的心情是沉重的,因为还有好多东西没弄明白。。。感叹自己的知识还是浅薄得很,前途钱途漫漫阿~~不过基本脉络是清楚的,具体的细节只能留在以后有时间再啃了。这里的第二部分启动流程指的是解压后kernel开始执行的一部分代码,这部分代码和ARM体系结构是紧密联系在一起的,所以最好是将ARM ARCHITECTURE REFERENCE MANUL仔细读读,尤其里面关于控制寄存器啊,MMU方面的内容~

前面说过解压以后,代码会跳到解压完成以后的vmlinux开始执行,具体从什么地方开始执行我们可以看看生成的vmlinux.lds(arch/arm/kernel/)这个文件:

view plainprint?

  1. OUTPUT_ARCH(arm)
  2. EN

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

网站地图

Top