mcuboot icon indicating copy to clipboard operation
mcuboot copied to clipboard

Bootloader should provide the version of zephyr, mcuboot and a user defined version to the application

Open caco3 opened this issue 3 years ago • 11 comments

This issue originally was opened in https://github.com/zephyrproject-rtos/zephyr/issues/37160

We are using the MCUBoot based bootloader (/bootloader/mcuboot) in a Zephyr project.

It seems there is no way for a (Zephyr) application to get the following information from the MCUBoot bootloader:

  • The used Zephyr version in the bootloader
  • The used MCUBoot version
  • A user defined bootloader version (like set in the application with the image tool, imgtool sign --version $VERSION_FOR_IMGTOOL ...)

We think that it is important that an application is able to read this information from the bootloader for troubleshooting or special handling of a newer bootloader version.

Did I miss such functionality or is it not existing? And if so, is there a reason for it to be missing?

As a workaround for our test system, I added such functionality by providing this information through the UART log:

# Add Git hash, MCUboot repo commit hash/tag and zephyrproject version to Startup Log Message
sed -i "/BOOT_LOG_INF(\"Starting bootloader/c\    BOOT_LOG_INF(\"Starting bootloader | \" __DATE__ \" \" __TIME__ \" | Version: $GIT_VERSION | MCUboot: $MCUBOOT_GIT_VERSION | Zephyrproject: $ZEPHYR_REVISION\");" mcuboot/boot/zephyr/main.c

How ever this is not be possible on the systems on the field.

I think the way to implement this is by defining fix locations in flash and store the mentioned information there. The right place most likely would be at the end of the boot_partition, https://github.com/zephyrproject-rtos/zephyr/blob/main/boards/arm/nrf52840dongle_nrf52840/fstab-debugger.dts#L18. I have done this on other projects (not Zephyr based) and it worked well.

caco3 avatar Jul 28 '21 12:07 caco3

I think the way to implement this is by defining fix locations in flash and store the mentioned information there.

There are hooks for doing this that are used by TF-M for boot measurements. Perhaps this could be leveraged to get this information into Zephyr.

I'm not sure this should be stored in flash, but in SRAM and passed to the running app from the bootloader.

d3zd3z avatar Jul 29 '21 17:07 d3zd3z

@d3zd3z Thanks for your input. Do you have any links to those hooks and boot measurements?

caco3 avatar Jul 29 '21 21:07 caco3

A little update:

Because we need a solution now, we went for following: We have a python script, which generates a little hex file. The hex file will put the needed information to the end of the bootloader_partition. Nordic provides a little tool to merge 2 hex files: mergehex. We then simply flash that combined hex file to the bootloader_partition.

The application itself can read the data out again from there:

bootloaderVersionBlock_t *bootloderVersionBlock = (bootloaderVersionBlock_t *)0xF000;
LOG_INF("Version: %d, bootloderVersionBlock.version);

caco3 avatar Aug 04 '21 06:08 caco3

I've added "enhancement" and "someday" to this so we can keep it around, but it sounds like you've found a way to meet your immediate needs.

d3zd3z avatar Aug 12 '21 20:08 d3zd3z

Hi @caco3, I had similar requirements for my mcuboot-based bootloaders.

There is a relatively new feature called data sharing (same feature @d3zd3z mentioned above that is used for TF-M measured boots). Essentially, it lets you store TLV-encoded values in a reserved region of RAM that is shared between the bootloader and application. You can see the official MCUboot documentation regarding this feature here.

Although it's for a different platform, you can see how it is implemented in the Mbed-OS port (#1115). I also just added demos of how to use it to the Mbed-OS demo repositories: bootloader demo, application demo.

Basically, in steps:

0.) Reserve the region of RAM using your platform/toolchain (ie: prevent a small area of RAM from being initialized at startup in the application) 1.) Configure MCUboot bootloader and application so that it knows where in RAM the reserved region is (see MCUBOOT_SHARED_DATA_BASE and MCUBOOT_SHARED_DATA_SIZE configuration parameters in documentation). 2.) Implement a hook function that MCUboot expects (must be a C symbol if building with C++): boot_save_shared_data 3.) In your boot_save_shared_data implementation, call boot_add_data_to_shared_area to add custom data to the shared region 4.) At application startup, read the shared data region TLVs. See an example of how to do this (in C++) here.

Note that it is imperative that you prevent your startup code from "initializing" (ie: RAM zeroing) this reserved section. You will have to refer to your platform/toolchain's documentation for details on how to do this. On Mbed-OS, I simply configure the linker script so that it does not "know" about the small reserved shared data region at the end of RAM.

I hope this helps! Let me know if you have any further questions. I encourage you to join the MCUboot slack channel as well.

AGlass0fMilk avatar Sep 13 '21 22:09 AGlass0fMilk

@d3zd3z Another thought that comes to mind: MCUboot should have the version in a #define somewhere. I can't find a place where the MCUboot version is available in code.

AGlass0fMilk avatar Sep 14 '21 16:09 AGlass0fMilk

@d3zd3z Thank you for sharing your knowledge in such detailed level! @AGlass0fMilk I also didn't find such a define. As a workaround, and since I want to see the version in the log, I patched main() as seen in the first post.

caco3 avatar Sep 15 '21 06:09 caco3

MCUboot should have the version in a #define somewhere. I can't find a place where the MCUboot version is available in code.

This is probably worth it's own issue. I'll create an issue for this #1151, which has a checklist for each platform.

d3zd3z avatar Sep 17 '21 22:09 d3zd3z

@AGlass0fMilk Do you have an example based on zephyr?

Cherish-Gww avatar Nov 16 '21 13:11 Cherish-Gww

@d3zd3z @AGlass0fMilk I found a easy way to get mcuboot version in zephyr. zephyr can generate merge.hex file and it will fill no use space to 0xff, so that when mcuboot boot up, check the tail of mcuboot, if not match it is version, then write version to flash, only once. when application upgrade mcuboot, it will earse mcuboot flash partition, so that is another chance to write it`s version.

that means mcuboot seal version in runtime.

Cherish-Gww avatar Dec 16 '21 03:12 Cherish-Gww

@Cherish-Gww The only comment I would make is that mcuboot should never be updated by the application. Two reasons, 1, if power were lost you would have an unbootable device, and 2. the hardware should be configurable so that mcuboot cannot be modified, otherwise you will be unable to trust the boot process.

d3zd3z avatar Dec 21 '21 22:12 d3zd3z

I have used a section of linker file that I added at a specified memory location in flash where I set a version number for bootloader. Then I read that address from app firmware. That's work for me.

raulperez avatar Oct 03 '23 18:10 raulperez

MCUboot now has a version when built using zephyr: https://github.com/mcu-tools/mcuboot/blob/main/boot/zephyr/VERSION This can be shared with an application using data sharing, see zephyr test here: https://github.com/zephyrproject-rtos/zephyr/tree/main/tests/boot/mcuboot_data_sharing

Therefore this can be closed?

nordicjm avatar Nov 08 '23 11:11 nordicjm

To my understanding, this only covers the MCUBoot version, but not the Zephyr and user defined version. Not sure if the Zephyr version could be found out based on the MUCBoot version (and the GIT history). Since we want traceability, our build process adds the user defined version and the GIT hash to the hex file so we can read it out in the application. Without this addings, I do not see how one could trace the MCUBoot build back to the pipeline/GIT commit..

caco3 avatar Nov 09 '23 08:11 caco3

But why would there be a user version for MCUboot? If you are using MCUboot as-is, then you have the version from it, if you are editing/forking MCUboot then you have your own version scheme which is custom to that.

You could probably use https://docs.zephyrproject.org/latest/services/binary_descriptors/index.html for that

nordicjm avatar Nov 10 '23 07:11 nordicjm

You are right, such information should not be part of MCUboot but the application where it is embedded into (eg. a Zephyr project). And thanks for the link to the Binary Descriptors. Thats exactly what I was looking for. It seems how ever to be fairly new (comming in Zephyr 3.5?)

caco3 avatar Nov 13 '23 07:11 caco3