0
点赞
收藏
分享

微信扫一扫

U-BOOT启动流程【03】

扬帆远航_df7c 2022-04-15 阅读 60
linux

前言

第一次学u-boot启动流程的时候我也是一头雾水,当然啦看一遍留个大概印象就好!

要想都学透的话也要花费很大的时间精力

本系列blog分三次写。本节讲最后一讲

在虚拟机中我的Vcode比较卡,所以就在window环境下演示的,不过效果都是相同的,所以无需担心!!!如有错误的地方请及时联系我,我们一起学习!!!

板子是正点原子提供的IMX6ULL系列,所以有些函数例如判断CPU、board类型的时候默认跳过

目录

前言

run_main_loop 函数详解

main_loop

cli_loop函数详解

完整版u-boot流程图

run_main_loop 函数详解
 

u-boot启动后会进入3秒倒计时(可以在secureCRT里设置环境变量),如果在 3 秒倒计时结束之前按下按下回车键,那么就会进入 uboot 的命令模式,如果倒计时结束以后都没有按下回车键,那么就会自动启动 Linux 内核 ,这个功能就是由 run_main_loop 函 数来完成的

 run_main_loop定义在common/board_r.c 中,代码如下

        代码可以看出来进入到run_main_loop函数,里面有一个死循环,紧接着进入main_loop函数

main_loop

        main_loop 函数定义在文件 common/main.c 里面,代码如下

        

        48 行:调用 bootstage_mark_name 函数,打印出启动进度

        56 行:如果定义了宏 CONFIG_VERSION_VARIABLE 的话就会执行函数 setenv,设置
换将变量 ver 的值为 version_string,也就是设置版本号环境变量。

        

        60 行:run_preboot_environment_command 函数,获取环境变量 perboot 的内容, perboot
是一些预启动命令,一般不使用这个环境变量。
        65 行:bootdelay_process 函数,此函数会读取环境变量 bootdelay 和 bootcmd 的内容,
然后将 bootdelay 的值赋值给全局变量 stored_bootdelay,返回值为环境变量 bootcmd 的值。bootdelay就是开头我们说的三秒倒计时

        68 行:autoboot_command 函数,此函数就是检查倒计时是否结束?倒计时结束之前有
没有被打断?

        此函数定义在文件common/autoboot.c中,代码如下

         当以下三条条件全部成立的话,就会执行389行run_command_list函数

                ①、stored_bootdelay 不等于-1。相当于环境变量bootdelay的值
                ②、s 不为空。s是bootcmd的值             

                ③、函数 abortboot 返回值为 0

                abortboot的函数定义在文件common/autoboot.c中,代码如下(跟紧!要开始套娃了)

        

        因为宏 CONFIG_AUTOBOOT_KEYE 未定义,因此执行函数 abortboot_normal

        abortboot_normal函数定义在common/autoboot.c(有关于一些通用的定义,大部分都在common根目录下)代码如下

        

        删除掉条件编译之后的代码如下

static int abortboot_normal(int bootdelay)
2 {
3     int abort = 0;
4     unsigned long ts;
5 
6     if (bootdelay >= 0)
7     printf("Hit any key to stop autoboot: %2d ", bootdelay);
8 
9     while ((bootdelay > 0) && (!abort)) {
10    --bootdelay;
11         /* delay 1000 ms */
12    ts = get_timer(0);
13    do {
14    if (tstc()) { /* we got a key press */
15    abort = 1; /* don't auto boot */
16    bootdelay = 0; /* no more delay */
17    (void) getc(); /* consume input */
18    break;
19    }
20    udelay(10000);
21    } while (!abort && get_timer(ts) < 1000);
22
23    printf("\b\b\b%2d ", bootdelay);
24    }
25    putc('\n');
26    return abort;
27    }

        3 行:abort 是函数 abortboot_normal 的返回值,默认值为 0。
        7 行:通过串口输出“Hit any key to stop autoboot”字样
        

        9-21 行:倒计时的具体实现 

        14 行:判断键盘是否有按下,是否打断倒计时。如果有键盘按下的话就执行相应的分支

        26 行:返回abort的值,如果倒计时自然结束,没有被打断abort就为0,否则abort的值为1

        显然易见,当倒计时自然结束,三条条件全部成立,就会执行行run_command_list函数

        此函数会执行参数 s 指定的一系列命令,也就是环境变量 bootcmd 的命令,
        bootcmd 里面保存着默认的启动命令,因此 linux 内核启动!这个就是 uboot 中倒计时结束以后自动启动 linux 内核的原理。如果倒计时结束之前按下了键盘上的按键

        那么 run_command_list函数就不会执行,相当于 autoboot_command 是个空函数。

        我们回到main_loop中,继续执行cli_loop函数
        这个就是命令处理函数,负责接受好处理输入的命令

cli_loop函数详解
 

        cli_loop 函数是 uboot 的命令行处理函数,我们在 uboot 中输入各种命令,进行各种操作就
是有 cli_loop 来处理的

        

        205 行:调用函数 parse_file_outer函数

        207 行:是个死循环,永远不会执行到这里

        我们来接着分析parse_file_outer函数,该函数在文件common/cli_hush.c中定义,代码如下

int parse_file_outer(void)
{
    int rcode;
    struct in_str input;
    setup_file_in_str(&input);
    rcode = parse_stream_outer(&input, FLAG_PARSE_SEMICOLON);
    return rcode;
}

        4 行:调用函数 setup_file_in_str 初始化变量 input 的成员变量。
        5 行:调用函数 parse_stream_outer,这个函数就是 hush shell 的命令解释器,负责接收命
令行输入,然后解析并执行相应的命令
        parse_stream_outer函数定义在文件common/cli_hush.c中,去掉条件编译后代码如下

static int parse_stream_outer(struct in_str *inp, int flag)
{
    struct p_context ctx;
    o_string temp=NULL_O_STRING;
    int rcode;
    int code = 1;
    do {
        ......
        rcode = parse_stream(&temp, &ctx, inp,
        flag & FLAG_CONT_ON_NEWLINE ? -1 : '\n');
        ......
        if (rcode != 1 && ctx.old_flag == 0) {
            ......
            run_list(ctx.list_head);
            ......
        } else {
            ......
        }
        b_free(&temp);
        /* loop on syntax errors, return on EOF */
    } while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP) &&(inp->peek != static_peek || b_peek(inp)));
    return 0;
}

        5 行:run_list 调用 run_list_real 函数
      16 行:run_list_real 函数调用 run_pipe_real 函数

      36 行:run_pipe_real 函数调用 cmd_process 函数

 最终通过函数 cmd_process 来处理命令,接下来就是分析 cmd_process 函数。

完整版u-boot流程图 



  





 

举报

相关推荐

0 条评论