UBOOT之main.c分析
main.c这个⽂件在common/main.c中定义
兄弟七八个/*******设置环境变量ver**************/
#ifdef CONFIG_VERSION_VARIABLE
{
extern char version_string[ ];
tenv ("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("tenv", 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); //运⾏启动内核的命令
# el
par_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);
#el
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 */
qwordfor (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 *p; /* end of token (parator) 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 parator, or string end
* Allow simple escape of ';' by writing "\;"
*/
for (inquotes = 0, p = str; *p; p++) {
if ((*p=='\'') &&
(*(p-1) != '\\'))
inquotes=!inquotes;
if (!inquotes &&
(*p == ';') && /* parator */
桃运青年
( p != str) && /* past string start */
(*(p-1) != '\\')) /* and NOT escaped */
break;
}
/*
* Limit the token to data between parators
*/
token = str;
if (*p) {
str = p + 1; /* start of command for next pass */
*p = '\0';
}
el
str = p; /* 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 */
qq登陆记录if ((argc = par_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;
} el {
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 ur stop this? */
if (had_ctrlc ()) //判断⽤户是否终⽌,ctrl+c
return -1; /* if stopped then not repeatable */
}
return rc ? rc : repeatable;
}
/****************进⼊交互模式************************/
奇葩说选手#ifdef CONFIG_SYS_HUSH_PARSER
par_file_outer();
/* This point is never reached */
for (;;);
#el
for (;;) {
#ifdef CONFIG_BOOT_RETRY_TIME
if (rc >= 0) {
/* Saw enough of a valid command to
* restart the timeout.
*/
ret_cmd_timeout();
}
#endif
len = readline (CONFIG_SYS_PROMPT);
flag = 0; /* assume no special flags for now */
if (len > 0)
strcpy (lastcommand, console_buffer);
el if (len == 0)
flag |= CMD_FLAG_REPEAT;
#ifdef CONFIG_BOOT_RETRY_TIME
el 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_ret (NULL, 0, 0, NULL);
# el
return; /* retry autoboot */
# endif