[v3] doc: develop: Describe system configuration

Heinrich Schuchardt xypron.glpk at gmx.de
Fri Jul 29 18:51:50 CEST 2022

On 7/29/22 18:07, Tom Rini wrote:
> Start by describing in general the best practices for how to implement
> configuration of some aspect of U-Boot.  This generally means finding
> the right choices for when something should be static or dynamically
> configured and enabled.  Then further document when to use CONFIG or CFG
> namespaces for static configuration.
> Signed-off-by: Tom Rini <trini at konsulko.com>
> ---
> Changes in v3:
> - Drop RFC prefix.
> - Incorporate most of the specific wording changes Heinrich requested
>    against v2.
> - Heinrich disliked the "namespace" wording in v2, and that in turn was
>    a hold over from when this talked only about CONFIG vs CFG. Remove
>    that word entirely and instead talk about configuration mechanisms.
>    Reword a number of sections and examples so that they read better or
>    hopefully more clearly now that we talk about different mechanisms.
> - Expand on when to use each configuration mechanism.  Generally don't
>    refer to CONFIG but instead Kconfig.
> RFCv2:
> - Based on Pali's feedback, remove the README section and start a new
>    section in this document to cover when to use each namespace. Try and
>    be clear about when to use "hidden" Kconfig options rather than CFG as
>    well.
> - Based on Heinrich's feedback, rename this to system_configuration.rst
>    and include some introductory remarks on when to use some dynamic or
>    static configuration.  Link to the driver model code for dynamic
>    configuration and then explain the CONFIG vs CFG namespaces for static
>    configuration.
> RFCv1:
> - This is essentially my idea on how to better handle the problem of
>    CONFIG values that just don't fit in Kconfig because it makes much
>    more sense to define them statically for a given SoC or calculate them
>    from other values, and so on.  One example here would be to revert
>    c7fad78ec0ee ("Convert CONFIG_SYS_BR0_PRELIM et al to Kconfig") and
>    re-name these to CFG_SYS_.. instead. Another big example here would be
>    a global search-and-replace of 's/CONFIG_HPS_/CFG_HPS_/g' as that's
>    all tool-generated. Not all CONFIG_SYS_ options would get this as
>    boolean choices are well handled in Kconfig, and that may not be clear
>    enough in what I wrote here?
> ---
>   README                               |  21 -----
>   doc/develop/index.rst                |   1 +
>   doc/develop/system_configuration.rst | 132 +++++++++++++++++++++++++++
>   3 files changed, 133 insertions(+), 21 deletions(-)
>   create mode 100644 doc/develop/system_configuration.rst
> diff --git a/README b/README
> index 2c4bde0b3297..623f35907217 100644
> --- a/README
> +++ b/README
> @@ -166,27 +166,6 @@ Directory Hierarchy:
>   Software Configuration:
>   =======================
> -Configuration is usually done using C preprocessor defines; the
> -rationale behind that is to avoid dead code whenever possible.
> -
> -There are two classes of configuration variables:
> -
> -* Configuration _OPTIONS_:
> -  These are selectable by the user and have names beginning with
> -  "CONFIG_".
> -
> -* Configuration _SETTINGS_:
> -  These depend on the hardware etc. and should not be meddled with if
> -  you don't know what you're doing; they have names beginning with
> -  "CONFIG_SYS_".
> -
> -Previously, all configuration was done by hand, which involved creating
> -symbolic links and editing configuration files manually. More recently,
> -U-Boot has added the Kbuild infrastructure used by the Linux kernel,
> -allowing you to use the "make menuconfig" command to configure your
> -build.
> -
> -
>   Selection of Processor Architecture and Board Type:
>   ---------------------------------------------------
> diff --git a/doc/develop/index.rst b/doc/develop/index.rst
> index 73741ceb6a2f..7c41e3f1b6e5 100644
> --- a/doc/develop/index.rst
> +++ b/doc/develop/index.rst
> @@ -13,6 +13,7 @@ General
>      designprinciples
>      process
>      release_cycle
> +   system_configuration
>   Implementation
>   --------------
> diff --git a/doc/develop/system_configuration.rst b/doc/develop/system_configuration.rst
> new file mode 100644
> index 000000000000..1279d12cb7ae
> --- /dev/null
> +++ b/doc/develop/system_configuration.rst
> @@ -0,0 +1,132 @@
> +.. SPDX-License-Identifier: GPL-2.0+
> +
> +System configuration
> +====================
> +
> +There are a number of different aspects to configuring U-Boot to build and then
> +run on a given platform or set of platforms. Broadly speaking, some aspects of
> +the world can be configured at run time and others must be done at build time.
> +In general run time configuration is preferred over build time configuration.
> +But when making these decisions, we also need to consider if we're talking about
> +a feature that could be useful to virtually every platform or something specific
> +to a single hardware platform. The resulting image size is also another
> +important consideration. Finally, run time configuration has additional overhead
> +both in terms of resource requirements and wall clock time. All of this means
> +that care must be taken when writing new code to select the most appropriate
> +configuration mechanism.
> +
> +When adding new features to U-Boot, be they a new subsystem or SoC support or
> +new platform for an existing supported SoC, the preferred configuration order
> +is:
> +
> +#. Hardware based run time configuration. Examples of this include reading
> +   processor specific registers, or a set of board specific GPIOs or an EEPROM
> +   with a known format to it. These are the cases where we either cannot or
> +   should not be relying on device tree checks. We use this for cases such as
> +   optimized boot time or starting with a generic device tree and then enabling
> +   or disabling features as we boot.
> +
> +#. Making use of our Kconfig infrastructure and C preprocessor macros that have
> +   the prefix ``CONFIG``. This is the primary method of build time
> +   configuration. This is generally the best fit for when we want to enable or
> +   disable some sort of feature, such as the SoC or network support. The
> +   ``CONFIG`` prefix for C preprocessor macros is strictly reserved for Kconfig
> +   usage only.
> +
> +#. Making use of the :doc:`device tree <devicetree/control>` to determine at
> +   run time how to configure a feature that we have enabled via Kconfig. For
> +   example, we would use Kconfig to enable an i2c chip driver, but use the device
> +   tree to know where the i2c chip resides in memory and other details we need
> +   in order to configure the bus.
> +
> +#. Making use of C header files directly and defining C preprocessor macros that
> +   have the ``CFG`` prefix. While the ``CFG`` prefix is reserved for this build
> +   time configuration mechanism, the usage is ad hoc. This is to be used when the
> +   previously mentioned mechanisms are not possible, or for legacy code that has
> +   not been converted.
> +
> +Dynamic run time configuration methods.
> +---------------------------------------
> +
> +Details of hardware specific run time configuration methods are found within the
> +documentation for a given processor family or board.
> +
> +Details of how to use run time configuration based on :doc:`driver model
> +<driver-model/index>` are covered in that documentation section.
> +
> +Static build time configuration methods
> +---------------------------------------
> +
> +There are two mechanisms used to control the build time configuration of U-Boot.
> +One is utilizing Kconfig and ``CONFIG`` prefixed macros and the other is ad hoc
> +usage of ``CFG`` prefixed macros. Both of these are used when it is either not
> +possible or not practical to make a run time determination about some
> +functionality of the hardware or a required software feature or similar. Each of
> +these has their own places where they are better suited than the other for use.
> +
> +The `Kconfig language
> +<https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html>`_ is well
> +documented and used in a number of projects, including the Linux kernel. We
> +implement this with the Kconfig files found throughout our sources. This
> +mechanism is the preferred way of exposing new configuration options as there
> +are a number of ways for both users and system integrators to manage and change
> +these options. Some common examples here are to enable a specific command within
> +U-Boot or even a whole subsystem such as NAND flash or network connectivity.
> +
> +The ``CFG`` mechanism is implemented directly as C preprocessor values or
> +macros, depending on what they are in turn describing. While we have some
> +functionality that is very reasonable to expose to the end user to enable or
> +disable we have other places where we need to describe things such as register
> +locations or values, memory map ranges and so on. When practical, we should be
> +getting these values from the device tree. However, there are cases where this
> +is either not practical due to when we need the information and may not have a
> +device tree yet or due to legacy reasons code has not been rewritten.
> +
> +When to use each mechanism
> +^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +While there are some cases where it should be fairly obvious where to use each
> +namespace, as for example a command would done via Kconfig, a new i2c driver


I will adjust this when merging.

Reviewed-by: Heinrich Schuchardt <xypron.glpk at gmx.de>

> +should use Kconfig and be configured via driver model and a header of values
> +generated by an external tool should be ``CFG``, there will be cases where it's
> +less clear and one needs to take care when implementing it. In general,
> +configuration *options* should be done in Kconfig and configuration *settings*
> +should done in driver model or ``CFG``. Let us discuss things to keep in mind
> +when picking the appropriate mechanism.
> +
> +A thing to keep in mind is that we have a strong preference for using Kconfig as
> +the primary build time configuration mechanism. Options expressed this way let
> +us easily express dependencies and abstractions. In addition, given that many
> +projects use this mechanism means it has a broad set of tooling and existing
> +knowledge base.
> +
> +Consider the example of a SHA256 hardware acceleration engine. This would be a
> +feature of the SoC and so something to not ask the user if it exists, but we
> +would want to have our generic framework for such engines be optionally
> +available and depend on knowing we have this engine on a given hardware
> +platform. Expressing this should be done as a hidden Kconfig symbol that is
> +``select``'ed by the SoC symbol which would in turn be ``select``'ed by the
> +board option, which is user visible. Hardware features that are either present
> +or not present should be expressed in Kconfig and in a similar manner, features
> +which will always have a constant value such as "this SoC always has 4 cores and
> +4 threads per core" should be as well.
> +
> +This brings us to differentiating between a configuration *setting* versus a
> +hardware feature. To build on the previous example, while we may know the number
> +of cores and threads, it's possible that within a given family of SoCs the base
> +addresses of peripherals has changed, but the register offsets within have not.
> +The preference in this case is to get our information from the device tree and
> +perform run time configuration. However, this is not always practical and in
> +those cases we instead rely on the ``CFG`` mechanism. While it would be possible
> +to use Kconfig in this case, it would result in using calculated rather than
> +constructed values, resulting in less clear code. Consider the example of a set
> +of register values for a memory controller. Defining this as a series of logical
> +ORs and shifts based on other defines is more clear than the Kconfig entry that
> +set the calculated value alone.
> +
> +When it has been determined that the practical solution is to utilize the
> +``CFG`` mechanism, the next decision is where to place these settings. It is
> +strongly encouraged to place these in the architecture header files, if they are
> +generic to a given SoC, or under the board directory if board specific. Placing
> +them under the board.h file in the *include/configs/* directory should be seen
> +as a last resort.

More information about the U-Boot mailing list