Skip to content

Add RIOT bootloader to manage firmware slots#6922

Closed
kYc0o wants to merge 11 commits intoRIOT-OS:masterfrom
kYc0o:riot_bootloader_and_slots
Closed

Add RIOT bootloader to manage firmware slots#6922
kYc0o wants to merge 11 commits intoRIOT-OS:masterfrom
kYc0o:riot_bootloader_and_slots

Conversation

@kYc0o
Copy link
Contributor

@kYc0o kYc0o commented Apr 18, 2017

This PR is based on #6919.

Following #6919, this PR aims to use the generated firmware metadata and put it at the beginning of a firmware binary.

A bootloader based on RIOT is now able to read the metadata and to boot the newest version if the application ID is the same, otherwise it will fallback to the slot 1. In addition, an interactive bootloader is available by setting INTERACTIVE_BOOTLOADER = 1 in the bootlaoder's Makefile.

The assumption to fallback to slot 1 is because this PR enables a new target that can be flashed directly from any application, by running make bootloader flash. This will compile the application, the bootloader, and create an ELF file with both images inside, which can be flashed by openocd. By default, the application will take the first slot (while the bootloader will take slot 0), thus I assume that at least slot 1 should be available.

In order to use slot 2, the user should implement a mechanism to download a firmware with valid metadata. A firmware of this kind can be generated by doing make FW_SLOT=2 APPID=[32bit Hex] VERSION=[16bit > 0] firmware-slot on any example or application. This will produce a file of the kind application-slot2-APPID-VERSION.bin which should fit slot 2 allocated space. This file will be located in the bin directory.

A following-up PR will propose a way to download such a firmware.

IMPORTANT
This PR will work only on iotlab-m3 platforms, or any stm32f103re mcu based board.
Adding new mcu's requires only to set where the slots begin and end. You can take cpu/stm32f1/include/cpu_conf.h as a example. Also, to write new firmwares, you will need the periph_flashpage feature, which is only available for some CPU's in RIOT.

Besides, the current approach to boot other slots is to move the VTOR location, which is a feature only available on cortex-m3/4 mcu's.

P.S. @haukepetersen for a strange reason the cpu_init does not need to be skipped anymore...
Fixed in #6970

@kYc0o kYc0o added Platform: ARM Platform: This PR/issue effects ARM-based platforms Type: new feature The issue requests / The PR implemements a new feature for RIOT Area: tools Area: Supplementary tools labels Apr 18, 2017
@kYc0o kYc0o force-pushed the riot_bootloader_and_slots branch from d4ed5ba to 9dabe0e Compare April 20, 2017 18:07
@kYc0o
Copy link
Contributor Author

kYc0o commented Apr 20, 2017

I just added another feature that could increase the security.

In #6919 it's proposed a single hash over the firmware, which can allow to send "valid" firmwares, by just changing the version. Now, the hash is done again including the metadata, which will also hash the version.

@kYc0o kYc0o force-pushed the riot_bootloader_and_slots branch 2 times, most recently from eb64f41 to 668ce72 Compare May 4, 2017 16:28
@kYc0o kYc0o added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label May 11, 2017
@kYc0o kYc0o force-pushed the riot_bootloader_and_slots branch 4 times, most recently from 85e543e to 71b4b54 Compare May 11, 2017 14:42
@kYc0o
Copy link
Contributor Author

kYc0o commented May 11, 2017

@kaspar030 for some reason this PR fails with pic32 boards... but I don't understand why, can you check?

@kYc0o kYc0o added CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR and removed CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels May 22, 2017
@kYc0o kYc0o force-pushed the riot_bootloader_and_slots branch from 71b4b54 to 8365d4c Compare May 22, 2017 13:39
@kYc0o
Copy link
Contributor Author

kYc0o commented May 22, 2017

@kaspar030 for some reason this PR fails with pic32 boards... but I don't understand why, can you check?

ping @kaspar030

@kaspar030
Copy link
Contributor

check your objcopy command lines. They include "--output-target elf32-littlearm --binary-architecture=arm", which certainly fails on mips.

@kYc0o
Copy link
Contributor Author

kYc0o commented May 22, 2017

check your objcopy command lines. They include "--output-target elf32-littlearm --binary-architecture=arm", which certainly fails on mips.

That line shouldn't also fail on AVR targets?

@kaspar030
Copy link
Contributor

That line shouldn't also fail on AVR targets?

Probably. I don't know... Can you reproduce the error locally?

@kYc0o
Copy link
Contributor Author

kYc0o commented May 22, 2017

Actually I don't see why Murdock execute such line, since it should only work for valid platforms using correct flags.

How can I execute that Murdock command locally?

@kaspar030
Copy link
Contributor

How can I execute that Murdock command locally?

Just compile any application for pic32-wildfire. This is not murdock specific.

@kYc0o
Copy link
Contributor Author

kYc0o commented May 22, 2017

/Users/facosta/git/RIOT-OS/RIOT/makefiles/arch/mips.inc.mk:3: *** "Please set $(MIPS_ELF_ROOT) and ensure $(MIPS_ELF_ROOT)/bin is on your PATH".  Stop.

Well... I need the toolchain...

@kaspar030
Copy link
Contributor

Well... I need the toolchain...

Try building in docker.

@kYc0o
Copy link
Contributor Author

kYc0o commented May 22, 2017

I'm trying to follow the instructions on the wiki but I have this error:

unable to prepare context: unable to evaluate symlinks in Dockerfile path: lstat /Users/facosta/git/RIOT-OS/RIOT/dist/Dockerfile: no such file or directory

Is the wiki updated with the current RIOT repository organisation?

@kaspar030
Copy link
Contributor

Is the wiki updated with the current RIOT repository organisation?

Looks outdated. If you've got docker installed, "BUILD_IN_DOCKER=1 make all" in any application directory should actually download the correct docker image if it is not locally available.

@kYc0o
Copy link
Contributor Author

kYc0o commented May 22, 2017

I have a completely unrelated error:

Launching build container using image "riot/riotbuild:latest".
docker run --rm -i -t -u "$(id -u)" \
	    -v '/Users/facosta/git/RIOT2/RIOT:/data/riotbuild/riotbase' \
	    -v '/Users/facosta/git/RIOT2/RIOT/cpu:/data/riotbuild/riotcpu' \
	    -v '/Users/facosta/git/RIOT2/RIOT/boards:/data/riotbuild/riotboard' \
	    -v '/Users/facosta/git/RIOT2/RIOT/makefiles:/data/riotbuild/riotmake' \
	    -v '/Users/facosta/git/RIOT2/RIOT:/data/riotbuild/riotproject' \
	    -v /etc/localtime:/etc/localtime:ro \
	    -e 'RIOTBASE=/data/riotbuild/riotbase' \
	    -e 'CCACHE_BASEDIR=/data/riotbuild/riotbase' \
	    -e 'RIOTCPU=/data/riotbuild/riotcpu' \
	    -e 'RIOTBOARD=/data/riotbuild/riotboard' \
	    -e 'RIOTMAKE=/data/riotbuild/riotmake' \
	    -e 'RIOTPROJECT=/data/riotbuild/riotproject' \
	    -e 'BOARD=pic32-wifire' \
	    -w '/data/riotbuild/riotproject/examples/default/' \
	    'riot/riotbuild:latest' make all 
Building application "default" for "pic32-wifire" with MCU "mips_pic32mz".

"make" -C /data/riotbuild/riotbase/core
"make" -C /data/riotbuild/riotbase/drivers
"make" -C /data/riotbuild/riotbase/drivers/saul
"make" -C /data/riotbuild/riotbase/sys
"make" -C /data/riotbuild/riotbase/sys/auto_init
"make" -C /data/riotbuild/riotbase/sys/auto_init/saul
"make" -C /data/riotbuild/riotbase/sys/fmt
"make" -C /data/riotbuild/riotbase/sys/phydat
"make" -C /data/riotbuild/riotbase/sys/ps
"make" -C /data/riotbuild/riotbase/sys/saul_reg
"make" -C /data/riotbuild/riotbase/sys/shell
"make" -C /data/riotbuild/riotbase/sys/shell/commands
"make" -C /data/riotbuild/riotboard/pic32-wifire
"make" -C /data/riotbuild/riotcpu/mips_pic32mz
"make" -C /data/riotbuild/riotcpu/mips32r2_common
"make" -C /data/riotbuild/riotcpu/mips32r2_common/periph
"make" -C /data/riotbuild/riotcpu/mips_pic32_common
"make" -C /data/riotbuild/riotcpu/mips_pic32_common/periph
/data/riotbuild/riotproject/examples/default/bin/pic32-wifire/cpu.a(thread_arch.o): In function `_mips_handle_exception':
/data/riotbuild/riotcpu/mips32r2_common/thread_arch.c:(.text._mips_handle_exception+0x4c): undefined reference to `uart_write'
/data/riotbuild/riotproject/examples/default/bin/pic32-wifire/board.a(wifire.o): In function `board_init':
/data/riotbuild/riotboard/pic32-wifire/wifire.c:(.text.board_init+0x20): undefined reference to `uart_init'
collect2: error: ld returned 1 exit status
/data/riotbuild/riotbase/Makefile.include:316: recipe for target 'all' failed
make: *** [all] Error 1
make: *** [..in-docker-container] Error 2

@kYc0o
Copy link
Contributor Author

kYc0o commented May 22, 2017

For the gnrc_networking example I succeeded to have the same error as Murdock. However, nothing is related to my code.

objcopy  -O ihex --change-section-lma .lowerbootflashalias-0xA0000000 --change-section-lma .bootflash1-0xA0000000 --change-section-lma .bootflash2-0xA0000000 --change-section-lma .exception_vector-0x80000000 --change-section-lma .text-0x80000000 --change-section-lma .init-0x80000000 --change-section-lma .fini-0x80000000 --change-section-lma .eh_frame-0x80000000 --change-section-lma .gcc_except_table-0x80000000 --change-section-lma .jcr-0x80000000 --change-section-lma .ctors-0x80000000 --change-section-lma .dtors-0x80000000 --change-section-lma .rodata-0x80000000 --change-section-lma .data-0x80000000 --change-section-lma .bss-0x80000000 --change-section-lma .startdata-0x80000000 /data/riotbuild/riotproject/examples/gnrc_networking/bin/pic32-wifire/gnrc_networking.elf /data/riotbuild/riotproject/examples/gnrc_networking/bin/pic32-wifire/gnrc_networking.hex
objcopy: --change-section-lma .gcc_except_table+0xffffffff80000000 never used
objcopy  -O binary /data/riotbuild/riotproject/examples/gnrc_networking/bin/pic32-wifire/gnrc_networking.elf /data/riotbuild/riotproject/examples/gnrc_networking/bin/pic32-wifire/gnrc_networking.bin
objcopy: Unable to recognise the format of the input file `/data/riotbuild/riotproject/examples/gnrc_networking/bin/pic32-wifire/gnrc_networking.elf'
/data/riotbuild/riotbase/Makefile.include:316: recipe for target 'all' failed

@kYc0o
Copy link
Contributor Author

kYc0o commented May 22, 2017

I think I found the error. BINFILE was defined without guards in my code, and I think somewhere in the Makefiles for mips BINFILE is used, so that's why the compiler gets confused. Let's see if Murdock thinks the same...

@kYc0o kYc0o force-pushed the riot_bootloader_and_slots branch from 442d3a5 to eb4529e Compare May 22, 2017 16:01
Copy link
Contributor

@kaspar030 kaspar030 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the functionality of this PR needs to be organized a little better.

  • find better name than "fw-slots"

  • factor out "multi-slot" stuff in seperate files.

  • is it really necessarry to have multiple compiles? Can't the necessary variables be set just at the linking step, or be deduced by e.g., the address of reset handler, or a combination?

  • One linker file should be enough (with parameterized sizes)

@kYc0o
Copy link
Contributor Author

kYc0o commented May 30, 2017

find better name than "fw-slots"

Well, I'm open to propositions, I need to describe what this modules does, which is manipulate images on the internal ROM divided by slots.

factor out "multi-slot" stuff in seperate files.

I don't really get this. Do you mean separate the functions in different files? What's the rationale?

is it really necessarry to have multiple compiles? Can't the necessary variables be set just at the linking step, or be deduced by e.g., the address of reset handler, or a combination?

Currently I'm only triggering two compiles (one for the bootloader, one for the application), which each one is linked to the correct addresses according to the slot information. I don't see how to avoid this, or why is harmful/suboptimal.

One linker file should be enough (with parameterized sizes)

Well I tried this once in #6450 using gcc to "compile" the linker file using external variables. The method looks fancy but IMHO was a bit ugly and unnecessary, since we're not handling with tons of linker scripts but only 3, one per slot and one for the bootloader. The assumption is that we don't need more than 2 slots, which represent the current image and the update.

@kYc0o kYc0o force-pushed the riot_bootloader_and_slots branch from 7d6cd0d to 02235f8 Compare June 9, 2017 16:31
@kYc0o kYc0o added the State: waiting for other PR State: The PR requires another PR to be merged first label Jun 9, 2017
* @brief Branch the execution to a specified address, usually used to
* jump to another RIOT instance.
*/
static inline void cortexm_branch_address(uint32_t destination_address)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this work for you on samr21-xpro? I'm getting a compile error in line 205. Also the jumping seems to hard fault.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nevermind, I fixed it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I had it too, apparently that option is only valid for M3 mcu.

I have a branch with some modifications to work with samr21 but there's something not working with the metadata.

@kYc0o
Copy link
Contributor Author

kYc0o commented Aug 7, 2017

Closing in favour of #7457.

@kYc0o kYc0o closed this Aug 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: tools Area: Supplementary tools CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms State: waiting for other PR State: The PR requires another PR to be merged first Type: new feature The issue requests / The PR implemements a new feature for RIOT

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants