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

完毕!

时间: 2024-10-14 19:50:14

uboot加载内核的相关文章

x01.os.8: 加载内核

在 x01.os.7 中,借助 freedos,学习了保护模式.但操作系统必须完成引导:boot, 加载内核:loader,kernel,进而管理process,memory,file等. 引导比较简单,开机启动时,CPU 采取硬的方式,直接把 BIOS 载入内存某处运行.这就是电脑启动时按 DEL 键可以看到的画面.此时,无硬盘可以,无内存则不可以.BIOS 是一个只读芯片,但我认为它仍有可写的部分,否则,启动盘设置的保存,就说不通.BIOS 退出时,它会检测启动盘 0 扇区的最后两个字节,是

linux内核设计的艺术--加载内核代码

在BIOS触发0x19中断将磁盘的第一个扇区(512B)加载到内存中后,计算机才真正开始执行磁盘上的程序.而这512B的程序bootsect.s中的第一批代码,此时处理器还处于实模式内存寻址的最大范围是1M(0x0000-0xFFFF),接下来我们看看在bootsect.s的第一批代码中做了些什么? SYSSIZE = 0x3000 //内核程序的大小 SETUPLEN = 4 //要加载的setup程序长度单位为扇区数 BOOTSEG = 0x07c0 //启动扇区被BIOS加载的位置,也就是

CentOS7 更改默认加载内核

CentOS7 更改默认加载内核 cat /boot/grub2/grub.cfg |grep menuentry  注意是单引号里面的都是.这里可以看到,这台机器目前有三个内核. 设置指定内核为默认加载项: grub2-set-default “CentOS Linux (3.10.0-862.el7.x86_64) 7 (Core)” 配置默认内核,验证是否修改成功: grub2-editenv list  重启系统,查看当前内核: uname -r 原文地址:https://www.cnb

转:A10/A20 Bootloader加载过程分析

来自:http://blog.csdn.net/allen6268198/article/details/12905425 A10/A20 Bootloader加载过程分析 注:由于全志A10和A20在加载Bootloader过程方面基本一致,下面仅以A20叙述,但同时也适用于A10.另外在不需要区分Cubieboard1和Cubieboard2的情况下,统称为Cubieboard:另现在市面上一般所说的SD卡即为Micro SD Card,也就是TF卡,为区别于一般传统的SD卡,本文一般使用T

转 A10/A20 Bootloader加载过程分析

A10/A20 Bootloader加载过程分析 注:由于全志A10和A20在加载Bootloader过程方面基本一致,下面仅以A20叙述,但同时也适用于A10.另外在不需要区分Cubieboard1和Cubieboard2的情况下,统称为Cubieboard:另现在市面上一般所说的SD卡即为Micro SD Card,也就是TF卡,为区别于一般传统的SD卡,本文一般使用TF卡描述,但同于平时所说的SD卡. A20的启动过程大概可分为5步:Boot ROM,SPL,Uboot,Kernel,Ro

S5P210-uboot源码分析-uboot如何启动内核

uboot如何启动内核 7.1.uboot和内核到底是什么? 1.uboot是一个裸机程序 (1)uboot的本质就是一个复杂点的裸机程序,和我们arm裸机中写的程序没有什么本质上的区别. (2)uboot最像我们在arm裸机中的最后写的那个shell,它其实就是一个迷你型的uboot. 2.linux内核本身也是一个"裸机程序" (1)操作系统内核本身就是一个裸机程序,和uboot并没有本质区别. (2)区别在于,操作系统运行起来后在软件层次上可以分为内核层和应用层,分层后两层的权限

VELT-0.1.6开发:加载根文件系统

快乐虾 http://blog.csdn.net/lights_joy/(QQ群:Visual EmbedLinux Tools 375515651) 欢迎转载,但请保留作者信息 VELT的全称是Visual EmbedLinuxTools,它是一个visual studio插件,用以辅助完成Linux开发.利用这个插件,将可以在visualstudio的IDE中进行Linux应用程序的开发(包括编译和调试),也可以进行uboot和linux内核的编译和调试,并根据编译时的错误信息正确定位到源码

java热加载

应用服务器一般都支持热部署(Hot Deployment),更新代码时把新编译的确类 替换旧的就行,后面的程序就执行新类中的代码.这也是由各种应用服务器的独 有的类加载器层次实现的.那如何在我们的程序中也实现这种热加载功能呢?即 要在虚拟机不关闭的情况下(比如一个),换个类,JVM 就知道加载这个新类,执 行新类中的逻辑呢?下面就简单演示这样一个热加载的例子,首先大致了解一下 类加载器. 标准 Java 启动器的类加载器层次 1. 引导类加载器(bootstrap): 加载内核 API,如 rt

Linux开机加载过程

目录 1 开机加载简介 2 常规加载流程 2.1 加载BIOS 2.2 读取MBR 2.3 boot loader 2.4 加载内核 2.5 init依据inittab文件来设定运行等级 2.6 init进程执行rc.sysinit 2.7 启动内核模块 2.8 执行不同运行级别的脚本程序 2.9 执行/etc/rc.d/rc.local 2.10 执行/bin/login程序,进入登录状态 3 环境变量加载 3.1 加载顺序说明 开机加载简介 开机过程指的是从打开计算机电源直到LINUX显示用