Skip to content
Open
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
2 changes: 2 additions & 0 deletions bootloaders/riotboot/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ APPLICATION = riotboot

# Include riotboot flash partition functionality
USEMODULE += riotboot_slot
USEMODULE += riotboot_flashwrite
USEMODULE += riotboot_wdt

# We don't want to re-configure any hardware
CFLAGS += -DDISABLE_BOARD_INIT=1
Expand Down
52 changes: 45 additions & 7 deletions bootloaders/riotboot/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,69 @@
* @}
*/

#include <string.h>

#include "cpu.h"
#include "panic.h"
#include "periph/flashpage.h"
#include "riotboot/hdr.h"
#include "riotboot/slot.h"
#include "riotboot/flashwrite.h"
#include "riotboot/wdt.h"

void kernel_init(void)
{
uint32_t version = 0;
int slot = -1;

uint32_t version;
int slot;
int state;
INIT:
version = 0;
slot = -1;
for (unsigned i = 0; i < riotboot_slot_numof; i++) {
const riotboot_hdr_t *riot_hdr = riotboot_slot_get_hdr(i);
if (riotboot_slot_validate(i)) {
/* skip slot if metadata broken */
continue;
}
if (riot_hdr->start_addr != riotboot_slot_get_image_startaddr(i)) {
if (riotboot_hdr_get_start_addr(riot_hdr) !=
riotboot_slot_get_image_startaddr(i)) {
continue;
}
state = riotboot_hdr_get_img_state(riot_hdr);
if (state == RIOTBOOT_HDR_IMG_STATE_DEACTIVATED ||
state == RIOTBOOT_HDR_IMG_STATE_DISMISSED) {
/* skip image which previously failed to boot or is not yet activated */
continue;
}
if (slot == -1 || riot_hdr->version > version) {
version = riot_hdr->version;
if (slot == -1 || riotboot_hdr_get_version(riot_hdr) > version) {
version = riotboot_hdr_get_version(riot_hdr);
slot = i;
}
}

unsigned boot = 0;
if (slot != -1) {
riotboot_hdr_t riot_hdr = *riotboot_slot_get_hdr(slot);
if (riotboot_hdr_is_v2(&riot_hdr)) {
boot = riotboot_hdr_get_boot_count(&riot_hdr);
if (state == RIOTBOOT_HDR_IMG_STATE_ACTIVATED) {
/* not yet confirmed */
if (boot == CONFIG_RIOTBOOT_MAX_ATTEMPTS) {
/* failed to boot for CONFIG_RIOTBOOT_MAX_ATTEMPTS attempts */
riotboot_hdr_set_img_state(&riot_hdr, RIOTBOOT_HDR_IMG_STATE_DISMISSED);
goto INIT; /* choose different slot */
}
else {
riotboot_hdr_set_boot_count(&riot_hdr, boot + 1);
}
}
if (memcmp(&riot_hdr, riotboot_slot_get_hdr(slot), sizeof(riot_hdr.v2))) {
flashpage_write(flashpage_addr(flashpage_page(riotboot_slot_get_hdr(slot))),
&riot_hdr.v2, sizeof(riot_hdr.v2));
}
}
#if IS_USED(MODULE_RIOTBOOT_WDT)
riotboot_wdt_start(CONFIG_RIOTBOOT_WDT_TIMEOUT_MSEC << boot);
#endif
riotboot_slot_jump(slot);
}

Expand Down
13 changes: 12 additions & 1 deletion core/lib/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@
#include "periph/pm.h"
#include "thread.h"
#include "stdio_base.h"

#if IS_USED(MODULE_RIOTBOOT)
# include "riotboot/slot.h"
# include "riotboot/wdt.h"
#endif
#if IS_USED(MODULE_VFS)
#include "vfs.h"
#endif
Expand Down Expand Up @@ -60,6 +63,14 @@ static void *main_trampoline(void *arg)
LOG_INFO(CONFIG_BOOT_MSG_STRING "\n");
}

#if IS_USED(MODULE_RIOTBOOT)
if (IS_USED(MODULE_RIOTBOOT_HDR_AUTO_CONFIRM)) {
riotboot_slot_confirm();
if (IS_USED(MODULE_RIOTBOOT_WDT)) {
riotboot_wdt_stop();
}
}
#endif
int res = main();

if (IS_USED(MODULE_TEST_UTILS_MAIN_EXIT_CB)) {
Expand Down
96 changes: 72 additions & 24 deletions dist/tools/riotboot_gen_hdr/genhdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,36 @@
*/
#define HDR_ALIGN (256)

static void populate_hdr(riotboot_hdr_t *hdr, uint32_t ver, uint32_t addr)
static size_t populate_hdr_v1(riotboot_hdr_t *hdr, uint32_t ver, uint32_t addr)
{
/* ensure the buffer and header have 0's */
memset(hdr, '\0', sizeof(riotboot_hdr_t));

/* Generate image header */
hdr->magic_number = RIOTBOOT_MAGIC;
hdr->version = ver;
hdr->start_addr = addr;
memset(hdr, '\0', sizeof(*hdr));
/* Generate image header v1 */
hdr->v1.magic_number = RIOTBOOT_MAGIC_V1;
hdr->v1.version = ver;
hdr->v1.start_addr = addr;
/* calculate header checksum */
hdr->v1.chksum = riotboot_hdr_checksum(hdr);
return sizeof(hdr->v1);
}

static size_t populate_hdr_v2(riotboot_hdr_t *hdr, uint32_t ver, uint32_t addr)
{
/* ensure the buffer and header have 0's */
memset(hdr, '\0', sizeof(*hdr));
/* Generate image header v2 */
hdr->v2.magic_number = RIOTBOOT_MAGIC_V2;
hdr->v2.version = ver;
hdr->v2.start_addr = addr;
hdr->v2.flags = 0xffffffff;
/* calculate header checksum */
hdr->chksum = riotboot_hdr_checksum(hdr);
hdr->v2.chksum = riotboot_hdr_checksum(hdr);
return sizeof(hdr->v2);
}

int genhdr(int argc, char *argv[])
{
const char generate_usage[] = "<IMG_BIN> <APP_VER> <START_ADDR> <HDR_LEN> <outfile|->";
const char generate_usage[] = "<IMG_BIN> <APP_VER> <START_ADDR> <HDR_LEN> <outfile|-> [-v [v1,v2]]";

/* riotboot_hdr buffer */
uint8_t *hdr_buf;
Expand Down Expand Up @@ -93,14 +106,41 @@ int genhdr(int argc, char *argv[])
hdr_len = hdr_len_arg;
}

/* generate only v1 by default */
bool gen_v1 = true;
bool gen_v2 = false;
if (argc >= 8) {
gen_v1 = false;
if (!strcmp(argv[6], "-v")) {
for (int a = 7; a < argc; a++) {
if (!strcmp(argv[a], "v1")) {
gen_v1 = true;
}
else if (!strcmp(argv[a], "v2")) {
gen_v2 = true;
}
else {
fprintf(stderr, "Error: unknown version '%s'!\n", argv[a]);
return -1;
}
}
}
}
/* prepare a 0 initialised buffer for riotboot_hdr_t */
hdr_buf = calloc(1, hdr_len);
if (hdr_buf == NULL) {
fprintf(stderr, "Error: not enough memory!\n");
return -1;
}

populate_hdr((riotboot_hdr_t*)hdr_buf, app_ver, start_addr);
size_t gen_hdr_size = 0;
uint8_t *p_hdr = hdr_buf;
if (gen_v1) {
gen_hdr_size += populate_hdr_v1((riotboot_hdr_t *)(p_hdr + gen_hdr_size), app_ver, start_addr);
}
if (gen_v2) {
gen_hdr_size += populate_hdr_v2((riotboot_hdr_t *)(p_hdr + gen_hdr_size), app_ver, start_addr);
}

/* Write the header */
if (!to_file(argv[5], hdr_buf, hdr_len)) {
Expand All @@ -124,35 +164,43 @@ int updatehdr(int argc, char *argv[])

riotboot_hdr_t hdr = { 0 };
int res = from_file(file, &hdr, sizeof(hdr));
if (res < (int)sizeof(hdr)) {
if (res < (int)sizeof(hdr.v1)) {
fprintf(stderr, "Can't read header from %s\n", file);
return -EIO;
}

if (hdr.magic_number != RIOTBOOT_MAGIC) {
fprintf(stderr, "Invalid magic: %x\n", hdr.magic_number);
uint32_t magic = riotboot_hdr_get_magic_number(&hdr);
if (magic == RIOTBOOT_MAGIC_V2) {
hdr.v2.magic_number = RIOTBOOT_MAGIC_V2;
hdr.v2.version = atoi(argv[2]);
hdr.v2.chksum = riotboot_hdr_checksum(&hdr);
to_file(file, &hdr, sizeof(hdr.v2));
}
else if (magic == RIOTBOOT_MAGIC_V1) {
hdr.v1.magic_number = RIOTBOOT_MAGIC_V1;
hdr.v1.version = atoi(argv[2]);
hdr.v1.chksum = riotboot_hdr_checksum(&hdr);
to_file(file, &hdr, sizeof(hdr.v1));
}
else {
fprintf(stderr, "Invalid magic: %x\n", magic);
return -EIO;
}

hdr.version = atoi(argv[2]);
hdr.chksum = riotboot_hdr_checksum(&hdr);
to_file(file, &hdr, sizeof(hdr));

return 0;
}

static void print_hdr(const riotboot_hdr_t *hdr)
{
printf("version: %u\n", hdr->version);
printf("address: 0x%x\n", hdr->start_addr);
printf("version: %u\n", riotboot_hdr_get_version(hdr));
printf("address: 0x%x\n", riotboot_hdr_get_start_addr(hdr));
printf("checksum: %svalid\n", riotboot_hdr_validate(hdr) ? "in" : "");
}

static void print_hdr_json(const riotboot_hdr_t *hdr)
{
printf("{\n");
printf("\t\"version\": %u,\n", hdr->version);
printf("\t\"address\": %u,\n", hdr->start_addr);
printf("\t\"version\": %u,\n", riotboot_hdr_get_version(hdr));
printf("\t\"address\": %u,\n", riotboot_hdr_get_start_addr(hdr));
printf("\t\"valid\": %s\n", riotboot_hdr_validate(hdr) ? "false" : "true");
printf("}\n");
}
Expand All @@ -166,8 +214,8 @@ int readhdr(const char *file, bool json)
return -EIO;
}

if (hdr.magic_number != RIOTBOOT_MAGIC) {
fprintf(stderr, "Invalid magic: %x\n", hdr.magic_number);
if (riotboot_hdr_get_magic_number(&hdr) != RIOTBOOT_MAGIC) {
fprintf(stderr, "Invalid magic: %x\n", riotboot_hdr_get_magic_number(&hdr));
return -EIO;
}

Expand Down
45 changes: 37 additions & 8 deletions examples/advanced/suit_update/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include "suit/transport/coap.h"
#ifdef MODULE_SUIT_STORAGE_FLASHWRITE
#include "periph/flashpage.h"
#include "riotboot/slot.h"
#endif

Expand Down Expand Up @@ -69,19 +70,47 @@ static int cmd_print_riotboot_hdr(int argc, char **argv)
(void)argc;
(void)argv;

int current_slot = riotboot_slot_current();
if (current_slot != -1) {
if (riotboot_slot_current() == -1) {
printf("[FAILED] You're not running riotboot\n");
return -1;
}
if (argc == 1) {
printf("Usage: %s [<slot> [activate|deactivate|confirm|dismiss]]\n", argv[0]);
return 0;
}
int slot = atoi(argv[1]);
if (argc == 2) {
/* Sometimes, udhcp output messes up the following printfs. That
* confuses the test script. As a workaround, just disable interrupts
* for a while.
*/
* confuses the test script. As a workaround, just disable interrupts
* for a while.
*/
unsigned state = irq_disable();
riotboot_slot_print_hdr(current_slot);
riotboot_slot_print_hdr(slot);
irq_restore(state);
return 0;
}
else {
printf("[FAILED] You're not running riotboot\n");
riotboot_hdr_t hdr = *riotboot_slot_get_hdr(slot);
if (riotboot_hdr_is_v2(&hdr)) {
if (!strcmp(argv[2], "activate")) {
riotboot_hdr_set_img_state(&hdr, RIOTBOOT_HDR_IMG_STATE_ACTIVATED);
}
else if (!strcmp(argv[2], "deactivate")) {
riotboot_hdr_set_img_state(&hdr, RIOTBOOT_HDR_IMG_STATE_DEACTIVATED);
}
else if (!strcmp(argv[2], "confirm")) {
riotboot_hdr_set_img_state(&hdr, RIOTBOOT_HDR_IMG_STATE_CONFIRMED);
}
else if (!strcmp(argv[2], "dismiss")) {
riotboot_hdr_set_img_state(&hdr, RIOTBOOT_HDR_IMG_STATE_DISMISSED);
}
else {
printf("Unknown command %s\n", argv[2]);
return -1;
}
flashpage_write(flashpage_addr(flashpage_page(riotboot_slot_get_hdr(slot))),
&hdr.v2, sizeof(hdr.v2));
}

return 0;
}

Expand Down
10 changes: 9 additions & 1 deletion makefiles/boot/riotboot.mk
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ $(BINDIR_RIOTBOOT)/%.elf: $(BASELIBS) $(ARCHIVES) $(BINDIR_RIOTBOOT)
$(Q)$(_LINK) -o $@
endif

RIOTBOOT_HDR_VERSION ?= -v
ifneq (,$(filter riotboot_hdr_v1, $(USEMODULE)))
RIOTBOOT_HDR_VERSION := $(RIOTBOOT_HDR_VERSION) v1
endif
ifneq (,$(filter riotboot_hdr_v2, $(USEMODULE)))
RIOTBOOT_HDR_VERSION := $(RIOTBOOT_HDR_VERSION) v2
endif

# Slot 0 and 1 firmware offset, after header
SLOT0_IMAGE_OFFSET := $$(($(SLOT0_OFFSET) + $(RIOTBOOT_HDR_LEN)))
SLOT1_IMAGE_OFFSET := $$(($(SLOT1_OFFSET) + $(RIOTBOOT_HDR_LEN)))
Expand Down Expand Up @@ -70,7 +78,7 @@ $(HEADER_TOOL): FORCE
# It must be always regenerated in case of any changes, so FORCE
.PRECIOUS: %.bin
%.hdr: $(HEADER_TOOL) %.bin FORCE
$(Q)$(HEADER_TOOL) generate $< $(APP_VER) $$(($(ROM_START_ADDR)+$(OFFSET))) $(RIOTBOOT_HDR_LEN) - > $@
$(HEADER_TOOL) generate $< $(APP_VER) $$(($(ROM_START_ADDR)+$(OFFSET))) $(RIOTBOOT_HDR_LEN) - $(RIOTBOOT_HDR_VERSION) > $@

$(BINDIR_RIOTBOOT)/slot0.hdr: OFFSET=$(SLOT0_IMAGE_OFFSET)
$(BINDIR_RIOTBOOT)/slot1.hdr: OFFSET=$(SLOT1_IMAGE_OFFSET)
Expand Down
9 changes: 5 additions & 4 deletions sys/include/riotboot/flashwrite.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ int riotboot_flashwrite_init_raw(riotboot_flashwrite_t *state, int target_slot,
* @brief Initialize firmware update (riotboot version)
*
* This function initializes a firmware update, skipping riotboot's magic
* number ("RIOT") by calling @ref riotboot_flashwrite_init_raw() with an
* number by calling @ref riotboot_flashwrite_init_raw() with an
* offset of RIOTBOOT_FLASHWRITE_SKIPLEN (4). This ensures that riotboot will
* ignore the slot until the magic number has been restored, e.g., through @ref
* riotboot_flashwrite_finish().
Expand All @@ -163,7 +163,7 @@ int riotboot_flashwrite_init_raw(riotboot_flashwrite_t *state, int target_slot,
static inline int riotboot_flashwrite_init(riotboot_flashwrite_t *state,
int target_slot)
{
/* initialize state, but skip "RIOT" */
/* initialize state, but skip magic number */
return riotboot_flashwrite_init_raw(state, target_slot,
RIOTBOOT_FLASHWRITE_SKIPLEN);
}
Expand Down Expand Up @@ -211,15 +211,16 @@ int riotboot_flashwrite_finish_raw(riotboot_flashwrite_t *state,
* @brief Finish a firmware update (riotboot version)
*
* This function finishes a firmware update by re-writing the first header so
* it includes riotboot's magic number ("RIOT").
* it includes riotboot's magic number.
*
* @param[in] state ptr to previously used state structure
*
* @returns 0 on success, <0 otherwise
*/
static inline int riotboot_flashwrite_finish(riotboot_flashwrite_t *state)
{
return riotboot_flashwrite_finish_raw(state, (const uint8_t *)"RIOT",
uint32_t magic = RIOTBOOT_MAGIC;
return riotboot_flashwrite_finish_raw(state, (const uint8_t *)&magic,
RIOTBOOT_FLASHWRITE_SKIPLEN);
}

Expand Down
Loading
Loading