uboot加载内核

1.bootcmd:这个参数包含了一些命令,这些命令将在u-boot进入主循环后执行示例:

       bootcmd=boot_logo;nand read 10000003c0000 300000;bootm          //需要注意的是在bootcmd变量的最后添加了bootm命令。

       意思是启动u-boot后,执行boot_logo显示logo信息,然后从nand flash中读内核映像到内存,然后启动内核。

2.bootargs这个参数设置要传递给内核的信息,主要用来告诉内核分区信息和根文件系统所在的分区。示例:

       root=/dev/mtdblock5 rootfstype=jffs2console=ttyS0,115200 mem=35M mtdparts=nand.0:3840k(u-boot),4096k(kernel),123136k(filesystem)

       其中:

       root=/dev/mtdblock5 表示根文件系统在第五分区

       rootfstype=jffs2 表示根文件系统的类型是jffs2

       console=ttyS0,115200 表示终端为ttyS0,串口波特率为115200

       mem=35M 表示内存大小为35M

       mtdparts告诉内核MTD分区情况

 

超时之前用户没有输入,uboot就会自动加载linux内核,其加载时将使用变量“bootcmd”和 “bootargs”,其值可以在在加载linux内核前在uboot的命令行中进行修改。

在main_loop()函数中,执行了"bootcmd" 所定义的命令bootm,bootm命令执行过程中调用了bootm_start函数:

common/cmd_bootm.c:

static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
    void        *os_hdr;
    int        ret;

    memset ((void *)&images, 0, sizeof (images));
    images.verify = getenv_yesno ("verify");

    bootm_start_lmb();

    /* get kernel image header, start address and length  寻找可用的内核镜像*/
    os_hdr = boot_get_kernel (cmdtp, flag, argc, argv,                 
            &images, &images.os.image_start, &images.os.image_len);   //返回指向内存中镜像头指针
    if (images.os.image_len == 0) {
        puts ("ERROR: can't get kernel image!\n");
        return 1;
    }

    /* get image parameters */
    switch (genimg_get_format (os_hdr)) {
    case IMAGE_FORMAT_LEGACY:
        images.os.type = image_get_type (os_hdr);       //镜像类型
        images.os.comp = image_get_comp (os_hdr);       //压缩类型
        images.os.os = image_get_os (os_hdr);           //操作系统类型 
        images.os.end = image_get_image_end (os_hdr);   //当前镜像的尾地址  
        images.os.load = image_get_load (os_hdr);       //镜像数据的载入地址
        break;
#if defined(CONFIG_FIT)
    case IMAGE_FORMAT_FIT:
        if (fit_image_get_type (images.fit_hdr_os,
                    images.fit_noffset_os, &images.os.type)) {
            puts ("Can't get image type!\n");
            show_boot_progress (-109);
            return 1;
        }

        if (fit_image_get_comp (images.fit_hdr_os,
                    images.fit_noffset_os, &images.os.comp)) {
            puts ("Can't get image compression!\n");
            show_boot_progress (-110);
            return 1;
        }

        if (fit_image_get_os (images.fit_hdr_os,
                    images.fit_noffset_os, &images.os.os)) {
            puts ("Can't get image OS!\n");
            show_boot_progress (-111);
            return 1;
        }

        images.os.end = fit_get_end (images.fit_hdr_os);

        if (fit_image_get_load (images.fit_hdr_os, images.fit_noffset_os,
                    &images.os.load)) {
            puts ("Can't get image load address!\n");
            show_boot_progress (-112);
            return 1;
        }
        break;
#endif
    default:
        puts ("ERROR: unknown image format type!\n");
        return 1;
    }

    /* find kernel entry point */
    if (images.legacy_hdr_valid) {
        images.ep = image_get_ep (&images.legacy_hdr_os_copy);
#if defined(CONFIG_FIT)
    } else if (images.fit_uname_os) {
        ret = fit_image_get_entry (images.fit_hdr_os,
                images.fit_noffset_os, &images.ep);
        if (ret) {
            puts ("Can't get entry point property!\n");
            return 1;
        }
#endif
    } else {
        puts ("Could not find kernel entry point!\n");
        return 1;
    }

    if (((images.os.type == IH_TYPE_KERNEL) ||
         (images.os.type == IH_TYPE_MULTI)) &&
        (images.os.os == IH_OS_LINUX)) {
        /* find ramdisk */
        ret = boot_get_ramdisk (argc, argv, &images, IH_INITRD_ARCH,
                &images.rd_start, &images.rd_end);
        if (ret) {
            puts ("Ramdisk image is corrupt or invalid\n");
            return 1;
        }

#if defined(CONFIG_OF_LIBFDT)
#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC)
        /* find flattened device tree */
        ret = boot_get_fdt (flag, argc, argv, &images,
                    &images.ft_addr, &images.ft_len);
        if (ret) {
            puts ("Could not find a valid device tree\n");
            return 1;
        }

        set_working_fdt_addr(images.ft_addr);
#endif
#endif
    }

    images.os.start = (ulong)os_hdr;       //指向内存中镜像的头地址
    images.state = BOOTM_STATE_START;

    return 0;
}

接下来:

//寻找内核映像、校验它的完整性和定位内核数据位置

static void *boot_get_kernel (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],bootm_headers_t *images, ulong *os_data, ulong *os_len){...}

 

//校验早期格式内核映像

static image_header_t *image_get_kernel (ulong img_addr, int verify){...}

 

/* bootm - boot application image from image in memory引导应用程序在内存中的镜像 */
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])

{

...

 ret = bootm_load_os(images.os, &load_end, 1);  //将镜像的数据从images.os.image_start复制到images.os.load  打印:Loading Kernel Image ... OK 

...

boot_fn = boot_os[images.os.os];  //根据操作系统的类型获取引导操作系统的函数

...

}

lib_arm/bootm.c:

int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
{
    bd_t    *bd = gd->bd;
    char    *s;
    int    machid = bd->bi_arch_number;
    void    (*theKernel)(int zero, int arch, uint params);

#ifdef CONFIG_CMDLINE_TAG
    char *commandline = getenv ("bootargs");        //获取bootargs环境变量。
#endif

    if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
        return 1;

    theKernel = (void (*)(int, int, uint))images->ep;

    s = getenv ("machid");
    if (s) {
        machid = simple_strtoul (s, NULL, 16);
        printf ("Using machid 0x%x from environment\n", machid);
    }

    show_boot_progress (15);

    debug ("## Transferring control to Linux (at address %08lx) ...\n",
           (ulong) theKernel);

#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
    defined (CONFIG_CMDLINE_TAG) || \
    defined (CONFIG_INITRD_TAG) || \
    defined (CONFIG_SERIAL_TAG) || \
    defined (CONFIG_REVISION_TAG) || \
    defined (CONFIG_LCD) || \
    defined (CONFIG_VFD)
    setup_start_tag (bd);
#ifdef CONFIG_SERIAL_TAG
    setup_serial_tag (&params);
#endif
#ifdef CONFIG_REVISION_TAG
    setup_revision_tag (&params);
#endif
#ifdef CONFIG_SETUP_MEMORY_TAGS
    setup_memory_tags (bd);
#endif
#ifdef CONFIG_CMDLINE_TAG
    setup_commandline_tag (bd, commandline);      //将bootargs传给tag
#endif
#ifdef CONFIG_INITRD_TAG
    if (images->rd_start && images->rd_end)
        setup_initrd_tag (bd, images->rd_start, images->rd_end);
#endif
#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
    setup_videolfb_tag ((gd_t *) gd);
#endif
    setup_end_tag (bd);
#endif

    /* we assume that the kernel is in place */
    printf ("\nStarting kernel ...\n\n");

#ifdef CONFIG_USB_DEVICE
    {
        extern void udc_disconnect (void);
        udc_disconnect ();
    }
#endif

    cleanup_before_linux ();

    theKernel (0, machid, bd->bi_boot_params);       //执行内核代码
    /* does not return */

    return 1;
}

 

完毕!

posted @ 2015-01-27 21:01  ht-beyond  阅读(2202)  评论(0编辑  收藏  举报