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

ARM linux的启动部分源代码简略分析

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

t machine_desc {

/*

* Note! The first four elements are used

* by assembler code in head.S, head-common.S

*/

unsigned int nr; /* architecture number */

unsigned int phys_io; /* start of physical io */

unsigned int io_pg_offst; /* byte offset for io

* page tabe entry */

const char *name; /* architecture name */

unsigned long boot_params; /* tagged list */

unsigned int video_start; /* start of video RAM */

unsigned int video_end; /* end of video RAM */

unsigned int reserve_lp0 :1; /* never has lp0 */

unsigned int reserve_lp1 :1; /* never has lp1 */

unsigned int reserve_lp2 :1; /* never has lp2 */

unsigned int soft_reboot :1; /* soft reboot */

void (*fixup)(struct machine_desc *,

struct tag *, char ,

struct meminfo *);

void (*map_io)(void);/* IO mapping function */

void (*init_irq)(void);

struct sys_timer *timer; /* system tick timer */

void (*init_machine)(void);

};

同样这个例程也用到了同上面很相似的方式来获得符号的地址:

adr r3, 4b
b代表back,即向后,这个符号为4,紧接着我们前面看到的那个为3的标号:

4: .long .

.long __arch_info_begin

.long __arch_info_end

在文件arch/arm/kernel/vmlinux.lds.S中我们可以看到段的定义:

__arch_info_begin = .;

*(.arch.info.init)

__arch_info_end = .;

这两个符号也是分别表示某种初始化的段的开始地址和结束地址。为了找到段的填充内容,还是得要了解一下到底都有哪些struct machine_desc结构体类型变量声明了要被放到这个段的。用关键字.arch.info.init来搜索所有的内核源文件。在arch/arm/include/asm/mach/arch.h文件中我们看到:

#define MACHINE_START(_type,_name) \

static const struct machine_desc __mach_desc_##_type \

__used \

__attribute__((__section__(".arch.info.init"))) = { \

.nr = MACH_TYPE_##_type, \

.name = _name,

#define MACHINE_END \

};

定义机器结构体,也就是.arch.info.init段中的内容,都是要通过两个宏MACHINE_START和MACHINE_END来完成的啊,MACHINE_START宏定义一个truct machine_desc结构体,并初始化它的机器号字段和机器名字段,可以在arch/arm/tools/mach-types文件中看到各种平台的机器号的定义。那接着我们来搜MACHINE_START吧,这是一个用于定义机器结构体的宏,所以可以看到这个符号好像都是在arch/arm/mach-*/mach-*.c这样的文件中出现的,我们感兴趣的应该是arch/arm/mach-s3c2440/ mach-mini2440.c文件中的这个符号:

MACHINE_START(MINI2440, "MINI2440")

/* Maintainer: Michel Pollet */

.phys_io = S3C2410_PA_UART,

.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

.boot_params = S3C2410_SDRAM_PA + 0x100,

.map_io = mini2440_map_io,

.init_machine = mini2440_init,

.init_irq = s3c24xx_init_irq,

.timer = &s3c24xx_timer,

MACHINE_END

OK,__lookup_machine_type这个例程的我们也搞明白了。回忆一下,启动代码现在已经完成的工作,R10寄存器中为指向proc_info_list结构体的指针(物理地址空间),这个结构体包含有关于我们的处理器的一些重要信息。R8寄存器中为指向一个与我们的平台相匹配的machine_desc结构体的指针,这个结构体中保存有一些关于我们的平台的重要信息。

回来接着看arch/arm/kernel/head.S文件中的stext:

bl __vet_atags

这个例程同样同样也是在arch/arm/kernel/head-common.S文件中定义:

__vet_atags:

tst r2, #0x3 @ aligned?

bne 1f

ldr r5, [r2, #0] @ is first tag ATAG_CORE?

cmp r5, #ATAG_CORE_SIZE

cmpne r5, #ATAG_CORE_SIZE_EMPTY

bne 1f

ldr r5, [r2, #4]

ldr r6, =ATAG_CORE

cmp r5, r6

bne 1f

mov pc, lr @ atag pointer is ok

1: mov r2, #0

mov pc, lr

ENDPROC(__vet_atags)

这个例程接收机器信息(R8寄存器)为参数,并检测r2中传入的ATAGS 指针的合法性。内核使用tag来作为bootloader传递内核参数的方式。系统要求r2中传进来的ATAGS指针式4字节对齐的,同时要求ATAGS列表的第一个tag是一个ATAG_CORE类型的。

此时R10寄存器中保存有指向CPU信息结构体的指针,R8寄存器中保存有指向机器结构体的指针,R2寄存器中保存有指向tag表的指针,R9中还保存有CPU ID信息。

回到arch/arm/kernel/head.S文件中的stext,之后就要进入初始化过程中比较关键的一步了

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

网站地图

Top