make zImage和make uImage的区别和mkimage工具的使用
剛剛接觸到linux內核編譯過程的時候,相信不少人跟我一樣,都是按照手冊或者網上的教程一步一步的執行,對于其中的很多原理和過程都是一知半解,這其中有一個很常見的問題,就是make image命令。
因為大家都知道,在編譯linux內核時,往往會涉及到以下3個命令:
- make Image
- make zImage
- make uImage
那么,這3個命令分別是做什么的?所生成的對象又有什么區別呢?
在網上查閱了很多的資料和博客,發現絕大部分都是千篇一律的說法,在對比上述3個概念的時候,順帶還對vmlinux、vmlinuz、initrd等諸多概念胡亂進行一通比較,概念模糊,根本沒把問題解釋清楚,很明顯是互相摘抄、囫圇吞棗的。算了,還是我自己來捋一捋好了。
1、首先來解釋一下前面2個命令的區別。Image為普通的內核映像文件,而zImage為壓縮過的內核映像文件(其中的z字母就是壓縮的意思)。一般情況下,編譯出來的Image大約為4M,而zImage不到2M。
2、然后來解釋一下第3個命令uImage。它是uboot專用的映像文件,它是在zImage之前加上一個長度為64字節的“頭”,說明這個內核的版本、加載位置、生成時間、大小等信息;其0x40之后與zImage沒區別。換句話說,如果直接從uImage的0x40位置開始執行,那么zImage和uImage沒有任何區別。
為什么要用uboot 的mkimage工具處理內核映像zImage呢?
因為uboot在用bootm命令引導內核的時候,bootm需要讀取一個64字節的文件頭,來獲取這個內核映象所針對的CPU體系結構、OS、加載到內存中的位置、在內存中入口點的位置以及映象名等等信息。這樣bootm才能為OS設置好啟動環境,并跳入內核映象的入口點。而mkimage就是添加這個文件頭的專用工具。具體的實現請看uboot中bootm的源碼和mkimage的源碼。
3、另外,要額外說明的是如何來生成uImage。資料上顯示,linux2.4之前版本的內核不支持直接生成uImage鏡像文件,需要手動來生成。而對于linux2.6之后版本的內核,盡管加入了很多對嵌入式系統的支持,但是uImage的生成也需要單獨設置。
那究竟要如何生成uImage呢?這就要從uboot處來想辦法了。
uboot源代碼的tools/目錄下有一個mkimage工具,這個工具可以用來制作不壓縮或者壓縮的多種可啟動映象文件。
leon@Ubuntu:~/u-boot-2010.03/tools$ ls bddb fdt_ro.o img2srec.o mkimage.c bin2header.c fdt_rw.o imls mkimage.h bmp_logo fdt_strerror.o imximage.c mkimage.o bmp_logo.c fdt_wip.o imximage.h mpc86x_clk.c bmp_logo.o fit_image.c imximage.o ncb.c crc32.o fit_image.o inca-swap-bytes.c netconsole default_image.c gdb jtagconsole os_support.c default_image.o gen_eth_addr kwbimage.c os_support.h easylogo gen_eth_addr.c kwbimage.h os_support.o env gen_eth_addr.o kwbimage.o scripts envcrc getline.c logos setlocalversion envcrc.c getline.h Makefile sha1.o envcrc.o image.o md5.o ubsha1.c env_embedded.o img2brec.sh mingw_support.c updater fdt_host.h img2srec mingw_support.h fdt.o img2srec.c mkimageleon@Ubuntu:~/u-boot-2010.03/tools$ ll mkimage -rwxrwxr-x 1 leon leon 62384 1月 26 22:30 mkimage*leon@Ubuntu:~/u-boot-2010.03/tools$ file mkimage mkimage: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x366213ad60c7c7fc6793def77d2df59d2ab85d5d, stripped下面介紹下mkimage這個工具的用法:
參數說明:
- -A:指定 CPU 的體系結構,可用值有:alpha、arm 、x86、ia64、mips、mips64、 ppc 、s390、sh、sparc 、sparc64、m68k 等;
- -O:指定操作系統類型,可用值有:openbsd、netbsd、freebsd、4_4bsd、linux、 svr4、esix、solaris、irix、sco、dell、ncr、lynxos、vxworks、psos、qnx、u-boot、rtems、artos;
- -T:指定映象類型,可用值有:standalone、kernel、ramdisk、multi、firmware、script、filesystem;
- -C:指定映象壓縮方式,可用值有:
:none 不壓縮(一般使用這個,因為 zImage 是已經被 bzip2 壓縮過的自解壓內核);
:zip 用 gzip 的壓縮方式;
:bzip2 用 bzip2 的壓縮方式; - -a:指定映象在內存中的加載地址,映象下載到內存中時,要按照用 mkimage 制作映象 時,這個參數所指定的地址值來下載;
- -e:指定映象運行的入口點地址,這個地址就是-a 參數指定的值加上 0x40(因為前面有個 mkimage 添加的 0x40 個字節的頭);
- -n:指定映象名;
- -d:指定制作映象的源文件;
以下是我的示例(摘自tekkaman的制作內核映像的命令):
mkimage -n 'mykernel' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage uImage.img該命令的作用就是,將目錄下的zImage文件制作成符合uboot引導要求的uImage.img文件,使得uboot能夠正確的引導和啟動linux內核。
其中有幾點要注意:
1、關于偏移量的問題(請千萬注意這一點)。’-e’命令之后的地址,必須比’-a’命令后的地址多0x40的偏移量。一旦沒有偏移,則會導致系統出現引導失敗的問題。而很多博客文章里,居然把這2個值寫成一樣的,都寫成0x30008000。也不知道各位博主們自己到底有沒有嘗試過,害我一開始折騰了半天才發現這個問題,簡直就是浪費我的時間。
**2、執行該命令時,要注意一下權限的問題。**我一開始時在虛擬機的共享目錄下執行,一直提示失敗:
leon@Ubuntu:/mnt/share/tmp/zImages$ mkimage -n 'mykernel' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage uImage.img mkimage: Can't map uImage.img: Invalid argument后來跳轉到~目錄下執行,就一下子成功了。成功后的提示信息如下:
leon@Ubuntu:~$ mkimage -n 'mykernel' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage uImage.img Image Name: mykernel Created: Wed Feb 1 14:50:47 2017 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 2266576 Bytes = 2213.45 kB = 2.16 MB Load Address: 30008000 Entry Point: 30008040將生成的image文件,拷貝到nfs目錄下,按照uboot環境變量的預設名稱改名,然后啟動uboot,系統成功引導啟動!
hit any key to stop auto_boot: 0 DM9000: Found at 0x20000300, id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 Operating at 100M full duplex mode Begin to Initiate NFS Process... NFS Process Using dm9000 device NFS: File transfer via NFS:Srver_Addr: 192.168.100.120;Local_Addr: 192.168.100.230;filename: '/opt/FriendlyARM/mini2440/rootfs/zImage.img'address: 0x30008000loading...... ...........................................................................................................................................................................................................................................................................................................................................................................................................................................................done Bytes transferred = 2266640 (229610 hex) ## Booting kernel from Legacy Image at 30008000 ...Image Name: leon_20170201Created: 2017-02-01 6:50:47 UTCImage Type: ARM Linux Kernel Image (uncompressed)Data Size: 2266576 Bytes = 2.2 MBLoad Address: 30008000Entry Point: 30008040Verifying Checksum ... OKXIP Kernel Image ... OK OKStarting kernel ... Uncompressing Linux................................................................................................................................................... done, booting the kernel. Linux version 2.6.32.2-leon (leon@Ubuntu) (gcc version 4.4.3 (ctng-1.6.1) ) #1 Wed Feb 1 08:33:10 CST 2017 CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177 CPU: VIVT data cache, VIVT instruction cache...(此處略去12345678個字).....NFS root ...Done**3、將mkimage工具所在目錄加入環境變量。**可以將mkimage這個工具拷貝到usr/bin等用戶目錄下,這樣直接在命令行輸入這個命令就可以運行,而無需每次都手工指定到uboot/tools這個目錄下去,提高執行效率。當然,也可以按照我的另一篇博客(linux(ubuntu)編譯linux內核提示"mkimage" command not found)中介紹的方案,直接在ubuntu系統中安裝一下uboot的mkimage命令,效果更好。
**4、關于linux2.6之后版本的系統,是否可以直接make uImage?**這一點,雖然絕大部分的網文和博客中都說到要單獨設置,但是卻沒有人明確指出要如何設置。我直接在ubuntu 12.04的系統(Linux Ubuntu 3.13.0-32-generic)中輸入make uImage命令,確實能夠運行,也確實在指定的目錄下生成了uImage文件。
leon@Ubuntu:/opt/FriendlyARM/mini2440/linux-2.6.32.2$ make uImageCHK include/linux/version.h make[1]: “include/asm-arm/mach-types.h”是最新的。CHK include/linux/utsrelease.hSYMLINK include/asm -> include/asm-armCALL scripts/checksyscalls.shCHK include/linux/compile.hKernel: arch/arm/boot/Image is readyKernel: arch/arm/boot/zImage is readyUIMAGE arch/arm/boot/uImage Image Name: Linux-2.6.32.2-leon Created: Wed Feb 1 15:48:37 2017 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 2266576 Bytes = 2213.45 kB = 2.16 MB Load Address: 30008000 Entry Point: 30008000 Image arch/arm/boot/uImage is ready但是,遺憾的是,上面生成的鏡像文件,導入到開發板上卻無法執行!
hit any key to stop auto_boot: 0 DM9000: Found at 0x20000300, id: 0x90000a46 DM9000: running in 16 bit mode MAC: 08:08:11:18:12:27 Operating at 100M full duplex mode Begin to Initiate NFS Process... NFS Process Using dm9000 device NFS: File transfer via NFS:Srver_Addr: 192.168.100.120;Local_Addr: 192.168.100.230;filename: '/opt/FriendlyARM/mini2440/rootfs/zImage.img'address: 0x30008000loading...... ..........................................T .................................................................................................................................................................................................................................................................................................................................................................................................................done Bytes transferred = 2266640 (229610 hex) ## Booting kernel from Legacy Image at 30008000 ...Image Name: Linux-2.6.32.2-leonCreated: 2017-02-01 7:48:37 UTCImage Type: ARM Linux Kernel Image (uncompressed)Data Size: 2266576 Bytes = 2.2 MBLoad Address: 30008000Entry Point: 30008000Verifying Checksum ... OKXIP Kernel Image ... OK OKStarting kernel ... (卡在這里不動了............)至于失敗的原因,我覺得很有可能就是因為沒有配置參數,導致上述第一點中的偏移量沒有設置進去。這一點,從上面的Load Address和Entry Point的值就可以看出來。待后續我查找到如何配置make uImage命令的參數時,再進行驗證!
不管如何,今天總算是成功搞清楚了make zImage和make uImage命令的區別,也成功編譯出了uImage鏡像文件,并下載到mini2440開發板上利用nfs引導成功,算是比較滿意的收獲吧!
搞定,收工!
總結
以上是生活随笔為你收集整理的make zImage和make uImage的区别和mkimage工具的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 腾讯课堂
- 下一篇: Win10怎么卸载自带软件 Win10自