Skip to content

[WIP] Add ota_update module (second attempt)#7398

Closed
kYc0o wants to merge 14 commits intoRIOT-OS:masterfrom
kYc0o:ota_updates
Closed

[WIP] Add ota_update module (second attempt)#7398
kYc0o wants to merge 14 commits intoRIOT-OS:masterfrom
kYc0o:ota_updates

Conversation

@kYc0o
Copy link
Contributor

@kYc0o kYc0o commented Jul 21, 2017

This PR is based on #7396 which is also based on @kaspar030 work.

It basically adds the capability of retrieving updates from a TFTP server.

To do so, you need to setup an ota-server following the steps in this repo.

Then you can run the server with the following parameters:

./ota-server --static-path=../otaserver/static --upload-path=../otaserver/static/uploads

This ensures the server looks for the firmware binaries in the right directory.
The ota-server application will start at CoAP server listening on the default port 5683, which will answer the requests from this ota_update module. As in #7167, the module requests periodically the latest version from the server, and if it finds a newer one it starts to download it using TFTP.

For the TFTP server, you need to install the tftpd-hpa server (sudo apt-get install tftpd-hpa on ubuntu). Afterwards, to manually setup the server folder, you need first to stop the daemon:

$ sudo /etc/init.d/tftpd-hpa stop

Then, start the server on the uploads folder:

$ sudo in.tftpd -vvv -L -6 -c -s -u ${USER} otaserver/static/uploads/

This will start to listen for TFTP request from this OTA module.

@kYc0o kYc0o added Type: new feature The issue requests / The PR implemements a new feature for RIOT State: waiting for other PR State: The PR requires another PR to be merged first State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet labels Jul 21, 2017
@kYc0o kYc0o added this to the Release 2017.10 milestone Jul 21, 2017
@kYc0o
Copy link
Contributor Author

kYc0o commented Jul 21, 2017

@emmanuelsearch You can try the instructions from #7396 in this branch. I tested it in samr21-xpro successfully, by updating incrementally on both slots.

@kYc0o kYc0o changed the title Add ota_update module (second attempt) [WIP] Add ota_update module (second attempt) Jul 21, 2017
@emmanuelsearch
Copy link
Member

when I make multislot I get

/home/vagrant/RIOT/Makefile.dep:660: *** extraneous 'endif'.  Stop.

@emmanuelsearch
Copy link
Member

and: what do you mean by 'this PR is based on #7396'?
Should we close #7396?
Is this PR dependent en #7396?

@kYc0o
Copy link
Contributor Author

kYc0o commented Jul 22, 2017

/home/vagrant/RIOT/Makefile.dep:660: *** extraneous 'endif'. Stop.

Sorry, a leftover from a previous rebase.

Should be good now

@kYc0o
Copy link
Contributor Author

kYc0o commented Jul 22, 2017

I found another bug which I fixed. Should be working now in OS X and Vagrant.

@kYc0o
Copy link
Contributor Author

kYc0o commented Jul 22, 2017

Is this PR dependent en #7396?

Yes it depends on that PR. I did it that way to ease the review process, so I wouldn't like to close it.

@emmanuelsearch
Copy link
Member

@kYc0o thanks for the update.
Now when I make multislot I get the following error:

$ BOARD=samr21-xpro make multislot
NON BOOTLOADER BUILD
Building application "hello-world" for "samr21-xpro" with MCU "samd21".

"make" -C /home/vagrant/RIOT/boards/samr21-xpro
"make" -C /home/vagrant/RIOT/core
"make" -C /home/vagrant/RIOT/cpu/samd21
"make" -C /home/vagrant/RIOT/cpu/cortexm_common
"make" -C /home/vagrant/RIOT/cpu/cortexm_common/periph
"make" -C /home/vagrant/RIOT/cpu/sam0_common
"make" -C /home/vagrant/RIOT/cpu/sam0_common/periph
"make" -C /home/vagrant/RIOT/cpu/samd21/periph
"make" -C /home/vagrant/RIOT/drivers
"make" -C /home/vagrant/RIOT/drivers/periph_common
"make" -C /home/vagrant/RIOT/sys
"make" -C /home/vagrant/RIOT/sys/auto_init
"make" -C /home/vagrant/RIOT/sys/isrpipe
"make" -C /home/vagrant/RIOT/sys/newlib_syscalls_default
"make" -C /home/vagrant/RIOT/sys/pm_layered
"make" -C /home/vagrant/RIOT/sys/tsrb
"make" -C /home/vagrant/RIOT/sys/uart_stdio
   text	   data	    bss	    dec	    hex	filename
   8608	    136	   2748	  11492	   2ce4	/home/vagrant/RIOT/examples/hello-world/bin/samr21-xpro/hello-world.elf
make: Entering directory '/home/vagrant/RIOT/bootloader'
BOOTLOADER BUILD
make: Nothing to be done for 'clean'.
Building application "bootloader" for "samr21-xpro" with MCU "samd21".

"make" -C /home/vagrant/RIOT/pkg/tweetnacl
rm -Rf /home/vagrant/RIOT/bootloader/bin/pkg/samr21-xpro/tweetnacl
mkdir -p /home/vagrant/RIOT/bootloader/bin/pkg/samr21-xpro/tweetnacl
/home/vagrant/RIOT/dist/tools/git/git-cache clone "https://github.com/RIOT-OS/tweetnacl" "7ea05c7098a16c87fa66e9166ce301666f3f2623" "/home/vagrant/RIOT/bootloader/bin/pkg/samr21-xpro/tweetnacl"
Cloning into '/home/vagrant/RIOT/bootloader/bin/pkg/samr21-xpro/tweetnacl'...
remote: Counting objects: 26, done.        
remote: Total 26 (delta 0), reused 0 (delta 0), pack-reused 26        
Unpacking objects: 100% (26/26), done.
Checking connectivity... done.
HEAD is now at 7ea05c7... Update README.md
touch /home/vagrant/RIOT/bootloader/bin/pkg/samr21-xpro/tweetnacl/.git-downloaded
"make" -C /home/vagrant/RIOT/bootloader/bin/pkg/samr21-xpro/tweetnacl
"make" -C /home/vagrant/RIOT/boards/samr21-xpro
"make" -C /home/vagrant/RIOT/core
"make" -C /home/vagrant/RIOT/cpu/samd21
"make" -C /home/vagrant/RIOT/cpu/cortexm_common
"make" -C /home/vagrant/RIOT/cpu/cortexm_common/periph
"make" -C /home/vagrant/RIOT/cpu/sam0_common
"make" -C /home/vagrant/RIOT/cpu/sam0_common/periph
"make" -C /home/vagrant/RIOT/cpu/samd21/periph
"make" -C /home/vagrant/RIOT/drivers
"make" -C /home/vagrant/RIOT/drivers/periph_common
"make" -C /home/vagrant/RIOT/sys
"make" -C /home/vagrant/RIOT/sys/auto_init
"make" -C /home/vagrant/RIOT/sys/checksum
"make" -C /home/vagrant/RIOT/sys/firmware
"make" -C /home/vagrant/RIOT/sys/isrpipe
"make" -C /home/vagrant/RIOT/sys/newlib_syscalls_default
"make" -C /home/vagrant/RIOT/sys/pm_layered
"make" -C /home/vagrant/RIOT/sys/tsrb
"make" -C /home/vagrant/RIOT/sys/uart_stdio
   text	   data	    bss	    dec	    hex	filename
  15580	    168	   6464	  22212	   56c4	/home/vagrant/RIOT/bootloader/bin/samr21-xpro/bootloader.elf
make: Leaving directory '/home/vagrant/RIOT/bootloader'
/bin/sh: 1: bc: not found
/bin/sh: 1: bc: not found
/home/vagrant/RIOT/dist/tools/firmware_metadata/bin/firmware: 1: /home/vagrant/RIOT/dist/tools/firmware_metadata/bin/firmware: Syntax error: "(" unexpected
/home/vagrant/RIOT/dist/tools/firmware_metadata/bin/firmware: 1: /home/vagrant/RIOT/dist/tools/firmware_metadata/bin/firmware: Syntax error: "(" unexpected
/home/vagrant/RIOT/makefiles/multislot.mk:140: recipe for target 'multislot' failed
make: *** [multislot] Error 2

@kYc0o
Copy link
Contributor Author

kYc0o commented Jul 23, 2017

Oh yes, for the vagrant image bc needs to be installed sudo apt-get install bc. In most "normal" Linux distros it's already installed. I'll add it to the documentation.

@miri64
Copy link
Member

miri64 commented Jul 23, 2017

Oh yes, for the vagrant image bc needs to be installed sudo apt-get install bc. In most "normal" Linux distros it's already installed. I'll add it to the documentation.

Wouldn't it be better to update the vagrant bootstrap script instead?

@emmanuelsearch
Copy link
Member

installed bc. Now I get:

$ BOARD=samr21-xpro make multislot
NON BOOTLOADER BUILD
make: Entering directory '/home/vagrant/RIOT/dist/tools/firmware_metadata'
mkdir -p bin
cc -g -I. -O3 -Wall -Wextra -pedantic -std=c99 -I../../../sys/include common.c tweetnacl.c randombytes.c ../../../sys/hashes/sha256.c ../../../sys/checksum/fletcher32.c ../../../sys/firmware/firmware.c firmware.c verify.c genkeys.c genmeta.c -o bin/firmware
../../../sys/firmware/firmware.c: In function 'firmware_metadata_print':
../../../sys/firmware/firmware.c:41:12: warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'uint32_t {aka unsigned int}' [-Wformat=]
     printf("Firmware Size: %lu\n", metadata->size);
            ^
../../../sys/firmware/firmware.c:42:12: warning: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'uint32_t {aka unsigned int}' [-Wformat=]
     printf("Firmware APPID: %#lx\n", metadata->appid);
            ^
../../../sys/firmware/firmware.c:43:12: warning: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'uint32_t {aka unsigned int}' [-Wformat=]
     printf("Firmware Version: %#lx\n", metadata->version);
            ^
make: Leaving directory '/home/vagrant/RIOT/dist/tools/firmware_metadata'
Building application "hello-world" for "samr21-xpro" with MCU "samd21".

"make" -C /home/vagrant/RIOT/boards/samr21-xpro
"make" -C /home/vagrant/RIOT/core
"make" -C /home/vagrant/RIOT/cpu/samd21
"make" -C /home/vagrant/RIOT/cpu/cortexm_common
"make" -C /home/vagrant/RIOT/cpu/cortexm_common/periph
"make" -C /home/vagrant/RIOT/cpu/sam0_common
"make" -C /home/vagrant/RIOT/cpu/sam0_common/periph
"make" -C /home/vagrant/RIOT/cpu/samd21/periph
"make" -C /home/vagrant/RIOT/drivers
"make" -C /home/vagrant/RIOT/drivers/periph_common
"make" -C /home/vagrant/RIOT/sys
"make" -C /home/vagrant/RIOT/sys/auto_init
"make" -C /home/vagrant/RIOT/sys/isrpipe
"make" -C /home/vagrant/RIOT/sys/newlib_syscalls_default
"make" -C /home/vagrant/RIOT/sys/pm_layered
"make" -C /home/vagrant/RIOT/sys/tsrb
"make" -C /home/vagrant/RIOT/sys/uart_stdio
   text	   data	    bss	    dec	    hex	filename
   8608	    136	   2748	  11492	   2ce4	/home/vagrant/RIOT/examples/hello-world/bin/samr21-xpro/hello-world.elf
usage: firmware genmeta <BINFILE> <VERSION> <APPID> <START-ADDR> <seckey> <outfile>
usage: firmware genmeta <BINFILE> <VERSION> <APPID> <START-ADDR> <seckey> <outfile>
/home/vagrant/RIOT/makefiles/multislot.mk:140: recipe for target 'multislot' failed
make: *** [multislot] Error 255

@kYc0o
Copy link
Contributor Author

kYc0o commented Jul 23, 2017

Hmm that starts to be strange... can you try again with QUIET=0

@kYc0o
Copy link
Contributor Author

kYc0o commented Jul 23, 2017

Wouldn't it be better to update the vagrant bootstrap script instead?

That would only work for new downloads of the vagrant image or?

@kYc0o
Copy link
Contributor Author

kYc0o commented Jul 27, 2017

Added support for iotlab-m3 board.

@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 Jul 27, 2017
@kYc0o kYc0o force-pushed the ota_updates branch 5 times, most recently from affff4f to 2ce0d0e Compare July 28, 2017 00:30
Copy link
Contributor

@aabadie aabadie left a comment

Choose a reason for hiding this comment

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

I made a pass of review on this one. Nice work.

I think the OTA test we made in July was with the previous version from #7167 ? In this case, I'd like to test this one soon ;)

Also sorry, I didn't noticed initially that it was based on #7396 so some of my comments here are related to this one.

uint32_t appid_slot1 = 0, appid_slot2 = 0;
firmware_metadata_t metadata;

puts("[bootlaoder] Checking for slots metadata...");
Copy link
Contributor

Choose a reason for hiding this comment

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

typo 'bootloader'

memcpy(&metadata, firmware_get_metadata(1), sizeof(firmware_metadata_t));
if (firmware_validate_metadata_checksum(&metadata) != -1) {
appid_slot1 = metadata.appid;
printf("[bootlaoder] Found slot 1 with APPID: 0x%lx \n", appid_slot1);
Copy link
Contributor

Choose a reason for hiding this comment

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

typo bootloader

memcpy(&metadata, firmware_get_metadata(2), sizeof(firmware_metadata_t));
if (firmware_validate_metadata_checksum(&metadata) != -1) {
appid_slot2 = metadata.appid;
printf("[bootlaoder] Found slot 2 with APPID: 0x%lx \n", appid_slot2);
Copy link
Contributor

Choose a reason for hiding this comment

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

typo

static int validate_and_boot(uint8_t slot)
{
if (firmware_validate_int_slot(slot) != -1) {
printf("[bootlaoder] slot %d validated! Booting...\n", slot);
Copy link
Contributor

Choose a reason for hiding this comment

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

typo bootloader

puts("[bootloader] Booting failed!");
}
else {
puts("[bootlaoder] Slot 1 inconsistent, no image to boot...");
Copy link
Contributor

Choose a reason for hiding this comment

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

typo

*/

/**
* @file
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing group definition

*
* @return 0 on success or error code
*/
uint32_t fw_slots_get_slot_address(uint8_t slot);
Copy link
Contributor

Choose a reason for hiding this comment

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

should be renamed to firmware_slots_... for consistency

int firmware_sign_metadata(firmware_metadata_t *metadata, unsigned char *sk);

/**
* @brief Validate FW metadata signature
Copy link
Contributor

Choose a reason for hiding this comment

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

FW => firmware
and in other places above

uint8_t sig[FIRMWARE_SIG_LEN]; /**< Firmware signature */
uint8_t pad[FIRMWARE_PADDING]; /**< padding to total of FIRMWARE_METADATA_SIZE bytes */
} firmware_metadata_t;
/** @} */
Copy link
Contributor

Choose a reason for hiding this comment

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

no need for this @{..@} block in doxygen

*/

/**
* @ingroup sys_firmware
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be @defgoup sys_firmware and add @ingroup sys

#include "checksum/fletcher32.h"
#include "tweetnacl.h"

void firmware_metadata_print(firmware_metadata_t *metadata)
Copy link
Contributor

Choose a reason for hiding this comment

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

If this is only for debugging, I think this modification could improve a little the readability of the messages :

void firmware_metadata_print(firmware_metadata_t *metadata, uint8_t slot_id)

Or moving the line 45 (metadata->start_addr) at the beginning of this function.

result = firmware_validate_metadata_signature(&metadata, ed25519_pub);

if (result == -1) {
printf("[firmware] Signature check failed!\n");
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest to modify to

printf("[firmware] Signature check failed! (slot %u)\n",slot );

This can help to identify the wrong slot if the node already rebooted.

@rfuentess
Copy link
Contributor

Nice work!

I have been able to testing this code for iotlab-m3 nodes, and also iotlab-a8-m3 nodes running in the FIT IoT-Lab (although, I need to run manually openocd for the latest).

@kYc0o kYc0o removed this from the Release 2017.10 milestone Oct 16, 2017
@LalunePierr0t
Copy link

Hi
I try to start a bootloader for samr21-xpro starting from your branch.
I do not really understand how to build a combined test app which includes the bootloader and the test app itself. I first tried on branch #7396. But I ddn't get any result. I ve seen a lot changes on this branch. So I start from it.
Let's see what I ve tried step by step :

  • Step 01 : cleaning
    kYc0oRIOT$ find -type d -name "bin" |xargs rm -rf
  • Step 02 : modify boot_img() from main.c from bootloader to add metadata printing :
static int boot_img(void)
{
    uint8_t boot_slot = 0;
    uint32_t appid_slot1 = 0, appid_slot2 = 0;
    firmware_metadata_t metadata;

    puts("[bootlaoder] Checking for slots metadata...");
    memcpy(&metadata, firmware_get_metadata(1), sizeof(firmware_metadata_t));
    if (firmware_validate_metadata_checksum(&metadata) != -1) {
        appid_slot1 = metadata.appid;
        printf("[bootlaoder] Found slot 1 with APPID: 0x%lx \n", appid_slot1);
    }
    else {
        puts("[bootloader] Slot 1 not valid");
    }
    firmware_metadata_print(&metadata);

    memcpy(&metadata, firmware_get_metadata(2), sizeof(firmware_metadata_t));
    if (firmware_validate_metadata_checksum(&metadata) != -1) {
        appid_slot2 = metadata.appid;
        printf("[bootlaoder] Found slot 2 with APPID: 0x%lx \n", appid_slot2);
    }
    else {
        puts("[bootloader] Slot 2 not valid");
    }
    firmware_metadata_print(&metadata);
  • Step 03 : build and flash bootloader :
~/repo_master/kYc0oRIOT$ cd bootloader/ && BOARD=samr21-xpro make flash
Building application "bootloader" for "samr21-xpro" with MCU "samd21".

rm -Rf /home/pierr0t/repo_master/kYc0oRIOT/bootloader/bin/pkg/samr21-xpro/tweetnacl
mkdir -p /home/pierr0t/repo_master/kYc0oRIOT/bootloader/bin/pkg/samr21-xpro/tweetnacl
/home/pierr0t/repo_master/kYc0oRIOT/dist/tools/git/git-cache clone "https://github.com/RIOT-OS/tweetnacl" "7ea05c7098a16c87fa66e9166ce301666f3f2623" "/home/pierr0t/repo_master/kYc0oRIOT/bootloader/bin/pkg/samr21-xpro/tweetnacl"
git-cache: cloning from cache.
Clonage dans '/home/pierr0t/repo_master/kYc0oRIOT/bootloader/bin/pkg/samr21-xpro/tweetnacl'...
fait.
touch /home/pierr0t/repo_master/kYc0oRIOT/bootloader/bin/pkg/samr21-xpro/tweetnacl/.git-downloaded
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/pkg/tweetnacl
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/bootloader/bin/pkg/samr21-xpro/tweetnacl
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/boards/samr21-xpro
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/core
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/samd21
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/cortexm_common
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/cortexm_common/periph
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/sam0_common
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/sam0_common/periph
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/samd21/periph
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/drivers
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/drivers/periph_common
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/auto_init
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/checksum
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/firmware
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/isrpipe
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/newlib_syscalls_default
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/pm_layered
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/tsrb
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/uart_stdio
   text	   data	    bss	    dec	    hex	filename
  15560	    168	   6464	  22192	   56b0	/home/pierr0t/repo_master/kYc0oRIOT/bootloader/bin/samr21-xpro/bootloader.elf
/home/pierr0t/repo_master/kYc0oRIOT/dist/tools/edbg/edbg  -t atmel_cm0p -b -e -v -p -f /home/pierr0t/repo_master/kYc0oRIOT/bootloader/bin/samr21-xpro/bootloader.bin
Debugger: ATMEL EDBG CMSIS-DAP ATML2127031800003702 03.22.01B3 (S)
Target: SAM R21G18
Erasing...  done.
Programming................................................................. done.
Verification................................................................. done.
  • Step 04 : check the samr21-xpro output :
(18:22:05.367913) main(): This is RIOT! (Version: 2016.03-devel-5669-gfafd-pierr0t-Vostro-3360-ota_updates)
(18:22:05.371701) [bootlaoder] Checking for slots metadata...
(18:22:05.377562) firmware_validate_metadata_checksum: metadata magic number invalid
(18:22:05.380153) [bootloader] Slot 1 not valid
(18:22:05.383086) Firmware magic_number: 0xffffffff
(18:22:05.385330) Firmware Size: 4294967295
(18:22:05.387676) Firmware APPID: 0xffffffff
(18:22:05.390200) Firmware Version: 0xffffffff
(18:22:05.393244) Firmware start address: 0xffffffff
(18:22:05.408628) Firmware HASH: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 
(18:22:05.411012) Firmware chksum: 0xffffffff
(18:22:05.426629) Firmware signature: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 
(18:22:05.432480) firmware_validate_metadata_checksum: metadata magic number invalid
(18:22:05.435073) [bootloader] Slot 2 not valid
(18:22:05.438016) Firmware magic_number: 0xffffffff
(18:22:05.440293) Firmware Size: 4294967295
(18:22:05.442640) Firmware APPID: 0xffffffff
(18:22:05.445694) Firmware Version: 0xffffffff
(18:22:05.448368) Firmware start address: 0xffffffff
(18:22:05.466073) Firmware HASH: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 
(18:22:05.468070) Firmware chksum: 0xffffffff
(18:22:05.485036) Firmware signature: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 
(18:22:05.494989) [bootloader] No valid slot found!

No fw found seem to be logical I ve only flashed the bootloader.

  • Step 05 : build and flash bootloader test app :
~/repo_master/kYc0oRIOT/bootloader$ cd ../tests/bootloader_test/ && BOARD=samr21-xpro make flash-multislot
make: Entering directory '/home/pierr0t/repo_master/kYc0oRIOT/dist/tools/firmware_metadata'
mkdir -p bin
cc -g -I. -O3 -Wall -Wextra -pedantic -std=c99 -I../../../sys/include -Itweetnacl common.c tweetnacl/tweetnacl.c randombytes.c ../../../sys/hashes/sha256.c ../../../sys/checksum/fletcher32.c ../../../sys/firmware/firmware.c firmware.c verify.c genkeys.c genmeta.c -o bin/firmware
../../../sys/firmware/firmware.c: In function 'firmware_metadata_print':
../../../sys/firmware/firmware.c:42:12: warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'uint32_t {aka unsigned int}' [-Wformat=]
     printf("Firmware Size: %lu\n", metadata->size);
            ^
../../../sys/firmware/firmware.c:43:12: warning: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'uint32_t {aka unsigned int}' [-Wformat=]
     printf("Firmware APPID: %#lx\n", metadata->appid);
            ^
../../../sys/firmware/firmware.c:44:12: warning: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'uint32_t {aka unsigned int}' [-Wformat=]
     printf("Firmware Version: %#lx\n", metadata->version);
            ^
make: Leaving directory '/home/pierr0t/repo_master/kYc0oRIOT/dist/tools/firmware_metadata'
Building application "bootloader_test" for "samr21-xpro" with MCU "samd21".

rm -Rf /home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/pkg/samr21-xpro/tweetnacl
mkdir -p /home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/pkg/samr21-xpro/tweetnacl
/home/pierr0t/repo_master/kYc0oRIOT/dist/tools/git/git-cache clone "https://github.com/RIOT-OS/tweetnacl" "7ea05c7098a16c87fa66e9166ce301666f3f2623" "/home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/pkg/samr21-xpro/tweetnacl"
git-cache: cloning from cache.
Clonage dans '/home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/pkg/samr21-xpro/tweetnacl'...
fait.
touch /home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/pkg/samr21-xpro/tweetnacl/.git-downloaded
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/pkg/tweetnacl
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/pkg/samr21-xpro/tweetnacl
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/boards/samr21-xpro
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/core
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/samd21
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/cortexm_common
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/cortexm_common/periph
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/sam0_common
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/sam0_common/periph
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/samd21/periph
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/drivers
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/drivers/periph_common
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/auto_init
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/checksum
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/firmware
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/isrpipe
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/newlib_syscalls_default
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/pm_layered
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/tsrb
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/uart_stdio
   text	   data	    bss	    dec	    hex	filename
   8952	    136	   2748	  11836	   2e3c	/home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/samr21-xpro/bootloader_test.elf
Firmware magic_number: 0x544f4952
Firmware Size: 9088
Firmware APPID: 0xbb8
Firmware Version: 0x1
Firmware start address: 0x00004100
Firmware HASH: 72 94 5f 90 7c b5 0f 19 0c fb f8 6b cb 7c b2 42 5e d0 09 c8 38 cc 3a e2 4a 57 cd 6b cb 73 52 64 
Firmware chksum: 0x41c80ddb
Firmware signature: e1 3a ee 67 d4 ee f4 50 85 d5 d6 db cd 82 d2 cb ec 9d 0c 34 8d 1b ab 4f c3 dd 71 a5 38 9c ad e3 93 6e 22 d1 e2 ae 84 7f da 2a 11 0b c5 12 41 fb 3d 31 2f 81 ff cd 9a 01 48 05 2b 5a 52 d7 68 0d 
Metadata size: 256
Firmware magic_number: 0x544f4952
Firmware Size: 9088
Firmware APPID: 0xbb8
Firmware Version: 0x1
Firmware start address: 0x00022100
Firmware HASH: 70 05 16 48 45 01 4b 86 ef a7 99 ed 81 f4 5d 8b 4a 0e 09 8c 8b 03 16 d0 09 7e e5 13 bd c7 03 9b 
Firmware chksum: 0x01caeddc
Firmware signature: 44 d1 4b 54 6b b5 4e 1d eb 45 33 8d 4c c5 aa fc 8c 8c ad 94 e6 42 57 c0 2a 61 ab 2f 62 91 28 41 51 c1 63 d2 73 87 3e 61 ac 75 68 01 36 cc 32 61 68 0b 45 89 23 77 ff 77 8c f0 96 12 f7 c6 be 0d 
Metadata size: 256
/home/pierr0t/repo_master/kYc0oRIOT/dist/tools/edbg/edbg  -t atmel_cm0p -b -e -v -p -f /home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/samr21-xpro/bootloader_test-slot1-0xBB8-0x1.combined.bin
Debugger: ATMEL EDBG CMSIS-DAP ATML2127031800003702 03.22.01B3 (S)
Target: SAM R21G18
Erasing...  done.
Programming..................................................................................................... done.
Verification..................................................................................................... done.
  • Step 06 : check the samr21-xpro output :
(18:25:42.599559) main(): This is RIOT! (Version: 2016.03-devel-5669-gfafd-pierr0t-Vostro-3360-ota_updates)
(18:25:42.603332) [bootlaoder] Checking for slots metadata...
(18:25:42.609182) firmware_validate_metadata_checksum: metadata magic number invalid
(18:25:42.611777) [bootloader] Slot 1 not valid
(18:25:42.614751) Firmware magic_number: 0x20000288
(18:25:42.617002) Firmware Size: 2030286128
(18:25:42.619343) Firmware APPID: 0x2000029c
(18:25:42.621846) Firmware Version: 0x2000028c
(18:25:42.624881) Firmware start address: 0xd9192908
(18:25:42.635492) Firmware HASH: 04 00 43 79 18 4a 9b 00 9d 58 08 34 00 2d 0d d0 2d 68 85 60 9d 58 2c 60 d4 50 01 23 44 79 13 4a 
(18:25:42.637954) Firmware chksum: 0xd8132b08
(18:25:42.658223) Firmware signature: a3 40 14 68 23 43 13 60 01 71 30 bd 84 60 f3 e7 08 2b f9 d9 42 79 0c 4c 92 00 13 59 00 2b 04 d0 1d 68 ab 42 0d d1 00 23 13 51 45 79 ab 00 e3 58 00 2b e9 d1 01 33 ab 40 04 4a 14 68 9c 43 23 00 
(18:25:42.664065) firmware_validate_metadata_checksum: metadata magic number invalid
(18:25:42.666682) [bootloader] Slot 2 not valid
(18:25:42.669630) Firmware magic_number: 0xffffffff
(18:25:42.671879) Firmware Size: 4294967295
(18:25:42.674221) Firmware APPID: 0xffffffff
(18:25:42.676755) Firmware Version: 0xffffffff
(18:25:42.679783) Firmware start address: 0xffffffff
(18:25:42.690362) Firmware HASH: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 
(18:25:42.692758) Firmware chksum: 0xffffffff
(18:25:42.713138) Firmware signature: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 
(18:25:42.716131) [bootloader] No valid slot found!

Slot1 & 2 are invalid.
What did I missed ?
Can you help me to getting started ?

Regards,
Pierre

@kYc0o
Copy link
Contributor Author

kYc0o commented Oct 23, 2017

Hi @LalunePierr0t ! Thanks for testing this PR.

I must say that recently I was working in a more robust solution for OTA, thus this PR got a bit outdated.

Please test this other branch (you can just fetch it from my repo). It will be PRed soon anyways.

Regarding this branch, apparently your images are being flashed in a wrong place, I suggest you delete the directory RIOT/bootloader/bin, if any, and launch the command make flash-multislot. If this doesn't work, maybe you can execute make multislot-clean and then try to flash again.

Hope this works and don't hesitate to publish here your results. Thanks again!

@rfuentess
Copy link
Contributor

Regarding this branch, apparently your images are being flashed in a wrong place, I suggest you delete the directory RIOT/bootloader/bin, if any, and launch the command make flash-multislot. If this doesn't work, maybe you can execute make multislot-clean and then try to flash again.

Additionally @LalunePierr0t , If you want to be extra paranoid, you can run the following between testings:

BOARD=samr21-xpro make clean distclean multislot-clean flash-multislot term

The only problem is that you need to save the tweetncl keys, otherwise a new couple of keys will be generated between each testing.

Please test this other branch (you can just fetch it from my repo). It will be PRed soon anyways.

I already tested that branch and is working nicely. However, I think is relevant to mention that some variables had their names changed:

APP_ID ?= 0xBB4  # Previously FW_APPID 
APP_VERSION ?= 0x1 # Previously FW_VERSION

Also, one of the new make rules has a new syntax:

BOARD=samr21-xpro make clean distclean clean-multislot flash-multislot term

@LalunePierr0t
Copy link

LalunePierr0t commented Oct 24, 2017

Hi @kYc0o ,

I can build and flash $(RIOTBASE)/test/bootloader_test from your branch.

  • build and flash :
~/repo_master/kYc0oRIOT/tests/bootloader_test$ BOARD=samr21-xpro make flash-multislot
Building application "tests_bootloader_test" for "samr21-xpro" with MCU "samd21".

rm -Rf /home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/pkg/samr21-xpro/tweetnacl
mkdir -p /home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/pkg/samr21-xpro/tweetnacl
/home/pierr0t/repo_master/kYc0oRIOT/dist/tools/git/git-cache clone "https://github.com/RIOT-OS/tweetnacl" "7ea05c7098a16c87fa66e9166ce301666f3f2623" "/home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/pkg/samr21-xpro/tweetnacl"
git-cache: cloning from cache.
Clonage dans '/home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/pkg/samr21-xpro/tweetnacl'...
fait.
touch /home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/pkg/samr21-xpro/tweetnacl/.git-downloaded
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/pkg/tweetnacl
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/pkg/samr21-xpro/tweetnacl
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/boards/samr21-xpro
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/core
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/samd21
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/cortexm_common
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/cortexm_common/periph
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/sam0_common
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/sam0_common/periph
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/cpu/samd21/periph
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/drivers
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/drivers/periph_common
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/auto_init
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/checksum
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/firmware
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/hashes
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/isrpipe
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/newlib_syscalls_default
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/pm_layered
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/tsrb
"make" -C /home/pierr0t/repo_master/kYc0oRIOT/sys/uart_stdio
   text	   data	    bss	    dec	    hex	filename
   8996	    136	   2748	  11880	   2e68	/home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/samr21-xpro/tests_bootloader_test.elf
Firmware magic_number: 0x544f4952
Firmware Size: 9132
Firmware APPID: 0xbb8
Firmware Version: 0x1
Firmware start address: 0x00004100
Firmware HASH: 6f d0 23 cd d7 26 54 b1 ba 87 fa 83 28 61 72 73 10 e2 58 16 47 6f b2 dd 07 32 1e d5 70 6b 22 e0 
Firmware chksum: 0x42780e07
Firmware signature: 19 1e d5 67 13 e9 36 66 63 26 0b 94 f2 fb 47 ad 4c eb 7a 6b fc d0 d3 19 94 37 e3 37 4c 3d d6 e2 28 84 60 f6 01 57 9d b5 f2 68 0e c5 e7 d3 e9 a2 28 5d 0a a7 df 2c f4 b8 45 11 f0 ac ab 1e 81 01 
Metadata size: 256
Firmware magic_number: 0x544f4952
Firmware Size: 9132
Firmware APPID: 0xbb8
Firmware Version: 0x1
Firmware start address: 0x00022100
Firmware HASH: a6 da c7 9b f0 10 22 26 59 72 a3 55 49 e6 1d 93 8b 20 2a 61 45 5e 8b 3d b7 f0 53 b5 d5 57 07 cb 
Firmware chksum: 0x027aee08
Firmware signature: 60 50 99 90 e3 39 99 b0 4c 90 1e 84 b3 58 94 e3 08 fb 53 f6 40 9b 38 d7 08 d3 9c c7 91 f8 b7 e0 b8 7f a6 e9 bd 1d 84 75 c2 61 21 cb 22 80 d0 65 f9 84 2a 46 1f 8e 08 28 58 12 1e 4c 5f 66 28 0a 
Metadata size: 256
/home/pierr0t/repo_master/kYc0oRIOT/dist/tools/edbg/edbg  -t atmel_cm0p -b -e -v -p -f /home/pierr0t/repo_master/kYc0oRIOT/tests/bootloader_test/bin/samr21-xpro/tests_bootloader_test.combined.bin
Debugger: ATMEL EDBG CMSIS-DAP ATML2127031800003702 03.22.01B3 (S)
Target: SAM R21G18
Erasing...  done.
Programming........................................................................................................ done.
Verification........................................................................................................ done.
  • Result seems to be correct :
(09:37:56.500824) main(): This is RIOT! (Version: 2016.03-devel-5781-g7334-pierr0t-Vostro-3360-ota_firmware_updates)
(09:37:56.502343) Hello Bootloader!
(09:37:56.506535) You are running RIOT on a(n) samr21-xpro board.
(09:37:56.509753) This board features a(n) samd21 MCU.
(09:37:56.511888) Active firmware slot: 1
(09:37:56.515914) slot 1: metadata: 0x00004000 image: 0x00004100
(09:37:56.520046) slot 2: metadata: 0x00022000 image: 0x00022100
  • But I still do not really understand. I I modify the bootloader itself $(RIOTBASE)/bootloader by adding a trace and a metadata print:
void kernel_init(void)
{
    uint32_t version = 0;
    uint32_t slot = 0;
    puts("BOOTLOADER");
    for (unsigned i = 1; i < firmware_num_slots; i++) {
        firmware_metadata_t *slot_metadata = firmware_get_metadata(i);
        firmware_metadata_print(slot_metadata);
        if (firmware_validate_metadata_checksum(slot_metadata)) {
            /* skip slot if metadata broken */
  • If I look at the result on serial, I cant see my modification when i re-build and re-flash the $(RIOTBASE)/test/bootloader_test app
  • It should means that when y use make flash-multislot it does not embed the bootloader.
  • I will look more deeply at what you ve done, sorry if I do get really the purpose of your work.
  • Here you can see what I expect from a bootloader:
Req :
  1. launch a firmware
  2. flash a new firmware in internal cpu flash
  3. check on boot that the current firmware has signal its availibility
  4. perform an hardware reset on current firmware availibility failure
  5. perform an hardware reset on user action (such as pressing button during boot)
Definitions :
  1. Firmware availibility : the current firmware runs fine and write this information to the flash to inform the
    bootloader on next reboot.
  2. Hardware reset : flash a stock firmware to the internal flash.
  3. Stock firmware : is a trusted firmware that always provides your basics needs ( such as OTA).
  • Do you have the same goals with your boot loader ?
  • In other words, do you mean your work could be foundations to implement my requirements ? If I assume that slot 1 is the current firmware and slot 2 my "stock firmware"

Regards,

@kYc0o
Copy link
Contributor Author

kYc0o commented Oct 24, 2017

If I look at the result on serial, I cant see my modification when i re-build and re-flash the $(RIOTBASE)/test/bootloader_test app

Currently the build system (or rather the way I manage the dependencies) doesn't detect when there's a change in the bootloader code, thus is not rebuilt. You need to clean the bootloader to take into account the modifications. The bootloader is systematically flashed (actually appended to the application binary).

Currently the development is in an early stage, we provide a bootloader which can explore the internal ROM for valid images for a maximum of two slots (the current one and the update), check for a valid and consistent header (metadata) and then boot the newest version.

On the other hand, the OTA update module fetches information about the upstream images, downloads the newest if present and then flashes it into the available slot (can be 1 or 2 depending on where are you running the application), verifies the cryptographic signature and if valid writes the metadata to the beginning of the slot, then reboots. All of this is done from the current running image, thus flashing and verification capabilities are not embedded in the bootloader.

Next steps:

  • Be able to mark an update as "safe" (it boots and it's somehow stable) or bad (it rebooted or hanged).
  • Fallback to the previous image which used to work.

Thanks again for looking at this!

@kYc0o kYc0o mentioned this pull request Oct 29, 2017
8 tasks
@aabadie
Copy link
Contributor

aabadie commented Jan 2, 2018

@kYc0o, what's the status here ? Do you think this one or #7396 or #7457 could make it for the next release ?

There is also #7167 but now it seems outdated. What do you plan to do with it ?

@kYc0o
Copy link
Contributor Author

kYc0o commented May 30, 2018

I think this PR got unrelated to the ongoing OTA work. Thus, will close.

@kYc0o kYc0o closed this May 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR State: waiting for other PR State: The PR requires another PR to be merged first State: WIP State: The PR is still work-in-progress and its code is not in its final presentable form yet 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.

8 participants