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

1.启动内核过程详解

看到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实现的是有分区:

1.启动内核过程详解

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

如:

1.启动内核过程详解

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

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

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

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

1.启动内核过程详解

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中看到有头部结构体

1.启动内核过程详解

1.启动内核过程详解

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

1.启动内核过程详解1.启动内核过程详解

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

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

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

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

代码里得到验证

1.启动内核过程详解

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

我们的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函数定义

这些参数就在这里定义

1.启动内核过程详解

发现

1.启动内核过程详解

1.启动内核过程详解

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);

1.启动内核过程详解

看看tag的定义

1.启动内核过程详解

 

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

1.启动内核过程详解

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

    setup_memory_tags (bd);  内存参数

    setup_commandline_tag (bd, commandline); 命令参数

    setup_end_tag (bd);  

 

 

1.启动内核过程详解

 

得出,我们的内核启动前,会先到地址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

1.启动内核过程详解

 

 

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

相关文章:

  • 2022-01-15
  • 2022-01-12
  • 2021-04-06
  • 2021-08-12
  • 2021-10-17
  • 2021-04-13
  • 2021-08-28
  • 2021-12-12
猜你喜欢
  • 2022-12-23
  • 2021-12-16
  • 2021-12-29
  • 2021-11-03
  • 2021-11-07
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案