Skip to content

Commit bf983c9

Browse files
committed
sys/riotboot: riotboot head v2
1 parent ef76a04 commit bf983c9

File tree

20 files changed

+724
-96
lines changed

20 files changed

+724
-96
lines changed

bootloaders/riotboot/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ APPLICATION = riotboot
33

44
# Include riotboot flash partition functionality
55
USEMODULE += riotboot_slot
6+
USEMODULE += riotboot_flashwrite
67

78
# We don't want to re-configure any hardware
89
CFLAGS += -DDISABLE_BOARD_INIT=1

bootloaders/riotboot/main.c

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,77 @@
2020
* @}
2121
*/
2222

23+
#include <string.h>
24+
2325
#include "cpu.h"
2426
#include "panic.h"
27+
#include "periph/flashpage.h"
28+
#include "riotboot/hdr.h"
2529
#include "riotboot/slot.h"
30+
#include "riotboot/flashwrite.h"
31+
#include "riotboot/wdt.h"
2632

2733
void kernel_init(void)
2834
{
29-
uint32_t version = 0;
30-
int slot = -1;
31-
32-
for (unsigned i = 0; i < riotboot_slot_numof; i++) {
33-
const riotboot_hdr_t *riot_hdr = riotboot_slot_get_hdr(i);
34-
if (riotboot_slot_validate(i)) {
35-
/* skip slot if metadata broken */
36-
continue;
37-
}
38-
if (riot_hdr->start_addr != riotboot_slot_get_image_startaddr(i)) {
39-
continue;
35+
int slot;
36+
unsigned boot = 0;
37+
38+
while (1) {
39+
int state = 0;
40+
uint32_t version = 0;
41+
slot = -1;
42+
for (unsigned i = 0; i < riotboot_slot_numof; i++) {
43+
const riotboot_hdr_t *riot_hdr = riotboot_slot_get_hdr(i);
44+
if (riotboot_slot_validate(i)) {
45+
/* skip slot if metadata broken */
46+
continue;
47+
}
48+
if (riotboot_hdr_get_start_addr(riot_hdr) !=
49+
riotboot_slot_get_image_startaddr(i)) {
50+
continue;
51+
}
52+
state = riotboot_hdr_get_img_state(riot_hdr);
53+
if (state == RIOTBOOT_HDR_IMG_STATE_DEACTIVATED ||
54+
state == RIOTBOOT_HDR_IMG_STATE_DISMISSED) {
55+
/* skip image which previously failed to boot or is not yet activated */
56+
continue;
57+
}
58+
if (slot == -1 || riotboot_hdr_get_version(riot_hdr) > version) {
59+
version = riotboot_hdr_get_version(riot_hdr);
60+
slot = i;
61+
}
4062
}
41-
if (slot == -1 || riot_hdr->version > version) {
42-
version = riot_hdr->version;
43-
slot = i;
63+
64+
if (slot != -1) {
65+
riotboot_hdr_t riot_hdr = *riotboot_slot_get_hdr(slot);
66+
if (riotboot_hdr_is_v2(&riot_hdr)) {
67+
boot = riotboot_hdr_get_boot_count(&riot_hdr);
68+
if (state == RIOTBOOT_HDR_IMG_STATE_ACTIVATED) {
69+
/* not yet confirmed */
70+
if (boot == CONFIG_RIOTBOOT_MAX_ATTEMPTS) {
71+
/* failed to boot for CONFIG_RIOTBOOT_MAX_ATTEMPTS attempts */
72+
riotboot_hdr_set_img_state(&riot_hdr, RIOTBOOT_HDR_IMG_STATE_DISMISSED);
73+
}
74+
else {
75+
riotboot_hdr_set_boot_count(&riot_hdr, boot + 1);
76+
}
77+
}
78+
if (memcmp(&riot_hdr, riotboot_slot_get_hdr(slot), sizeof(riot_hdr.v2))) {
79+
flashpage_write(flashpage_addr(flashpage_page(riotboot_slot_get_hdr(slot))),
80+
&riot_hdr.v2, sizeof(riot_hdr.v2));
81+
}
82+
if (riotboot_hdr_get_img_state(&riot_hdr) == RIOTBOOT_HDR_IMG_STATE_DISMISSED) {
83+
continue; /* try next slot */
84+
}
85+
}
86+
break; /* found a slot to boot */
4487
}
4588
}
4689

47-
if (slot != -1) {
48-
riotboot_slot_jump(slot);
49-
}
90+
#if IS_USED(MODULE_RIOTBOOT_WDT)
91+
riotboot_wdt_start(CONFIG_RIOTBOOT_WDT_TIMEOUT_MSEC << boot);
92+
#endif
93+
riotboot_slot_jump(slot);
5094

5195
/* serious trouble! nothing to boot */
5296
while (1) {}

core/lib/init.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@
3030
#include "periph/pm.h"
3131
#include "thread.h"
3232
#include "stdio_base.h"
33-
33+
#if IS_USED(MODULE_RIOTBOOT)
34+
# include "riotboot/slot.h"
35+
# include "riotboot/wdt.h"
36+
#endif
3437
#if IS_USED(MODULE_VFS)
3538
#include "vfs.h"
3639
#endif
@@ -60,6 +63,14 @@ static void *main_trampoline(void *arg)
6063
LOG_INFO(CONFIG_BOOT_MSG_STRING "\n");
6164
}
6265

66+
#if IS_USED(MODULE_RIOTBOOT)
67+
if (IS_USED(MODULE_RIOTBOOT_HDR_AUTO_CONFIRM)) {
68+
riotboot_slot_confirm();
69+
if (IS_USED(MODULE_RIOTBOOT_WDT)) {
70+
riotboot_wdt_stop();
71+
}
72+
}
73+
#endif
6374
int res = main();
6475

6576
if (IS_USED(MODULE_TEST_UTILS_MAIN_EXIT_CB)) {

dist/tools/riotboot_gen_hdr/genhdr.c

Lines changed: 72 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,36 @@
2828
*/
2929
#define HDR_ALIGN (256)
3030

31-
static void populate_hdr(riotboot_hdr_t *hdr, uint32_t ver, uint32_t addr)
31+
static size_t populate_hdr_v1(riotboot_hdr_t *hdr, uint32_t ver, uint32_t addr)
3232
{
3333
/* ensure the buffer and header have 0's */
34-
memset(hdr, '\0', sizeof(riotboot_hdr_t));
35-
36-
/* Generate image header */
37-
hdr->magic_number = RIOTBOOT_MAGIC;
38-
hdr->version = ver;
39-
hdr->start_addr = addr;
34+
memset(hdr, '\0', sizeof(*hdr));
35+
/* Generate image header v1 */
36+
hdr->v1.magic_number = RIOTBOOT_MAGIC_V1;
37+
hdr->v1.version = ver;
38+
hdr->v1.start_addr = addr;
39+
/* calculate header checksum */
40+
hdr->v1.chksum = riotboot_hdr_checksum(hdr);
41+
return sizeof(hdr->v1);
42+
}
4043

44+
static size_t populate_hdr_v2(riotboot_hdr_t *hdr, uint32_t ver, uint32_t addr)
45+
{
46+
/* ensure the buffer and header have 0's */
47+
memset(hdr, '\0', sizeof(*hdr));
48+
/* Generate image header v2 */
49+
hdr->v2.magic_number = RIOTBOOT_MAGIC_V2;
50+
hdr->v2.version = ver;
51+
hdr->v2.start_addr = addr;
52+
hdr->v2.flags = 0xffffffff;
4153
/* calculate header checksum */
42-
hdr->chksum = riotboot_hdr_checksum(hdr);
54+
hdr->v2.chksum = riotboot_hdr_checksum(hdr);
55+
return sizeof(hdr->v2);
4356
}
4457

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

4962
/* riotboot_hdr buffer */
5063
uint8_t *hdr_buf;
@@ -93,14 +106,41 @@ int genhdr(int argc, char *argv[])
93106
hdr_len = hdr_len_arg;
94107
}
95108

109+
/* generate only v1 by default */
110+
bool gen_v1 = true;
111+
bool gen_v2 = false;
112+
if (argc >= 8) {
113+
gen_v1 = false;
114+
if (!strcmp(argv[6], "-v")) {
115+
for (int a = 7; a < argc; a++) {
116+
if (!strcmp(argv[a], "v1")) {
117+
gen_v1 = true;
118+
}
119+
else if (!strcmp(argv[a], "v2")) {
120+
gen_v2 = true;
121+
}
122+
else {
123+
fprintf(stderr, "Error: unknown version '%s'!\n", argv[a]);
124+
return -1;
125+
}
126+
}
127+
}
128+
}
96129
/* prepare a 0 initialised buffer for riotboot_hdr_t */
97130
hdr_buf = calloc(1, hdr_len);
98131
if (hdr_buf == NULL) {
99132
fprintf(stderr, "Error: not enough memory!\n");
100133
return -1;
101134
}
102135

103-
populate_hdr((riotboot_hdr_t*)hdr_buf, app_ver, start_addr);
136+
size_t gen_hdr_size = 0;
137+
uint8_t *p_hdr = hdr_buf;
138+
if (gen_v1) {
139+
gen_hdr_size += populate_hdr_v1((riotboot_hdr_t *)(p_hdr + gen_hdr_size), app_ver, start_addr);
140+
}
141+
if (gen_v2) {
142+
gen_hdr_size += populate_hdr_v2((riotboot_hdr_t *)(p_hdr + gen_hdr_size), app_ver, start_addr);
143+
}
104144

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

125165
riotboot_hdr_t hdr = { 0 };
126166
int res = from_file(file, &hdr, sizeof(hdr));
127-
if (res < (int)sizeof(hdr)) {
167+
if (res < (int)sizeof(hdr.v1)) {
128168
fprintf(stderr, "Can't read header from %s\n", file);
129169
return -EIO;
130170
}
131-
132-
if (hdr.magic_number != RIOTBOOT_MAGIC) {
133-
fprintf(stderr, "Invalid magic: %x\n", hdr.magic_number);
171+
uint32_t magic = riotboot_hdr_get_magic_number(&hdr);
172+
if (magic == RIOTBOOT_MAGIC_V2) {
173+
hdr.v2.magic_number = RIOTBOOT_MAGIC_V2;
174+
hdr.v2.version = atoi(argv[2]);
175+
hdr.v2.chksum = riotboot_hdr_checksum(&hdr);
176+
to_file(file, &hdr, sizeof(hdr.v2));
177+
}
178+
else if (magic == RIOTBOOT_MAGIC_V1) {
179+
hdr.v1.magic_number = RIOTBOOT_MAGIC_V1;
180+
hdr.v1.version = atoi(argv[2]);
181+
hdr.v1.chksum = riotboot_hdr_checksum(&hdr);
182+
to_file(file, &hdr, sizeof(hdr.v1));
183+
}
184+
else {
185+
fprintf(stderr, "Invalid magic: %x\n", magic);
134186
return -EIO;
135187
}
136188

137-
hdr.version = atoi(argv[2]);
138-
hdr.chksum = riotboot_hdr_checksum(&hdr);
139-
to_file(file, &hdr, sizeof(hdr));
140-
141189
return 0;
142190
}
143191

144192
static void print_hdr(const riotboot_hdr_t *hdr)
145193
{
146-
printf("version: %u\n", hdr->version);
147-
printf("address: 0x%x\n", hdr->start_addr);
194+
printf("version: %u\n", riotboot_hdr_get_version(hdr));
195+
printf("address: 0x%x\n", riotboot_hdr_get_start_addr(hdr));
148196
printf("checksum: %svalid\n", riotboot_hdr_validate(hdr) ? "in" : "");
149197
}
150198

151199
static void print_hdr_json(const riotboot_hdr_t *hdr)
152200
{
153201
printf("{\n");
154-
printf("\t\"version\": %u,\n", hdr->version);
155-
printf("\t\"address\": %u,\n", hdr->start_addr);
202+
printf("\t\"version\": %u,\n", riotboot_hdr_get_version(hdr));
203+
printf("\t\"address\": %u,\n", riotboot_hdr_get_start_addr(hdr));
156204
printf("\t\"valid\": %s\n", riotboot_hdr_validate(hdr) ? "false" : "true");
157205
printf("}\n");
158206
}
@@ -166,8 +214,8 @@ int readhdr(const char *file, bool json)
166214
return -EIO;
167215
}
168216

169-
if (hdr.magic_number != RIOTBOOT_MAGIC) {
170-
fprintf(stderr, "Invalid magic: %x\n", hdr.magic_number);
217+
if (riotboot_hdr_get_magic_number(&hdr) != RIOTBOOT_MAGIC) {
218+
fprintf(stderr, "Invalid magic: %x\n", riotboot_hdr_get_magic_number(&hdr));
171219
return -EIO;
172220
}
173221

examples/advanced/suit_update/main.c

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "suit/transport/coap.h"
2727
#ifdef MODULE_SUIT_STORAGE_FLASHWRITE
28+
#include "periph/flashpage.h"
2829
#include "riotboot/slot.h"
2930
#endif
3031

@@ -69,19 +70,47 @@ static int cmd_print_riotboot_hdr(int argc, char **argv)
6970
(void)argc;
7071
(void)argv;
7172

72-
int current_slot = riotboot_slot_current();
73-
if (current_slot != -1) {
73+
if (riotboot_slot_current() == -1) {
74+
printf("[FAILED] You're not running riotboot\n");
75+
return -1;
76+
}
77+
if (argc == 1) {
78+
printf("Usage: %s [<slot> [activate|deactivate|confirm|dismiss]]\n", argv[0]);
79+
return 0;
80+
}
81+
int slot = atoi(argv[1]);
82+
if (argc == 2) {
7483
/* Sometimes, udhcp output messes up the following printfs. That
75-
* confuses the test script. As a workaround, just disable interrupts
76-
* for a while.
77-
*/
84+
* confuses the test script. As a workaround, just disable interrupts
85+
* for a while.
86+
*/
7887
unsigned state = irq_disable();
79-
riotboot_slot_print_hdr(current_slot);
88+
riotboot_slot_print_hdr(slot);
8089
irq_restore(state);
90+
return 0;
8191
}
82-
else {
83-
printf("[FAILED] You're not running riotboot\n");
92+
riotboot_hdr_t hdr = *riotboot_slot_get_hdr(slot);
93+
if (riotboot_hdr_is_v2(&hdr)) {
94+
if (!strcmp(argv[2], "activate")) {
95+
riotboot_hdr_set_img_state(&hdr, RIOTBOOT_HDR_IMG_STATE_ACTIVATED);
96+
}
97+
else if (!strcmp(argv[2], "deactivate")) {
98+
riotboot_hdr_set_img_state(&hdr, RIOTBOOT_HDR_IMG_STATE_DEACTIVATED);
99+
}
100+
else if (!strcmp(argv[2], "confirm")) {
101+
riotboot_hdr_set_img_state(&hdr, RIOTBOOT_HDR_IMG_STATE_CONFIRMED);
102+
}
103+
else if (!strcmp(argv[2], "dismiss")) {
104+
riotboot_hdr_set_img_state(&hdr, RIOTBOOT_HDR_IMG_STATE_DISMISSED);
105+
}
106+
else {
107+
printf("Unknown command %s\n", argv[2]);
108+
return -1;
109+
}
110+
flashpage_write(flashpage_addr(flashpage_page(riotboot_slot_get_hdr(slot))),
111+
&hdr.v2, sizeof(hdr.v2));
84112
}
113+
85114
return 0;
86115
}
87116

makefiles/boot/riotboot.mk

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ $(BINDIR_RIOTBOOT)/%.elf: $(BASELIBS) $(ARCHIVES) $(BINDIR_RIOTBOOT)
3535
$(Q)$(_LINK) -o $@
3636
endif
3737

38+
RIOTBOOT_HDR_VERSION ?= -v
39+
ifneq (,$(filter riotboot_hdr_v1, $(USEMODULE)))
40+
RIOTBOOT_HDR_VERSION := $(RIOTBOOT_HDR_VERSION) v1
41+
endif
42+
ifneq (,$(filter riotboot_hdr_v2, $(USEMODULE)))
43+
RIOTBOOT_HDR_VERSION := $(RIOTBOOT_HDR_VERSION) v2
44+
endif
45+
3846
# Slot 0 and 1 firmware offset, after header
3947
SLOT0_IMAGE_OFFSET := $$(($(SLOT0_OFFSET) + $(RIOTBOOT_HDR_LEN)))
4048
SLOT1_IMAGE_OFFSET := $$(($(SLOT1_OFFSET) + $(RIOTBOOT_HDR_LEN)))
@@ -70,7 +78,7 @@ $(HEADER_TOOL): FORCE
7078
# It must be always regenerated in case of any changes, so FORCE
7179
.PRECIOUS: %.bin
7280
%.hdr: $(HEADER_TOOL) %.bin FORCE
73-
$(Q)$(HEADER_TOOL) generate $< $(APP_VER) $$(($(ROM_START_ADDR)+$(OFFSET))) $(RIOTBOOT_HDR_LEN) - > $@
81+
$(Q)$(HEADER_TOOL) generate $< $(APP_VER) $$(($(ROM_START_ADDR)+$(OFFSET))) $(RIOTBOOT_HDR_LEN) - $(RIOTBOOT_HDR_VERSION) > $@
7482

7583
$(BINDIR_RIOTBOOT)/slot0.hdr: OFFSET=$(SLOT0_IMAGE_OFFSET)
7684
$(BINDIR_RIOTBOOT)/slot1.hdr: OFFSET=$(SLOT1_IMAGE_OFFSET)

0 commit comments

Comments
 (0)