首页 > 代码库 > uboot加载内核

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;}

 

完毕!

uboot加载内核