1.启动内核过程详解

u-boot命令中,我们用print打印信息

看到u-boot启动命令:bootcmd=nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0

这里包含两条信息:读内核和启动内核

 

分析

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

从Nand读出内核,从哪里读:从kernel分区(1)

                             放到哪里去:---0x30007FC0

(1)什么是分区

    PC:硬盘有分区表

嵌入式Flash:没有分区表

但是我们要让FLASH实现的是有分区:

所以我们所谓的有分区,是在源码里写死了。

如:

我们也可以在u-boot命令端上输入:mtd参看分区

其中0x00060000 就是内核(uImage)存放的位置(相对于为我的开发版)

我们在u-boot命令输入bootm时,会输出0x30008000这个就是把内核读到SDRAM的位置

FLASH的0x00060000  读到——> SDRAM 的0x30008000

nand read.jffs2 0x30007FC0 kernel  --0x00020000      0x00060000   

 

2.bootm 0x30007FC0

(1)怎么启动,我们参看u-boot-1.1.6\common\Cmd_bootm.c的

int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])

(2)我们先来说一下内核格式

        内核是放在FLASH中,以uImage(64字节头部+真正内核组成)存在。

我们在do_bootm中看到有头部结构体

这里面定义了头部的各种信息,我们关系load和rp这两个。

load:加载地址(内核存放的地址)

ep:入口地址(启动内核时跳到的地址)

我们在u-boot命令中启动内核时一般是输入bootm  地址(uImage存放的地址)

我们想一下,bootm应该会去头部读出加载地址,如果它发现这个真正的内核不在它的加载地址的话,它就要把内核移到他的加载地址去,最后到入口地址去执行

代码里得到验证

如果内核刚好放在加载地址,就不用移动

我们的jz2440开发板设置的加载地址是0x30008000,64字节+0x30007FC0=0x30008000

所以,为什么一开始程序要

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

现在我们知道了是去头部地址开始读

 

(3)启动

我们一路把Cmd_bootm.c的do_bootm函数读下来,当移动内核到加载地址后,正式开始启动,由函数

do_bootm_linux  (cmdtp, flag, argc, argv,addr, len_ptr, verify);完成

 

到这里,函数先要做的有两点:

                            {

                            |   1.u-boot告诉内核一些参数:设置启动参数

do_bootm_linux:

                            |   2.跳到入口地址启动内核

                            {

完成这两步,才是真正去启动内核

我们分析这个u-boot-1.1.6\lib_arm\Armlinux.c的do_bootm_linux函数定义

这些参数就在这里定义

发现

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

hdr->ih_ep就是头部的入口地址

theKernel (0, bd->bi_arch_number, bd->bi_boot_params);这个就是真正的启动内核

 

(4)分析启动参数

这里我们又想到,我们启动内核后,之前的u-boot怎么和内核交互数据:在某个地址(我的开发板是0x30000100)按某种格式(TAG)保存数据(启动参数,就是上面的参数)

    setup_start_tag (bd); 启动参数

    setup_memory_tags (bd);  内存参数

    setup_commandline_tag (bd, commandline); 命令参数

    setup_end_tag (bd);  

分析setup_start_tag (bd);

看看tag的定义

 

搜setup_start_tag里的bi_boot_params可得知参数是放在0x30000100和我们刚才说的一样

最终分析四个参数    setup_start_tag (bd); 启动参数

    setup_memory_tags (bd);  内存参数

    setup_commandline_tag (bd, commandline); 命令参数

    setup_end_tag (bd);  

 

 

 

得出,我们的内核启动前,会先到地址0x30000100读取启动参数,再去启动内核

在回顾u-boot的终极目的:启动内核

(1)从Flash读出内核(2)启动(1.设置启动参数,2.到入口地址启动)

是不是豁然开朗

 

(5)分析函数theKernel (0, bd->bi_arch_number, bd->bi_boot_params);这个函数启动了内核

参数bd->bi_boot_params:是我们刚才那些参数

参数bd->bi_arch_number:机器ID

 

 

最终,系统进入了内核,u-boot把控制权交给了内核,以后没u-boot什么事了

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值