diff mbox series

[v3,3/5] bootloader: document the Bootloader Interface

Message ID 20220322112903.32726-3-christian.storm@siemens.com
State Accepted
Headers show
Series [v3,1/5] bootloader: runtime-dynamic bootloader selection | expand

Commit Message

Storm, Christian March 22, 2022, 11:29 a.m. UTC
Signed-off-by: Christian Storm <christian.storm@siemens.com>
---
 doc/source/bootloader_interface.rst | 164 ++++++++++++++++++++++++++++
 doc/source/index.rst                |   1 +
 2 files changed, 165 insertions(+)
 create mode 100644 doc/source/bootloader_interface.rst
diff mbox series

Patch

diff --git a/doc/source/bootloader_interface.rst b/doc/source/bootloader_interface.rst
new file mode 100644
index 0000000..9066c74
--- /dev/null
+++ b/doc/source/bootloader_interface.rst
@@ -0,0 +1,164 @@ 
+.. SPDX-FileCopyrightText: 2022 Christian Storm <christian.storm@siemens.com>
+.. SPDX-License-Identifier: GPL-2.0-only
+
+====================
+Bootloader Interface
+====================
+
+Overview
+========
+
+SWUpdate has bindings to various bootloaders in order to store persistent
+state information across reboots. Currently, the following bootloaders are
+supported:
+
+* A fake bootloader called "Environment in RAM",
+* `EFI Boot Guard <https://github.com/siemens/efibootguard>`_,
+* `U-Boot <https://www.denx.de/wiki/U-Boot>`_, and
+* `GRUB <https://www.gnu.org/software/grub/>`_.
+
+The actual (sub)set of bootloaders supported is a compile-time choice. At
+run-time, the compile-time set default bootloader interface implementation
+is used unless overruled to use another bootloader interface implementation
+via the ``-B`` command line switch or a configuration file (via the
+``bootloader`` setting in the ``globals`` section, see
+``examples/configuration/swupdate.cfg``).
+
+Note that the run-time support for some bootloaders, currently U-Boot and
+EFI Boot Guard, relies on loading the respective bootloader's environment
+modification shared library at run-time. Hence, even if support for
+a particular bootloader is compiled-in, the according shared library must
+be present and loadable on the target system at run-time for using this
+bootloader interface implementation.
+This allows, e.g., distributions to ship a generic SWUpdate package and
+downstream integrators to combine this generic package with the appropriate
+bootloader by just providing its environment modification shared library.
+
+
+Bootloader Interface Description
+================================
+
+The bootloader interface implementations are located in ``bootloader/``.
+Each bootloader has to implement the interface functions as defined in
+``include/bootloader.h``, more precisely
+
+.. code-block:: c
+
+    char *env_get(const char *name);
+    int env_set(const char *name, const char *value);
+    int env_unset(const char *name);
+    int apply_list(const char *filename);
+
+which
+retrieve a key's value from the bootloader environment,
+set a key to a value in the bootloader environment,
+delete a key-value pair from the bootloader environment, and
+apply the ``key=value`` pairs found in a file.
+
+
+Then, each bootloader interface implementation has to register itself to
+SWUpdate at run-time by calling the ``register_bootloader(const char *name,
+bootloader *bl)`` function that takes the bootloader's name and a pointer
+to ``struct bootloader`` as in ``include/bootloader.h`` which is filled
+with pointers to the respective above mentioned interface functions.
+If the bootloader setup fails and hence it cannot be successfully registered,
+e.g., because the required shared library for environment modification cannot
+be loaded, ``NULL`` is to be returned as pointer to ``struct bootloader``.
+
+For example, assuming a bootloader named "trunk" and (static) interface
+functions implementations ``do_env_{get,set,unset}()`` as well as
+``do_apply_list()`` in a ``bootloader/trunk.c`` file, the following snippet
+registers this bootloader to SWUpdate at run-time:
+
+.. code-block:: c
+
+    static bootloader trunk = {
+        .env_get = &do_env_get,
+        .env_set = &do_env_set,
+        .env_unset = &do_env_unset,
+        .apply_list = &do_apply_list
+    };
+
+    __attribute__((constructor))
+    static void trunk_probe(void)
+    {
+        (void)register_bootloader("trunk", &trunk);
+    }
+
+.. attention:: Take care to uniquely name the bootloader.
+
+
+See, e.g., ``bootloader/{uboot,ebg}.c`` for examples of a bootloader using
+a shared environment modification library and ``bootloader/{grub,none}.c``
+for a simpler bootloader support example.
+
+
+Bootloader Build System Integration
+===================================
+
+A bootloader support implementation needs to be registered to the kconfig
+build system.
+
+First, the bootloader support implementation, named "trunk" and implemented
+in ``bootloader/trunk.c`` for example, needs to be added to
+``bootloader/Config.in`` in the ``Bootloader Interfaces`` menu as
+follows:
+
+.. code-block:: kconfig
+
+    ...
+
+    menu "Bootloader"
+
+    menu "Bootloader Interfaces"
+
+    ...
+
+    config BOOTLOADER_TRUNK
+        bool "TrUnK Bootloader"
+        help
+          Support for the TrUnK Bootloader
+          https://github.com/knurt/trunk
+
+
+Then, in order to enable the compile-time selection of the "trunk" bootloader
+as default, add a section to the ``Default Bootloader Interface`` choice
+submenu of the ``Bootloader`` menu as follows:
+
+.. code-block:: kconfig
+
+    choice
+    	prompt "Default Bootloader Interface"
+    	help
+    	  Default bootloader interface to use if not explicitly
+    	  overridden via configuration or command-line option
+    	  at run-time.
+
+    ...
+
+    config BOOTLOADER_DEFAULT_TRUNK
+        bool "TrUnK"
+        depends on BOOTLOADER_TRUNK
+        help
+          Use TrUnK as default bootloader interface.
+
+
+Finally, ``bootloader/Makefile`` needs to be adapted to build the "trunk"
+bootloader support code, given ``BOOTLOADER_TRUNK`` was enabled:
+
+.. code-block:: makefile
+
+    obj-$(CONFIG_BOOTLOADER_TRUNK) += trunk.o
+
+
+If the "trunk" bootloader, for example, requires loading a shared
+environment modification library, then ``Makefile.flags`` needs to be
+adapted as well, e.g., as follows:
+
+.. code-block:: makefile
+
+    ifeq ($(CONFIG_BOOTLOADER_TUNK),y)
+    LDLIBS += dl
+    endif
+
+
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 8ed508e..3b9998e 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -47,6 +47,7 @@  SWUpdate Documentation
    swupdate-ipc-interface.rst
    progress.rst
    bindings.rst
+   bootloader_interface.rst
    building-with-yocto.rst
    swupdate-best-practise.rst
    delta-update.rst