高通linux-系统启动

版权声明:本文为博主原创文章,未经博主允许不得转载。转载请标注出处: https://blog.csdn.net/sheji105/article/details/82625168

概述

本平台采用的是高通apq8009 arm平台,linux内核版本3.18,采用设备树方式。

linux系统启动过程从软件方面看可分为:bootloader,linux内核,文件系统和应用程序。

 

设备是以emmc方式启动的, 烧写文件都烧写到emmc中。上电后读取emmc,emmc被分了很多区,这里会有一个分区信息描述,就像x86 windows的mbr, 启动时候可确定bootloader在emmc中位置,开始启动bootloader。

bootloader是引导加载程序, uboot是常用的bootloader,它有很多功能,初始化处理器,调试口,有些还会初始化usb,以太网,便于数据传输;uboot还得支持设备树方式;uboot可以通过帮助命令,查看支持哪些功能,本平台就可以支持fastboot功能,bootcmd中是对内核影响的参数;

进入linux内核阶段,解析设备树, 根据设备树信息的的描述,内核匹配了apq8009 arm平台, 初始化,加载驱动,最后内核会启动一个init进程。它是Linux系统中的1号进程(Linux系统没有0号进程)。到此,完成了内核启动阶段的工作,交接给init来管理。

init进程运行一系列的脚本(startup scripts),可到etc/下查看,这些脚本功能可检测文件系统,挂载硬盘,设置网络,运行各种应用程序, 等等。

启动完以后,命令行方式会显示login 把权限交给用户,然后linux系统旅程就开始了。

       映像文件介绍

内核编译后会产生映像文件,映像文件类型分为压缩和非压缩方式。这主要是嵌入式系统存储器容量小,对容量有严格要求的,一般采用压缩式映像文件,内核启动用时间换空间。这两种方式,内核启动时是不同的,压缩式启动的时候,需要解压映像文件。

压缩式映像文件:uImage和zImage。

非压缩方式映像文件:Image, 由elf格式vmlinux转换而来。

vmlinux属于未压缩,带调试信息、符号表

Image是由objcopy工具去除vmlinux调试信息、注释、符号表等内容。

uImage可由工具mkimage 把zImage和64字节的头信息生成uImage。头信息描述映像文件的类型、加载位置、生成时间、大小等信息。

熟悉了zImage生成过程,才能更容易明白内核是怎么启动起来的。linux内核映像文件生成如下图:

生成带设备树的内核,命令格式: cat zImage xxx.dtb > zImage-dtb

 

 

ARM GCC 内嵌(inline)汇编手册

可直接看网址:http://www.ethernut.de/en/documents/arm-inline-asm.html

摘录网址中内容,gcc 中ARM寄存器使用:

Register

Alt. Name

Usage

r0

a1

First function argument
Integer function result
Scratch register

r1

a2

Second function argument
Scratch register

r2

a3

Third function argument
Scratch register

r3

a4

Fourth function argument
Scratch register

r4

v1

Register variable

r5

v2

Register variable

r6

v3

Register variable

r7

v4

Register variable

r8

v5

Register variable

r9

v6
rfp

Register variable
Real frame pointer

r10

sl

Stack limit

r11

fp

Argument pointer

r12

ip

Temporary workspace

r13

sp

Stack pointer

r14

lr

Link register
Workspace

r15

pc

Program counter

理解了这些后,看内核中汇编代码就容易多了。

 

linux内核启动

  1. 内核启动第一阶段 --- 解压内核

该平台是arm系列处理器,入口程序路径为arch/arm/;对于非arm平台, 比如x86, 入口程序路径为arch/x86/。

用的是压缩式内核zImage,zImage的入口程序即为 arch/arm/boot/compressed/head.S。

解压准备阶段将执行中断禁用、分配动态内存、初始化BBS区域、初始化页目录、打开缓存等任务。

对软硬件进行初始化完成后,开是执行任务start任务,见下方代码:

  1. start:  
  2.         .type   start,#function  
  3.         .rept   7  
  4.         mov r0, r0  
  5.         .endr  
  6.    ARM(     mov r0, r0      )  
  7.    ARM(     b   1f      )  
  8.  THUMB(     adr r12, BSYM(1f)   )  
  9.  THUMB(     bx  r12     )  
  10.   
  11.         .word   _magic_sig  @ Magic numbers to help the loader  
  12.         .word   _magic_start    @ absolute load/run zImage address  
  13.         .word   _magic_end  @ zImage end address  
  14.         .word   0x04030201  @ endianness flag  
  15.   
  16.  THUMB(     .thumb          )  
  17. 1:  
  18.  ARM_BE8(   setend  be )            @ go BE8 if compiled for BE8  
  19.         mrs r9, cpsr  
  20. #ifdef CONFIG_ARM_VIRT_EXT  
  21.         bl  __hyp_stub_install  @ get into SVC mode, reversibly  
  22. #endif  
  23.         mov r7, r1          @ save architecture ID  
  24.         mov r8, r2          @ save atags pointer  
  25.   
  26.         /* 
  27.          * Booting from Angel - need to enter SVC mode and disable 
  28.          * FIQs/IRQs (numeric definitions from angel arm.h source). 
  29.          * We only do this if we were in user mode on entry. 
  30.          */  
  31.         mrs r2, cpsr        @ get current mode  
  32.         tst r2, #3          @ not user?  
  33.         bne not_angel  
  34.         mov r0, #0x17       @ angel_SWIreason_EnterSVC  
  35.  ARM(       swi 0x123456    )   @ angel_SWI_ARM  
  36.  THUMB(     svc 0xab        )   @ angel_SWI_THUMB  
  37. not_angel:  
  38.         safe_svcmode_maskall r0  
  39.         msr spsr_cxsf, r9       @ Save the CPU boot mode in  
  40.                         @ SPSR  
  41.         /* 
  42.          * Note that some cache flushing and other stuff may 
  43.          * be needed here - is there an Angel SWI call for this? 
  44.          */  
  45.   
  46.         /* 
  47.          * some architecture specific code can be inserted 
  48.          * by the linker here, but it should preserve r7, r8, and r9. 
  49.          */  
  50.   
  51.         .text  
  52.   
  53. #ifdef CONFIG_AUTO_ZRELADDR  
  54.         @ determine final kernel image address  
  55.         mov r4, pc  
  56.         and r4, r4, #0xf8000000  
  57.         add r4, r4, #TEXT_OFFSET  
  58. #else  
  59.         ldr r4, =zreladdr  
  60. #endif  
  61.   
  62.         /* 
  63.          * Set up a page table only if it won't overwrite ourself. 
  64.          * That means r4 < pc && r4 - 16k page directory > &_end. 
  65.          * Given that r4 > &_end is most unfrequent, we add a rough 
  66.          * additional 1MB of room for a possible appended DTB. 
  67.          */  
  68.         mov r0, pc  
  69.         cmp r0, r4  
  70.         ldrcc   r0, LC0+32  
  71.         addcc   r0, r0, pc  
  72.         cmpcc   r4, r0  
  73.         orrcc   r4, r4, #1      @ remember we skipped cache_on  
  74.         blcs    cache_on  

行23是保存体系结构ID,行24是保存atags指针。34行开始输入SVC模式,禁用FIQs/IRQs

行68开始,给DTB留空间,记住跳开cache_on

 

  1. cache_on:   mov r3, #8          @ cache_on function  
  2.         b   call_cache_fn  
  3.   
  4. call_cache_fn:  adr r12, proc_types  
  5. #ifdef CONFIG_CPU_CP15  
  6.         mrc p15, 0, r9, c0, c0  @ get processor ID  
  7. #else  
  8.         ldr r9, =CONFIG_PROCESSOR_ID  
  9. #endif  
  10. 1:      ldr r1, [r12, #0]       @ get value  
  11.         ldr r2, [r12, #4]       @ get mask  
  12.         eor r1, r1, r9      @ (real ^ match)  
  13.         tst r1, r2          @       & mask  
  14.  ARM(       addeq   pc, r12, r3     ) @ call cache function  
  15.  THUMB(     addeq   r12, r3         )  
  16.  THUMB(     moveq   pc, r12         ) @ call cache function  
  17.         add r12, r12, #PROC_ENTRY_SIZE  
  18.         b   1b  
  19.   
  20. /* 
  21.  * Table for cache operations.  This is basically: 
  22.  *   - CPU ID match 
  23.  *   - CPU ID mask 
  24.  *   - 'cache on' method instruction 
  25.  *   - 'cache off' method instruction 
  26.  *   - 'cache flush' method instruction 
  27.  * 
  28.  * We match an entry using: ((real_id ^ match) & mask) == 0 
  29.  * 
  30.  * Writethrough caches generally only need 'on' and 'off' 
  31.  * methods.  Writeback caches _must_ have the flush method 
  32.  * defined. 
  33.  */  
  34.         .align  2  
  35.         .type   proc_types,#object  
  36. proc_types:  
  37.         .word   0x41000000      @ old ARM ID  
  38.         .word   0xff00f000  
  39.         mov pc, lr  
  40.  THUMB(     nop             )  
  41.         mov pc, lr  
  42.  THUMB(     nop             )  
  43.         mov pc, lr  
  44.  THUMB(     nop             )  
  45.   
  46.         .word   0x41007000      @ ARM7/710  
  47.         .word   0xfff8fe00  
  48.         mov pc, lr  
  49.  THUMB(     nop             )  
  50.         mov pc, lr  
  51.  THUMB(     nop             )  
  52.         mov pc, lr  
  53.  THUMB(     nop             )  
  54.   
  55.         .word   0x41807200      @ ARM720T (writethrough)  
  56.         .word   0xffffff00  
  57.         W(b)    __armv4_mmu_cache_on  
  58.         W(b)    __armv4_mmu_cache_off  
  59.         mov pc, lr  
  60.  THUMB(     nop             )  
  61.   
  62.         .word   0x41007400      @ ARM74x  
  63.         .word   0xff00ff00  
  64.         W(b)    __armv3_mpu_cache_on  
  65.         W(b)    __armv3_mpu_cache_off  
  66.         W(b)    __armv3_mpu_cache_flush  
  67.           
  68.         .word   0x41009400      @ ARM94x  
  69.         .word   0xff00ff00  
  70.         W(b)    __armv4_mpu_cache_on  
  71.         W(b)    __armv4_mpu_cache_off  
  72.         W(b)    __armv4_mpu_cache_flush  
  73.   
  74.         .word   0x41069260      @ ARM926EJ-S (v5TEJ)  
  75.         .word   0xff0ffff0  
  76.         W(b)    __arm926ejs_mmu_cache_on  
  77.         W(b)    __armv4_mmu_cache_off  
  78.         W(b)    __armv5tej_mmu_cache_flush  
  79.   
  80.         .word   0x00007000      @ ARM7 IDs  
  81.         .word   0x0000f000  
  82.         mov pc, lr  
  83.  THUMB(     nop             )  
  84.         mov pc, lr  
  85.  THUMB(     nop             )  
  86.         mov pc, lr  
  87.  THUMB(     nop             )  
  88.   
  89.         @ Everything from here on will be the new ID system.  
  90.   
  91.         .word   0x4401a100      @ sa110 / sa1100  
  92.         .word   0xffffffe0  
  93.         W(b)    __armv4_mmu_cache_on  
  94.         W(b)    __armv4_mmu_cache_off  
  95.         W(b)    __armv4_mmu_cache_flush  
  96.   
  97.         .word   0x6901b110      @ sa1110  
  98.         .word   0xfffffff0  
  99.         W(b)    __armv4_mmu_cache_on  
  100.         W(b)    __armv4_mmu_cache_off  
  101.         W(b)    __armv4_mmu_cache_flush  
  102.   
  103.         .word   0x56056900  
  104.         .word   0xffffff00      @ PXA9xx  
  105.         W(b)    __armv4_mmu_cache_on  
  106.         W(b)    __armv4_mmu_cache_off  
  107.         W(b)    __armv4_mmu_cache_flush  
  108.   
  109.         .word   0x56158000      @ PXA168  
  110.         .word   0xfffff000  
  111.         W(b)    __armv4_mmu_cache_on  
  112.         W(b)    __armv4_mmu_cache_off  
  113.         W(b)    __armv5tej_mmu_cache_flush  
  114.   
  115.         .word   0x56050000      @ Feroceon  
  116.         .word   0xff0f0000  
  117.         W(b)    __armv4_mmu_cache_on  
  118.         W(b)    __armv4_mmu_cache_off  
  119.         W(b)    __armv5tej_mmu_cache_flush  
  120.   
  121. #ifdef CONFIG_CPU_FEROCEON_OLD_ID  
  122.         /* this conflicts with the standard ARMv5TE entry */  
  123.         .long   0x41009260      @ Old Feroceon  
  124.         .long   0xff00fff0  
  125.         b   __armv4_mmu_cache_on  
  126.         b   __armv4_mmu_cache_off  
  127.         b   __armv5tej_mmu_cache_flush  
  128. #endif  
  129.   
  130.         .word   0x66015261      @ FA526  
  131.         .word   0xff01fff1  
  132.         W(b)    __fa526_cache_on  
  133.         W(b)    __armv4_mmu_cache_off  
  134.         W(b)    __fa526_cache_flush  
  135.   
  136.         @ These match on the architecture ID  
  137.   
  138.         .word   0x00020000      @ ARMv4T  
  139.         .word   0x000f0000  
  140.         W(b)    __armv4_mmu_cache_on  
  141.         W(b)    __armv4_mmu_cache_off  
  142.         W(b)    __armv4_mmu_cache_flush  
  143.   
  144.         .word   0x00050000      @ ARMv5TE  
  145.         .word   0x000f0000  
  146.         W(b)    __armv4_mmu_cache_on  
  147.         W(b)    __armv4_mmu_cache_off  
  148.         W(b)    __armv4_mmu_cache_flush  
  149.   
  150.         .word   0x00060000      @ ARMv5TEJ  
  151.         .word   0x000f0000  
  152.         W(b)    __armv4_mmu_cache_on  
  153.         W(b)    __armv4_mmu_cache_off  
  154.         W(b)    __armv5tej_mmu_cache_flush  
  155.   
  156.         .word   0x0007b000      @ ARMv6  
  157.         .word   0x000ff000  
  158.         W(b)    __armv6_mmu_cache_on  
  159.         W(b)    __armv4_mmu_cache_off  
  160.         W(b)    __armv6_mmu_cache_flush  
  161.   
  162.         .word   0x000f0000      @ new CPU Id  
  163.         .word   0x000f0000  
  164.         W(b)    __armv7_mmu_cache_on  
  165.         W(b)    __armv7_mmu_cache_off  
  166.         W(b)    __armv7_mmu_cache_flush  
  167.   
  168.         .word   0           @ unrecognised type  
  169.         .word   0  
  170.         mov pc, lr  
  171.  THUMB(     nop             )  
  172.         mov pc, lr  
  173.  THUMB(     nop             )  
  174.         mov pc, lr  
  175.  THUMB(     nop             )  
  176.   
  177.         .size   proc_types, . - proc_types  
  178.   
  179.         /* 
  180.          * If you get a "non-constant expression in ".if" statement" 
  181.          * error from the assembler on this line, check that you have 
  182.          * not accidentally written a "b" instruction where you should 
  183.          * have written W(b). 
  184.          */  
  185.         .if (. - proc_types) % PROC_ENTRY_SIZE != 0  
  186.         .error "The size of one or more proc_types entries is wrong."  
  187.         .endif  
  188.   
  189. /* 
  190.  * Turn off the Cache and MMU.  ARMv3 does not support 
  191.  * reading the control register, but ARMv4 does. 
  192.  * 
  193.  * On exit, 
  194.  *  r0, r1, r2, r3, r9, r12 corrupted 
  195.  * This routine must preserve: 
  196.  *  r4, r7, r8 
  197.  */  
  198.         .align  5  

行2,把常数8写入寄存器r3中并跳转到call_cache_fn

 

打开汇编程序arch/arm/kernel/head.S,head.S依次完成:开启 MMU 和 cache,调用 decompress_kernel()解压内核,最后通过调用 call_kernel()进入非压缩内核 Image 的启动。下面将具体分析在此之后 Linux 内核的启动过程。

 

 

猜你喜欢

转载自blog.csdn.net/sheji105/article/details/82625168