boot: zephyr: Add MCUboot status callback support
Adds an optional callback when the MCUboot status changes which can
allow components to react.
Signed-off-by: Jamie McCrae <jamie.mccrae@lairdconnect.com>
diff --git a/boot/bootutil/include/bootutil/mcuboot_status.h b/boot/bootutil/include/bootutil/mcuboot_status.h
new file mode 100644
index 0000000..b734923
--- /dev/null
+++ b/boot/bootutil/include/bootutil/mcuboot_status.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2022, Laird Connectivity
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef H_MCUBOOT_STATUS_
+#define H_MCUBOOT_STATUS_
+
+/* Enumeration representing the states that MCUboot can be in */
+typedef enum
+{
+ MCUBOOT_STATUS_STARTUP = 0,
+ MCUBOOT_STATUS_UPGRADING,
+ MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND,
+ MCUBOOT_STATUS_NO_BOOTABLE_IMAGE_FOUND,
+ MCUBOOT_STATUS_BOOT_FAILED,
+ MCUBOOT_STATUS_USB_DFU_WAITING,
+ MCUBOOT_STATUS_USB_DFU_ENTERED,
+ MCUBOOT_STATUS_USB_DFU_TIMED_OUT,
+ MCUBOOT_STATUS_SERIAL_DFU_ENTERED,
+} mcuboot_status_type_t;
+
+#if defined(CONFIG_MCUBOOT_ACTION_HOOKS)
+extern void mcuboot_status_change(mcuboot_status_type_t status);
+#else
+#define mcuboot_status_change(_status) do {} while (0)
+#endif
+
+#endif /* H_MCUBOOT_STATUS_ */
diff --git a/boot/bootutil/src/loader.c b/boot/bootutil/src/loader.c
index 6f6343c..27f2e5f 100644
--- a/boot/bootutil/src/loader.c
+++ b/boot/bootutil/src/loader.c
@@ -46,6 +46,7 @@
#include "bootutil/fault_injection_hardening.h"
#include "bootutil/ramload.h"
#include "bootutil/boot_hooks.h"
+#include "bootutil/mcuboot_status.h"
#ifdef MCUBOOT_ENC_IMAGES
#include "bootutil/enc_key.h"
@@ -1998,6 +1999,9 @@
}
#endif
+ /* Trigger status change callback with upgrading status */
+ mcuboot_status_change(MCUBOOT_STATUS_UPGRADING);
+
/* Iterate over all the images. At this point there are no aborted swaps
* and the swap types are determined for each image. By the end of the loop
* all required update operations will have been finished.
diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig
index 0efd0f0..c67d9e3 100644
--- a/boot/zephyr/Kconfig
+++ b/boot/zephyr/Kconfig
@@ -582,6 +582,16 @@
located. If the key file is not there, the build system uses relative
path that starts from the zephyr port cmake directory (boot/zephyr/).
+config MCUBOOT_ACTION_HOOKS
+ bool "Enable hooks for responding to MCUboot status changes"
+ help
+ This will call a handler when the MCUboot status changes which allows
+ for some level of user feedback, for instance to change LED status to
+ indicate a failure, using the callback:
+ 'void mcuboot_status_change(mcuboot_status_type_t status)' where
+ 'mcuboot_status_type_t' is listed in
+ boot/bootutil/include/bootutil/mcuboot_status.h
+
endmenu
config MCUBOOT_DEVICE_SETTINGS
diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c
index e885fb0..9cd0d0a 100644
--- a/boot/zephyr/main.c
+++ b/boot/zephyr/main.c
@@ -33,6 +33,7 @@
#include "bootutil/image.h"
#include "bootutil/bootutil.h"
#include "bootutil/fault_injection_hardening.h"
+#include "bootutil/mcuboot_status.h"
#include "flash_map_backend/flash_map_backend.h"
#ifdef CONFIG_MCUBOOT_SERIAL
@@ -452,6 +453,8 @@
(void)rc;
+ mcuboot_status_change(MCUBOOT_STATUS_STARTUP);
+
#if (!defined(CONFIG_XTENSA) && DT_HAS_CHOSEN(zephyr_flash_controller))
if (!flash_device_get_binding(DT_LABEL(DT_CHOSEN(zephyr_flash_controller)))) {
BOOT_LOG_ERR("Flash device %s not found",
@@ -477,6 +480,8 @@
gpio_pin_set_dt(&led0, 1);
#endif
+ mcuboot_status_change(MCUBOOT_STATUS_SERIAL_DFU_ENTERED);
+
BOOT_LOG_INF("Enter the serial recovery mode");
rc = boot_console_init();
__ASSERT(rc == 0, "Error initializing boot console.\n");
@@ -493,6 +498,9 @@
#ifdef CONFIG_MCUBOOT_INDICATION_LED
gpio_pin_set_dt(&led0, 1);
#endif
+
+ mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_ENTERED);
+
rc = usb_enable(NULL);
if (rc) {
BOOT_LOG_ERR("Cannot enable USB");
@@ -508,8 +516,13 @@
BOOT_LOG_ERR("Cannot enable USB");
} else {
BOOT_LOG_INF("Waiting for USB DFU");
+
+ mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_WAITING);
+
wait_for_usb_dfu(K_MSEC(CONFIG_BOOT_USB_DFU_WAIT_DELAY_MS));
BOOT_LOG_INF("USB DFU wait time elapsed");
+
+ mcuboot_status_change(MCUBOOT_STATUS_USB_DFU_TIMED_OUT);
}
#endif
@@ -537,6 +550,9 @@
if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
BOOT_LOG_ERR("Unable to find bootable image");
+
+ mcuboot_status_change(MCUBOOT_STATUS_NO_BOOTABLE_IMAGE_FOUND);
+
FIH_PANIC;
}
@@ -548,9 +564,14 @@
#else
BOOT_LOG_INF("Jumping to the first image slot");
#endif
+
+ mcuboot_status_change(MCUBOOT_STATUS_BOOTABLE_IMAGE_FOUND);
+
ZEPHYR_BOOT_LOG_STOP();
do_boot(&rsp);
+ mcuboot_status_change(MCUBOOT_STATUS_BOOT_FAILED);
+
BOOT_LOG_ERR("Never should get here");
while (1)
;