微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux启动代码分析

ARM Linux启动代码分析

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

单说说上一个“年代”的bootloader是怎么引导、启动内核的,主要的流程如下:

(1)上电

(2)必要的设置

(3)关看门狗

(4)初始化SDRAM、初始化Nand Flash

(5)把bootloader拷贝到SDRAM的高处

(6)清BSS段

(7)跳到SDRAM继续执行

(8)把Nand Flash中的内核Image拷贝到SDRAM(0x58)

(9)设置启动参数,r0、r1等寄存器,关闭MMU、cache等

(10)跳到内核Image的起始处(0x58)执行,此后,bootloader时代一去不复返,进入Linux新时代。

现在应该知道执行到161行时,PC的值就为0x50~0x58之间的某一个值(假定内存为128MB,s3c6410物理内存的起始地址为0x50),即一物理地址,因此r3的值就为194行的标号3处的物理地址。

162行,分别将r3、r3+4、r3+8地址上的内容存放到r5、r6、r7寄存器中,即r5存放的是__proc_info_begin的值(是一个链接地址,或者说虚拟地址),r6存放的是__proc_info_end的值(是一个链接地址,或者说虚拟地址),因为 . 表示的是当前的链接地址,所以r7存放的是标号4的链接地址,这跟LD链接脚本里的 . 表示的意思是一样的。

163行,将r3的值加8,即现在r3的值为196行的标号4的物理地址。

164行,r3 = r3 – r7,即r3 = 标号4的物理地址 - 标号4的虚拟地址,这样就可以计算出物理地址和虚拟地址的偏移量,显然r3的值为一负数。

165行,结果为r5 = __proc_info_begin的物理地址。

166行,结果为r6 = __proc_info_end的物理地址。

167行,取出struct proc_info_list结构体的前两个成员的值分别放到r3、r4。struct proc_info_list结构体的定义如下:

struct proc_info_list {unsigned int        cpu_val;unsigned int        cpu_mask;unsigned long        __cpu_mm_mmu_flags;    /* used by head.S */unsigned long        __cpu_io_mmu_flags;    /* used by head.S */unsigned long        __cpu_flush;        /* used by head.S */const char        *arch_name;const char        *elf_name;unsigned int        elf_hwcap;const char        *cpu_name;struct processor    *proc;struct cpu_tlb_fns    *tlb;struct cpu_user_fns    *user;struct cpu_cache_fns    *cache;};

每一种体系结构都有一个这样的结构体变量,对于s3c6410,来说,它属于ARMv6体系结构,它的struct proc_info_list变量在arch/arm/mm/proc-v6.S中定义,在链接的时候所有这些变量都被放在__proc_info_begin和__proc_info_end之间。因此,167行执行后,r3 = cpu_val,r4 = cpu_mask。

168行,将r4的值与r9的值相与,得到的CPU ID存在r4中。

169行,比较r4与r3的值。

170行,如果r4=r3,那么跳到175行处执行,即子程序返回。如果r4不等于r3,那么执行171行,将r5的值加上sizeof(struct proc_info_list),即指向下一个struct proc_info_list变量。

172行,比较r5和r6。

173行,如果r5小于r6,则跳转到167行,重复上面的过程。如果所有struct proc_info_list变量都比较后都没有找到对应的CPU ID,那么执行174行,r5 = 0,然后返回。

至此,__lookup_processor_type分析完毕,回到head.S的83行,把r5的值赋给r10,并影响标志位。

84行,如果r5=0,那么跳转到__error_p标号。这里假设内核是支持当前CPU的,即r5不为0,因此不分析__error_p的内容。

85行,跳到__lookup_machine_type标号处,同样是在arch/arm/kernel/head-common.S中定义:

00196 4:    .long    .00197     .long    __arch_info_begin00198     .long    __arch_info_end00211 __lookup_machine_type:00212     adr    r3, 4b00213     ldmia    r3, {r4, r5, r6}00214     sub    r3, r3, r4            @ get offset between virt&phys00215     add    r5, r5, r3            @ convert virt addresses to00216     add    r6, r6, r3            @ physical address space00217 1:    ldr    r3, [r5, #MACHINFO_TYPE]    @ get machine type00218     teq    r3, r1                @ matches loader number?00219     beq    2f                @ found00220     add    r5, r5, #SIZEOF_MACHINE_DESC    @ next machine_desc00221     cmp    r5, r600     blo    1b00223     mov    r5, #0                @ unknown machine00224 2:    mov    pc, lr00225 ENDPROC(__lookup_machine_type)

和前面的__lookup_processor_type非常类似,只不过这里查找的是struct machine_desc结构体变量,

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

网站地图

Top