Chinaunix首页 | 论坛 | 博客
  • 博客访问: 860469
  • 博文数量: 321
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 936
  • 用 户 组: 普通用户
  • 注册时间: 2013-02-23 11:25
文章分类

全部博文(321)

文章存档

2017年(1)

2016年(10)

2015年(61)

2014年(187)

2013年(62)

分类: 嵌入式

2013-03-28 23:17:42

/*
 * (C) Copyright 2000
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * Add to readline cmdline-editing by
 * (C) Copyright 2005
 * JinHua Luo, GuangDong Linux Center,
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */


/* #define DEBUG */


#include
#include
#include
#ifdef CONFIG_MODEM_SUPPORT
#include /* for free() prototype */
#endif


#ifdef CONFIG_SYS_HUSH_PARSER
#include
#endif


#include


#if defined(CONFIG_SILENT_CONSOLE) || defined(CONFIG_POST) || defined(CONFIG_CMDLINE_EDITING)
DECLARE_GLOBAL_DATA_PTR;
#endif


/*
 * Board-specific Platform code can reimplement show_boot_progress () if needed
 */
void inline __show_boot_progress (int val) {}
void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress")));


#if defined(CONFIG_BOOT_RETRY_TIME) && defined(CONFIG_RESET_TO_RETRY)
extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); /* for do_reset() prototype */
#endif


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


#if defined(CONFIG_UPDATE_TFTP)
void update_tftp (void);
#endif /* CONFIG_UPDATE_TFTP */


#define MAX_DELAY_STOP_STR 32


#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
static int abortboot(int);
#endif


#undef DEBUG_PARSER


char        console_buffer[CONFIG_SYS_CBSIZE]; /* console I/O buffer */


static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen);
static char erase_seq[] = "\b \b"; /* erase sequence */
static char   tab_seq[] = "        "; /* used to expand TABs */


#ifdef CONFIG_BOOT_RETRY_TIME
static uint64_t endtime = 0;  /* must be set, default is instant timeout */
static int      retry_time = -1; /* -1 so can call readline before main_loop */
#endif


#define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk())


#ifndef CONFIG_BOOT_RETRY_MIN
#define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME
#endif


#ifdef CONFIG_MODEM_SUPPORT
int do_mdm_init = 0;
extern void mdm_init(void); /* defined in board.c */
#endif


/***************************************************************************
 * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
 * returns: 0 -  no key string, allow autoboot
 *          1 - got key string, abort
 */
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
# if defined(CONFIG_AUTOBOOT_KEYED)  //未定义
static __inline__ int abortboot(int bootdelay)
{
int abort = 0;
uint64_t etime = endtick(bootdelay);
struct {
char* str;
u_int len;
int retry;
}
delaykey [] = {
{ str: getenv ("bootdelaykey"),  retry: 1 },
{ str: getenv ("bootdelaykey2"), retry: 1 },
{ str: getenv ("bootstopkey"),   retry: 0 },
{ str: getenv ("bootstopkey2"),  retry: 0 },
};


char presskey [MAX_DELAY_STOP_STR];
u_int presskey_len = 0;
u_int presskey_max = 0;
u_int i;


#  ifdef CONFIG_AUTOBOOT_PROMPT
printf(CONFIG_AUTOBOOT_PROMPT);
#  endif


#  ifdef CONFIG_AUTOBOOT_DELAY_STR
if (delaykey[0].str == NULL)
delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
#  endif
#  ifdef CONFIG_AUTOBOOT_DELAY_STR2
if (delaykey[1].str == NULL)
delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2;
#  endif
#  ifdef CONFIG_AUTOBOOT_STOP_STR
if (delaykey[2].str == NULL)
delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR;
#  endif
#  ifdef CONFIG_AUTOBOOT_STOP_STR2
if (delaykey[3].str == NULL)
delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2;
#  endif


for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {
delaykey[i].len = delaykey[i].str == NULL ?
   0 : strlen (delaykey[i].str);
delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ?
   MAX_DELAY_STOP_STR : delaykey[i].len;


presskey_max = presskey_max > delaykey[i].len ?
   presskey_max : delaykey[i].len;


#  if DEBUG_BOOTKEYS
printf("%s key:<%s>\n",
      delaykey[i].retry ? "delay" : "stop",
      delaykey[i].str ? delaykey[i].str : "NULL");
#  endif
}


/* In order to keep up with incoming data, check timeout only
* when catch up.
*/
do {
if (tstc()) {
if (presskey_len < presskey_max) {
presskey [presskey_len ++] = getc();
}
else {
for (i = 0; i < presskey_max - 1; i ++)
presskey [i] = presskey [i + 1];


presskey [i] = getc();
}
}


for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {
if (delaykey[i].len > 0 &&
   presskey_len >= delaykey[i].len &&
   memcmp (presskey + presskey_len - delaykey[i].len,
   delaykey[i].str,
   delaykey[i].len) == 0) {
#  if DEBUG_BOOTKEYS
printf("got %skey\n",
      delaykey[i].retry ? "delay" : "stop");
#  endif


#  ifdef CONFIG_BOOT_RETRY_TIME
/* don't retry auto boot */
if (! delaykey[i].retry)
retry_time = -1;
#  endif
abort = 1;
}
}
} while (!abort && get_ticks() <= etime);


#  if DEBUG_BOOTKEYS
if (!abort)
puts("key timeout\n");
#  endif


#ifdef CONFIG_SILENT_CONSOLE
if (abort)
gd->flags &= ~GD_FLG_SILENT;
#endif


return abort;
}


# else /* !defined(CONFIG_AUTOBOOT_KEYED) */


#ifdef CONFIG_MENUKEY
static int menukey = 0;
#endif


//判断在指定的时间内用户是否终止引导
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 //未定义   检查是否有按键按下
/*
* Check if key already pressed
* Don't check if bootdelay < 0
*/
if (bootdelay >= 0) {
if (tstc()) { /* we got a key press */
(void) getc();  /* consume input */
puts ("\b\b\b 0");
abort = 1; /* don't auto boot */
}
}
#endif
    //检查是否有按键按下的循环
while ((bootdelay > 0) && (!abort)) {  //如果延时未到且未选择终止
int i;


--bootdelay;
/* delay 100 * 10ms */
for (i=0; !abort && i<100; ++i) {
if (tstc()) { /* we got a key press *///有按键按下
abort  = 1; /* don't auto boot */ //引导终止
bootdelay = 0; /* no more delay *///延时计数清零
# ifdef CONFIG_MENUKEY
menukey = getc();
# else
(void) getc();  /* consume input */ //清空输入缓冲
# endif
break;
}
udelay(10000);
}


printf ("\b\b\b%2d ", bootdelay);//打印剩余时间
}


putc('\n');


#ifdef CONFIG_SILENT_CONSOLE//未定义 
if (abort)
gd->flags &= ~GD_FLG_SILENT;
#endif


return abort;
}
# endif /* CONFIG_AUTOBOOT_KEYED */
#endif /* CONFIG_BOOTDELAY >= 0  */


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


void main_loop (void)
{
                    //L306--L468的编译开关基本上没定义
#ifndef CONFIG_SYS_HUSH_PARSER//定义一些变量
static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
int len;
int rc = 1;
int flag;
#endif


#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)    //有定义;自启动的秒数
char *s;
int bootdelay;
#endif
#ifdef CONFIG_PREBOOT  //没定义
char *p;
#endif
#ifdef CONFIG_BOOTCOUNT_LIMIT   //没定义
unsigned long bootcount = 0;
unsigned long bootlimit = 0;
char *bcs;
char bcs_set[16];
#endif /* CONFIG_BOOTCOUNT_LIMIT */


#if defined(CONFIG_VFD) && defined(VFD_TEST_LOGO)  //没定义
ulong bmp = 0; /* default bitmap */
extern int trab_vfd (ulong bitmap);


#ifdef CONFIG_MODEM_SUPPORT   //没定义
if (do_mdm_init)
bmp = 1; /* alternate bitmap */
#endif
trab_vfd (bmp);
#endif /* CONFIG_VFD && VFD_TEST_LOGO */


#ifdef CONFIG_BOOTCOUNT_LIMIT    //没定义
bootcount = bootcount_load();
bootcount++;
bootcount_store (bootcount);
sprintf (bcs_set, "%lu", bootcount);
setenv ("bootcount", bcs_set);
bcs = getenv ("bootlimit");
bootlimit = bcs ? simple_strtoul (bcs, NULL, 10) : 0;
#endif /* CONFIG_BOOTCOUNT_LIMIT */


#ifdef CONFIG_MODEM_SUPPORT    //没定义
debug ("DEBUG: main_loop:   do_mdm_init=%d\n", do_mdm_init);
if (do_mdm_init) {
char *str = strdup(getenv("mdm_cmd"));
setenv ("preboot", str);  /* set or delete definition */
if (str != NULL)
free (str);
mdm_init(); /* wait for modem connection */
}
#endif  /* CONFIG_MODEM_SUPPORT */


#ifdef CONFIG_VERSION_VARIABLE    //没定义
{
extern char version_string[];


setenv ("ver", version_string);  /* set version variable */
}
#endif /* CONFIG_VERSION_VARIABLE */


#ifdef CFG_HUSH_PARSER  //没定义
u_boot_hush_start ();
#endif


#if defined(CONFIG_HUSH_INIT_VAR)
hush_init_var ();
#endif


#ifdef CONFIG_AUTO_COMPLETE   //没定义
install_auto_complete();
#endif


#ifdef CONFIG_PREBOOT   //没定义
if ((p = getenv ("preboot")) != NULL) {
# ifdef CONFIG_AUTOBOOT_KEYED
int prev = disable_ctrlc(1); /* disable Control C checking */
# endif


# ifndef CONFIG_SYS_HUSH_PARSER
run_command (p, 0);
# else
parse_string_outer(p, FLAG_PARSE_SEMICOLON |
   FLAG_EXIT_FROM_LOOP);
# endif


# ifdef CONFIG_AUTOBOOT_KEYED
disable_ctrlc(prev); /* restore Control C checking */
# endif
}
#endif /* CONFIG_PREBOOT */


#if defined(CONFIG_UPDATE_TFTP)
update_tftp ();
#endif /* CONFIG_UPDATE_TFTP */


//获得就是Uboot启动后多久进入内核。
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)   //获得延时时长 
s = getenv ("bootdelay");
bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;


debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);


# ifdef CONFIG_BOOT_RETRY_TIME  //没定义
init_cmd_timeout ();
# endif /* CONFIG_BOOT_RETRY_TIME */


#ifdef CONFIG_POST
if (gd->flags & GD_FLG_POSTFAIL) {
s = getenv("failbootcmd");
}
else
#endif /* CONFIG_POST */
#ifdef CONFIG_BOOTCOUNT_LIMIT   //没定义
if (bootlimit && (bootcount > bootlimit)) {
printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
       (unsigned)bootlimit);
s = getenv ("altbootcmd");
}
else
#endif /* CONFIG_BOOTCOUNT_LIMIT */
s = getenv ("bootcmd");          // 1、读预先设置的环境变量命令


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


if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
//abortboot()有键按下返回1,不执行,无键按下执行启动内核
               //若延时期间用户没终止程序,即上面粗体字函数abortboot (bootdelay) 
               // 返回0,
                //则不会进入命令行模式,直接运行bootcmd
# ifdef CONFIG_AUTOBOOT_KEYED    //没定义
int prev = disable_ctrlc(1); /* disable Control C checking */
# endif


# ifndef CFG_HUSH_PARSER      //没定义,执行
run_command (s, 0);     //   2、没有键按下,执行预先设置的命令
//s = getenv ("bootcmd");          // 1、读预先设置的环境变量命令
# 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
}


//for 语句的结束


//有键按下到控制台




# 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 */


#ifdef CONFIG_AMIGAONEG3SE    //没定义
{
   extern void video_banner(void);
   video_banner();
}
#endif


/*
* Main Loop for Monitor Command Processing
*/
#ifdef CFG_HUSH_PARSER         //  没定义
parse_file_outer();
/* This point is never reached */
for (;;);
#else
for (;;) {                       //      3、死循环,等待用户输入
#ifdef CONFIG_BOOT_RETRY_TIME        //  有定义,执行
if (rc >= 0) {
/* Saw enough of a valid command to
* restart the timeout.
*/
reset_cmd_timeout();//设置一个时间,多久没键按下将重启我们系统
}
#endif
                                        //   4、打印提示符GEC2440#:  并且打印输入的命令。LEN>0,正常输入
len = readline (CONFIG_SYS_PROMPT);//读键盘的输入


flag = 0; /* assume no special flags for now */
if (len > 0)                                //    5、有字串输入
strcpy (lastcommand, console_buffer);   //  6 、把命令拷贝进来
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 ("\n");
else
rc = run_command (lastcommand, flag);        //   7、这里执行命令


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


#ifdef CONFIG_BOOT_RETRY_TIME
/***************************************************************************
 * initialize command line timeout
 */
void init_cmd_timeout(void)
{
char *s = getenv ("bootretry");


if (s != NULL)
retry_time = (int)simple_strtol(s, NULL, 10);
else
retry_time =  CONFIG_BOOT_RETRY_TIME;


if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN)
retry_time = CONFIG_BOOT_RETRY_MIN;
}


/***************************************************************************
 * reset command line timeout to retry_time seconds
 */
void reset_cmd_timeout(void)
{
endtime = endtick(retry_time);
}
#endif


#ifdef CONFIG_CMDLINE_EDITING


/*
 * cmdline-editing related codes from vivi.
 * Author: Janghoon Lyu
 */


#define putnstr(str,n) do { \
printf ("%.*s", (int)n, str); \
} while (0)


#define CTL_CH(c) ((c) - 'a' + 1)


#define MAX_CMDBUF_SIZE 256


#define CTL_BACKSPACE ('\b')
#define DEL ((char)255)
#define DEL7 ((char)127)
#define CREAD_HIST_CHAR ('!')


#define getcmd_putch(ch) putc(ch)
#define getcmd_getch() getc()
#define getcmd_cbeep() getcmd_putch('\a')


#define HIST_MAX 20
#define HIST_SIZE MAX_CMDBUF_SIZE


static int hist_max = 0;
static int hist_add_idx = 0;
static int hist_cur = -1;
unsigned hist_num = 0;


char* hist_list[HIST_MAX];
char hist_lines[HIST_MAX][HIST_SIZE];


#define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1)


static void hist_init(void)
{
int i;


hist_max = 0;
hist_add_idx = 0;
hist_cur = -1;
hist_num = 0;


for (i = 0; i < HIST_MAX; i++) {
hist_list[i] = hist_lines[i];
hist_list[i][0] = '\0';
}
}


static void cread_add_to_hist(char *line)
{
strcpy(hist_list[hist_add_idx], line);


if (++hist_add_idx >= HIST_MAX)
hist_add_idx = 0;


if (hist_add_idx > hist_max)
hist_max = hist_add_idx;


hist_num++;
}


static char* hist_prev(void)
{
char *ret;
int old_cur;


if (hist_cur < 0)
return NULL;


old_cur = hist_cur;
if (--hist_cur < 0)
hist_cur = hist_max;


if (hist_cur == hist_add_idx) {
hist_cur = old_cur;
ret = NULL;
} else
ret = hist_list[hist_cur];


return (ret);
}


static char* hist_next(void)
{
char *ret;


if (hist_cur < 0)
return NULL;


if (hist_cur == hist_add_idx)
return NULL;


if (++hist_cur > hist_max)
hist_cur = 0;


if (hist_cur == hist_add_idx) {
ret = "";
} else
ret = hist_list[hist_cur];


return (ret);
}


#ifndef CONFIG_CMDLINE_EDITING
static void cread_print_hist_list(void)
{
int i;
unsigned long n;


n = hist_num - hist_max;


i = hist_add_idx + 1;
while (1) {
if (i > hist_max)
i = 0;
if (i == hist_add_idx)
break;
printf("%s\n", hist_list[i]);
n++;
i++;
}
}
#endif /* CONFIG_CMDLINE_EDITING */


#define BEGINNING_OF_LINE() { \
while (num) { \
getcmd_putch(CTL_BACKSPACE); \
num--; \
} \
}


#define ERASE_TO_EOL() { \
if (num < eol_num) { \
int tmp; \
for (tmp = num; tmp < eol_num; tmp++) \
getcmd_putch(' '); \
while (tmp-- > num) \
getcmd_putch(CTL_BACKSPACE); \
eol_num = num; \
} \
}


#define REFRESH_TO_EOL() { \
if (num < eol_num) { \
wlen = eol_num - num; \
putnstr(buf + num, wlen); \
num = eol_num; \
} \
}


static void cread_add_char(char ichar, int insert, unsigned long *num,
      unsigned long *eol_num, char *buf, unsigned long len)
{
unsigned long wlen;


/* room ??? */
if (insert || *num == *eol_num) {
if (*eol_num > len - 1) {
getcmd_cbeep();
return;
}
(*eol_num)++;
}


if (insert) {
wlen = *eol_num - *num;
if (wlen > 1) {
memmove(&buf[*num+1], &buf[*num], wlen-1);
}


buf[*num] = ichar;
putnstr(buf + *num, wlen);
(*num)++;
while (--wlen) {
getcmd_putch(CTL_BACKSPACE);
}
} else {
/* echo the character */
wlen = 1;
buf[*num] = ichar;
putnstr(buf + *num, wlen);
(*num)++;
}
}


static void cread_add_str(char *str, int strsize, int insert, unsigned long *num,
     unsigned long *eol_num, char *buf, unsigned long len)
{
while (strsize--) {
cread_add_char(*str, insert, num, eol_num, buf, len);
str++;
}
}


static int cread_line(const char *const prompt, char *buf, unsigned int *len)
{
unsigned long num = 0;
unsigned long eol_num = 0;
unsigned long wlen;
char ichar;
int insert = 1;
int esc_len = 0;
char esc_save[8];
int init_len = strlen(buf);


if (init_len)
cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len);


while (1) {
#ifdef CONFIG_BOOT_RETRY_TIME
while (!tstc()) { /* while no incoming data */
if (retry_time >= 0 && get_ticks() > endtime)
return (-2); /* timed out */
}
#endif


ichar = getcmd_getch();


if ((ichar == '\n') || (ichar == '\r')) {
putc('\n');
break;
}


/*
* handle standard linux xterm esc sequences for arrow key, etc.
*/
if (esc_len != 0) {
if (esc_len == 1) {
if (ichar == '[') {
esc_save[esc_len] = ichar;
esc_len = 2;
} else {
cread_add_str(esc_save, esc_len, insert,
     &num, &eol_num, buf, *len);
esc_len = 0;
}
continue;
}


switch (ichar) {


case 'D': /* <- key */
ichar = CTL_CH('b');
esc_len = 0;
break;
case 'C': /* -> key */
ichar = CTL_CH('f');
esc_len = 0;
break; /* pass off to ^F handler */
case 'H': /* Home key */
ichar = CTL_CH('a');
esc_len = 0;
break; /* pass off to ^A handler */
case 'A': /* up arrow */
ichar = CTL_CH('p');
esc_len = 0;
break; /* pass off to ^P handler */
case 'B': /* down arrow */
ichar = CTL_CH('n');
esc_len = 0;
break; /* pass off to ^N handler */
default:
esc_save[esc_len++] = ichar;
cread_add_str(esc_save, esc_len, insert,
     &num, &eol_num, buf, *len);
esc_len = 0;
continue;
}
}


switch (ichar) {
case 0x1b:
if (esc_len == 0) {
esc_save[esc_len] = ichar;
esc_len = 1;
} else {
puts("impossible condition #876\n");
esc_len = 0;
}
break;


case CTL_CH('a'):
BEGINNING_OF_LINE();
break;
case CTL_CH('c'): /* ^C - break */
*buf = '\0'; /* discard input */
return (-1);
case CTL_CH('f'):
if (num < eol_num) {
getcmd_putch(buf[num]);
num++;
}
break;
case CTL_CH('b'):
if (num) {
getcmd_putch(CTL_BACKSPACE);
num--;
}
break;
case CTL_CH('d'):
if (num < eol_num) {
wlen = eol_num - num - 1;
if (wlen) {
memmove(&buf[num], &buf[num+1], wlen);
putnstr(buf + num, wlen);
}


getcmd_putch(' ');
do {
getcmd_putch(CTL_BACKSPACE);
} while (wlen--);
eol_num--;
}
break;
case CTL_CH('k'):
ERASE_TO_EOL();
break;
case CTL_CH('e'):
REFRESH_TO_EOL();
break;
case CTL_CH('o'):
insert = !insert;
break;
case CTL_CH('x'):
case CTL_CH('u'):
BEGINNING_OF_LINE();
ERASE_TO_EOL();
break;
case DEL:
case DEL7:
case 8:
if (num) {
wlen = eol_num - num;
num--;
memmove(&buf[num], &buf[num+1], wlen);
getcmd_putch(CTL_BACKSPACE);
putnstr(buf + num, wlen);
getcmd_putch(' ');
do {
getcmd_putch(CTL_BACKSPACE);
} while (wlen--);
eol_num--;
}
break;
case CTL_CH('p'):
case CTL_CH('n'):
{
char * hline;


esc_len = 0;


if (ichar == CTL_CH('p'))
hline = hist_prev();
else
hline = hist_next();


if (!hline) {
getcmd_cbeep();
continue;
}


/* nuke the current line */
/* first, go home */
BEGINNING_OF_LINE();


/* erase to end of line */
ERASE_TO_EOL();


/* copy new line into place and display */
strcpy(buf, hline);
eol_num = strlen(buf);
REFRESH_TO_EOL();
continue;
}
#ifdef CONFIG_AUTO_COMPLETE
case '\t': {
int num2, col;


/* do not autocomplete when in the middle */
if (num < eol_num) {
getcmd_cbeep();
break;
}


buf[num] = '\0';
col = strlen(prompt) + eol_num;
num2 = num;
if (cmd_auto_complete(prompt, buf, &num2, &col)) {
col = num2 - num;
num += col;
eol_num += col;
}
break;
}
#endif
default:
cread_add_char(ichar, insert, &num, &eol_num, buf, *len);
break;
}
}
*len = eol_num;
buf[eol_num] = '\0'; /* lose the newline */


if (buf[0] && buf[0] != CREAD_HIST_CHAR)
cread_add_to_hist(buf);
hist_cur = hist_add_idx;


return 0;
}


#endif /* CONFIG_CMDLINE_EDITING */


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


/*
 * Prompt for input and read a line.
 * If  CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0,
 * time out when time goes past endtime (timebase time in ticks).
 * Return: number of read characters
 * -1 if break
 * -2 if timed out
 */
 //提示用户输入,然后一直等待用户输入,指到用户输入完成, 
//然后获取用户数据,并存入全局变量console_buffer中。
int readline (const char *const prompt)
{
/*
* If console_buffer isn't 0-length the user will be prompted to modify
* it instead of entering it from scratch as desired.
*/
console_buffer[0] = '\0';


return readline_into_buffer(prompt, console_buffer);
}




int readline_into_buffer (const char *const prompt, char * buffer)
{
char *p = buffer;
#ifdef CONFIG_CMDLINE_EDITING
unsigned int len=MAX_CMDBUF_SIZE;
int rc;
static int initted = 0;


/*
* History uses a global array which is not
* writable until after relocation to RAM.
* Revert to non-history version if still
* running from flash.
*/
if (gd->flags & GD_FLG_RELOC) {
if (!initted) {
hist_init();
initted = 1;
}


if (prompt)
puts (prompt);


rc = cread_line(prompt, p, &len);
return rc < 0 ? rc : len;


} else {
#endif /* CONFIG_CMDLINE_EDITING */
char * p_buf = p;
int n = 0; /* buffer index */
int plen = 0; /* prompt length */
int col; /* output column cnt */
char c;


/* print prompt */
if (prompt) {
plen = strlen (prompt);
puts (prompt);         // 1    打印提示符
}
col = plen;


for (;;) {             //  2    等待输入命令
#ifdef CONFIG_BOOT_RETRY_TIME      //没定义
while (!tstc()) { /* while no incoming data */
if (retry_time >= 0 && get_ticks() > endtime)
return (-2); /* timed out */
}
#endif
WATCHDOG_RESET(); /* Trigger watchdog, if needed */


#ifdef CONFIG_SHOW_ACTIVITY  //没定义
while (!tstc()) {
extern void show_activity(int arg);
show_activity(0);
}
#endif
c = getc();    // 3     接受输入的命令


/*
* Special character handling
*/
switch (c) {         //  4     键盘输入处理不同的字符
case '\r': /* Enter */
case '\n':
*p = '\0';
puts ("\r\n");
return (p - p_buf);


case '\0': /* nul 忽略,继续*/
continue;


case 0x03: /* ^C - break */
p_buf[0] = '\0'; /* discard input */
return (-1);


case 0x15: /* ^U - erase line 删除*/
while (col > plen) {
puts (erase_seq);
--col;
}
p = p_buf;
n = 0;
continue;


case 0x17: /* ^W - erase word 删除*/
p=delete_char(p_buf, p, &col, &n, plen);
while ((n > 0) && (*p != ' ')) {
p=delete_char(p_buf, p, &col, &n, plen);
}
continue;


case 0x08: /* ^H  - backspace */
case 0x7F: /* DEL - backspace 删除*/
p=delete_char(p_buf, p, &col, &n, plen);
continue;


default:
/*
* Must be a normal character then
*/
if (n < CONFIG_SYS_CBSIZE-2) {
if (c == '\t') { /* expand TABs 自动补齐 */
#ifdef CONFIG_AUTO_COMPLETE              // 没定义
/* if auto completion triggered just continue */
                   /*自动补全功能,熟悉linux的肯定知道*/


*p = '\0';
if (cmd_auto_complete(prompt, console_buffer, &n, &col)) {
p = p_buf + n; /* reset */
continue;
}
#endif
puts (tab_seq+(col&07));
col += 8 - (col&07);
} else {
++col; /* echo input */
putc (c);
}
*p++ = c;  ;/*把字符保存在buffer中*/
++n;
} else { /* Buffer full */
putc ('\a');//表示蜂鸣器响
}
}
}
#ifdef CONFIG_CMDLINE_EDITING
}
#endif
}


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


static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen)
{
char *s;


if (*np == 0) {
return (p);
}


if (*(--p) == '\t') { /* will retype the whole line */
while (*colp > plen) {
puts (erase_seq);
(*colp)--;
}
for (s=buffer; s if (*s == '\t') {
puts (tab_seq+((*colp) & 07));
*colp += 8 - ((*colp) & 07);
} else {
++(*colp);
putc (*s);
}
}
} else {
puts (erase_seq);
(*colp)--;
}
(*np)--;
return (p);
}


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


int parse_line (char *line, char *argv[])
{
int nargs = 0;


#ifdef DEBUG_PARSER
printf ("parse_line: \"%s\"\n", line);
#endif
while (nargs < CONFIG_SYS_MAXARGS) {


/* skip any white space */
while ((*line == ' ') || (*line == '\t')) {
++line;
}


if (*line == '\0') { /* end of line, no more args */
argv[nargs] = NULL;
#ifdef DEBUG_PARSER
printf ("parse_line: nargs=%d\n", nargs);
#endif
return (nargs);
}


argv[nargs++] = line; /* begin of argument string */


/* find end of string */
while (*line && (*line != ' ') && (*line != '\t')) {
++line;
}


if (*line == '\0') { /* end of line, no more args */
argv[nargs] = NULL;
#ifdef DEBUG_PARSER
printf ("parse_line: nargs=%d\n", nargs);
#endif
return (nargs);
}


*line++ = '\0'; /* terminate current arg */
}


printf ("** Too many args (max. %d) **\n", CONFIG_SYS_MAXARGS);


#ifdef DEBUG_PARSER
printf ("parse_line: nargs=%d\n", nargs);
#endif
return (nargs);
}


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


static void process_macros (const char *input, char *output)
{
char c, prev;
const char *varname_start = NULL;
int inputcnt = strlen (input);
int outputcnt = CONFIG_SYS_CBSIZE;
int state = 0; /* 0 = waiting for '$'  */


/* 1 = waiting for '(' or '{' */
/* 2 = waiting for ')' or '}' */
/* 3 = waiting for '''  */
#ifdef DEBUG_PARSER
char *output_start = output;


printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen (input),
input);
#endif


prev = '\0'; /* previous character   */


while (inputcnt && outputcnt) {
c = *input++;
inputcnt--;


if (state != 3) {
/* remove one level of escape characters */
if ((c == '\\') && (prev != '\\')) {
if (inputcnt-- == 0)
break;
prev = c;
c = *input++;
}
}


switch (state) {
case 0: /* Waiting for (unescaped) $    */
if ((c == '\'') && (prev != '\\')) {
state = 3;
break;
}
if ((c == '$') && (prev != '\\')) {
state++;
} else {
*(output++) = c;
outputcnt--;
}
break;
case 1: /* Waiting for (        */
if (c == '(' || c == '{') {
state++;
varname_start = input;
} else {
state = 0;
*(output++) = '$';
outputcnt--;


if (outputcnt) {
*(output++) = c;
outputcnt--;
}
}
break;
case 2: /* Waiting for )        */
if (c == ')' || c == '}') {
int i;
char envname[CONFIG_SYS_CBSIZE], *envval;
int envcnt = input - varname_start - 1; /* Varname # of chars */


/* Get the varname */
for (i = 0; i < envcnt; i++) {
envname[i] = varname_start[i];
}
envname[i] = 0;


/* Get its value */
envval = getenv (envname);


/* Copy into the line if it exists */
if (envval != NULL)
while ((*envval) && outputcnt) {
*(output++) = *(envval++);
outputcnt--;
}
/* Look for another '$' */
state = 0;
}
break;
case 3: /* Waiting for '        */
if ((c == '\'') && (prev != '\\')) {
state = 0;
} else {
*(output++) = c;
outputcnt--;
}
break;
}
prev = c;
}


if (outputcnt)
*output = 0;
else
*(output - 1) = 0;


#ifdef DEBUG_PARSER
printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n",
strlen (output_start), output_start);
#endif
}


/****************************************************************************
 * returns:
 * 1  - command executed, repeatable
 * 0  - command executed but not repeatable, interrupted commands are
 *     always considered not repeatable
 * -1 - not executed (unrecognized, bootd recursion or too many args)
 *           (If cmd is NULL or "" or longer than CONFIG_SYS_CBSIZE-1 it is
 *           considered unrecognized)
 *
 * WARNING:
 *
 * We must create a temporary copy of the command since the command we get
 * may be the result from getenv(), which returns a pointer directly to
 * the environment data, which may change magicly when the command we run
 * creates or modifies environment variables (like "bootp" does).
 */


int run_command (const char *cmd, int flag)  //saveenv
{
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;


#ifdef DEBUG_PARSER  //没定义
printf ("[RUN_COMMAND] cmd[%p]=\"", cmd);
puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */
puts ("\"\n");
#endif


clear_ctrlc(); /* forget any previous Control C */


if (!cmd || !*cmd) {                  //   1   空命令   ,退出
return -1; /* empty command */
}


if (strlen(cmd) >= CONFIG_SYS_CBSIZE) {
puts ("## Command too long!\n");
return -1;
}


strcpy (cmdbuf, cmd);                //  3     把命令copy to cmdbuf


/* Process separators and check for invalid
* repeatable commands
*/


#ifdef DEBUG_PARSER     //没定义
printf ("[PROCESS_SEPARATORS] %s\n", cmd);
#endif
while (*str) {


/*
* Find separator, or string end
* Allow simple escape of ';' by writing "\;"
*/
                          //   4、以分隔符\;来查找命令
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;  //最终获得的命令token
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) {            //5、查找命令
   // find_cmd()负责匹配输入的命令,从列表中找出对应的命令结构体并返回指向这一结构体的指针。
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;
}


#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) {
                                    //6、把参数传递过去,执行命令
rc = -1;
}


repeatable &= cmdtp->repeatable;


/* Did the user stop this? */
if (had_ctrlc ())
return -1; /* if stopped then not repeatable */
}


return rc ? rc : repeatable;
}


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


#if defined(CONFIG_CMD_RUN)
int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
int i;


if (argc < 2) {
cmd_usage(cmdtp);
return 1;
}


for (i=1; i char *arg;


if ((arg = getenv (argv[i])) == NULL) {
printf ("## Error: \"%s\" not defined\n", argv[i]);
return 1;
}
#ifndef CONFIG_SYS_HUSH_PARSER
if (run_command (arg, flag) == -1)
return 1;
#else
if (parse_string_outer(arg,
   FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) != 0)
return 1;
#endif
}
return 0;
}
#endif

阅读(1672) | 评论(0) | 转发(0) |
0

上一篇:网络设备

下一篇:mini2440---board.c注释

给主人留下些什么吧!~~