On 9/10/21 12:08 PM, François Ozog wrote:


On Thu, 9 Sept 2021 at 22:10, Simon Glass <[email protected]
<mailto:[email protected]>> 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 <[email protected] <mailto:[email protected]>>
    Reviewed-by: Marcel Ziswiler <[email protected]
    <mailto:[email protected]>>
    ---

    Changes in v3:
    - Fix typos linst suppled receive EFL
    - Drop 'and' before 'self-defeating'
    - Reword mention of control of QEMU's devicetree generation
    - Add mention of dropping CONFIG_OF_BOARD
    - Clarify the 'Once this bug is fixed' paragraph a bit
    - Expand ways that CONFIG_OF_PRIOR_STAGE can support the U-Boot
    devicetree
    - Add a note at the top explaining that his patch covers 'now', not
    'future'
    - Add note 'Note: Some boards use a devicetree in U-Boot which does
    not match'

    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/index.rst              |   1 +
      doc/develop/package/devicetree.rst | 583 +++++++++++++++++++++++++++++
      doc/develop/package/index.rst      |   1 +
      3 files changed, 585 insertions(+)
      create mode 100644 doc/develop/package/devicetree.rst

    diff --git a/doc/develop/index.rst b/doc/develop/index.rst
    index 83c929babda..d5ad8f9fe53 100644
    --- a/doc/develop/index.rst
    +++ b/doc/develop/index.rst
    @@ -36,6 +36,7 @@ Packaging
         :maxdepth: 1

         package/index
    +   package/devicetree

      Testing
      -------
    diff --git a/doc/develop/package/devicetree.rst
    b/doc/develop/package/devicetree.rst
    new file mode 100644
    index 00000000000..b1bd310d906
    --- /dev/null
    +++ b/doc/develop/package/devicetree.rst
    @@ -0,0 +1,583 @@
    +.. SPDX-License-Identifier: GPL-2.0+
    +
    +Updating the devicetree
    +=======================
    +
    +Note: This documentation describes how things are today, mostly,
    with some
    +mention of things that need to be fixed. It is not intended to
    point the way to
    +what might be done in the future. That should be the subject of
    discussions on
    +the mailing list.
    +

Some text about device tree usage and standardization may be good.
What about something along the lines:

Device Tree defines a source language, a serialized binary format and
bindings.
The power of device tree is that it can be leveraged by applications
to store self describing rich data out of the context of hardware
description.
This power led to abuse in hardware description and device drivers
started to
leverage that to store parameters instead of using the operating system
provided
capabilities to do so.
The current state of standardization is such that source and binary
formats are
fully defined but unfortunately bindings standardization is split
between devicetree.org <http://devicetree.org>,
IEEE1475 and Linux kernel Documentation tree.
A platform may have multiple device trees attached to it:
- there can be a System Device Tree covering compute elements outside
scope of
U-Boot and subsequent payloads
- pre-U-Boot firmware components may have their specific ones to deal
with power
and clock distribution infrastructure
- U-Boot may have a richer/different vision of the hardware than the
booted payload,
for instance U-Boot may have to view SerDes hardware to configure lines
into PCI
or MDIO lanes to match actual board physical routing. The booted payload
(say Linux)
should only see the PCI ports or Ethernet ports, not the Serdes. For
boot-time control
one may want to limit the hardware vision of U-Boot to just what is
necessary to boot
- U-Boot is in the best position to assemble the full device view that
can result from
connected capes or hats.
- The booted payload should just consume what U-Boot hands over

    +U-Boot uses devicetree for runtime configuration and storing
    required blobs or
    +any other information it needs to operate.

Those elements shall not be visible to the booted payload. They may be
stored in a
separate device tree binary. The bindings for this tree are out of scope
for projects other
than U-Boot. U-Boot shall define its own bindings, even if it means
referring to external
ones.

    It is possible to update the
    +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)

Console control is still in its infancy and has many problems. For
instance, Linux leverages
stdout *only* with earlyconsole, there is no way to state console=dt/stdout
in the command line so that the console is directed to firmware provided
source.

    +
    +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).


That should be noted as current situation, not a *must* that will last
forever
U-Boot plays a central role in "massaging" the device tree that is
handed over
to the booted payload. But it is certainly not the "authoritative"
entity that defines
the board. It may even control only a portion of the entire board
(covered by System
Device Tree).


    This is specified using the
    +`CONFIG DEFAULT_DEVICE_TREE` option.
    +
    +
    +Current situation (August 2021)
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    +
    +As an aside, at present U-Boot allows `CONFIG_DEFAULT_DEVICE_TREE`
    to be empty,
    +e.g. if `CONFIG_OF_BOARD` or `CONFIG_OF_PRIOR_STAGE` are used. This has
    +unfortunately created an enormous amount of confusion and some
    wasted effort.
    +This was not intended and this bug will be fixed 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
    list, this
    +  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, with some control from command-line args, but it is
    not clear
    +  how to add properties required by U-Boot.
    +
    +Specifically on the changes in U-Boot:
    +
    +- `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
    +- `CONFIG_OF_PRIOR_STAGE` was added in bcm_patch_ as part of a
    larger Broadcom
    +  change with a tag indicating it only affected one board, so the
    change in
    +  behaviour was not noticed at the time. It has since been used by
    RISC-V qemu
    +  boards.
    +
    +Note: It is not clear that we actually need both of these. Possibly
    +`CONFIG_OF_BOARD` can be dropped.
    +
    +Once this bug is fixed, CONFIG_OF_BOARD and CONFIG_OF_PRIOR_STAGE
    will override
    +(at runtime) the devicetree supplied 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`. To be clear, the
    devicetree in the
    +U-Boot tree may be largely for documentation and build-testing
    purposes, if at
    +runtime the devicetree if provided by another project. But the in-tree
    +devicetree is packaged with U-Boot as a fallback if it does not get
    one from a
    +prior stage at runtime. This does not create two devicetrees that
    need to be
    +merged, or anything like that. If the prior stage provides one, it
    is used as
    +is, with the one provided by U-Boot being ignored.
    +
    +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.
    +
    +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.
    +

    +Note: Some boards use a devicetree in U-Boot which does not match
    that in Linux.
    +This is a significant problem which needs to be fixed.


That may not be a problem. The requirement is that the generated Device
Tree is
conformant to the spec and complete and accurate. U-Boot may further
amend it.
Should Qemu change PSCI implementation (new version of API...), U-Boot
shall
not have a different vision of this in a separately maintained device tree,
that just make no sense. For CI/CD, you just use different Qemu runtime
  parameters rather than use fake static device trees.

    +
    +Offending boards are:
    +
    +- bcm7260
    +- bcm7445
    +- 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 ELF
    +    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_PRIOR_STAGE
    +    In this case the devicetree must be modified in the project
    which provides
    +    it, as described below. This can be achieved by copying the
    devicetree from
    +    the U-Boot tree, for example, or by providing an option to (at
    build-time)
    +    merge U-Boot's version with the one provided by the project.
    +
    +- CONFIG_OF_BOARD
    +    This is a board-specific situation, so needs to be considered on a
    +    case-by-case base. The devicetree must be modified so that the
    correct
    +    one is provided to U-Boot. How this is done depends entirely on the
    +    implementation of this option for the board. It might require
    injecting the
    +    changes into a different project somehow using tooling
    available there, or
    +    it might involve merging an overlay file at runtime to obtain
    the desired
    +    result.
    +
    +
    +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 receives 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:


STRONG NO. there shall be a platform device tree that is "massaged" by
different
firmware components before reaching the booted payload.
TF-A shall ignore *entirely* if the non secure firmware is U-Boot or
LinuxBoot or EDK2.
It shall do what it has authority to do on the platform DT and that's all.

    +
    +- U-Boot only has one devicetree.


U-Boot has vision on hardware that the booted payload shall not even see,
U-Boot builder for the platform may decide to only consider a hardware
subset
for booting purposes. The implementation may be either a single

Hello Francois,

some part of your the message got lost here. Could you, please resend
with the missing part.

Best regards

Heinrich


    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.
    +
    +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 <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`).
    +
    +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. U-Boot
    would be in the
    +  unfortunate position of having to describe this 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/[email protected]/
    
<https://patchwork.ozlabs.org/project/uboot/patch/[email protected]/>
    +.. _bcm_patch:
    
https://patchwork.ozlabs.org/project/uboot/patch/16fc0901f4521d3c399eac950c52a634b2f9473b.1528485916.git.fitz...@fitzsim.org/
    
<https://patchwork.ozlabs.org/project/uboot/patch/16fc0901f4521d3c399eac950c52a634b2f9473b.1528485916.git.fitz...@fitzsim.org/>
    +.. _`TF-A`: https://www.trustedfirmware.org/projects/tf-a
    <https://www.trustedfirmware.org/projects/tf-a>
    +.. _`QEMU ARM`:
    https://github.com/qemu/qemu/blob/master/hw/arm/virt.c
    <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
    <https://github.com/qemu/qemu/blob/master/hw/riscv/virt.c>
    +.. _`/chosen node`:
    https://www.kernel.org/doc/Documentation/devicetree/bindings/chosen.txt
    <https://www.kernel.org/doc/Documentation/devicetree/bindings/chosen.txt>
    +.. _fdt_add_pubkey:
    https://patchwork.ozlabs.org/project/uboot/list/?series=157843&state=*
    <https://patchwork.ozlabs.org/project/uboot/list/?series=157843&state=*>
    +.. _dtspec: https://www.devicetree.org/specifications/
    <https://www.devicetree.org/specifications/>
    diff --git a/doc/develop/package/index.rst
    b/doc/develop/package/index.rst
    index 9374be2e62c..188c376950e 100644
    --- a/doc/develop/package/index.rst
    +++ b/doc/develop/package/index.rst
    @@ -17,3 +17,4 @@ SPI flash.
         :maxdepth: 2

         binman
    +   devicetree
    --
    2.33.0.309.g3052b89438-goog



--

François-Frédéric Ozog | /Director Business Development/
T: +33.67221.6485
[email protected] <mailto:[email protected]> | Skype: ffozog


Reply via email to