含义
当前位置:首页 > 其他范文 > 含义 > 列表页

bootargs,mem含义

小草范文网  发布于:2017-05-17  分类: 含义 手机版

篇一:bootcmd及bootargs命令

U-boot的环境变量值得注意的有两个:bootcmd 和bootargs。

u-bootcmd

bootcmd是自动启动时默认执行的一些命令,因此可以在当前环境中定义各种不同配置,不同环境的参数设置,然后设置bootcmd为经常使用的那种参数。

u-bootargs

bootargs是环境变量中的重中之重,甚至可以说整个环境变量都是围绕着bootargs来设置的。

A. root

用来指定rootfs的位置, 常见的情况有:

root=/dev/ram rw

root=/dev/mtdx rw

root=/dev/mtdblockx rw

root=/dev/mtdblock/x rw

root=31:0x

上面的这几个在一定情况下是通用的,当然这要看你当前的系统是否支持,不过mtd是字符设备,而mtdblock是块设备,有时候你的挨个的试到底当前的系统支持上面那种情况下,不过root=/dev/mtdblockx rw比较通用。此外,如果直接指定设备名可以的话,那么使用此设备的设备号也是可以的。

root=/dev/nfs

在文件系统为基于nfs的文件系统的时候使用。当然指定root=/dev/nfs之后,还需要指定nfsroot=serverip:nfs_dir,即指明文件系统存在那个主机的那个目录下面。

B. rootfstype

这个选项需要跟root一起配合使用,一般如果根文件系统是ext2的话,有没有这个选项是无所谓的,但是如果是jffs2,squashfs等文件系统的话,就需要rootfstype指明文件系统的类型,不然会无法挂载根分区.

C. console

console=tty 使用虚拟串口终端设备 .

console=ttyS[,options] 使用特定的串口,options可以是这样的形式bbbbpnx,这里bbbb是指串口的波特率,p是奇偶位(从来没有看过使用过),n是指的bits。

D. mem

mem=xxM 指定内存的大小,不是必须的

E. ramdisk_size

ramdisk_size=xxxxx推荐

上面这两个都可以告诉ramdisk 驱动,创建的ramdisk的size,默认情况下是4m(s390默认8M),你可以查看Documentation/ramdisk.txt找到相关的描述。

F. initrd, noinitrd

当你没有使用ramdisk启动系统的时候,你需要使用noinitrd这个参数,但是如果使用了的话,就需要指定initrd=r_addr,size, r_addr表示initrd在内存中的位置,size表示initrd的大小。

G. init

init指定的是内核启起来后,进入系统中运行的第一个脚本,一般init=/linuxrc, 或者init=/etc/preinit,preinit的内容一般是创建console,null设备节点,运行init程序,挂载一些文件系统等等操作。请注意,很多初学者以为init=/linuxrc是固定写法,其实不然,/linuxrc指的是/目录下面的linuxrc脚本,一般是一个连接罢了。

H. mtdparts

mtdparts=fc000000.nor_flash:1920k(linux),128k(fdt),20M(ramdisk),4M(jffs2),38272k(user),256k(env),384k(uboot)

要想这个参数起作用,内核中的mtd驱动必须要支持,即内核配置时需要选上Device Drivers ---> Memory Technology Device (MTD) support ---> Command line partition table parsing

mtdparts的格式如下:

mtdparts=[;

:= :[,]

:= [@offset][][ro]

:= unique id used in mapping driver/device

:= standard linux memsize OR "-" to denote all remaining space

:= (NAME)

因此你在使用的时候需要按照下面的格式来设置:

mtdparts=mtd-id:@(),@()

这里面有几个必须要注意的:

a. mtd-id 必须要跟你当前平台的flash的mtd-id一致,不然整个mtdparts会失效

b. size在设置的时候可以为实际的size(xxM,xxk,xx),也可以为'-'这表示剩余的所有空间。 举例:

假设flash 的mtd-id是sa1100,那么你可以使用下面的方式来设置:

mtdparts=sa1100:- → 只有一个分区

mtdparts=sa1100:256k(ARMboot)ro,-(root) → 有两个分区

可以查看drivers/mtd/cmdlinepart.c中的注释找到相关描述。

I. ip

指定系统启动之后网卡的ip地址,如果你使用基于nfs的文件系统,那么必须要有这个参数,其他的情况下就看你自己的喜好了。设置ip有两种方法:

ip = ip addr

ip=ip addr:server ip addr:gateway:netmask::which netcard:off

这两种方法可以用,不过很明显第二种要详细很多,请注意第二种中which netcard 是指开发板上的网卡,而不是主机上的网卡。

说完常见的几种bootargs,那么我们来讨论平常我经常使用的几种组合:

1). 假设文件系统是ramdisk,且直接就在内存中,bootargs的设置应该如下:

setenv bootargs ‘initrd=0x32000000,0xa00000 root=/dev/ram0 console=ttySAC0 mem=64M init=/linuxrc’

2). 假设文件系统是ramdisk,且在flash中,bootargs的设置应该如下:

setenv bootargs ‘mem=32M console=ttyS0,115200 root=/dev/ram rw init=/linuxrc’

注意这种情况下你应该要在bootm命令中指定ramdisk在flash中的地址,如bootm kernel_addr ramdisk_addr (fdt_addr)

3). 假设文件系统是jffs2类型的,且在flash中,bootargs的设置应该如下

setenv bootargs ‘mem=32M console=ttyS0,115200 noinitrd root=/dev/mtdblock2 rw rootfstype=jffs2 init=/linuxrc’

4). 假设文件系统是基于nfs的,bootargs的设置应该如下

setenv bootargs ‘noinitrd mem=64M console=ttySAC0 root=/dev/nfs nfsroot=192.168.0.3:/nfs ip=192.168.0.5:192.168.0.3:192.168.0.3:255.255.255.0::eth0:off’

或者

setenv bootargs ‘noinitrd mem=64M console=ttySAC0 root=/dev/nfs nfsroot=192.168.0.3:/nfs ip=192.168.0.5’

篇二:Linux启动bootargs参数分析

Linux启动bootargs参数分析

这几天刚好在看linux c语言启动,现在就顺便把内核在启动时解析bootargs这一块单独拎出来讲解下,内核对于bootargs的解析分为几块: 1.setup_arch(&command_line);

综述:在这个函数中,系统会获得bootargs参数,并对其做简单的初步分析。并将bootargs的参数保存在command_line这个地址中。

详解:

A. 先获得bootargs的地址,uboot传进来的参数是放在30000100的地方的

//一般默认为0x30000100位置//boot_params 如果为0则表示bootloader没有传参数

if (mdesc->boot_params)

tags = phys_to_virt(mdesc->boot_params);

B. 是通过标签ATAG来辨别的, uboot中有相应的标签字,将相应的uboot参数放置到相应的全局变量中。

if (tags->hdr.tag == ATAG_CORE) {

//已经被fixup函数修改,则将atag中的mem段置为none

if (meminfo._banks != 0)

squash_mem_tags(tags);

//继续把atag的参数传递结束, 通过参数的类型(比如ATAG_CMDLINE,ATAG_MEM诸如此类的参数)将bootargs参数全部分析完毕。 parse_tags(tags);

{

extern struct tagtable __tagtable_begin, __tagtable_end;

struct tagtable *t;

//我们的参数是放在__tagtable_begin到__tagtable_end区间内,各个类型的通过__tagtable的宏定义在编译的时候就将其定位在这个区间,我们的每一个参数只需要和每个宏比较,并调用其对用的parse函数。

//对于我们一般的bootargs,只传递了ATAG_CMDLINE,而在其对应的parse函数就是把传递进来的cmdline存放到default_command_line中。 for (t = &__tagtable_begin; t < &__tagtable_end; t++)

if (tag->hdr.tag == t->tag) {

t->parse(tag);

break;

}

return t < &__tagtable_end;

}

}

C. 将cmdline存放至saved_command_line中

//在setup_arch函数刚开始就定义了char *from= default_command_line,因此通过下面这个函数实现把cmdline存放至saved_command_line中。 memcpy(saved_command_line, from, COMMAND_LINE_SIZE);

D.对cmdline做简单的 分析,主要是mem和initrd的

这里的处理和B步比较类似,通过对cmdline中的一个个参数和

__early_begin到__early_end间的参数进行比较。从而得到匹配的参数,然后调用其相应的parse函数进行处理,同时将剩余部分存放到

setup_arch(&command_line)传进来的字符串指针command_line中。。这部分先对cmdline进行分析是因为接下来就需要对页表进行建立,所以必须知道内存mem和initrd文件系统的信息,所以这部分属于early,parse的参数很少。其余的参数解析都留至后面的参数分析中。

2.parse_early_param();

综述:第二次分析cmdline,不过在这里分析的是系统能够辨别的一些早期参数(这个函数甚至可以去掉),而且在分析的时候并不是以setup_arch(&command_line)传出来的command_line为基础,而是以最原生态的saved_command_line为基础的。

详解:

parse_args("early options", tmp_cmdline, NULL, 0, do_early_param);

{

args = next_arg(args, &param, &val);//一个个参数分离

ret = parse_one(param, val, params, num, unknown(就是

do_early_param));//解析参数

由于传进去的num为0,因此对于每一个参数param和值value,直接调用do_early_param解析。

}

// do_early_param这部分的实现就和1中的B/D的处理类似,通过对

__setup_start和__setup_end区间的参数进行比较,找到对应的参数,调用该参数的解析函数。这部分的定义是以__setup(str, fn)的类型出现的,在linux中这类型的启动参数有非常多(比如root,console,ro,rw,rootfstype,md,resume……),几乎这步可以涵盖所有有用的,而且我们自己也可以增加这种操作来支持新的启动参数。

static int __init do_early_param(char *param, char *val)

{

struct obs_kernel_param *p;

for (p = __setup_start; p < __setup_end; p++) {

if (p->early && strcmp(param, p->str) == 0) {

if (p->setup_func(val) != 0)

printk(KERN_WARNING

"Malformed early option '%s'\n", param);

}

}

}

3.parse_args("Booting kernel", command_line, __start___param, __stop___param - __start___param,&unknown_bootoption);

综述:对于比较新的版本真正起作用的函数,与2的parse_early_param();相比,此处对解析列表的处理范围加大了,解析列表中除了包括系统以setup定义的启动参数,还包括模块中定义的param参数以及系统不能辨别的参数。 详解:

command_line是setup_arch函数传递出来的值;

__start___param是param参数的起始地址,在System.map文件中能看到 __stop___param - __start___param是参数个数

unknown_bootoption是对应与启动参数不是param的相应处理函数

同样跟进去最核心的函数也是parse_args(同2中分析):

parse_args("early options", tmp_cmdline, NULL, 0, do_early_param);

{

args = next_arg(args, &param, &val);//一个个参数分离

ret = parse_one(param, val, params, num, unknown(就是

do_early_param));//解析参数

由于传进去的num为就是parm的个数,所以先要将启动参数和param一个个比较。

static int parse_one(char *param,char *val,struct kernel_param *params,

unsigned num_params,int (*handle_unknown)(char *param, char *val)) {

unsigned int i;

//先寻找启动参数是否和param匹配, param变量一般是在驱动模块中

module_param定义的,存放在*(param)空间。如果匹配则将param参数的值用相应的value代替。

//也就是说通过这种方式可以在启动参数中为驱动的参数赋值,而且可以看出linux中认为param参数是以后主要使用的启动参数传递方式,将慢慢摒弃__setup的形式。

for (i = 0; i < num_params; i++) {

if (parameq(param, params[i].name)) {

DEBUGP("They are equal! Calling %p\n",

params[i].set);

return params[i].set(val, &params[i]);

}

}

//当然对于嵌入式的cmdline,一般而言都没有param参数的值,所以都是调用此处的handle_unknown

如一个很简单的例子

Kernel command line: root=/dev/mtdblock3 console=ttyS0,115200

rootfstype=yaffs mem=32m

Unknown argument: calling c00082e4

parram is root, val is /dev/mtdblock3

parram is console, val is ttyS0,115200

parram is rootfstype, val is yaffs

if (handle_unknown) {

DEBUGP("Unknown argument: calling %p\n", handle_unknown);return handle_unknown(param, val);

}

{

/* Handle obsolete-style parameters */其实我们的参数在handle_unknown中还是过时的参数解析方式的,就是obsolette_checksetup函数,这个函数内部的处理和parse_early_param()类似,所以这里就不详细解释了。 if (obsolete_checksetup(param))

return 0;

对于既不是param,在handle_unknown中又不是setup形式的参数字符串,但设置了参数值。就将其放置在系统启动后的环境变量全局数组envp_init[]中的同名参数或空环境变量中。

对于没有设置参数值的参数字符串就将其传给argv_init[]中同名参数或空参数。

……

}

DEBUGP("Unknown argument `%s'\n", param);

return -ENOENT;

}

}

篇三:linux bootargs参数解析

【原创】Linux启动bootargs参数分析

Written by leeming

这几天刚好在看linux c语言启动,现在就顺便把内核在启动时解析bootargs这一块单独拎出来讲解下,内核对于bootargs的解析分为几块:

1. setup_arch(&command_line);

综述:在这个函数中,系统会获得bootargs参数,并对其做简单的初步分析。并将bootargs的参数保存在command_line这个地址中。

详解:

A.先获得bootargs的地址,uboot传进来的参数是放在30000100的地方的 //一般默认为0x30000100位置//boot_params 如果为0则表示bootloader没有传参数

if (mdesc->boot_params)

tags = phys_to_virt(mdesc->boot_params);

B. 是通过标签ATAG来辨别的, uboot中有相应的标签字,将相应的uboot参数放置到相应的全局变量中。

if (tags->hdr.tag == ATAG_CORE) {

//已经被fixup函数修改,则将atag中的mem段置为none

if (meminfo._banks != 0)

squash_mem_tags(tags);

//继续把atag的参数传递结束, 通过参数的类型(比如ATAG_CMDLINE,ATAG_MEM诸如此类的参数)将bootargs参数全部分析完毕。

parse_tags(tags);

{

extern struct tagtable __tagtable_begin, __tagtable_end;

struct tagtable *t;

//我们的参数是放在__tagtable_begin到__tagtable_end区间内,各个类型的通过__tagtable的宏定义在编译的时候就将其定位在这个区间,我们的每一个参数只需要和每个宏比较,并调用其对用的parse函数。

//(转自:wWw.XiAocAoFanWeN.cOm 小 草 范文网:bootargs,mem含义)对于我们一般的bootargs,只传递了ATAG_CMDLINE,而在其对应的parse函数就是把传递进来的cmdline存放到default_command_line中。 for (t = &__tagtable_begin; t < &__tagtable_end; t++)

if (tag->hdr.tag == t->tag) {

t->parse(tag);

break;

}

return t < &__tagtable_end;

}

}

C.将cmdline存放至saved_command_line中

//在setup_arch函数刚开始就定义了char *from= default_command_line,因此通过下面这个函数实现把cmdline存放至saved_command_line中。 memcpy(saved_command_line, from, COMMAND_LINE_SIZE);

D. 对cmdline做简单的 分析,主要是mem和initrd的

这里的处理和B步比较类似,通过对cmdline中的一个个参数和__early_begin到__early_end间的参数进行比较。从而得到匹配的参数,然后调用其相应的parse函数进行处理,同时将剩余部分存放到setup_arch(&command_line)传进来的字符串指针command_line中。。这部分先对cmdline进行分析是因为接下来就需要对页表进行建立,所以必须知道内存mem和initrd文件系统的信息,所以这部分属于early,parse的参数很少。其余的参数解析都留至后面的参数分析中。

2. parse_early_param();

综述:第二次分析cmdline,不过在这里分析的是系统能够辨别的一些早期参数(这个函数甚至可以去掉),而且在分析的时候并不是以setup_arch(&command_line)传出来的command_line为基础,而是以最原生态的saved_command_line为基础的。

详解:

parse_args("early options", tmp_cmdline, NULL, 0, do_early_param);

{

args = next_arg(args, &param, &val);//一个个参数分离

ret = parse_one(param, val, params, num, unknown(就是do_early_param));//解析参数

由于传进去的num为0,因此对于每一个参数param和值value,直接调用do_early_param解析。

}

// do_early_param这部分的实现就和1中的B/D的处理类似,通过对__setup_start和__setup_end区间的参数进行比较,找到对应的参数,调用该参数的解析函数。这部分的定义是以__setup(str, fn)的类型出现的,在linux中这类型的启动参数有非常多(比如root,console,ro,rw,rootfstype,md,resume……),几乎这步可以涵盖所有有用的,而且我们自己也可以增加这种操作来支持新的启动参数。

static int __init do_early_param(char *param, char *val)

{

struct obs_kernel_param *p;

for (p = __setup_start; p < __setup_end; p++) {

if (p->early && strcmp(param, p->str) == 0) {

if (p->setup_func(val) != 0)

printk(KERN_WARNING

"Malformed early option '%s'\n", param);

}

}

}

3. parse_args("Booting kernel", command_line, __start___param, __stop___param - __start___param,&unknown_bootoption);

综述:对于比较新的版本真正起作用的函数,与2的parse_early_param();相比,此处对解析列表的处理范围加大了,解析列表中除了包括系统以setup定义的启动参数,还包括模块中定义的param参数以及系统不能辨别的参数。 详解:

command_line是setup_arch函数传递出来的值;

__start___param是param参数的起始地址,在System.map文件中能看到 __stop___param - __start___param是参数个数

unknown_bootoption是对应与启动参数不是param的相应处理函数

同样跟进去最核心的函数也是parse_args(同2中分析):

parse_args("early options", tmp_cmdline, NULL, 0, do_early_param);

{

args = next_arg(args, &param, &val);//一个个参数分离

ret = parse_one(param, val, params, num, unknown(就是do_early_param));//解析参数

由于传进去的num为就是parm的个数,所以先要将启动参数和param一个个比较。

static int parse_one(char *param,char *val,struct kernel_param *params,

unsigned num_params,int (*handle_unknown)(char *param, char *val)) {

unsigned int i;

//先寻找启动参数是否和param匹配, param变量一般是在驱动模块中module_param定义的,存放在*(param)空间。如果匹配则将param参数的值用相应的value代替。

//也就是说通过这种方式可以在启动参数中为驱动的参数赋值,而且可以看出linux中认为param参数是以后主要使用的启动参数传递方式,将慢慢摒弃__setup的形式。

for (i = 0; i < num_params; i++) {

if (parameq(param, params[i].name)) {

DEBUGP("They are equal! Calling %p\n",

params[i].set);

return params[i].set(val, &params[i]);

}

}

//当然对于嵌入式的cmdline,一般而言都没有param参数的值,所以都是调用此处的handle_unknown

如一个很简单的例子:

Kernel command line: root=/dev/mtdblock3 console=ttyS0,115200 rootfstype=yaffs mem=32m

Unknown argument: calling c00082e4

parram is root, val is /dev/mtdblock3

parram is console, val is ttyS0,115200

parram is rootfstype, val is yaffs

if (handle_unknown) {

DEBUGP("Unknown argument: calling %p\n", handle_unknown);return handle_unknown(param, val);

}

{

/* Handle obsolete-style parameters */其实我们的参数在handle_unknown中还是过时的参数解析方式的,就是obsolette_checksetup函数,这个函数内部的处理和parse_early_param()类似,所以这里就不详细解释了。 if (obsolete_checksetup(param))

return 0;

对于既不是param,在handle_unknown中又不是setup形式的参数字符串,但设置了参数值。就将其放置在系统启动后的环境变量全局数组envp_init[]中的同名参数或空环境变量中。

对于没有设置参数值的参数字符串就将其传给argv_init[]中同名参数或空参数。

……

}

DEBUGP("Unknown argument `%s'\n", param);

return -ENOENT;

}

}

本文已影响