先来引用一下这篇介绍“ARM Linux内核启动要求”的文章ARM Linux Kernel Boot Requirements,是ARM Linux内核的维护者Russell King写的。
大致就是以上条件了,请特别关注一下第一条,这个基本上就是U-Boot的go命令和bootm命令之间的本质区别所在了。先来看看bootm命令的实现,在common/cmd_bootm.c的第119行开始有:
这里的预编译宏说明了,非 PPC体系结构的CPU的do_bootm_linux()函数都不是在这个文件内实现的(extern)。可想而知,这个函数的实现应该是和体系结构相关的,具体到arm体系结构的实现就是在lib_arm/armlinux.c这个文件当中。可以看到从lib_arm/armlinux.c中的第77 行开始就是do_bootm_linux()函数的实现。
其中第85行声明了这样一个函数指针theKernel:
看看它的名字和参数的命名我们也可以猜到这个其实就是内核的入口函数的指针了。几个参数的命名也说明了上文提到的ARM Linux内核启动要求的第一条,因为根据ACPS(ARM/Thumb Procedure Call Standard)的规定,这三个参数就是依次使用r0,r1和r2来传递的。
接下来第93行就是给这个函数指针赋值:
可以看到theKernel被赋值为hdr->ih_ep,这个hdr是指使用tools/mkimage工具程序制作uImage时加在linux.bin.gz前面的一个头部,而ih_ep结构体成员保存的就是使用mkimage时指定的-e参数的值,即内核的入口点(Entry Point)。知道了hdr->ih_ep的意义之后,给theKernel赋这个值也就是理所当然的了。
最后是对内核入口函数的调用,发生在第270行:
调用的时候对参数进行赋值,r0=0,r1=bd->bi_arch_number,r2=bd->bi_boot_params,一个都不少。至此U-Boot的使命完成,开始进入ARM Linux的美丽新世界。
====================================================================
要知道哪个地址是启动内核,哪个地址启动文件系统,要分析common/cmd_bootm.c中的函数do_bootm,因为引导kernel就是bootm这条命令的工作,do_bootm是命令bootm的执行函数。
现在我们来分析一下common/cmd_bootm.c中的函数do_bootm,这是bootm命令的处理函数。
读取uboot的环境变量verify,如果环境变量verify等于’n’,则局部变量verify赋值成为0;如果环境变量verify为空(即没有定义环境变量verify)或者环境变量verify不等于’n’,则局部变量verify赋值成为1。
如果参数个数小于2(即只是输入了bootm),使用缺省加载地址CFG_LOAD_ADDR;否则使用第二个参数作为加载地址。
将mkimage添加到映象文件头部的64字节提取到image_header_t 结构变量header中。
/* Copy header so we can blank CRC field for re-calculation */
定义了CONFIG_HAS_DATAFLASH,表示系统中存在ATMEL的数据Flash。
判断image header的magic是否匹配,如果不匹配,说明下载过程中发生了错误。
校验image header的CRC以及image data的CRC,如果校验不匹配,说明下载过程中发生了错误。
判断体系结构。
判断image类型。
判断image压缩类型
如果image header中指示的加载地址和bootm命令中参数2指定的地址不相同,则表示要从image header中指示的加载地址处把image data copy到bootm命令中参数2指定的地址处,然后再执行。
根据image 执行type来决定如何引导。
根据image 的OS type来决定如何引导
bootm命令是用来引导经过u-boot的工具mkimage打包后的kernel image的,什么叫做经过u-boot的工具mkimage打包后的kernel image,这个就要看mkimage的代码,看看它做了些什么,虽然我很希望大家不要偷懒,认真地去看看,但是我知道还是有很多人懒得去做这件,那么我就j将分析mkimage代码后得到的总结告诉大家,mkimage做了些什么,怎么用这个工具。
mkimage的用法
uboot源代码的tools/目录下有mkimage工具,这个工具可以用来制作不压缩或者压缩的多种可启动映象文件。
mkimage在制作映象文件的时候,是在原来的可执行映象文件的前面加上一个0x40字节的头,记录参数所指定的信息,这样uboot才能识别这个映象是针对哪个CPU体系结构的,哪个OS的,哪种类型,加载内存中的哪个位置, 入口点在内存的那个位置以及映象名是什么
参数说明:
-A 指定CPU的体系结构:
取值 表示的体系结构
alpha Alpha
arm A RM
x86 Intel x86
ia64 IA64
mips MIPS
mips64 MIPS 64 Bit
ppc PowerPC
s390 IBM S390
sh SuperH
sparc SPARC
sparc64 SPARC 64 Bit
m68k MC68000
-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 不压缩
gzip 用gzip的压缩方式
bzip2 用bzip2的压缩方式
-a 指定映象在内存中的加载地址,映象下载到内存中时,要按照用mkimage制作映象时,这个参数所指定的地址值来下载
-e 指定映象运行的入口点地址,这个地址就是-a参数指定的值加上0x40(因为前面有个mkimage添加的0x40个字节的头)
-n 指定映象名
-d 指定制作映象的源文件
本文轉自: http://blog.chinaunix.net/u/17660/showart_279896.html