最近一直在做U-boot-2009.08和Linux-2.6.32.2的内核的移植,今天终于可以使用自己移植的U-Boot-2009.08引导自己修改的Linux-2.6.33.2内核了,还有移植的Yaffs2文件系统,真是太高兴的,现在在把这近两个月内,断断续续的移植做个最后的终结吧!在这个过程中也有想放弃的时候,不过现在都过来了,哈哈!遇到困难不要放弃,也许当时解决不了,不过可以先放一放,很可能过几天,从新分析时,会发现问题的所在。这也是我经常不是解决问题的办法的办法!下面开始这篇文章了:
1、机器码的确认:
   U-Boot和Linux中都有一个机器码,只有当这两个机器码一致的时候,才能够正确的引导Linux内核。在这个版本中的U-boot和Linux中,对MINI2440的板子支持的都很好了,也有了官方的机器码,只要添加上就可以了。在U-Boot中我们可以看到,在u-boot-2009.08/include/asm-arm/mach-types.h文件中的1985行附近的位置

#define MACH_TYPE_Q2440 1997
#define MACH_TYPE_QQ2440 1998
#define MACH_TYPE_MINI2440 1999  //mini2440的机器码
#define MACH_TYPE_COLIBRI300 2000
#define MACH_TYPE_JADES 2001

而在内核中的kernel/linux-2.6.32.2/arch/arm/tools/mach-typs.h文件中的1989行附近的位置

f5d8231_4_v2        MACH_F5D8231_4_V2    F5D8231_4_V2        1996
q2440            MACH_Q2440        Q2440            1997
qq2440            MACH_QQ2440        QQ2440            1998
mini2440        MACH_MINI2440        MINI2440        1999 //Linux中的MINI2440的机器码
colibri300        MACH_COLIBRI300        COLIBRI300        2000
jades            MACH_JADES        JADES            2001

   从这里我们可以知道MINI2440的机器码就是1999,那么我们就需要修改U-Boot中的机器码,以便和Linux中的机器码一致。在文件u-boot-2009.08/board/frankzfz/mini2440/mini2440.c目录可能会不一样,这是我自己建立的一个目录,大约在127行附近的位置。在board_init()函数中。

    gpio->GPHUP = 0x000007FF;
    /* arch number of SMDK2410-Board */
    #if defined(CONFIG_S3C2440)
    gd->bd->bi_arch_number = MACH_TYPE_MINI2440; //为u-boot添加机器码
    //gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
#endif

     还有一个地方也已经在另一篇文章《移植Linux内核》中做了说明,也就是在kernel/linux-2.6.32.2/arch/arm/mach-s3c2440/mach-mini2440.c文件中的230行附近中的MACHINE_START,修改成如下:

MACHINE_START(MINI2440, "FriendlyARM MINI2440 development board")

2、用u-boot引导Linux的镜象文件uImage
   通常,kernel的启动需要u-boot提供一些参数信息,比如ramdisk在RAM中的地址。经过编译后的u-boot在根目录下的tools目录中,会有个叫做mkimage的工具,他可以给zImage添加一个header,也就是说使得通常我们编译的内核zImage添加一个数据头信息部分,我们把添加头后的image通常叫uImage,uImage是可以被u-boot直接引导的内核镜像。我们如何使用这个工具生成我们需要的uImage格式的镜像文件呢?
1)编译u-boot成功后会在u-boot-2009.08/tools下生成mkimage的可执行的文件,为了我们在任何地方都可以使用这个命令,首先我们可以把这个可执行文件复制到/usr/local/bin.这样就可以在任意的目录下执行这个命令了。复制完以后我们在终端下输入“mkimage”,并按下回车。可以看到下面的输出的信息,说明我们已经可以使用改命令了。

Usage: mkimage -l image
          -l ==> list image header information
       mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image
          -A ==> set architecture to 'arch'
//用于指定CPU类型,比如ARM
          -O ==> set operating system to 'os'
//用于指定操作系统,比如Linux
          -T ==> set image type to 'type'
//用于指定image类型,比如Kernelramdisk
          -C ==> set compression type 'comp'
//指定压缩类型
          -a ==> set load address to 'addr' (hex)
//指定image的载入地址
          -e ==> set entry point to 'ep' (hex)
//内核的入口地址,一般是:image的载入地址+0x40(信息头的大小)
          -n ==> set image name to 'name'
//image在头结构中的命名
          -d ==> use image data from 'datafile'
//无头信息的image文件名
          -x ==> set XIP (execute in place)
//设置执行位置即不进行文件的拷贝,在当前位置执行
       mkimage [-D dtc_options] -f fit-image.its fit-image

对于ARM Linux我们可以这样使用各个参数:

对于ARM linux内核映象用法:
-A arm -------- 架构是arm
-O linux -------- 操作系统是linux
-T kernel -------- 类型是kernel
-C none/bzip/gzip -------- 压缩类型
-a 20008000 ---- image的载入地址(hex),通常为0xX00008000
-e 200080XX---- 内核的入口地址(hex),XX为0x40或者0x00
-n linux-XXX --- image的名字,任意
-d nameXXX ---- 无头信息的image文件名,你的源内核文件
uImageXXX ---- 加了头信息之后的image文件名,任意取

   现在我们可以进入kernel/linux-2.6.32.2/arch/arm/boot目录了,然后执行下面的命令,就会在改目录下面生成uImage.img格式的,u-boot可以引导的内核镜象。

mkimage -n 'linux-2.6.32.2' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage uImage.img

   现在我们可以把生成的uImage.img格式的镜像文件复制到tftp目录下,使用tftp进行下载了:不过现在下载到以后复制到Nand Flash中u-boot还是无法引导内核,还是需要在u-boot中一些配置。
在u-boot-2009.08/include/configs/mini2440.h文件中

#define CONFIG_BOOTDELAY    3 //自动启动前延时3秒,不过这个要和下面的另一个配置一

                              //起定义后才会其作用

配置命令行的参数

#define CONFIG_BOOTARGS    "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0,115200 mem=64M"

//只有这个宏定义了以后 上面的哪个宏的定义才会生效,否则还是会直接的出现命令行的提示符,不会引导内核的。 root=/dev/mtdblock3 这是有我们Linux中的nand Flash分区所决定的,我的NandFlash的第四个分区为根文件系统所以是mtdblock3,如果不是的话请修改

我的NandFlash的情况是这样的

"U-boot",0x00000000 -- 0x00040000,
"param", 0x00040000--
0x00060000,
 "Kernel", 0x00060000---0x00560000,    
"root",
0x00560000---结束

还要在该文件中增加下面两个宏的定义:

#define CONFIG_SETUP_MEMORY_TAGS 1 //向内核传递内存分布信息
#define CONFIG_INITRD_TAG
#define CONFIG_CMDLINE_TAG 1   //向内核传递命令行参数

在该文件中添加下面的定义

#define CONFIG_MTD_NAND_YAFFS2 1
#define MTDIDS_DEFAULT "nand0=nandflash0"
#define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k(bootloader),"\
            "128k(params),"\
            "5m(kernel),"\
            "-(root)"  //这里要和Linux内核中的分区信息相一致

下面的这两个定义也要和分区相一致

#define CONFIG_ENV_OFFSET 0x40000 //将环境变量保存在Nand中的0x30000位置
#define CONFIG_ENV_SIZE 0x20000 //Total Size of Environment Sector

为了使u-boot可以自行引导Linux内核,我们还需要添加下面的这句话。

#define CONFIG_BOOTCOMMAND    "nand read 0x32000000 0x60000 0x560000;bootm 0x32000000" 

//这个宏定义的意思是将nand中0x60000-0x560000(和kernel分区一致)的内容读到内存0x32000000中,然后用bootm命令来执行

3、下载系统到内存
  我们先把内核下载到内存中,然后我们执行bootm命令(同一个地址)看能不能启动系统。在U-Boot下执行:
tftp 0x31000000 uImage.img (或uImage)
    在提示下载完成后再执行:
bootm 0x31000000
    如果成功则证明我们的设置没有问题。
4、下载固化
   在前面我们看到了NandFlash的分区信息。下面我们使用命令,把我们的Linux内核和制作的根文件系统下载到NandFlash中,以便以开始启动就可以引导Linux内核。
                             起始地址             结束地址
   uboot            :       0x00000000      0x00040000      0
   param            :       0x00040000      0x00060000      0
   kernel           :       0x00060000      0x00560000      0
   root             :       0x00560000      0x07FFFFFF     0
这是NandFlash的分区情况;
    在u-boot下输入
tftp 0x30000000 uImage.img(或uImage),稍等即可下载uImage到内存中。
    接着执行 nand erase 0x60000 0x500000 删除掉kernel空间原有的数据。
    执行 nand write 0x30000000 0x50000 0x500000,将内存中的kernel烧入nand flash。
    接下来,输入tftp 30000000 rootfs.img,将根文件系统镜象下载到内存中。
    再输入nand erase 0x560000 0x07FFFFFF 将root空间内原有数据删除。
    再输入nand write.yaffs2 0x30000000 0x560000 0x6ffcc0,其中0x6ffcc0是文件系统镜象的size,一定不能写错,它可以tftp下载完毕后看到。
nand erase[clean][off size] 擦除NANDFlash。加上“clean”时,表示在每个块的第一个扇区的OOB区加写入清除的标记:off size表示要擦除的开始偏移地址和长度,如果省略off size 擦除整个NandFlash。现在可以从新启动开发板,从NandFlash启动可以看到启动的信息了。
下载Linux 镜像

[U-Boot@mini2440]#tftp 0x30000000 uImage.img
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 08:00:3e:26:0a:5b
operating at 100M full duplex mode
Using dm9000 device
TFTP from server 10.27.10.48; our IP address is 10.27.10.23
Filename 'uImage.img'.
Load address: 0x30000000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ###################
done
Bytes transferred = 2092996 (1fefc4 hex)
[U-Boot@mini2440]#nand erase 0x60000 0x500000
                                                                                
NAND erase: device 0 offset 0x60000, size 0x500000
Erasing at 0x54000002800000 -- 0% complete.
OK
[U-Boot@mini2440]#nand write 0x30000000 0x60000 0x500000
                                                                                
NAND write: device 0 offset 0x60000, size 0x500000
 5242880 bytes written: OK

下载根文件系统

[U-Boot@mini2440]#tftp 30000000 rootfs.img
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 08:00:3e:26:0a:5b
operating at 100M full duplex mode
Using dm9000 device
TFTP from server 10.27.10.48; our IP address is 10.27.10.23
Filename 'rootfs.img'.
Load address: 0x30000000
Loading: #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         #################################################################
         ####
done
Bytes transferred = 7339200 (6ffcc0 hex)
[U-Boot@mini2440]#nand erase 0x560000
                                                                                
NAND erase: device 0 offset 0x560000, size 0x7aa0000
Erasing at 0x7fe000007aa0000 -- 0% complete.
OK
[U-Boot@mini2440]#nand write.yaffs2 0x30000000 0x560000 0x6ffcc0
                                                                                
NAND write: device 0 offset 0x560000, size 0x6ffcc0
skip first good block 56000000020000
 Writing at 0xc4000000020000 --100% is complete 7116800 bytes written: OK

引导Linux内核启动

U-Boot 2009.08 ( 4

10-15 16:39