u-boot如何传递参数给kernel

u-boot环境变量bootargs就是要传递给kernel的参数,如:

bootargs=console=ttymxc0 init=/init androidboot.console=ttymxc0 video=mxcdi0fb:RGB24,CPT-WVGA di0_primary video=mxcdi1fb:RGB666,AUO ldb=single,di=1,ch1_map=JEIDA gpu_nommu gpu_memory=32M calibration lpj=3997696 pty.legacy_count=32 quiet


u-boot中对环境变量的修改,可以用下面的方式:

    sprintf(tz, "tz=%d", value);

    s = getenv("bootargs");
    sprintf(buf, "%s %s", s, tz); 

    setenv("bootargs", buf);


kernel中两个重要的宏:

在include/linux/init.h中

#define __setup(str, fn)                    \
    __setup_param(str, fn, fn, 0)

#define early_param(str, fn)                    \
    __setup_param(str, fn, fn, 1)


__setup与early_param不同的是,early_param 宏注册的内核选项必须要在其他内核选项之前被处理。
在函数start_kernel中,parse_early_param处理early_param定义的参数,parse_args处理__setup定义的参数。


kernel/printk.c

static int __init console_setup(char *str)
{
    char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for index */
    char *s, *options, *brl_options = NULL;
    int idx; 

#ifdef CONFIG_A11Y_BRAILLE_CONSOLE
    if (!memcmp(str, "brl,", 4)) {
        brl_options = "";
        str += 4;
    } else if (!memcmp(str, "brl=", 4)) {
        brl_options = str + 4; 
        str = strchr(brl_options, ',');
        if (!str) {
            printk(KERN_ERR "need port name after brl=\n");
            return 1;
        }    
        *(str++) = 0; 
    }    
#endif

    /*   
     * Decode str into name, index, options.
     */
    if (str[0] >= '0' && str[0] <= '9') {
        strcpy(buf, "ttyS");
        strncpy(buf + 4, str, sizeof(buf) - 5);
    } else {
        strncpy(buf, str, sizeof(buf) - 1);
    }
    buf[sizeof(buf) - 1] = 0;
    if ((options = strchr(str, ',')) != NULL)
        *(options++) = 0;
#ifdef __sparc__
    if (!strcmp(str, "ttya"))
        strcpy(buf, "ttyS0");
    if (!strcmp(str, "ttyb"))
        strcpy(buf, "ttyS1");
#endif
    for (s = buf; *s; s++)
        if ((*s >= '0' && *s <= '9') || *s == ',')
            break;
    idx = simple_strtoul(s, NULL, 10);
    *s = 0;

    __add_preferred_console(buf, idx, options, brl_options);
    console_set_on_cmdline = 1;
    return 1;
}
__setup("console=", console_setup);


init/main.c

static int __init init_setup(char *str)
{
    unsigned int i;

    execute_command = str;
    /*  
     * In case LILO is going to boot us with default command line,
     * it prepends "auto" before the whole cmdline which makes
     * the shell think it should execute a script with such name.
     * So we ignore all arguments entered _before_ init=... [MJ]
     */
    for (i = 1; i < MAX_INIT_ARGS; i++)
        argv_init[i] = NULL;
    return 1;
}
__setup("init=", init_setup);

arch/arm/mach-mx5/early_setup.c

static int __init di1_setup(char *__unused)
{
    primary_di = 1;
    return 1;
}
__setup("di1_primary", di1_setup);

static int __init di0_setup(char *__unused)
{
    primary_di = 0;
    return 1;
}
__setup("di0_primary", di0_setup);

drivers/video/fbmem.c:

static int __init video_setup(char *options)
{
    int i, global = 0; 

    if (!options || !*options)
        global = 1; 

    if (!global && !strncmp(options, "ofonly", 6)) {
        ofonly = 1; 
        global = 1; 
    }    

    if (!global && !strchr(options, ':')) {
        fb_mode_option = options;
        global = 1; 
    }    

    if (!global) {
        for (i = 0; i < FB_MAX; i++) {
            if (video_options[i] == NULL) {
                video_options[i] = options;
                break;
            }    

        }    
    }    

    return 1;
}
__setup("video=", video_setup);
其中 video=mxcdi0fb:RGB24,CPT-WVGA di0_primary 表示主屏幕(RGB)显示,video=mxcdi1fb:RGB666,AUO表示分离屏(LVDS)显示。

drivers/video/mxc/ldb.c:

static int __init ldb_setup(char *options)
{
    if (!strcmp(options, "=off")) {
        g_enable_ldb = MXC_DISABLE;
        return 1;
    } else 
        g_enable_ldb = MXC_ENABLE;

    if (!strlen(options))
        return 1;
    else if (!strsep(&options, "="))
        return 1;

    if (!strncmp(options, "di0", 3))
        g_di0_used = true;

    if (!strncmp(options, "di1", 3))
        g_di1_used = true;

    if (!strncmp(options, "single", 6)) {
        strsep(&options, ",");
        if (!strncmp(options, "di=0", 4)) {
            g_chan_mode_opt = LDB_SIN_DI0;
            g_di0_used = true;
        } else {
            g_chan_mode_opt = LDB_SIN_DI1;
            g_di1_used = true;
        }    
    } else if (!strncmp(options, "separate", 8)) {
        g_chan_mode_opt = LDB_SEP;
        g_di0_used = true;
        g_di1_used = true;
    } else if (!strncmp(options, "dual", 4)) {
        strsep(&options, ",");
        if (!strncmp(options, "di=", 3)) {
            if (simple_strtoul(options + 3, NULL, 0) == 0) {
                g_chan_mode_opt = LDB_DUL_DI0;
                g_di0_used = true;
            } else {
                g_chan_mode_opt = LDB_DUL_DI1;
                g_di1_used = true;
            }
        }
    } else if (!strncmp(options, "split", 5)) {
        strsep(&options, ",");
        if (!strncmp(options, "di=", 3)) {
            if (simple_strtoul(options + 3, NULL, 0) == 0) {
                g_chan_mode_opt = LDB_SPL_DI0;
                g_di0_used = true;
            } else {
                g_chan_mode_opt = LDB_SPL_DI1;
                g_di1_used = true;
            }
        }
    } else
        return 1;

    if ((strsep(&options, ",") != NULL) &&
        !strncmp(options, "ch0_map=", 8)) {
        if (!strncmp(options + 8, "SPWG", 4))
            g_chan_bit_map[0] = LDB_BIT_MAP_SPWG;
        else
            g_chan_bit_map[0] = LDB_BIT_MAP_JEIDA;
    }

    if (!(g_chan_mode_opt == LDB_SIN_DI0 ||
          g_chan_mode_opt == LDB_SIN_DI1) &&
        (strsep(&options, ",") != NULL) &&
        !strncmp(options, "ch1_map=", 8)) {
        if (!strncmp(options + 8, "SPWG", 4))
            g_chan_bit_map[1] = LDB_BIT_MAP_SPWG;
        else
            g_chan_bit_map[1] = LDB_BIT_MAP_JEIDA;
    }

    return 1;
}
__setup("ldb", ldb_setup);

板级初始化文件arch/arm/mach-mx5/mx53_a1001em.c中:

static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags,
                   char **cmdline, struct meminfo *mi) 
{
    struct tag *t;
    struct tag *mem_tag = 0; 
    int total_mem = SZ_512M;
    int left_mem = 0; 
    int gpu_mem = SZ_128M;
    int fb_mem = SZ_32M;
    char *str;

    mxc_set_cpu_type(MXC_CPU_MX53);

    for_each_tag(mem_tag, tags) {
        if (mem_tag->hdr.tag == ATAG_MEM) {
            total_mem = mem_tag->u.mem.size;
            break;
        }    
    }    

    for_each_tag(t, tags) {
        if (t->hdr.tag == ATAG_CMDLINE) {
            str = t->u.cmdline.cmdline;
            str = strstr(str, "mem=");
            if (str != NULL) {
                str += 4;
                left_mem = memparse(str, &str);
            }

            str = t->u.cmdline.cmdline;
            str = strstr(str, "gpu_nommu");
            if (str != NULL)
                gpu_data.enable_mmu = 0;

            str = t->u.cmdline.cmdline;
            str = strstr(str, "gpu_memory=");
            if (str != NULL) {
                str += 11;
                gpu_mem = memparse(str, &str);
            }

            break;
        }
    }

    ...
}

init/main.c:

static int __init debug_kernel(char *str)
{
    console_loglevel = 10; 
    return 0;
}

static int __init quiet_kernel(char *str)
{
    console_loglevel = 4;
    return 0;
}

early_param("debug", debug_kernel);
early_param("quiet", quiet_kernel);


init/calibrate.c

static int __init lpj_setup(char *str)
{
    preset_lpj = simple_strtoul(str,NULL,0);
    return 1;
}

__setup("lpj=", lpj_setup);

u-boot参数直接传递到android应用层:

system/core/init/init.c

static void import_kernel_nv(char *name, int in_qemu)
{
    char *value = strchr(name, '=');

    if (value == 0) {
    if (!strcmp(name, "calibration"))
        calibration = 1;
    else if (!strcmp(name, "mksnapshot"))
        mksnapshot = 1;
    return;
    }
    *value++ = 0;
    if (*name == 0) return;

    if (!in_qemu)
    {
        /* on a real device, white-list the kernel options */
        if (!strcmp(name,"qemu")) {
            strlcpy(qemu, value, sizeof(qemu));
        } else if (!strcmp(name,"androidboot.console")) {
            strlcpy(console, value, sizeof(console));
        } else if (!strcmp(name,"androidboot.mode")) {
            strlcpy(bootmode, value, sizeof(bootmode));
        } else if (!strcmp(name,"androidboot.serialno")) {
            strlcpy(serialno, value, sizeof(serialno));
        } else if (!strcmp(name,"androidboot.baseband")) {
            strlcpy(baseband, value, sizeof(baseband));
        } else if (!strcmp(name,"androidboot.carrier")) {
            strlcpy(carrier, value, sizeof(carrier));
        } else if (!strcmp(name,"androidboot.bootloader")) {
            strlcpy(bootloader, value, sizeof(bootloader));
        } else if (!strcmp(name,"androidboot.hardware")) {
            strlcpy(hardware, value, sizeof(hardware));
        } else if (!strcmp(name,"boot_type")) {
            strlcpy(boot_type, value, sizeof(boot_type));
        }
    } else {
        /* in the emulator, export any kernel option with the
         * ro.kernel. prefix */
        char  buff[32];
        int   len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name );
        if (len < (int)sizeof(buff)) {
            property_set( buff, value );
        }
    }
}




你可能感兴趣的:(Linux内核)