blob: 5bb2e190895fc62d788fa4143c5f4212cf405095 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass66ded172014-04-10 20:01:28 -06002/*
3 * (C) Copyright 2000
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
Simon Glass66ded172014-04-10 20:01:28 -06005 */
6
7#include <common.h>
Jeroen Hofstee39e12302014-07-13 22:57:58 +02008#include <autoboot.h>
Simon Glass0098e172014-04-10 20:01:30 -06009#include <bootretry.h>
Simon Glass66ded172014-04-10 20:01:28 -060010#include <cli.h>
Simon Glass288b29e2019-11-14 12:57:43 -070011#include <command.h>
Simon Glass24b852a2015-11-08 23:47:45 -070012#include <console.h>
Simon Glassc7694dd2019-08-01 09:46:46 -060013#include <env.h>
Simon Glass66ded172014-04-10 20:01:28 -060014#include <fdtdec.h>
Simon Glasse8c78052019-07-20 20:51:16 -060015#include <hash.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060016#include <log.h>
Simon Glass336d4612020-02-03 07:36:16 -070017#include <malloc.h>
Heiko Schocherecaae802019-07-29 07:23:19 +020018#include <memalign.h>
Simon Glass66ded172014-04-10 20:01:28 -060019#include <menu.h>
20#include <post.h>
Simon Glass10453152019-11-14 12:57:30 -070021#include <time.h>
Simon Glass401d1c42020-10-30 21:38:53 -060022#include <asm/global_data.h>
Simon Glassc05ed002020-05-10 11:40:11 -060023#include <linux/delay.h>
Stefan Roese8f0b1e22015-05-18 14:08:24 +020024#include <u-boot/sha256.h>
Lukasz Majewskibc8c4402018-05-02 16:10:53 +020025#include <bootcount.h>
Steffen Jaeckel1a4a7782021-07-08 15:57:35 +020026#include <crypt.h>
Simon Glass66ded172014-04-10 20:01:28 -060027
28DECLARE_GLOBAL_DATA_PTR;
29
Steffen Jaeckel1b2d6802021-07-08 15:57:36 +020030#define DELAY_STOP_STR_MAX_LENGTH 64
Simon Glass66ded172014-04-10 20:01:28 -060031
32#ifndef DEBUG_BOOTKEYS
33#define DEBUG_BOOTKEYS 0
34#endif
35#define debug_bootkeys(fmt, args...) \
36 debug_cond(DEBUG_BOOTKEYS, fmt, ##args)
37
Simon Glassaffb2152014-04-10 20:01:35 -060038/* Stored value of bootdelay, used by autoboot_command() */
39static int stored_bootdelay;
Simon Glassd915ad22019-07-20 20:51:23 -060040static int menukey;
Simon Glassaffb2152014-04-10 20:01:35 -060041
Steffen Jaeckel1a4a7782021-07-08 15:57:35 +020042#if !defined(CONFIG_AUTOBOOT_STOP_STR_CRYPT)
43#define CONFIG_AUTOBOOT_STOP_STR_CRYPT ""
44#endif
45#if !defined(CONFIG_AUTOBOOT_STOP_STR_SHA256)
46#define CONFIG_AUTOBOOT_STOP_STR_SHA256 ""
Simon Glass0c4bd312019-07-20 20:51:15 -060047#endif
48
Da Xue5a87df82021-06-21 22:39:19 -040049#ifdef CONFIG_AUTOBOOT_USE_MENUKEY
Da Xue760d2f92021-07-02 12:32:43 -040050#define AUTOBOOT_MENUKEY CONFIG_AUTOBOOT_MENUKEY
Simon Glassd915ad22019-07-20 20:51:23 -060051#else
52#define AUTOBOOT_MENUKEY 0
53#endif
54
Steffen Jaeckel1a4a7782021-07-08 15:57:35 +020055/**
56 * passwd_abort_crypt() - check for a crypt-style hashed key sequence to abort booting
57 *
58 * This checks for the user entering a password within a given time.
59 *
60 * The entered password is hashed via one of the crypt-style hash methods
61 * and compared to the pre-defined value from either
62 * the environment variable "bootstopkeycrypt"
63 * or
64 * the config value CONFIG_AUTOBOOT_STOP_STR_CRYPT
65 *
Steffen Jaeckel6c0ce6d2021-07-08 15:57:37 +020066 * In case the config value CONFIG_AUTOBOOT_NEVER_TIMEOUT has been enabled
67 * this function never times out if the user presses the <Enter> key
68 * before starting to enter the password.
69 *
Steffen Jaeckel1a4a7782021-07-08 15:57:35 +020070 * @etime: Timeout value ticks (stop when get_ticks() reachs this)
71 * @return 0 if autoboot should continue, 1 if it should stop
72 */
73static int passwd_abort_crypt(uint64_t etime)
74{
75 const char *crypt_env_str = env_get("bootstopkeycrypt");
Steffen Jaeckel1b2d6802021-07-08 15:57:36 +020076 char presskey[DELAY_STOP_STR_MAX_LENGTH];
Steffen Jaeckel1a4a7782021-07-08 15:57:35 +020077 u_int presskey_len = 0;
78 int abort = 0;
Steffen Jaeckel6c0ce6d2021-07-08 15:57:37 +020079 int never_timeout = 0;
Steffen Jaeckel1a4a7782021-07-08 15:57:35 +020080 int err;
81
82 if (IS_ENABLED(CONFIG_AUTOBOOT_STOP_STR_ENABLE) && !crypt_env_str)
83 crypt_env_str = CONFIG_AUTOBOOT_STOP_STR_CRYPT;
84
85 if (!crypt_env_str)
86 return 0;
87
88 /* We expect the stop-string to be newline-terminated */
89 do {
90 if (tstc()) {
91 /* Check for input string overflow */
92 if (presskey_len >= sizeof(presskey))
93 return 0;
94
95 presskey[presskey_len] = getchar();
96
97 if ((presskey[presskey_len] == '\r') ||
98 (presskey[presskey_len] == '\n')) {
Steffen Jaeckel6c0ce6d2021-07-08 15:57:37 +020099 if (IS_ENABLED(CONFIG_AUTOBOOT_NEVER_TIMEOUT) &&
100 !presskey_len) {
101 never_timeout = 1;
102 continue;
103 }
Steffen Jaeckel1a4a7782021-07-08 15:57:35 +0200104 presskey[presskey_len] = '\0';
105 err = crypt_compare(crypt_env_str, presskey,
106 &abort);
107 if (err)
108 debug_bootkeys(
109 "crypt_compare() failed with: %s\n",
110 errno_str(err));
111 /* you had one chance */
112 break;
113 } else {
114 presskey_len++;
115 }
116 }
Steffen Jaeckel6c0ce6d2021-07-08 15:57:37 +0200117 } while (never_timeout || get_ticks() <= etime);
Steffen Jaeckel1a4a7782021-07-08 15:57:35 +0200118
119 return abort;
120}
121
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200122/*
123 * Use a "constant-length" time compare function for this
124 * hash compare:
125 *
126 * https://crackstation.net/hashing-security.htm
Simon Glass66ded172014-04-10 20:01:28 -0600127 */
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200128static int slow_equals(u8 *a, u8 *b, int len)
129{
130 int diff = 0;
131 int i;
132
133 for (i = 0; i < len; i++)
134 diff |= a[i] ^ b[i];
135
136 return diff == 0;
137}
138
Simon Glass88fa4be2019-07-20 20:51:17 -0600139/**
140 * passwd_abort_sha256() - check for a hashed key sequence to abort booting
141 *
142 * This checks for the user entering a SHA256 hash within a given time.
143 *
144 * @etime: Timeout value ticks (stop when get_ticks() reachs this)
145 * @return 0 if autoboot should continue, 1 if it should stop
146 */
Simon Glasse8c78052019-07-20 20:51:16 -0600147static int passwd_abort_sha256(uint64_t etime)
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200148{
Simon Glass00caae62017-08-03 12:22:12 -0600149 const char *sha_env_str = env_get("bootstopkeysha256");
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200150 u8 sha_env[SHA256_SUM_LEN];
Heiko Schocherecaae802019-07-29 07:23:19 +0200151 u8 *sha;
152 char *presskey;
Joel Peshkin652b5042020-11-21 17:18:59 -0800153 char *c;
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200154 const char *algo_name = "sha256";
155 u_int presskey_len = 0;
156 int abort = 0;
Martin Etnestad2d06fd82018-01-12 09:04:38 +0100157 int size = sizeof(sha);
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200158 int ret;
159
160 if (sha_env_str == NULL)
Steffen Jaeckel1a4a7782021-07-08 15:57:35 +0200161 sha_env_str = CONFIG_AUTOBOOT_STOP_STR_SHA256;
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200162
Steffen Jaeckel1b2d6802021-07-08 15:57:36 +0200163 presskey = malloc_cache_aligned(DELAY_STOP_STR_MAX_LENGTH);
Joel Peshkin652b5042020-11-21 17:18:59 -0800164 c = strstr(sha_env_str, ":");
Steffen Jaeckel1b2d6802021-07-08 15:57:36 +0200165 if (c && (c - sha_env_str < DELAY_STOP_STR_MAX_LENGTH)) {
Joel Peshkin652b5042020-11-21 17:18:59 -0800166 /* preload presskey with salt */
167 memcpy(presskey, sha_env_str, c - sha_env_str);
168 presskey_len = c - sha_env_str;
169 sha_env_str = c + 1;
170 }
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200171 /*
172 * Generate the binary value from the environment hash value
173 * so that we can compare this value with the computed hash
174 * from the user input
175 */
176 ret = hash_parse_string(algo_name, sha_env_str, sha_env);
177 if (ret) {
178 printf("Hash %s not supported!\n", algo_name);
179 return 0;
180 }
181
Heiko Schocherecaae802019-07-29 07:23:19 +0200182 sha = malloc_cache_aligned(SHA256_SUM_LEN);
183 size = SHA256_SUM_LEN;
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200184 /*
185 * We don't know how long the stop-string is, so we need to
186 * generate the sha256 hash upon each input character and
187 * compare the value with the one saved in the environment
188 */
189 do {
190 if (tstc()) {
191 /* Check for input string overflow */
Steffen Jaeckel1b2d6802021-07-08 15:57:36 +0200192 if (presskey_len >= DELAY_STOP_STR_MAX_LENGTH) {
Heiko Schocherecaae802019-07-29 07:23:19 +0200193 free(presskey);
194 free(sha);
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200195 return 0;
Heiko Schocherecaae802019-07-29 07:23:19 +0200196 }
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200197
Heinrich Schuchardtc670aee2020-10-07 18:11:48 +0200198 presskey[presskey_len++] = getchar();
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200199
200 /* Calculate sha256 upon each new char */
201 hash_block(algo_name, (const void *)presskey,
202 presskey_len, sha, &size);
203
204 /* And check if sha matches saved value in env */
205 if (slow_equals(sha, sha_env, SHA256_SUM_LEN))
206 abort = 1;
207 }
208 } while (!abort && get_ticks() <= etime);
209
Heiko Schocherecaae802019-07-29 07:23:19 +0200210 free(presskey);
211 free(sha);
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200212 return abort;
213}
Simon Glasse8c78052019-07-20 20:51:16 -0600214
Simon Glass88fa4be2019-07-20 20:51:17 -0600215/**
216 * passwd_abort_key() - check for a key sequence to aborted booting
217 *
218 * This checks for the user entering a string within a given time.
219 *
220 * @etime: Timeout value ticks (stop when get_ticks() reachs this)
221 * @return 0 if autoboot should continue, 1 if it should stop
222 */
Simon Glasse8c78052019-07-20 20:51:16 -0600223static int passwd_abort_key(uint64_t etime)
Simon Glass66ded172014-04-10 20:01:28 -0600224{
225 int abort = 0;
Simon Glass66ded172014-04-10 20:01:28 -0600226 struct {
227 char *str;
228 u_int len;
229 int retry;
230 }
231 delaykey[] = {
Simon Glass00caae62017-08-03 12:22:12 -0600232 { .str = env_get("bootdelaykey"), .retry = 1 },
233 { .str = env_get("bootstopkey"), .retry = 0 },
Simon Glass66ded172014-04-10 20:01:28 -0600234 };
235
Steffen Jaeckel1b2d6802021-07-08 15:57:36 +0200236 char presskey[DELAY_STOP_STR_MAX_LENGTH];
Yuezhang.Mo@sony.come088f0c2021-01-15 03:11:49 +0000237 int presskey_len = 0;
238 int presskey_max = 0;
239 int i;
Simon Glass66ded172014-04-10 20:01:28 -0600240
Simon Glass66ded172014-04-10 20:01:28 -0600241# ifdef CONFIG_AUTOBOOT_DELAY_STR
242 if (delaykey[0].str == NULL)
243 delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
244# endif
Simon Glass66ded172014-04-10 20:01:28 -0600245# ifdef CONFIG_AUTOBOOT_STOP_STR
Stefan Roese2d908fa2015-05-18 14:08:22 +0200246 if (delaykey[1].str == NULL)
247 delaykey[1].str = CONFIG_AUTOBOOT_STOP_STR;
Simon Glass66ded172014-04-10 20:01:28 -0600248# endif
249
250 for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) {
251 delaykey[i].len = delaykey[i].str == NULL ?
252 0 : strlen(delaykey[i].str);
Steffen Jaeckel1b2d6802021-07-08 15:57:36 +0200253 delaykey[i].len = delaykey[i].len > DELAY_STOP_STR_MAX_LENGTH ?
254 DELAY_STOP_STR_MAX_LENGTH : delaykey[i].len;
Simon Glass66ded172014-04-10 20:01:28 -0600255
256 presskey_max = presskey_max > delaykey[i].len ?
257 presskey_max : delaykey[i].len;
258
259 debug_bootkeys("%s key:<%s>\n",
260 delaykey[i].retry ? "delay" : "stop",
261 delaykey[i].str ? delaykey[i].str : "NULL");
262 }
263
264 /* In order to keep up with incoming data, check timeout only
265 * when catch up.
266 */
267 do {
268 if (tstc()) {
269 if (presskey_len < presskey_max) {
Heinrich Schuchardtc670aee2020-10-07 18:11:48 +0200270 presskey[presskey_len++] = getchar();
Simon Glass66ded172014-04-10 20:01:28 -0600271 } else {
272 for (i = 0; i < presskey_max - 1; i++)
273 presskey[i] = presskey[i + 1];
274
Heinrich Schuchardtc670aee2020-10-07 18:11:48 +0200275 presskey[i] = getchar();
Simon Glass66ded172014-04-10 20:01:28 -0600276 }
277 }
278
279 for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) {
280 if (delaykey[i].len > 0 &&
281 presskey_len >= delaykey[i].len &&
282 memcmp(presskey + presskey_len -
283 delaykey[i].len, delaykey[i].str,
284 delaykey[i].len) == 0) {
285 debug_bootkeys("got %skey\n",
286 delaykey[i].retry ? "delay" :
287 "stop");
288
Simon Glass66ded172014-04-10 20:01:28 -0600289 /* don't retry auto boot */
290 if (!delaykey[i].retry)
291 bootretry_dont_retry();
Simon Glass66ded172014-04-10 20:01:28 -0600292 abort = 1;
293 }
294 }
295 } while (!abort && get_ticks() <= etime);
296
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200297 return abort;
298}
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200299
Steffen Jaeckeld199c3a2021-07-08 15:57:38 +0200300/**
301 * flush_stdin() - drops all pending characters from stdin
302 */
303static void flush_stdin(void)
304{
305 while (tstc())
306 (void)getchar();
307}
308
Steffen Jaeckel33198742021-07-08 15:57:39 +0200309/**
310 * fallback_to_sha256() - check whether we should fall back to sha256
311 * password checking
312 *
313 * This checks for the environment variable `bootstopusesha256` in case
314 * sha256-fallback has been enabled via the config setting
315 * `AUTOBOOT_SHA256_FALLBACK`.
316 *
317 * @return `false` if we must not fall-back, `true` if plain sha256 should be tried
318 */
319static bool fallback_to_sha256(void)
320{
321 if (IS_ENABLED(CONFIG_AUTOBOOT_SHA256_FALLBACK))
322 return env_get_yesno("bootstopusesha256") == 1;
323 else if (IS_ENABLED(CONFIG_CRYPT_PW))
324 return false;
325 else
326 return true;
327}
328
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200329/***************************************************************************
330 * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
331 * returns: 0 - no key string, allow autoboot 1 - got key string, abort
332 */
Simon Glasse79e4b22019-07-20 20:51:19 -0600333static int abortboot_key_sequence(int bootdelay)
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200334{
335 int abort;
336 uint64_t etime = endtick(bootdelay);
337
Steffen Jaeckeld199c3a2021-07-08 15:57:38 +0200338 if (IS_ENABLED(CONFIG_AUTOBOOT_FLUSH_STDIN))
339 flush_stdin();
Stefan Roese8f0b1e22015-05-18 14:08:24 +0200340# ifdef CONFIG_AUTOBOOT_PROMPT
341 /*
342 * CONFIG_AUTOBOOT_PROMPT includes the %d for all boards.
343 * To print the bootdelay value upon bootup.
344 */
345 printf(CONFIG_AUTOBOOT_PROMPT, bootdelay);
346# endif
347
Steffen Jaeckel1a4a7782021-07-08 15:57:35 +0200348 if (IS_ENABLED(CONFIG_AUTOBOOT_ENCRYPTION)) {
Steffen Jaeckel33198742021-07-08 15:57:39 +0200349 if (IS_ENABLED(CONFIG_CRYPT_PW) && !fallback_to_sha256())
Steffen Jaeckel1a4a7782021-07-08 15:57:35 +0200350 abort = passwd_abort_crypt(etime);
351 else
352 abort = passwd_abort_sha256(etime);
353 } else {
Simon Glasse8c78052019-07-20 20:51:16 -0600354 abort = passwd_abort_key(etime);
Steffen Jaeckel1a4a7782021-07-08 15:57:35 +0200355 }
Simon Glass66ded172014-04-10 20:01:28 -0600356 if (!abort)
357 debug_bootkeys("key timeout\n");
358
Simon Glass66ded172014-04-10 20:01:28 -0600359 return abort;
360}
361
Simon Glasse79e4b22019-07-20 20:51:19 -0600362static int abortboot_single_key(int bootdelay)
Simon Glass66ded172014-04-10 20:01:28 -0600363{
364 int abort = 0;
365 unsigned long ts;
366
Masahiro Yamada46327392016-06-27 16:23:04 +0900367 printf("Hit any key to stop autoboot: %2d ", bootdelay);
Simon Glass66ded172014-04-10 20:01:28 -0600368
Simon Glass66ded172014-04-10 20:01:28 -0600369 /*
370 * Check if key already pressed
Simon Glass66ded172014-04-10 20:01:28 -0600371 */
Masahiro Yamada46327392016-06-27 16:23:04 +0900372 if (tstc()) { /* we got a key press */
Heinrich Schuchardtc670aee2020-10-07 18:11:48 +0200373 getchar(); /* consume input */
Masahiro Yamada46327392016-06-27 16:23:04 +0900374 puts("\b\b\b 0");
375 abort = 1; /* don't auto boot */
Simon Glass66ded172014-04-10 20:01:28 -0600376 }
Simon Glass66ded172014-04-10 20:01:28 -0600377
378 while ((bootdelay > 0) && (!abort)) {
379 --bootdelay;
380 /* delay 1000 ms */
381 ts = get_timer(0);
382 do {
383 if (tstc()) { /* we got a key press */
Simon Glassd915ad22019-07-20 20:51:23 -0600384 int key;
385
Simon Glass66ded172014-04-10 20:01:28 -0600386 abort = 1; /* don't auto boot */
387 bootdelay = 0; /* no more delay */
Heinrich Schuchardtc670aee2020-10-07 18:11:48 +0200388 key = getchar();/* consume input */
Da Xue5a87df82021-06-21 22:39:19 -0400389 if (IS_ENABLED(CONFIG_AUTOBOOT_USE_MENUKEY))
Simon Glassd915ad22019-07-20 20:51:23 -0600390 menukey = key;
Simon Glass66ded172014-04-10 20:01:28 -0600391 break;
392 }
393 udelay(10000);
394 } while (!abort && get_timer(ts) < 1000);
395
396 printf("\b\b\b%2d ", bootdelay);
397 }
398
399 putc('\n');
400
Simon Glass66ded172014-04-10 20:01:28 -0600401 return abort;
402}
Simon Glass66ded172014-04-10 20:01:28 -0600403
404static int abortboot(int bootdelay)
405{
Masahiro Yamada46327392016-06-27 16:23:04 +0900406 int abort = 0;
Masahiro Yamada09b9d9e2016-06-27 16:23:03 +0900407
Simon Glasse79e4b22019-07-20 20:51:19 -0600408 if (bootdelay >= 0) {
Simon Glasscb897002021-07-24 15:14:39 -0600409 if (autoboot_keyed())
Simon Glasse79e4b22019-07-20 20:51:19 -0600410 abort = abortboot_key_sequence(bootdelay);
411 else
412 abort = abortboot_single_key(bootdelay);
413 }
Masahiro Yamada09b9d9e2016-06-27 16:23:03 +0900414
Simon Glass42b4d142019-07-20 20:51:18 -0600415 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && abort)
Masahiro Yamada09b9d9e2016-06-27 16:23:03 +0900416 gd->flags &= ~GD_FLG_SILENT;
Masahiro Yamada09b9d9e2016-06-27 16:23:03 +0900417
418 return abort;
Simon Glass66ded172014-04-10 20:01:28 -0600419}
420
Simon Glass66ded172014-04-10 20:01:28 -0600421static void process_fdt_options(const void *blob)
422{
Simon Glass5fa3fd22019-07-20 20:51:27 -0600423#ifdef CONFIG_SYS_TEXT_BASE
Simon Glass66ded172014-04-10 20:01:28 -0600424 ulong addr;
425
426 /* Add an env variable to point to a kernel payload, if available */
427 addr = fdtdec_get_config_int(gd->fdt_blob, "kernel-offset", 0);
428 if (addr)
Simon Glass018f5302017-08-03 12:22:10 -0600429 env_set_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
Simon Glass66ded172014-04-10 20:01:28 -0600430
431 /* Add an env variable to point to a root disk, if available */
432 addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0);
433 if (addr)
Simon Glass018f5302017-08-03 12:22:10 -0600434 env_set_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
Simon Glass5fa3fd22019-07-20 20:51:27 -0600435#endif /* CONFIG_SYS_TEXT_BASE */
Simon Glassaffb2152014-04-10 20:01:35 -0600436}
Simon Glass66ded172014-04-10 20:01:28 -0600437
Simon Glassaffb2152014-04-10 20:01:35 -0600438const char *bootdelay_process(void)
Simon Glass66ded172014-04-10 20:01:28 -0600439{
Simon Glass66ded172014-04-10 20:01:28 -0600440 char *s;
441 int bootdelay;
Simon Glass66ded172014-04-10 20:01:28 -0600442
Lukasz Majewskibc8c4402018-05-02 16:10:53 +0200443 bootcount_inc();
Simon Glass66ded172014-04-10 20:01:28 -0600444
Simon Glass00caae62017-08-03 12:22:12 -0600445 s = env_get("bootdelay");
Simon Glass66ded172014-04-10 20:01:28 -0600446 bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
447
Simon Glass5fa3fd22019-07-20 20:51:27 -0600448 if (IS_ENABLED(CONFIG_OF_CONTROL))
449 bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay",
450 bootdelay);
Simon Glass66ded172014-04-10 20:01:28 -0600451
452 debug("### main_loop entered: bootdelay=%d\n\n", bootdelay);
453
Simon Glass5fa3fd22019-07-20 20:51:27 -0600454 if (IS_ENABLED(CONFIG_AUTOBOOT_MENU_SHOW))
455 bootdelay = menu_show(bootdelay);
Simon Glassb26440f2014-04-10 20:01:31 -0600456 bootretry_init_cmd_timeout();
Simon Glass66ded172014-04-10 20:01:28 -0600457
458#ifdef CONFIG_POST
459 if (gd->flags & GD_FLG_POSTFAIL) {
Simon Glass00caae62017-08-03 12:22:12 -0600460 s = env_get("failbootcmd");
Simon Glass66ded172014-04-10 20:01:28 -0600461 } else
462#endif /* CONFIG_POST */
Lukasz Majewskibc8c4402018-05-02 16:10:53 +0200463 if (bootcount_error())
Simon Glass00caae62017-08-03 12:22:12 -0600464 s = env_get("altbootcmd");
Lukasz Majewskibc8c4402018-05-02 16:10:53 +0200465 else
Simon Glass00caae62017-08-03 12:22:12 -0600466 s = env_get("bootcmd");
Simon Glass66ded172014-04-10 20:01:28 -0600467
Simon Glass5fa3fd22019-07-20 20:51:27 -0600468 if (IS_ENABLED(CONFIG_OF_CONTROL))
469 process_fdt_options(gd->fdt_blob);
Simon Glassaffb2152014-04-10 20:01:35 -0600470 stored_bootdelay = bootdelay;
Simon Glass66ded172014-04-10 20:01:28 -0600471
Simon Glassaffb2152014-04-10 20:01:35 -0600472 return s;
473}
Simon Glass66ded172014-04-10 20:01:28 -0600474
Simon Glassaffb2152014-04-10 20:01:35 -0600475void autoboot_command(const char *s)
476{
Simon Glass66ded172014-04-10 20:01:28 -0600477 debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
478
Heiko Schocher6ebe6b32020-10-07 08:06:54 +0200479 if (s && (stored_bootdelay == -2 ||
480 (stored_bootdelay != -1 && !abortboot(stored_bootdelay)))) {
Simon Glass5ec35ff2019-07-20 20:51:28 -0600481 bool lock;
482 int prev;
483
Simon Glasscb897002021-07-24 15:14:39 -0600484 lock = autoboot_keyed() &&
Simon Glass5ec35ff2019-07-20 20:51:28 -0600485 !IS_ENABLED(CONFIG_AUTOBOOT_KEYED_CTRLC);
486 if (lock)
487 prev = disable_ctrlc(1); /* disable Ctrl-C checking */
Simon Glass66ded172014-04-10 20:01:28 -0600488
489 run_command_list(s, -1, 0);
490
Simon Glass5ec35ff2019-07-20 20:51:28 -0600491 if (lock)
492 disable_ctrlc(prev); /* restore Ctrl-C checking */
Simon Glass66ded172014-04-10 20:01:28 -0600493 }
494
Da Xue5a87df82021-06-21 22:39:19 -0400495 if (IS_ENABLED(CONFIG_AUTOBOOT_USE_MENUKEY) &&
Simon Glassd915ad22019-07-20 20:51:23 -0600496 menukey == AUTOBOOT_MENUKEY) {
Simon Glass00caae62017-08-03 12:22:12 -0600497 s = env_get("menucmd");
Simon Glass66ded172014-04-10 20:01:28 -0600498 if (s)
499 run_command_list(s, -1, 0);
500 }
Simon Glasscb897002021-07-24 15:14:39 -0600501}