• 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!
    ");
            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!
    ");
                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!
    ");
                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!
    ");
                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!
    ");
                show_boot_progress (-112);
                return 1;
            }
            break;
    #endif
        default:
            puts ("ERROR: unknown image format type!
    ");
            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!
    ");
                return 1;
            }
    #endif
        } else {
            puts ("Could not find kernel entry point!
    ");
            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
    ");
                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
    ");
                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
    ", machid);
        }
    
        show_boot_progress (15);
    
        debug ("## Transferring control to Linux (at address %08lx) ...
    ",
               (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 ("
    Starting kernel ...
    
    ");
    
    #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;
    }

    完毕!

  • 相关阅读:
    MySQL批量删除指定前缀表
    jquery--checkbox全选/全不选
    jquery--监听checkbox多选框是否选中,展示输入框
    shell--脚本之间传值,模仿jenkins内置变量的功能
    python--os模块递归本地目录
    python--脚本添加定时任务
    paramiko--密钥连接远端服务器并递归目录
    django--完成客户端下载文件的三种方式
    python--如何给dict字典类型排序
    python--时间相差8小时问题
  • 原文地址:https://www.cnblogs.com/ht-beyond/p/4253944.html
Copyright © 2020-2023  润新知