Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions Makefile.dep
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,22 @@ USEPKG += nanocoap
USEMODULE += gnrc_sock_udp
endif

ifneq (,$(filter firmware,$(USEMODULE)))
USEPKG += tweetnacl
USEMODULE += checksum
FEATURES_REQUIRED += periph_flashpage
endif

ifneq (,$(filter ota_update_%,$(USEMODULE)))
USEMODULE += gcoap
USEMODULE += ota_update
USEMODULE += firmware
USEMODULE += sema
ifneq (,$(filter ota_update_tftp,$(USEMODULE)))
USEMODULE += gnrc_tftp
endif
endif

# include package dependencies
-include $(USEPKG:%=$(RIOTPKG)/%/Makefile.dep)

Expand Down
12 changes: 12 additions & 0 deletions boards/iotlab-common/Makefile.include
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ export CPU_MODEL = stm32f103re
PORT_LINUX ?= /dev/ttyUSB1
PORT_DARWIN ?= $(firstword $(sort $(wildcard /dev/tty.usbserial*B)))

# export ROM partitions
export ROM_SIZE = 0x80000
export SLOT0_ADDR = 0x8000000
export SLOT0_SIZE = 0x4000
CFLAGS +=-DSLOT0_SIZE=$(SLOT0_SIZE)
export SLOT_SIZE = 0x3E000
CFLAGS +=-DSLOT_SIZE=$(SLOT_SIZE)
export SLOT1_SIZE = 0x3E000
CFLAGS +=-DSLOT1_SIZE=$(SLOT1_SIZE)
export SLOT2_SIZE = 0x3E000
CFLAGS +=-DSLOT2_SIZE=$(SLOT2_SIZE)

# setup serial terminal
export BAUD = 500000
include $(RIOTMAKE)/tools/serial.inc.mk
Expand Down
12 changes: 12 additions & 0 deletions boards/samr21-xpro/Makefile.include
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,16 @@ export CPU_MODEL = samr21g18a
# set edbg device type
EDBG_DEVICE_TYPE = atmel_cm0p

# export ROM partitions
export ROM_SIZE = 0x40000
export SLOT0_ADDR = 0x0
export SLOT0_SIZE = 0x4000
CFLAGS +=-DSLOT0_SIZE=$(SLOT0_SIZE)
export SLOT_SIZE = 0x1E000
CFLAGS +=-DSLOT_SIZE=$(SLOT_SIZE)
export SLOT1_SIZE = 0x1E000
CFLAGS +=-DSLOT1_SIZE=$(SLOT1_SIZE)
export SLOT2_SIZE = 0x1E000
CFLAGS +=-DSLOT2_SIZE=$(SLOT2_SIZE)

include $(RIOTMAKE)/boards/sam0.inc.mk
13 changes: 13 additions & 0 deletions bootloader/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
APPLICATION = bootloader
BOARD ?= samr21-xpro

USEMODULE += bootloader
USEMODULE += firmware

#CFLAGS += -DNDEBUG -DLOG_LEVEL=LOG_NONE
#DISABLE_MODULE += auto_init
CFLAGS += -DTHREAD_STACKSIZE_MAIN=\(5*THREAD_STACKSIZE_DEFAULT\)
# This has to be the absolute path to the RIOT base directory:
RIOTBASE ?= $(CURDIR)/..

include $(RIOTBASE)/Makefile.include
110 changes: 110 additions & 0 deletions bootloader/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright (C) 2017 Kaspar Schleiser
* Inria
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @ingroup bootloader
* @{
*
* @file
* @brief RIOT Bootloader
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author Francisco Acosta <francisco.acosta@inria.fr>
*
* @}
*/
#include <string.h>
#include <stdio.h>

#include "firmware.h"


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
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

typo bootloader

firmware_jump_to_slot(slot);
}
else {
puts("[bootloader] no valid signature!");
return -1;
}

/* Should not happen */
return -1;
}

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...");

Copy link
Copy Markdown
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
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

typo bootloader

}
else {
puts("[bootloader] Slot 1 not valid");
}

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
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

typo

}
else {
puts("[bootloader] Slot 2 not valid");
}

if ((appid_slot1 == 0) && (appid_slot2 == 0)) {
puts("[bootloader] No valid slot found!");
return -1;
}
else {
if (appid_slot1 != appid_slot2) {
puts("[bootloader] Warning! application IDs are different!");
puts("[bootloader] falling back to slot 1");
if (validate_and_boot(1) == -1) {
puts("[bootloader] Booting failed!");
}
else {
puts("[bootlaoder] Slot 1 inconsistent, no image to boot...");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

typo

return -1;
}
}
else {
puts("[bootloader] Looking for the newest image on ROM, listing...");
boot_slot = firmware_find_newest_int_image();

if (boot_slot > 0) {
printf("[bootloader] newest image found on slot %d, checking...\n",
boot_slot);
if (validate_and_boot(boot_slot) == -1) {
puts("[bootloader] Booting failed!");
}
}
else {
(void) puts("No bootable slot found!\n");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(void) can be removed here

return -1;
}
}
}

/* Shouldn't happen */
return 0;
}

int main(void)
{
return boot_img();

}
86 changes: 86 additions & 0 deletions cpu/cortexm_common/include/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,92 @@ static inline void cortexm_isr_end(void)
}
}

/**
* @brief Jumps to another image in flash
*
* This function is supposed to be called by a bootloader application.
*
* @param[in] image_address address in flash of other image
*/
static inline void cpu_jump_to_image(uint32_t image_address)
{
/* Disable IRQ */
__disable_irq();

/* set PSP */
__set_PSP(*(uint32_t*)image_address);

/* skip stack pointer */
image_address += 4;

/* load the images reset_vector address */
uint32_t destination_address = *(uint32_t*)image_address;

/* Make sure the Thumb State bit is set. */
destination_address |= 0x1;

/* Branch execution */
__asm("BX %0" :: "r" (destination_address));
}

/* The following register is only present for Cortex-M0+, -M3, -M4 and -M7 CPUs */
#if defined(CPU_ARCH_CORTEX_M0PLUS) || defined(CPU_ARCH_CORTEX_M3) || \
defined(CPU_ARCH_CORTEX_M4) || defined(CPU_ARCH_CORTEX_M4F) || \
defined(CPU_ARCH_CORTEX_M7)
static inline unsigned cpu_get_image_baseaddr(void)
{
return (unsigned)SCB->VTOR;
}
#endif

#if defined(SLOT0_SIZE) && defined(SLOT1_SIZE)
/**
* @brief Get FW internal address for a given slot
*
* @param[in] slot FW slot
*
* @return FW slot address
*/
static inline uint32_t cpu_get_slot_address(uint8_t slot)
{
switch (slot) {
case 1:
return SLOT0_SIZE;
break;

case 2:
return SLOT0_SIZE + SLOT1_SIZE;
break;
}

return 0;
}
#endif

#if defined(SLOT0_SIZE) && defined(SLOT2_SIZE)
/**
* @brief Get internal page for a given slot
*
* @param[in] slot FW slot
*
* @return FW slot page
*/
static inline uint32_t cpu_get_slot_page(uint8_t slot)
{
switch (slot) {
case 1:
return SLOT0_SIZE / FLASHPAGE_SIZE;
break;

case 2:
return (SLOT0_SIZE + SLOT1_SIZE) / FLASHPAGE_SIZE;
break;
}

return 0;
}
#endif

#ifdef __cplusplus
}
#endif
Expand Down
8 changes: 6 additions & 2 deletions cpu/sam0_common/ldscripts/samr21g18a.ld
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@
* @}
*/

rom_length = 256K;

INCLUDE multislot.ld

MEMORY
{
rom (rx) : ORIGIN = 0x00000000, LENGTH = 256K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 32K
rom (rx) : ORIGIN = 0x00000000 + boot_offset, LENGTH = rom_length
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 32K
}

INCLUDE cortexm_base.ld
10 changes: 7 additions & 3 deletions cpu/stm32f1/ldscripts/stm32f103re.ld
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@
* @}
*/

rom_length = 512K;

INCLUDE multislot.ld

MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
cpuid (r) : ORIGIN = 0x1ffff7e8, LENGTH = 12
rom (rx) : ORIGIN = 0x08000000 + boot_offset, LENGTH = rom_length
ram (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
cpuid (r) : ORIGIN = 0x1ffff7e8, LENGTH = 12
}

_cpuid_address = ORIGIN(cpuid);
Expand Down
50 changes: 50 additions & 0 deletions dist/tools/firmware_metadata/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
RIOTBASE := ../../..
RIOT_INCLUDE := $(RIOTBASE)/sys/include
SHA256_DIR := $(RIOTBASE)/sys/hashes
SHA256_INCLUDE := $(RIOT_INCLUDE)/hashes
TWEETNACL_DIR := tweetnacl
TWEETNACL_SRC := $(TWEETNACL_DIR)/tweetnacl.c randombytes.c
TWEETNACL_HDR := $(TWEETNACL_DIR)/tweetnacl.h
COMMON_SRC := common.c
COMMON_HDR := common.h

RIOT_FIRMWARE_SRC := \
$(SHA256_DIR)/sha256.c \
$(RIOTBASE)/sys/checksum/fletcher32.c \
$(RIOTBASE)/sys/firmware/firmware.c

RIOT_FIRMWARE_HDR := $(RIOT_INCLUDE)/firmware.h \
$(RIOT_INCLUDE)/hashes/sha256.h \
$(RIOT_INCLUDE)/checksum/fletcher32.h

FIRMWARE_SRC := $(COMMON_SRC) $(TWEETNACL_SRC) $(RIOT_FIRMWARE_SRC) \
firmware.c verify.c genkeys.c genmeta.c

FIRMWARE_HDR := $(COMMON_HDR) $(RIOT_FIRMWARE_HDR)

GITCACHE = ../git/git-cache
TWEETNACL_URL = https://github.com/RIOT-OS/tweetnacl.git
TWEETNACL_VERSION = 7ea05c7098a16c87fa66e9166ce301666f3f2623

CFLAGS += -g -I. -O3 -Wall -Wextra -pedantic -std=c99

all: bin/firmware

bin/:
mkdir -p bin

git-fetch-tweetnacl:
rm -Rf $(TWEETNACL_DIR)
mkdir -p $(TWEETNACL_DIR)
$(GITCACHE) clone "$(TWEETNACL_URL)" "$(TWEETNACL_VERSION)" "$(TWEETNACL_DIR)"
touch $@

bin/firmware: git-fetch-tweetnacl $(FIRMWARE_HDR) $(FIRMWARE_SRC) Makefile | bin/
$(CC) $(CFLAGS) -I$(RIOT_INCLUDE) -I$(TWEETNACL_DIR) $(FIRMWARE_SRC) -o $@

clean:
rm -rf bin/firmware

distclean:
rm -rf $(TWEETNACL_DIR)
rm -f git-fetch-tweetnacl
Loading