Linux内核 ---------- Linux-3.4.72
实验开发板 --------- TQ2440 board
arch = arm
沉睡很久的开发板又重新上电了。经历了两年的工作洗礼,终于又勇气去试图驾驭它。路漫漫其修远兮 吾将上下而求索!!!
第一阶段目标:将Linux 3.4.72 移植到 TQ2440 实验开发板中,能够看到启动信息即可!
写这篇博客的时候,已经证明这个阶段的目标已经实现了。我很欣慰。废话不多说,直入重点。
Linux kernel Image 是由什么组成的? 这个问题很重要,因为Linux 的启动汇编分为两部分,并且这两部分并非物理地址上连续的,有明显的分割线!!!。
.zImage.cmd文件是在生成zImage后产生的隐藏文件,里面记录了如何生成zImage的,内容如下:
cmd_arch/arm/boot/zImage := arm-linux-objcopy -O binary -R .comment -S arch/arm/boot/compressed/vmlinux arch/arm/boot/zImage
zImage是由arch/arm/boot/compressed/vmlinux生成的,那么.vmlinux.cmd文件中的内容为:
cmd_arch/arm/boot/compressed/vmlinux := arm-linux-ld -EL --defsym _kernel_bss_size=113472 --defsym zreladdr=0x30008000 -p --no-undefined -X -T arch/arm/boot/compressed/vmlinux.lds arch/arm/boot/compressed/head.o arch/arm/boot/compressed/piggy.gzip.o arch/arm/boot/compressed/misc.o arch/arm/boot/compressed/decompress.o arch/arm/boot/compressed/string.o arch/arm/boot/compressed/lib1funcs.o arch/arm/boot/compressed/ashldi3.o -o arch/arm/boot/compressed/vmlinux
上面有黑体标出的文件,就是组成vmlinux的文件。其中最重要的的文件有 head.S(生成head.o), misc.S, decompress.S,和piggy.gzip.S。 特别注意的piggy.gzip.S汇编文件。
piggy.gzip.S:
.section .piggydata,#alloc
.globl input_data
input_data:
.incbin "arch/arm/boot/compressed/piggy.gzip"
.globl input_data_end
input_data_end:
这个汇编就是包含piggy.gzip文件。那么piggy.gzip又是什么呢? 查看.piggy.gzip.cmd文件:
cmd_arch/arm/boot/compressed/piggy.gzip := (cat arch/arm/boot/compressed/../Image| gzip -n -f -9 > arch/arm/boot/compressed/piggy.gzip) || (rm -f arch/arm/boot/compressed/piggy.gzip ; false)
由此可以知道piggy.gzip是由 gzip工具将arch/arm/boot/compressed/../Image压缩而生成的。这里插入一个问题, 为什么是gzip呢?默认的配置就用gzip工具压缩的,kernel还支持lzo,lzma ,xzkern的压缩,但是我没有尝试过,另外以前看见过有uImage,其实这个是由uboot将linux kernel进行压缩,然后由uboot进行解压,只不过,现在的linux kernel 已经不在需要uboot的帮忙了。言归正传,Image是如何生成的呢?同理查看arch/arm/boot/.Image.cmd 文件:
cmd_arch/arm/boot/Image := arm-linux-objcopy -O binary -R .comment -S vmlinux arch/arm/boot/Image
这里又出现了一个vmlinux,不要误会,这个vmlinux不是上面提到的那个,而是在Linux 3.4.72的根目录下生成的同名的vmlinux。到跟目录下查看
cmd_vmlinux := arm-linux-ld -EL -p --no-undefined -X --build-id -o vmlinux -T arch/arm/kernel/vmlinux.lds arch/arm/kernel/head.o arch/arm/kernel/init_task.o init/built-in.o --start-group usr/built-in.o arch/arm/kernel/built-in.o arch/arm/mm/built-in.o arch/arm/common/built-in.o arch/arm/net/built-in.o arch/arm/mach-s3c24xx/built-in.o arch/arm/mach-s3c2412/built-in.o arch/arm/mach-s3c2440/built-in.o arch/arm/plat-s3c24xx/built-in.o arch/arm/plat-samsung/built-in.o kernel/built-in.o mm/built-in.o fs/built-in.o ipc/built-in.o security/built-in.o crypto/built-in.o block/built-in.o arch/arm/lib/lib.a lib/lib.a arch/arm/lib/built-in.o lib/built-in.o drivers/built-in.o sound/built-in.o firmware/built-in.o net/built-in.o --end-group .tmp_kallsyms2.o
这里可以看出,这个vmlinux就是将子目录中的built-in.o和其他的文件链接而成的。到此不在分析下去。 不过需要记住,这个分析是逆向的。我们称这个vmlinux为vmlinux0,加以区分最上面的提到vmlinux。
我们从vmlinux0 开始简单的分析其是如何生成zImage的
1. 将linux根目录的vmlinux0, 拷贝到arch/arm/boot/下变成二进制Image文件。
2.将Image文件用gzip压缩成piggy.gzip,存放在arch/arm/boot/compressed/。
3.将arch/arm/boot/compressed/目录中的 head.o piggy.gzip.o misc.o decompress.o 生成vmlinux。
4.将arch/arm/boot/compressed目录中的vmlinux,用arm-linux-objcopy文件拷贝到arch/arm/boot目录下生成zImage
可以看出上面的操作中有一个压缩的Linux kernel的过程。在启动过程中,Linux 首先要做的就是将压缩的piggy.gzip文件解压,所以,Linux kernel的维护人员将 head.S misc.S decompress.S等文件编译后,放到piggy.gzip前面。这几个文件最主要的功能就是解压piggy.gzip(即Image压缩后的文件)。
在文章的开头讲过Linux的启动汇编由两部分组成,并且有明显的分割线,这个分割线就是由压缩Linux kernel操作产生的。第一部分汇编的功能就是将piggy.gzip进行解压, 使其还原成Image。而在Image的首地址同样是由汇编组成,我称为第二部分汇编。
在下篇博文中主要分析Linux kernel 第一部分汇编做了 什么,其跟串口初始是否有关系。