ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Mini440之uboot移植流程之linux内核启动分析(六)

2022-01-17 23:33:51  阅读:226  来源: 互联网

标签:bootm uboot image BOOTM images STATE linux Mini440 os


在前面的章节关于u-boot的源码,以及u-boot的移植这一块我们介绍完了。接下来,我们开始进入第二个阶段,linux内核移植,以及驱动开发。

在这之前,我们遗漏了u-boot中的一个重要环节没有介绍,就是u-boot如何执行bootm命令,如何实现linux内核启动。

一、linux内核启动入口之do_bootm

我们在Mini440之uboot移植之源码分析命令解析(五) 介绍过如果配置了CONFIG_BOOTCOMMAND宏:

#define CONFIG_BOOTCOMMAND "nand read 0x30000000 kernel; bootm 0x30000000" //bootcmd  

那么在执行autoboot_command函数的时候,将会执行该命令。

bootm这个命令用于启动一个操作系统映射,它会从映射文件的头部取得一些信息,这些信息包括:映射文件的基于的cpu架构、其操作系统类型、映射的类型、压缩方式、映射文件在内存中的加载地址、映射文件运行的入口地址、映射文件名等。

nand read 0x30000000命令:这里将NAND kernel分区的代码加载到地址0x30000000;

bootm 0x3000000:启动linux内核;

1.1 autoboot_command(common/autoboot.c)

void autoboot_command(const char *s)
{
    debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");

    if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
        run_command_list(s, -1, 0);
    }
}

如果在u-boot启动倒计时结束之前,没有按下任何键,将会执行那么将执行run_command_list,此函数会执行参数s指定的一系列命令,也就是bootcmd中配置中的命令,bootcmd中保存着默认的启动命令。

在默认环境变量default_environment中定义有:

#ifdef    CONFIG_BOOTCOMMAND
    "bootcmd="    CONFIG_BOOTCOMMAND        "\0"
#endif

1.2 do_bootm(cmd/bootm.c)

由于要执行bootm命令,所以我们需要打开与bootm命令相关的文件进行分析,bootm命令定义在cmc/bootm.c文件中:

U_BOOT_CMD(
    bootm,    CONFIG_SYS_MAXARGS,    1,    do_bootm,
    "boot application image from memory", bootm_help_text
);

找到对应的do_bootm函数,去除无用的代码:

/*******************************************************************/
/* bootm - boot application image from image in memory */
/*******************************************************************/

int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
    /* determine if we have a sub command */
    argc--; argv++;
    if (argc > 0) {
        char *endp;

        simple_strtoul(argv[0], &endp, 16);
        /* endp pointing to NULL means that argv[0] was just a
         * valid number, pass it along to the normal bootm processing
         *
         * If endp is ':' or '#' assume a FIT identifier so pass
         * along for normal processing.
         *
         * Right now we assume the first arg should never be '-'
         */
        if ((*endp != 0) && (*endp != ':') && (*endp != '#'))
            return do_bootm_subcommand(cmdtp, flag, argc, argv);
    }

// 到这里参数中的bootm参数会被去掉 return do_bootm_states(cmdtp, flag, argc, argv, BOOTM_STATE_START | BOOTM_STATE_FINDOS | BOOTM_STATE_FINDOTHER | BOOTM_STATE_LOADOS | BOOTM_STATE_OS_PREP | BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO, &images, 1); }

当执行bootm 0x30000000,函数入参:第一个参数是bootm命令结构体,flag是命令标志位,argv[0]='"bootm"、argv[1]="0x3000000",argc=2。

这里进入函数之后argc=1,argv[0]=0x30000000.

bootm的核心是do_bootm_states,以全局变量bootm_headers_t images作为do_bootm_states的参数,改变量在cmd/bootm.c文件中声明。

bootm_headers_t images;        /* pointers to os/initrd/fdt images */

 bootm会根据参数以及参数指向的镜像来填充这个结构体里面的成员。 最终再使用这个结构体里面的信息来填充kernel启动信息并且到跳转到kernel中。 

下面详细说明这个函数。

二、do_bootm_states(cmd/bootm.c)

我们先来看一下这个函数的声明:

int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
            int states, bootm_headers_t *images, int boot_progress);

2.1 bootm_headers_t(include/image.h)

bootm_headers_t是一个复杂的数据结构,官网是这样描述的:

/*
 * Legacy and FIT format headers used by do_bootm() and do_bootm_<os>()
 * routines.
 */
typedef struct bootm_headers {
    /*
     * Legacy os image header, if it is a multi component image
     * then boot_get_ramdisk() and get_fdt() will attempt to get
     * data from second and third component accordingly.
     */
    image_header_t    *legacy_hdr_os;        /* image header pointer */
    image_header_t    legacy_hdr_os_copy;    /* header copy */
    ulong        legacy_hdr_valid;

#if IMAGE_ENABLE_FIT
    const char    *fit_uname_cfg;    /* configuration node unit name */

    void        *fit_hdr_os;    /* os FIT image header */
    const char    *fit_uname_os;    /* os subimage node unit name */
    int        fit_noffset_os;    /* os subimage node offset */

    void        *fit_hdr_rd;    /* init ramdisk FIT image header */
    const char    *fit_uname_rd;    /* init ramdisk subimage node unit name */
    int        fit_noffset_rd;    /* init ramdisk subimage node offset */

    void        *fit_hdr_fdt;    /* FDT blob FIT image header */
    const char    *fit_uname_fdt;    /* FDT blob subimage node unit name */
    int        fit_noffset_fdt;/* FDT blob subimage node offset */

    void        *fit_hdr_setup;    /* x86 setup FIT image header */
    const char    *fit_uname_setup; /* x86 setup subimage node name */
    int        fit_noffset_setup;/* x86 setup subimage node offset */
#endif

#ifndef USE_HOSTCC
    image_info_t    os;        /* os image info */
    ulong        ep;        /* entry point of OS */

    ulong        rd_start, rd_end;/* ramdisk start/end */

    char        *ft_addr;    /* flat dev tree address */
    ulong        ft_len;        /* length of flat device tree */

    ulong        initrd_start;
    ulong        initrd_end;
    ulong        cmdline_start;
    ulong        cmdline_end;
    bd_t        *kbd;
#endif

    int        verify;        /* getenv("verify")[0] != 'n' */

#define    BOOTM_STATE_START    (0x00000001)
#define    BOOTM_STATE_FINDOS    (0x00000002)
#define    BOOTM_STATE_FINDOTHER    (0x00000004)
#define    BOOTM_STATE_LOADOS    (0x00000008)
#define    BOOTM_STATE_RAMDISK    (0x00000010)
#define    BOOTM_STATE_FDT        (0x00000020)
#define    BOOTM_STATE_OS_CMDLINE    (0x00000040)
#define    BOOTM_STATE_OS_BD_T    (0x00000080)
#define    BOOTM_STATE_OS_PREP    (0x00000100)
#define    BOOTM_STATE_OS_FAKE_GO    (0x00000200)    /* 'Almost' run the OS */
#define    BOOTM_STATE_OS_GO    (0x00000400)
    int        state;

#ifdef CONFIG_LMB
    struct lmb    lmb;        /* for memory mgmt */
#endif
} bootm_headers_t;

bootm_headers_t用于Legacy或设备树(FDT)方式镜像的启动,其中包括了os/initrd/fdt images的信息。我们这里大概介绍一下和这个结构体的成员变量:

  • legacy_hdr_os:Legacy-uImage的镜像头;
  • legacy_hdr_os_copy:Legacy-uImage的镜像头备份;
  • fit_uname_cfg:配置节点名;
  • fit_hdr_os:FIT-uImage中kernel镜像头;
  • fit_uname_os:FIT-uImag中kernel的节点名;
  • fit_noffset_os:FIT-uImage中kernel的节点偏移;
  • fit_hdr_rd:FIT-uImage中ramdisk的镜像头;
  • fit_uname_rd:FIT-uImage中ramdisk的节点名;
  • fit_noffset_rd:FIT-uImage中ramdisk的节点偏移;
  • fit_hdr_fdt:FIT-uImage中FDT的镜像头;
  • fit_uname_fdt:FIT-uImage中FDT的节点名;
  • fit_noffset_fdt:FIT-uImage中FDT的节点偏移;
  • os:操作系统信息的结构体,比如内核镜像在内存的起始地址、以及大小;
  • ep:操作系统的入口地址;
  • rd_start:ramdisk在内存上的起始地址;
  • rd_end:ramdisk在内存上的结束地址
  • ft_addr:fdt在内存上的地址;
  • ft_len:fdt在内存上的长度;
  • verify:是否需要验证;
  • state:状态标识,用于标识对应的bootm需要做什么操作;

其中 legacy_hdr_os是image_header_t类型。这个结构尤为重要,下面来介绍。

2.2 (include/image.h)

/*
 * Legacy format image header,
 * all data in network byte order (aka natural aka bigendian).
 */
typedef struct image_header {
    __be32        ih_magic;    /* Image Header Magic Number    */
    __be32        ih_hcrc;    /* Image Header CRC Checksum    */
    __be32        ih_time;    /* Image Creation Timestamp    */
    __be32        ih_size;    /* Image Data Size        */
    __be32        ih_load;    /* Data     Load  Address        */
    __be32        ih_ep;        /* Entry Point Address        */
    __be32        ih_dcrc;    /* Image Data CRC Checksum    */
    uint8_t        ih_os;        /* Operating System        */
    uint8_t        ih_arch;    /* CPU architecture        */
    uint8_t        ih_type;    /* Image Type            */
    uint8_t        ih_comp;    /* Compression Type        */
    uint8_t        ih_name[IH_NMLEN];    /* Image Name        */
} image_header_t;

比较重要的成员有:

  • ih_magic:镜像的魔数,用来给uboot判断是什么格式的镜像(zImage、uImage等);
  • ih_ep:镜像的入口;
  • inj_os:镜像的系统;

2.3 状态说明

do_bootm_states的state参数是一大堆的标志宏,这些标志宏就是u-boot启动时需要的阶段,每个阶段都有一个宏来表示。

#define    BOOTM_STATE_START    (0x00000001)
#define    BOOTM_STATE_FINDOS    (0x00000002)
#define    BOOTM_STATE_FINDOTHER    (0x00000004)
#define    BOOTM_STATE_LOADOS    (0x00000008)
#define    BOOTM_STATE_RAMDISK    (0x00000010)
#define    BOOTM_STATE_FDT        (0x00000020)
#define    BOOTM_STATE_OS_CMDLINE    (0x00000040)
#define    BOOTM_STATE_OS_BD_T    (0x00000080)
#define    BOOTM_STATE_OS_PREP    (0x00000100)
#define    BOOTM_STATE_OS_FAKE_GO    (0x00000200)    /* 'Almost' run the OS */
#define    BOOTM_STATE_OS_GO    (0x00000400)
  • BOOTM_STATE_START :开始执行bootm的一些准备动作;
  • BOOTM_STATE_FINDOS :查找操作系统镜像;
  • BOOTM_STATE_FINDOTHER :查找操作系统镜像外的其它镜像,比如FDT、ramdisk等;
  • BOOTM_STATE_LOADOS :加载操作系统;
  • BOOTM_STATE_RAMDISK :操作ramdisk;
  • BOOTM_STATE_FDT :操作FDT;
  • BOOTM_STATE_OS_CMDLINE :操作commandline;
  • BOOTM_STATE_OS_BD_T :跳转到操作系统的前的准备动作;
  • BOOTM_STATE_OS_PREP :执行跳转前的准备动作 ;
  • BOOTM_STATE_OS_FAKE_GO :伪跳转,一般都能直接跳转到kernel中去
  • BOOTM_STATE_OS_GO :设置启动参数,跳转到kernel所在的地址上 ;

do_bootm_states根据states来判断要执行的操作。在这些流程中,起传递作用的是bootm_headers_t images这个数据结构,有些流程是解析镜像,往这个结构体里写数据。 而跳转的时候,则需要使用到这个结构体里面的数据。

2.4 do_bootm_states函数执行流程

/**
 * Execute selected states of the bootm command.
 *
 * Note the arguments to this state must be the first argument, Any 'bootm'
 * or sub-command arguments must have already been taken.
 *
 * Note that if states contains more than one flag it MUST contain
 * BOOTM_STATE_START, since this handles and consumes the command line args.
 *
 * Also note that aside from boot_os_fn functions and bootm_load_os no other
 * functions we store the return value of in 'ret' may use a negative return
 * value, without special handling.
 *
 * @param cmdtp        Pointer to bootm command table entry
 * @param flag        Command flags (CMD_FLAG_...)
 * @param argc        Number of subcommand arguments (0 = no arguments)
 * @param argv        Arguments
 * @param states    Mask containing states to run (BOOTM_STATE_...)
 * @param images    Image header information
 * @param boot_progress 1 to show boot progress, 0 to not do this
 * @return 0 if ok, something else on error. Some errors will cause this
 *    function to perform a reboot! If states contains BOOTM_STATE_OS_GO
 *    then the intent is to boot an OS, so this function will not return
 *    unless the image type is standalone.
 */
int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
            int states, bootm_headers_t *images, int boot_progress)
{
    boot_os_fn *boot_fn;
    ulong iflag = 0;
    int ret = 0, need_boot_fn;

    images->state |= states;

    /*
     * Work through the states and see how far we get. We stop on
     * any error.
     */
    if (states & BOOTM_STATE_START)
        ret = bootm_start(cmdtp, flag, argc, argv);

    if (!ret && (states & BOOTM_STATE_FINDOS))
        ret = bootm_find_os(cmdtp, flag, argc, argv);

    if (!ret && (states & BOOTM_STATE_FINDOTHER)) {
        ret = bootm_find_other(cmdtp, flag, argc, argv);
        argc = 0;    /* consume the args */
    }

    /* Load the OS */
    if (!ret && (states & BOOTM_STATE_LOADOS)) {
        ulong load_end;

        iflag = bootm_disable_interrupts();
        ret = bootm_load_os(images, &load_end, 0);
        if (ret == 0)
            lmb_reserve(&images->lmb, images->os.load,
                    (load_end - images->os.load));
        else if (ret && ret != BOOTM_ERR_OVERLAP)
            goto err;
        else if (ret == BOOTM_ERR_OVERLAP)
            ret = 0;
#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY)
        if (images->os.os == IH_OS_LINUX)
            fixup_silent_linux();
#endif
    }

    /* Relocate the ramdisk */
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH
    if (!ret && (states & BOOTM_STATE_RAMDISK)) {
        ulong rd_len = images->rd_end - images->rd_start;

        ret = boot_ramdisk_high(&images->lmb, images->rd_start,
            rd_len, &images->initrd_start, &images->initrd_end);
        if (!ret) {
            setenv_hex("initrd_start", images->initrd_start);
            setenv_hex("initrd_end", images->initrd_end);
        }
    }
#endif
#if IMAGE_ENABLE_OF_LIBFDT && defined(CONFIG_LMB)
    if (!ret && (states & BOOTM_STATE_FDT)) {
        boot_fdt_add_mem_rsv_regions(&images->lmb, images->ft_addr);
        ret = boot_relocate_fdt(&images->lmb, &images->ft_addr,
                    &images->ft_len);
    }
#endif

    /* From now on, we need the OS boot function */
    if (ret)
        return ret;
    boot_fn = bootm_os_get_boot_func(images->os.os);
    need_boot_fn = states & (BOOTM_STATE_OS_CMDLINE |
            BOOTM_STATE_OS_BD_T | BOOTM_STATE_OS_PREP |
            BOOTM_STATE_OS_FAKE_GO | BOOTM_STATE_OS_GO);
    if (boot_fn == NULL && need_boot_fn) {
        if (iflag)
            enable_interrupts();
        printf("ERROR: booting os '%s' (%d) is not supported\n",
               genimg_get_os_name(images->os.os), images->os.os);
        bootstage_error(BOOTSTAGE_ID_CHECK_BOOT_OS);
        return 1;
    }

    /* Call various other states that are not generally used */
    if (!ret && (states & BOOTM_STATE_OS_CMDLINE))
        ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images);
    if (!ret && (states & BOOTM_STATE_OS_BD_T))
        ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images);
    if (!ret && (states & BOOTM_STATE_OS_PREP))
        ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);

#ifdef CONFIG_TRACE
    /* Pretend to run the OS, then run a user command */
    if (!ret && (states & BOOTM_STATE_OS_FAKE_GO)) {
        char *cmd_list = getenv("fakegocmd");

        ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_FAKE_GO,
                images, boot_fn);
        if (!ret && cmd_list)
            ret = run_command_list(cmd_list, -1, flag);
    }
#endif

    /* Check for unsupported subcommand. */
    if (ret) {
        puts("subcommand not supported\n");
        return ret;
    }

    /* Now run the OS! We hope this doesn't return */
    if (!ret && (states & BOOTM_STATE_OS_GO))
        ret = boot_selected_os(argc, argv, BOOTM_STATE_OS_GO,
                images, boot_fn);

    /* Deal with any fallout */
err:
    if (iflag)
        enable_interrupts();

    if (ret == BOOTM_ERR_UNIMPLEMENTED)
        bootstage_error(BOOTSTAGE_ID_DECOMP_UNIMPL);
    else if (ret == BOOTM_ERR_RESET)
        do_reset(cmdtp, flag, argc, argv);

    return ret;
}

代码具体执行流程:

  • 初始化images->state|=states;
  • states跟宏BOOTM_STATE_START进行与操作,通过执行bootm_start;
  • states跟宏BOOTM_STATE_FINDOS进行与操作,通过执行bootm_find_os;
  • states跟宏BOOTM_STATE_FINDOTHER进行与操作,通过执行bootm_find_other;
  • states跟宏BOOTM_STATE_LOADOS进行与操作,通过关闭中断,执行bootm_load_os;
  • states跟宏BOOTM_STATE_OS_PREP进行与操作,通过执行boot_fn;
  • states跟宏BOOTM_STATE_OS_GO进行与操作,通过执行boot_selected_os;

boot_selected_os,这函数里面就执行do_bootm_linux跳转到我们的内核去运行了,如无意外,到了这里一般情况下就不返回了。

我们根据状态参数,绘制出这个函数的执行流程:

2.5 bootm_start(common/bootm.c)

static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc,
               char * const argv[])
{
    memset((void *)&images, 0, sizeof(images));
    images.verify = getenv_yesno("verify");

    boot_start_lmb(&images);

    bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
    images.state = BOOTM_STATE_START;

    return 0;
}

代码具体执行流程:

  • 清空images结构体;
  • 获取环境遍历verify,并赋值给images.verify;
  • 执行boot_start_lmb()初始化images.lmb;
  • 执行bootstage_mark_name,记录启动阶段的名字;
  • 设置images.state = BOOTM_STATE_START;

2.6 bootm_find_os(common/bootm.c)

 

 

static int bootm_find_os(cmd_tbl_t *cmdtp, int flag, int argc,
             char * const argv[])
{
    const void *os_hdr;
    bool ep_found = false;
    int ret;

    /* 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)) {
#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
    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);
        images.os.arch = image_get_arch(os_hdr);
        break;
#endif
#if IMAGE_ENABLE_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");
            bootstage_error(BOOTSTAGE_ID_FIT_TYPE);
            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");
            bootstage_error(BOOTSTAGE_ID_FIT_COMPRESSION);
            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");
            bootstage_error(BOOTSTAGE_ID_FIT_OS);
            return 1;
        }

        if (fit_image_get_arch(images.fit_hdr_os,
                       images.fit_noffset_os,
                       &images.os.arch)) {
            puts("Can't get image ARCH!\n");
            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");
            bootstage_error(BOOTSTAGE_ID_FIT_LOADADDR);
            return 1;
        }
        break;
#endif
#ifdef CONFIG_ANDROID_BOOT_IMAGE
    case IMAGE_FORMAT_ANDROID:
        images.os.type = IH_TYPE_KERNEL;
        images.os.comp = IH_COMP_NONE;
        images.os.os = IH_OS_LINUX;

        images.os.end = android_image_get_end(os_hdr);
        images.os.load = android_image_get_kload(os_hdr);
        images.ep = images.os.load;
        ep_found = true;
        break;
#endif
    default:
        puts("ERROR: unknown image format type!\n");
        return 1;
    }

    /* If we have a valid setup.bin, we will use that for entry (x86) */
    if (images.os.arch == IH_ARCH_I386 ||
        images.os.arch == IH_ARCH_X86_64) {
        ulong len;

        ret = boot_get_setup(&images, IH_ARCH_I386, &images.ep, &len);
        if (ret < 0 && ret != -ENOENT) {
            puts("Could not find a valid setup.bin for x86\n");
            return 1;
        }
        /* Kernel entry point is the setup.bin */
    } else if (images.legacy_hdr_valid) {
        images.ep = image_get_ep(&images.legacy_hdr_os_copy);
#if IMAGE_ENABLE_FIT
    } else if (images.fit_uname_os) {
        int ret;

        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 if (!ep_found) {
        puts("Could not find kernel entry point!\n");
        return 1;
    }

    if (images.os.type == IH_TYPE_KERNEL_NOLOAD) {
        images.os.load = images.os.image_start;
        images.ep += images.os.load;
    }

    images.os.start = map_to_sysmem(os_hdr);

    return 0;
}

 

代码具体执行流程:

  • boot_get_kernel函数获取内核镜像在内存地址和大小:
    • genimg_get_kernel_addr_fit获取内核真是地址,也就是我们传入的0x30000000参数;
    • genimg_get_image解析0x30000000这个地址,如果这个地址位于dataflash storage,将会将内核镜像加载到RAM中;
    • genimg_get_format获取内核镜像头信息,它是在 zImage 之前加上一个长度为0x40的头信息(tag)(也就是说uImage 是一个二进制文件),在头信息内说明了该镜像文件的类型、加载 位置、生成时间、大小等信息;镜像文件的类型有多种:传统格式,FIT格式和安卓格式等;

    • 然后初始化images.os.image_start和images.os.image_len,如果是FIT格式,还会初始化images中部分与fit相关的字段;
  • 根据返回的头部信息指针,我们去获取到内核想信息并复制给images.os的各个成员,包括内核类型type,内核压缩方式comp,内核是什么操作系统os,内核要装载到内存的哪个位置load,内核是什么体系架构arch,为以后的工作做准备,这里要说明一下,现在内核所在的内存地址是uboot所指定,而内核启动的内存地址不一定在这里,是在laod成员所执行的地址,后面需要把整个镜像拷贝到这里;

  • 最后将images.os.load赋值给images.ep,其实就是内核的启动地址了;

 

2.7 bootm_find_other

2.8 bootm_load_os

2.9 boot_fn

2.10 boot_selected_os

参考文章

[1]七,移植linux-3.19内核

[2][uboot] uboot启动kernel篇(二)——bootm跳转到kernel的流程

[3]linux驱动之uboot启动过程及参数传递

[4]S5PV210-uboot解析(五)-do_bootm函数分析

[5]Linux内核镜像格式

 

标签:bootm,uboot,image,BOOTM,images,STATE,linux,Mini440,os
来源: https://www.cnblogs.com/zyly/p/15814964.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有