]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - common/autoboot.c
autoboot.c: Remove CONFIG_AUTOBOOT_STOP_STR2 and CONFIG_AUTOBOOT_DELAY_STR2
[karo-tx-uboot.git] / common / autoboot.c
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>
9 #include <autoboot.h>
10 #include <bootretry.h>
11 #include <cli.h>
12 #include <fdtdec.h>
13 #include <menu.h>
14 #include <post.h>
15
16 DECLARE_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
26 /* Stored value of bootdelay, used by autoboot_command() */
27 static int stored_bootdelay;
28
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)
34 static 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[] = {
44                 { .str = getenv("bootdelaykey"),  .retry = 1 },
45                 { .str = getenv("bootstopkey"),   .retry = 0 },
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
59         printf(CONFIG_AUTOBOOT_PROMPT);
60 #  endif
61
62 #  ifdef CONFIG_AUTOBOOT_DELAY_STR
63         if (delaykey[0].str == NULL)
64                 delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
65 #  endif
66 #  ifdef CONFIG_AUTOBOOT_STOP_STR
67         if (delaykey[1].str == NULL)
68                 delaykey[1].str = CONFIG_AUTOBOOT_STOP_STR;
69 #  endif
70
71         for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) {
72                 delaykey[i].len = delaykey[i].str == NULL ?
73                                     0 : strlen(delaykey[i].str);
74                 delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ?
75                                     MAX_DELAY_STOP_STR : delaykey[i].len;
76
77                 presskey_max = presskey_max > delaykey[i].len ?
78                                     presskey_max : delaykey[i].len;
79
80                 debug_bootkeys("%s key:<%s>\n",
81                                delaykey[i].retry ? "delay" : "stop",
82                                delaykey[i].str ? delaykey[i].str : "NULL");
83         }
84
85         /* In order to keep up with incoming data, check timeout only
86          * when catch up.
87          */
88         do {
89                 if (tstc()) {
90                         if (presskey_len < presskey_max) {
91                                 presskey[presskey_len++] = getc();
92                         } else {
93                                 for (i = 0; i < presskey_max - 1; i++)
94                                         presskey[i] = presskey[i + 1];
95
96                                 presskey[i] = getc();
97                         }
98                 }
99
100                 for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) {
101                         if (delaykey[i].len > 0 &&
102                             presskey_len >= delaykey[i].len &&
103                                 memcmp(presskey + presskey_len -
104                                         delaykey[i].len, delaykey[i].str,
105                                         delaykey[i].len) == 0) {
106                                         debug_bootkeys("got %skey\n",
107                                                 delaykey[i].retry ? "delay" :
108                                                 "stop");
109
110                                 /* don't retry auto boot */
111                                 if (!delaykey[i].retry)
112                                         bootretry_dont_retry();
113                                 abort = 1;
114                         }
115                 }
116         } while (!abort && get_ticks() <= etime);
117
118         if (!abort)
119                 debug_bootkeys("key timeout\n");
120
121 #ifdef CONFIG_SILENT_CONSOLE
122         if (abort)
123                 gd->flags &= ~GD_FLG_SILENT;
124 #endif
125
126         return abort;
127 }
128
129 # else  /* !defined(CONFIG_AUTOBOOT_KEYED) */
130
131 #ifdef CONFIG_MENUKEY
132 static int menukey;
133 #endif
134
135 static int abortboot_normal(int bootdelay)
136 {
137         int abort = 0;
138         unsigned long ts;
139
140 #ifdef CONFIG_MENUPROMPT
141         printf(CONFIG_MENUPROMPT);
142 #else
143         if (bootdelay >= 0)
144                 printf("Hit any key to stop autoboot: %2d ", bootdelay);
145 #endif
146
147 #if defined CONFIG_ZERO_BOOTDELAY_CHECK
148         /*
149          * Check if key already pressed
150          * Don't check if bootdelay < 0
151          */
152         if (bootdelay >= 0) {
153                 if (tstc()) {   /* we got a key press   */
154                         (void) getc();  /* consume input        */
155                         puts("\b\b\b 0");
156                         abort = 1;      /* don't auto boot      */
157                 }
158         }
159 #endif
160
161         while ((bootdelay > 0) && (!abort)) {
162                 --bootdelay;
163                 /* delay 1000 ms */
164                 ts = get_timer(0);
165                 do {
166                         if (tstc()) {   /* we got a key press   */
167                                 abort  = 1;     /* don't auto boot      */
168                                 bootdelay = 0;  /* no more delay        */
169 # ifdef CONFIG_MENUKEY
170                                 menukey = getc();
171 # else
172                                 (void) getc();  /* consume input        */
173 # endif
174                                 break;
175                         }
176                         udelay(10000);
177                 } while (!abort && get_timer(ts) < 1000);
178
179                 printf("\b\b\b%2d ", bootdelay);
180         }
181
182         putc('\n');
183
184 #ifdef CONFIG_SILENT_CONSOLE
185         if (abort)
186                 gd->flags &= ~GD_FLG_SILENT;
187 #endif
188
189         return abort;
190 }
191 # endif /* CONFIG_AUTOBOOT_KEYED */
192
193 static int abortboot(int bootdelay)
194 {
195 #ifdef CONFIG_AUTOBOOT_KEYED
196         return abortboot_keyed(bootdelay);
197 #else
198         return abortboot_normal(bootdelay);
199 #endif
200 }
201
202 static void process_fdt_options(const void *blob)
203 {
204 #if defined(CONFIG_OF_CONTROL)
205         ulong addr;
206
207         /* Add an env variable to point to a kernel payload, if available */
208         addr = fdtdec_get_config_int(gd->fdt_blob, "kernel-offset", 0);
209         if (addr)
210                 setenv_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
211
212         /* Add an env variable to point to a root disk, if available */
213         addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0);
214         if (addr)
215                 setenv_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
216 #endif /* CONFIG_OF_CONTROL */
217 }
218
219 const char *bootdelay_process(void)
220 {
221         char *s;
222         int bootdelay;
223 #ifdef CONFIG_BOOTCOUNT_LIMIT
224         unsigned long bootcount = 0;
225         unsigned long bootlimit = 0;
226 #endif /* CONFIG_BOOTCOUNT_LIMIT */
227
228 #ifdef CONFIG_BOOTCOUNT_LIMIT
229         bootcount = bootcount_load();
230         bootcount++;
231         bootcount_store(bootcount);
232         setenv_ulong("bootcount", bootcount);
233         bootlimit = getenv_ulong("bootlimit", 10, 0);
234 #endif /* CONFIG_BOOTCOUNT_LIMIT */
235
236         s = getenv("bootdelay");
237         bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
238
239 #ifdef CONFIG_OF_CONTROL
240         bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay",
241                         bootdelay);
242 #endif
243
244         debug("### main_loop entered: bootdelay=%d\n\n", bootdelay);
245
246 #if defined(CONFIG_MENU_SHOW)
247         bootdelay = menu_show(bootdelay);
248 #endif
249         bootretry_init_cmd_timeout();
250
251 #ifdef CONFIG_POST
252         if (gd->flags & GD_FLG_POSTFAIL) {
253                 s = getenv("failbootcmd");
254         } else
255 #endif /* CONFIG_POST */
256 #ifdef CONFIG_BOOTCOUNT_LIMIT
257         if (bootlimit && (bootcount > bootlimit)) {
258                 printf("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n",
259                        (unsigned)bootlimit);
260                 s = getenv("altbootcmd");
261         } else
262 #endif /* CONFIG_BOOTCOUNT_LIMIT */
263                 s = getenv("bootcmd");
264
265         process_fdt_options(gd->fdt_blob);
266         stored_bootdelay = bootdelay;
267
268         return s;
269 }
270
271 void autoboot_command(const char *s)
272 {
273         debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
274
275         if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
276 #if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
277                 int prev = disable_ctrlc(1);    /* disable Control C checking */
278 #endif
279
280                 run_command_list(s, -1, 0);
281
282 #if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC)
283                 disable_ctrlc(prev);    /* restore Control C checking */
284 #endif
285         }
286
287 #ifdef CONFIG_MENUKEY
288         if (menukey == CONFIG_MENUKEY) {
289                 s = getenv("menucmd");
290                 if (s)
291                         run_command_list(s, -1, 0);
292         }
293 #endif /* CONFIG_MENUKEY */
294 }