内核在start_kernel()开始启动:
start_kernel
-->setup_arch(&command_line); //arch/arm/kernel/setup.c
-->setup_machine_fdt(__atags_pointer); //存储了配置参数的物理地址
-->of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); //调用early_init_dt_scan_chosen来查找入参,并保存在boot_command_line字符串中;
|
int __init early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data) |
|
/* Retrieve command line */ p = of_get_flat_dt_prop(node, "bootargs", &l); if (p != NULL && l > 0) strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE)); |
可以看出来这个查找的是bootargs字符,并将其值拷贝到boot_command_line中;
再来看一下,boot下参数列表里是否有bootargs项,如下可以找到对应的参数
|
Marvell>> pri CASset=max MALLOC_len=5 MPmode=SMP activeimage=imagea amp_enable=no autoload=no baudrate=115200 boot_order=hd_scr hd_img pxe net_img net_scr bootargs=console=ttyS0,115200 root=/dev/mtdblock4 mtdparts=armada-nand:1m(boota),1m@1m(bootb),2m@2m(configa),2m@4m(configb),28m@6m(imagea),14m@34m(imagec0),28m@48m(imageb),14m@76m(imagec1),1m@90m(misca),1m@91m(miscb),-(reserved) rootfstype=cramfs mv_net_config=0 5srst=0 major=0xa5 minor=0x1 hwver=0x1 longrst=0 bootargs_dflt=$console $nandEcc $mtdparts $bootargs_root nfsroot=$serverip:$rootpath ip=$ipaddr:$serverip$bootargs_end $mvNetConfig video=dovefb:lcd0:$lcd0_params clcd.lcd0_enable=$lcd0_enable clcd.lcd_panel=$lcd_panel bootargs_end=:10.4.50.254:255.255.255.0:AvantaLP:eth0:none bootargs_root=root=/dev/nfs rw bootcmd=fsload;bootm bootdelay=3 cacheShare=no ...... |
这样bootargs的参数就拷贝到boot_command_line中,
在setup_arch中,又将boot_command_line拷贝到入参command_line中;
|
/* populate cmd_line too for later use, preserving boot_command_line */ strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE); *cmdline_p = cmd_line; |
__atags_pointer值如何获取???
在head-common.s中,也没看懂汇编,可以参考下面链接;
配置启动参数
启动参数存入后command_line后,会在setup_command_line中,再次将启动参数拷贝到static_command_line中;
|
static void __init setup_command_line(char *command_line) { saved_command_line = alloc_bootmem(strlen (boot_command_line)+1); static_command_line = alloc_bootmem(strlen (command_line)+1); strcpy (saved_command_line, boot_command_line); strcpy (static_command_line, command_line); } |
参数配置:
|
printk(KERN_NOTICE "Kernel command line: %s\n", boot_command_line); parse_early_param(); parse_args("Booting kernel", static_command_line, __start___param, __stop___param - __start___param, -1, -1, &unknown_bootoption); |
有些选项需要在其他选项之前被处理就会调用parse_early_param
|
void __init parse_early_options(char *cmdline) { parse_args("early options", cmdline, NULL, 0, 0, 0, do_early_param); } /* Arch code calls this early on, or if not, just before other parsing. */ void __init parse_early_param(void) { static __initdata int done = 0; static __initdata char tmp_cmdline[COMMAND_LINE_SIZE]; if (done) return; /* All fall through to do_early_param. */ strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE); parse_early_options(tmp_cmdline); done = 1; } |
最终调用do_early_param,与__setup宏有关;可参考之前的博客;
非特殊的选项在parse_args-->parse_one中被处理;
可以看到最初处理函数是在__start___param/__stop___param区域内查找的,该区域存储的列表是build-in类型module的配置参数,
可参考
但是__setup设置的参数在__setup_start __setup_end表示的段内,所有大部分调用unknown_bootoption函数处理;
与__setup宏有关;可参考之前的博客
与__setup宏有关;可参考之前的博客