当前位置: 首页 > article >正文

uboot剖析之命令行延时

configs/rk3506_defconfig文件中可以配置启动延时选项

CONFIG_BOOTDELAY=3

bootdelay_process处理delay延时值解析,按键捕获由autoboot_command负责

void main_loop(void)
{
        const char *s;

        bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");

#ifdef CONFIG_VERSION_VARIABLE
        env_set("ver", version_string);  /* set version variable */
#endif /* CONFIG_VERSION_VARIABLE */

        cli_init();

        run_preboot_environment_command();

#if defined(CONFIG_UPDATE_TFTP)
        update_tftp(0UL, NULL, NULL);
#endif /* CONFIG_UPDATE_TFTP */

        s = bootdelay_process();
        if (cli_process_fdt(&s))
                cli_secure_boot_cmd(s);

        autoboot_command(s);

        cli_loop();
        panic("No CLI available");
}

要么从环境变量bootdelay里边获取,要么就从CONFIG_BOOTDELAY里边获取,最后更新stored_bootdelay

const char *bootdelay_process(void)
{
        char *s;
        int bootdelay;
#ifdef CONFIG_BOOTCOUNT_LIMIT
        unsigned long bootcount = 0;
        unsigned long bootlimit = 0;
#endif /* CONFIG_BOOTCOUNT_LIMIT */

#ifdef CONFIG_BOOTCOUNT_LIMIT
        bootcount = bootcount_load();
        bootcount++;
        bootcount_store(bootcount);
        env_set_ulong("bootcount", bootcount);
        bootlimit = env_get_ulong("bootlimit", 10, 0);
#endif /* CONFIG_BOOTCOUNT_LIMIT */

        s = env_get("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);
#endif

        debug("### main_loop entered: bootdelay=%d\n\n", bootdelay);

#if defined(CONFIG_MENU_SHOW)
        bootdelay = menu_show(bootdelay);
#endif
        bootretry_init_cmd_timeout();

#ifdef CONFIG_POST
        if (gd->flags & GD_FLG_POSTFAIL) {
                s = env_get("failbootcmd");
        } else
#endif /* CONFIG_POST */
#ifdef CONFIG_BOOTCOUNT_LIMIT
        if (bootlimit && (bootcount > bootlimit)) {
                printf("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
                       (unsigned)bootlimit);
                s = env_get("altbootcmd");
        } else
#endif /* CONFIG_BOOTCOUNT_LIMIT */
                s = env_get("bootcmd");

        process_fdt_options(gd->fdt_blob);
        stored_bootdelay = bootdelay;

        return s;
}

autoboot_command:在执行启动命令run_command_list前先检查stored_bootdelay

void autoboot_command(const char *s)
{
        debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");

        if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
#if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
                int prev = disable_ctrlc(1);        /* disable Control C checking */
#endif

                run_command_list(s, -1, 0);
                autoboot_command_fail_handle();

#if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
                disable_ctrlc(prev);        /* restore Control C checking */
#endif
        }

#ifdef CONFIG_MENUKEY
        if (menukey == CONFIG_MENUKEY) {
                s = env_get("menucmd");
                if (s)
                        run_command_list(s, -1, 0);
        }
#endif /* CONFIG_MENUKEY */
}

abortboot:真正的功能实现在__abortboot

static int abortboot(int bootdelay)
{
        int abort = 0;

        if (bootdelay >= 0)
                abort = __abortboot(bootdelay);

#ifdef CONFIG_SILENT_CONSOLE
        if (abort)
                gd->flags &= ~GD_FLG_SILENT;
#endif

        return abort;
}

__abortboot:bootdelay延时计数 + 等待按键ctrl+c输入

static int __abortboot(int bootdelay)
{
        int abort = 0;
        unsigned long ts;

#ifdef CONFIG_MENUPROMPT
        printf(CONFIG_MENUPROMPT);
#else
        printf("Hit key to stop autoboot('CTRL+C'): %2d ", bootdelay);
#endif

#ifdef CONFIG_ARCH_ROCKCHIP
        if (!IS_ENABLED(CONFIG_CONSOLE_DISABLE_CLI) && ctrlc()) {        /* we press ctrl+c ? */
#else
        /*
         * Check if key already pressed
         */
        if (tstc()) {        /* we got a key press        */
#endif
                (void) getc();  /* consume input        */
                puts("\b\b\b 0");
                abort = 1;        /* don't auto boot        */
        }

        while ((bootdelay > 0) && (!abort)) {
                --bootdelay;
                /* delay 1000 ms */
                ts = get_timer(0);
                do {
                        if (ctrlc()) {        /* we got a ctrl+c key press        */
                                abort  = 1;        /* don't auto boot        */
                                bootdelay = 0;        /* no more delay        */
# ifdef CONFIG_MENUKEY
                                menukey = 0x03;        /* ctrl+c key code */
# endif
                                break;
                        }
                        udelay(10000);
                } while (!abort && get_timer(ts) < 1000);

                printf("\b\b\b%2d ", bootdelay);
        }

        putc('\n');

        return abort;
}

http://www.kler.cn/a/513060.html

相关文章:

  • 【Node.js]
  • React Context 实现全局组件注册
  • 豆包升级了“眼睛”,看APP截图就能写代码了!超低价让多模态AI普惠
  • 4.C++中的循环语句
  • STM32补充——FLASH
  • Numpy基础01(Jupyter基本用法/Ndarray创建与基本操作)
  • C++ 学习:深入理解 Linux 系统中的冯诺依曼架构
  • python爬虫入门(实践)
  • 基于Springboot+Redis秒杀系统 demo
  • 【2024年华为OD机试】 (JavaScriptJava PythonC/C++)
  • 网络安全态势感知技术综述
  • Apache Hive 聚合函数与 OVER 窗口函数:从基础到高级应用
  • Oracle审计
  • SecureUtil.aes数据加密工具类
  • 通义万相:阿里巴巴 AI 生成式多模态平台解析与实战应用
  • 细说STM32F407单片机电源低功耗StandbyMode待机模式及应用示例
  • AI编程工具使用技巧:在Visual Studio Code中高效利用阿里云通义灵码
  • 如何提升IP地址查询数据服务的安全?
  • controlnet 多 condition 融合
  • 网安篇(一)日志分析——从给的登录日志中找出攻击IP和使用的用户名
  • 数据结构学习记录-树和二叉树
  • 堆的实现(C语言详解版)
  • yolo系列模型为什么坚持使用CNN网络?
  • LeetCode:37. 解数独
  • [Easy] leetcode-500 键盘行
  • Pix2Pix:图像到图像转换的条件生成对抗网络深度解析