根据命令找到对应的函数
命令结构体
分离开命令,命令中有 ; 等,还是在common/main.c中,
/*
* 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 */
处理一些宏,如通过网卡下载文件时产生的宏,
/* find macros in this tokenand replace them */
process_macros (token, finaltoken);
提取命令和参数,argv[0](命令), argv[1](参数)等等
/* 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;
}
命令结构体cmd_tbl_s,在include/command.h中,命令名字,参数,是否可重复(回车就可以再次执行),函数指针执行命令,短(help)长(help print)帮助信息,
/*
* Monitor Command Table
*/
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
};
查找命令find_cmd,在common/command.c中,for循环依次在__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++;
}
__u_boot_cmd_start~__u_boot_cmd_end这俩东西在代码中找不到,但可以通过链接脚本(board/100ask24x0/u-boot.lds)传入,
. = .;
__u_boot_cmd_start = .;
.u_boot_cmd : { *(.u_boot_cmd) }
__u_boot_cmd_end = .;
想查看究竟这俩中间放了些什么命令,需要在include/command.h中找到u_boot_cmd的定义
#define Struct_Section __attribute__ ((unused,section (".u_boot_cmd")))
假设命令为bootcmd nand read 0x30007fc0 kernel;bootm 0x30007fc0
以bootm命令为例,找到这个宏U_BOOT_CMD,在common/cmd_bootm.c中,
U_BOOT_CMD(
bootm, CFG_MAXARGS, 1, do_bootm,
"bootm - boot application image from memory\n",
"[addr [arg ...]]\n - boot application image stored in memory\n"
"\tpassing arguments 'arg ...'; when booting a Linux kernel,\n"
"\t'arg' can be the address of an initrd image\n"
#ifdef CONFIG_OF_FLAT_TREE
"\tWhen booting a Linux kernel which requires a flat device-tree\n"
"\ta third argument is required which is the address of the of the\n"
"\tdevice-tree blob. To boot that kernel without an initrd image,\n"
"\tuse a '-' for the second argument. If you do not pass a third\n"
"\ta bd_info struct will be passed instead\n"
#endif
);
定义之处还是在include/command.h中,
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}
展开如下,cmd_tbl_t为结构体类型,Struct_Section为前面的定义的宏__attribute__ ((unused,section (".u_boot_cmd")))。定义一个结构体变量__u_boot_cmd_bootm,其有段属性被强制设置为".u_boot_cmd",这个东西在lds中。
#name, maxargs, rep, cmd, usage, help分别在这个宏U_BOOT_CMD中对应,usage和help为字符串,
cmd_tbl_t __u_boot_cmd_bootm __attribute__ ((unused,section (".u_boot_cmd"))) = {"bootm", CFG_MAXARGS, 1, do_bootm, 小help, 大help}
===最后:在代码段用U_BOOT_CMD表示的东西最终被解析成
cmd_tbl_t __u_boot_cmd_bootm __attribute__ ((unused,section (".u_boot_cmd"))) = {"bootm", CFG_MAXARGS, 1, do_bootm, 小help, 大help}
这就相当于定义了一个结构体,这个结构体有个属性强制把他的段指定成".u_boot_cmd",所以所有的命令都会被集中到lds中的.u_boot_cmd : { *(.u_boot_cmd) }
这里。=====
在uboot中增加一个自定义命令
uboot命令都放在common/下吧,
命名为cmd_my_hello.c,
#include <common.h>
#include <watchdog.h>
#include <command.h>
#include <image.h>
#include <malloc.h>
#include <zlib.h>
#include <bzlib.h>
#include <environment.h>
#include <asm/byteorder.h>
int do_my_hello (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int i = 0;
printf ("my_hello add uboot cmd\n");
for (i=0; i<argc; ++i)
{
printf("argv[%d]: %s\n", i, argv[i]);
}
return 0;
}
U_BOOT_CMD(
my_hello, CFG_MAXARGS, 1, do_my_hello,
"my_hello short help, just for test.\n",
"my_hello, long help\n"
"\tmy_hello, long help1....\n"
"\tmy_hello, long help2....\n"
);
修改common/Makefile, 只需要添加就是了,
s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o spartan3.o \
usb.o usb_kbd.o usb_storage.o \
virtex2.o xilinx.o crc16.o xyzModem.o cmd_mac.o cmd_suspend.o \
cmd_my_hello.o # 自定义uboot命令
重新编译uboot,cd到uboot根目录,make。
根目录下生成的u-boot.bin烧写到开发板就ok了。
检查是否添加,命令成功,
OpenJTAG> help
OpenJTAG> help my_hello
OpenJTAG> my_hello