Passing information from bootloader to Zephyr


David Brown
 

Background
==========

On larger platforms, there will generally be a protocol for passing
information from the bootloader to the operating system that it is
booting. There are various standards for this, from BIOS, UEFI, to
the more simplistic approach used on many ARM targets of passing a
pointer to a flattened device tree in a register.

Now that we are approaching a 1.0 release of mcuboot, it would be nice
to also have a way for the bootloader to pass information to the
running application. This will likely be a fairly simple method,
given the memory constraints of the devices typically used by Zephyr.

It is important to note that the bootloader and application will
generally be built separately, and generally, the bootloader will not
be upgraded, but only the application. This is why it is necessary
for a possibly upgraded application to know about the bootloader
present in a particular device.

At this time, most of this information is needed by over-the-air
updating, since this effectively has to communicate back to the
bootloader in order to be able to use the new image. Currently, we're
thinking of:

- Version information about the bootloader.
- Information about how to perform an upgrade.
- Information about the flash device itself, specifically the
bootloader's ideas of the partitions it cares about.

Proposal
========

https://github.com/runtimeco/mcuboot/pull/61 has current work on this,
although it is quite tentative. The idea is to pass a pair of
registers from the bootloader to the application. One register will
have a magic value, and the other a pointer to a structure (likely in
flash).

Passing a pointer to flash simplifies the design because it will not
be necessary to reserve a section of RAM that the application needs to
avoid using for another purpose.

The structure contains an additional magic value, a version field, and
currently, a function pointer. Additional queries are made by calling
this function with specific commands.

There is additional complexity because of the function pointer, with
some pros and cons. Pros:

- It is fairly easy to add new commands, and even deprecate
commands.

- It allows data that must be computed at run time rather than just
being compile-time constant data.

and some cons as well:

- It could be considered risky to have the application call into
code in the bootloader.

- The code has to be carefully written to not use RAM data, which
will have been overwritten by the application.

The other option would be to define a larger structure, and place the
current data within this structure. Pros:

- No risk of running code in the bootloader.

Cons:

- Versioning becomes more complicated, and the logic to handle
various versions must make it into every application.

- Complex data (e.g. a representation of the partitions) needs to be
determined at compile time so it can be placed in a ROM data
structure.

It would also be possible to place this structure in RAM, if we can
define an area for this purpose. Because mcuboot has a goal to work
with more than just Zephyr, this may impose additional constraints on
every OS that wishes to use mcuboot.

Zephyr Details
==============
Supporting this in Zephyr involves adding a small amount of assembly
to system startup to detect if the register contains the magic value,
and if so, stashing away the pointer in the other register. Once this
is stored, the rest of the use can be done at a library level or by an
application.

In addition, the MPU/MMU may need to be configured to allow reading
and/or execution from the area of flash containing the bootloader.

Questions
=========

- What do people think of this proposal?

- Preferences for: ROM+callback, ROM only, or RAM only

- How formally should we define this proposal? Is a de-facto
implementation by mcuboot sufficient at this time?

- Thoughts on future data that may need to be passed?

Thanks,
David Brown

Join devel@lists.zephyrproject.org to automatically receive all group messages.