2018-05-06 21:58:06 +00:00
|
|
|
# SPDX-License-Identifier: GPL-2.0
|
2016-01-15 18:15:24 +00:00
|
|
|
# Copyright (c) 2015 Stephen Warren
|
|
|
|
# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
|
|
|
|
|
2021-11-22 23:01:48 +00:00
|
|
|
"""
|
|
|
|
Logic to interact with the sandbox port of U-Boot, running as a sub-process.
|
|
|
|
"""
|
2016-01-15 18:15:24 +00:00
|
|
|
|
|
|
|
import time
|
|
|
|
from u_boot_spawn import Spawn
|
|
|
|
from u_boot_console_base import ConsoleBase
|
|
|
|
|
|
|
|
class ConsoleSandbox(ConsoleBase):
|
2016-01-26 20:41:30 +00:00
|
|
|
"""Represents a connection to a sandbox U-Boot console, executed as a sub-
|
|
|
|
process."""
|
2016-01-15 18:15:24 +00:00
|
|
|
|
|
|
|
def __init__(self, log, config):
|
2016-01-26 20:41:30 +00:00
|
|
|
"""Initialize a U-Boot console connection.
|
2016-01-15 18:15:24 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
log: A multiplexed_log.Logfile instance.
|
|
|
|
config: A "configuration" object as defined in conftest.py.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Nothing.
|
2016-01-26 20:41:30 +00:00
|
|
|
"""
|
2016-01-15 18:15:24 +00:00
|
|
|
|
|
|
|
super(ConsoleSandbox, self).__init__(log, config, max_fifo_fill=1024)
|
2018-11-16 01:44:00 +00:00
|
|
|
self.sandbox_flags = []
|
2016-01-15 18:15:24 +00:00
|
|
|
|
|
|
|
def get_spawn(self):
|
2016-01-26 20:41:30 +00:00
|
|
|
"""Connect to a fresh U-Boot instance.
|
2016-01-15 18:15:24 +00:00
|
|
|
|
|
|
|
A new sandbox process is created, so that U-Boot begins running from
|
|
|
|
scratch.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
None.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
A u_boot_spawn.Spawn object that is attached to U-Boot.
|
2016-01-26 20:41:30 +00:00
|
|
|
"""
|
2016-01-15 18:15:24 +00:00
|
|
|
|
2016-07-04 17:58:40 +00:00
|
|
|
bcfg = self.config.buildconfig
|
|
|
|
config_spl = bcfg.get('config_spl', 'n') == 'y'
|
|
|
|
fname = '/spl/u-boot-spl' if config_spl else '/u-boot'
|
2017-09-14 21:34:43 +00:00
|
|
|
print(fname)
|
test/py: support running sandbox under gdbserver
Implement command--line option --gdbserver COMM, which does two things:
a) Run the sandbox process under gdbserver, using COMM as gdbserver's
communication channel.
b) Disables all timeouts, so that if U-Boot is halted under the debugger,
tests don't fail. If the user gives up in the middle of a debugging
session, they can simply CTRL-C the test script to abort it.
This allows easy debugging of test failures without having to manually
re-create the failure conditions. Usage is:
Window 1:
./test/py/test.py --bd sandbox --gdbserver localhost:1234
Window 2:
gdb ./build-sandbox/u-boot -ex 'target remote localhost:1234'
When using this option, it likely makes sense to use pytest's -k option
to limit the set of tests that are executed.
Simply running U-Boot directly under gdb (rather than gdbserver) was
also considered. However, this was rejected because:
a) gdb's output would then be processed by the test script, and likely
confuse it causing false failures.
b) pytest by default hides stdout from tests, which would prevent the
user from interacting with gdb.
While gdb can be told to redirect the debugee's stdio to a separate
PTY, this would appear to leave gdb's stdio directed at the test
scripts and the debugee's stdio directed elsewhere, which is the
opposite of the desired effect. Perhaps some complicated PTY muxing
and process hierarchy could invert this. However, the current scheme
is simple to implement and use, so it doesn't seem worth complicating
matters.
c) Using gdbserver allows arbitrary debuggers to be used, even those with
a GUI. If the test scripts invoked the debugger themselves, they'd have
to know how to execute arbitary applications. While the user could hide
this all in a wrapper script, this feels like extra complication.
An interesting future idea might be a --gdb-screen option, which could
spawn both U-Boot and gdb separately, and spawn the screen into a newly
created window under screen. Similar options could be envisaged for
creating a new xterm/... too.
--gdbserver currently only supports sandbox, and not real hardware.
That's primarily because the test hooks are responsible for all aspects of
hardware control, so there's nothing for the test scripts themselves can
do to enable gdbserver on real hardware. We might consider introducing a
separate --disable-timeouts option to support use of debuggers on real
hardware, and having --gdbserver imply that option.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
2016-02-04 23:11:50 +00:00
|
|
|
cmd = []
|
|
|
|
if self.config.gdbserver:
|
|
|
|
cmd += ['gdbserver', self.config.gdbserver]
|
|
|
|
cmd += [
|
2016-07-04 17:58:40 +00:00
|
|
|
self.config.build_dir + fname,
|
2016-04-04 17:04:50 +00:00
|
|
|
'-v',
|
2016-01-28 06:57:52 +00:00
|
|
|
'-d',
|
2016-07-03 15:40:36 +00:00
|
|
|
self.config.dtb
|
2016-01-28 06:57:52 +00:00
|
|
|
]
|
2018-11-16 01:44:00 +00:00
|
|
|
cmd += self.sandbox_flags
|
2016-01-28 06:57:53 +00:00
|
|
|
return Spawn(cmd, cwd=self.config.source_dir)
|
2016-01-15 18:15:24 +00:00
|
|
|
|
2018-11-16 01:44:00 +00:00
|
|
|
def restart_uboot_with_flags(self, flags):
|
|
|
|
"""Run U-Boot with the given command-line flags
|
|
|
|
|
|
|
|
Args:
|
|
|
|
flags: List of flags to pass, each a string
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
A u_boot_spawn.Spawn object that is attached to U-Boot.
|
|
|
|
"""
|
|
|
|
|
|
|
|
try:
|
|
|
|
self.sandbox_flags = flags
|
|
|
|
return self.restart_uboot()
|
|
|
|
finally:
|
|
|
|
self.sandbox_flags = []
|
|
|
|
|
2016-01-15 18:15:24 +00:00
|
|
|
def kill(self, sig):
|
2016-01-26 20:41:30 +00:00
|
|
|
"""Send a specific Unix signal to the sandbox process.
|
2016-01-15 18:15:24 +00:00
|
|
|
|
|
|
|
Args:
|
|
|
|
sig: The Unix signal to send to the process.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Nothing.
|
2016-01-26 20:41:30 +00:00
|
|
|
"""
|
2016-01-15 18:15:24 +00:00
|
|
|
|
|
|
|
self.log.action('kill %d' % sig)
|
|
|
|
self.p.kill(sig)
|
|
|
|
|
|
|
|
def validate_exited(self):
|
2016-01-26 20:41:30 +00:00
|
|
|
"""Determine whether the sandbox process has exited.
|
2016-01-15 18:15:24 +00:00
|
|
|
|
|
|
|
If required, this function waits a reasonable time for the process to
|
|
|
|
exit.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
None.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
Boolean indicating whether the process has exited.
|
2016-01-26 20:41:30 +00:00
|
|
|
"""
|
2016-01-15 18:15:24 +00:00
|
|
|
|
|
|
|
p = self.p
|
|
|
|
self.p = None
|
2017-09-14 21:34:44 +00:00
|
|
|
for i in range(100):
|
2016-01-15 18:15:24 +00:00
|
|
|
ret = not p.isalive()
|
|
|
|
if ret:
|
|
|
|
break
|
|
|
|
time.sleep(0.1)
|
|
|
|
p.close()
|
|
|
|
return ret
|