diff --git a/common/Kconfig b/common/Kconfig index bc7cb0f..57418ca 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -937,6 +937,14 @@ See Documentation/devicetree/bindings/barebox/barebox,state.rst for more information. +config STATE_BACKWARD_COMPATIBLE + bool "backward compatible 'direct storage backend'" + depends on STATE + help + With this option enabled the 'direct' storage backend keeps backward + compatibility with older revisions of the state framework. Newer + revisions expect an additional 'meta header' and fail otherwise. + config BOOTCHOOSER bool "bootchooser infrastructure" depends on !SHELL_NONE diff --git a/common/state/backend_bucket_direct.c b/common/state/backend_bucket_direct.c index 4465ed0..958696e 100644 --- a/common/state/backend_bucket_direct.c +++ b/common/state/backend_bucket_direct.c @@ -69,6 +69,11 @@ if (meta.magic == direct_magic) { read_len = meta.written_length; } else { + if (!IS_ENABLED(CONFIG_STATE_BACKWARD_COMPATIBLE)) { + dev_err(direct->dev, "No meta data header found\n"); + dev_dbg(direct->dev, "Enable backward compatibility or increase stride size\n"); + return -EINVAL; + } read_len = direct->max_size; ret = lseek(direct->fd, direct->offset, SEEK_SET); if (ret < 0) { @@ -103,21 +108,26 @@ int ret; struct state_backend_storage_bucket_direct_meta meta; - if (len > direct->max_size - sizeof(meta)) - return -E2BIG; - ret = lseek(direct->fd, direct->offset, SEEK_SET); if (ret < 0) { dev_err(direct->dev, "Failed to seek file, %d\n", ret); return ret; } - meta.magic = direct_magic; - meta.written_length = len; - ret = write_full(direct->fd, &meta, sizeof(meta)); - if (ret < 0) { - dev_err(direct->dev, "Failed to write metadata to file, %d\n", ret); - return ret; + /* write the meta data only if there is head room */ + if (len <= direct->max_size - sizeof(meta)) { + meta.magic = direct_magic; + meta.written_length = len; + ret = write_full(direct->fd, &meta, sizeof(meta)); + if (ret < 0) { + dev_err(direct->dev, "Failed to write metadata to file, %d\n", ret); + return ret; + } + } else { + if (!IS_ENABLED(CONFIG_STATE_BACKWARD_COMPATIBLE)) { + dev_dbg(direct->dev, "Too small stride size: must skip metadata! Increase stride size\n"); + return -EINVAL; + } } ret = write_full(direct->fd, buf, len);