U-boot 与kernel的关系

来源:互联网 发布:2016年世界经济数据 编辑:程序博客网 时间:2024/05/19 13:25

U-boot 与kernel的关系(转载)  

   U-boot为kernel服务,u-boot为kernel提供一些kernel无法知道的信

息,比如ramdisk在RAM中的地址

   Kernel也必须为U-boot提供必要的信息:通过mkimage这个tool可以给

zImage添加一个header: 

typedef struct image_header 

{

uint32_t ih_magic; /* Image Header Magic Number */

uint32_t ih_hcrc; /* Image Header CRC Checksum */

uint32_t ih_time; /* Image Creation Timestamp */

uint32_t ih_size; /* Image Data Size */

uint32_t ih_load; /* Data  Load  Address */

uint32_t ih_ep; /* Entry Point Address */

uint32_t ih_dcrc; /* Image Data CRC Checksum */

uint8_t ih_os; /* Operating System */

uint8_t ih_arch; /* CPU architecture */

uint8_t ih_type; /* Image Type */

uint8_t ih_comp; /* Compression Type */

uint8_t ih_name[IH_NMLEN]; /* Image Name */

} image_header_t;

   此header是如何生成的?利用u-boot里面的mkimage工具来生成uImage(u-boot源码包/tools/mkimage.c )

用法:

-A arm     -------- 架构是arm

-O linux    -------- 操作系统是linux

-T kernel  -------- 类型是kernel

-C none    -------- 压缩类型为无压缩

-a 30008000 ---- image的载入地址(hex)

-e 30008040 ---- 内核的入口地址(hex),因为信息头的大小是0x40

-n linux-2.6.18.8 --- image的名字

-d zImage             ---- 无头信息的image文件名

uImage2.6. 18.8    ---- 加了头信息之后的image文件名

生成uImage 的方法:

   mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 

30008000 -n linux-2.6.18.8 -d zImage uImage2.6.18.8 

注释:这里的意思就是把zImage的前面加上一个0x40长度的header,没有

压缩(none),kernel的load地址是:-a 30008000; kernel的入口地址是

–e 30008000 

   不知道是否对入口地址有疑问:为什么入口地址不是 0x80003040 呢?

答案就在 u-boot 里面的bootm命令的实现代码上,我会在 “分析bootm

源码”中分析介绍,来详细分析。

1> mkimage 如何指定入口参数 ( -e  0xxxxxx)

2> mkimage 指定了入口参数后, 你用tftpboot 下载kernel到哪个地址?

Mkimage 的执行结果:

#/usr/local/src/u-boot-1.2.0/tools/mkimage -A arm -O linux-T kernel -C none -a 30008000 -e 30008000 -n linux-2.6.18.8   -d zImage uImage2.6.18.8

imagefile = uImage2.6.18.8

Image Name:   linux-2.6.18.8

Created:      Fri Jun 15 13:56:06 2007

Image Type:   ARM Linux Kernel Image (uncompressed)

Data Size:    1068212 Bytes = 1043.18 kB = 1.02 MB

Load Address: 0x30008000

Entry Point:  0x30008000

准备工作:快速数制转换:

为了方便后面的图的计算,先熟练换算:

0x0000,0100 256 Byte

0x0000,1000 4K

0x0001,0000 64K

0x0010,0000 1M

0x0100,0000 16M

0x1000,0000    256M

0x8000  就是 8(十进制)X 0x1000 = 32K

0x400000 =  4M

U-boot 与kernel的关系(转载) - grape - cug_zhang 的博客

(30000000 - 34000000)

    这些地址是怎么得来呢? 哪些是固定呢? 哪些是自己计算得来得呢? 哪

些是比较灵活得呢?

结论:

生成uImage的方法: 利用mkimage命令把zImage包装 , 

mkimage -A arm -O linux -T kernel -C none -a 30008000 -e 30008000 -n linux-2.6.18.8 -d zImage uImage2.6.18.8 

    下面的总结都是 稍微调整一下上面的 -a -e -x 参数什么的,你会发现这些参数不同,就会导致你 tftp dowload的地址会有不同,有的时候kernel会run不起来。 

    addr是地址,如果两个地方都addr,说明是同一个地址,否则我会比如addr+0x40 的 

1> mkimage -a addr -e addr 

   那么tftp 下载kernel 就一定不能下载 addr处, 否则,kernelrun不起来。 因为u-boot并不搬运kernel 代码, 也就是没有把header去掉。 所以只有入口是addr+0x40才是kernel的入口。 

   当然也不能下到 < addr + 2M 的地方,否则搬运的时候会有一些覆盖,导致搬运后的kernel不完整, bootm的时候,u-boot就会RESET的。 

2> mkimage -a addr -e addr+0x40 或者mkimage -a addr -x 两个是一

回事 。 -x的意思 是就在kernel所在地执行。不必搬运(代码里面的条

件是 tftp 下kernel的时候 就下到 addr处,这样bootm就没有必要搬运

了) 

   这种情况: tftp 就一定把kernel下载到addr处,这样u-boot 在bootm

的时候就不搬运了。 其实这种情况更多的用在flash里面 。 

//  -----------------------------------------------------

switch (hdr->ih_comp) 

{  

case IH_COMP_NONE:  // -C none

if(ntohl(hdr->ih_load) == addr) 

         { //不搬运

    printf (“   XIP %s ... ”, name);//注意屏幕信息

   } 

       else 

         {

memmove ((void *) ntohl(hdr->ih_load), (uchar *)data, len);   //搬运:这里data指向实际的kernel ,把kernel搬运到hdr->ih_load处,这个值就是mkimage –d 0x30008000

  }

}

Bootm 命令源码分析(源码就是最好的文档)

对于u-boot最常用得命令莫过于:

Tftpboot 和 bootm 命令了。

    具体分析一下这两个过程, 这样大家用的时候就知其所以然了,也

就能少犯一些错误了。 具体参考:common/cmd_bootm.c  è do_bootm() 

还有do_bootm_linux() 函数

比如 :

Tftpboot 0x3300,0000  uImage

Tftpboot 0x3080,0000  ramdisk.gz

Bootm 0x3300,0000  0x3080,0000

    过程:tftpboot把uImage 下载地址0x33000000 ,然后把ramdisk.gz 

下载到0x30800000 .最后执行bootm ,

    Bootm 会首先取出uImage的0x40个header,然后读取header的

ih_load字段,只有这样u-boot 才知道把uImage搬运到哪里。   

在中间的时候,u-boot会判断tftp 下载kernel的地址是否等于ih_load ,这里非常关键。如果等于就不搬运;如果不等于u-boot 把指针定位到0x40之后的位置, 这里才是真正的kernel(zImage), 把zImage 搬运(copy)到  ih_load这个地址上去。 然后执行kernel 。

     一般情况下都在生成 vmlinux 后,再对内核进行压缩成zImage,

原创粉丝点击