u-boot分析之u-boot命令实现
2016-11-21 17:48
507 查看
当我们在串口的控制台上输入一个命令,要么提示不能识别的命令,要么就会打印某些东西(执行)。这些命令是怎么实现的?
使用命令的步骤:
1,输入字符串,对应某些命令名。
2,执行。
显然,在程序里面是根据这些命令,找到对应的函数,然后执行相应的函数;在在u-boot不会只有一个结构体,这些命令肯定会有一个结构体,结构体中包括:名字、函数;根据输入的命令到这个结构体链中一一比较,然后执行;
先看一下run_command的实现,它的代码如下:
这段代码中调用了find_cmd函数查找命令对应的函数,find_cmd函数如下:
命令对应的结构体代码如下:
这个命令结构体包含了命令名、帮助信息、执行函数,其中cmd就是一个函数指针;
实践操作
如何在u-boot里面自定义一个hello命令?
1,首先我们在u-boot的common目录下增加一个cmd_hello.c文件 。
参照其他命令的书写方式,代码如下 :
2, 修改common下面的makefile文件,告诉U-Boot编译我们自定义的C文件
参考Makefile中其他文件的定义,加入一句
3,重新make编译 u-boot
使用命令的步骤:
1,输入字符串,对应某些命令名。
2,执行。
显然,在程序里面是根据这些命令,找到对应的函数,然后执行相应的函数;在在u-boot不会只有一个结构体,这些命令肯定会有一个结构体,结构体中包括:名字、函数;根据输入的命令到这个结构体链中一一比较,然后执行;
先看一下run_command的实现,它的代码如下:
int run_command (const char *cmd, int flag) { cmd_tbl_t *cmdtp; char cmdbuf[CFG_CBSIZE]; /* working copy of cmd */ char *token; /* start of token in cmdbuf */ char *sep; /* end of token (separator) in cmdbuf */ char finaltoken[CFG_CBSIZE]; char *str = cmdbuf; char *argv[CFG_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) { return -1; /* empty command */ } if (strlen(cmd) >= CFG_CBSIZE) { puts ("## Command too long!\n"); return -1; } strcpy (cmdbuf, cmd); /* 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 "\;" */ //解析输入命令里面的符号 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) { printf ("Usage:\n%s\n", cmdtp->usage); rc = -1; continue; } #if (CONFIG_COMMANDS & CFG_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 /* CFG_CMD_BOOTD */ /* 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 ()) return 0; /* if stopped then not repeatable */ } return rc ? rc : repeatable; }
这段代码中调用了find_cmd函数查找命令对应的函数,find_cmd函数如下:
/*************************************************************************** * find command table entry for a command */ cmd_tbl_t *find_cmd (const char *cmd) { cmd_tbl_t *cmdtp; cmd_tbl_t *cmdtp_temp = &__u_boot_cmd_start; /*Init value */ const char *p; int len; int n_found = 0; /* * Some commands allow length modifiers (like "cp.b"); * compare command name only until first dot. */ len = ((p = strchr(cmd, '.')) == NULL) ? strlen (cmd) : (p - cmd); /* * __u_boot_cmd_start,__u_boot_cmd_end这两个变量是在链接脚本里面 * **/ for (cmdtp = &__u_boot_cmd_start; cmdtp != &__u_boot_cmd_end; cmdtp++) { /* * 比较名字 **/ if (strncmp (cmd, cmdtp->name, len) == 0) { if (len == strlen (cmdtp->name)) return cmdtp; /* full match 返回结构体*/ cmdtp_temp = cmdtp; /* abbreviated command ? 指向下一个,继续往下找*/ n_found++; } } if (n_found == 1) { /* exactly one match */ return cmdtp_temp; } return NULL; /* not found or ambiguous command */ }
命令对应的结构体代码如下:
struct cmd_tbl_s { char *name; /* Command Name */ int maxargs; /* maximum number of arguments */ int repeatable; /* autorepeat allowed? */ /* Implementation function */ int (*cmd)(struct cmd_tbl_s *, int, int, char *[]); char *usage; /* Usage message (short) */ #ifdef CFG_LONGHELP char *help; /* Help message (long) */ #endif #ifdef CONFIG_AUTO_COMPLETE /* do auto completion on the arguments */ int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]); #endif };
这个命令结构体包含了命令名、帮助信息、执行函数,其中cmd就是一个函数指针;
实践操作
如何在u-boot里面自定义一个hello命令?
1,首先我们在u-boot的common目录下增加一个cmd_hello.c文件 。
参照其他命令的书写方式,代码如下 :
#include <image.h> #include <malloc.h> #include <u-boot/zlib.h> #include <bzlib.h> #include <environment.h> #include <lmb.h> #include <linux/ctype.h> #include <asm/byteorder.h> int do_hello (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { int i = 0; printf("hello,Lover!!!\nthe argcs are \n"); for(i = 0 ; i<argc ; i++) printf("argv[%d]: %s\n",i,argv[i]); return 0; } U_BOOT_CMD( hello, CONFIG_SYS_MAXARGS, 1, do_hello, "This is a user defined command hello,Lover!!!", "hello,long help ......\n" );
2, 修改common下面的makefile文件,告诉U-Boot编译我们自定义的C文件
参考Makefile中其他文件的定义,加入一句
COBJS-y += cmd_hello.o
3,重新make编译 u-boot
相关文章推荐
- u-boot分析 七 (添加u-boot命令,学习u-boot命令实现原理)
- u-boot分析 七 (添加u-boot命令,学习u-boot命令实现原理)
- 伟东山视频自学笔记——uboot命令分析+实现_________精华————————
- u-boot分析(三)---boot命令实现以及内核的启动
- U_BOOT_CMD 命令实现分析
- 04-S3C2440u-boot学习之u-boot分析(4)之u-boot命令实现
- u-boot分析(三)---boot命令实现以及内核的启动
- u-boot命令分析&命令实现
- 一步步学Linux网络编程--ping命令的实现分析
- u-boot-2012.10 shell模式命令自动补齐功能 源代码分析
- U_BOOT_CMD命令的实现
- 笔记:一个操作系统的实现第一章boot.asm文件分析
- u-boot go命令分析
- date 命令实现源码分析
- U-boot分析与移植(4)----U-boot 添加命令
- u-boot reset命令分析
- U-BOOT环境变量的获取和保存的实现分析
- U_BOOT_CMD命令的实现
- uboot源码分析(1)uboot 命令解析流程简析
- 关于S5PV210的启动问题和u-boot分析并自己实现一个简单的boot(一)