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



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

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执行的大致流程如下(细节不做分析,不在本节分析范畴)

ldr r13, =__mmap_switched @ address to jump to after

@ mmu has been enabled

mov r3, r13

mov pc, 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

 */

b start_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_cmdline console_cmdline[MAX_CMDLINECONSOLES];对于串口参数则这个变量得到的相关值为

struct console_cmdline

{

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

int index=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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值