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
系统引导成功。