<Linux>u-boot启动Linux内核分析

来源:互联网 发布:3dmax的mac 编辑:程序博客网 时间:2024/05/27 20:26

一、uImage的结构

通过前面分析u-boot的启动流程,我们可以知道,u-boot启动内核的命令是bootcmd=nand read.jffs 0x30007FC0  kernel:bootm 0x30007FC0;也就是先吧内核读到内存上,再去启动内核。在此之前我们先来明确一个定义,nandflash上的内核成为:uImage

其格式为:一个64k的头部+真正的内核

其中头部的定义如下:


我们重点关注的是ih_load(加载地址)和ih_ep(入口地址)这两个变量。

二、bootm执行流程

bootm首先读取头部,知道它的加载地址和入口地址,如果bootm发现内核并不在加载地址上,那么就把内核放到加载地址上,并跳到入口地址去执行

而如果内核刚好在加载地址上,那就不用转移,节约时间。代码如下:


321行,这个判断的意思是说如果内核刚好在加载地址上,那么bootm就直接跳到入口地址执行,而如果bootm发现内核并没有在加载地址上,那么就先将其转移到加载地址上,具体实现的语句是340行的调用memmove函数,将data也就是真正的内核数据转移到load(加载地址)上。

而一旦把内核转移到加载地址上,那么bootm就跳到入口地址处执行,下面来分析具体的代码是如何实现的。


418行,bootm通过do_bootm_linux这个函数来执行启动内核,我们跟踪这个函数看看它的结构:


而在这个函数里面,我们真正要关心的是theKernel (0, bd->bi_arch_number, bd->bi_boot_params);这个函数的调用,继续查看kernel的定义:

theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);

很明显,:theKernel就是入口的地址。也就是说,执行theKernel这个函数实际上就是在入口函数执行内核。而我们看一下theKernel的第二个参数:bi_boot_params,也就是一些参数设定。参数分析如下:


在do_bootm_linux函数下,调用这样一些函数,这些函数就是进行一些参数的设定,对应的我们可以看到这些设置参数以setup_start_tag (bd)开始,以setup_end_tag (bd);结束。我们先跟踪一下setup_start_tag (bd):


在setup_start_tag 函数中,283行要做的事情就是确定tag这个结构体的起始地址,bi_boot_params这个变量的定义是0x30000100,也就是tag的起始地址,而在setup_start_tag 具体给 size、flag、pagesize、rootdev这些变量设置函数,接着指向下一个tag。

同样地,我们可以分析接下来的几个函数,最后它们要做的事情如下:


就是说,要启动内核的时候,bootm要进行这些参数的设定,最后才是跳到入口地址处执行。

最后还是来总结一下u-boot启动整个内核的过程:

整个u-boot的内心函数是:

s = getenv ("bootcmd");和run_command(s…),即获取并且执行命令。

而在run_command(s…)这个函数中,最重要的是这个条命令:bootcmd=nand_read.jffs 0x30007FC0  kernel:bootm 0x30007FC0 

也就是,从flash把uImage读到内存中,然后做一些参数的设定,之后启动内核。


0 0
原创粉丝点击