Adding USB capability to secure DFU BLE bootloader

Hi,

I'd like to add the capability to perform secure DFU over USB with the secure DFU BLE bootloader as a baseline. What needs to be done to achieve this? In addition to adding the USB transport, do I need to add USB CDC in the bootloader to be able to send the DFU using nrfutil?

I'm using sdk v17 as the baseline for the secure DFU bootloader.

Thanks

Parents
  • Hi,

    The open USB bootloader have everything needed to be a secure bootloader (and in fact by default it do require signature on bootloader updates). The only change that is needed in order to also require signature verification on application and SoftDevice updates is to set NRF_DFU_REQUIRE_SIGNED_APP_UPDATE to 1 in the bootlaoder's sdk_config.h. So if all you need is the USB transport, then take the example and make this change.

    If you want to combine USB with BLE, then you should take one of the examples and add includes, configuration, etc from the other, as well as adjust size and start address (there are quite a few things to resolve so it is a bit of work but not a huge task). Essentially all you need to add a transport is to add the required files, and then it will automatically be initialized and work out of the box. You do not need to do anything else to support for the USB CDC, as that is all part of the USB transport implementation.

  • Hi,

    To get a combined USB + BLE DFU secure bootloader, I took the USB example as a baseline and merged sdk_config.h, the Makefile, and the linker script from the BLE example. However, it looks like there are conflicts in the linker script and there's not enough room in Flash:

    _build/nrf52840_xxaa.out section `.text' will not fit in region `FLASH'
    region FLASH overflowed with .data and user data
    section .mbr_params_page VMA [00000000000fe000,00000000000fefff] overlaps section .text VMA [00000000000f4000,00000000000fe077]
    section .crypto_data VMA [00000000000fe078,00000000000fe07f] overlaps section .mbr_params_page VMA [00000000000fe000,00000000000fefff]
    region `FLASH' overflowed by 284 bytes

    Could you advise on how the best way to resolve these issues? What's the best way to attach the resulting sdk_config.h, Makefile, and linker script, so you can better assist?

Reply
  • Hi,

    To get a combined USB + BLE DFU secure bootloader, I took the USB example as a baseline and merged sdk_config.h, the Makefile, and the linker script from the BLE example. However, it looks like there are conflicts in the linker script and there's not enough room in Flash:

    _build/nrf52840_xxaa.out section `.text' will not fit in region `FLASH'
    region FLASH overflowed with .data and user data
    section .mbr_params_page VMA [00000000000fe000,00000000000fefff] overlaps section .text VMA [00000000000f4000,00000000000fe077]
    section .crypto_data VMA [00000000000fe078,00000000000fe07f] overlaps section .mbr_params_page VMA [00000000000fe000,00000000000fefff]
    region `FLASH' overflowed by 284 bytes

    Could you advise on how the best way to resolve these issues? What's the best way to attach the resulting sdk_config.h, Makefile, and linker script, so you can better assist?

Children
  • Hi,

    mablabs said:
    To get a combined USB + BLE DFU secure bootloader, I took the USB example as a baseline

    I think it would be easier to take the BLE bootloader as baseline, just because that would probably have you doing fewer modifications. But both will work as long as you get all you need from both. If you use the USB project as stating point, remember to add all the SoftDevice and BLE related files and includes to the Makefile, and also defines such as SOFTDEVICE_PRESENT instead of MBR_PRESENT, get S140, etc.

    mablabs said:
    Could you advise on how the best way to resolve these issues?

    Regarding flash size that will increase when you need to fit both the USB and BLE transport, so you need to move down the start address and increase the size. When you use GCC and Makefile, that means adjusting this line in the linker script:

      FLASH (rx) : ORIGIN = 0xf8000, LENGTH = 0x6000

    Lower the start address and increase the length so that everything fits, and you have two free pages above (for MBR params and bootloader settings).

    mablabs said:
    What's the best way to attach the resulting sdk_config.h, Makefile, and linker script, so you can better assist?

    Use Insert -> Image/video/file, click the "Upload" text, select the file and click the OK button after it has been uploaded. Do this for every file, or zip all files together and upload the zip.

  • Thanks for the response. I was able to modify the FLASH regions in the linker script in the following manner to eliminate the overflow by 284 bytes and the overlap in the sections, but still get the following error (which is not too descriptive):

    "region FLASH overflowed with .data and user data"

    /* Linker script to configure memory regions. */

    SEARCH_DIR(.)
    GROUP(-lgcc -lc -lnosys)

    MEMORY
    {
    FLASH (rx) : ORIGIN = 0xf3ed8, LENGTH = 0xa128
    RAM (rwx) : ORIGIN = 0x20000008, LENGTH = 0x3fff8
    uicr_bootloader_start_address (r) : ORIGIN = 0x10001014, LENGTH = 0x4
    bootloader_settings_page (r) : ORIGIN = 0x000FF000, LENGTH = 0x1000
    uicr_mbr_params_page (r) : ORIGIN = 0x10001018, LENGTH = 0x4
    mbr_params_page (r) : ORIGIN = 0x000FE000, LENGTH = 0x1000
    }

    SECTIONS
    {
    . = ALIGN(4);
    .uicr_bootloader_start_address :
    {
    PROVIDE(__start_uicr_bootloader_start_address = .);
    KEEP(*(SORT(.uicr_bootloader_start_address*)))
    PROVIDE(__stop_uicr_bootloader_start_address = .);
    } > uicr_bootloader_start_address
    . = ALIGN(4);
    .bootloader_settings_page(NOLOAD) :
    {
    PROVIDE(__start_bootloader_settings_page = .);
    KEEP(*(SORT(.bootloader_settings_page*)))
    PROVIDE(__stop_bootloader_settings_page = .);
    } > bootloader_settings_page
    . = ALIGN(4);
    .uicr_mbr_params_page :
    {
    PROVIDE(__start_uicr_mbr_params_page = .);
    KEEP(*(SORT(.uicr_mbr_params_page*)))
    PROVIDE(__stop_uicr_mbr_params_page = .);
    } > uicr_mbr_params_page
    . = ALIGN(4);
    .mbr_params_page(NOLOAD) :
    {
    PROVIDE(__start_mbr_params_page = .);
    KEEP(*(SORT(.mbr_params_page*)))
    PROVIDE(__stop_mbr_params_page = .);
    } > mbr_params_page
    }

    SECTIONS
    {
    . = ALIGN(4);
    .mem_section_dummy_ram :
    {
    }
    .fs_data :
    {
    PROVIDE(__start_fs_data = .);
    KEEP(*(.fs_data))
    PROVIDE(__stop_fs_data = .);
    } > RAM
    .log_dynamic_data :
    {
    PROVIDE(__start_log_dynamic_data = .);
    KEEP(*(SORT(.log_dynamic_data*)))
    PROVIDE(__stop_log_dynamic_data = .);
    } > RAM
    .log_filter_data :
    {
    PROVIDE(__start_log_filter_data = .);
    KEEP(*(SORT(.log_filter_data*)))
    PROVIDE(__stop_log_filter_data = .);
    } > RAM

    } INSERT AFTER .data;

    SECTIONS
    {
    .mem_section_dummy_rom :
    {
    }
    .crypto_data :
    {
    PROVIDE(__start_crypto_data = .);
    KEEP(*(SORT(.crypto_data*)))
    PROVIDE(__stop_crypto_data = .);
    } > FLASH
    .dfu_trans :
    {
    PROVIDE(__start_dfu_trans = .);
    KEEP(*(SORT(.dfu_trans*)))
    PROVIDE(__stop_dfu_trans = .);
    } > FLASH
    .svc_data :
    {
    PROVIDE(__start_svc_data = .);
    KEEP(*(.svc_data))
    PROVIDE(__stop_svc_data = .);
    } > FLASH
    .nrf_queue :
    {
    PROVIDE(__start_nrf_queue = .);
    KEEP(*(.nrf_queue))
    PROVIDE(__stop_nrf_queue = .);
    } > FLASH
    .log_const_data :
    {
    PROVIDE(__start_log_const_data = .);
    KEEP(*(SORT(.log_const_data*)))
    PROVIDE(__stop_log_const_data = .);
    } > FLASH
    .nrf_balloc :
    {
    PROVIDE(__start_nrf_balloc = .);
    KEEP(*(.nrf_balloc))
    PROVIDE(__stop_nrf_balloc = .);
    } > FLASH
    .sdh_ble_observers :
    {
    PROVIDE(__start_sdh_ble_observers = .);
    KEEP(*(SORT(.sdh_ble_observers*)))
    PROVIDE(__stop_sdh_ble_observers = .);
    } > FLASH
    .log_backends :
    {
    PROVIDE(__start_log_backends = .);
    KEEP(*(SORT(.log_backends*)))
    PROVIDE(__stop_log_backends = .);
    } > FLASH
    .sdh_req_observers :
    {
    PROVIDE(__start_sdh_req_observers = .);
    KEEP(*(SORT(.sdh_req_observers*)))
    PROVIDE(__stop_sdh_req_observers = .);
    } > FLASH
    .sdh_state_observers :
    {
    PROVIDE(__start_sdh_state_observers = .);
    KEEP(*(SORT(.sdh_state_observers*)))
    PROVIDE(__stop_sdh_state_observers = .);
    } > FLASH
    .sdh_stack_observers :
    {
    PROVIDE(__start_sdh_stack_observers = .);
    KEEP(*(SORT(.sdh_stack_observers*)))
    PROVIDE(__stop_sdh_stack_observers = .);
    } > FLASH
    .sdh_soc_observers :
    {
    PROVIDE(__start_sdh_soc_observers = .);
    KEEP(*(SORT(.sdh_soc_observers*)))
    PROVIDE(__stop_sdh_soc_observers = .);
    } > FLASH

    } INSERT AFTER .text


    INCLUDE "nrf_common.ld"

  • It looks like you still need to move the bootloader start address down a bit (say 0x2000 down). See this thread.

  • Thanks for the response.

    • By the bootloader start address, do you mean the "uicr_bootloader_start_address"?
    • How did you determine that it's the bootloader that needs to be moved down (since the error isn't descriptive)?
    • By "down", do you mean to increase the value of the origin? 
  • Hi,

    mablabs said:
    By the bootloader start address, do you mean the "uicr_bootloader_start_address"?

    No. That is the address where the bootloader start address is placed, and that happens automatically during the build. I mean the start address of the bootloader, which is what you set in your linker configuration, in the exact same way as you set the start address of your application. Specifically, in this line FLASH ORIGIN is where you set the start address:

      FLASH (rx) : ORIGIN =...

    I did not spot this before, but you also have this set to a odd value. note that this must always be page aligned (so it must be a multiple of 0x1000).

    mablabs said:
    How did you determine that it's the bootloader that needs to be moved down (since the error isn't descriptive)?

    That may have been a wrong assumption, I was thinking that you were building the bootloader project? If you are, then that is what needs to move, as the message tells you that it cannot fit whatever you are building in the flash region you have specified in the linker script.

    mablabs said:
    By "down", do you mean to increase the value of the origin? 

    No, I mean decrease the value. With a lower start address you can increase the size (the end address is given by the physically available flash memory). Note that you must ensure that you do not move it so far down that it overlaps with your application and also leave room for potential application data in the flash area between the application itself and the bootloader (if any)

Related