Blame view

common/autoboot.c 8.31 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
18
19
20
21
22
23
24
25
26
  
  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...
27
28
  /* Stored value of bootdelay, used by autoboot_command() */
  static int stored_bootdelay;
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
29
30
31
32
33
34
35
36
  #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...
37
   */
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
38
39
40
41
42
43
44
45
46
47
48
49
50
  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...
51
  	const char *sha_env_str = env_get("bootstopkeysha256");
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
52
53
54
55
56
57
  	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...
58
  	int size = sizeof(sha);
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
59
60
61
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
  	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...
103
104
  {
  	int abort = 0;
66ded17df   Simon Glass   Move autoboot cod...
105
106
107
108
109
110
  	struct {
  		char *str;
  		u_int len;
  		int retry;
  	}
  	delaykey[] = {
00caae6d4   Simon Glass   env: Rename geten...
111
112
  		{ .str = env_get("bootdelaykey"),  .retry = 1 },
  		{ .str = env_get("bootstopkey"),   .retry = 0 },
66ded17df   Simon Glass   Move autoboot cod...
113
114
115
116
117
118
  	};
  
  	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...
119
120
121
122
  #  ifdef CONFIG_AUTOBOOT_DELAY_STR
  	if (delaykey[0].str == NULL)
  		delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
  #  endif
66ded17df   Simon Glass   Move autoboot cod...
123
  #  ifdef CONFIG_AUTOBOOT_STOP_STR
2d908fa08   Stefan Roese   autoboot.c: Remov...
124
125
  	if (delaykey[1].str == NULL)
  		delaykey[1].str = CONFIG_AUTOBOOT_STOP_STR;
66ded17df   Simon Glass   Move autoboot cod...
126
127
128
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
  #  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...
168
169
170
  				/* don't retry auto boot */
  				if (!delaykey[i].retry)
  					bootretry_dont_retry();
66ded17df   Simon Glass   Move autoboot cod...
171
172
173
174
  				abort = 1;
  			}
  		}
  	} while (!abort && get_ticks() <= etime);
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
175
176
177
178
179
180
181
182
  	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 ...
183
  static int __abortboot(int bootdelay)
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
184
185
186
  {
  	int abort;
  	uint64_t etime = endtick(bootdelay);
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
187
188
189
190
191
192
193
194
195
  #  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...
196
197
198
  	if (!abort)
  		debug_bootkeys("key timeout
  ");
66ded17df   Simon Glass   Move autoboot cod...
199
200
201
202
203
204
205
206
  	return abort;
  }
  
  # else	/* !defined(CONFIG_AUTOBOOT_KEYED) */
  
  #ifdef CONFIG_MENUKEY
  static int menukey;
  #endif
d8da8298a   Masahiro Yamada   autoboot: rename ...
207
  static int __abortboot(int bootdelay)
66ded17df   Simon Glass   Move autoboot cod...
208
209
210
211
212
213
214
  {
  	int abort = 0;
  	unsigned long ts;
  
  #ifdef CONFIG_MENUPROMPT
  	printf(CONFIG_MENUPROMPT);
  #else
463273920   Masahiro Yamada   autoboot: move bo...
215
  	printf("Hit any key to stop autoboot: %2d ", bootdelay);
66ded17df   Simon Glass   Move autoboot cod...
216
  #endif
66ded17df   Simon Glass   Move autoboot cod...
217
218
  	/*
  	 * Check if key already pressed
66ded17df   Simon Glass   Move autoboot cod...
219
  	 */
463273920   Masahiro Yamada   autoboot: move bo...
220
221
222
223
  	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...
224
  	}
66ded17df   Simon Glass   Move autoboot cod...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
  
  	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...
249
250
251
252
253
254
  	return abort;
  }
  # endif	/* CONFIG_AUTOBOOT_KEYED */
  
  static int abortboot(int bootdelay)
  {
463273920   Masahiro Yamada   autoboot: move bo...
255
  	int abort = 0;
09b9d9e55   Masahiro Yamada   autoboot: move CO...
256

463273920   Masahiro Yamada   autoboot: move bo...
257
258
  	if (bootdelay >= 0)
  		abort = __abortboot(bootdelay);
09b9d9e55   Masahiro Yamada   autoboot: move CO...
259
260
261
262
263
264
265
  
  #ifdef CONFIG_SILENT_CONSOLE
  	if (abort)
  		gd->flags &= ~GD_FLG_SILENT;
  #endif
  
  	return abort;
66ded17df   Simon Glass   Move autoboot cod...
266
  }
66ded17df   Simon Glass   Move autoboot cod...
267
268
  static void process_fdt_options(const void *blob)
  {
9f73690ce   Stefan Roese   autoboot.c: Fill ...
269
  #if defined(CONFIG_OF_CONTROL) && defined(CONFIG_SYS_TEXT_BASE)
66ded17df   Simon Glass   Move autoboot cod...
270
271
272
273
274
  	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...
275
  		env_set_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
66ded17df   Simon Glass   Move autoboot cod...
276
277
278
279
  
  	/* 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...
280
  		env_set_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
9f73690ce   Stefan Roese   autoboot.c: Fill ...
281
  #endif /* CONFIG_OF_CONTROL && CONFIG_SYS_TEXT_BASE */
affb21562   Simon Glass   main: Make the ex...
282
  }
66ded17df   Simon Glass   Move autoboot cod...
283

affb21562   Simon Glass   main: Make the ex...
284
  const char *bootdelay_process(void)
66ded17df   Simon Glass   Move autoboot cod...
285
  {
66ded17df   Simon Glass   Move autoboot cod...
286
287
288
289
290
291
292
293
294
295
296
  	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...
297
  	env_set_ulong("bootcount", bootcount);
bfebc8c96   Simon Glass   env: Rename geten...
298
  	bootlimit = env_get_ulong("bootlimit", 10, 0);
66ded17df   Simon Glass   Move autoboot cod...
299
  #endif /* CONFIG_BOOTCOUNT_LIMIT */
00caae6d4   Simon Glass   env: Rename geten...
300
  	s = env_get("bootdelay");
66ded17df   Simon Glass   Move autoboot cod...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  	bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
  
  #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 ...
315
  	bootretry_init_cmd_timeout();
66ded17df   Simon Glass   Move autoboot cod...
316
317
318
  
  #ifdef CONFIG_POST
  	if (gd->flags & GD_FLG_POSTFAIL) {
00caae6d4   Simon Glass   env: Rename geten...
319
  		s = env_get("failbootcmd");
66ded17df   Simon Glass   Move autoboot cod...
320
321
322
323
324
325
326
  	} 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...
327
  		s = env_get("altbootcmd");
66ded17df   Simon Glass   Move autoboot cod...
328
329
  	} else
  #endif /* CONFIG_BOOTCOUNT_LIMIT */
00caae6d4   Simon Glass   env: Rename geten...
330
  		s = env_get("bootcmd");
66ded17df   Simon Glass   Move autoboot cod...
331
332
  
  	process_fdt_options(gd->fdt_blob);
affb21562   Simon Glass   main: Make the ex...
333
  	stored_bootdelay = bootdelay;
66ded17df   Simon Glass   Move autoboot cod...
334

affb21562   Simon Glass   main: Make the ex...
335
336
  	return s;
  }
66ded17df   Simon Glass   Move autoboot cod...
337

affb21562   Simon Glass   main: Make the ex...
338
339
  void autoboot_command(const char *s)
  {
66ded17df   Simon Glass   Move autoboot cod...
340
341
  	debug("### main_loop: bootcmd=\"%s\"
  ", s ? s : "<UNDEFINED>");
affb21562   Simon Glass   main: Make the ex...
342
  	if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
66ded17df   Simon Glass   Move autoboot cod...
343
344
345
346
347
348
349
350
351
352
353
354
355
  #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...
356
  		s = env_get("menucmd");
66ded17df   Simon Glass   Move autoboot cod...
357
358
359
360
361
  		if (s)
  			run_command_list(s, -1, 0);
  	}
  #endif /* CONFIG_MENUKEY */
  }