Boot 传参至 Kernel 的方法


1. 需求

将boot中的字符串传到kernel中。

2. 实现方法

目前的框架已经有从boot传参到kernel的方法,比如cmdline会把bootargs的数据传到kernel下,我们只需要模拟cmdline的实现方法,添加一个接口即可。

2.1. boot部分修改

arch/arm/include/asm/setup.h:

/* command line: \0 terminated string */
#define ATAG_CMDLINE 0x54410009

/* custom atag: char array */
#define ATAG_CUSTOM  0x54410100

struct tag_custom {
    u8 size;
    char data[128]; /* this is the minimum size */
};

union {
    ... ...
    struct tag_cmdline cmdline;
    struct tag_custom custom;

    ... ...

} u;

arch/arm/lib/bootm.c:

static void setup_custom_tag(char *data, u8 size)
{
    params->hdr.tag = ATAG_CUSTOM;
    params->hdr.size = (sizeof (struct tag_header) + size + 4) >> 2;
    params->u.custom.size = size;
    memcpy(params->u.custom.data, data, size);
    params = tag_next (params);
}

/* Subcommand: PREP */
static void boot_prep_linux(bootm_headers_t *images)
{
    char *commandline = getenv("bootargs");
    char *pethaddr = getenv("ethaddr");

    if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len) {
        ... ...
    } else if (BOOTM_ENABLE_TAGS) {

        ... ...

        if (BOOTM_ENABLE_CMDLINE_TAG)
            setup_commandline_tag(gd->bd, commandline);
        ... ....
        setup_custom_tag(pethaddr, 128);
        setup_board_tags(&params);
        setup_end_tag(gd->bd);
    } else {
        printf("FDT and ATAGS support not compiled in - hanging\n");
        hang();
    }
}

2.2. kernel部分修改

arch/arm/include/uapi/asm/setup.h:

struct tag_cmdline {
    char cmdline[1]; /* this is the minimum size */
};

/* custom atag: char array */
#define ATAG_CUSTOM 0x54410100

struct tag_custom {
    __u8 size;
    char data[128]; /* this is the minimum size */
};

union {
    ... ...
    struct tag_cmdline cmdline;
    struct tag_custom custom;

    ... ...

} u;

arch/arm/mach-sstar/atags_to_fdt.c:

#include <linux/kernel.h>

int early_atags_to_fdt(void *atag_list, void *fdt, int total_space)
{
    ... ...

    for_each_tag(atag, atag_list) {
        if (atag->hdr.tag == ATAG_CMDLINE) {
            /* Append the ATAGS command line to the device tree
            * command line.
            * NB: This means that if the same parameter is set in
            * the device tree and in the tags, the one from the
            * tags will be chosen.
            */
            if (do_extend_cmdline)
                merge_fdt_bootargs(fdt, atag->u.cmdline.cmdline);
            else
                setprop_string(fdt, "/chosen", "bootargs",
            atag->u.cmdline.cmdline);
        }

        else if (atag->hdr.tag == ATAG_CUSTOM) {
            char data[128];
            memcpy(data, atag->u.custom.data, atag->u.custom.size);
            printk("atag_custom test:%d\n", (int)atag->u.custom.size);
            printk("atag_custom test:%s\n", atag->u.custom.data);
        }

... ...
    }

}

3. 检查确认

添加成功之后,上电启动,从如下打印信息中,可以看到已经获取到mac addr了。

Starting kernel ...

Booting Linux on physical CPU 0x0
CPU: ARMv7 Processor [410fd034] revision 4 (ARMv7), cr=70c5383d
CPU: div instructions available: patching division code
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
atag_custom test:128
atag_custom test:00:30:1b:ba:02:db
early_atags_to_fdt() success