Add a handler to manage the boot selection process according to
the Firmware Update (FWU) metadata specification using the
libfwumdata library.
The handler is a script handler that updates the active_index
and marks the selected bank as valid during the post-install phase.
Example in sw-description:
scripts: (
{
type = "fwumdata";
properties: {
active = "1";
}
}
);
Signed-off-by: Dario Binacchi <
dario.b...@amarulasolutions.com>
---
Kconfig | 4 ++
Makefile.deps | 4 ++
Makefile.flags | 3 +
bootloader/Kconfig | 7 ++
configs/all_handlers_defconfig | 1 +
doc/source/handlers.rst | 37 ++++++++++
handlers/Kconfig | 17 +++++
handlers/Makefile | 1 +
handlers/fwumdata_handler.c | 125 +++++++++++++++++++++++++++++++++
9 files changed, 199 insertions(+)
create mode 100644 handlers/fwumdata_handler.c
diff --git a/Kconfig b/Kconfig
index 2cf68eb890b0..fcb60f900b3f 100644
--- a/Kconfig
+++ b/Kconfig
@@ -129,6 +129,10 @@ config HAVE_ZCK
bool
option env="HAVE_ZCK"
+config HAVE_LIBFWUMDATA
+ bool
+ option env="HAVE_LIBFWUMDATA"
+
menu "SWUpdate Settings"
menu "General Configuration"
diff --git a/Makefile.deps b/Makefile.deps
index c759f6876dea..313d5af6230c 100644
--- a/Makefile.deps
+++ b/Makefile.deps
@@ -121,3 +121,7 @@ endif
ifeq ($(HAVE_ZCK),)
export HAVE_ZCK = y
endif
+
+ifeq ($(HAVE_LIBFWUMDATA),)
+export HAVE_LIBFWUMDATA = y
+endif
diff --git a/Makefile.flags b/Makefile.flags
index 40dd3b66856e..76b87e67fe67 100644
--- a/Makefile.flags
+++ b/Makefile.flags
@@ -233,6 +233,9 @@ ifeq ($(CONFIG_UCFWHANDLER),y)
LDLIBS += gpiod
endif
+ifeq ($(CONFIG_FWUMDATA_HANDLER),y)
+LDLIBS += fwumdata
+endif
ifeq ($(CONFIG_BOOTLOADER_STATIC_LINKED),y)
ifeq ($(CONFIG_BOOTLOADER_EBG),y)
diff --git a/bootloader/Kconfig b/bootloader/Kconfig
index edc02d99b2d1..36f856507356 100644
--- a/bootloader/Kconfig
+++ b/bootloader/Kconfig
@@ -158,3 +158,10 @@ config UPDATE_STATE_BOOTLOADER
help
Store update information in Bootloader's environment.
+config FWUMDATA_CONFIG_FILE
+ string "FWU Metadata Configuration file"
+ depends on HAVE_LIBFWUMDATA
+ default "/etc/fwumdata.config"
+ help
+ It tells where the FWU metadata are saved.
+
diff --git a/configs/all_handlers_defconfig b/configs/all_handlers_defconfig
index 16cd9b6b98f1..63299bd223ae 100644
--- a/configs/all_handlers_defconfig
+++ b/configs/all_handlers_defconfig
@@ -20,6 +20,7 @@ CONFIG_DISKPART=y
CONFIG_DISKPART_FORMAT=y
CONFIG_DISKFORMAT_HANDLER=y
CONFIG_FAT_FILESYSTEM=y
+CONFIG_FWUMDATA_HANDLER=y
CONFIG_EXT_FILESYSTEM=y
CONFIG_LUASCRIPTHANDLER=y
CONFIG_RAW=y
diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst
index 6742c10a58c3..cbfb146f099c 100644
--- a/doc/source/handlers.rst
+++ b/doc/source/handlers.rst
@@ -1710,3 +1710,40 @@ Examples:
name = "helloworld";
};
});
+
+FWU Metadata Handler
+--------------------
+
+This is a script handler used to manage the boot selection process according to
+the Firmware Update (FWU) metadata specification.
+
+The handler implements a post-install script that updates the metadata to switch
+the active bank and marks it as valid, ensuring the system boots from the new
+bank at the next reset. The ``active`` property defines which bank must be
+selected.
+
+Example selecting boot bank 1 (bank A in A/B schema):
+
+::
+
+ scripts: (
+ {
+ type = "fwumdata";
+ properties: {
+ active = "1";
+ }
+ }
+ );
+
+Example selecting boot bank 2 (bank B in A/B schema):
+
+::
+
+ scripts: (
+ {
+ type = "fwumdata";
+ properties: {
+ active = "2";
+ }
+ }
+ );
diff --git a/handlers/Kconfig b/handlers/Kconfig
index 152bc08074a1..b7d9e51a20c9 100644
--- a/handlers/Kconfig
+++ b/handlers/Kconfig
@@ -151,6 +151,23 @@ config EMMC_HANDLER
with a dual-copy concept. This guarantees that the upgrade
is power-cut safe.
+config FWUMDATA_HANDLER
+ bool "FWU metadata update"
+ depends on HAVE_LIBFWUMDATA
+ default n
+ help
+ This handler allows to manage the boot selection process using
+ firmware update (FWU) metadata via libfwumdata.
+
+ Selecting the new boot bank automatically triggers the handler to
+ set the current bank for rollback and mark the selected boot-up
+ bank as 'valid'.
+
+ This ensures the system is ready to boot from the updated
+ partition while maintaining a safe path to revert to the previous
+ working state if the new firmware fails to reach the 'accepted'
+ state
+
config RAW
bool "raw"
default n
diff --git a/handlers/Makefile b/handlers/Makefile
index 8490172a10a3..45fcb525e461 100644
--- a/handlers/Makefile
+++ b/handlers/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_SWUFORWARDER_HANDLER) += swuforward_handler.o swuforward-ws.o
obj-$(CONFIG_UBIVOL) += ubivol_handler.o
obj-$(CONFIG_UCFWHANDLER) += ucfw_handler.o
obj-$(CONFIG_DOCKER) += docker_handler.o
+obj-$(CONFIG_FWUMDATA_HANDLER) += fwumdata_handler.o
diff --git a/handlers/fwumdata_handler.c b/handlers/fwumdata_handler.c
new file mode 100644
index 000000000000..1331fe64aa74
--- /dev/null
+++ b/handlers/fwumdata_handler.c
@@ -0,0 +1,125 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <linux/version.h>
+#include <sys/ioctl.h>
+#include <stddef.h>
+
+#include "swupdate_image.h"
+#include "handler.h"
+#include "util.h"
+
+#include <libfwumdata.h>
+
+static int _fwumdata_set(uint32_t active_index, uint32_t previous_index,
+ uint8_t bank_state)
+{
+ int mdd;
+ int ret;
+
+ mdd = fwumdata_init();
+ if (mdd < 0) {
+ ERROR("Cannot initialize libfwumdata\n");
+ return mdd;
+ }
+
+ ret = fwumdata_read_config(mdd, CONFIG_FWUMDATA_CONFIG_FILE);
+ if (ret) {
+ ERROR("Cannot read %s\n", CONFIG_FWUMDATA_CONFIG_FILE);
+ goto exit;
+ }
+
+ ret = fwumdata_open(mdd, 0);
+ if (ret) {
+ ERROR("Cannot open %s\n", CONFIG_FWUMDATA_CONFIG_FILE);
+ goto exit;
+ }
+
+ ret = fwumdata_set_active_index(mdd, active_index);
+ if (ret) {
+ ERROR("Cannot set active index\n");
+ goto close;
+ }
+
+ fwumdata_set_previous_index(mdd, previous_index);
+ if (ret) {
+ ERROR("Cannot set previous index\n");
+ goto close;
+ }
+
+ ret = fwumdata_set_bank_state(mdd, active_index, bank_state);
+ if (ret) {
+ ERROR("Cannot set bank state\n");
+ goto close;
+ }
+
+ ret = fwumdata_store(mdd);
+ if (ret) {
+ ERROR("Cannot store fwu metadata\n");
+ goto close;
+ }
+
+ DEBUG("fwumdata: active: %d, previous: %d, state: 0x%x",
+ active_index, previous_index, bank_state);
+
+close:
+ fwumdata_close(mdd);
+exit:
+ fwumdata_exit(mdd);
+ return ret;
+}
+
+static int fwumdata_set(struct img_type *img, void *data)
+{
+ struct script_handler_data *script_data;
+ char *value;
+ int active_index = -1;
+ int previous_index;
+
+
+ if (!data)
+ return -EINVAL;
+
+ script_data = data;
+
+ /*
+ * Call only in case of postinstall
+ */
+ if (script_data->scriptfn != POSTINSTALL)
+ return 0;
+
+ value = dict_get_value(&img->properties, "active");
+ if (!value) {
+ ERROR("active: cannot find in sw-description");
+ return -EINVAL;
+ }
+
+ active_index = ustrtoull(value, NULL, 10);
+ if (errno) {
+ ERROR("active %s: ustrotull failed", value);
+ return -EINVAL;
+ }
+
+ active_index--;
+ if (active_index == 0) {
+ previous_index = 1;
+ } else if (active_index == 1) {
+ previous_index = 0;
+ } else {
+ ERROR("active %s: invalid value", value);
+ return -EINVAL;
+
+ }
+
+ return _fwumdata_set(active_index, previous_index, FWUMDATA_BANK_VALID);
+}
+
+__attribute__((constructor))
+void fwumdata_handler(void)
+{
+ register_handler("fwumdata", fwumdata_set,
+ SCRIPT_HANDLER | NO_DATA_HANDLER, NULL);
+}
--
2.43.0