Linux内核对bootargs的使用,uboot启动linux内核小结(boot,bootd,boom,bootcmd,bootargs)

uboot在进行系统启动和内核加载的时候被分为俩个阶段, 第一阶段主要是写汇编代码,我没有仔细研究,只是看了看移植好的针对mini2440的tekkman的uboot代码。 第二个阶段为由C写成,易于研究和学习。掌握了基本的流程。 (1)第一阶段的功能 ? 硬件设备初始化

uboot在进行系统启动和内核加载的时候被分为俩个阶段,

第一阶段主要是写汇编代码,我没有仔细研究,只是看了看移植好的针对mini2440的tekkman的uboot代码。

第二个阶段为由C写成,易于研究和学习。掌握了基本的流程。

(1)第一阶段的功能

? 硬件设备初始化

? 加载U-Boot第二阶段代码到RAM空间

? 设置好栈

? 跳转到第二阶段代码入口

(2)第二阶段的功能

? 初始化本阶段使用的硬件设备

? 检测系统内存映射

? 将内核从Flash读取到RAM中

? 为内核设置启动参数

? 调用内核

第二阶段的C出口函数为:

由于在cpu/arm920t/start.S的最后阶段有如下代码:

ldr pc, _start_armboot

_start_armboot: .word start_armboot 此时pc指针将会跳转到lib_arm/board.c中定义的函数start_armboot().因此start_armboot().函数是c代码的入口代码,分析就从这里起航。

而在函数start_armboot()中有个死循环,

/* main_loop() can return to retry autoboot, if so just run it again. */

for (;;)

{

main_loop ();接受用户在uboot命令行输入的命令。

}

在uboot启动的时候,如果在#define CONFIG_BOOTDELAY 1超时之前用户没有输入,uboot就会自动加载linux内核,

其加载时将使用变量“bootcmd”和 “bootargs”在uboot代码所定义的变量值进行启动代码。

变量“bootcmd”和 “bootargs”的值可以在在加载linux内核前,uboot的命令行中进行修改。

我这俩个参数的值如下:

bootcmd=nfs 0x30008000 192.168.1.149:/opt/FriendlyARM/uImage;bootm ------ 需要注意的是再bootcmd变量的最后添加了bootm命令。

bootargs=noinitrd root=/dev/nfs proto=tcp,nolock,nfsvers=3, rw nfsroot=192.168.1.149:/mini2440/rootfs ip=192.168.1.144:192.168.1.149::255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=64M

首先看看启动内核是俩种比较简单明白的方式,boot,bootd命令的实现。

现实代码如下:

/*******************************************************************/

/* bootd - boot default image */

/*******************************************************************/

#if defined(CONFIG_CMD_BOOTD)

int do_bootd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])

{

int rcode = 0;

#ifndef CONFIG_SYS_HUSH_PARSER

if (run_command (getenv ("bootcmd"), flag) < 0)

rcode = 1;

#else

if (parse_string_outer (getenv ("bootcmd"),

FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0)

rcode = 1;

#endif

return rcode;

}

U_BOOT_CMD(

boot, 1, 1, do_bootd,

"boot default, i.e., run 'bootcmd'",

""

);

/* keep old command name "bootd" for backward compatibility */

U_BOOT_CMD(

bootd, 1, 1, do_bootd,

"boot default, i.e., run 'bootcmd'",

""

);

#endif

从上面的对命令boot,bootd命令实现可以知道,其命令的最终执行的是“bootcmd”命令行参数所定义的值

即"nfs 0x30008000 192.168.1.149:/opt/FriendlyARM/uImage;bootm ":

在上面的函数main_loop ()中又如下代码片段

s = getenv ("bootcmd");

debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "");

if (bootdelay >= 0 && s && !abortboot (bootdelay))

{

# ifdef CONFIG_AUTOBOOT_KEYED

int prev = disable_ctrlc(1); /* disable Control C checking */

# endif

# ifndef CONFIG_SYS_HUSH_PARSER

run_command (s, 0);

# else

parse_string_outer(s, FLAG_PARSE_SEMICOLON |

FLAG_EXIT_FROM_LOOP);

# endif

# ifdef CONFIG_AUTOBOOT_KEYED

disable_ctrlc(prev); /* restore Control C checking */

# endif

}

# ifdef CONFIG_MENUKEY

if (menukey == CONFIG_MENUKEY) {

s = getenv("menucmd");

if (s) {

# ifndef CONFIG_SYS_HUSH_PARSER

run_command (s, 0);

# else

parse_string_outer(s, FLAG_PARSE_SEMICOLON |

FLAG_EXIT_FROM_LOOP);

# endif

}

}

#endif /* CONFIG_MENUKEY */

#endif /* CONFIG_BOOTDELAY */

上的代码中在函数abortboot (bootdelay))

执行的过程中已经超时,则自动的执行"bootcmd" 所定义的命令。

现在看看命令"bootm"命令式如何实现的?

"boot application image from memory",这句话很重要,表明bootm执行是必须确保uImage已经在内从中,

在"bootm addr"中当addr省略的时候bootm加载宏#define CONFIG_SYS_LOAD_ADDR  0x30008000 /* default load address */定义处的内核image。

"bootm"命令的实现函数为do_bootm(),在do_bootm()中完成对linux内核的加载启动。

其加载函数为:do_bootm_linux()函数中获取了"bootargs"环境变量的值。最终将此值传递给linux内核,用来加载文件系统时候使用。

对do_bootm()和do_bootm_linux()函数的分析可以找到看其他朋友的分析。

总结

在uboot中每一个命令都对应一个其实现的函数,在启动linux内核过程中,主要是执行环境变量bootcmd和bootargs所定义的命令。因此,对这俩个变量的定义很重要,如果定义不对就不能正确的加载内核和文件系统。尤其是必须确保文件系统所在分区。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值