[PATCH v6 01/25] doc: Add documentation about devicetree usage

Heinrich Schuchardt xypron.glpk at gmx.de
Fri Dec 3 14:09:05 CET 2021


On 12/3/21 13:34, Heinrich Schuchardt wrote:
> On 12/2/21 16:58, Simon Glass wrote:
>> At present some of the ideas and techniques behind devicetree in U-Boot
>> are assumed, implied or unsaid. Add some documentation to cover how
>> devicetree is build, how it can be modified and the rules about using
>> the various CONFIG_OF_... options.
>>
>> Signed-off-by: Simon Glass <sjg at chromium.org>
>> Reviewed-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>
>> ---
>> This patch attracted quite a bit of discussion here:
>>
>> https://patchwork.ozlabs.org/project/uboot/patch/20210909201033.755713-4-sjg@chromium.org/
>>
>>
>> I have not included the text suggested by François. While I agree that
>> it would be useful to have an introduction in this space, I do not agree
>> that we should have two devicetrees or that U-Boot should not have its
>> own
>> things in the devicetree, so it is not clear to me what we should
>> actually
>> write.
>>
>> The 'Devicetree Control in U-Boot' docs were recently merged and these
>> provide some base info, for now.
>>
>> Changes in v6:
>> - Fix description of OF_BOARD so it refers just to the current state
>> - Explain that the 'two devicetrees' refers to two *control* devicetrees
>>
>> Changes in v5:
>> - Bring into the OF_BOARD series
>> - Rebase to master and drop mention of OF_PRIOR_STAGE, since removed
>> - Refer to the 'control' DTB in the first paragraph
>> - Use QEMU instead of qemu
>>
>> Changes in v3:
>> - Clarify the 'bug' refered to at the top
>> - Reword 'This means that there' paragraph to explain U-Boot-specific
>> things
>> - Move to doc/develop/devicetree now that OF_CONTROL is in the docs
>>
>> Changes in v2:
>> - Fix typos per Sean (thank you!) and a few others
>> - Add a 'Use of U-Boot /config node' section
>> - Drop mention of dm-verity since that actually uses the kernel cmdline
>> - Explain that OF_BOARD will still work after these changes (in
>>    'Once this bug is fixed...' paragraph)
>> - Expand a bit on the reason why the 'Current situation' is bad
>> - Clarify in a second place that Linux and U-Boot use the same devicetree
>>    in 'To be clear, while U-Boot...'
>> - Expand on why we should have rules for other projects in
>>    'Devicetree in another project'
>> - Add a comment as to why devicetree in U-Boot is not 'bad design'
>> - Reword 'in-tree U-Boot devicetree' to 'devicetree source in U-Boot'
>> - Rewrite 'Devicetree generated on-the-fly in another project' to cover
>>    points raised on v1
>> - Add 'Why does U-Boot have its nodes and properties?'
>> - Add 'Why not have two devicetrees?'
>>
>>   doc/develop/devicetree/dt_update.rst | 555 +++++++++++++++++++++++++++
>>   doc/develop/devicetree/index.rst     |   1 +
>>   2 files changed, 556 insertions(+)
>>   create mode 100644 doc/develop/devicetree/dt_update.rst
>>
>> diff --git a/doc/develop/devicetree/dt_update.rst
>> b/doc/develop/devicetree/dt_update.rst
>> new file mode 100644
>> index 00000000000..a1429d6e21a
>> --- /dev/null
>> +++ b/doc/develop/devicetree/dt_update.rst
>> @@ -0,0 +1,555 @@
>> +.. SPDX-License-Identifier: GPL-2.0+
>> +
>> +Updating the devicetree
>> +=======================
>> +
>> +U-Boot uses devicetree for runtime configuration and storing required
>> blobs or
>> +any other information it needs to operate. This is called the 'control'
>> +devicetree since it controls U-Boot. It is possible to update the
>> control
>> +devicetree separately from actually building U-Boot. This provides a
>> good degree
>> +of control and flexibility for firmware that uses U-Boot in
>> conjunction with
>> +other project.
>> +
>> +There are many reasons why it is useful to modify the devicetree
>> after building
>> +it:
>> +
>> +- Configuration can be changed, e.g. which UART to use
>> +- A serial number can be added
>> +- Public keys can be added to allow image verification
>> +- Console output can be changed (e.g. to select serial or vidconsole)
>> +
>> +This section describes how to work with devicetree to accomplish your
>> goals.
>> +
>> +See also :doc:`../devicetree/control` for a basic summary of the
>> available
>> +features.
>> +
>> +
>> +Devicetree source
>> +-----------------
>> +
>> +Every board in U-Boot must include a devicetree sufficient to build
>> and boot
>> +that board on suitable hardware (or emulation). This is specified
>> using the
>> +`CONFIG DEFAULT_DEVICE_TREE` option.
>> +
>> +
>> +Current situation (October 2021)
>> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> +
>> +As an aside, at present U-Boot allows `CONFIG_DEFAULT_DEVICE_TREE` to
>> be empty,
>> +e.g. if `CONFIG_OF_BOARD` is used. This has unfortunately created an
>> enormous
>> +amount of confusion and some wasted effort. This was not intended.
>> Support for
>> +an empty `CONFIG_DEFAULT_DEVICE_TREE` will be dropped soon.
>> +
>> +Some of the problems created are:
>> +
>> +- It is not obvious that the devicetree is coming from another project
>> +
>> +- There is no way to see even a sample devicetree for these platform
>> in U-Boot,
>> +  so it is hard to know what is going on, e.g. which devices are
>> typically
>> +  present
>> +
>> +- The other project may not provide a way to support U-Boot's
>> requirements for
>> +  devicetree, such as the /config node. Note: On the U-Boot mailing
>> linst, this
>
> Even if you remove these lines in 17/25 I would prefer not to introduce
> typos here:
>
> %s/linst/list/
>
>> +  was only discovered after weeks of discussion and confusion
>> +
>> +- For QEMU specifically, consulting two QEMU source files is
>> required, for which
>> +  there are no references in U-Boot documentation. The code is
>> generating a
>> +  devicetree, but it is not clear what controls affect this generation.
>> +
>> +Specifically on the changes in U-Bootm `CONFIG_OF_BOARD` was added in
>> +rpi_patch_ for Raspberry Pi, which does have an in-tree devicetree,
>> but this
>> +feature has since been used for boards that don't
>> +
>> +Once this bug is fixed, CONFIG_OF_BOARD will override (at runtime) the
>> +evicetree suppled with U-Boot, but will otherwise use
>> CONFIG_OF_SEPARATE for the
>> +in-tree build. So these two will become options, moving out of the
>> 'choice' in
>> +`dts/Kconfig`.
>> +
>> +This means that there is a basic devicetree build in the U-Boot tree,
>> for
>> +build-testing, consistency and documentation purposes, but at runtime
>> U-Boot can
>> +accept its devicetree from another source. The in-tree devicetree may
>> contain
>> +U-Boot-specific features (in u-boot*.dtsi files) and this may prove
>> useful for
>> +the other project, so it can ensure that U-Boot functions correctly
>> and supports
>> +all its expected features.
>> +
>> +To be clear, while U-Boot has its own copy of the devicetree source
>> for each
>> +board, this must match the Linux source, perhaps with some u-boot.dtsi
>> +additions. The intent here is not to create a separate binding, just
>> to provide
>> +a representative devicetree in U-Boot.
>> +
>> +Offending boards are:
>> +
>> +- rpi_4 and rpi_4_32b (other rpi boards do have an in-tree devicetree)
>> +- qemu_arm64
>> +- qemu_arm
>> +- qemu-ppce500
>> +- qemu-riscv32
>> +- qemu-riscv32_smode
>> +- qemu-riscv64
>> +- qemu-riscv64_smode
>> +
>> +All of these need to have a devicetree added in-tree. This is
>> targeted to be
>> +fixed in the 2022.01 release.
>> +
>> +
>> +Building the devicetree
>> +-----------------------
>> +
>> +U-Boot automatically builds the devicetree for a board, from the
>> +`arch/<arch>/dts` directory. The Makefile in those directories has
>> rules for
>> +building devicetree files. It is preferable to avoid target-specific
>> rules in
>> +those files: i.e. all boards for a particular SoC should be built at
>> once,
>> +where practical. Apart from simplifying the Makefile, this helps to
>> efficiently
>> +(and immediately) ensure that changes in one board's DT do not break
>> others that
>> +are related. Building devicetrees is fast, so performance is seldom a
>> concern
>> +here.
>> +
>> +
>> +Overriding the default devicetree
>> +---------------------------------
>> +
>> +When building U-Boot, the `DEVICE_TREE` environment variable allows the
>> +default devicetree file to be overridden at build time. This can be
>> useful if
>> +modifications have to be made to the in-tree devicetree file, for the
>> benefit
>> +of a downstream build system. Note that the in-tree devicetree must be
>> +sufficient to build and boot, so this is not a way to bypass that
>> requirement.
>> +
>> +
>> +Modifying the devicetree after building
>> +---------------------------------------
>> +
>> +While it is generally painful and hacky to modify the code or rodata
>> of a
>> +program after it is built, in many cases it is useful to do so, e.g.
>> to add
>> +configuration information like serial numbers, enabling/disabling
>> features, etc.
>> +
>> +Devicetree provides a very nice solution to these problems since it is
>> +structured data and it is relatively easy to change it, even in
>> binary form
>> +(see fdtput).
>> +
>> +U-Boot takes care that the devicetree is easily accessible after the
>> build
>> +process. In fact it is placed in a separate file called `u-boot.dtb`.
>> If the
>> +build system wants to modify or replace that file, it can do so. Then
>> all that
>> +is needed is to run `binman update` to update the file inside the
>> image. If
>> +binman is not used, then `u-boot-nodtb.bin` and the new `u-boot.dtb`
>> can simply
>> +be concatenated to achieve the desired result. U-Boot happily copes
>> with the
>> +devicetree growing or shrinking.
>> +
>> +The `u-boot.bin` image contains both pieces. While it is possible to
>> locate the
>> +devicetree within the image using the signature at the start of the
>> file, this
>> +is a bit messy.
>> +
>> +This is why `CONFIG_OF_SEPARATE` should always be used when building
>> U-Boot.
>> +The `CONFIG_OF_EMBED` option embeds the devicetree somewhere in the
>> U-Boot ELF
>> +image as rodata, meaning that it is hard to find it and it cannot
>> increase in
>> +size.
>> +
>> +When modifying the devicetree, the different cases to consider are as
>> follows:
>> +
>> +- CONFIG_OF_SEPARATE
>> +    This is easy, described above. Just change, replace or rebuild the
>> +    devicetree so it suits your needs, then rerun binman or redo the
>> `cat`
>> +    operation to join `u-boot-nodtb.bin` and the new `u-boot.dtb`
>> +
>> +- CONFIG_OF_EMBED
>> +    This is tricky, since the devicetree cannot easily be located. If
>> the EFL
>> +    file is available, then the _dtb_dt_begin and __dtb_dt_end
>> symbols can be
>> +    examined to find it. While it is possible to contract the file,
>> it is not
>> +    possible to expand the file since that would involve re-linking
>> +
>> +- CONFIG_OF_BOARD
>> +    This is a board-specific situation, so needs to be considered on a
>> +    case-by-case base.
>> +
>> +
>> +Use of U-Boot /config node
>> +--------------------------
>> +
>> +A common problem with firmware is that many builds are needed to deal
>> with the
>> +slight variations between different, related models. For example, one
>> model may
>> +have a TPM and another may not. Devicetree provides an excellent
>> solution to
>> +this problem, in that the devicetree to actually use on a platform
>> can be
>> +injected in the factory based on which model is being manufactured at
>> the time.
>> +
>> +A related problem causing build proliferation is dealing with the
>> differences
>> +between development firmware, developer-friendly firmware (e.g. with all
>> +security features present but with the ability to access the command
>> line),
>> +test firmware (which runs tests used in the factory), final
>> production firmware
>> +(before signing), signed firmware (where the signatures have been
>> inserted) and
>> +the like. Ideally all or most of these should use the same U-Boot
>> build, with
>> +just some options to determine the features available. For example,
>> being able
>> +to control whether the UART console or JTAG are available, on any
>> image, is a
>> +great debugging aid.
>> +
>> +When the firmware consists of multiple parts, it is helpful that all
>> operate
>> +the same way at runtime, regardless of how they were built. This can
>> be achieved
>> +by passing the runtime configuration (e.g. 'enable UART console)
>> along the chain
>> +through each firmware stage. It is frustrating to have to replicate a
>> bug on
>> +production firmware which does happen on developer firmware, because
>> they are
>> +completely different builds.
>> +
>> +The /config node provides useful functionality for this. It allows
>> the different
>> +controls to be 'factored out' of the U-Boot binary, so they can be
>> controlled
>> +separately from the initial source-code build. The node can be easily
>> updated by
>> +a build or factory tool and can control various features in U-Boot.
>> It is
>> +similar in concept to a Kconfig option, except that it can be changed
>> after
>> +U-Boot is built.
>> +
>> +The /config node is similar in concept to the `/chosen node`_ except
>> that it is
>> +for passing information *into* firmware instead of from firmware to the
>> +Operating System. Also, while Linux has a (sometimes extremely long)
>> command
>> +line, U-Boot does not support this. The devicetree provides a more
>> structured
>> +approach in any case.
>> +
>> +
>> +Devicetree in another project
>> +-----------------------------
>> +
>> +In some cases U-Boot receive its devicetree at runtime from a program
>> that calls
>> +it. For example ARM's Trusted Firmware A (`TF-A`_) may have a
>> devicetree that it
>> +passes to U-Boot. This overrides any devicetree build by U-Boot. When
>> packaging
>> +the firmware, the U-Boot devicetree may in fact be left out if it can be
>> +guaranteed that it will receive one from another project.
>> +
>> +In this case, the devicetree in the other project must track U-Boot's
>> use of
>> +device tree, for the following reasons:
>> +
>> +- U-Boot only has one devicetree. See `Why not have two devicetrees?`_.
>> +- For a consistent firmware build, decisions made in early stages
>> should be
>> +  communicated to later ones at runtime. For example, if the serial
>> console is
>> +  enabled in an early stage, it should be enabled in U-Boot too.
>> +- U-Boot is quite capable of managing its own copy of the devicetree. If
>> +  another project wants to bypass this (often for good reason), it is
>> reasonable
>> +  that it should take on the (fairly small) requirements that U-Boot
>> features
>> +  that rely on devicetree are still available
>> +- The point here is not that *U-Boot needs this extra node*, or
>> *U-Boot needs
>> +  to have this public key*. These features are present in U-Boot in
>> service of
>> +  the entire firmware system. If the U-Boot features are used, but
>> cannot be
>> +  supported in the normal way, then there is pressure to implement these
>> +  features in other ways. In the end, we would have a different
>> mechanism for
>> +  every other project that uses U-Boot. This introduces duplicate
>> ways of doing
>> +  the same thing, needlessly increases the complexity of the U-Boot
>> source code,
>> +  forces authors to consider parallel implementations when writing
>> new features,
>> +  makes U-Boot harder to test, complicates documentation and confuses
>> the
>> +  runtime flow of U-Boot. If every board did things its own way
>> rather than
>> +  contributing to the common code, U-Boot would lose a lot of its
>> cross-platform
>> +  value.
>> +
>> +The above does not indicate *bad design* within U-Boot. Devicetree is
>> a core
>> +component of U-Boot and U-Boot makes use of it to the full. It solves
>> a myriad
>> +of problems that would otherwise need their own special C struct,
>> binary format,
>> +special property, tooling for viewing and updating, etc.
>> +
>> +Specifically, the other project must provide a way to add
>> configuration and
>> +other information to the devicetree for use by U-Boot, such as the
>> /config node.
>> +Note that the U-Boot in-tree devicetree source must be sufficient to
>> build and
>> +boot, so this is not a way to bypass that requirement.
>> +
>> +If binman is used, the devicetree source in U-Boot must contain the
>> binman
>> +definition so that a valid image can be build. This helps people
>> discover what
>> +other firmware components are needed and seek out appropriate
>> documentation.
>> +
>> +If verified boot is used, the project must provide a way to inject a
>> public key,
>> +certificate or other material into the U-Boot devicetree so that it
>> is available
>> +to U-Boot at runtime. See `Signing with U-Boot devicetree`_. This may be
>> +through tooling in the project itself or by making use of U-Boot's
>> tooling.
>> +
>> +
>> +Devicetree generated on-the-fly in another project
>> +--------------------------------------------------
>> +
>> +In some rare cases, another project may wish to create a devicetree
>> for U-Boot
>> +entirely on-the-fly, then pass it to U-Boot at runtime. The only
>> known example
>> +of this at the time of writing (2021) is QEMU, for ARM (`QEMU ARM`_) and
>> +RISC-V (`QEMU RISC-V`_).
>> +
>> +In effect, when the board boots, U-Boot is *downstream* of the other
>> project.
>> +It is entirely reliant on that project for its correct operation.
>> +
>> +This does not mean to imply that the other project is creating its own,
>> +incompatible devicetree. In fact QEMU generates a valid devicetree
>> which is
>> +suitable for both U-Boot and Linux. It is quite normal for a
>> devicetree to be
>> +present in flash and be made available to U-Boot at runtime. What
>> matters is
>> +where the devicetree comes from. If the other project builds a
>> devicetree for
>> +U-Boot then it needs to support adding the things needed by U-Boot
>> features.
>> +Without them, for example:
>> +
>> +- U-Boot may not boot because too many devices are enabled before
>> relocation
>> +- U-Boot may not have access to the developer or production public
>> keys used for
>> +  signing
>> +- U-Boot may not support controlling whether the console is enabled
>> +- U-Boot may not be know which MMC device to boot from
>> +- U-Boot may not be able to find other firmware components that it
>> needs to load
>> +
>> +Normally, supporting U-Boot's features is trivial, since the
>> devicetree compiler
>> +(dtc) can compile the source, including any U-Boot pieces. So the
>> burden is
>> +extremely low.
>> +
>> +In this case, the devicetree in the other project must track U-Boot's
>> use of
>> +device tree, so that it remains compatible. See `Devicetree in
>> another project`_
>> +for reasons why.
>
> Did you ever ask the QEMU community what they think about your ideas?
> What was the reply?

Looking at the thread
https://lore.kernel.org/all/20210926183410.256484-1-sjg@chromium.org/
the QEMU project said NAK. This matches the expectation that I expressed
repeatedly.

Why don't you mention the QEMU reply in this patch series and adjust
your design accordingly?

Best regards

Heinrich

>
> Best regards
>
> Heinrich
>
>> +
>> +If a particular version of the project is needed for a particular
>> version of
>> +U-Boot, that must be documented in both projects.
>> +
>> +Further, it must provide a way to add configuration and other
>> information to
>> +the devicetree for use by U-Boot, such as the `/config` node and the
>> tags used
>> +by driver model. Note that the U-Boot in-tree devicetree must be
>> sufficient to
>> +build and boot, so this is not a way to bypass that requirement.
>> +
>> +More specifically, tooling or command-line arguments must provide a
>> way to
>> +add a `/config` node or items within that node, so that U-Boot can
>> receive a
>> +suitable configuration. It must provide a way of adding
>> `u-boot,dm-...` tags for
>> +correct operation of driver model. These options can then be used as
>> part of the
>> +build process, which puts the firmware image together. For binman, a
>> way must be
>> +provided to add the binman definition into the devicetree in the same
>> way.
>> +
>> +One way to do this is to allow a .dtsi file to be merged in with the
>> generated
>> +devicetree.
>> +
>> +Note that the burden goes both ways. If a new feature is added to
>> U-Boot which
>> +needs support in another project, then the author of the U-Boot patch
>> must add
>> +any required support to the other project.
>> +
>> +
>> +Passing the devicetree through to Linux
>> +---------------------------------------
>> +
>> +Ideally U-Boot and Linux use the same devicetree source, even though
>> it is
>> +hosted in separate projects. U-Boot adds some extra pieces, such as the
>> +`config/` node and tags like `u-boot,dm-spl`. Linux adds some extra
>> pieces, such
>> +as `linux,default-trigger` and `linux,code`. This should not
>> interfere with
>> +each other.
>> +
>> +In principle it is possible for U-Boot's control devicetree to be
>> passed to
>> +Linux. This is, after all, one of the goals of devicetree and the
>> original
>> +Open Firmware project, to have the firmware provide the hardware
>> description to
>> +the Operating System.
>> +
>> +For boards where this approach is used, care must be taken. U-Boot
>> typically
>> +needs to 'fix up' the devicetree before passing it to Linux, e.g. to add
>> +information about the memory map, about which serial console is used,
>> provide
>> +the kernel address space layout randomization (KASLR) seed or select
>> whether the
>> +console should be silenced for a faster boot.
>> +
>> +Fix-ups involve modifying the devicetree. If the control devicetree
>> is used,
>> +that means the control devicetree could be modified, while U-Boot is
>> using it.
>> +Removing a device and reinserting it can cause problems if the
>> devicetree offset
>> +has changed, for example, since the device will be unable to locates its
>> +devicetree properties at the expected devicetree offset, which is a
>> fixed
>> +integer.
>> +
>> +To deal with this, it is recommended to employ one or more of the
>> following
>> +approaches:
>> +
>> +- Make a copy of the devicetree and 'fix up' the copy, leaving the
>> control
>> +  devicetree alone
>> +- Enable `CONFIG_OF_LIVE` so that U-Boot makes its own copy of the
>> devicetree
>> +  during relocation; fixups then happen on the original flat tree
>> +- Ensure that fix-ups happen after all loading has happened and
>> U-Boot has
>> +  completed image verification
>> +
>> +In practice,the last point is typically observed, since
>> boot_prep_linux() is
>> +called just before jumping to Linux, long after signature
>> verification, for
>> +example. But it is important to make sure that this line is not blurred,
>> +particularly if untrusted user data is involved.
>> +
>> +
>> +Devicetree use cases that must be supported
>> +-------------------------------------------
>> +
>> +Regardless of how the devicetree is provided to U-Boot at runtime,
>> various
>> +U-Boot features must be fully supported. This section describes some
>> of these
>> +features and the implications for other projects.
>> +
>> +If U-Boot uses its own in-tree devicetree these features are supported
>> +automatically.
>> +
>> +
>> +Signing with U-Boot devicetree
>> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> +
>> +U-Boot supports signing a payload so that it can be verified to have
>> been
>> +created by a party owning a private key. This is called verified boot
>> in U-Boot
>> +(see doc/uImage.FIT/verified-boot.txt).
>> +
>> +Typically this works by creating a FIT and then running the `mkimage`
>> tool to
>> +add signatures for particular images. As part of this process,
>> `mkimage` writes
>> +a public key to the U-Boot devicetree, although this can be done
>> separately.
>> +See fdt_add_pubkey_ for patches for a suitable tool, for example.
>> +
>> +As with all configuration information, if another project is
>> providing the
>> +devicetree to U-Boot, it must provide a way to add this public key
>> into the
>> +devicetree it passes to U-Boot. This could be via a tooling option,
>> making use
>> +of `mkimage`, or allowing a .dtsi file to be merged in with what is
>> generated in
>> +the other project.
>> +
>> +
>> +Providing the binman image definition
>> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> +
>> +In complex systems U-Boot must locate and make use of other firmware
>> components,
>> +such as images for the user interface, files containing peripheral
>> firmware,
>> +multiple copies of U-Boot for use with A/B boot, etc. U-Boot uses
>> +:doc:`Binman <../package/binman>` as a standard way of putting an image
>> +together.
>> +
>> +Typically this works by running binman with the devicetree as an
>> input, to
>> +create the file image. Binman then outputs an updated devicetree
>> which is
>> +packed in the firmware image, so U-Boot can access the binman
>> definition and
>> +locate all the components.
>> +
>> +As with all configuration information, if another project is
>> providing the
>> +devicetree to U-Boot, it must provide a way to add this binman
>> definition into
>> +the devicetree it passes to U-Boot. This could be via a tooling
>> option, making
>> +use of `binman`, or alowing a .dtsi file to be merged in with what is
>> generated
>> +in the other project.
>> +
>> +
>> +Protecting the devicetree
>> +-------------------------
>> +
>> +U-Boot relies heavily on devicetree for correct operation. A corrupt
>> or invalid
>> +device can cause U-Boot to fail to start, behave incorrectly, crash
>> (e.g. if
>> +`CONFIG_OF_LIBFDT_ASSUME_MASK` is adjusted, or fail to boot an
>> Operating System.
>> +Within U-Boot, the devicetree is as important as any other part of
>> the source
>> +code. At ruuntime, the devicetree can be considered to be structured
>> rodata.
>> +
>> +With secure systems, care must be taken that the devicetree is valid:
>> +
>> +- If the code / rodata has a hash or signature, the devicetree should
>> also, if
>> +  they are packaged separately.
>> +- If the code / rodata is write-protected when running, the
>> devicetree should be
>> +  also. Note that U-Boot relocates its code and devicetree, so this
>> is not as
>> +  simple as it sounds. U-Boot must write-protect these items after
>> relocating.
>> +
>> +
>> +Why does U-Boot have its nodes and properties?
>> +----------------------------------------------
>> +
>> +See also :doc:`../devicetree/intro`.
>> +
>> +There has been pushback at the concept that U-Boot dares have its own
>> nodes and
>> +properties in the devicetree.
>> +
>> +Apart from these nodes and properties, U-Boot uses the same bindings
>> as Linux.
>> +A `u-boot.dtsi` file helps to keep U-Boot-specific changes in
>> separate files,
>> +making it easier to keep devicetree source files in U-Boot in sync
>> with Linux.
>> +
>> +As a counter-example, the Zephyr OS project takes a different
>> approach. It uses
>> +entirely different bindings, in general, making no effort to sync
>> devicetree
>> +source files with Linux. U-Boot strives to be compatible with Linux
>> in a number
>> +of ways, such as source code style and common APIs, to aid porting of
>> code
>> +between the projects. Devicetree is another way where U-Boot and
>> Linux follow a
>> +similar approach.
>> +
>> +Fundamentally, the idea that U-Boot cannot have its own tags flies in
>> the face
>> +of the devicetree specification (see dtspec_), which says:
>> +
>> +  Nonstandard property names should specify a **unique string
>> prefix**, such as
>> +  a stock ticker symbol, identifying the name of the company **or
>> organization**
>> +  that defined the property. Examples:
>> +
>> +  - fsl,channel-fifo-len
>> +  - ibm,ppc-interrupt-server#s
>> +  - **linux**,network-index
>> +
>> +It is also fundamentally unbalanced. Linux has many tags of its own
>> (some 36 in
>> +version 5.13) and at least one Linux-specific node, even if you
>> ignore things
>> +like flash partitions which clearly provide configuration information
>> to Linux.
>> +
>> +Practically speaking there are many reasons why U-Boot has its own
>> nodes and
>> +properties. Some examples:
>> +
>> +- Binding every device before relocation even if it won't be used,
>> consumes time
>> +  and memory: tags on each node can specify which are needed in SPL
>> or before
>> +  relocation. Linux has no such constraints.
>> +
>> +- Requiring the full clock tree to be up and running just to get the
>> debug UART
>> +  running is inefficient. It is also and self-defeating, since if
>> that much
>> +  code is working properly, you probably don't need the debug UART. A
>> devicetree
>> +  property to provide the UART input-clock frequency is a simple
>> solution.
>> +
>> +- U-Boot does not have a user space to provide policy and
>> configuration. It
>> +  cannot do what Linux does and run programs and look up filesystems
>> to figure
>> +  out how to boot.
>> +
>> +
>> +Why not have two devicetrees?
>> +-----------------------------
>> +
>> +Setting aside the argument for restricting U-Boot from having its own
>> nodes and
>> +properties, another idea proposed is to have two devicetrees, one for
>> the
>> +U-Boot-specific bits (here called `special`) and one for everything
>> else (here
>> +called `linux`). This would mean that U-Boot would be controlled by two
>> +devicetrees, i.e. OF_CONTROL would require/allow two devicetrees in
>> order to
>> +work.
>> +
>> +On the positive side, it might quieten the discussion alluded to in
>> the section
>> +above. But there are many negatives to consider and many open
>> questions to
>> +resolve.
>> +
>> +- **Bindings** - Presumably the special devicetree would have its own
>> bindings.
>> +  It would not be necessary to put a `u-boot,` prefix on anything.
>> People coming
>> +  across the devicetree source would wonder how it fits in with the
>> Linux
>> +  devicetree.
>> +
>> +- **Access** - U-Boot has a nice `ofnode` API for accessing the
>> devicetree. This
>> +  would need to be expanded to support two trees. Features which need
>> to access
>> +  both (such as a device driver which reads the special devicetree to
>> get some
>> +  configuration info) could become quite confusing to read and write.
>> +
>> +- **Merging** - Can the two devicetree be merged if a platform
>> desires it? If
>> +  so, how is this managed in tooling? Does it happen during the
>> build, in which
>> +  case they are not really separate at all. Or does U-Boot merge them at
>> +  runtime, in which case this adds time and memory?
>> +
>> +- **Efficiency** - A second device tree adds more code and more code
>> paths. It
>> +  requires that both be made available to the code in U-Boot, e.g. via a
>> +  separate pointer or argument or API. Overall the separation would
>> certainly
>> +  not speed up U-Boot, nor decrease its size.
>> +
>> +- **Source code** - At present `u-boot.dtsi` files provide the pieces
>> needed for
>> +  U-Boot for a particular board. Would we use these same files for
>> the special
>> +  devicetree?
>> +
>> +- **Complexity** - Two devicetrees complicates the build system since
>> it must
>> +  build and package them both. Errors must be reported in such a way
>> that it
>> +  is obvious which one is failing.
>> +
>> +- **Referencing each other** - The `u-boot,dm-xxx` tags used by
>> driver model
>> +  are currently placed in the nodes they relate to. How would these tags
>> +  reference a node that is in a separate devicetree? What extra
>> validation would
>> +  be needed?
>> +
>> +- **Storage** - How would the two devicetrees be stored in the image?
>> At present
>> +  we simply concatenate the U-Boot binary and the devicetree. We
>> could add the
>> +  special devicetree before the Linux one, so two are concatenated,
>> but it is
>> +  not pretty. We could use binman to support more complex
>> arrangements, but only
>> +  some boards use this at present, so it would be a big change.
>> +
>> +- **API** - How would another project provide two devicetree files to
>> U-Boot at
>> +  runtime? Presumably this would just be too painful. But if it
>> doesn't, it
>> +  would be unable to configure run-time features of U-Boot during the
>> boot.
>> +
>> +- **Confusion** - No other project has two devicetrees used for
>> controlling its
>> +  operation (although having multiple devicetrees to pass on to the
>> OS is
>> +  common). U-Boot would be in the unfortunate position of having to
>> describe
>> +  the purpose of the two control devicetrees fact to new users, along
>> with the
>> +  (arguably contrived) reason for the arrangement.
>> +
>> +- **Signing flow** - The current signing flow is simple as it
>> involves running
>> +  `mkimage` with the U-Boot devicetree. This would have to be updated
>> to use the
>> +  special devicetree. Some way of telling the user that they have
>> done it wrong
>> +  would have to be invented.
>> +
>> +Overall, adding a second devicetree would create enormous confusion and
>> +complexity. It seems a lot cheaper to solve this by a change of
>> attitude.
>> +
>> +
>> +.. _rpi_patch:
>> https://patchwork.ozlabs.org/project/uboot/patch/20170402082520.32546-1-deymo@google.com/
>>
>> +.. _`TF-A`: https://www.trustedfirmware.org/projects/tf-a
>> +.. _`QEMU ARM`: https://github.com/qemu/qemu/blob/master/hw/arm/virt.c
>> +.. _`QEMU RISC-V`:
>> https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c
>> +.. _`/chosen node`:
>> https://www.kernel.org/doc/Documentation/devicetree/bindings/chosen.txt
>> +.. _fdt_add_pubkey:
>> https://patchwork.ozlabs.org/project/uboot/list/?series=157843&state=*
>> +.. _dtspec: https://www.devicetree.org/specifications/
>> diff --git a/doc/develop/devicetree/index.rst
>> b/doc/develop/devicetree/index.rst
>> index fa5db3eb76e..b5b33dfea0f 100644
>> --- a/doc/develop/devicetree/index.rst
>> +++ b/doc/develop/devicetree/index.rst
>> @@ -11,3 +11,4 @@ build-time and runtime configuration.
>>
>>      intro
>>      control
>> +   dt_update
>>
>



More information about the U-Boot mailing list