u-boot引导Linux内核有两种方式,go命令或者bootm命令。go命令引导zImage格式的内核映像,默认方式下不向内核传递参数,需要我们修改,相应的修改也有两种选择。一种是用使用struct param_struct传递内核参数,另一种是以标记列表(taggedlist)的形式来传递启动参数。第一种方式设置简单,Linux2.6继续支持该格式,未来是否继续支持有待考察。实践中,用structparam_struct方式引导Linux-2.6.35没问题,但在引导Linux-2.6.39.3时失败。提示以下信息:

Root-NFS: No NFS server available, giving up. 
        VFS: Unable to mount root fs via NFS, trying floppy.

怀疑是内核参数传递不正确。因此,尝试用bootm命令引导Linux-2.6.39.3。

bootm命令只能引导uImage格式的内核映像,用makeuImage命令生成uImage格式的内核映像,用bootm命令引导Linux-2.6.39.3,但也不成功。经查,bootm命令默认方式也不向内核传递参数,需要在配置头文件(例如,include/configs/smdk2410.h)中定义以下两个宏:

#define CONFIG_SETUP_MEMORY_TAGS 1
        #define CONFIG_CMDLINE_TAG 1

重新编译生成u-boot.bin,烧写到开发板中并重启开发板,引导Linux-2.6.39.3仍不成功。

zImage格式的内核映像和uImage格式的内核映像文件头部分不同,后者多64个字节。注意到make uImage时的提示信息:

Load Address: 0x30108000
        Entry Point: 0x30108000

这两个地址一个是解压后的加载地址,一个是内核映像的执行入口地址,二者应该不同,有64(0x40)字节的偏移。

打开arch/arm/boot目录中的Makefile,找到$(obj)/uImage: STARTADDR=$(LOADADDR) 这一句,显然,直接把加载地址赋给了执行地址。修改如下:

$(obj)/uImage: STARTADDR=$(shell echo $(LOADADDR) | sed –e “s/..$$/40/”)

其中,sed –e “s/..$$/40/”的意思是把字符串的最后两个字节用40替换。

重新make uImage,提示信息为:

Load Address: 0x30108000
        Entry Point: 0x30108040

在开发板上重新引导内核:

# tftp 33000000 uImage
        # bootm 33000000

系统引导成功。
12-11 15:16