From 743e46d5a0e2dfc16289c502f48ffc025cce7d76 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 21 May 2024 07:32:29 -0600 Subject: [PATCH] doc: Add documentation for U-Boot integration [v2] Cover the drivers, scripts, pytest and the Gitlab information. Note: This implementation is the result of working through what is needed in Labgrid to support U-Boot labs. I did initially file quite a few issues[1] but there has not been a lot of traction and I got feedback that I have overwhelmed people with too many. So I have stopped filing issues on the things I hit along the way. I have carried on with the implementation in the hope that this can be a better basis for discussion. Note that all of these patches are work-in-progress. Feedback on any or all may change the implementation and documentation substantially. Changes in v4: - Support for Beagleplay, which needs files from two separate U-Boot builds - Support for a 'recovery' button needed to boot the image - Tidy up the internal-console support - Fix pytest behaviour with an unpatched U-Boot (that doesn't have lab mode) Changes in v3: - Rebase on top of grpc branch - Don't mess with terminal setting unless stdin is a terminal - Don't show an error if there are no resources when auto-acquiring - Support QEMU in UBootWriter Some changes in v2: - Rationalise the flags for the U-Boot scripts - Support tracing with em100 - Support an internal terminal instead of microcom - Add a -D flag for debugging - Support send-only boards - Add a way to build the U-Boot config - Add a control for buildman's process-limit - allow the build-dir to be specified in a variable - add documentation about U-Boot-pytest integration - add source_dir and config_file to UBootProviderDriver - add an internal terminal - expand the U-Boot scripts - significantly improve the U-Boot-pytest integration The approximate diffstat is: contrib/sync-places.py | 23 +- contrib/u-boot/.gitignore | 1 + contrib/u-boot/_ub-bisect-try | 47 ++ contrib/u-boot/conftest.py | 21 + contrib/u-boot/get_args.sh | 128 +++++ contrib/u-boot/index.rst | 232 +++++++++ contrib/u-boot/lg-client | 11 + contrib/u-boot/lg-env | 10 + contrib/u-boot/test_smoke.py | 3 + contrib/u-boot/ub-bisect | 44 ++ contrib/u-boot/ub-cli | 39 ++ contrib/u-boot/ub-int | 41 ++ contrib/u-boot/ub-pyt | 69 +++ contrib/u-boot/ub-smoke | 48 ++ doc/configuration.rst | 611 ++++++++++++++++++++++- doc/usage.rst | 288 +++++++++++ labgrid/driver/__init__.py | 10 +- labgrid/driver/common.py | 11 + labgrid/driver/consoleexpectmixin.py | 7 + labgrid/driver/powerdriver.py | 29 ++ labgrid/driver/qemudriver.py | 84 ++-- labgrid/driver/recoverydriver.py | 25 + labgrid/driver/resetdriver.py | 7 + labgrid/driver/servodriver.py | 157 ++++++ labgrid/driver/sfemulatordriver.py | 102 ++++ labgrid/driver/ubootdriver.py | 27 +- labgrid/driver/ubootproviderdriver.py | 323 ++++++++++++ labgrid/driver/ubootwriterdriver.py | 160 ++++++ labgrid/driver/usbhidrelay.py | 7 +- labgrid/driver/usbloader.py | 170 ++++++- labgrid/driver/usbstoragedriver.py | 18 +- labgrid/factory.py | 4 +- labgrid/protocol/__init__.py | 1 + labgrid/protocol/bootstrapprotocol.py | 8 +- labgrid/protocol/recoveryprotocol.py | 14 + labgrid/protocol/resetprotocol.py | 12 + labgrid/pytestplugin/fixtures.py | 21 +- labgrid/pytestplugin/hooks.py | 8 + labgrid/remote/client.py | 351 ++++++++----- labgrid/remote/config.py | 7 +- labgrid/remote/exporter.py | 122 ++++- labgrid/resource/__init__.py | 6 + labgrid/resource/remote.py | 24 + labgrid/resource/servo.py | 485 ++++++++++++++++++ labgrid/resource/sfemulator.py | 33 ++ labgrid/resource/suggest.py | 6 + labgrid/resource/udev.py | 33 ++ labgrid/strategy/ubootstrategy.py | 151 +++++- labgrid/target.py | 120 ++++- labgrid/util/helper.py | 220 ++++---- labgrid/util/ssh.py | 3 +- labgrid/util/term.py | 184 +++++++ labgrid/var_dict.py | 8 + man/labgrid-client.1 | 6 + man/labgrid-client.rst | 4 + man/labgrid-device-config.5 | 4 + 56 files changed, 4267 insertions(+), 321 deletions(-) [1] https://github.com/labgrid-project/labgrid/issues/created_by/sjg20 Signed-off-by: Simon Glass --- doc/configuration.rst | 11 ++ doc/usage.rst | 277 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+) diff --git a/doc/configuration.rst b/doc/configuration.rst index 147a1957e..e5317847c 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -2021,6 +2021,8 @@ Arguments: - login_timeout (int, default=60): timeout for password/login prompt detection - for other arguments, see `UBootDriver`_ +.. _UBootProviderInfo: + UBootProviderDriver ~~~~~~~~~~~~~~~~~~~ @@ -2064,6 +2066,11 @@ Variables: specified in the environment file - do-clean (str): If set to "1" this cleans the build before starting, otherwise it does an incremental build + - build-dir (str): If set, this is used as the build directory for U-Boot + - process-limit (int): Limits the number of buildman processes which can + be running jobs at once. Set this to 1 to avoid over-taxing your + CPU. Buildman does its own multithreading, so each process will use + all available CPUs anyway. Environment variables: - U_BOOT_BUILD_DIR (str): If present, this is used as the build directory for @@ -2115,6 +2122,8 @@ Tools: tools: buildman: "buildman.stable" +.. _UBootWriterInfo: + UBootWriterDriver ~~~~~~~~~~~~~~~~~ @@ -3875,6 +3884,8 @@ the "shell" state: This command would transition directly into a Linux shell and activate the `ShellDriver`_. +.. _UBootStrategyInfo: + UBootStrategy ~~~~~~~~~~~~~ A :any:`UBootStrategy` has five states: diff --git a/doc/usage.rst b/doc/usage.rst index 95caa4f22..8b163687a 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -883,3 +883,280 @@ like this: $ labgrid-client -p example allow sirius/john To remove the allow it is currently necessary to unlock and lock the place. + +U-Boot Integration +------------------ + +.. note:: + See status_ for current status and development branches. + +Most ARM boards (and some others) use U-Boot as their bootloader. Labgrid +provides various features to help with development and testing on these boards. +Together these features allow interactive use of Labgrid to build U-Boot from +source, write it to a board and boot it. Support is provided for U-Boot's pytest +and Gitlab setup. + +This section describes the various features which contribute to the overall +functionality. The names of contributed scripts (in *contrib/u-boot*) are shown +in brackets. + +Interactive use +~~~~~~~~~~~~~~~ + +Labgrid provides a 'console' command which can be used to connect to a board. +The :ref:`UBootStrategyInfo` driver provides a way to power cycle (or reset) +the board so that U-Boot starts. It also provides two useful states: + +- `start` which starts up U-Boot and lets it boot (*ub-int*) +- `uboot` which starts up U-Boot and stops it at the CLI prompt (*ub-cli*) + +Both of these are useful in development. + +Building U-Boot +~~~~~~~~~~~~~~~ + +Labgrid intentionally +`doesn't include `_ +build functionality as usually the software-under-test already comes with a +build system and it wants to test the artifacts as built by the "real" build +system. + +U-Boot is no exception and it provides the +`buildman `_ for this +purpose. + +Still, for interactive use some sort of build is needed. The +:ref:`UBootProviderInfo` provides an interface to buildman and a way of dealing +with board-specific binary blobs. The buildman tool works automatically provided +that you have set it up with suitable toolchains. See +`buildman `_ for more +information. + +Writing U-Boot +~~~~~~~~~~~~~~ + +Writing U-Boot to a board can be complicated, because each SoC uses its own +means of booting. The other problem is that special lab hardware is generally +needed to update the boot device, e.g. +`SD-wire `_. + +Fortunately Labgrid provides the means for manipulating the lab hardware. All +that is needed is a driver which understands where to write images, which files +to use and the sequence to use in each case. The :ref:`UBootWriterInfo` driver +handles this. It picks out the necessary files from a build directory and writes +them to the selected boot media, or sends them using the SoC-specific bootrom. +Combined with :ref:`UBootStrategyInfo` it provides automated updating of U-Boot +on suported SoCs regardless of the lab setup. + +Run labgrid tests +~~~~~~~~~~~~~~~~~ + +Labgrid provides integration with pytest. As part of the U-Boot integration, a +conftest.py file is provided which can build and smoke-test U-Boot on a board +(*ub-smoke*). + +Run U-Boot tests +~~~~~~~~~~~~~~~~~ + +It is also possible to run the U-Boot tests (*ub-pyt*). To do this you will need +to set up Labgrid integration with the +`U-Boot test hooks `_. +To do this, create the directory `u-boot-test-hooks/bin/$hostname` and add an +executable file called `common.labgrid` which sets the crossbar and environment +information: + +.. code-block:: bash + + export LG_CROSSBAR="ws://kea:20408/ws" + export LG_ENV="/path/to/env.cfg" + + flash_impl=none + reset_impl=none + console_impl=labgrid + release_impl=labgrid + +The last four lines tell the hooks to use labgrid. + +Then create another executable file (in the same directory) called 'conf.all', +containing: + +.. code-block:: bash + + . "${bin_dir}/${hostname}/common-labgrid" + +Bisecting +~~~~~~~~~ + +It is possible to use the *ub-pyt* or *ub-smoke* scripts with `git bisect run` +to bisect a problem on a particular board. However there is a slightly more +powerful script which supports applying a commit each time (*ub-bisect*). + +Setting up pytest +~~~~~~~~~~~~~~~~~ + +To set up the U-Boot pytest integration: + +#. Copy the `contrib/u-boot` directory to somewhere suitable and add it to your + path. For example: + +.. code-block:: bash + + cp -a contrib/u-boot ~/bin/u-boot + echo 'PATH="$PATH:~/bin/u-boot"' >> ~/.bashrc + +#. Edit the `lg-env` file to set the lab parameters according to your setup. +#. Start a new terminal, or login again, so the path updates. You can now use + the scripts as documented below. + +Gitlab Integration +~~~~~~~~~~~~~~~~~~ + +U-Boot uses `Gitlab `_ as the basis for its Continuous +Integration (CI) system (`U-Boot instance `_). +It is possible to set up your own lab which integrates with Gitlab, with your +own Git lab 'runner' which can control Labgrid. This allows pushing branches to +Gitlab and running tests on real hardware, similarly to how QEMU is used in +Gitlab. + +To set this up: + +#. Install `gitlab-runner` using these + `instructions `_. + +#. Register a + `new runner `_ + following the instructions using your custodian CI settings (i.e. do this at + `https://source.denx.de`). + + Select Linux and with tags set to `lab`. Click `Create runner` and use the + command line to register the runner. Use `-lab` (for example + `kea-lab`) as your host name and select `shell` as the executor: + + .. code-block:: console + + $ gitlab-runner register --url https://source.denx.de --token glrt-xxx + Enter the GitLab instance URL (for example, https://gitlab.com/): + [https://source.denx.de]: + Verifying runner... is valid runner=yyy + Enter a name for the runner. This is stored only in the local config.toml file: + []: -lab + Enter an executor: ssh, parallels, docker-windows, docker+machine, kubernetes, instance, custom, shell, virtualbox, docker, docker-autoscaler: + shell + Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! + +#. Edit the resulting `/etc/gitlab-runner/config.toml` file to allow more than + one job at a time by adding 'concurrent = x' where x is the number of jobs. + Here we use concurrent = 8 (this is just an example; don't replace your file + with this): + + .. code-block:: toml + + concurrent = 8 + check_interval = 0 + shutdown_timeout = 0 + + [session_server] + session_timeout = 1800 + + [[runners]] + name = "ellesmere-lab" + url = "https://source.denx.de" + id = 130 + token = "..." + token_obtained_at = 2024-05-15T20:41:29Z + token_expires_at = 0001-01-01T00:00:00Z + executor = "shell" + [runners.custom_build_dir] + +#. Gitlab will run tests as the 'gitlab-runner' user. Make sure your labgrid + installation is installed such that it is visible to that user. One way is: + + .. code-block:: bash + + sudo su - gitlab-runner + cd /path/to/labgrid + pip install . + +#. Add the following to U-Boot's `.gitlab-ci.yml`, adjusting the variables as + needed. For trying it out initially you might want to disable all the other + rules by changing `when: always` to `when: never`: + + .. code-block:: yaml + + .lab_template: &lab_dfn + stage: lab + tags: [ 'lab' ] + script: + # Environment: + # SRC - source tree + # ROOT - directory above that + # OUT - output directory for builds + - export SRC="$(pwd)" + - ROOT="$(dirname ${SRC})" + - export OUT="${ROOT}/out" + - export PATH=$PATH:~/bin + - export PATH=$PATH:/vid/software/devel/ubtest/u-boot-test-hooks/bin + + # Load it on the device + - ret=0 + - echo "board ${BOARD} id ${ID}" + - ${SRC}/test/py/test.py -B "${BOARD}" --id ${ID} --configure + --build-dir "${OUT}/current/${BOARD}" -k "not bootstd"|| ret=$? + - if [[ $ret -ne 0 ]]; then + exit $ret; + fi + + rpi3: + variables: + BOARD: rpi_3_32b ## This is a U-Boot board name + ID: rpi3 ## This is the corresponding role/target + <<: *lab_dfn + +#. Commit your changes and push to your custodian tree. This example shows the + driver model tree at a remote called 'dm': + + .. code-block:: bash + + $ git remote -v |grep dm + dm git@source.denx.de:u-boot/custodians/u-boot-dm.git (fetch) + dm git@source.denx.de:u-boot/custodians/u-boot-dm.git (push) + $ git push dm HEAD:try + +#. Navigate to the pipelines and you should see your tests running. You can + debug things from there, e.g. using the `ub-int` or `ub-pyt` scripts on an + individual board. An example may be visible + `here `_. + +Scripts +~~~~~~~ + +Various scripts are provided in the `contrib/` directory, specifically targeted +at U-Boot testing and development. + +.. include:: ../contrib/u-boot/index.rst + + +.. _status: + +U-Boot Integration Status +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Date: May '24 +Overall status: Ready for early testing + +Required pieces: + +- `Labgrid WIP PR `_ +- `U-Boot test hooks branch `_ +- `U-Boot branch `_ (needed for + U-Boot pytest integration) + +Testing has been very limited, basically a set of 21 boards, including sunxi, +rpi, RK3399, ODroid-C4, pine64, Orange Pi PC, various Chromebooks and Intel +Minnowboard Max. + +Some U-Boot pytests fails on some hardware: +- TPM tests fail on boards with a TPM +- test_log_format fails on several (perhaps all?) boards + +There are likely many other problems.