UBOOT之main.c分析

来源:互联网 发布:java中九九乘法表 编辑:程序博客网 时间:2024/05/21 04:38
main.c这个文件在common/main.c中定义

/*******设置环境变量ver**************/
#ifdef CONFIG_VERSION_VARIABLE
{
extern char version_string[ ];

setenv ("ver", version_string);      //设置环境变量ver的值
}
#endif 

version_string在lib_arm/board.c中定义:
const char version_string[ ] =
U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")"CONFIG_IDENT_STRING;
数组中的那些都是一些已经定义好的宏

/****************初始化uboot_hush******************************/

u_boot_hush_start ();
#if defined(CONFIG_HUSH_INIT_VAR)
hush_init_var ();                                        //初始化hush
#endif

u_boot_hush_start 函数在common/hush.c中定义:
int u_boot_hush_start(void)                        //这个函数其实就是进行一系列的赋值操作
{
if (top_vars == NULL) {
top_vars = malloc(sizeof(struct variables));
top_vars->name = "HUSH_VERSION";
top_vars->value = "0.01";
top_vars->next = 0;
top_vars->flg_export = 0;
top_vars->flg_read_only = 1;
#ifndef CONFIG_RELOC_FIXUP_WORKS        
u_boot_hush_reloc();                    //定义上面那个宏,这个函数不执行
#endif
}
return 0;
}


/*********************命令安装自动补全功能*******************************************************/

#ifdef CONFIG_AUTO_COMPLETE
install_auto_complete();
#endif

install_auto_complete这个函数在common/command.c中定义:
void install_auto_complete(void)
{
install_auto_complete_handler("printenv", var_complete);    //安装自动补全功能,var_complete就是实现自动补全功能的函数
install_auto_complete_handler("setenv", var_complete);        
#if defined(CONFIG_CMD_RUN)
install_auto_complete_handler("run", var_complete);
#endif
}
install_auto_complete_handler这个函数在common/command.c中定义:
static void install_auto_complete_handler(const char *cmd,
int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]))
{
cmd_tbl_t *cmdtp;

cmdtp = find_cmd(cmd);            //查找要安装自动补全功能的命令
if (cmdtp == NULL)
return;

cmdtp->complete = complete;        //将自动补全功能的函数赋值给这个命令结构体中的complete成员
}

/******************设置bootdelay 的值********************/
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
s = getenv ("bootdelay");            //获取环境变量bootdelay的值
bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;  //如果获取到的bootdelay值不为0,则将这个字符串
                                                                                                                                     //转换成long型,否则使用CONFIG_BOOTDELAY
s = getenv ("bootcmd");                    //获得环境变量bootcmd的值,也就是获取启动命令

if (bootdelay >= 0 && s && !abortboot (bootdelay)) {     //倒计时,如果倒计时内没有按下任何键,则执行if中的内容,启动内核

                # ifndef CONFIG_SYS_HUSH_PARSER
        run_command (s, 0);                //运行启动内核的命令
                # else
        parse_string_outer(s, FLAG_PARSE_SEMICOLON  |  FLAG_EXIT_FROM_LOOP);  //运行启动内核的命令
                # endif
}

abortboot 在common/main.c中定义:
static __inline__ int abortboot(int bootdelay)
{
int abort = 0;

#ifdef CONFIG_MENUPROMPT                        //此宏没有被定义
printf(CONFIG_MENUPROMPT);
#else
printf("Hit any key to stop autoboot: %2d ", bootdelay);    //打印出倒计时的信息
#endif

#if defined CONFIG_ZERO_BOOTDELAY_CHECK
if (bootdelay >= 0) {                                        //
if (tstc()) {/* we got a key press */      //tstc主要用于检查是否有输入
(void) getc();  /* consume input*/     //如果有输入则用getc消耗这个输入
puts ("\b\b\b 0");                                   //当有一个输入后,倒计时的数立刻变为0
abort = 1;/* don't auto boot */    //将abort置1,这样函数返回后,就不会执行if中的语句,也就不会自动启动内核
}
}
#endif

while ((bootdelay > 0) && (!abort)) {            //这里开始真正的倒计时,只要bootdelay大于0,且abort没有被置1,那么就会
int i;                                                         //循环倒计时           

--bootdelay;                                        //每当进来一次,bootdelay的值减1
/* delay 100 * 10ms */
for (i=0; !abort && i<100; ++i) {                //循环检测是否有输入
if (tstc()) {/* we got a key press */      //tstc主要用于检查是否有输入
abort  = 1;/* don't auto boot */        //如果有输入,则将abort置1
bootdelay = 0;/* no more delay*/   //并且将bootdelay的值赋值为0

(void) getc();  /* consume input*/        //消耗这个输入
# endif
break;                                                        //跳出循环
}
udelay(10000);                    //延时
}

printf("\b\b\b%2d ", bootdelay);            //打印倒计时的值
}

putc('\n');    //打印一个换行符

return abort;
}

run_command 函数在common/main.c中定义:
int run_command (const char *cmd, int flag)
{
cmd_tbl_t *cmdtp;
char cmdbuf[CONFIG_SYS_CBSIZE];/* working copy of cmd */
char *token;/* start of token in cmdbuf */
char *sep;/* end of token (separator) in cmdbuf */
char finaltoken[CONFIG_SYS_CBSIZE];
char *str = cmdbuf;
char *argv[CONFIG_SYS_MAXARGS + 1];/* NULL terminated */
int argc, inquotes;
int repeatable = 1;
int rc = 0;

clear_ctrlc();/* forget any previous Control C */        //清除ctrl+c

if (!cmd || !*cmd) {                            //如果命令为空,则返回
return -1;/* empty command */
}

if (strlen(cmd) >= CONFIG_SYS_CBSIZE) {        //如果命令的长度大于规定的最大长度,返回
puts ("## Command too long!\n");
return -1;
}

strcpy (cmdbuf, cmd);                    //将命令复制到cmdbuf中

/* 分隔命令循环:根据’;’ 将命令序列分隔成多条命令,结果放入token */
while (*str) {

/*
 * Find separator, or string end
 * Allow simple escape of ';' by writing "\;"
 */
for (inquotes = 0, sep = str; *sep; sep++) {
if ((*sep=='\'') &&
    (*(sep-1) != '\\'))
inquotes=!inquotes;

if (!inquotes &&
    (*sep == ';') &&/* separator */
    ( sep != str) &&/* past string start */
    (*(sep-1) != '\\'))/* and NOT escaped */
break;
}

/*
 * Limit the token to data between separators
 */
token = str;
if (*sep) {
str = sep + 1;/* start of command for next pass */
*sep = '\0';
}
else
str = sep;/* no more commands for next pass */

#ifdef DEBUG_PARSER
printf ("token: \"%s\"\n", token);
#endif

/* find macros in this token and replace them */
process_macros (token, finaltoken);            //处理命令中的宏替换

/* Extract arguments */
if ((argc = parse_line (finaltoken, argv)) == 0) {    //解析命令参数
rc = -1; /* no command at all */
continue;
}

/* Look up command in command table */
if ((cmdtp = find_cmd(argv[0])) == NULL) {        //在命令表中寻找命令
printf ("Unknown command '%s' - try 'help'\n", argv[0]);    //找不到就打印这句话
rc = -1; /* give up after bad command */
continue;                                                //返回继续分割命令
}

/* found - check max args */
if (argc > cmdtp->maxargs) {    //判断命令最大参数个数
cmd_usage(cmdtp);        //如果超出命令最大参数个数,打印用法信息
rc = -1;
continue;                      //返回继续分割命令
}

/* bootd命令处理*/
#if defined(CONFIG_CMD_BOOTD)
/* avoid "bootd" recursion */
if (cmdtp->cmd == do_bootd) {
#ifdef DEBUG_PARSER
printf ("[%s]\n", finaltoken);
#endif
if (flag & CMD_FLAG_BOOTD) {
puts ("'bootd' recursion detected\n");
rc = -1;
continue;
} else {
flag |= CMD_FLAG_BOOTD;
}
}
#endif

/* OK - call function to do the command */
if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) {    //执行命令的处理函数
rc = -1;
}

repeatable &= cmdtp->repeatable;        //设置可重复执行标记

/* Did the user stop this? */
if (had_ctrlc ())                        //判断用户是否终止,ctrl+c
return -1;/* if stopped then not repeatable */
}

return rc ? rc : repeatable;
}


/****************进入交互模式************************/

#ifdef CONFIG_SYS_HUSH_PARSER
parse_file_outer();
/* This point is never reached */
for (;;);
#else
for (;;) {
#ifdef CONFIG_BOOT_RETRY_TIME
if (rc >= 0) {
/* Saw enough of a valid command to
 * restart the timeout.
 */
reset_cmd_timeout();
}
#endif
len = readline (CONFIG_SYS_PROMPT);

flag = 0;/* assume no special flags for now */
if (len > 0)
strcpy (lastcommand, console_buffer);
else if (len == 0)
flag |= CMD_FLAG_REPEAT;
#ifdef CONFIG_BOOT_RETRY_TIME
else if (len == -2) {
/* -2 means timed out, retry autoboot
 */
puts ("\nTimed out waiting for command\n");
# ifdef CONFIG_RESET_TO_RETRY
/* Reinit board to run initialization code again */
do_reset (NULL, 0, 0, NULL);
# else
return; /* retry autoboot */
# endif
}
#endif

if (len == -1)
puts ("<INTERRUPT>\n");
else
rc = run_command (lastcommand, flag);

if (rc <= 0) {
/* invalid command or not repeatable, forget it */
lastcommand[0] = 0;
}
}
#endif /*CONFIG_SYS_HUSH_PARSER*/





































0 0