uImage、zImage、bzImage、vlinzx区别

http://blog.163.com/tianjunqiang666@126/blog/static/87259119201322692242257/



uImage、zImage、bzImage、vlinzx区别

http://hi.baidu.com/cbncb/item/389b155c62acd316abf6d748

在网络中,不少服务器采用的是Linux系统。为了进一步提高服务器的性能,可能需要根 据特定的硬件及需求重新编译Linux内核。编译Linux 内核,需要根据规定的步骤进行,编译内核过程中涉及到几个重要的文件。比如对于RedHat Linux,在/boot目录下有一些与Linux内核有关的文件 .
  编译过RedHat Linux内核的人对其中的System.map、vmlinuz、initrd-2.4.7-10.img印象可能比较深刻,因为编译内核过程中涉及到这些文件的建立等操作。那么这几个文件是怎么产生的?又有什么作用呢?

对于Linux内核,编译可以生成不同格式的映像文件,例如:
# make zImage
# make uImage
# make bzImage
zImage是ARM Linux常用的一种压缩映像文件不能超过512KB,bzImage 即bigzImage ,二者的内核都是gzip压缩的
uImage是U-boot专用的映像文件,它是在zImage之前加上一个长度为0x40的“头”,说明这个映像文件的类型、加载位置、生成时间、大小等信息。换句话说,如果直接从uImage的0x40位置开始执行,zImage和uImage没有任何区别。另外,Linux2.4内核不支持uImage,Linux2.6内核加入了很多对嵌入式系统的支持,但是uImage的生成也需要设置。

  一、vmlinuz

  vmlinuz是可引导的、压缩的内核。“vm”代表“Virtual Memory”。Linux 支持虚拟内存,不像老的操作系统比如DOS有640KB内存的限制。Linux能够使用硬盘空间作为虚拟内存,因此得名“vm”。vmlinuz是可执行 的Linux内核,它位于/boot/vmlinuz,它一般是一个软链接,比如图中是vmlinuz-2.4.7-10的软链接。

vmlinuz的建立有两种方式。

一是编译内核时通过“make zImage”创建,手动拷贝到/boot目录下面。zImage适用于小内核的情况,它的存在是为了向后的兼容性。

  二是内核编译时通过命令make bzImage创建,然后手动拷贝至/boot目录下。bzImage是压缩的内核映像,需要注意,bzImage不是用bzip2压缩的,bz表示“big zImage”。 bzImage中的b是“big”意思。 zImage(vmlinuz)和bzImage(vmlinuz)都是用gzip压缩的。它们不仅是一个压缩文件,而且在这两个文件的开头部分内嵌有gzip解压缩代码。所以你不能用gunzip或gzip –dc解包vmlinuz。

内核文件中包含一个微型的gzip用于解压缩内核并引导它。两者的不同之处在于,老的zImage解压缩内核到低端内存(第一个 640K),bzImage解压缩内核到高端内存(1M以上)。如果内核比较小,那么可以采用zImage或bzImage之一,两种方式引导的系统运行 时是相同的。大的内核采用bzImage,不能采用zImage。

vmlinux是未压缩的内核,vmlinuz是vmlinux的压缩文件。

  二、initrd-x.x.x.img

  initrd是“initial ramdisk”的简写。initrd一般被用来临时的引导硬件到实际内核vmlinuz能够接管并继续引导的状态。图中的initrd-2.4.7-10.img主要是用于加载ext3等文件系统及scsi设备的驱动。

  比如,使用的是scsi硬盘,而内核vmlinuz中并没有这个scsi硬件的驱动,scsi模块是存储在根文件系统的/lib/modules下的,那么在装入scsi模块之前,内核不能加载根文件系统。为了解决这个问题,可以引导一个能够读实际内核的initrd内核并用initrd修正 scsi引导问题。initrd-2.4.7-10.img是用gzip压缩的文件,initrd实现加载一些模块和安装文件系统等功能。

initrd映象文件是使用mkinitrd创建的。mkinitrd实用程序能够创建initrd映象文件。这个命令是RedHat专有的(这也是为什么,在Linux内核包里/Documentation/Changes里面没有提到要将mkinitrd升级)。其它Linux发行版或许有相应的命令。这是个很方便的实用程序。具体情况请看帮助:man mkinitrd下面的命令创建initrd映象文件。

initrd映象文件是使用mkinitrd创建的。mkinitrd实用程序能够创建initrd映象文件。这个命令是RedHat专有的。其它Linux发行版或许有相应的命令。这是个很方便的实用程序。具体情况请看帮助:man mkinitrd下面的命令创建initrd映象文件。

  三、uImage文件

vmlinux是内核文件,zImage是一般情况下默认的压缩内核映像文件,压缩vmlinux,加上一段解压启动代码得到。而uImage是u-boot使用bootm命令引导的Linux压缩内核映像文件格式,是使用工具mkimage对普通的压缩内核映像文件(zImage)加工而得。它是uboot专用的映像文件,它是在zImage之前加上一个长度为 64字节的“头”,说明这个内核的版本、加载位置、生成时间、大小等信息;其0x40之后与zImage没区别。

由于bootloader一般要占用0X0地址,所以,uImage相比zImage的好处就是可以和bootloader共存。

其实就是一个自动跟手动的区别,有了uImage头部的描述,u-boot就知道对应Image的信息,如果没有头部则需要自己手动去搞那些参数。

如何生成uImage文件?首先 在uboot的/tools目录下寻找mkimage文件,把其copy到系统/usr/local/bin目录下,这样就完成制作工具。然后在内核目录下运行make uImage,如果成功,便可以在arch/arm/boot/目录下发现uImage文件,其大小比zImage多64个字节。

此外,平时调试用uImage,不用去管调整了哪些东西;zImage则是一切OK后直接烧0X0。开机就运行


修改过程
首先修改的地方是uboot的bootcmd命令
修改图中红色圈下的地方  即启动位置
OK6410 UBOOT移植(10)引导uImage - 寒江独垂 - 寒江独垂
使用SD卡启动盘启动烧写uboot.bin文件
之后切换开关从NandFlash启动,即启动下载进去的uboot
前面已经移植好的DNW进去了
这里可以支持DNW下载

在移植日志
OK6410移植LINUX3.5(4)中linux'源文件中使用make uImage  生成uImage
在使用make uImage时需要用到mkinmge  可以使用apt-get获得
 之后在dnw中下载uImage
SMDK6400 # dnw 50008000
OTG cable Connected!
Now, Waiting for DNW to transmit data
Download Done!! Download Address: 0x50008000, Download Filesize:0x1dafa0
Checksum is being calculated..
Checksum O.K.
SMDK6400 # nand erase 100000 500000
NAND erase: device 0 offset 0x100000, size 0x500000
Erasing at 0xa00100000 --   80x5000480000 -- 128nand write.e 50008000 100000 500000
NAND write: device 0 offset 0x100000, size 0x500000
 5242880 bytes written: OK
 
启动信息如下
OK6410 UBOOT移植(10)引导uImage - 寒江独垂 - 寒江独垂
停在了starting kernel上不在启动
需要修改linux'源码下的文件
这里是修改启动位置和入口位置
参考http://www.cnblogs.com/sywtt/archive/2012/01/25/2329284.html
OK6410 UBOOT移植(10)引导uImage - 寒江独垂 - 寒江独垂
然后重新生成uImage
OK6410 UBOOT移植(10)引导uImage - 寒江独垂 - 寒江独垂
 
OK6410 UBOOT移植(10)引导uImage - 寒江独垂 - 寒江独垂
这里为止正常启动了
OK6410 UBOOT移植(10)引导uImage - 寒江独垂 - 寒江独垂
 
 

uboot load address、entry point、 bootm address以及kernel运行地址的意义及联系

按各地址起作用的顺序,uboot引导linux内核启动涉及到以下地址:

  1. load address:
  2. entry point: 这两个地址是mkimage时指定的
  3. bootm address:bootm为uboot的一个命令,以此从address启动kernel
  4. kernel运行地址:在具体mach目录中的Makefile.boot中指定,为kernel启动后实际运行的物理地址
mkimage -n 'linux-3.2.1' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage uImage

理论上因为mkimage要为zImage加上0x40字节的header,所以entry point = load address + 0x40

但由于uboot 的bootm对uImage处理不是简单的go操作,其对前三个地址都有比较判断,所以在实际的操作中,就分为两种不同的情况:

1. bootm地址和load address一样

  此种情况下,bootm不会对uImage header后的zImage进行memory move的动作,而会直接go到entry point开始执行。因此此时的entry point必须设置为load address + 0x40。如果kernel boot过程没有到uncompressing the kernel,就可能是这里设置不对。

boom address == load address == entry point - 0x40

具体细节可参看uboot代码common/cmd_bootm.c中bootm_load_os函数的实现:

复制代码
        switch (comp) {
        case IH_COMP_NONE:
                if (load == blob_start || load == image_start) {
                        printf("   XIP %s ... ", type_name);
                        no_overlap = 1;
                } else {
                        printf("   Loading %s ... ", type_name);
                        memmove_wd((void *)load, (void *)image_start,
                                        image_len, CHUNKSZ);
                }
                *load_end = load + image_len;
                puts("OK\n");
                break;
复制代码

2. bootm地址和load address不一样(但需要避免出现memory move时出现覆盖导致zImage被破坏的情况)

  此种情况下,bootm会把uImage header后的zImage move到load address(见上方代码),然后go到entry point开始执行。 由此知道此时的load address必须等于entry point。

boom address != load address == entry point

因此,在mkimage以及设置uboot boot command的时候需要注意到以上两种情况。

至于kernel的运行地址,其与前3个地址没有关系,除了要避免内存覆盖导致解压后kernel不完整的情况。

zImage的头部有地址无关的自解压程序,因此刚开始执行的时候,zImage所在的内存地址(entry point)不需要同编译kernel的地址相同。自解压程序会把kernel解压到编译时指定的物理地址,然后开始地址相关代码的执行。在开启MMU之前,kernel都是直接使用物理地址(可参看System.map)。


 
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值