上面的do-while会循环命令解析器的"命令输入解析–执行"运行模式。
其中的函数run_list执行如下的函数调用流程:run_list–>run_list_real–>run_pipe_real->cmd_process
# u-boot/common/main.c
void main_loop(void)
cli_init();
...
s = bootdelay_process();
...
autoboot_command(s);
cli_loop();
# u-boot/common/board_r.c
;...
static init_fnc_t init_sequence_r[] = {
...
stdio_init_tables,
INIT_LIST_HEAD(&(devs.list));
initr_serial,
serial_initialize();
serial_init();
...
stdio_add_devices,
drv_system_init ();
...
strcpy (dev.name, "serial");
dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
dev.putc = stdio_serial_putc;
#ifdef CONFIG_NETCONSOLE
drv_nc_init ();
...
strcpy(dev.name, "nc");
dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;
dev.start = nc_stdio_start;
dev.putc = nc_stdio_putc;
...
run_main_loop,
for (;;)
main_loop(); // 进入交互终端
void main_loop(void)
cli_init();
#ifdef CONFIG_HUSH_PARSER // 使用HUSH解释器
u_boot_hush_start();
if (top_vars == NULL) {
top_vars = malloc(sizeof(struct variables));
top_vars->name = "HUSH_VERSION"; // 使用命令showvar可查看
top_vars->value = "0.01";
...
s = bootdelay_process();
s = env_get("bootdelay"); // 获取bootdelay信息
bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
#ifdef CONFIG_OF_CONTROL
bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay", bootdelay); // 支持fdt中修改的bootdelay;
...
s = env_get("bootcmd"); // 获取默认引导命令;
process_fdt_options(gd->fdt_blob); // 获取:kernel-offset、rootdisk-offset信息;
stored_bootdelay = bootdelay; // 记录引导倒计时:bootdelay
return s; // 返回引导命令:bootcmd
...
autoboot_command(s); // 执行引导命令:bootcmd
if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) { // 有设置bootdelay,引导命令非空,无人为打断
run_command_list(s, -1, 0); // 执行
autoboot_command_fail_handle();
cli_loop(); // 自动引导未正常进行后,进入命令行交互
#ifndef CONFIG_CONSOLE_DISABLE_CLI
void cli_loop(void)
#ifdef CONFIG_HUSH_PARSER // rk3568_defconfig, 开启
parse_file_outer();
struct in_str input;
setup_file_in_str(&input);
i->peek = file_peek;
i->get = file_get; // 与b_getch 关联:#define b_getch(input) ((input)->get(input))
...
rcode = parse_stream_outer(&input, FLAG_PARSE_SEMICOLON); // flags标记:分号
...
do {
...
rcode = parse_stream(&temp, &ctx, inp, flag & FLAG_CONT_ON_NEWLINE ? -1 : '\n');
/* This point is never reached */ // 不应运行到此
for (;;);