blob: d8d0bdf9fd473458f58f1e1288bac8eede3dda9b [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0
Stephen Warren10e50632016-01-15 11:15:24 -07002# Copyright (c) 2015 Stephen Warren
3# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
Stephen Warren10e50632016-01-15 11:15:24 -07004
5# Common logic to interact with U-Boot via the console. This class provides
6# the interface that tests use to execute U-Boot shell commands and wait for
7# their results. Sub-classes exist to perform board-type-specific setup
8# operations, such as spawning a sub-process for Sandbox, or attaching to the
9# serial console of real hardware.
10
11import multiplexed_log
12import os
13import pytest
14import re
15import sys
Stephen Warren97a54662016-01-22 12:30:09 -070016import u_boot_spawn
Simon Glass7a1e9b42024-10-09 18:29:04 -060017from u_boot_spawn import BootFail, Timeout, Unexpected, handle_exception
Stephen Warren10e50632016-01-15 11:15:24 -070018
19# Regexes for text we expect U-Boot to send to the console.
Heiko Schocherce251232018-12-05 11:29:54 +010020pattern_u_boot_spl_signon = re.compile('(U-Boot SPL \\d{4}\\.\\d{2}[^\r\n]*\\))')
Stephen Warren5af83c42016-02-05 18:04:43 -070021pattern_u_boot_main_signon = re.compile('(U-Boot \\d{4}\\.\\d{2}[^\r\n]*\\))')
Stephen Warren10e50632016-01-15 11:15:24 -070022pattern_stop_autoboot_prompt = re.compile('Hit any key to stop autoboot: ')
23pattern_unknown_command = re.compile('Unknown command \'.*\' - try \'help\'')
24pattern_error_notification = re.compile('## Error: ')
Stephen Warren3bd79d32016-01-27 23:57:50 -070025pattern_error_please_reset = re.compile('### ERROR ### Please RESET the board ###')
Stephen Warren10e50632016-01-15 11:15:24 -070026
Stephen Warren1115a972016-01-27 23:57:48 -070027PAT_ID = 0
28PAT_RE = 1
29
Simon Glass64914152024-10-09 18:28:58 -060030# Timeout before expecting the console to be ready (in milliseconds)
31TIMEOUT_MS = 30000
32
Stephen Warren1115a972016-01-27 23:57:48 -070033bad_pattern_defs = (
34 ('spl_signon', pattern_u_boot_spl_signon),
35 ('main_signon', pattern_u_boot_main_signon),
36 ('stop_autoboot_prompt', pattern_stop_autoboot_prompt),
37 ('unknown_command', pattern_unknown_command),
38 ('error_notification', pattern_error_notification),
Stephen Warren3bd79d32016-01-27 23:57:50 -070039 ('error_please_reset', pattern_error_please_reset),
Stephen Warren1115a972016-01-27 23:57:48 -070040)
41
Stephen Warren10e50632016-01-15 11:15:24 -070042class ConsoleDisableCheck(object):
Stephen Warren75e731e2016-01-26 13:41:30 -070043 """Context manager (for Python's with statement) that temporarily disables
Stephen Warren10e50632016-01-15 11:15:24 -070044 the specified console output error check. This is useful when deliberately
45 executing a command that is known to trigger one of the error checks, in
46 order to test that the error condition is actually raised. This class is
47 used internally by ConsoleBase::disable_check(); it is not intended for
Stephen Warren75e731e2016-01-26 13:41:30 -070048 direct usage."""
Stephen Warren10e50632016-01-15 11:15:24 -070049
50 def __init__(self, console, check_type):
51 self.console = console
52 self.check_type = check_type
53
54 def __enter__(self):
55 self.console.disable_check_count[self.check_type] += 1
Stephen Warren1115a972016-01-27 23:57:48 -070056 self.console.eval_bad_patterns()
Stephen Warren10e50632016-01-15 11:15:24 -070057
58 def __exit__(self, extype, value, traceback):
59 self.console.disable_check_count[self.check_type] -= 1
Stephen Warren1115a972016-01-27 23:57:48 -070060 self.console.eval_bad_patterns()
Stephen Warren10e50632016-01-15 11:15:24 -070061
Love Kumarc35e66e2024-05-22 18:45:13 +053062class ConsoleEnableCheck(object):
63 """Context manager (for Python's with statement) that temporarily enables
64 the specified console output error check. This is useful when executing a
65 command that might raise an extra bad pattern, beyond the default bad
66 patterns, in order to validate that the extra bad pattern is actually
67 detected. This class is used internally by ConsoleBase::enable_check(); it
68 is not intended for direct usage."""
69
70 def __init__(self, console, check_type, check_pattern):
71 self.console = console
72 self.check_type = check_type
73 self.check_pattern = check_pattern
74
75 def __enter__(self):
76 global bad_pattern_defs
77 self.default_bad_patterns = bad_pattern_defs
78 bad_pattern_defs += ((self.check_type, self.check_pattern),)
79 self.console.disable_check_count = {pat[PAT_ID]: 0 for pat in bad_pattern_defs}
80 self.console.eval_bad_patterns()
81
82 def __exit__(self, extype, value, traceback):
83 global bad_pattern_defs
84 bad_pattern_defs = self.default_bad_patterns
85 self.console.disable_check_count = {pat[PAT_ID]: 0 for pat in bad_pattern_defs}
86 self.console.eval_bad_patterns()
87
Michal Simek6b463182016-05-19 07:57:41 +020088class ConsoleSetupTimeout(object):
89 """Context manager (for Python's with statement) that temporarily sets up
90 timeout for specific command. This is useful when execution time is greater
91 then default 30s."""
92
93 def __init__(self, console, timeout):
94 self.p = console.p
95 self.orig_timeout = self.p.timeout
96 self.p.timeout = timeout
97
98 def __enter__(self):
99 return self
100
101 def __exit__(self, extype, value, traceback):
102 self.p.timeout = self.orig_timeout
103
Stephen Warren10e50632016-01-15 11:15:24 -0700104class ConsoleBase(object):
Stephen Warren75e731e2016-01-26 13:41:30 -0700105 """The interface through which test functions interact with the U-Boot
Stephen Warren10e50632016-01-15 11:15:24 -0700106 console. This primarily involves executing shell commands, capturing their
107 results, and checking for common error conditions. Some common utilities
Stephen Warren75e731e2016-01-26 13:41:30 -0700108 are also provided too."""
Stephen Warren10e50632016-01-15 11:15:24 -0700109
110 def __init__(self, log, config, max_fifo_fill):
Stephen Warren75e731e2016-01-26 13:41:30 -0700111 """Initialize a U-Boot console connection.
Stephen Warren10e50632016-01-15 11:15:24 -0700112
113 Can only usefully be called by sub-classes.
114
115 Args:
Simon Glass53d65832024-10-09 18:29:05 -0600116 log: A multiplexed_log.Logfile object, to which the U-Boot output
Stephen Warren10e50632016-01-15 11:15:24 -0700117 will be logged.
118 config: A configuration data structure, as built by conftest.py.
119 max_fifo_fill: The maximum number of characters to send to U-Boot
120 command-line before waiting for U-Boot to echo the characters
121 back. For UART-based HW without HW flow control, this value
122 should be set less than the UART RX FIFO size to avoid
123 overflow, assuming that U-Boot can't keep up with full-rate
124 traffic at the baud rate.
125
126 Returns:
127 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -0700128 """
Stephen Warren10e50632016-01-15 11:15:24 -0700129
130 self.log = log
131 self.config = config
132 self.max_fifo_fill = max_fifo_fill
133
134 self.logstream = self.log.get_stream('console', sys.stdout)
135
136 # Array slice removes leading/trailing quotes
137 self.prompt = self.config.buildconfig['config_sys_prompt'][1:-1]
Stephen Warren6d083402016-08-16 19:58:59 -0600138 self.prompt_compiled = re.compile('^' + re.escape(self.prompt), re.MULTILINE)
Stephen Warren10e50632016-01-15 11:15:24 -0700139 self.p = None
Stephen Warren1115a972016-01-27 23:57:48 -0700140 self.disable_check_count = {pat[PAT_ID]: 0 for pat in bad_pattern_defs}
141 self.eval_bad_patterns()
Stephen Warren10e50632016-01-15 11:15:24 -0700142
143 self.at_prompt = False
144 self.at_prompt_logevt = None
Stephen Warren10e50632016-01-15 11:15:24 -0700145
Simon Glassf7990762022-02-11 13:23:23 -0700146 def get_spawn(self):
147 # This is not called, ssubclass must define this.
148 # Return a value to avoid:
149 # u_boot_console_base.py:348:12: E1128: Assigning result of a function
150 # call, where the function returns None (assignment-from-none)
151 return u_boot_spawn.Spawn([])
152
153
Stephen Warren1115a972016-01-27 23:57:48 -0700154 def eval_bad_patterns(self):
155 self.bad_patterns = [pat[PAT_RE] for pat in bad_pattern_defs \
156 if self.disable_check_count[pat[PAT_ID]] == 0]
157 self.bad_pattern_ids = [pat[PAT_ID] for pat in bad_pattern_defs \
158 if self.disable_check_count[pat[PAT_ID]] == 0]
159
Stephen Warren10e50632016-01-15 11:15:24 -0700160 def close(self):
Stephen Warren75e731e2016-01-26 13:41:30 -0700161 """Terminate the connection to the U-Boot console.
Stephen Warren10e50632016-01-15 11:15:24 -0700162
163 This function is only useful once all interaction with U-Boot is
164 complete. Once this function is called, data cannot be sent to or
165 received from U-Boot.
166
167 Args:
168 None.
169
170 Returns:
171 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -0700172 """
Stephen Warren10e50632016-01-15 11:15:24 -0700173
174 if self.p:
175 self.p.close()
176 self.logstream.close()
177
Masami Hiramatsu4d3b9962022-02-16 15:16:02 +0900178 def wait_for_boot_prompt(self, loop_num = 1):
Masami Hiramatsu0ff22782022-02-16 15:15:52 +0900179 """Wait for the boot up until command prompt. This is for internal use only.
180 """
181 try:
182 bcfg = self.config.buildconfig
Masami Hiramatsu0ff22782022-02-16 15:15:52 +0900183 config_spl_serial = bcfg.get('config_spl_serial', 'n') == 'y'
184 env_spl_skipped = self.config.env.get('env__spl_skipped', False)
Tom Rinidec7ea02024-05-20 13:35:03 -0600185 env_spl_banner_times = self.config.env.get('env__spl_banner_times', 1)
Masami Hiramatsu0ff22782022-02-16 15:15:52 +0900186
Masami Hiramatsu4d3b9962022-02-16 15:16:02 +0900187 while loop_num > 0:
188 loop_num -= 1
Tom Rinidec7ea02024-05-20 13:35:03 -0600189 while config_spl_serial and not env_spl_skipped and env_spl_banner_times > 0:
Masami Hiramatsu4d3b9962022-02-16 15:16:02 +0900190 m = self.p.expect([pattern_u_boot_spl_signon] +
191 self.bad_patterns)
192 if m != 0:
Simon Glass573171e2024-10-09 18:29:02 -0600193 raise BootFail('Bad pattern found on SPL console: ' +
Masami Hiramatsu4d3b9962022-02-16 15:16:02 +0900194 self.bad_pattern_ids[m - 1])
Tom Rinidec7ea02024-05-20 13:35:03 -0600195 env_spl_banner_times -= 1
196
Masami Hiramatsu4d3b9962022-02-16 15:16:02 +0900197 m = self.p.expect([pattern_u_boot_main_signon] + self.bad_patterns)
Masami Hiramatsu0ff22782022-02-16 15:15:52 +0900198 if m != 0:
Simon Glass573171e2024-10-09 18:29:02 -0600199 raise BootFail('Bad pattern found on console: ' +
Masami Hiramatsu0ff22782022-02-16 15:15:52 +0900200 self.bad_pattern_ids[m - 1])
Masami Hiramatsu0ff22782022-02-16 15:15:52 +0900201 self.u_boot_version_string = self.p.after
202 while True:
203 m = self.p.expect([self.prompt_compiled,
204 pattern_stop_autoboot_prompt] + self.bad_patterns)
205 if m == 0:
206 break
207 if m == 1:
208 self.p.send(' ')
209 continue
Simon Glass573171e2024-10-09 18:29:02 -0600210 raise BootFail('Bad pattern found on console: ' +
Masami Hiramatsu0ff22782022-02-16 15:15:52 +0900211 self.bad_pattern_ids[m - 2])
212
Masami Hiramatsu0ff22782022-02-16 15:15:52 +0900213 finally:
214 self.log.timestamp()
215
Stephen Warren10e50632016-01-15 11:15:24 -0700216 def run_command(self, cmd, wait_for_echo=True, send_nl=True,
Masami Hiramatsu0ff22782022-02-16 15:15:52 +0900217 wait_for_prompt=True, wait_for_reboot=False):
Stephen Warren75e731e2016-01-26 13:41:30 -0700218 """Execute a command via the U-Boot console.
Stephen Warren10e50632016-01-15 11:15:24 -0700219
220 The command is always sent to U-Boot.
221
222 U-Boot echoes any command back to its output, and this function
223 typically waits for that to occur. The wait can be disabled by setting
224 wait_for_echo=False, which is useful e.g. when sending CTRL-C to
225 interrupt a long-running command such as "ums".
226
227 Command execution is typically triggered by sending a newline
228 character. This can be disabled by setting send_nl=False, which is
229 also useful when sending CTRL-C.
230
231 This function typically waits for the command to finish executing, and
232 returns the console output that it generated. This can be disabled by
233 setting wait_for_prompt=False, which is useful when invoking a long-
234 running command such as "ums".
235
236 Args:
237 cmd: The command to send.
Heinrich Schuchardtbec160a2017-09-14 12:27:07 +0200238 wait_for_echo: Boolean indicating whether to wait for U-Boot to
Stephen Warren10e50632016-01-15 11:15:24 -0700239 echo the command text back to its output.
240 send_nl: Boolean indicating whether to send a newline character
241 after the command string.
242 wait_for_prompt: Boolean indicating whether to wait for the
243 command prompt to be sent by U-Boot. This typically occurs
244 immediately after the command has been executed.
Masami Hiramatsu0ff22782022-02-16 15:15:52 +0900245 wait_for_reboot: Boolean indication whether to wait for the
246 reboot U-Boot. If this sets True, wait_for_prompt must also
247 be True.
Stephen Warren10e50632016-01-15 11:15:24 -0700248
249 Returns:
250 If wait_for_prompt == False:
251 Nothing.
252 Else:
253 The output from U-Boot during command execution. In other
254 words, the text U-Boot emitted between the point it echod the
255 command string and emitted the subsequent command prompts.
Stephen Warren75e731e2016-01-26 13:41:30 -0700256 """
Stephen Warren10e50632016-01-15 11:15:24 -0700257
Stephen Warren10e50632016-01-15 11:15:24 -0700258 if self.at_prompt and \
259 self.at_prompt_logevt != self.logstream.logfile.cur_evt:
260 self.logstream.write(self.prompt, implicit=True)
261
Stephen Warren10e50632016-01-15 11:15:24 -0700262 try:
263 self.at_prompt = False
264 if send_nl:
265 cmd += '\n'
266 while cmd:
267 # Limit max outstanding data, so UART FIFOs don't overflow
268 chunk = cmd[:self.max_fifo_fill]
269 cmd = cmd[self.max_fifo_fill:]
270 self.p.send(chunk)
271 if not wait_for_echo:
272 continue
273 chunk = re.escape(chunk)
274 chunk = chunk.replace('\\\n', '[\r\n]')
Stephen Warren1115a972016-01-27 23:57:48 -0700275 m = self.p.expect([chunk] + self.bad_patterns)
Stephen Warren10e50632016-01-15 11:15:24 -0700276 if m != 0:
277 self.at_prompt = False
Simon Glass573171e2024-10-09 18:29:02 -0600278 raise BootFail('Bad pattern found on console: ' +
Stephen Warren1115a972016-01-27 23:57:48 -0700279 self.bad_pattern_ids[m - 1])
Stephen Warren10e50632016-01-15 11:15:24 -0700280 if not wait_for_prompt:
281 return
Masami Hiramatsu0ff22782022-02-16 15:15:52 +0900282 if wait_for_reboot:
283 self.wait_for_boot_prompt()
284 else:
285 m = self.p.expect([self.prompt_compiled] + self.bad_patterns)
286 if m != 0:
287 self.at_prompt = False
Simon Glass573171e2024-10-09 18:29:02 -0600288 raise BootFail('Missing prompt on console: ' +
Masami Hiramatsu0ff22782022-02-16 15:15:52 +0900289 self.bad_pattern_ids[m - 1])
Stephen Warren10e50632016-01-15 11:15:24 -0700290 self.at_prompt = True
291 self.at_prompt_logevt = self.logstream.logfile.cur_evt
292 # Only strip \r\n; space/TAB might be significant if testing
293 # indentation.
294 return self.p.before.strip('\r\n')
Simon Glass573171e2024-10-09 18:29:02 -0600295 except Timeout as exc:
Simon Glass7a1e9b42024-10-09 18:29:04 -0600296 handle_exception(self.config, self, self.log, exc, 'Lab failure',
297 True)
Simon Glass573171e2024-10-09 18:29:02 -0600298 raise
Simon Glass7a1e9b42024-10-09 18:29:04 -0600299 except BootFail as exc:
300 handle_exception(self.config, self, self.log, exc, 'Boot fail',
301 True, self.get_spawn_output())
Stephen Warren10e50632016-01-15 11:15:24 -0700302 raise
Stephen Warrenb1c556a2017-10-27 11:04:08 -0600303 finally:
304 self.log.timestamp()
Stephen Warren10e50632016-01-15 11:15:24 -0700305
Simon Glass2436bb02016-07-03 09:40:42 -0600306 def run_command_list(self, cmds):
307 """Run a list of commands.
308
309 This is a helper function to call run_command() with default arguments
310 for each command in a list.
311
312 Args:
Simon Glassd5deca02016-07-31 17:35:04 -0600313 cmd: List of commands (each a string).
Simon Glass2436bb02016-07-03 09:40:42 -0600314 Returns:
Simon Glass2ca73112016-07-31 17:35:09 -0600315 A list of output strings from each command, one element for each
316 command.
Simon Glass2436bb02016-07-03 09:40:42 -0600317 """
Simon Glass2ca73112016-07-31 17:35:09 -0600318 output = []
Simon Glass2436bb02016-07-03 09:40:42 -0600319 for cmd in cmds:
Simon Glass2ca73112016-07-31 17:35:09 -0600320 output.append(self.run_command(cmd))
Simon Glass2436bb02016-07-03 09:40:42 -0600321 return output
322
Stephen Warren10e50632016-01-15 11:15:24 -0700323 def ctrlc(self):
Stephen Warren75e731e2016-01-26 13:41:30 -0700324 """Send a CTRL-C character to U-Boot.
Stephen Warren10e50632016-01-15 11:15:24 -0700325
326 This is useful in order to stop execution of long-running synchronous
327 commands such as "ums".
328
329 Args:
330 None.
331
332 Returns:
333 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -0700334 """
Stephen Warren10e50632016-01-15 11:15:24 -0700335
Stephen Warrena88c4172016-01-22 12:30:10 -0700336 self.log.action('Sending Ctrl-C')
Stephen Warren10e50632016-01-15 11:15:24 -0700337 self.run_command(chr(3), wait_for_echo=False, send_nl=False)
338
Stephen Warrenef824f52016-01-22 12:30:12 -0700339 def wait_for(self, text):
Stephen Warren75e731e2016-01-26 13:41:30 -0700340 """Wait for a pattern to be emitted by U-Boot.
Stephen Warrenef824f52016-01-22 12:30:12 -0700341
342 This is useful when a long-running command such as "dfu" is executing,
343 and it periodically emits some text that should show up at a specific
344 location in the log file.
345
346 Args:
347 text: The text to wait for; either a string (containing raw text,
348 not a regular expression) or an re object.
349
350 Returns:
351 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -0700352 """
Stephen Warrenef824f52016-01-22 12:30:12 -0700353
354 if type(text) == type(''):
355 text = re.escape(text)
Stephen Warren68a9bb62016-01-27 23:57:49 -0700356 m = self.p.expect([text] + self.bad_patterns)
357 if m != 0:
Simon Glass573171e2024-10-09 18:29:02 -0600358 raise Unexpected(
359 "Unexpected pattern found on console (exp '{text}': " +
360 self.bad_pattern_ids[m - 1])
Stephen Warrenef824f52016-01-22 12:30:12 -0700361
Stephen Warren97a54662016-01-22 12:30:09 -0700362 def drain_console(self):
Stephen Warren75e731e2016-01-26 13:41:30 -0700363 """Read from and log the U-Boot console for a short time.
Stephen Warren97a54662016-01-22 12:30:09 -0700364
365 U-Boot's console output is only logged when the test code actively
366 waits for U-Boot to emit specific data. There are cases where tests
367 can fail without doing this. For example, if a test asks U-Boot to
368 enable USB device mode, then polls until a host-side device node
369 exists. In such a case, it is useful to log U-Boot's console output
370 in case U-Boot printed clues as to why the host-side even did not
371 occur. This function will do that.
372
373 Args:
374 None.
375
376 Returns:
377 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -0700378 """
Stephen Warren97a54662016-01-22 12:30:09 -0700379
380 # If we are already not connected to U-Boot, there's nothing to drain.
381 # This should only happen when a previous call to run_command() or
382 # wait_for() failed (and hence the output has already been logged), or
383 # the system is shutting down.
384 if not self.p:
385 return
386
387 orig_timeout = self.p.timeout
388 try:
389 # Drain the log for a relatively short time.
390 self.p.timeout = 1000
391 # Wait for something U-Boot will likely never send. This will
392 # cause the console output to be read and logged.
393 self.p.expect(['This should never match U-Boot output'])
Stephen Warren677b9cc2018-09-20 16:55:03 -0600394 except:
395 # We expect a timeout, since U-Boot won't print what we waited
396 # for. Squash it when it happens.
397 #
398 # Squash any other exception too. This function is only used to
399 # drain (and log) the U-Boot console output after a failed test.
400 # The U-Boot process will be restarted, or target board reset, once
401 # this function returns. So, we don't care about detecting any
402 # additional errors, so they're squashed so that the rest of the
403 # post-test-failure cleanup code can continue operation, and
404 # correctly terminate any log sections, etc.
Stephen Warren97a54662016-01-22 12:30:09 -0700405 pass
406 finally:
407 self.p.timeout = orig_timeout
408
Masami Hiramatsu4d3b9962022-02-16 15:16:02 +0900409 def ensure_spawned(self, expect_reset=False):
Stephen Warren75e731e2016-01-26 13:41:30 -0700410 """Ensure a connection to a correctly running U-Boot instance.
Stephen Warren10e50632016-01-15 11:15:24 -0700411
412 This may require spawning a new Sandbox process or resetting target
413 hardware, as defined by the implementation sub-class.
414
415 This is an internal function and should not be called directly.
416
417 Args:
Masami Hiramatsu4d3b9962022-02-16 15:16:02 +0900418 expect_reset: Boolean indication whether this boot is expected
419 to be reset while the 1st boot process after main boot before
420 prompt. False by default.
Stephen Warren10e50632016-01-15 11:15:24 -0700421
422 Returns:
423 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -0700424 """
Stephen Warren10e50632016-01-15 11:15:24 -0700425
426 if self.p:
Bin Meng739b3862022-05-17 23:24:43 +0800427 # Reset the console timeout value as some tests may change
428 # its default value during the execution
429 if not self.config.gdbserver:
Simon Glass64914152024-10-09 18:28:58 -0600430 self.p.timeout = TIMEOUT_MS
Stephen Warren10e50632016-01-15 11:15:24 -0700431 return
432 try:
Stephen Warren80eea632016-02-11 11:46:12 -0700433 self.log.start_section('Starting U-Boot')
Stephen Warren10e50632016-01-15 11:15:24 -0700434 self.at_prompt = False
Stephen Warren10e50632016-01-15 11:15:24 -0700435 self.p = self.get_spawn()
436 # Real targets can take a long time to scroll large amounts of
437 # text if LCD is enabled. This value may need tweaking in the
438 # future, possibly per-test to be optimal. This works for 'help'
439 # on board 'seaboard'.
Stephen Warren33db1ee2016-02-04 16:11:50 -0700440 if not self.config.gdbserver:
Simon Glass64914152024-10-09 18:28:58 -0600441 self.p.timeout = TIMEOUT_MS
Stephen Warren10e50632016-01-15 11:15:24 -0700442 self.p.logfile_read = self.logstream
Masami Hiramatsu4d3b9962022-02-16 15:16:02 +0900443 if expect_reset:
444 loop_num = 2
445 else:
446 loop_num = 1
447 self.wait_for_boot_prompt(loop_num = loop_num)
Stephen Warren10e50632016-01-15 11:15:24 -0700448 self.at_prompt = True
449 self.at_prompt_logevt = self.logstream.logfile.cur_evt
450 except Exception as ex:
451 self.log.error(str(ex))
452 self.cleanup_spawn()
453 raise
Stephen Warren80eea632016-02-11 11:46:12 -0700454 finally:
Stephen Warrenb1c556a2017-10-27 11:04:08 -0600455 self.log.timestamp()
Stephen Warren80eea632016-02-11 11:46:12 -0700456 self.log.end_section('Starting U-Boot')
Stephen Warren10e50632016-01-15 11:15:24 -0700457
458 def cleanup_spawn(self):
Stephen Warren75e731e2016-01-26 13:41:30 -0700459 """Shut down all interaction with the U-Boot instance.
Stephen Warren10e50632016-01-15 11:15:24 -0700460
461 This is used when an error is detected prior to re-establishing a
462 connection with a fresh U-Boot instance.
463
464 This is an internal function and should not be called directly.
465
466 Args:
467 None.
468
469 Returns:
470 Nothing.
Stephen Warren75e731e2016-01-26 13:41:30 -0700471 """
Stephen Warren10e50632016-01-15 11:15:24 -0700472
473 try:
474 if self.p:
475 self.p.close()
476 except:
477 pass
478 self.p = None
479
Masami Hiramatsu4d3b9962022-02-16 15:16:02 +0900480 def restart_uboot(self, expect_reset=False):
Simon Glass37c2ce12016-07-31 17:35:08 -0600481 """Shut down and restart U-Boot."""
482 self.cleanup_spawn()
Masami Hiramatsu4d3b9962022-02-16 15:16:02 +0900483 self.ensure_spawned(expect_reset)
Simon Glass37c2ce12016-07-31 17:35:08 -0600484
Simon Glass9bc20832016-07-04 11:58:39 -0600485 def get_spawn_output(self):
486 """Return the start-up output from U-Boot
487
488 Returns:
489 The output produced by ensure_spawed(), as a string.
490 """
491 if self.p:
492 return self.p.get_expect_output()
493 return None
494
Stephen Warren10e50632016-01-15 11:15:24 -0700495 def validate_version_string_in_text(self, text):
Stephen Warren75e731e2016-01-26 13:41:30 -0700496 """Assert that a command's output includes the U-Boot signon message.
Stephen Warren10e50632016-01-15 11:15:24 -0700497
498 This is primarily useful for validating the "version" command without
499 duplicating the signon text regex in a test function.
500
501 Args:
502 text: The command output text to check.
503
504 Returns:
505 Nothing. An exception is raised if the validation fails.
Stephen Warren75e731e2016-01-26 13:41:30 -0700506 """
Stephen Warren10e50632016-01-15 11:15:24 -0700507
508 assert(self.u_boot_version_string in text)
509
510 def disable_check(self, check_type):
Stephen Warren75e731e2016-01-26 13:41:30 -0700511 """Temporarily disable an error check of U-Boot's output.
Stephen Warren10e50632016-01-15 11:15:24 -0700512
513 Create a new context manager (for use with the "with" statement) which
514 temporarily disables a particular console output error check.
515
516 Args:
517 check_type: The type of error-check to disable. Valid values may
518 be found in self.disable_check_count above.
519
520 Returns:
521 A context manager object.
Stephen Warren75e731e2016-01-26 13:41:30 -0700522 """
Stephen Warren10e50632016-01-15 11:15:24 -0700523
524 return ConsoleDisableCheck(self, check_type)
Michal Simek6b463182016-05-19 07:57:41 +0200525
Love Kumarc35e66e2024-05-22 18:45:13 +0530526 def enable_check(self, check_type, check_pattern):
527 """Temporarily enable an error check of U-Boot's output.
528
529 Create a new context manager (for use with the "with" statement) which
530 temporarily enables a particular console output error check. The
531 arguments form a new element of bad_pattern_defs defined above.
532
533 Args:
534 check_type: The type of error-check or bad pattern to enable.
535 check_pattern: The regexes for text error pattern or bad pattern
536 to be checked.
537
538 Returns:
539 A context manager object.
540 """
541
542 return ConsoleEnableCheck(self, check_type, check_pattern)
543
Michal Simek6b463182016-05-19 07:57:41 +0200544 def temporary_timeout(self, timeout):
545 """Temporarily set up different timeout for commands.
546
547 Create a new context manager (for use with the "with" statement) which
548 temporarily change timeout.
549
550 Args:
551 timeout: Time in milliseconds.
552
553 Returns:
554 A context manager object.
555 """
556
557 return ConsoleSetupTimeout(self, timeout)