zoukankan      html  css  js  c++  java
  • uboot2009.08引导内核学习笔记(转)

    U-Boot移植好后就要考虑如何引导内核了(以下介绍的是bootm方式,开发板是友善之臂的mini2440)。所用的U-Boot是移植的U-Boot-2009.08 ,内核是mini2440光盘中的kernel-2.6.29。U-Boot引导内核分三步:内核的编译、启动参数的设置、下载固化。
    (一)内核的编译
        通常,u-boot为kernel提供一些kernel无法知道的信息,比如ramdisk在RAM中的地址。Kernel也必须为U-boot提供必要的信息,如通过mkimage这个工具(在u-boot代码的tools目录中)可以给zImage添加一个header,也就是使得通常编译的内核zImage添加一个数据头,把添加头后的image通常叫uImage,uImage是可以被U-boot直接引导的内核镜像。那么如何使用mkimage工具而产生uImage的呢?
    1. 工具 mkimage
    --------------------------------------------------------------------------------
        编译U-Boot成功后,在u-boot代码的tools目录中生成一些工具,比如mkimage。将它们复制到/usr/local/bin 目录下,就可以直接使用了。现在我们编译内核需要用到mkimage来生成U-Boot格式的内核映像文件uImage 。复制完成后在终端输入命令" mkimage "并回车,显示关于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类型,比如Kernel
        -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
    2. 编译
    --------------------------------------------------------------------------------
        在内核的根目录下执行命令进行编译。如果之前编译过,最好先 make clean 一下。然后 make zImage 生成 zImage 的内核(在此之前别忘了参看说明书装载缺省配置文件)。最后在目录kernel-2.6.29/arch/arm/boot下执行命令            
    mkimage -n 'linux-2.6.29' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage uImage.img生成 U-Boot可以引导的内核,生成的文件名为uImage.img (也可以使用默认设置,在内核根目录下执行make uImage,生成默认的文件名为uImage)。生成的内核文件都在目录kernel-2.6.29/arch/arm/boot下。
    注:这里我用的mkimage是在U-BOOT-2009.08版本中生成的,在执行mkimage -n 'linux-2.6.29' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage uImage.img时,会出现错误,错误提示代码大概意思是说zImage是不支持的image类型,提示中还会列出支持的image类型。 开始还以为编译出来的zImage文件有问题,结果用友善提光盘中提供的zImage文件执行时也出同样的错误。在网上找了很多别人的做法也都是这么做的,没办法,最后试着将zImage文件改名为kernel,再执行命令:mkimage -n 'linux-2.6.29' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d kernel uImage.img  顺利通过了。
    关于mkimage -a -e参数的设置,还有另一种方式,具体请google一下。
    (二)启动参数的设置
    这里我用的是通过串口下载的方式,故暂不提tftp的设置.
    将bootcmd的参数改变成从nand flash引导kernel(每次开机后让u-boot复制到sdram中,再使用env参数中的bootm命令引导)。方法是在u-boot提示符下输入:
    set bootcmd 'nand read 0x31000000 0x80000 0x00200000;bootm 0x31000000'再改变bootargs,使得从nand flash启动根文件系统。方法是在u-boot提示符下输入:
    set bootargs 'noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0'最后保存设置:
    saveenv
    注:这里需要特别说明的一下的是set bootcmd 'nand read 0x31000000 0x80000 0x00200000;bootm 0x31000000' ,这个启动命令的意思是:启动时从nand flash的0x80000处(也就是内核存放在NAND FLASH中的起始地址)开始读取大小为0x200000的数据到内存地址0x31000000处,最后调用bootm指令启动内核,bootm指令参数为0x31000000即内核在RAM中的起始地址。
    关于内核在NAND FLASH中起始地址的设置,我这里设置的为0x80000.这里主要根据U-BOOT存放区域和UBOOT启动参数存放区域来确定。下面列一个我的NAND区域划分:
    0x00000000-0x00060000     //u-boot
    0x00060000-0x00080000     //启动参数,即saveenv命令,将设置的参数保存的地址。
    这个地址区的确定,可查看UBOOT代码./u-boot-2009.08/include/configs/mini2440.h
    #define CONFIG_ENV_OFFSET 0X60000
    #define CONFIG_ENV_SIZE        0x20000        /* Total Size of Environment Sector */
    从这两个宏,可以得知参数保存的区域为0x00060000-0x00080000。
    0x00080000-0x00280000   //内核
    内核区域的起始地址尤其关键,如果在用nand write指令固化内核到NAND FLASH中时,写入起始地址在0x00080000之前时,就可以能导致覆盖u-boot和启动参数,导致无法开始或失去上面设置过的启动参数,而无法引导内核。
    0x00280000-之后的就是文件系统存放的区域了。
    (三)下载固化
    1. 引导系统测试
    --------------------------------------------------------------------------------
        我们先把内核下载到内存中(地址为环境参数bootcmd中的nand read 和bootm 后的地址),然后我们执行bootm命令(同一个地址)看能不能启动系统。在U-Boot下执行:
    loadx 0x31000000     //通过超级终端传送文件,将uImage.img下载到0x31000000
        在提示下载完成后再执行:
    bootm 0x31000000
        如果成功则证明我们的设置没有问题(如果有文件系统的话可以正常启动,这个文件系统可以是用Nor Flash 中的 supervivi 烧到 Nand Flash中的)。
    很不幸失败了.....
    加载内核时跑到:
    Starting kernel ...
    Uncompressing Linux.......................................................................................... done, booting the kernel.
    到这里就不动了。老办法GOOGLE一下,发现这是个经典问题了,经典问题自有经典的办法解决:
    1、u-boot中的命令行参数中console设定有问题,对2.6的内核应该使用ttySAC0,而不是ttyS0。更改为"console=ttySAC0"就可以解决问题。
    2、u-boot中FCLK与kernel时钟频率不一致。kernel的FCLK为200MHz,但是uboot的默认值是202.8MHz。(vivi默认的也是200MHz,所以vivi不会出现这个问题。)这样修改uboot的时钟频率设定就可以解决问题。
    3. u-boot传递的mach_type参数与内核设置的mach_type不对。
    通过分析,发现存在第三种问题。
    a).通过对U-BOOT-2009.08代码的分析,mach_type参数在board_Init函数中传出来,在u-boot-2009.08/board/mini2440/mini2440.c文件中,
    #if defined(CONFIG_S3C2440)
    /* arch number of S3C2440 -Board */
         gd->bd->bi_arch_number = MACH_TYPE_S3C2440 ;
    #endif
    由此可见,mach_type的值由宏MACH_TYPE_S3C2440定义决定。
    在u-boot-2009.08/include/asm-arm/mach-types.h中可以找到,默认定义为:
    #define MACH_TYPE_S3C2440              362
    b).通过对友善内核2.6.29代码分析,在./linux-2.6.29/arch/arm/mach-s3c2440/mach-mini2440.c中,找到MACHINE_START(MINI2440, "FriendlyARM Mini2440 development board"),由此发现,由MINI2440这个参数确定。
    在./linux-2.6.29/arch/arm/tools/mach-types中,找到
    mini2440                MACH_MINI2440                MINI2440                1999
    由此可见,内核设定的mach_type的值为1999。
    c).将U-BOOT中,#define MACH_TYPE_S3C2440              362
    改为#define MACH_TYPE_S3C2440              1999
    重新编译uboot,启动nor flash中的 supervivi将重新编译得到的uboot.bin烧到NAND FLASH中,按上面所说的方法测试加载到RAM中的内核。
    一长串串的打印英文飘过,OK。。。引导内核成功了。
    2.下载固化
    ----------------------------------------------------------------------------------------
    在u-boot下输入loadx 0x31000000,通过超级终端将uImage下载到内存中。
    接着执行 nand erase 0x80000 0x200000 删除掉该区域原有的数据。
    执行 nand write 0x31000000 0x80000 0x200000,将内存中的kernel烧入nand flash。
    重新开机,OK。。。。。引导成功。。。

  • 相关阅读:
    linux基础-第十八单元_nginx部署
    centos7 启动docker失败--selinux-enabled=false
    crontab 写入文件目录
    kvm : Permission denied
    使用spice连接kvm guest主机
    python中bottle模块的使用
    如何监控开源 Apache Kafka?
    Spring Quartz
    【问题排查】kafka0.10.x过期数据不会自动删除问题
    Apache Kafka监控之Kafka Web Console
  • 原文地址:https://www.cnblogs.com/xmphoenix/p/2009259.html
Copyright © 2011-2022 走看看