这一节的主要内容
一、分析run_command
二、自己写一个u-boot命令
在u-boot启动等待超时的过程中按下空格键,u-boot会进入菜单模式(用于调试)
run_command主要作用是在菜单模式中读取用户输入的字符串,根据字符串从表中提取参数、找到相应命令结构体,并调用命令结构体的功能函数,启动内核也是通过这个函数来进行的
分析run-command:
1、处理字符串
clear_ctrlc(); /*去掉前面的空格*/
if (!cmd || !*cmd) { /*判断命令是否为空*/
return -1; /* empty command */
}
if (strlen(cmd) >= CFG_CBSIZE) { /*判断命令长度是否合适*/
puts ("## Command too long!\n");
return -1;
}
while (*str) { /*解析字符串并执行命令*/
for (inquotes = 0, sep = str; *sep; sep++) {
if ((*sep=='\'') &&
(*(sep-1) != '\\'))
inquotes=!inquotes;
if (!inquotes &&
(*sep == ';') &&
( sep != str) &&
(*(sep-1) != '\\'))
break;
}
token = str;
if (*sep) {
str = sep + 1;
*sep = '\0';
}
else
str = sep;
#ifdef DEBUG_PARSER
printf ("token: \"%s\"\n", token);
#endif
process_macros (token, finaltoken);
if ((argc = parse_line (finaltoken, argv)) == 0) { /*提取参数*/
rc = -1;
continue;
}
2、根据字符串找到命令结构体
if ((cmdtp = find_cmd(argv[0])) == NULL) { /*查表找到命令*/
printf ("Unknown command '%s' - try 'help'\n", argv[0]);
rc = -1; /* give up after bad command */
continue;
}
3、调用命令结构体的功能函数
if (argc > cmdtp->maxargs) { /*检查参数个数*/
printf ("Usage:\n%s\n", cmdtp->usage);
rc = -1;
continue;
}
#if (CONFIG_COMMANDS & CFG_CMD_BOOTD)
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
if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) { /*执行命令*/
rc = -1;
}
repeatable &= cmdtp->repeatable;
if (had_ctrlc ())
return 0;
}
其中cmd_tbl_t类型的结构体用于描述命令,结构体类型定义在u-boot-1.1.6/include/command.h
struct cmd_tbl_s {
char *name; /*命令名称*/
int maxargs; /*最大参数个数*/
int repeatable; /*可重复的标志位*/
int (*cmd)(struct cmd_tbl_s *, int, int, char *[]); /*命令功能函数指针*/
char *usage; /*短的帮助信息*/
#ifdef CFG_LONGHELP
char *help; /*长的帮助信息*/
#endif
#ifdef CONFIG_AUTO_COMPLETE
int (*complete)(int argc, char *argv[], char last_char, int maxv, char *cmdv[]);
#endif
};
typedef struct cmd_tbl_s cmd_tbl_t;
并且在该文件还定义了一个重要的宏:
#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}
各种命令的定义在u-boot-1.1.6/common的cmd_xxx.c文件中,如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
);
将宏展开后:
cmd_tbl_t __u_boot_cmd_bootm Struct_Section = {
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
};
这个结构体中的函数成员do_bootm的头部为
int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
二、自己写一个u-boot命令
知道这些,就可以仿照实现自己需要的u-boot命令,例如实现一个打印语句”test\r\n”的命令
1、新建文件cmd_test.c,放在u-boot-1.1.6/common中
2、修改u-boot-1.1.6/common/Makefile,在55行添加
COBJS += cmd_test.o
3、在cmd_test.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_test (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
printf(“test\r\n”);
return 1;
}
U_BOOT_CMD(
test, CFG_MAXARGS, 1, do_test,
"short help\n",
"long help\n"
);
4、重新编译烧写u-boot,即可在u-boot菜单模式中输入test来执行自己编写的命令了