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




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 以下是一个基本的 U-Boot 脚本,用于配置 SPI Flash。该脚本使用 `sf probe` 命令探测 SPI Flash 设备,然后设置 U-Boot 环境变量来存储 Flash 设备的参数。请注意,此示例中的参数值需要根据您的 Flash 设备进行更改。 ``` # 定义 Flash 设备参数 setenv spi_flash_addr 0x0 # Flash 设备地址 setenv spi_flash_size 0x800000 # Flash 设备大小 # 探测 Flash 设备 sf probe # 将 Flash 设备参数存储到环境变量中 setenv bootargs root=/dev/mtdblock0 rootfstype=jffs2 rw setenv bootcmd 'sf read ${loadaddr} ${spi_flash_addr} ${spi_flash_size}; bootm' saveenv ``` 在这个例子中,`spi_flash_addr` 表示 Flash 设备的起始地址,`spi_flash_size` 表示 Flash 设备的大小。`sf probe` 命令用于探测 SPI Flash 设备,并且将 Flash 设备参数存储到 U-Boot 环境变量中。最后,`bootcmd` 环境变量定义了如何从 Flash 设备启动系统。 ### 回答2: 以下是一个使用u-boot脚本配置SPI闪存的示例: ``` # 使用U-Boot脚本配置SPI闪存示例 # 首先,我们需要加载SPI闪存驱动 # 根据硬件版本和芯片型号进行适配 # 这里我们以Spansion SPI闪存为例 sf probe # 然后,我们需要设置闪存的相关参数 # 首先是闪存器件的名称 setenv spi_flash_name "spansion" # 接下来是闪存器件的页大小 # 这里以256字节为例 setenv spi_flash_page_size 256 # 然后是扇区大小 # 这里以4KB为例 setenv spi_flash_sector_size 4096 # 最后是闪存总大小 # 这里以32MB为例 setenv spi_flash_total_size 32M # 配置完成后,可以将相关参数保存到环境变量中 saveenv # 如果需要擦除整个闪存,可以使用以下命令 sf erase 0 ${spi_flash_total_size} # 如果需要读取闪存中的数据,可以使用以下命令 sf read ${loadaddr} 0 ${filesize} # 如果需要将数据写入闪存,可以使用以下命令 sf write ${loadaddr} 0 ${filesize} # 使用以上命令和参数,我们可以在U-Boot环境中配置和操作SPI闪存。 ``` 请注意,实际的配置和操作可能因硬件和芯片型号不同而有所不同。以上示例仅供参考,具体操作步骤和参数应根据实际情况进行适配。 ### 回答3: 下面是一个示例的u-boot脚本配置SPI Flash的例子: ``` # 定义相关环境变量 setenv spi_flash_addr 0x1000000 # SPI Flash起始地址 setenv kernel_image_addr 0x200000 # 内核镜像在内存中的加载地址 setenv dtb_addr 0x400000 # 设备树在内存中的加载地址 # 配置SPI Flash sf probe 0:0 # 扫描并初始化第0个SPI Flash设备 sf erase ${spi_flash_addr} 0x100000 # 擦除SPI Flash的前1MB空间 # 将内核镜像和设备树加载到内存中 tftp ${kernel_image_addr} kernel.img # 从TFTP服务器下载内核镜像 tftp ${dtb_addr} device_tree.dtb # 从TFTP服务器下载设备树 # 将内核镜像和设备树写入SPI Flash sf write ${kernel_image_addr} ${spi_flash_addr} 0x100000 # 将内核镜像写入SPI Flash的第1MB位置 sf write ${dtb_addr} ${spi_flash_addr} 0x200000 # 将设备树写入SPI Flash的第2MB位置 # 设定内核启动参数 setenv bootargs 'console=ttyS0,115200 root=/dev/mtdblock2 rootfstype=jffs2' # 启动内核 bootm ${kernel_image_addr} - ${dtb_addr} ``` 这个例子展示了如何使用u-boot脚本配置SPI Flash。首先定义了SPI Flash的起始地址,并擦除了前1MB的空间。然后从TFTP服务器下载内核镜像和设备树,并将它们写入SPI Flash的相应位置。接着设置内核启动参数,并最后启动内核。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值