1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
.. 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(BOOTLOADER_TRUNK, &trunk);
}
with
.. code-block:: c
#define BOOTLOADER_TRUNK "trunk"
added to ``include/bootloader.h`` as a single central "trunk" bootloader
name definition aiding in maintaining the uniqueness of bootloader names.
This new "trunk" bootloader should also be added to the Suricatta Lua
Module interface specification's bootloader Table
``suricatta.bootloader.bootloaders = { ... }`` in
``suricatta/suricatta.lua``.
.. 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/Kconfig`` 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
|