nRF53 Custom b0n Build

I am trying to compile a custom bootloader for nRF5340 net core (b0n) that is part of a multi-image build.

I have created two separate applications, one based on b0n (nrf/samples/nrf5340/netboot) and one based on nrf/samples/bluetooth/peripheral_lbs. These both build without issue when used as single image applications and I can debug them (using hello_world on the app core) and they appear to work.

I have tried adding the b0n as a child image of the application by adding the following code to CMakeLists.txt

if (CONFIG_SECURE_BOOT)
  add_child_image(
    NAME b0n
    SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../boot_stage1
  )
endif()

If I then build the net app, the application builds, but b0n is neither built nor linked.

I have tried adding CONFIG_SECURE_BOOT=y to the prj.conf file. If I have the above CMakeLists.txt change, I get the following compilation error:

=== child image b0n -  begin ===
loading initial cache file C:/Users/anton/src/bootloader-test/netapp/build/b0n/child_image_preload.cmake
CMake Error: The source "C:/Users/anton/src/bootloader-test/boot_stage1/CMakeLists.txt" does not match the source "C:/Users/anton/ncs/v1.9.1/nrf/samples/nrf5340/netboot/CMakeLists.txt" used to generate cache.  Re-run cmake with a different source directory.
CMake Error at C:\Users\anton\ncs\v1.9.1\nrf\cmake\multi_image.cmake:409 (message):
  CMake generation for b0n failed, aborting.  Command: 1
Call Stack (most recent call first):
  C:\Users\anton\ncs\v1.9.1\nrf\cmake\multi_image.cmake:150 (add_child_image_from_source)
  c:\Users\anton\src\bootloader-test\netapp\build\CMakeLists.txt:21 (add_child_image)
This confuses me in the following ways
  • I don't know why the netboot sample should be used to generate the cache.
  • The CMakeLists.txt are identical in both the sample and in my local build.
  • I don't know why they need to match anyway.

What is going wrong here?

p.s. Most of the documnetation about multi-image bootloader builds suggest using CONFIG_B0_BUILD_STRATEGY_FROM_SOURCE=y. There doesn't appear to be an equivalent CONFIG_B0N_BUILD_STRATEGY_FROM_SOURCE.

Parents
  • Hi Anton

    I have tried adding the b0n as a child image of the application by adding the following code to CMakeLists.txt

    Can you specify which CmakeLists.txt you are referring to here?

    If I then build the net app

    The b0n is usually used alongside the bootloader in the application core. What happens if you build for nrf5340dk_nrf5340_cpuapp instead?

    Regards,
    Sigurd Hellesvik

  • The CMakeLists.txt that I am referring to is the root level CMakeLists.txt for the application on the net core (based on nrf/samples/bluetooth/peripheral_lbs on the net core).

    I think you are mistaken: b0 is the app core bootloader, b0n is the net core bootloader (https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/nrf5340/netboot/README.html). Also, as I have said, I can compile and run b0n on the net core without issue. Also, b0n isn't used alongside the bootloader, it is a bootloader. Did you mean it is often run alongside mcuboot as a set of first and second stage bootloaders?

    Edited: I attempted to build the b0n/app using app core but that failed as it was unable to find "pm_config.h" ... but I don't think that is the correct path to follow anyway.

  • Thanks for your honesty.

    This project is for a product that needs to be able to recover even under extreme circumstances so custom bootloaders are absolutely necessary. I have worked around the worst of the issues modifying the SDK by adding the following lines to the top of the application root CMakeLists.txt :

    set(CONFIG_B0_CUSTOM_FOLDER "${CMAKE_SOURCE_DIR}/cpuboot")
    set(CONFIG_B0N_CUSTOM_FOLDER "${CMAKE_SOURCE_DIR}/netboot")

    I have then added the custom bootloaders at those subdirectories. I then copied the SDK into a new directory next to the application (so as not to polute the common SDK) and made the following changes to the samples CMakeLists.txt :

    if (CONFIG_SECURE_BOOT)
      if (CONFIG_SOC_NRF5340_CPUNET)
        # Share some information which is used when generating the zip file
        # with the update binaries.
        set_shared(IMAGE net_core PROPERTY SOC ${CONFIG_SOC})
        set_shared(IMAGE net_core PROPERTY VERSION ${CONFIG_FW_INFO_FIRMWARE_VERSION})
        if (DEFINED CONFIG_B0N_CUSTOM_FOLDER)
          add_child_image(
            NAME b0n
            SOURCE_DIR ${CONFIG_B0N_CUSTOM_FOLDER}
            )
        else()
          add_child_image(
            NAME b0n
            SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/nrf5340/netboot
            )
        endif()
      else()
        if (DEFINED CONFIG_B0_CUSTOM_FOLDER)
          add_child_image(
            NAME b0
            SOURCE_DIR ${CONFIG_B0_CUSTOM_FOLDER}
            )
        else()
          add_child_image(
            NAME b0
            SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/bootloader
            )
        endif()
      endif()

    This does get the job done but is still a bit of a hack; so, I am not marking this as an answer until custom bootloaders can be built using the unmodified SDK.

  • Sigurd,

    I found this discussion  due to a similar need. I also appreciate the honesty and candor in your response.

    Can you comment if there has been any progress on this or any plans by Nordic to support custom(ized) bootloader builds in nrf connect (without needed to modify the sdk)?

    Anton's use case is very common in the real world :

    "This project is for a product that needs to be able to recover even under extreme circumstances so custom bootloaders are absolutely necessary."

    The use of well structured, well designed, well tested, and open (in case of mcuboot) bootloaders is a good thing, but there will always be real world low level (and often proprietary/legacy methods) recovery needed  directly from the lowest levels of code. It is most often the more complex and higher levels of boot which fail (later stage bootloaders, application etc). And there may also be some other low level/sensitive/proprietary customization required in the first and/or second stages of boot.

    On this same topic and related, Nordic should consider the case of being able to build the bootloaders as standalone projects directly in the toolchain (the documentation states that this is somewhat doable via command line).

    There are  numerous real world (especially in production and repair environments) where a standalone bootloader project/build (not as a child project) is required for the various workflows.

    Building as child application embedded in main effort can also create design isolation challenges: some extreme security projects have separate bootloader/security development environments and don't want to share source/build with the application teams.

    Having the bootloader projects  as  separate standalone examples would allow that customization and should be accommodated by your toolchain, in addition to composite projects that have bootloader and app.

    There are some cases where products never even see an application until some post fielding OTA/download/low level upgrade that is done by bootloader.

    Thank you for considering these inputs.

  • Thank you for the complements!

    Joe Kane said:
    Can you comment if there has been any progress on this or any plans by Nordic to support custom(ized) bootloader builds in nrf connect (without needed to modify the sdk)?

    There have not been any changes to the multi-image builds yet.

    However, there are work being done on sysbuild. From these release notes:
    "Sysbuild was introduced in Zephyr's v3.2.0 release, and has been adopted in the nRF Connect SDK v2.4.0. Sysbuild will gradually become the new workflow for handling multi-image build configurations and it will replace the child image mechanism, specific to the nRF Connect SDK
    "

    I have still  not tried sysbuild myself, but from what I have heard I suspect it could make it easier to add customized bootloaders to projects.

    Joe Kane said:

    On this same topic and related, Nordic should consider the case of being able to build the bootloaders as standalone projects directly in the toolchain (the documentation states that this is somewhat doable via command line).

    There are  numerous real world (especially in production and repair environments) where a standalone bootloader project/build (not as a child project) is required for the various workflows.

    Building as child application embedded in main effort can also create design isolation challenges: some extreme security projects have separate bootloader/security development environments and don't want to share source/build with the application teams.

    Having the bootloader projects  as  separate standalone examples would allow that customization and should be accommodated by your toolchain, in addition to composite projects that have bootloader and app.

    There are some cases where products never even see an application until some post fielding OTA/download/low level upgrade that is done by bootloader.

    In the end, a bootloader does not really care about how which binary it boots to (as long as said binary is signed).

    Therefore, you can in theory add your own bootloader and boot any nRF Connect SDK application after.
    As long as the bootloader is good enough at resetting states of peripherals and such, the application should not be affected by this either.

    In fact, our nRF52840 Dongles run the (old) nRF5 Bootloader, which does not know anything about the nRF Connect SDK.
    And this works.
    You can use the Kconfig option CONFIG_FLASH_LOAD_OFFSET to make the application start at the correct offset for your bootloader.
    And then if you want to do DFU, you either must have an update mechanism in the bootloader (ex. serial recovery) or one in your application which supports the custom bootloader.

    Here you can see a case where I discuss using the nRF Bootloader  One bootloader to rule them all .

    Did this make sense to you?

    Regards,
    Sigurd Hellesvik

  • Sigurd,

    Thank you for the fast response. Yes, I understand that it is possible to add another stage of custom bootloader that runs after  after SIBS or mcuboot runs  as long as the signing chain is honored.

    But this does add complexity and code size, and in some designs it is really required to do some custom development in the first stage boot (and there can be only one bootloader) and be as small as possible due to limited memory.

    I have been running  up to nrfconnect 2.3 and haven't toured 2.4 yet, and I missed sysbuild. Taking a quick look at the architecture, it can probably do the kind of things I requested.

    We have  accomplished this in the past  with customized linker scripts and custom makefile targets for 'standalone' or 'composite' images, but sysbuild can probably handle the job.

    I will take a further look.

    Thank you.

  • Quick answer before I am taking the weekend now:

    Joe Kane said:
    Thank you for the fast response. Yes, I understand that it is possible to add another stage of custom bootloader that runs after  after SIBS or mcuboot runs  as long as the signing chain is honored.

    This is not what I mean. I refer to only Custom Bootloader + Applicaton.

    For the case of the nRF5 Bootloader and the nRF52840Dongle, neither NSIB or MCUboot runs on the dongle with the NCS applications here.

Reply
  • Quick answer before I am taking the weekend now:

    Joe Kane said:
    Thank you for the fast response. Yes, I understand that it is possible to add another stage of custom bootloader that runs after  after SIBS or mcuboot runs  as long as the signing chain is honored.

    This is not what I mean. I refer to only Custom Bootloader + Applicaton.

    For the case of the nRF5 Bootloader and the nRF52840Dongle, neither NSIB or MCUboot runs on the dongle with the NCS applications here.

Children
  • Sigurd,

    Thank you for quick answer (again!) Please enjoy your weekend.

    I see now. I was still thinking in terms of  the sdk tool kit building (and it only supporting either SIBS or Mcuboot)  But you meant  build separate proprietary bootloader app. separately, and build NRF application with offset from CONFIG_FLASH_LOAD_OFFSET (separately) .

    This would be very similar to our previous process (with offsets tied to linker script and makefile targets (to know which offset to use) .

    And finally maybe we can build either standalone or composite images using sysbuild with sysbuild kconfig options.

  • Joe Kane said:
      But you meant  build separate proprietary bootloader app. separately, and build NRF application with offset from CONFIG_FLASH_LOAD_OFFSET (separately) .

    Correct

    Let me know if you got any further questions.

Related