uboot中的命令解析

最近有点空了,就看了点开发板的UBOOT源码(主要是去分析如何解析命令)。

uboot最开始执行的代码是汇编,在标签 _start处开始,后面有了个中断向量表(主要是为个让这点代码被放有地址0x0处),用汇编程序是它可以保证这点代码就在0X0处。

.globl _start

_start: b reset  //上电后执行的第一行,跳到reset处。

  ldr pc, _undefined_instruction  //未定义中断

  ldr pc, _software_interrupt  //软中断

  ldr pc, _prefetch_abort  

  ldr pc, _data_abort  

  ldr pc, _not_used  

  ldr pc, _irq  

  ldr pc, _fiq

进入到后,

之后设置,CPU工作在SVC32 模式,

对设备要完成很多的设置,这里不详讲。

在汇编的最后

ldr pc, _start_armboot  //PC指针指向start_armboot函数,在/lib_arm/board.c中

在这个函数里做了很多数据的初始化工作,

start_armboot在最后用了一个for(;;)死循环,之后调用了main_loop();在/common/main.c中。在这里用死循环的主要原因是防止main_loop的调用没有成功执行。

1 在main_loop的前面部分记录并限制开机的次数。

2 初始化modem

3 set version

4 启动延迟功能,需要等待用户从串口/网络接口输入等。

完成设置后main_loop函数又用了一个for(;;)循环,之后就在这个死循环里面不断的读命令并执行命令,命令的解析开始~~~

parse_file_outer();也是一种命令 解析,可是没有用,我本也想去看一下是如何用行命令解析的,可是看了半天,由于水平太差了。没有看明白,它的命令解析主要是用的Hush.c中实现。

今天讲的是后面的这一种。

 readline (CFG_PROMPT);用来获得用户输入的命令,CFG_PROMPT就如同root@bt  # 的东西。

在readline(CFG_PROMPT)中用getc()获得用户的输入,并存放在console_buffer数组当中。后面用了一个switch语句对输入的值进行检测,若是一些特别的ASCII码值(如:^H)则进行不同的处理(在这里实现了输入的一个比较复杂的操作就是删除操作)。

在readline中的前面定义了一些变量,之后打印了一些东西就不多讲了。后面会有一些打印之类的函数调用也同样不多讲了。

 

clear_ctrlc();//这个函数太简单了,我就不说了,

if (strlen(cmd) >= CFG_CBSIZE) {   //这里的strlen是测试的cmd这个指针指向的命令的字符长度,长度不能超过CFG_CBSIZE。

  puts ("## Command too long!\n");   

  return -1;

}

strcpy (cmdbuf, cmd);//把cmd里面的内容拷到cmdbuf中去。

while (*str) {   //这里的这个while函数 的注释说是分离“;“   但我真没看出来哪里有分离,(本人水平真的很有限)

  ........

}

 

token = str;  

 if (*sep) {       //把*sep清空,

   str = sep + 1; 

  *sep = '\0';   

}

 

后面用了一个函数process_macros的作用我也不是很清楚,但看起来也不是太重要了。

parse_line(finaltoken, argv)是对参数进行获得,

find_cmd(argv[0])再用这个函数在一个对命令与命令库中的命令进行比较,在这个函数里面用来比较是用的strncmp(cmd, cmdtp->name, len) == 0)。而放这些命令 的就是一个结构体cmd_tbl_s,

struct cmd_tbl_s {

  char  *name;     //命令的名字,进行命令的解析就是用的名字。

  int  maxargs;   //最大行参数

  int  repeatable; //允许自动覆盖。   

  int  (*cmd)(struct cmd_tbl_s *, int, int, char *[]);     //命令实现用的指针

  char  *usage;  /* Usage message (short) */

#ifdef CFG_LONGHELP

   char  *help; //命令的帮助

#endif

#ifdef CONFIG_AUTO_COMPLETE  

  int  (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[])

 #endif

};

在strncmp中比较用的是对指针中的值进行相减,如果每一位相减都为0,则这命令找到了,返回该命令的指针。此时就已经得到了命令,后面要做的事当然就是实现用户的命令了。

if (cmdtp->cmd == do_bootd) 下面这一句,是防止bootd的递归。

if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) //这里就是调用的cmd_tbl_s结构体当中的一个函数指针,

{                           //cmd指针指向命令的实现函数。

   rc = -1;   

}

run_command函数结束,由于这是在一个for(;;)死循环当中,程序又回到了readline (CFG_PROMPT);获取用户输入的命令,

 

 

 

posted @ 2012-03-01 22:07  blunsmith  阅读(1579)  评论(0编辑  收藏  举报