Blame view

common/autoboot.c 9.45 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
66ded17df   Simon Glass   Move autoboot cod...
2
3
4
  /*
   * (C) Copyright 2000
   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
66ded17df   Simon Glass   Move autoboot cod...
5
6
7
   */
  
  #include <common.h>
39e1230ed   Jeroen Hofstee   autoboot: add its...
8
  #include <autoboot.h>
0098e179e   Simon Glass   Move bootretry co...
9
  #include <bootretry.h>
66ded17df   Simon Glass   Move autoboot cod...
10
  #include <cli.h>
288b29e44   Simon Glass   common: Move comm...
11
  #include <command.h>
24b852a7a   Simon Glass   Move console defi...
12
  #include <console.h>
c7694dd48   Simon Glass   env: Move env_set...
13
  #include <env.h>
66ded17df   Simon Glass   Move autoboot cod...
14
  #include <fdtdec.h>
e8c780560   Simon Glass   autoboot: Drop #i...
15
  #include <hash.h>
336d4615f   Simon Glass   dm: core: Create ...
16
  #include <malloc.h>
ecaae801d   Heiko Schocher   autoboot: fix bug...
17
  #include <memalign.h>
66ded17df   Simon Glass   Move autoboot cod...
18
19
  #include <menu.h>
  #include <post.h>
1045315df   Simon Glass   common: Move get_...
20
  #include <time.h>
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
21
  #include <u-boot/sha256.h>
bc8c440fa   Lukasz Majewski   bootcount: Rewrit...
22
  #include <bootcount.h>
decfa9848   Ye Li   MLK-21854-2 imx: ...
23
24
25
  #ifdef is_boot_from_usb
  #include <env.h>
  #endif
66ded17df   Simon Glass   Move autoboot cod...
26
27
28
29
30
31
32
33
34
35
  
  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...
36
37
  /* Stored value of bootdelay, used by autoboot_command() */
  static int stored_bootdelay;
d915ad277   Simon Glass   autoboot: Tidy up...
38
  static int menukey;
affb21562   Simon Glass   main: Make the ex...
39

0c4bd318f   Simon Glass   autoboot: Use CON...
40
41
42
43
44
  #ifdef CONFIG_AUTOBOOT_ENCRYPTION
  #define AUTOBOOT_STOP_STR_SHA256 CONFIG_AUTOBOOT_STOP_STR_SHA256
  #else
  #define AUTOBOOT_STOP_STR_SHA256 ""
  #endif
d915ad277   Simon Glass   autoboot: Tidy up...
45
46
47
48
49
  #ifdef CONFIG_USE_AUTOBOOT_MENUKEY
  #define AUTOBOOT_MENUKEY CONFIG_USE_AUTOBOOT_MENUKEY
  #else
  #define AUTOBOOT_MENUKEY 0
  #endif
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
50
51
52
53
54
  /*
   * Use a "constant-length" time compare function for this
   * hash compare:
   *
   * https://crackstation.net/hashing-security.htm
66ded17df   Simon Glass   Move autoboot cod...
55
   */
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
56
57
58
59
60
61
62
63
64
65
  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;
  }
88fa4beb6   Simon Glass   autoboot: Improve...
66
67
68
69
70
71
72
73
  /**
   * passwd_abort_sha256() - check for a hashed key sequence to abort booting
   *
   * This checks for the user entering a SHA256 hash within a given time.
   *
   * @etime: Timeout value ticks (stop when get_ticks() reachs this)
   * @return 0 if autoboot should continue, 1 if it should stop
   */
e8c780560   Simon Glass   autoboot: Drop #i...
74
  static int passwd_abort_sha256(uint64_t etime)
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
75
  {
00caae6d4   Simon Glass   env: Rename geten...
76
  	const char *sha_env_str = env_get("bootstopkeysha256");
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
77
  	u8 sha_env[SHA256_SUM_LEN];
ecaae801d   Heiko Schocher   autoboot: fix bug...
78
79
  	u8 *sha;
  	char *presskey;
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
80
81
82
  	const char *algo_name = "sha256";
  	u_int presskey_len = 0;
  	int abort = 0;
2d06fd839   Martin Etnestad   Initialize SHA bu...
83
  	int size = sizeof(sha);
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
84
85
86
  	int ret;
  
  	if (sha_env_str == NULL)
0c4bd318f   Simon Glass   autoboot: Use CON...
87
  		sha_env_str = AUTOBOOT_STOP_STR_SHA256;
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
88
89
90
91
92
93
94
95
96
97
98
99
  
  	/*
  	 * 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;
  	}
ecaae801d   Heiko Schocher   autoboot: fix bug...
100
101
102
  	presskey = malloc_cache_aligned(MAX_DELAY_STOP_STR);
  	sha = malloc_cache_aligned(SHA256_SUM_LEN);
  	size = SHA256_SUM_LEN;
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
103
104
105
106
107
108
109
110
  	/*
  	 * 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 */
ecaae801d   Heiko Schocher   autoboot: fix bug...
111
112
113
  			if (presskey_len >= MAX_DELAY_STOP_STR) {
  				free(presskey);
  				free(sha);
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
114
  				return 0;
ecaae801d   Heiko Schocher   autoboot: fix bug...
115
  			}
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
116
117
118
119
120
121
122
123
124
125
126
127
  
  			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);
ecaae801d   Heiko Schocher   autoboot: fix bug...
128
129
  	free(presskey);
  	free(sha);
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
130
131
  	return abort;
  }
e8c780560   Simon Glass   autoboot: Drop #i...
132

88fa4beb6   Simon Glass   autoboot: Improve...
133
134
135
136
137
138
139
140
  /**
   * passwd_abort_key() - check for a key sequence to aborted booting
   *
   * This checks for the user entering a string within a given time.
   *
   * @etime: Timeout value ticks (stop when get_ticks() reachs this)
   * @return 0 if autoboot should continue, 1 if it should stop
   */
e8c780560   Simon Glass   autoboot: Drop #i...
141
  static int passwd_abort_key(uint64_t etime)
66ded17df   Simon Glass   Move autoboot cod...
142
143
  {
  	int abort = 0;
66ded17df   Simon Glass   Move autoboot cod...
144
145
146
147
148
149
  	struct {
  		char *str;
  		u_int len;
  		int retry;
  	}
  	delaykey[] = {
00caae6d4   Simon Glass   env: Rename geten...
150
151
  		{ .str = env_get("bootdelaykey"),  .retry = 1 },
  		{ .str = env_get("bootstopkey"),   .retry = 0 },
66ded17df   Simon Glass   Move autoboot cod...
152
153
154
155
156
157
  	};
  
  	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...
158
159
160
161
  #  ifdef CONFIG_AUTOBOOT_DELAY_STR
  	if (delaykey[0].str == NULL)
  		delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
  #  endif
66ded17df   Simon Glass   Move autoboot cod...
162
  #  ifdef CONFIG_AUTOBOOT_STOP_STR
2d908fa08   Stefan Roese   autoboot.c: Remov...
163
164
  	if (delaykey[1].str == NULL)
  		delaykey[1].str = CONFIG_AUTOBOOT_STOP_STR;
66ded17df   Simon Glass   Move autoboot cod...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  #  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...
207
208
209
  				/* don't retry auto boot */
  				if (!delaykey[i].retry)
  					bootretry_dont_retry();
66ded17df   Simon Glass   Move autoboot cod...
210
211
212
213
  				abort = 1;
  			}
  		}
  	} while (!abort && get_ticks() <= etime);
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
214
215
  	return abort;
  }
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
216
217
218
219
220
  
  /***************************************************************************
   * Watch for 'delay' seconds for autoboot stop or autoboot delay string.
   * returns: 0 -  no key string, allow autoboot 1 - got key string, abort
   */
e79e4b250   Simon Glass   autoboot: Drop #i...
221
  static int abortboot_key_sequence(int bootdelay)
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
222
223
224
  {
  	int abort;
  	uint64_t etime = endtick(bootdelay);
8f0b1e24e   Stefan Roese   autoboot.c: Add f...
225
226
227
228
229
230
231
  #  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
e8c780560   Simon Glass   autoboot: Drop #i...
232
233
234
235
  	if (IS_ENABLED(CONFIG_AUTOBOOT_ENCRYPTION))
  		abort = passwd_abort_sha256(etime);
  	else
  		abort = passwd_abort_key(etime);
66ded17df   Simon Glass   Move autoboot cod...
236
237
238
  	if (!abort)
  		debug_bootkeys("key timeout
  ");
66ded17df   Simon Glass   Move autoboot cod...
239
240
  	return abort;
  }
e79e4b250   Simon Glass   autoboot: Drop #i...
241
  static int abortboot_single_key(int bootdelay)
66ded17df   Simon Glass   Move autoboot cod...
242
243
244
  {
  	int abort = 0;
  	unsigned long ts;
463273920   Masahiro Yamada   autoboot: move bo...
245
  	printf("Hit any key to stop autoboot: %2d ", bootdelay);
66ded17df   Simon Glass   Move autoboot cod...
246

66ded17df   Simon Glass   Move autoboot cod...
247
248
  	/*
  	 * Check if key already pressed
66ded17df   Simon Glass   Move autoboot cod...
249
  	 */
463273920   Masahiro Yamada   autoboot: move bo...
250
251
252
253
  	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...
254
  	}
66ded17df   Simon Glass   Move autoboot cod...
255
256
257
258
259
260
261
  
  	while ((bootdelay > 0) && (!abort)) {
  		--bootdelay;
  		/* delay 1000 ms */
  		ts = get_timer(0);
  		do {
  			if (tstc()) {	/* we got a key press	*/
d915ad277   Simon Glass   autoboot: Tidy up...
262
  				int key;
66ded17df   Simon Glass   Move autoboot cod...
263
264
  				abort  = 1;	/* don't auto boot	*/
  				bootdelay = 0;	/* no more delay	*/
d915ad277   Simon Glass   autoboot: Tidy up...
265
266
267
  				key = getc(); /* consume input	*/
  				if (IS_ENABLED(CONFIG_USE_AUTOBOOT_MENUKEY))
  					menukey = key;
66ded17df   Simon Glass   Move autoboot cod...
268
269
270
271
272
273
274
275
276
277
  				break;
  			}
  			udelay(10000);
  		} while (!abort && get_timer(ts) < 1000);
  
  		printf("\b\b\b%2d ", bootdelay);
  	}
  
  	putc('
  ');
66ded17df   Simon Glass   Move autoboot cod...
278
279
  	return abort;
  }
66ded17df   Simon Glass   Move autoboot cod...
280
281
282
  
  static int abortboot(int bootdelay)
  {
463273920   Masahiro Yamada   autoboot: move bo...
283
  	int abort = 0;
09b9d9e55   Masahiro Yamada   autoboot: move CO...
284

e79e4b250   Simon Glass   autoboot: Drop #i...
285
286
287
288
289
290
  	if (bootdelay >= 0) {
  		if (IS_ENABLED(CONFIG_AUTOBOOT_KEYED))
  			abort = abortboot_key_sequence(bootdelay);
  		else
  			abort = abortboot_single_key(bootdelay);
  	}
09b9d9e55   Masahiro Yamada   autoboot: move CO...
291

42b4d14e3   Simon Glass   autoboot: Use if(...
292
  	if (IS_ENABLED(CONFIG_SILENT_CONSOLE) && abort)
09b9d9e55   Masahiro Yamada   autoboot: move CO...
293
  		gd->flags &= ~GD_FLG_SILENT;
09b9d9e55   Masahiro Yamada   autoboot: move CO...
294
295
  
  	return abort;
66ded17df   Simon Glass   Move autoboot cod...
296
  }
66ded17df   Simon Glass   Move autoboot cod...
297
298
  static void process_fdt_options(const void *blob)
  {
5fa3fd25e   Simon Glass   autoboot: Move a ...
299
  #ifdef CONFIG_SYS_TEXT_BASE
66ded17df   Simon Glass   Move autoboot cod...
300
301
302
303
304
  	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...
305
  		env_set_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
66ded17df   Simon Glass   Move autoboot cod...
306
307
308
309
  
  	/* 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...
310
  		env_set_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr));
5fa3fd25e   Simon Glass   autoboot: Move a ...
311
  #endif /* CONFIG_SYS_TEXT_BASE */
affb21562   Simon Glass   main: Make the ex...
312
  }
66ded17df   Simon Glass   Move autoboot cod...
313

affb21562   Simon Glass   main: Make the ex...
314
  const char *bootdelay_process(void)
66ded17df   Simon Glass   Move autoboot cod...
315
  {
66ded17df   Simon Glass   Move autoboot cod...
316
317
  	char *s;
  	int bootdelay;
bc8c440fa   Lukasz Majewski   bootcount: Rewrit...
318
319
  
  	bootcount_inc();
66ded17df   Simon Glass   Move autoboot cod...
320

00caae6d4   Simon Glass   env: Rename geten...
321
  	s = env_get("bootdelay");
66ded17df   Simon Glass   Move autoboot cod...
322
  	bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY;
5fa3fd25e   Simon Glass   autoboot: Move a ...
323
324
325
  	if (IS_ENABLED(CONFIG_OF_CONTROL))
  		bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay",
  						  bootdelay);
66ded17df   Simon Glass   Move autoboot cod...
326

decfa9848   Ye Li   MLK-21854-2 imx: ...
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
  #if defined(is_boot_from_usb)
  	if (is_boot_from_usb() && env_get("bootcmd_mfg")) {
  		disconnect_from_pc();
  		printf("Boot from USB for mfgtools
  ");
  		bootdelay = 0;
  		env_set_default("Use default environment for \
  				 mfgtools
  ", 0);
  	} else if (is_boot_from_usb()) {
  		printf("Boot from USB for uuu
  ");
  		env_set("bootcmd", "fastboot 0");
  	} else {
  		printf("Normal Boot
  ");
  	}
  #endif
66ded17df   Simon Glass   Move autoboot cod...
345
346
347
  	debug("### main_loop entered: bootdelay=%d
  
  ", bootdelay);
5fa3fd25e   Simon Glass   autoboot: Move a ...
348
349
  	if (IS_ENABLED(CONFIG_AUTOBOOT_MENU_SHOW))
  		bootdelay = menu_show(bootdelay);
b26440f1f   Simon Glass   Rename bootretry ...
350
  	bootretry_init_cmd_timeout();
66ded17df   Simon Glass   Move autoboot cod...
351
352
353
  
  #ifdef CONFIG_POST
  	if (gd->flags & GD_FLG_POSTFAIL) {
00caae6d4   Simon Glass   env: Rename geten...
354
  		s = env_get("failbootcmd");
66ded17df   Simon Glass   Move autoboot cod...
355
356
  	} else
  #endif /* CONFIG_POST */
bc8c440fa   Lukasz Majewski   bootcount: Rewrit...
357
  	if (bootcount_error())
00caae6d4   Simon Glass   env: Rename geten...
358
  		s = env_get("altbootcmd");
bc8c440fa   Lukasz Majewski   bootcount: Rewrit...
359
  	else
00caae6d4   Simon Glass   env: Rename geten...
360
  		s = env_get("bootcmd");
66ded17df   Simon Glass   Move autoboot cod...
361

decfa9848   Ye Li   MLK-21854-2 imx: ...
362
363
364
365
366
367
368
  #if defined(is_boot_from_usb)
  	if (is_boot_from_usb() && env_get("bootcmd_mfg")) {
  		s = env_get("bootcmd_mfg");
  		printf("Run bootcmd_mfg: %s
  ", s);
  	}
  #endif
5fa3fd25e   Simon Glass   autoboot: Move a ...
369
370
  	if (IS_ENABLED(CONFIG_OF_CONTROL))
  		process_fdt_options(gd->fdt_blob);
affb21562   Simon Glass   main: Make the ex...
371
  	stored_bootdelay = bootdelay;
66ded17df   Simon Glass   Move autoboot cod...
372

affb21562   Simon Glass   main: Make the ex...
373
374
  	return s;
  }
66ded17df   Simon Glass   Move autoboot cod...
375

affb21562   Simon Glass   main: Make the ex...
376
377
  void autoboot_command(const char *s)
  {
66ded17df   Simon Glass   Move autoboot cod...
378
379
  	debug("### main_loop: bootcmd=\"%s\"
  ", s ? s : "<UNDEFINED>");
affb21562   Simon Glass   main: Make the ex...
380
  	if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) {
5ec35ff3e   Simon Glass   autoboot: Adjust ...
381
382
383
384
385
386
387
  		bool lock;
  		int prev;
  
  		lock = IS_ENABLED(CONFIG_AUTOBOOT_KEYED) &&
  			!IS_ENABLED(CONFIG_AUTOBOOT_KEYED_CTRLC);
  		if (lock)
  			prev = disable_ctrlc(1); /* disable Ctrl-C checking */
66ded17df   Simon Glass   Move autoboot cod...
388
389
  
  		run_command_list(s, -1, 0);
5ec35ff3e   Simon Glass   autoboot: Adjust ...
390
391
  		if (lock)
  			disable_ctrlc(prev);	/* restore Ctrl-C checking */
66ded17df   Simon Glass   Move autoboot cod...
392
  	}
d915ad277   Simon Glass   autoboot: Tidy up...
393
394
  	if (IS_ENABLED(CONFIG_USE_AUTOBOOT_MENUKEY) &&
  	    menukey == AUTOBOOT_MENUKEY) {
00caae6d4   Simon Glass   env: Rename geten...
395
  		s = env_get("menucmd");
66ded17df   Simon Glass   Move autoboot cod...
396
397
398
  		if (s)
  			run_command_list(s, -1, 0);
  	}
66ded17df   Simon Glass   Move autoboot cod...
399
  }