Skip to content

Commit 3558f08

Browse files
committed
boot: add NuttX bootloader with update and recovery support
This commit adds NuttX based bootloader with the support for image update and recovery if not confirmed. The algorithm utilizes three flash partitions: primary (image runs from this area), secondary and tertiary. Secondary and tertiary areas are used for update upload and recovery. The update is performed by simple copy from update area to primary area with recovery being created in recovery area if not already present. Once image is confirmed by the user, the image in update area is confirmed as well, update area becomes recovery area and vice versa. This means the recovery is always present (except for the first update) and subsequent updates just copy image from update to primary. This makes the update significantly faster and more considerable to flash wear while keeping the recovery/revert possibility. A header (aligned to flash's erase size) must be added to the beginning of the image. Python script nximage.py can be used to prepend this header to built binary. The algorithm implementation is based on a patch initially developed for MCUboot project but rejected by the project's maintainers mcu-tools/mcuboot#1902 Signed-off-by: Michal Lenc <michallenc@seznam.cz>
1 parent 8d82bd7 commit 3558f08

File tree

13 files changed

+1833
-0
lines changed

13 files changed

+1833
-0
lines changed

boot/nxboot/CMakeLists.txt

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# ##############################################################################
2+
# apps/boot/nxboot/CMakeLists.txt
3+
#
4+
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
5+
# license agreements. See the NOTICE file distributed with this work for
6+
# additional information regarding copyright ownership. The ASF licenses this
7+
# file to you under the Apache License, Version 2.0 (the "License"); you may not
8+
# use this file except in compliance with the License. You may obtain a copy of
9+
# the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16+
# License for the specific language governing permissions and limitations under
17+
# the License.
18+
#
19+
# ##############################################################################
20+
21+
if(CONFIG_BOOT_NXBOOT)
22+
nuttx_add_library(nxboot)
23+
set(SRCS
24+
loader/boot.c
25+
loader/crc32.c
26+
loader/flash.c)
27+
28+
if(BOOT_NXBOOT)
29+
nuttx_add_application(
30+
NAME
31+
nxboot_loader
32+
SRCS
33+
nxboot_main.c
34+
INCLUDE_DIRECTORIES
35+
include)
36+
endif()
37+
38+
target_include_directories(nxboot PUBLIC include)
39+
target_sources(nxboot PRIVATE ${SRCS})
40+
endif()

boot/nxboot/Kconfig

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#
2+
# For a description of the syntax of this configuration file,
3+
# see the file kconfig-language.txt in the NuttX tools repository.
4+
#
5+
6+
menuconfig BOOT_NXBOOT
7+
bool "NuttX bootloader"
8+
default n
9+
select BCH
10+
---help---
11+
Enable support for the minimal NuttX based bootloader.
12+
13+
if BOOT_NXBOOT
14+
15+
config NXBOOT_PRIMARY_SLOT_PATH
16+
string "Application firmware primary image slot path"
17+
default "/dev/ota0"
18+
---help---
19+
The path to the application firmware image primary slot character
20+
device driver. The image runs from this location.
21+
Default: /dev/ota0
22+
23+
config NXBOOT_SECONDARY_SLOT_PATH
24+
string "Application firmware secondary image slot path"
25+
default "/dev/ota1"
26+
---help---
27+
The path to the application firmware image primary slot character
28+
device driver. This is either update or recovery slot.
29+
Default: /dev/ota1
30+
31+
config NXBOOT_TERTIARY_SLOT_PATH
32+
string "Application firmware tertiary image slot path"
33+
default "/dev/ota2"
34+
---help---
35+
The path to the application firmware image primary slot character
36+
device driver. This is either update or recovery slot.
37+
Default: /dev/ota2
38+
39+
config NXBOOT_HEADER_SIZE
40+
hex "Application firmware image header size"
41+
default 0x200
42+
---help---
43+
Note that this size should be aligned with the program memory erase
44+
page size!
45+
46+
config NXBOOT_BOOTLOADER
47+
bool "Build nxboot bootloader application"
48+
default n
49+
select BOARDCTL
50+
select BOARDCTL_BOOT_IMAGE
51+
---help---
52+
This option builds and links a bootloader application. This application
53+
should be an entry function for NuttX. It checks for possible update/
54+
revert operation, performs it and boot the correct image.
55+
56+
if NXBOOT_BOOTLOADER
57+
58+
config NXBOOT_SWRESET_ONLY
59+
bool "Perform update/revert only on SW reset"
60+
default n
61+
select BOARDCTL_RESET_CAUSE
62+
---help---
63+
This option ensures the update/revert is performed only for following
64+
reset causes:
65+
BOARDIOC_RESETCAUSE_CPU_SOFT: software reset
66+
BOARDIOC_RESETCAUSE_CPU_RWDT: watchdog error
67+
BOARDIOC_RESETCAUSE_PIN: reset button
68+
69+
This way the board can keep its image (even if not confirmed) during
70+
for example power shutdown and perform update/revent only if expected
71+
based on user/maintainer input.
72+
73+
config NXBOOT_PREVENT_DOWNGRADE
74+
bool "Perform update only for newer version"
75+
default n
76+
---help---
77+
NXboot uses Semantic Version 2.0.0 (without build metadata). By default
78+
the update is performed for every version that doesn't match the
79+
currently running one. If NXBOOT_PREVENT_DOWNGRADE selected, update is
80+
performed only for newer versions (according to Semantic Version
81+
preference rules).
82+
83+
WARNING: NXboot currently implementes preferences only for
84+
MAJOR.MINOR.PATCH and ignores prerelease.
85+
86+
endif # NXBOOT_BOOTLOADER
87+
88+
endif # BOOT_NXBOOT

boot/nxboot/Make.defs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
############################################################################
2+
# apps/boot/nxboot/Make.defs
3+
#
4+
# Licensed to the Apache Software Foundation (ASF) under one or more
5+
# contributor license agreements. See the NOTICE file distributed with
6+
# this work for additional information regarding copyright ownership. The
7+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance with the
9+
# License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16+
# License for the specific language governing permissions and limitations
17+
# under the License.
18+
#
19+
############################################################################
20+
21+
ifneq ($(CONFIG_BOOT_NXBOOT),)
22+
CONFIGURED_APPS += $(APPDIR)/boot/nxboot
23+
24+
CFLAGS += ${INCDIR_PREFIX}$(APPDIR)/boot/nxboot/include
25+
26+
endif

boot/nxboot/Makefile

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
############################################################################
2+
# apps/boot/nxboot/Makefile
3+
#
4+
# Licensed to the Apache Software Foundation (ASF) under one or more
5+
# contributor license agreements. See the NOTICE file distributed with
6+
# this work for additional information regarding copyright ownership. The
7+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance with the
9+
# License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing, software
14+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16+
# License for the specific language governing permissions and limitations
17+
# under the License.
18+
#
19+
############################################################################
20+
21+
include $(APPDIR)/Make.defs
22+
23+
ifneq ($(CONFIG_NXBOOT_BOOTLOADER),)
24+
PROGNAME = nxboot_loader
25+
PRIORITY = SCHED_PRIORITY_DEFAULT
26+
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
27+
28+
MAINSRC = nxboot_main.c
29+
endif
30+
31+
CSRCS := loader/boot.c \
32+
loader/crc32.c \
33+
loader/flash.c
34+
35+
include $(APPDIR)/Application.mk

boot/nxboot/include/nxboot.h

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/****************************************************************************
2+
* apps/boot/nxboot/include/nxboot.h
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one or more
5+
* contributor license agreements. See the NOTICE file distributed with
6+
* this work for additional information regarding copyright ownership. The
7+
* ASF licenses this file to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance with the
9+
* License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16+
* License for the specific language governing permissions and limitations
17+
* under the License.
18+
*
19+
****************************************************************************/
20+
21+
#ifndef __BOOT_NXBOOT_INCLUDE_NXBOOT_H
22+
#define __BOOT_NXBOOT_INCLUDE_NXBOOT_H
23+
24+
/****************************************************************************
25+
* Included Files
26+
****************************************************************************/
27+
28+
#include <nuttx/config.h>
29+
#include <assert.h>
30+
#include <stdbool.h>
31+
32+
/****************************************************************************
33+
* Pre-processor Definitions
34+
****************************************************************************/
35+
36+
#define NXBOOT_PRIMARY_SLOT_NUM 0
37+
#define NXBOOT_SECONDARY_SLOT_NUM 1
38+
#define NXBOOT_TERTIARY_SLOT_NUM 2
39+
40+
#define NXBOOT_IMAGE_STATE_CONFIRM 1 /* Flag set -> image confirmed */
41+
#define NXBOOT_IMAGE_STATE_UPDATED 3 /* Flag set -> image was updated */
42+
#define NXBOOT_IMAGE_STATE_AVAIL 4 /* Flag set -> partition available */
43+
#define NXBOOT_IMAGE_STATE_UNSET 0xff /* Flag not set -> image not confirmed */
44+
45+
#define NXBOOT_HEADER_MAGIC 0x534f584e /* NXOS */
46+
#define NXBOOT_HEADER_PRERELEASE_MAXLEN 109
47+
48+
/****************************************************************************
49+
* Public Types
50+
****************************************************************************/
51+
52+
enum nxboot_update_type
53+
{
54+
NXBOOT_UPDATE_TYPE_NONE = 0, /* No action to do */
55+
NXBOOT_UPDATE_TYPE_UPDATE = 1, /* Update will take place upon reboot */
56+
NXBOOT_UPDATE_TYPE_REVERT = 2, /* Revert will take place upon reboot */
57+
};
58+
59+
/* Versioning is according to Semantic Versioning 2.0.0
60+
* refer to (https://semver.org/spec/v2.0.0.html)
61+
*/
62+
63+
struct nxboot_img_version
64+
{
65+
uint16_t major; /* MAJOR version */
66+
uint16_t minor; /* MINOR version */
67+
uint16_t patch; /* PATCH version */
68+
69+
char pre_release[NXBOOT_HEADER_PRERELEASE_MAXLEN]; /* Additional pre-release version */
70+
};
71+
72+
struct nxboot_img_header
73+
{
74+
uint32_t magic; /* Header magic */
75+
uint32_t size; /* Image size (excluding the header) */
76+
uint32_t crc32; /* CRC32 of image (excluding the header) */
77+
uint8_t state; /* Image state */
78+
79+
struct nxboot_img_version img_version; /* Image version */
80+
};
81+
static_assert(CONFIG_NXBOOT_HEADER_SIZE > sizeof(struct nxboot_img_header),
82+
"CONFIG_NXBOOT_HEADER_SIZE has to be larger than"
83+
"sizeof(struct nxboot_img_header)");
84+
85+
struct nxboot_state
86+
{
87+
int update; /* Number of update slot */
88+
int recovery; /* Number of recovery slot */
89+
bool recovery_valid; /* True if recovery image contains valid recovery */
90+
bool primary_confirmed; /* True if primary slot is confirmed */
91+
enum nxboot_update_type next_boot; /* True if update slot has a valid image */
92+
};
93+
94+
/****************************************************************************
95+
* Public Function Prototypes
96+
****************************************************************************/
97+
98+
/****************************************************************************
99+
* Name: nxboot_get_state
100+
*
101+
* Description:
102+
* Gets the current bootloader state and stores it in the nxboot_state
103+
* structure passed as an argument. This function may be used to determine
104+
* which slot is update slot and where should application save incoming
105+
* firmware.
106+
*
107+
* Input parameters:
108+
* state: The pointer to nxboot_state structure. The state is stored here.
109+
*
110+
* Returned Value:
111+
* 0 on success, -1 and sets errno on failure.
112+
*
113+
****************************************************************************/
114+
115+
int nxboot_get_state(struct nxboot_state *state);
116+
117+
/****************************************************************************
118+
* Name: nxboot_get_confirm
119+
*
120+
* Description:
121+
* This function can be used to determine whether primary image is
122+
* confirmed or not. This provides more direct access to confirm
123+
* state compared to nxboot_get_state function that returns the full
124+
* state of the bootloader.
125+
*
126+
* Returned Value:
127+
* 1 means confirmed, 0 not confirmed, -1 and sets errno on failure.
128+
*
129+
****************************************************************************/
130+
131+
int nxboot_get_confirm(void);
132+
133+
/****************************************************************************
134+
* Name: nxboot_confirm
135+
*
136+
* Description:
137+
* Confirms the image currently located in primary partition and marks
138+
* its copy in update partition as a recovery.
139+
*
140+
* Returned Value:
141+
* 0 on success, -1 and sets errno on failure.
142+
*
143+
****************************************************************************/
144+
145+
int nxboot_confirm(void);
146+
147+
/****************************************************************************
148+
* Name: nxboot_perform_swap
149+
*
150+
* Description:
151+
* Checks for the possible firmware update and performs it by copying
152+
* update image to primary slot or recovery image to primary slot in case
153+
* of the revert. In any situation, this function ends with the valid
154+
* image in primary slot.
155+
*
156+
* This is an entry point function that should be called from the
157+
* bootloader application.
158+
*
159+
* Input parameters:
160+
* check_only: Only repairs corrupted update, but do not start another one
161+
*
162+
* Returned Value:
163+
* 0 on success, -1 and sets errno on failure.
164+
*
165+
****************************************************************************/
166+
167+
int nxboot_perform_update(bool check_only);
168+
169+
#endif /* __BOOT_NXBOOT_INCLUDE_NXBOOT_H */

0 commit comments

Comments
 (0)