boot 传递了什么内容到 kernel

boot 传递了什么内容到 kernel?  是怎样传递的?

/********************************************************************************/
 boot 传递了什么内容到 kernel?  是怎样传递的?
 传递的内容是machid and tag address, 当然kernel entry 也是这里决定的
/********************************************************************************/

从最终的地方开始看:

arch/arm/lib/bootm.c

int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
{
    /* No need for those on ARM */
    if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
        return -1;

    if (flag & BOOTM_STATE_OS_PREP) {
        boot_prep_linux(images);
        return 0;
    }

    if (flag & BOOTM_STATE_OS_GO) {
        boot_jump_linux(images);
        return 0;
    }

    boot_prep_linux(images);
    boot_jump_linux(images);
    return 0;
}

1] 首先看输入参数:

   flag标识boot的方法,这里的flag为0,不关注flag的具体含义。另外argv没有使用,所以只需关注bootm_headers_t *images。


    /*
     * 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;
        
        image_info_t    os;            /* os image info */
        ulong        ep;            /* entry point of OS */

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

        struct lmb    lmb;            /* for memory mgmt */
    } bootm_headers_t;

2] /* Subcommand: PREP */

static void boot_prep_linux(bootm_headers_t *images)
{
    char *commandline = getenv("bootargs");

    debug("using: ATAGS\n");
    setup_start_tag(gd->bd);
    setup_commandline_tag(gd->bd, commandline);
    setup_memory_tags(gd->bd);
    setup_end_tag(gd->bd);
}

/* gd 是个全局变量,boot_params的值是在 board_ini时赋值的,offset 为 0x100
 * setup TAG, 就是把TAG写到地址固定的地方,kernel 从这个地方读取。
 * 对应的kernel代码在哪里?
 */
static void setup_start_tag (bd_t *bd)
{
    params = (struct tag *)bd->bi_boot_params;

    params->hdr.tag = ATAG_CORE;
    params->hdr.size = tag_size (tag_core);

    params->u.core.flags = 0;
    params->u.core.pagesize = 0;
    params->u.core.rootdev = 0;

    params = tag_next (params);
}

borad/nufront/ns115xx/yy.c
 board_init:
    /* adress of boot parameters */
    gd->bd->bi_boot_params = 0x80000100;

3]/* Subcommand: GO */

static void boot_jump_linux(bootm_headers_t *images)
{
    unsigned long machid = gd->bd->bi_arch_number;
    char *s;
    /* how to get a function point variable */
    void (*kernel_entry)(int zero, int arch, uint params);
    unsigned long r2;
    /* how to value a function point variable */
    kernel_entry = (void (*)(int, int, uint))images->ep;

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

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

    s = getenv("dtbaddr");
    if (s) {
        strict_strtoul(s, 16, &r2);
        printf("Using r2 0x%lx from environment\n", r2);
    } else {
        r2 = DTBADDR_DEFAULT;
        printf("Using r2 0x%lx from default dtbaddr\n", r2);
    }
    /*r0:0, r1:machid, r2: tag address*/
    kernel_entry(0, machid, r2);
}

TAG的内容来自哪里?怎样赋值的?怎样更改?

/********************************************************************************/
TAG的内容来自哪里?怎样赋值的?怎样更改?
TAG的内容来自env,可以来自代码的设置,也可以从MMC等地方读出,setenv and saveenv
/********************************************************************************/
boot_prep_linux -> getenv("bootargs");

arch/arm/cpu/armxxx/start.s
bl    board_init_f

board_init_f ->
    for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
        if ((*init_fnc_ptr)() != 0) {
            hang ();
        }
    }
    -> env_init,        /* initialize environment */
有多个 env_init的定义:从包含的头文件判断是: env_mmc.c
int env_init(void)
{
    /* use default */
    gd->env_addr    = (ulong)&default_environment[0];
    gd->env_valid    = 1;

    return 0;
}

board_init_r -> env_relocate();
void env_relocate(void)
{

    if (gd->env_valid == 0) {
        ----
    } else {
        env_relocate_spec();
    }
}

void env_relocate_spec(void)
{

    ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
    struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
    u32 offset;

    if (init_mmc_for_env(mmc) || mmc_get_env_addr(mmc, &offset))
        return set_default_env(NULL);

    if (read_env(mmc, CONFIG_ENV_SIZE, offset, buf))
        return set_default_env(NULL);

    env_import(buf, 1);
}

/*这里看上去只是建立了hash table,数据来自哪里?数据到底是存在hash table 里还是MMC中?*/
void set_default_env(const char *s)
{

    if (himport_r(&env_htab, (char *)default_environment,
            sizeof(default_environment), '\0', 0) == 0)
        error("Environment import failed: errno = %d\n", errno);

    gd->flags |= GD_FLG_ENV_READY;
}

U_BOOT_CMD_COMPLETE(
    printenv, CONFIG_SYS_MAXARGS, 1,    do_env_print,
    "print environment variables",
    "\n    - print values of all environment variables\n"
    "printenv name ...\n"
    "    - print value of environment variable 'name'",
    var_complete
);
do_env_print -> env_print -> hexport_r(&env_htab,)[print whole list]

感到困惑的,为什么代码里没有决定bootargs, 是因为你写了set bootargs 'xxxx',
如果不写就是默认值,如果写入一次就保存啦?不是的必须使用saveenv才会保存到mmc,
setenv只是保存到ram中,也就是写道那个hash table 中。

该实例是使用保存在MMC中的数据:从MMC 中读出数据进行分析,代码中的 defaultsetting不起作用。
void env_relocate_spec(void)
{
    ALLOC_CACHE_ALIGN_BUFFER(char, buf, CONFIG_ENV_SIZE);
    struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
    env_import(buf, 1);
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值