]> git.ipfire.org Git - people/ms/u-boot.git/blame - common/autoboot.c
autoboot.c: Move config options to Kconfig
[people/ms/u-boot.git] / common / autoboot.c
CommitLineData
66ded17d
SG
1/*
2 * (C) Copyright 2000
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <common.h>
39e1230e 9#include <autoboot.h>
0098e179 10#include <bootretry.h>
66ded17d
SG
11#include <cli.h>
12#include <fdtdec.h>
13#include <menu.h>
14#include <post.h>
15
16DECLARE_GLOBAL_DATA_PTR;
17
18#define MAX_DELAY_STOP_STR 32
19
20#ifndef DEBUG_BOOTKEYS
21#define DEBUG_BOOTKEYS 0
22#endif
23#define debug_bootkeys(fmt, args...) \
24 debug_cond(DEBUG_BOOTKEYS, fmt, ##args)
25
affb2156
SG
26/* Stored value of bootdelay, used by autoboot_command() */
27static int stored_bootdelay;
28
66ded17d
SG
29/***************************************************************************
30 * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
31 * returns: 0 - no key string, allow autoboot 1 - got key string, abort
32 */
33# if defined(CONFIG_AUTOBOOT_KEYED)
34static int abortboot_keyed(int bootdelay)
35{
36 int abort = 0;
37 uint64_t etime = endtick(bootdelay);
38 struct {
39 char *str;
40 u_int len;
41 int retry;
42 }
43 delaykey[] = {
9e546ee9 44 { .str = getenv("bootdelaykey"), .retry = 1 },
9e546ee9 45 { .str = getenv("bootstopkey"), .retry = 0 },
66ded17d
SG
46 };
47
48 char presskey[MAX_DELAY_STOP_STR];
49 u_int presskey_len = 0;
50 u_int presskey_max = 0;
51 u_int i;
52
53#ifndef CONFIG_ZERO_BOOTDELAY_CHECK
54 if (bootdelay == 0)
55 return 0;
56#endif
57
58# ifdef CONFIG_AUTOBOOT_PROMPT
d126e016
SR
59 /*
60 * CONFIG_AUTOBOOT_PROMPT includes the %d for all boards.
61 * To print the bootdelay value upon bootup.
62 */
63 printf(CONFIG_AUTOBOOT_PROMPT, bootdelay);
66ded17d
SG
64# endif
65
66# ifdef CONFIG_AUTOBOOT_DELAY_STR
67 if (delaykey[0].str == NULL)
68 delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
69# endif
66ded17d 70# ifdef CONFIG_AUTOBOOT_STOP_STR
2d908fa0
SR
71 if (delaykey[1].str == NULL)
72 delaykey[1].str = CONFIG_AUTOBOOT_STOP_STR;
66ded17d
SG
73# endif
74
75 for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) {
76 delaykey[i].len = delaykey[i].str == NULL ?
77 0 : strlen(delaykey[i].str);
78 delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ?
79 MAX_DELAY_STOP_STR : delaykey[i].len;
80
81 presskey_max = presskey_max > delaykey[i].len ?
82 presskey_max : delaykey[i].len;
83
84 debug_bootkeys("%s key:<%s>\n",
85 delaykey[i].retry ? "delay" : "stop",
86 delaykey[i].str ? delaykey[i].str : "NULL");
87 }
88
89 /* In order to keep up with incoming data, check timeout only
90 * when catch up.
91 */
92 do {
93 if (tstc()) {
94 if (presskey_len < presskey_max) {
95 presskey[presskey_len++] = getc();
96 } else {
97 for (i = 0; i < presskey_max - 1; i++)
98 presskey[i] = presskey[i + 1];
99
100 presskey[i] = getc();
101 }
102 }
103
104 for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) {
105 if (delaykey[i].len > 0 &&
106 presskey_len >= delaykey[i].len &&
107 memcmp(presskey + presskey_len -
108 delaykey[i].len, delaykey[i].str,
109 delaykey[i].len) == 0) {
110 debug_bootkeys("got %skey\n",
111 delaykey[i].retry ? "delay" :
112 "stop");
113
66ded17d
SG
114 /* don't retry auto boot */
115 if (!delaykey[i].retry)
116 bootretry_dont_retry();
66ded17d
SG
117 abort = 1;
118 }
119 }
120 } while (!abort && get_ticks() <= etime);
121
122 if (!abort)
123 debug_bootkeys("key timeout\n");
124
125#ifdef CONFIG_SILENT_CONSOLE
126 if (abort)
127 gd->flags &= ~GD_FLG_SILENT;
128#endif
129
130 return abort;
131}
132
133# else /* !defined(CONFIG_AUTOBOOT_KEYED) */
134
135#ifdef CONFIG_MENUKEY
136static int menukey;
137#endif
138
139static int abortboot_normal(int bootdelay)
140{
141 int abort = 0;
142 unsigned long ts;
143
144#ifdef CONFIG_MENUPROMPT
145 printf(CONFIG_MENUPROMPT);
146#else
147 if (bootdelay >= 0)
148 printf("Hit any key to stop autoboot: %2d ", bootdelay);
149#endif
150
151#if defined CONFIG_ZERO_BOOTDELAY_CHECK
152 /*
153 * Check if key already pressed
154 * Don't check if bootdelay < 0
155 */
156 if (bootdelay >= 0) {
157 if (tstc()) { /* we got a key press */
158 (void) getc(); /* consume input */
159 puts("\b\b\b 0");
160 abort = 1; /* don't auto boot */
161 }
162 }
163#endif
164
165 while ((bootdelay > 0) && (!abort)) {
166 --bootdelay;
167 /* delay 1000 ms */
168 ts = get_timer(0);
169 do {
170 if (tstc()) { /* we got a key press */
171 abort = 1; /* don't auto boot */
172 bootdelay = 0; /* no more delay */
173# ifdef CONFIG_MENUKEY
174 menukey = getc();
175# else
176 (void) getc(); /* consume input */
177# endif
178 break;
179 }
180 udelay(10000);
181 } while (!abort && get_timer(ts) < 1000);
182
183 printf("\b\b\b%2d ", bootdelay);
184 }
185
186 putc('\n');
187
188#ifdef CONFIG_SILENT_CONSOLE
189 if (abort)
190 gd->flags &= ~GD_FLG_SILENT;
191#endif
192
193 return abort;
194}
195# endif /* CONFIG_AUTOBOOT_KEYED */
196
197static int abortboot(int bootdelay)
198{
199#ifdef CONFIG_AUTOBOOT_KEYED
200 return abortboot_keyed(bootdelay);
201#else
202 return abortboot_normal(bootdelay);
203#endif
204}
205
66ded17d
SG
206static void process_fdt_options(const void *blob)
207{
affb2156 208#if defined(CONFIG_OF_CONTROL)
66ded17d
SG
209 ulong addr;
210
211 /* Add an env variable to point to a kernel payload, if available */
212 addr = fdtdec_get_config_int(gd->fdt_blob, "kernel-offset", 0);
213 if (addr)
214 setenv_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
215
216 /* Add an env variable to point to a root disk, if available */
217 addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0);
218 if (addr)
219 setenv_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
66ded17d 220#endif /* CONFIG_OF_CONTROL */
affb2156 221}
66ded17d 222
affb2156 223const char *bootdelay_process(void)
66ded17d 224{
66ded17d
SG
225 char *s;
226 int bootdelay;
227#ifdef CONFIG_BOOTCOUNT_LIMIT
228 unsigned long bootcount = 0;
229 unsigned long bootlimit = 0;
230#endif /* CONFIG_BOOTCOUNT_LIMIT */
231
232#ifdef CONFIG_BOOTCOUNT_LIMIT
233 bootcount = bootcount_load();
234 bootcount++;
235 bootcount_store(bootcount);
236 setenv_ulong("bootcount", bootcount);
237 bootlimit = getenv_ulong("bootlimit", 10, 0);
238#endif /* CONFIG_BOOTCOUNT_LIMIT */
239
240 s = getenv("bootdelay");
241 bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
242
243#ifdef CONFIG_OF_CONTROL
244 bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay",
245 bootdelay);
246#endif
247
248 debug("### main_loop entered: bootdelay=%d\n\n", bootdelay);
249
250#if defined(CONFIG_MENU_SHOW)
251 bootdelay = menu_show(bootdelay);
252#endif
b26440f1 253 bootretry_init_cmd_timeout();
66ded17d
SG
254
255#ifdef CONFIG_POST
256 if (gd->flags & GD_FLG_POSTFAIL) {
257 s = getenv("failbootcmd");
258 } else
259#endif /* CONFIG_POST */
260#ifdef CONFIG_BOOTCOUNT_LIMIT
261 if (bootlimit && (bootcount > bootlimit)) {
262 printf("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
263 (unsigned)bootlimit);
264 s = getenv("altbootcmd");
265 } else
266#endif /* CONFIG_BOOTCOUNT_LIMIT */
267 s = getenv("bootcmd");
66ded17d
SG
268
269 process_fdt_options(gd->fdt_blob);
affb2156 270 stored_bootdelay = bootdelay;
66ded17d 271
affb2156
SG
272 return s;
273}
66ded17d 274
affb2156
SG
275void autoboot_command(const char *s)
276{
66ded17d
SG
277 debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
278
affb2156 279 if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
66ded17d
SG
280#if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
281 int prev = disable_ctrlc(1); /* disable Control C checking */
282#endif
283
284 run_command_list(s, -1, 0);
285
286#if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
287 disable_ctrlc(prev); /* restore Control C checking */
288#endif
289 }
290
291#ifdef CONFIG_MENUKEY
292 if (menukey == CONFIG_MENUKEY) {
293 s = getenv("menucmd");
294 if (s)
295 run_command_list(s, -1, 0);
296 }
297#endif /* CONFIG_MENUKEY */
298}