微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 嵌入式Linux之我行——u-boot-2009.08在2440上的移植详解(六)

嵌入式Linux之我行——u-boot-2009.08在2440上的移植详解(六)

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

d address toaddr(hex)//指定image的载入地址
-e:set entry point toep(hex)//内核的入口地址,一般为image的载入地址+0x40(信息头的大小)
-n:set image name toname//image在头结构中的命名
-d:use image data fromdatafile//无头信息的image文件名
-x:set XIP(execute in place)//设置执行位置

例如:
mkimage-nlinux-2.6.30.4-A arm-O linux-T kernel-C none-a 0x30008000-e 0x30008000-d zImage uImage.img

呵呵,相信此时的你拨云见日,茅塞顿开了吧!这个入口地址就是0x30008000,这也正是为什么u-boot一定要使用uImage的格式来启动内核的原因之一。注意:这里有个kernel入口地址0x30008000,在上面还提到一个u-boot参数链表在内存中的地址0x30000100,试想如果这里指定的kernel入口地址覆盖了参数链表的地址会怎么样?

好了,把上面每个步骤从下往上看就可以知道u-boot参数项在u-boot端的传递的整个流程了,那么,接下来再分析u-boot参数项在kernel端是怎样接收的。

kernel启动的流程如下图所示:

在文件arch/arm/boot/compressed/head.S中,start是zImage的起始点,部分代码如下:

start:
......

.word0x016f2818@ Magic numbers to help the loader
.wordstart@ absolute load/run zImage address
.word_edata@ zImage end address
1:movr7, r1 @ save architecture ID
movr8, r2 @ save atags pointer
......

wont_overwrite:movr0, r4
movr3, r7
bldecompress_kernel
bcall_kernel

......

call_kernel:blcache_clean_flush
blcache_off
movr0, #0@ must be zero
movr1, r7@ restore architecture number
movr2, r8@ restore atags pointer
movpc, r4@ call kernel

......

首先,将u-boot传递过来的r1(机器码)、r2(参数链表在内在中的物理地址)分别保存到ARM寄存器r7、r8中,再将r7作为参数传递给解压函数decompress_kernel(),在这个解压函数中再将r7传递给全局变量__machine_arch_type,然后在跳转到vmlinux入口之前再将r7、r8还原到r1、r2中。

在arch/arm/kernel/head.S文件中,内核vmlinux入口的部分代码如下:

ENTRY(stext)
setmodePSR_F_BIT|PSR_I_BIT|SVC_MODE,r9 @ ensure svc mode @andirqs disabled
mrcp15,0,r9,c0,c0@ get processor id
bl __lookup_processor_type@ r5=procinfo r9=cpuid
movsr10,r5 @ invalid processor(r5=0)?
beq__error_p @ yes,errorp
bl __lookup_machine_type@ r5=machinfo
movsr8,r5 @ invalid machine(r5=0)?
beq__error_a @ yes,errora
bl __vet_atags
bl __create_page_tables

......


首先从ARM特殊寄存器(CP15)中获得ARM内核的类型,从处理器内核描述符(proc_info_list)表(__proc_info_begin—__proc_info_end)中查询有无此ARM 内核的类型,如果无就出错退出。处理器内核描述符定义在include/asm-arm/procinfo.h中,具体的函数实现在 arch/arm/mm/proc-xxx.S中,在编译连接过程中将各种处理器内核描述符组合成表。接着从机器描述(machine_desc)表(__mach_info_begin—__mach_info_end)中查询有无r1寄存器指定的机器码,如果没有就出错退出,所以这也说明了为什么在u-boot中指定的机器码一定要与内核中指定的一致,否则内核就无法启动。机器编号mach_type_xxx在arch/arm/tools/mach-types文件中说明,每个机器描述符中包括一个唯一的机器编号,机器描述符的定义在 include/asm-arm/mach/arch.h中,具体实现在arch/arm/mach-xxxx文件夹中,在编译连接过程中将基于同一种处理器的不同机器描述符组合成表。例如,S3C2440处理器的机器码为1008的机器描述符如下所示:

MACHINE_START(SMDK2440,"SMDK2440")

.phys_io=S3C2410_PA_UART,
.io_pg_offst=(((u32)S3C24XX_VA_UART)>>18)&0xfffc,
.boot_params=S3C2410_SDRAM_PA+0x100,//注意:这个地址就是与u-boot中参数链表在内存中的物理地址相对应

.init_irq=s3c24xx_init_irq,
.map_io=smdk2440_map_io,
.init_machine=smdk2440_machine_init,
.timer=&s3c24xx_timer,
MACHINE_END

最后就打开MMU,并跳转到 init/main.c的start_kernel()初始化系统。函数start_kernel()的部分代码如下:

asmlinkagevoid__init start_kernel(void)
{
......
setup_arch(&command_line);
......
}

函数setup_arch在arch/arm/kernel/setup.c中实现,部分代码如下:

void__init setup_arch(char**cmdline_p)
{
......
setup_processor();
mdesc=setup_machine(machine_arch_type);
......
parse_tags(tags);
......
}


setup_processor()函数从处理器内核描述符表中找到匹配的描述符,并初始化一些处理器
变量。setup_machine()用机器编号(在解压函数decompress_kernel 中被赋值)作为参数返回机器描述符。从机器描述符中获得内核参数的物理地址,赋值给tags 变量。然后调用parse_tags()函数分析内核参数链表,把各个参数值传递给全局变量。这样内核就收到了u-boot传递的参数。

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

网站地图

Top