Blame view

common/autoboot.c 8.91 KB
66ded17df   Simon Glass   Move autoboot cod...
1
2
3
4
5
6
7
8
  /*
   * (C) Copyright 2000
   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   *
   * SPDX-License-Identifier:	GPL-2.0+
   */
  
  #include <common.h>
39e1230ed   Jeroen Hofstee   autoboot: add its...
9
  #include <autoboot.h>
0098e179e   Simon Glass   Move bootretry co...
10
  #include <bootretry.h>
66ded17df   Simon Glass   Move autoboot cod...
11
  #include <cli.h>
24b852a7a   Simon Glass   Move console defi...
12
  #include <console.h>
66ded17df   Simon Glass   Move autoboot cod...
13
14
15
  #include <fdtdec.h>
  #include <menu.h>
  #include <post.h>
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
16
  #include <u-boot/sha256.h>
66ded17df   Simon Glass   Move autoboot cod...
17

a92c4806b   Ye Li   MLK-18157 mfgtool...
18
19
20
  #ifdef is_boot_from_usb
  #include <environment.h>
  #endif
66ded17df   Simon Glass   Move autoboot cod...
21
22
23
24
25
26
27
28
29
  DECLARE_GLOBAL_DATA_PTR;
  
  #define MAX_DELAY_STOP_STR 32
  
  #ifndef DEBUG_BOOTKEYS
  #define DEBUG_BOOTKEYS 0
  #endif
  #define debug_bootkeys(fmt, args...)		\
  	debug_cond(DEBUG_BOOTKEYS, fmt, ##args)
affb21562   Simon Glass   main: Make the ex...
30
31
  /* Stored value of bootdelay, used by autoboot_command() */
  static int stored_bootdelay;
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
32
33
34
35
36
37
38
39
  #if defined(CONFIG_AUTOBOOT_KEYED)
  #if defined(CONFIG_AUTOBOOT_STOP_STR_SHA256)
  
  /*
   * Use a "constant-length" time compare function for this
   * hash compare:
   *
   * https://crackstation.net/hashing-security.htm
66ded17df   Simon Glass   Move autoboot cod...
40
   */
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
41
42
43
44
45
46
47
48
49
50
51
52
53
  static int slow_equals(u8 *a, u8 *b, int len)
  {
  	int diff = 0;
  	int i;
  
  	for (i = 0; i < len; i++)
  		diff |= a[i] ^ b[i];
  
  	return diff == 0;
  }
  
  static int passwd_abort(uint64_t etime)
  {
00caae6d4   Simon Glass   env: Rename geten...
54
  	const char *sha_env_str = env_get("bootstopkeysha256");
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
55
56
57
58
59
60
  	u8 sha_env[SHA256_SUM_LEN];
  	u8 sha[SHA256_SUM_LEN];
  	char presskey[MAX_DELAY_STOP_STR];
  	const char *algo_name = "sha256";
  	u_int presskey_len = 0;
  	int abort = 0;
2d06fd839   Martin Etnestad   Initialize SHA bu...
61
  	int size = sizeof(sha);
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  	int ret;
  
  	if (sha_env_str == NULL)
  		sha_env_str = CONFIG_AUTOBOOT_STOP_STR_SHA256;
  
  	/*
  	 * Generate the binary value from the environment hash value
  	 * so that we can compare this value with the computed hash
  	 * from the user input
  	 */
  	ret = hash_parse_string(algo_name, sha_env_str, sha_env);
  	if (ret) {
  		printf("Hash %s not supported!
  ", algo_name);
  		return 0;
  	}
  
  	/*
  	 * We don't know how long the stop-string is, so we need to
  	 * generate the sha256 hash upon each input character and
  	 * compare the value with the one saved in the environment
  	 */
  	do {
  		if (tstc()) {
  			/* Check for input string overflow */
  			if (presskey_len >= MAX_DELAY_STOP_STR)
  				return 0;
  
  			presskey[presskey_len++] = getc();
  
  			/* Calculate sha256 upon each new char */
  			hash_block(algo_name, (const void *)presskey,
  				   presskey_len, sha, &size);
  
  			/* And check if sha matches saved value in env */
  			if (slow_equals(sha, sha_env, SHA256_SUM_LEN))
  				abort = 1;
  		}
  	} while (!abort && get_ticks() <= etime);
  
  	return abort;
  }
  #else
  static int passwd_abort(uint64_t etime)
66ded17df   Simon Glass   Move autoboot cod...
106
107
  {
  	int abort = 0;
66ded17df   Simon Glass   Move autoboot cod...
108
109
110
111
112
113
  	struct {
  		char *str;
  		u_int len;
  		int retry;
  	}
  	delaykey[] = {
00caae6d4   Simon Glass   env: Rename geten...
114
115
  		{ .str = env_get("bootdelaykey"),  .retry = 1 },
  		{ .str = env_get("bootstopkey"),   .retry = 0 },
66ded17df   Simon Glass   Move autoboot cod...
116
117
118
119
120
121
  	};
  
  	char presskey[MAX_DELAY_STOP_STR];
  	u_int presskey_len = 0;
  	u_int presskey_max = 0;
  	u_int i;
66ded17df   Simon Glass   Move autoboot cod...
122
123
124
125
  #  ifdef CONFIG_AUTOBOOT_DELAY_STR
  	if (delaykey[0].str == NULL)
  		delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
  #  endif
66ded17df   Simon Glass   Move autoboot cod...
126
  #  ifdef CONFIG_AUTOBOOT_STOP_STR
2d908fa08   Stefan Roese   autoboot.c: Remov...
127
128
  	if (delaykey[1].str == NULL)
  		delaykey[1].str = CONFIG_AUTOBOOT_STOP_STR;
66ded17df   Simon Glass   Move autoboot cod...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  #  endif
  
  	for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) {
  		delaykey[i].len = delaykey[i].str == NULL ?
  				    0 : strlen(delaykey[i].str);
  		delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ?
  				    MAX_DELAY_STOP_STR : delaykey[i].len;
  
  		presskey_max = presskey_max > delaykey[i].len ?
  				    presskey_max : delaykey[i].len;
  
  		debug_bootkeys("%s key:<%s>
  ",
  			       delaykey[i].retry ? "delay" : "stop",
  			       delaykey[i].str ? delaykey[i].str : "NULL");
  	}
  
  	/* In order to keep up with incoming data, check timeout only
  	 * when catch up.
  	 */
  	do {
  		if (tstc()) {
  			if (presskey_len < presskey_max) {
  				presskey[presskey_len++] = getc();
  			} else {
  				for (i = 0; i < presskey_max - 1; i++)
  					presskey[i] = presskey[i + 1];
  
  				presskey[i] = getc();
  			}
  		}
  
  		for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) {
  			if (delaykey[i].len > 0 &&
  			    presskey_len >= delaykey[i].len &&
  				memcmp(presskey + presskey_len -
  					delaykey[i].len, delaykey[i].str,
  					delaykey[i].len) == 0) {
  					debug_bootkeys("got %skey
  ",
  						delaykey[i].retry ? "delay" :
  						"stop");
66ded17df   Simon Glass   Move autoboot cod...
171
172
173
  				/* don't retry auto boot */
  				if (!delaykey[i].retry)
  					bootretry_dont_retry();
66ded17df   Simon Glass   Move autoboot cod...
174
175
176
177
  				abort = 1;
  			}
  		}
  	} while (!abort && get_ticks() <= etime);
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
178
179
180
181
182
183
184
185
  	return abort;
  }
  #endif
  
  /***************************************************************************
   * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
   * returns: 0 -  no key string, allow autoboot 1 - got key string, abort
   */
d8da8298a   Masahiro Yamada   autoboot: rename ...
186
  static int __abortboot(int bootdelay)
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
187
188
189
  {
  	int abort;
  	uint64_t etime = endtick(bootdelay);
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
190
191
192
193
194
195
196
197
198
  #  ifdef CONFIG_AUTOBOOT_PROMPT
  	/*
  	 * CONFIG_AUTOBOOT_PROMPT includes the %d for all boards.
  	 * To print the bootdelay value upon bootup.
  	 */
  	printf(CONFIG_AUTOBOOT_PROMPT, bootdelay);
  #  endif
  
  	abort = passwd_abort(etime);
66ded17df   Simon Glass   Move autoboot cod...
199
200
201
  	if (!abort)
  		debug_bootkeys("key timeout
  ");
66ded17df   Simon Glass   Move autoboot cod...
202
203
204
205
206
207
208
209
  	return abort;
  }
  
  # else	/* !defined(CONFIG_AUTOBOOT_KEYED) */
  
  #ifdef CONFIG_MENUKEY
  static int menukey;
  #endif
d8da8298a   Masahiro Yamada   autoboot: rename ...
210
  static int __abortboot(int bootdelay)
66ded17df   Simon Glass   Move autoboot cod...
211
212
213
214
215
216
217
  {
  	int abort = 0;
  	unsigned long ts;
  
  #ifdef CONFIG_MENUPROMPT
  	printf(CONFIG_MENUPROMPT);
  #else
463273920   Masahiro Yamada   autoboot: move bo...
218
  	printf("Hit any key to stop autoboot: %2d ", bootdelay);
66ded17df   Simon Glass   Move autoboot cod...
219
  #endif
66ded17df   Simon Glass   Move autoboot cod...
220
221
  	/*
  	 * Check if key already pressed
66ded17df   Simon Glass   Move autoboot cod...
222
  	 */
463273920   Masahiro Yamada   autoboot: move bo...
223
224
225
226
  	if (tstc()) {	/* we got a key press	*/
  		(void) getc();  /* consume input	*/
  		puts("\b\b\b 0");
  		abort = 1;	/* don't auto boot	*/
66ded17df   Simon Glass   Move autoboot cod...
227
  	}
66ded17df   Simon Glass   Move autoboot cod...
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
  
  	while ((bootdelay > 0) && (!abort)) {
  		--bootdelay;
  		/* delay 1000 ms */
  		ts = get_timer(0);
  		do {
  			if (tstc()) {	/* we got a key press	*/
  				abort  = 1;	/* don't auto boot	*/
  				bootdelay = 0;	/* no more delay	*/
  # ifdef CONFIG_MENUKEY
  				menukey = getc();
  # else
  				(void) getc();  /* consume input	*/
  # endif
  				break;
  			}
  			udelay(10000);
  		} while (!abort && get_timer(ts) < 1000);
  
  		printf("\b\b\b%2d ", bootdelay);
  	}
  
  	putc('
  ');
66ded17df   Simon Glass   Move autoboot cod...
252
253
254
255
256
257
  	return abort;
  }
  # endif	/* CONFIG_AUTOBOOT_KEYED */
  
  static int abortboot(int bootdelay)
  {
463273920   Masahiro Yamada   autoboot: move bo...
258
  	int abort = 0;
09b9d9e55   Masahiro Yamada   autoboot: move CO...
259

463273920   Masahiro Yamada   autoboot: move bo...
260
261
  	if (bootdelay >= 0)
  		abort = __abortboot(bootdelay);
09b9d9e55   Masahiro Yamada   autoboot: move CO...
262
263
264
265
266
267
268
  
  #ifdef CONFIG_SILENT_CONSOLE
  	if (abort)
  		gd->flags &= ~GD_FLG_SILENT;
  #endif
  
  	return abort;
66ded17df   Simon Glass   Move autoboot cod...
269
  }
66ded17df   Simon Glass   Move autoboot cod...
270
271
  static void process_fdt_options(const void *blob)
  {
9f73690ce   Stefan Roese   autoboot.c: Fill ...
272
  #if defined(CONFIG_OF_CONTROL) && defined(CONFIG_SYS_TEXT_BASE)
66ded17df   Simon Glass   Move autoboot cod...
273
274
275
276
277
  	ulong addr;
  
  	/* Add an env variable to point to a kernel payload, if available */
  	addr = fdtdec_get_config_int(gd->fdt_blob, "kernel-offset", 0);
  	if (addr)
018f53032   Simon Glass   env: Rename commo...
278
  		env_set_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
66ded17df   Simon Glass   Move autoboot cod...
279
280
281
282
  
  	/* Add an env variable to point to a root disk, if available */
  	addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0);
  	if (addr)
018f53032   Simon Glass   env: Rename commo...
283
  		env_set_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
9f73690ce   Stefan Roese   autoboot.c: Fill ...
284
  #endif /* CONFIG_OF_CONTROL && CONFIG_SYS_TEXT_BASE */
affb21562   Simon Glass   main: Make the ex...
285
  }
66ded17df   Simon Glass   Move autoboot cod...
286

affb21562   Simon Glass   main: Make the ex...
287
  const char *bootdelay_process(void)
66ded17df   Simon Glass   Move autoboot cod...
288
  {
66ded17df   Simon Glass   Move autoboot cod...
289
290
291
292
293
294
295
296
297
298
299
  	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);
018f53032   Simon Glass   env: Rename commo...
300
  	env_set_ulong("bootcount", bootcount);
bfebc8c96   Simon Glass   env: Rename geten...
301
  	bootlimit = env_get_ulong("bootlimit", 10, 0);
66ded17df   Simon Glass   Move autoboot cod...
302
  #endif /* CONFIG_BOOTCOUNT_LIMIT */
00caae6d4   Simon Glass   env: Rename geten...
303
  	s = env_get("bootdelay");
66ded17df   Simon Glass   Move autoboot cod...
304
  	bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
d39fd3f88   Frank Li   MLK-18257-4 use a...
305
306
  #if defined(is_boot_from_usb)
  	if (is_boot_from_usb() && env_get("bootcmd_mfg")) {
a92c4806b   Ye Li   MLK-18157 mfgtool...
307
308
309
310
311
312
313
  		disconnect_from_pc();
  		printf("Boot from USB for mfgtools
  ");
  		bootdelay = 0;
  		set_default_env("Use default environment for \
  				 mfgtools
  ");
5d7462168   faqiang.zhu   MA-12283-2 fix is...
314
315
316
317
  	} else if (is_boot_from_usb()) {
  		printf("Boot from USB for uuu
  ");
  		env_set("bootcmd", "fastboot 0");
a92c4806b   Ye Li   MLK-18157 mfgtool...
318
319
320
321
322
  	} else {
  		printf("Normal Boot
  ");
  	}
  #endif
66ded17df   Simon Glass   Move autoboot cod...
323
324
325
326
327
328
329
330
331
332
333
334
  #ifdef CONFIG_OF_CONTROL
  	bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay",
  			bootdelay);
  #endif
  
  	debug("### main_loop entered: bootdelay=%d
  
  ", bootdelay);
  
  #if defined(CONFIG_MENU_SHOW)
  	bootdelay = menu_show(bootdelay);
  #endif
b26440f1f   Simon Glass   Rename bootretry ...
335
  	bootretry_init_cmd_timeout();
66ded17df   Simon Glass   Move autoboot cod...
336
337
338
  
  #ifdef CONFIG_POST
  	if (gd->flags & GD_FLG_POSTFAIL) {
00caae6d4   Simon Glass   env: Rename geten...
339
  		s = env_get("failbootcmd");
66ded17df   Simon Glass   Move autoboot cod...
340
341
342
343
344
345
346
  	} else
  #endif /* CONFIG_POST */
  #ifdef CONFIG_BOOTCOUNT_LIMIT
  	if (bootlimit && (bootcount > bootlimit)) {
  		printf("Warning: Bootlimit (%u) exceeded. Using altbootcmd.
  ",
  		       (unsigned)bootlimit);
00caae6d4   Simon Glass   env: Rename geten...
347
  		s = env_get("altbootcmd");
66ded17df   Simon Glass   Move autoboot cod...
348
349
  	} else
  #endif /* CONFIG_BOOTCOUNT_LIMIT */
00caae6d4   Simon Glass   env: Rename geten...
350
  		s = env_get("bootcmd");
66ded17df   Simon Glass   Move autoboot cod...
351

d39fd3f88   Frank Li   MLK-18257-4 use a...
352
353
  #if defined(is_boot_from_usb)
  	if (is_boot_from_usb() && env_get("bootcmd_mfg")) {
a92c4806b   Ye Li   MLK-18157 mfgtool...
354
355
356
357
358
  		s = env_get("bootcmd_mfg");
  		printf("Run bootcmd_mfg: %s
  ", s);
  	}
  #endif
66ded17df   Simon Glass   Move autoboot cod...
359
  	process_fdt_options(gd->fdt_blob);
affb21562   Simon Glass   main: Make the ex...
360
  	stored_bootdelay = bootdelay;
66ded17df   Simon Glass   Move autoboot cod...
361

affb21562   Simon Glass   main: Make the ex...
362
363
  	return s;
  }
66ded17df   Simon Glass   Move autoboot cod...
364

affb21562   Simon Glass   main: Make the ex...
365
366
  void autoboot_command(const char *s)
  {
66ded17df   Simon Glass   Move autoboot cod...
367
368
  	debug("### main_loop: bootcmd=\"%s\"
  ", s ? s : "<UNDEFINED>");
affb21562   Simon Glass   main: Make the ex...
369
  	if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
66ded17df   Simon Glass   Move autoboot cod...
370
371
372
373
374
375
376
377
378
379
380
381
382
  #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);
  
  #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) {
00caae6d4   Simon Glass   env: Rename geten...
383
  		s = env_get("menucmd");
66ded17df   Simon Glass   Move autoboot cod...
384
385
386
387
388
  		if (s)
  			run_command_list(s, -1, 0);
  	}
  #endif /* CONFIG_MENUKEY */
  }