summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/Kconfig8
-rw-r--r--common/state/backend_bucket_direct.c28
2 files changed, 27 insertions, 9 deletions
diff --git a/common/Kconfig b/common/Kconfig
index bc7cb0fe76..57418cadc6 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -937,6 +937,14 @@ config STATE_CRYPTO
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 4465ed0e41..958696ed94 100644
--- a/common/state/backend_bucket_direct.c
+++ b/common/state/backend_bucket_direct.c
@@ -69,6 +69,11 @@ static int state_backend_bucket_direct_read(struct state_backend_storage_bucket
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 @@ static int state_backend_bucket_direct_write(struct state_backend_storage_bucket
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);