B:LINUX解析UBOOT传入参数的原理

来源:互联网 发布:web q前端开发json 编辑:程序博客网 时间:2024/05/17 08:51


(会把传入的参数存一个字符串中)

LINUX内核源码版本:linux-3.0.86  

 

kernel_entry(0, machid, bd->bi_boot_params);bd->bi_boot_params=0x40000100

R0=0,r1=machid,r2=0x40000100.由上节的此函数从UBOOT转入LINUX代继续执行,转入的首地址由vmlinux.lds.s文件可知在/arch/arm/kernel/head.s中的

__HEAD

ENTRY(stext)

定义处。从UBOOT转入LINUX执行的大致流程如下(细节不做分析,不在本节分析范畴)

ldrr13, =__mmap_switched@ address to jump to after

@ mmu has been enabled

movr3, r13

movpc, r3  //

通过上面代码转入__mmap_switched定义的址处继续执行

__mmap_switchedhead-common.S (arch\arm\kernel)中定义

__mmap_switched:下面注释是当前相关寄存器中代表的值

/*

 *  r0  = cp#15 control register

 *  r1  = machine ID

 *  r2  = atags/dtb pointer

 *  r9  = processor ID

 */

bstart_kernel //这儿函数转入C代码中执行,其中的参数值如上面注释

上面代码是UBOOT转入LINUX执行的大概流程,细节不在本节分析。下面就是正式进入LINUX代码初始化等相关流程。我们此节中只分析解析UBOOT传入参数的流程。通过分析代码解析参数的流程分两部分:

start_kernel->parse_early_param->parse_early_options->parse_one->handle_unknown(do_early_param)实现在还未解析UBOOT传入的传数前从串口输出调试信息。这个时候输出调试信息需要调用early_printkprintk函数都可以,实现原理和解析之后的输出原理本质一样的。采用了一个默认的输出配置。

boot_command_line =CONFIG_CMDLINE="console=ttySAC0,115200"采用的默认配置,在LINUX配置文件中去定义的。

parse_early_param>parse_early_options(boot_command_line)->parse_args("early options", cmdline, NULL, 0, do_early_param)->parse_one(param, val, params, num, unknown)

->handle_unknown(param, val);handle_unknown=Do_early_param

/* Check for early params. */

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

//param=console=    val=ttySAC0,115200

{

const struct obs_kernel_param *p;

 

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

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

//查询到满足条件的函数为/kernel/printk.c

//__setup("console=", console_setup);,这儿查询的原理为__setup_start__section(.init.setup)段的开始地址,对这个区域内的所有成员一一扫描,在我们的代码中未查询到p->early=1同时p->str=console=成员

 

    (strcmp(param, "console") == 0 &&

     strcmp(p->str, "earlycon") == 0)//第二个条件我们代码中了未满足,因此我们系统是不是支持在UBOOT传入参数解析前就输出调试信息的。

) {

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

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

}

}

/* We accept everything at this stage. */

return 0;

}

上面解析中用了这个boot_command_line是如何得到的,大胆猜应该是UBOOT传入的字符串变量。

setup_arch->setup_machine_tags

if (__atags_pointer)

tags = phys_to_virt(__atags_pointer);这个地址是在UBOOT转入LINUX执行时把传入的标记址存储地址传给LINUX的存储地方。__atags_pointer=0x40000100.,因此对这个地址的操作就是对UBOOT传入参数的操作。

strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);

saved_command_line=boot_command_line=static_command_line

通过上面的准备工作下面正式进入解析UBOOT传入的串口相关参数执行流程。

parse_args->parse_one->handle_unknown(param, val)=unknown_bootoption

nknown_bootoption函数把前面分解后的引导参数又重新恢复成原来的模样,因为通过上面执行流程分解成了param val两部分,这儿又重新合成为console=ttySAC0,115200n8

if (obsolete_checksetup(param))

strncmp(line, p->str, n)//查找我们已初始化的设置函数。对于串口就是__setup("console=", console_setup);

p->setup_func(line + n)=console_setupttySAC0,115200n8

通过上面分析找进入了我们本机针对UBOOT传入参数而注册同名函数执行流程。

onsole_setupttySAC0,115200n8//kernel/printk.c

__add_preferred_console(buf, idx, options, brl_options);

//buf=ttySAC0,115200n8

Idx=0

Options=115200n8

Brl_options=null;

 

selected_console=0代表确定用那个操控台来做串口的输出信息显示端口。这个很重要。后面在PRINTK打印原理中会有用到,到时具体分析。

__add_preferred_console这个函数把上面解析得到的东西赋值一个全局变量

static struct console_cmdlineconsole_cmdline[MAX_CMDLINECONSOLES];对于串口参数则这个变量得到的相关值为

struct console_cmdline

{

charname[8]=ttySAC0;/* Name of the driver    */

intindex=0;/* Minor dev. to use    */

char*options=115200n8;/* Options for the driver   */

#ifdef CONFIG_A11Y_BRAILLE_CONSOLE

char*brl_options;/* Options for braille driver */

#endif

};本节分析达到了准备材料的目的。为LINUX内核准备了UBOOT传入参数的解析和分类准备。后面就可以直接使用了。

 

兴趣交流群抠抠: 461283592

1 0
原创粉丝点击