Skip to content

Commit d225c82

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

File tree

17 files changed

+588
-64
lines changed

17 files changed

+588
-64
lines changed

bootloaders/riotboot/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ APPLICATION = riotboot
33

44
# Include riotboot flash partition functionality
55
USEMODULE += riotboot_slot
6+
USEMODULE += riotboot_flashwrite
7+
USEMODULE += riotboot_wdt
68

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

bootloaders/riotboot/main.c

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,69 @@
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-
35+
uint32_t version;
36+
int slot;
37+
int state;
38+
INIT:
39+
version = 0;
40+
slot = -1;
3241
for (unsigned i = 0; i < riotboot_slot_numof; i++) {
3342
const riotboot_hdr_t *riot_hdr = riotboot_slot_get_hdr(i);
3443
if (riotboot_slot_validate(i)) {
3544
/* skip slot if metadata broken */
3645
continue;
3746
}
38-
if (riot_hdr->start_addr != riotboot_slot_get_image_startaddr(i)) {
47+
if (riotboot_hdr_get_start_addr(riot_hdr) !=
48+
riotboot_slot_get_image_startaddr(i)) {
49+
continue;
50+
}
51+
state = riotboot_hdr_get_img_state(riot_hdr);
52+
if (state == RIOTBOOT_HDR_IMG_STATE_INSTALLED ||
53+
state == RIOTBOOT_HDR_IMG_STATE_DISMISSED) {
54+
/* skip image which previously failed to boot or is not yet activated */
3955
continue;
4056
}
41-
if (slot == -1 || riot_hdr->version > version) {
42-
version = riot_hdr->version;
57+
if (slot == -1 || riotboot_hdr_get_version(riot_hdr) > version) {
58+
version = riotboot_hdr_get_version(riot_hdr);
4359
slot = i;
4460
}
4561
}
46-
62+
unsigned boot = 0;
4763
if (slot != -1) {
64+
riotboot_hdr_t riot_hdr = *riotboot_slot_get_hdr(slot);
65+
if (riotboot_hdr_is_v2(&riot_hdr)) {
66+
boot = riotboot_hdr_get_boot_count(&riot_hdr);
67+
if (state == RIOTBOOT_HDR_IMG_STATE_ACTIVATED) {
68+
/* not yet confirmed */
69+
if (boot == CONFIG_RIOTBOOT_MAX_ATTEMPTS) {
70+
/* failed to boot for CONFIG_RIOTBOOT_MAX_ATTEMPTS attempts */
71+
riotboot_hdr_set_img_state(&riot_hdr, RIOTBOOT_HDR_IMG_STATE_DISMISSED);
72+
goto INIT; /* choose different slot */
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+
}
83+
#if IS_USED(MODULE_RIOTBOOT_WDT)
84+
riotboot_wdt_start(CONFIG_RIOTBOOT_WDT_TIMEOUT_MSEC << boot);
85+
#endif
4886
riotboot_slot_jump(slot);
4987
}
5088

core/lib/init.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
#include "periph/pm.h"
3131
#include "thread.h"
3232
#include "stdio_base.h"
33-
33+
#if IS_USED(MODULE_RIOTBOOT)
34+
#include "riotboot/wdt.h"
35+
#endif
3436
#if IS_USED(MODULE_VFS)
3537
#include "vfs.h"
3638
#endif
@@ -60,6 +62,11 @@ static void *main_trampoline(void *arg)
6062
LOG_INFO(CONFIG_BOOT_MSG_STRING "\n");
6163
}
6264

65+
#if IS_USED(MODULE_RIOTBOOT)
66+
if (IS_USED(MODULE_RIOTBOOT_HDR_MAIN_CONFIRM)) {
67+
riotboot_wdt_stop();
68+
}
69+
#endif
6370
int res = main();
6471

6572
if (IS_USED(MODULE_TEST_UTILS_MAIN_EXIT_CB)) {

dist/tools/riotboot_gen_hdr/genhdr.c

Lines changed: 74 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,38 @@
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;
53+
hdr->v2.flags &= ~RIOTBOOT_HDR_IMAGE_STATE_MASK;
54+
hdr->v2.flags |= (RIOTBOOT_HDR_IMG_STATE_ACTIVATED << RIOTBOOT_HDR_IMAGE_STATE_SHIFT);
4155
/* calculate header checksum */
42-
hdr->chksum = riotboot_hdr_checksum(hdr);
56+
hdr->v2.chksum = riotboot_hdr_checksum(hdr);
57+
return sizeof(hdr->v2);
4358
}
4459

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

4964
/* riotboot_hdr buffer */
5065
uint8_t *hdr_buf;
@@ -93,14 +108,41 @@ int genhdr(int argc, char *argv[])
93108
hdr_len = hdr_len_arg;
94109
}
95110

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

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

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

125167
riotboot_hdr_t hdr = { 0 };
126168
int res = from_file(file, &hdr, sizeof(hdr));
127-
if (res < (int)sizeof(hdr)) {
169+
if (res < (int)sizeof(hdr.v1)) {
128170
fprintf(stderr, "Can't read header from %s\n", file);
129171
return -EIO;
130172
}
131-
132-
if (hdr.magic_number != RIOTBOOT_MAGIC) {
133-
fprintf(stderr, "Invalid magic: %x\n", hdr.magic_number);
173+
uint32_t magic = riotboot_hdr_get_magic_number(&hdr);
174+
if (magic == RIOTBOOT_MAGIC_V2) {
175+
hdr.v2.magic_number = RIOTBOOT_MAGIC_V2;
176+
hdr.v2.version = atoi(argv[2]);
177+
hdr.v2.chksum = riotboot_hdr_checksum(&hdr);
178+
to_file(file, &hdr, sizeof(hdr.v2));
179+
}
180+
else if (magic == RIOTBOOT_MAGIC_V1) {
181+
hdr.v1.magic_number = RIOTBOOT_MAGIC_V1;
182+
hdr.v1.version = atoi(argv[2]);
183+
hdr.v1.chksum = riotboot_hdr_checksum(&hdr);
184+
to_file(file, &hdr, sizeof(hdr.v1));
185+
}
186+
else {
187+
fprintf(stderr, "Invalid magic: %x\n", magic);
134188
return -EIO;
135189
}
136190

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

144194
static void print_hdr(const riotboot_hdr_t *hdr)
145195
{
146-
printf("version: %u\n", hdr->version);
147-
printf("address: 0x%x\n", hdr->start_addr);
196+
printf("version: %u\n", riotboot_hdr_get_version(hdr));
197+
printf("address: 0x%x\n", riotboot_hdr_get_start_addr(hdr));
148198
printf("checksum: %svalid\n", riotboot_hdr_validate(hdr) ? "in" : "");
149199
}
150200

151201
static void print_hdr_json(const riotboot_hdr_t *hdr)
152202
{
153203
printf("{\n");
154-
printf("\t\"version\": %u,\n", hdr->version);
155-
printf("\t\"address\": %u,\n", hdr->start_addr);
204+
printf("\t\"version\": %u,\n", riotboot_hdr_get_version(hdr));
205+
printf("\t\"address\": %u,\n", riotboot_hdr_get_start_addr(hdr));
156206
printf("\t\"valid\": %s\n", riotboot_hdr_validate(hdr) ? "false" : "true");
157207
printf("}\n");
158208
}
@@ -166,8 +216,8 @@ int readhdr(const char *file, bool json)
166216
return -EIO;
167217
}
168218

169-
if (hdr.magic_number != RIOTBOOT_MAGIC) {
170-
fprintf(stderr, "Invalid magic: %x\n", hdr.magic_number);
219+
if (riotboot_hdr_get_magic_number(&hdr) != RIOTBOOT_MAGIC) {
220+
fprintf(stderr, "Invalid magic: %x\n", riotboot_hdr_get_magic_number(&hdr));
171221
return -EIO;
172222
}
173223

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+
$(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)

sys/include/riotboot/flashwrite.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,15 +211,16 @@ int riotboot_flashwrite_finish_raw(riotboot_flashwrite_t *state,
211211
* @brief Finish a firmware update (riotboot version)
212212
*
213213
* This function finishes a firmware update by re-writing the first header so
214-
* it includes riotboot's magic number ("RIOT").
214+
* it includes riotboot's magic number.
215215
*
216216
* @param[in] state ptr to previously used state structure
217217
*
218218
* @returns 0 on success, <0 otherwise
219219
*/
220220
static inline int riotboot_flashwrite_finish(riotboot_flashwrite_t *state)
221221
{
222-
return riotboot_flashwrite_finish_raw(state, (const uint8_t *)"RIOT",
222+
uint32_t magic = RIOTBOOT_MAGIC;
223+
return riotboot_flashwrite_finish_raw(state, (const uint8_t *)&magic,
223224
RIOTBOOT_FLASHWRITE_SKIPLEN);
224225
}
225226

0 commit comments

Comments
 (0)