现在的位置: 首页 > 综合 > 正文

u-boot学习(五):u-boot启动内核

2018年05月02日 ⁄ 综合 ⁄ 共 1807字 ⁄ 字号 评论关闭

u-boot的目的是启动内核,内核位于Flash中,那么u-boot就要将内核转移到内存中,然后执行命令运行之。这些操作是由bootcmd命令完成的。

bootcmd=nand read.jffs2 0x30007FC0 kernel;bootm 0x30007FC0

nand read.jffs2 0x30007FC0 kernel 从Flash读出内核,kernel代表从kernel分区读出内核到0x30007FC0。

1、为什么会用0x30007FC0这么怪的地址呢,因为真实的内核映像文件是uImage文件,它包含:头部+真正的内核,而头部大小正好是64字节,64字节+0x30007FC0正好是0x30008000,这个0x30008000就是真正内核的加载地址,这样安排,就不用重新移动内核了。

2、还有一个概念就是kernel分区,其实这是分区的概念,我们在include/configs/100ask24x0.h中将分区写死,分区的名字并不重要,重要的是起始地址以及分区的大小。

#define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k@0(bootloader)," \
                            "128k(params)," \
                            "2m(kernel)," \
                            "-(root)"

bootm 0x30007FC0命令在读取完内核后启动内核,调用do_bootm函数,它有零个作用:

1、根据头部移动内核到合适的位置(上面分析了,此处不需移动)。

2、启动do_bootm_linux,它也有两个作用:告诉内核一些参数,即设置启动参数;跳到入口地址启动内核。

Bootloader与内核的交互是单向的,Bootloader将各类参数传给内核。由于它们不能同时运行,传递办法只有一个:Bootloader将参数放在某个约定的地方后,再启动内核,内核启动后从这个地方获得参数。除了约定好参数存放的地址外,还要规定参数的结构。内核期望以标记列表的形式来传递启动参数。标记,就是一种数据结构;标记列表,就是挨着存放的多个标记。标记列表以标记ATAG_CORE开始,以标记ATAG_NONE结束。标记的数据结构为tag,它由一个tag_header结构和一个联合(union)组成。tag_header结构表示标记的类型及长度,比如是表示内存还是表示命令行参数等。对于不同类型的标记使用不同的联合(union),比如表示内存时使用tag_mem32,表示命令时使用tag_cmdline。数据结构tag和tag_header定义在inlcude/asm/setup.h头文件中。

struct tag_header {
	u32 size;
	u32 tag;
};

struct tag {
	struct tag_header hdr;
	union {
		struct tag_core		core;
		struct tag_mem32	mem;
		struct tag_videotext	videotext;
		struct tag_ramdisk	ramdisk;
		struct tag_initrd	initrd;
		struct tag_serialnr	serialnr;
		struct tag_revision	revision;
		struct tag_videolfb	videolfb;
		struct tag_cmdline	cmdline;

		/*
		 * Acorn specific
		 */
		struct tag_acorn	acorn;

		/*
		 * DC21285 specific
		 */
		struct tag_memclk	memclk;
	} u;
};

可以利用这些结构设置标记ATAG_CORE、设置内存标记、设置命令行标记、设置标记ATAG_CORE。源码中的setup_memory_tags、setup_commadnline_tag函数完成内存标记和命令标记的设置,一般设置这两个标记就可以了。设置完标记后,最后通过theKernel(0, bd->bi_arch_number, bd->bi_boot_params)调用内核。其中,theKernel指向内核存放的地址(对于ARM架构的CPU,通常是上面提到的0x30008000),bd->bi_arch_number就是第二阶段代码中board_init函数设置的机器类型ID,而bd->bi_boot_params就是标记列表的开始地址。

参考:韦东山 《嵌入式Linux应用开发完全手册》

抱歉!评论已关闭.