summaryrefslogtreecommitdiffstats
path: root/common/state
diff options
context:
space:
mode:
Diffstat (limited to 'common/state')
-rw-r--r--common/state/backend_bucket_circular.c4
-rw-r--r--common/state/backend_bucket_direct.c22
-rw-r--r--common/state/backend_format_dtb.c4
-rw-r--r--common/state/backend_format_raw.c4
-rw-r--r--common/state/backend_storage.c2
-rw-r--r--common/state/state.c73
-rw-r--r--common/state/state.h16
-rw-r--r--common/state/state_variables.c11
8 files changed, 92 insertions, 44 deletions
diff --git a/common/state/backend_bucket_circular.c b/common/state/backend_bucket_circular.c
index 735510e0d3..2ac5bf6a82 100644
--- a/common/state/backend_bucket_circular.c
+++ b/common/state/backend_bucket_circular.c
@@ -62,7 +62,7 @@ struct state_backend_storage_bucket_circular {
#endif
/* For outputs */
- struct device_d *dev;
+ struct device *dev;
};
/*
@@ -456,7 +456,7 @@ static int bucket_circular_is_block_bad(struct state_backend_storage_bucket_circ
}
#endif
-int state_backend_bucket_circular_create(struct device_d *dev, const char *path,
+int state_backend_bucket_circular_create(struct device *dev, const char *path,
struct state_backend_storage_bucket **bucket,
unsigned int eraseblock,
ssize_t writesize,
diff --git a/common/state/backend_bucket_direct.c b/common/state/backend_bucket_direct.c
index 117cdfb46c..03c752d6fe 100644
--- a/common/state/backend_bucket_direct.c
+++ b/common/state/backend_bucket_direct.c
@@ -29,7 +29,7 @@ struct state_backend_storage_bucket_direct {
int fd;
- struct device_d *dev;
+ struct device *dev;
};
struct __attribute__((__packed__)) state_backend_storage_bucket_direct_meta {
@@ -52,7 +52,7 @@ static int state_backend_bucket_direct_read(struct state_backend_storage_bucket
struct state_backend_storage_bucket_direct *direct =
get_bucket_direct(bucket);
struct state_backend_storage_bucket_direct_meta meta;
- uint32_t read_len;
+ uint32_t read_len, header_len = 0;
void *buf;
int ret;
@@ -72,6 +72,8 @@ static int state_backend_bucket_direct_read(struct state_backend_storage_bucket
return -EINVAL;
}
+
+ header_len = sizeof(meta);
} else {
if (meta.magic != ~0 && !!meta.magic)
bucket->wrong_magic = 1;
@@ -87,12 +89,16 @@ static int state_backend_bucket_direct_read(struct state_backend_storage_bucket
-errno);
return -errno;
}
+
}
buf = xmalloc(read_len);
if (!buf)
return -ENOMEM;
+ dev_dbg(direct->dev, "Read state from %lld length %d\n", (long long) direct->offset,
+ header_len + read_len);
+
ret = read_full(direct->fd, buf, read_len);
if (ret < 0) {
dev_err(direct->dev, "Failed to read from file, %d\n", ret);
@@ -112,6 +118,7 @@ static int state_backend_bucket_direct_write(struct state_backend_storage_bucket
{
struct state_backend_storage_bucket_direct *direct =
get_bucket_direct(bucket);
+ size_t header_len = 0;
int ret;
struct state_backend_storage_bucket_direct_meta meta;
@@ -129,6 +136,8 @@ static int state_backend_bucket_direct_write(struct state_backend_storage_bucket
dev_err(direct->dev, "Failed to write metadata to file, %d\n", ret);
return ret;
}
+
+ header_len = sizeof(meta);
} else {
if (!IS_ENABLED(CONFIG_STATE_BACKWARD_COMPATIBLE)) {
dev_dbg(direct->dev, "Too small stride size: must skip metadata! Increase stride size\n");
@@ -148,6 +157,9 @@ static int state_backend_bucket_direct_write(struct state_backend_storage_bucket
return ret;
}
+ dev_dbg(direct->dev, "Written state to offset %lld length %zu data length %zu\n",
+ (long long)direct->offset, len + header_len, len);
+
return 0;
}
@@ -162,14 +174,14 @@ static void state_backend_bucket_direct_free(struct
free(direct);
}
-int state_backend_bucket_direct_create(struct device_d *dev, const char *path,
+int state_backend_bucket_direct_create(struct device *dev, const char *path,
struct state_backend_storage_bucket **bucket,
- off_t offset, ssize_t max_size)
+ off_t offset, ssize_t max_size, bool readonly)
{
int fd;
struct state_backend_storage_bucket_direct *direct;
- fd = open(path, O_RDWR);
+ fd = open(path, readonly ? O_RDONLY : O_RDWR);
if (fd < 0) {
dev_err(dev, "Failed to open file '%s', %d\n", path, -errno);
return -errno;
diff --git a/common/state/backend_format_dtb.c b/common/state/backend_format_dtb.c
index d0fc948859..b41b896aac 100644
--- a/common/state/backend_format_dtb.c
+++ b/common/state/backend_format_dtb.c
@@ -28,7 +28,7 @@ struct state_backend_format_dtb {
struct device_node *root;
/* For outputs */
- struct device_d *dev;
+ struct device *dev;
};
static inline struct state_backend_format_dtb *get_format_dtb(struct
@@ -131,7 +131,7 @@ static void state_backend_format_dtb_free(struct state_backend_format *format)
}
int backend_format_dtb_create(struct state_backend_format **format,
- struct device_d *dev)
+ struct device *dev)
{
struct state_backend_format_dtb *dtb;
diff --git a/common/state/backend_format_raw.c b/common/state/backend_format_raw.c
index 7835f977c9..105f7dd444 100644
--- a/common/state/backend_format_raw.c
+++ b/common/state/backend_format_raw.c
@@ -32,7 +32,7 @@ struct state_backend_format_raw {
unsigned int digest_length;
/* For outputs */
- struct device_d *dev;
+ struct device *dev;
char *secret_name;
int needs_secret;
@@ -299,7 +299,7 @@ static int backend_format_raw_init_digest(struct state_backend_format_raw *raw,
int backend_format_raw_create(struct state_backend_format **format,
struct device_node *node, const char *secret_name,
- struct device_d *dev)
+ struct device *dev)
{
struct state_backend_format_raw *raw;
int ret;
diff --git a/common/state/backend_storage.c b/common/state/backend_storage.c
index c55d22e37f..df81902bf7 100644
--- a/common/state/backend_storage.c
+++ b/common/state/backend_storage.c
@@ -332,7 +332,7 @@ static int state_storage_file_buckets_init(struct state_backend_storage *storage
offset = storage->offset + n * stridesize;
ret = state_backend_bucket_direct_create(storage->dev, storage->path,
&bucket, offset,
- stridesize);
+ stridesize, storage->readonly);
if (ret) {
dev_warn(storage->dev, "Failed to create direct bucket at '%s' offset %lld\n",
storage->path, (long long) offset);
diff --git a/common/state/state.c b/common/state/state.c
index a614c849c7..219309d715 100644
--- a/common/state/state.c
+++ b/common/state/state.c
@@ -21,8 +21,10 @@
#include <fs.h>
#include <crc.h>
#include <init.h>
+#include <block.h>
#include <linux/err.h>
#include <linux/list.h>
+#include <linux/uuid.h>
#include <linux/mtd/mtd-abi.h>
#include <malloc.h>
@@ -333,8 +335,10 @@ static int state_convert_node_variable(struct state *state,
goto out;
return 0;
- out_free:free(name);
- out: return ret;
+out_free:
+ free(name);
+out:
+ return ret;
}
struct device_node *state_to_node(struct state *state,
@@ -361,7 +365,8 @@ struct device_node *state_to_node(struct state *state,
}
return root;
- out: of_delete_node(root);
+out:
+ of_delete_node(root);
return ERR_PTR(ret);
}
@@ -556,12 +561,12 @@ static int of_state_fixup(struct device_node *root, void *ctx)
goto out;
/* delete existing node */
- if (node)
- of_delete_node(node);
+ of_delete_node(node);
return 0;
- out: of_delete_node(new_node);
+out:
+ of_delete_node(new_node);
return ret;
}
@@ -578,6 +583,22 @@ void state_release(struct state *state)
free(state);
}
+#ifdef __BAREBOX__
+static char *cdev_to_devpath(struct cdev *cdev, off_t *offset, size_t *size)
+{
+ /*
+ * We only accept partitions exactly mapping the barebox-state,
+ * but dt-utils may need to set non-zero values here
+ */
+ *offset = 0;
+ *size = 0;
+
+ return basprintf("/dev/%s", cdev->name);
+}
+#endif
+
+static guid_t barebox_state_partition_guid = BAREBOX_STATE_PARTITION_GUID;
+
/*
* state_new_from_node - create a new state instance from a device_node
*
@@ -594,12 +615,13 @@ struct state *state_new_from_node(struct device_node *node, bool readonly)
const char *alias;
uint32_t stridesize;
struct device_node *partition_node;
- off_t offset = 0;
- size_t size = 0;
+ struct cdev *cdev;
+ off_t offset;
+ size_t size;
alias = of_alias_get(node);
if (!alias) {
- pr_err("State node %s does not have an alias in the /aliases/ node\n", node->full_name);
+ pr_err("State node %pOF does not have an alias in the /aliases/ node\n", node);
return ERR_PTR(-EINVAL);
}
@@ -614,15 +636,8 @@ struct state *state_new_from_node(struct device_node *node, bool readonly)
goto out_release_state;
}
-#ifdef __BAREBOX__
- ret = of_partition_ensure_probed(partition_node);
- if (ret)
- goto out_release_state;
-
- ret = of_find_path_by_node(partition_node, &state->backend_path, 0);
-#else
- ret = of_get_devicepath(partition_node, &state->backend_path, &offset, &size);
-#endif
+ cdev = of_cdev_find(partition_node);
+ ret = PTR_ERR_OR_ZERO(cdev);
if (ret) {
if (ret != -EPROBE_DEFER)
dev_err(&state->dev, "state failed to parse path to backend: %s\n",
@@ -630,6 +645,22 @@ struct state *state_new_from_node(struct device_node *node, bool readonly)
goto out_release_state;
}
+ /* Is the backend referencing an on-disk partitionable block device? */
+ if (cdev_is_block_disk(cdev)) {
+ cdev = cdev_find_child_by_gpt_typeuuid(cdev, &barebox_state_partition_guid);
+ if (IS_ERR(cdev)) {
+ ret = -EINVAL;
+ goto out_release_state;
+ }
+
+ pr_debug("%pOF: backend GPT partition looked up via PartitionTypeGUID\n",
+ node);
+ }
+
+ state->backend_path = cdev_to_devpath(cdev, &offset, &size);
+
+ pr_debug("%pOF: backend resolved to %s\n", node, state->backend_path);
+
state->backend_reproducible_name = of_get_reproducible_name(partition_node);
ret = of_property_read_string(node, "backend-type", &backend_type);
@@ -653,14 +684,14 @@ struct state *state_new_from_node(struct device_node *node, bool readonly)
if (ret)
goto out_release_state;
+ if (readonly)
+ state_backend_set_readonly(state);
+
ret = state_storage_init(state, state->backend_path, offset,
size, stridesize, storage_type);
if (ret)
goto out_release_state;
- if (readonly)
- state_backend_set_readonly(state);
-
ret = state_from_node(state, node, 1);
if (ret) {
goto out_release_state;
diff --git a/common/state/state.h b/common/state/state.h
index 0545cf6ac1..f0c5b1de41 100644
--- a/common/state/state.h
+++ b/common/state/state.h
@@ -90,7 +90,7 @@ struct state_backend_storage {
struct list_head buckets;
/* For outputs */
- struct device_d *dev;
+ struct device *dev;
const char *name;
@@ -105,7 +105,7 @@ struct state_backend_storage {
struct state {
struct list_head list; /* Entry to enqueue on list of states */
- struct device_d dev;
+ struct device dev;
char *of_path;
const char *name;
uint32_t magic;
@@ -202,21 +202,21 @@ struct device_node *state_to_node(struct state *state,
enum state_convert conv);
int backend_format_raw_create(struct state_backend_format **format,
struct device_node *node, const char *secret_name,
- struct device_d *dev);
+ struct device *dev);
int backend_format_dtb_create(struct state_backend_format **format,
- struct device_d *dev);
+ struct device *dev);
int state_storage_init(struct state *state, const char *path,
off_t offset, size_t max_size, uint32_t stridesize,
const char *storagetype);
void state_storage_set_readonly(struct state_backend_storage *storage);
void state_add_var(struct state *state, struct state_variable *var);
struct variable_type *state_find_type_by_name(const char *name);
-int state_backend_bucket_circular_create(struct device_d *dev, const char *path,
+int state_backend_bucket_circular_create(struct device *dev, const char *path,
struct state_backend_storage_bucket **bucket,
unsigned int eraseblock,
ssize_t writesize,
struct mtd_info_user *mtd_uinfo);
-int state_backend_bucket_cached_create(struct device_d *dev,
+int state_backend_bucket_cached_create(struct device *dev,
struct state_backend_storage_bucket *raw,
struct state_backend_storage_bucket **out);
struct state_variable *state_find_var(struct state *state, const char *name);
@@ -224,9 +224,9 @@ struct digest *state_backend_format_raw_get_digest(struct state_backend_format
*format);
void state_backend_set_readonly(struct state *state);
void state_storage_free(struct state_backend_storage *storage);
-int state_backend_bucket_direct_create(struct device_d *dev, const char *path,
+int state_backend_bucket_direct_create(struct device *dev, const char *path,
struct state_backend_storage_bucket **bucket,
- off_t offset, ssize_t max_size);
+ off_t offset, ssize_t max_size, bool readonly);
int state_storage_write(struct state_backend_storage *storage,
const void * buf, ssize_t len);
int state_storage_read(struct state_backend_storage *storage,
diff --git a/common/state/state_variables.c b/common/state/state_variables.c
index f112c60bf6..77946206cd 100644
--- a/common/state/state_variables.c
+++ b/common/state/state_variables.c
@@ -180,6 +180,8 @@ static int state_enum32_export(struct state_variable *var,
str += sprintf(str, "%s", enum32->names[i]) + 1;
ret = of_set_property(node, "names", prop, len, 1);
+ if (ret)
+ return ret;
free(prop);
@@ -261,7 +263,8 @@ static struct state_variable *state_enum32_create(struct state *state,
}
return &enum32->var;
- out: for (i--; i >= 0; i--)
+out:
+ for (i--; i >= 0; i--)
free((char *)enum32->names[i]);
free(enum32->names);
free(enum32);
@@ -327,7 +330,8 @@ static struct state_variable *state_mac_create(struct state *state,
}
return &mac->var;
- out: free(mac);
+out:
+ free(mac);
return ERR_PTR(ret);
}
@@ -442,7 +446,8 @@ static struct state_variable *state_string_create(struct state *state,
}
return &string->var;
- out: free(string);
+out:
+ free(string);
return ERR_PTR(ret);
}