1
2
3
4
5
6
7#include <common.h>
8#include <autoboot.h>
9#include <bootretry.h>
10#include <cli.h>
11#include <command.h>
12#include <console.h>
13#include <env.h>
14#include <fdtdec.h>
15#include <hash.h>
16#include <log.h>
17#include <malloc.h>
18#include <memalign.h>
19#include <menu.h>
20#include <post.h>
21#include <time.h>
22#include <asm/global_data.h>
23#include <linux/delay.h>
24#include <u-boot/sha256.h>
25#include <bootcount.h>
26#include <crypt.h>
27
28DECLARE_GLOBAL_DATA_PTR;
29
30#define DELAY_STOP_STR_MAX_LENGTH 64
31
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
38
39static int stored_bootdelay;
40static int menukey;
41
42#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 ""
47#endif
48
49#ifdef CONFIG_AUTOBOOT_USE_MENUKEY
50#define AUTOBOOT_MENUKEY CONFIG_AUTOBOOT_MENUKEY
51#else
52#define AUTOBOOT_MENUKEY 0
53#endif
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73static int passwd_abort_crypt(uint64_t etime)
74{
75 const char *crypt_env_str = env_get("bootstopkeycrypt");
76 char presskey[DELAY_STOP_STR_MAX_LENGTH];
77 u_int presskey_len = 0;
78 int abort = 0;
79 int never_timeout = 0;
80 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
89 do {
90 if (tstc()) {
91
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')) {
99 if (IS_ENABLED(CONFIG_AUTOBOOT_NEVER_TIMEOUT) &&
100 !presskey_len) {
101 never_timeout = 1;
102 continue;
103 }
104 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
112 break;
113 } else {
114 presskey_len++;
115 }
116 }
117 } while (never_timeout || get_ticks() <= etime);
118
119 return abort;
120}
121
122
123
124
125
126
127
128static 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
139
140
141
142
143
144
145
146
147static int passwd_abort_sha256(uint64_t etime)
148{
149 const char *sha_env_str = env_get("bootstopkeysha256");
150 u8 sha_env[SHA256_SUM_LEN];
151 u8 *sha;
152 char *presskey;
153 char *c;
154 const char *algo_name = "sha256";
155 u_int presskey_len = 0;
156 int abort = 0;
157 int size = sizeof(sha);
158 int ret;
159
160 if (sha_env_str == NULL)
161 sha_env_str = CONFIG_AUTOBOOT_STOP_STR_SHA256;
162
163 presskey = malloc_cache_aligned(DELAY_STOP_STR_MAX_LENGTH);
164 c = strstr(sha_env_str, ":");
165 if (c && (c - sha_env_str < DELAY_STOP_STR_MAX_LENGTH)) {
166
167 memcpy(presskey, sha_env_str, c - sha_env_str);
168 presskey_len = c - sha_env_str;
169 sha_env_str = c + 1;
170 }
171
172
173
174
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
182 sha = malloc_cache_aligned(SHA256_SUM_LEN);
183 size = SHA256_SUM_LEN;
184
185
186
187
188
189 do {
190 if (tstc()) {
191
192 if (presskey_len >= DELAY_STOP_STR_MAX_LENGTH) {
193 free(presskey);
194 free(sha);
195 return 0;
196 }
197
198 presskey[presskey_len++] = getchar();
199
200
201 hash_block(algo_name, (const void *)presskey,
202 presskey_len, sha, &size);
203
204
205 if (slow_equals(sha, sha_env, SHA256_SUM_LEN))
206 abort = 1;
207 }
208 } while (!abort && get_ticks() <= etime);
209
210 free(presskey);
211 free(sha);
212 return abort;
213}
214
215
216
217
218
219
220
221
222
223static int passwd_abort_key(uint64_t etime)
224{
225 int abort = 0;
226 struct {
227 char *str;
228 u_int len;
229 int retry;
230 }
231 delaykey[] = {
232 { .str = env_get("bootdelaykey"), .retry = 1 },
233 { .str = env_get("bootstopkey"), .retry = 0 },
234 };
235
236 char presskey[DELAY_STOP_STR_MAX_LENGTH];
237 int presskey_len = 0;
238 int presskey_max = 0;
239 int i;
240
241# ifdef CONFIG_AUTOBOOT_DELAY_STR
242 if (delaykey[0].str == NULL)
243 delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
244# endif
245# ifdef CONFIG_AUTOBOOT_STOP_STR
246 if (delaykey[1].str == NULL)
247 delaykey[1].str = CONFIG_AUTOBOOT_STOP_STR;
248# 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);
253 delaykey[i].len = delaykey[i].len > DELAY_STOP_STR_MAX_LENGTH ?
254 DELAY_STOP_STR_MAX_LENGTH : delaykey[i].len;
255
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
265
266
267 do {
268 if (tstc()) {
269 if (presskey_len < presskey_max) {
270 presskey[presskey_len++] = getchar();
271 } else {
272 for (i = 0; i < presskey_max - 1; i++)
273 presskey[i] = presskey[i + 1];
274
275 presskey[i] = getchar();
276 }
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
289
290 if (!delaykey[i].retry)
291 bootretry_dont_retry();
292 abort = 1;
293 }
294 }
295 } while (!abort && get_ticks() <= etime);
296
297 return abort;
298}
299
300
301
302
303static void flush_stdin(void)
304{
305 while (tstc())
306 (void)getchar();
307}
308
309
310
311
312
313
314
315
316
317
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
329
330
331
332
333static int abortboot_key_sequence(int bootdelay)
334{
335 int abort;
336 uint64_t etime = endtick(bootdelay);
337
338 if (IS_ENABLED(CONFIG_AUTOBOOT_FLUSH_STDIN))
339 flush_stdin();
340# ifdef CONFIG_AUTOBOOT_PROMPT
341
342
343
344
345 printf(CONFIG_AUTOBOOT_PROMPT, bootdelay);
346# endif
347
348 if (IS_ENABLED(CONFIG_AUTOBOOT_ENCRYPTION)) {
349 if (IS_ENABLED(CONFIG_CRYPT_PW) && !fallback_to_sha256())
350 abort = passwd_abort_crypt(etime);
351 else
352 abort = passwd_abort_sha256(etime);
353 } else {
354 abort = passwd_abort_key(etime);
355 }
356 if (!abort)
357 debug_bootkeys("key timeout\n");
358
359 return abort;
360}
361
362static int abortboot_single_key(int bootdelay)
363{
364 int abort = 0;
365 unsigned long ts;
366
367 printf("Hit any key to stop autoboot: %2d ", bootdelay);
368
369
370
371
372 if (tstc()) {
373 getchar();
374 puts("\b\b\b 0");
375 abort = 1;
376 }
377
378 while ((bootdelay > 0) && (!abort)) {
379 --bootdelay;
380
381 ts = get_timer(0);
382 do {
383 if (tstc()) {
384 int key;
385
386 abort = 1;
387 bootdelay = 0;
388 key = getchar();
389 if (IS_ENABLED(CONFIG_AUTOBOOT_USE_MENUKEY))
390 menukey = key;
391 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
401 return abort;
402}
403
404static int abortboot(int bootdelay)
405{
406 int abort = 0;
407
408 if (bootdelay >= 0) {
409 if (autoboot_keyed())
410 abort = abortboot_key_sequence(bootdelay);
411 else
412 abort = abortboot_single_key(bootdelay);
413 }
414
415 if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && abort)
416 gd->flags &= ~GD_FLG_SILENT;
417
418 return abort;
419}
420
421static void process_fdt_options(const void *blob)
422{
423#ifdef CONFIG_SYS_TEXT_BASE
424 ulong addr;
425
426
427 addr = fdtdec_get_config_int(gd->fdt_blob, "kernel-offset", 0);
428 if (addr)
429 env_set_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
430
431
432 addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0);
433 if (addr)
434 env_set_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
435#endif
436}
437
438const char *bootdelay_process(void)
439{
440 char *s;
441 int bootdelay;
442
443 bootcount_inc();
444
445 s = env_get("bootdelay");
446 bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
447
448 if (IS_ENABLED(CONFIG_OF_CONTROL))
449 bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay",
450 bootdelay);
451
452 debug("### main_loop entered: bootdelay=%d\n\n", bootdelay);
453
454 if (IS_ENABLED(CONFIG_AUTOBOOT_MENU_SHOW))
455 bootdelay = menu_show(bootdelay);
456 bootretry_init_cmd_timeout();
457
458#ifdef CONFIG_POST
459 if (gd->flags & GD_FLG_POSTFAIL) {
460 s = env_get("failbootcmd");
461 } else
462#endif
463 if (bootcount_error())
464 s = env_get("altbootcmd");
465 else
466 s = env_get("bootcmd");
467
468 if (IS_ENABLED(CONFIG_OF_CONTROL))
469 process_fdt_options(gd->fdt_blob);
470 stored_bootdelay = bootdelay;
471
472 return s;
473}
474
475void autoboot_command(const char *s)
476{
477 debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
478
479 if (s && (stored_bootdelay == -2 ||
480 (stored_bootdelay != -1 && !abortboot(stored_bootdelay)))) {
481 bool lock;
482 int prev;
483
484 lock = autoboot_keyed() &&
485 !IS_ENABLED(CONFIG_AUTOBOOT_KEYED_CTRLC);
486 if (lock)
487 prev = disable_ctrlc(1);
488
489 run_command_list(s, -1, 0);
490
491 if (lock)
492 disable_ctrlc(prev);
493 }
494
495 if (IS_ENABLED(CONFIG_AUTOBOOT_USE_MENUKEY) &&
496 menukey == AUTOBOOT_MENUKEY) {
497 s = env_get("menucmd");
498 if (s)
499 run_command_list(s, -1, 0);
500 }
501}
502