summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Pargmann <mpa@pengutronix.de>2016-07-05 12:37:36 +0200
committerMarkus Pargmann <mpa@pengutronix.de>2016-07-05 16:05:21 +0200
commit2839d4f6f4fe6908cd41976807261ec760490499 (patch)
tree5444c351ab2e00d19bd7be066630fbe80c0fc1e6
parent10c085e428ab5497166142cbd57de2b52cccc2e5 (diff)
downloaddt-utils-2839d4f6f4fe6908cd41976807261ec760490499.tar.gz
dt-utils-2839d4f6f4fe6908cd41976807261ec760490499.tar.xz
Update barebox-state
Fixed direct bucket Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
-rw-r--r--Makefile.am2
-rw-r--r--src/barebox-state.c8
-rw-r--r--src/barebox-state/backend.c31
-rw-r--r--src/barebox-state/backend_bucket_cached.c155
-rw-r--r--src/barebox-state/backend_bucket_circular.c117
-rw-r--r--src/barebox-state/backend_format_raw.c2
-rw-r--r--src/barebox-state/backend_storage.c65
-rw-r--r--src/barebox-state/state.c31
-rw-r--r--src/barebox-state/state.h16
-rw-r--r--src/crc.h1
-rw-r--r--src/dt/common.h16
-rw-r--r--src/state.h2
12 files changed, 305 insertions, 141 deletions
diff --git a/Makefile.am b/Makefile.am
index a8dcd18..62979fa 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -53,6 +53,7 @@ barebox_state_SOURCES = \
src/base64.c \
src/barebox-state/backend_bucket_circular.c \
src/barebox-state/backend_bucket_direct.c \
+ src/barebox-state/backend_bucket_cached.c \
src/barebox-state/backend.c \
src/barebox-state/backend_format_dtb.c \
src/barebox-state/backend_format_raw.c \
@@ -82,6 +83,7 @@ barebox_state_SOURCES = \
src/libbb.h \
src/fdt.h \
src/of.h \
+ src/crc.h \
src/mtd/mtd-peb.h \
src/driver.h
barebox_state_CFLAGS = $(LIBDT_CFLAGS)
diff --git a/src/barebox-state.c b/src/barebox-state.c
index 2bfd85c..36da8fa 100644
--- a/src/barebox-state.c
+++ b/src/barebox-state.c
@@ -309,7 +309,7 @@ static int state_set_var(struct state *state, const char *var, const char *val)
}
-struct state *state_get(const char *name)
+struct state *state_get(const char *name, bool readonly)
{
struct device_node *root, *node, *partition_node;
char *path;
@@ -363,7 +363,7 @@ struct state *state_get(const char *name)
return ERR_PTR(ret);
}
- state = state_new_from_node(node, devpath, offset, size);
+ state = state_new_from_node(node, devpath, offset, size, readonly);
if (IS_ERR(state)) {
fprintf(stderr, "unable to initlialize state: %s\n",
strerror(PTR_ERR(state)));
@@ -421,6 +421,7 @@ int main(int argc, char *argv[])
struct list_head sg_list;
char *statename = NULL;
int lock_fd;
+ bool readonly = true;
INIT_LIST_HEAD(&sg_list);
@@ -443,6 +444,7 @@ int main(int argc, char *argv[])
sg->get = 0;
sg->arg = optarg;
list_add_tail(&sg->list, &sg_list);
+ readonly = false;
break;
case 'd':
do_dump = 1;
@@ -472,7 +474,7 @@ int main(int argc, char *argv[])
exit(1);
}
- state = state_get(statename);
+ state = state_get(statename, readonly);
if (IS_ERR(state)) {
ret = 1;
goto out_unlock;
diff --git a/src/barebox-state/backend.c b/src/barebox-state/backend.c
index 054f8d6..2f2e6df 100644
--- a/src/barebox-state/backend.c
+++ b/src/barebox-state/backend.c
@@ -153,8 +153,6 @@ int state_backend_init(struct state_backend *backend, struct device_d *dev,
char *of_path, off_t offset, size_t max_size,
uint32_t stridesize, const char *storagetype)
{
- struct state_backend_storage_bucket *bucket;
- struct state_backend_storage_bucket *bucket_tmp;
int ret;
ret = state_format_init(backend, dev, backend_format, node, state_name);
@@ -166,34 +164,10 @@ int state_backend_init(struct state_backend *backend, struct device_d *dev,
if (ret)
goto out_free_format;
- list_for_each_entry_safe(bucket, bucket_tmp, &backend->storage.buckets,
- bucket_list) {
- if (!bucket->init)
- continue;
-
- ret = bucket->init(bucket);
- if (ret) {
- dev_warn(dev, "Bucket init failed, state degraded, %d\n",
- ret);
- list_del(&bucket->bucket_list);
- bucket->free(bucket);
- continue;
- }
- }
-
- if (list_empty(&backend->storage.buckets)) {
- dev_err(dev, "Failed to initialize any state bucket\n");
- ret = -EIO;
- goto out_free_storage;
- }
-
-
backend->of_path = of_path;
return 0;
-out_free_storage:
- state_storage_free(&backend->storage);
out_free_format:
state_format_free(backend->format);
backend->format = NULL;
@@ -201,6 +175,11 @@ out_free_format:
return ret;
}
+void state_backend_set_readonly(struct state_backend *backend)
+{
+ state_storage_set_readonly(&backend->storage);
+}
+
void state_backend_free(struct state_backend *backend)
{
state_storage_free(&backend->storage);
diff --git a/src/barebox-state/backend_bucket_cached.c b/src/barebox-state/backend_bucket_cached.c
new file mode 100644
index 0000000..781ac2d
--- /dev/null
+++ b/src/barebox-state/backend_bucket_cached.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2016 Pengutronix, Markus Pargmann <mpa@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include "state.h"
+
+struct state_backend_storage_bucket_cache {
+ struct state_backend_storage_bucket bucket;
+
+ struct state_backend_storage_bucket *raw;
+
+ u8 *data;
+ ssize_t data_len;
+ bool force_write;
+
+ /* For outputs */
+ struct device_d *dev;
+};
+
+static inline struct state_backend_storage_bucket_cache
+ *get_bucket_cache(struct state_backend_storage_bucket *bucket)
+{
+ return container_of(bucket,
+ struct state_backend_storage_bucket_cache,
+ bucket);
+}
+
+static inline void state_backend_bucket_cache_drop(
+ struct state_backend_storage_bucket_cache *cache)
+{
+ if (cache->data) {
+ free(cache->data);
+ cache->data = NULL;
+ cache->data_len = 0;
+ }
+}
+
+static int state_backend_bucket_cache_fill(
+ struct state_backend_storage_bucket_cache *cache)
+{
+ int ret;
+
+ ret = cache->raw->read(cache->raw, &cache->data, &cache->data_len);
+ if (ret == -EUCLEAN)
+ cache->force_write = true;
+ else if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int state_backend_bucket_cache_read(struct state_backend_storage_bucket *bucket,
+ uint8_t ** buf_out,
+ ssize_t * len_hint)
+{
+ struct state_backend_storage_bucket_cache *cache =
+ get_bucket_cache(bucket);
+ int ret;
+
+ if (!cache->data) {
+ ret = state_backend_bucket_cache_fill(cache);
+ if (ret)
+ return ret;
+ }
+
+ if (cache->data) {
+ *buf_out = xmemdup(cache->data, cache->data_len);
+ if (!*buf_out)
+ return -ENOMEM;
+ *len_hint = cache->data_len;
+ }
+
+ return 0;
+}
+
+static int state_backend_bucket_cache_write(struct state_backend_storage_bucket *bucket,
+ const uint8_t * buf, ssize_t len)
+{
+ struct state_backend_storage_bucket_cache *cache =
+ get_bucket_cache(bucket);
+ int ret;
+
+ if (!cache->force_write) {
+ if (!cache->data)
+ ret = state_backend_bucket_cache_fill(cache);
+
+ if (cache->data_len == len && !memcmp(cache->data, buf, len))
+ return 0;
+ }
+
+ state_backend_bucket_cache_drop(cache);
+
+ ret = cache->raw->write(cache->raw, buf, len);
+ if (ret)
+ return ret;
+
+ cache->data = xmemdup(buf, len);
+ cache->data_len = len;
+ return 0;
+}
+
+static int state_backend_bucket_cache_init(
+ struct state_backend_storage_bucket *bucket)
+{
+ struct state_backend_storage_bucket_cache *cache =
+ get_bucket_cache(bucket);
+
+ if (cache->raw->init) {
+ return cache->raw->init(cache->raw);
+ }
+
+ return 0;
+}
+
+static void state_backend_bucket_cache_free(
+ struct state_backend_storage_bucket *bucket)
+{
+ struct state_backend_storage_bucket_cache *cache =
+ get_bucket_cache(bucket);
+
+ state_backend_bucket_cache_drop(cache);
+ cache->raw->free(cache->raw);
+ free(cache);
+}
+
+int state_backend_bucket_cached_create(struct device_d *dev,
+ struct state_backend_storage_bucket *raw,
+ struct state_backend_storage_bucket **out)
+{
+ struct state_backend_storage_bucket_cache *cache;
+
+ cache = xzalloc(sizeof(*cache));
+ cache->raw = raw;
+ cache->dev = dev;
+
+ cache->bucket.free = state_backend_bucket_cache_free;
+ cache->bucket.read = state_backend_bucket_cache_read;
+ cache->bucket.write = state_backend_bucket_cache_write;
+ cache->bucket.init = state_backend_bucket_cache_init;
+
+ *out = &cache->bucket;
+
+ return 0;
+}
diff --git a/src/barebox-state/backend_bucket_circular.c b/src/barebox-state/backend_bucket_circular.c
index 64e9be2..72e165e 100644
--- a/src/barebox-state/backend_bucket_circular.c
+++ b/src/barebox-state/backend_bucket_circular.c
@@ -43,12 +43,6 @@ struct state_backend_storage_bucket_circular {
int fd;
#endif
- /* Cached data of the last read/write */
- u8 *current_data;
- ssize_t current_data_len;
-
- bool force_rewrite; /* In case of degradation, force a rewrite */
-
/* For outputs */
struct device_d *dev;
};
@@ -92,21 +86,19 @@ static int state_mtd_peb_read(struct state_backend_storage_bucket_circular *circ
* behind this area
*/
memset(buf, 0, len);
- circ->force_rewrite = true;
+ ret = -EUCLEAN;
circ->write_area = 0;
dev_dbg(circ->dev, "PEB %u has ECC error, forcing rewrite\n",
circ->eraseblock);
} else if (ret == -EUCLEAN) {
- circ->force_rewrite = true;
dev_dbg(circ->dev, "PEB %u is unclean, forcing rewrite\n",
circ->eraseblock);
} else if (ret < 0) {
dev_err(circ->dev, "Failed to read PEB %u, %d\n",
circ->eraseblock, ret);
- return ret;
}
- return 0;
+ return ret;
}
static int state_mtd_peb_write(struct state_backend_storage_bucket_circular *circ,
@@ -126,14 +118,13 @@ static int state_mtd_peb_write(struct state_backend_storage_bucket_circular *cir
ret);
return ret;
}
- circ->force_rewrite = true;
+ ret = -EUCLEAN;
} else if (ret < 0 && ret != -EUCLEAN) {
dev_err(circ->dev, "Failed to write PEB %u, %d\n",
circ->eraseblock, ret);
- return ret;
}
- return 0;
+ return ret;
}
static int state_mtd_peb_erase(struct state_backend_storage_bucket_circular *circ)
@@ -181,16 +172,16 @@ static int state_mtd_peb_read(struct state_backend_storage_bucket_circular *circ
return 0;
if (stat2.failed - stat1.failed > 0) {
- circ->force_rewrite = true;
+ ret = -EUCLEAN;
dev_dbg(circ->dev, "PEB %u has ECC error, forcing rewrite\n",
circ->eraseblock);
} else if (stat2.corrected - stat1.corrected > 0) {
- circ->force_rewrite = true;
+ ret = -EUCLEAN;
dev_dbg(circ->dev, "PEB %u is unclean, forcing rewrite\n",
circ->eraseblock);
}
- return 0;
+ return ret;
}
static int state_mtd_peb_write(struct state_backend_storage_bucket_circular *circ,
@@ -234,8 +225,9 @@ static int state_mtd_peb_erase(struct state_backend_storage_bucket_circular *cir
}
#endif
-static int state_backend_bucket_circular_fill_cache(
- struct state_backend_storage_bucket *bucket)
+static int state_backend_bucket_circular_read(struct state_backend_storage_bucket *bucket,
+ uint8_t ** buf_out,
+ ssize_t * len_hint)
{
struct state_backend_storage_bucket_circular *circ =
get_bucket_circular(bucket);
@@ -282,44 +274,17 @@ static int state_backend_bucket_circular_fill_cache(
circ->eraseblock, offset, read_len);
ret = state_mtd_peb_read(circ, buf, offset, read_len);
- if (ret < 0) {
+ if (ret < 0 && ret != -EUCLEAN) {
dev_err(circ->dev, "Failed to read circular storage len %zd, %d\n",
read_len, ret);
free(buf);
return ret;
}
- circ->current_data = buf;
- circ->current_data_len = read_len;
-
- return 0;
-}
-
-static int state_backend_bucket_circular_read(struct state_backend_storage_bucket *bucket,
- uint8_t ** buf_out,
- ssize_t * len_hint)
-{
- struct state_backend_storage_bucket_circular *circ =
- get_bucket_circular(bucket);
- int ret;
+ *buf_out = buf;
+ *len_hint = read_len - sizeof(struct state_backend_storage_bucket_circular_meta);
- if (!circ->current_data) {
- ret = state_backend_bucket_circular_fill_cache(bucket);
- if (ret)
- return ret;
- }
-
- /*
- * We keep the internal copy in the cache and duplicate the data for
- * external use
- */
- *buf_out = xmemdup(circ->current_data, circ->current_data_len);
- if (!*buf_out)
- return -ENOMEM;
-
- *len_hint = circ->current_data_len - sizeof(struct state_backend_storage_bucket_circular_meta);
-
- return 0;
+ return ret;
}
static int state_backend_bucket_circular_write(struct state_backend_storage_bucket *bucket,
@@ -354,31 +319,6 @@ static int state_backend_bucket_circular_write(struct state_backend_storage_buck
meta->magic = circular_magic;
meta->written_length = written_length;
- /* Nothing in cache? Then read to see what is on the device currently */
- if (!circ->current_data) {
- state_backend_bucket_circular_fill_cache(bucket);
- }
-
- /*
- * If we would write the same data that is currently on the device, we
- * can return successfully without writing.
- * Note that the cache may still be empty if the storage is empty or
- * errors occured.
- */
- if (circ->current_data) {
- dev_dbg(circ->dev, "Comparing cached data, writing %zd bytes, cached %zd bytes\n",
- written_length, circ->current_data_len);
- if (!circ->force_rewrite &&
- written_length == circ->current_data_len &&
- !memcmp(circ->current_data, write_buf, written_length)) {
- dev_dbg(circ->dev, "Data already on device, not writing again\n");
- goto out_free;
- } else {
- free(circ->current_data);
- circ->current_data = NULL;
- }
- }
-
if (circ->write_area + written_length >= circ->max_size) {
circ->write_area = 0;
}
@@ -408,7 +348,7 @@ static int state_backend_bucket_circular_write(struct state_backend_storage_buck
circ->write_area += written_length;
ret = state_mtd_peb_write(circ, write_buf, offset, written_length);
- if (ret < 0) {
+ if (ret < 0 && ret != -EUCLEAN) {
dev_err(circ->dev, "Failed to write circular to %ld length %zd, %d\n",
offset, written_length, ret);
goto out_free;
@@ -417,17 +357,9 @@ static int state_backend_bucket_circular_write(struct state_backend_storage_buck
dev_dbg(circ->dev, "Written state to PEB %u offset %ld length %zd data length %zd\n",
circ->eraseblock, offset, written_length, len);
- /* Put written data into the cache */
- WARN_ON(circ->current_data);
- circ->current_data = write_buf;
- circ->current_data_len = written_length;
- write_buf = NULL;
- circ->force_rewrite = false;
-
out_free:
- if (write_buf)
- free(write_buf);
- return 0;
+ free(write_buf);
+ return ret;
}
/**
@@ -492,8 +424,6 @@ static void state_backend_bucket_circular_free(struct
struct state_backend_storage_bucket_circular *circ =
get_bucket_circular(bucket);
- if (circ->current_data)
- free(circ->current_data);
free(circ);
}
@@ -528,7 +458,8 @@ int state_backend_bucket_circular_create(struct device_d *dev, const char *path,
struct state_backend_storage_bucket **bucket,
unsigned int eraseblock,
ssize_t writesize,
- struct mtd_info_user *mtd_uinfo)
+ struct mtd_info_user *mtd_uinfo,
+ bool lazy_init)
{
struct state_backend_storage_bucket_circular *circ;
int ret;
@@ -564,9 +495,13 @@ int state_backend_bucket_circular_create(struct device_d *dev, const char *path,
circ->bucket.free = state_backend_bucket_circular_free;
*bucket = &circ->bucket;
- ret = state_backend_bucket_circular_init(*bucket);
- if (ret)
- goto out_free;
+ if (!lazy_init) {
+ ret = state_backend_bucket_circular_init(*bucket);
+ if (ret)
+ goto out_free;
+ } else {
+ circ->bucket.init = state_backend_bucket_circular_init;
+ }
return 0;
diff --git a/src/barebox-state/backend_format_raw.c b/src/barebox-state/backend_format_raw.c
index ad55b9f..4209424 100644
--- a/src/barebox-state/backend_format_raw.c
+++ b/src/barebox-state/backend_format_raw.c
@@ -21,7 +21,9 @@
#include <digest.h>
#include <linux/kernel.h>
#include <malloc.h>
+#include <crc.h>
#include <of.h>
+#include <crc.h>
#include "state.h"
diff --git a/src/barebox-state/backend_storage.c b/src/barebox-state/backend_storage.c
index 4620eda..6b9d86b 100644
--- a/src/barebox-state/backend_storage.c
+++ b/src/barebox-state/backend_storage.c
@@ -27,6 +27,23 @@
const unsigned int min_copies_written = 1;
+static int bucket_lazy_init(struct state_backend_storage_bucket *bucket)
+{
+ int ret;
+
+ if (bucket->initialized)
+ return 0;
+
+ if (bucket->init) {
+ ret = bucket->init(bucket);
+ if (ret)
+ return ret;
+ }
+ bucket->initialized = true;
+
+ return 0;
+}
+
/**
* state_storage_write - Writes the given data to the storage
* @param storage Storage object
@@ -48,9 +65,19 @@ int state_storage_write(struct state_backend_storage *storage,
int ret;
int copies_written = 0;
+ if (storage->readonly)
+ return 0;
+
list_for_each_entry(bucket, &storage->buckets, bucket_list) {
- ret = bucket->write(bucket, buf, len);
+ ret = bucket_lazy_init(bucket);
if (ret) {
+ dev_warn(storage->dev, "Failed to init bucket/write state backend bucket, %d\n",
+ ret);
+ continue;
+ }
+
+ ret = bucket->write(bucket, buf, len);
+ if (ret < 0) {
dev_warn(storage->dev, "Failed to write state backend bucket, %d\n",
ret);
} else {
@@ -78,9 +105,8 @@ int state_storage_write(struct state_backend_storage *storage,
* to all buckets. Bucket implementations that need to keep the number of writes
* low, can read their own copy first and compare it.
*/
-int state_storage_restore_consistency(struct state_backend_storage
- *storage, const uint8_t * buf,
- ssize_t len)
+int state_storage_restore_consistency(struct state_backend_storage *storage,
+ const uint8_t * buf, ssize_t len)
{
return state_storage_write(storage, buf, len);
}
@@ -111,6 +137,13 @@ int state_storage_read(struct state_backend_storage *storage,
list_for_each_entry(bucket, &storage->buckets, bucket_list) {
*len = len_hint;
+ ret = bucket_lazy_init(bucket);
+ if (ret) {
+ dev_warn(storage->dev, "Failed to init bucket/read state backend bucket, %d\n",
+ ret);
+ continue;
+ }
+
ret = bucket->read(bucket, buf, len);
if (ret) {
dev_warn(storage->dev, "Failed to read from state backend bucket, trying next, %d\n",
@@ -250,6 +283,7 @@ static int state_storage_mtd_buckets_init(struct state_backend_storage *storage,
int ret;
ssize_t writesize = meminfo->writesize;
unsigned int eraseblock = offset / meminfo->erasesize;
+ bool lazy_init = true;
if (non_circular)
writesize = meminfo->erasesize;
@@ -258,13 +292,21 @@ static int state_storage_mtd_buckets_init(struct state_backend_storage *storage,
&bucket,
eraseblock,
writesize,
- meminfo);
+ meminfo,
+ lazy_init);
if (ret) {
dev_warn(storage->dev, "Failed to create bucket at '%s' eraseblock %u\n",
path, eraseblock);
continue;
}
+ ret = state_backend_bucket_cached_create(storage->dev, bucket,
+ &bucket);
+ if (ret) {
+ dev_warn(storage->dev, "Failed to setup cache bucket, continuing without cache, %d\n",
+ ret);
+ }
+
list_add_tail(&bucket->bucket_list, &storage->buckets);
++nr_copies;
if (nr_copies >= desired_copies)
@@ -387,6 +429,13 @@ static int state_storage_file_buckets_init(struct state_backend_storage *storage
continue;
}
+ ret = state_backend_bucket_cached_create(storage->dev, bucket,
+ &bucket);
+ if (ret) {
+ dev_warn(storage->dev, "Failed to setup cache bucket, continuing without cache, %d\n",
+ ret);
+ }
+
list_add_tail(&bucket->bucket_list, &storage->buckets);
++nr_copies;
if (nr_copies >= desired_copies)
@@ -428,6 +477,7 @@ int state_storage_init(struct state_backend_storage *storage,
INIT_LIST_HEAD(&storage->buckets);
storage->dev = dev;
storage->name = storagetype;
+ storage->stridesize = stridesize;
ret = mtd_get_meminfo(path, &meminfo);
if (!ret && !(meminfo.flags & MTD_NO_ERASE)) {
@@ -450,6 +500,11 @@ int state_storage_init(struct state_backend_storage *storage,
dev_err(storage->dev, "storage init done\n");
}
+void state_storage_set_readonly(struct state_backend_storage *storage)
+{
+ storage->readonly = true;
+}
+
/**
* state_storage_free - Free backend storage
* @param storage Storage object
diff --git a/src/barebox-state/state.c b/src/barebox-state/state.c
index 5e2625e..28cfb83 100644
--- a/src/barebox-state/state.c
+++ b/src/barebox-state/state.c
@@ -19,6 +19,7 @@
#include <digest.h>
#include <errno.h>
#include <fs.h>
+#include <crc.h>
#include <linux/err.h>
#include <linux/list.h>
@@ -66,10 +67,6 @@ static struct state *state_new(const char *name)
return state;
}
-#ifndef __BAREBOX__
-#define asprintf(fmt, arg...) barebox_asprintf(fmt, ##arg)
-#endif
-
static int state_convert_node_variable(struct state *state,
struct device_node *node,
struct device_node *parent,
@@ -92,8 +89,8 @@ static int state_convert_node_variable(struct state *state,
*indexs = 0;
/* construct full name */
- name = asprintf("%s%s%s", parent_name, parent_name[0] ? "." : "",
- short_name);
+ name = basprintf("%s%s%s", parent_name, parent_name[0] ? "." : "",
+ short_name);
free(short_name);
if ((conv == STATE_CONVERT_TO_NODE) || (conv == STATE_CONVERT_FIXUP))
@@ -380,6 +377,13 @@ static int of_state_fixup(struct device_node *root, void *ctx)
}
}
+ if (state->backend.storage.stridesize) {
+ ret = of_property_write_u32(new_node, "backend-stridesize",
+ state->backend.storage.stridesize);
+ if (ret)
+ goto out;
+ }
+
/* address-cells + size-cells */
ret = of_property_write_u32(new_node, "#address-cells", 1);
if (ret)
@@ -417,9 +421,11 @@ void state_release(struct state *state)
* @offset Offset in the device path. May be 0 to start at the beginning.
* @max_size Maximum size of the area used. This may be 0 to use the full
* size.
+ * @readonly This is a read-only state. Note that with this option set,
+ * there are no repairs done.
*/
struct state *state_new_from_node(struct device_node *node, char *path,
- off_t offset, size_t max_size)
+ off_t offset, size_t max_size, bool readonly)
{
struct state *state;
int ret = 0;
@@ -459,7 +465,7 @@ struct state *state_new_from_node(struct device_node *node, char *path,
ret = of_find_path_by_node(partition_node, &path, 0);
}
if (!path) {
- pr_err("state failed to parse path to backend\n");
+ dev_err(&state->dev, "state failed to parse path to backend\n");
ret = -EINVAL;
goto out_release_state;
}
@@ -479,7 +485,7 @@ struct state *state_new_from_node(struct device_node *node, char *path,
&storage_type);
if (ret) {
storage_type = NULL;
- pr_info("No backend-storage-type found, using default.\n");
+ dev_info(&state->dev, "No backend-storage-type found, using default.\n");
}
ret = state_backend_init(&state->backend, &state->dev, node,
@@ -488,6 +494,9 @@ struct state *state_new_from_node(struct device_node *node, char *path,
if (ret)
goto out_release_state;
+ if (readonly)
+ state_backend_set_readonly(&state->backend);
+
ret = state_from_node(state, node, 1);
if (ret) {
goto out_release_state;
@@ -500,11 +509,11 @@ struct state *state_new_from_node(struct device_node *node, char *path,
ret = state_load(state);
if (ret) {
- pr_warn("Failed to load persistent state, continuing with defaults, %d\n", ret);
+ dev_warn(&state->dev, "Failed to load persistent state, continuing with defaults, %d\n", ret);
state->state_default = 1;
}
- pr_info("New state registered '%s'\n", alias);
+ dev_info(&state->dev, "New state registered '%s'\n", alias);
return state;
diff --git a/src/barebox-state/state.h b/src/barebox-state/state.h
index 2226356..48a6785 100644
--- a/src/barebox-state/state.h
+++ b/src/barebox-state/state.h
@@ -27,6 +27,7 @@ struct state_backend_storage_bucket {
uint8_t ** buf, ssize_t * len_hint);
void (*free) (struct state_backend_storage_bucket * bucket);
+ bool initialized;
struct list_head bucket_list;
};
@@ -70,6 +71,9 @@ struct state_backend_storage {
struct device_d *dev;
const char *name;
+ uint32_t stridesize;
+
+ bool readonly;
};
/**
@@ -200,13 +204,18 @@ int state_storage_init(struct state_backend_storage *storage,
struct device_d *dev, 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,
- struct state_backend_storage_bucket
- **bucket, unsigned int eraseblock,
+ struct state_backend_storage_bucket **bucket,
+ unsigned int eraseblock,
ssize_t writesize,
- struct mtd_info_user *mtd_uinfo);
+ struct mtd_info_user *mtd_uinfo,
+ bool lazy_init);
+int state_backend_bucket_cached_create(struct device_d *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);
struct digest *state_backend_format_raw_get_digest(struct state_backend_format
*format);
@@ -215,6 +224,7 @@ int state_backend_init(struct state_backend *backend, struct device_d *dev,
const char *storage_path, const char *state_name, const
char *of_path, off_t offset, size_t max_size,
uint32_t stridesize, const char *storagetype);
+void state_backend_set_readonly(struct state_backend *backend);
void state_backend_free(struct state_backend *backend);
void state_storage_free(struct state_backend_storage *storage);
int state_backend_bucket_direct_create(struct device_d *dev, const char *path,
diff --git a/src/crc.h b/src/crc.h
new file mode 100644
index 0000000..40a8c17
--- /dev/null
+++ b/src/crc.h
@@ -0,0 +1 @@
+/* empty */
diff --git a/src/dt/common.h b/src/dt/common.h
index f903176..2c45c11 100644
--- a/src/dt/common.h
+++ b/src/dt/common.h
@@ -153,6 +153,8 @@ static inline char *barebox_asprintf(const char *fmt, ...)
return ret == -1 ? NULL : p;
}
+#define basprintf(fmt, arg...) barebox_asprintf(fmt, ##arg)
+
/**
* strlcpy - Copy a %NUL terminated string into a sized buffer
* @dest: Where to copy the string to
@@ -579,7 +581,19 @@ static inline __u32 ror32(__u32 word, unsigned int shift)
uint32_t crc32(uint32_t crc, const void *_buf, unsigned int len);
uint32_t crc32_no_comp(uint32_t crc, const void *_buf, unsigned int len);
-#define flush(fd) fsync(fd)
+static inline int flush(int fd)
+{
+ int ret;
+
+ ret = fsync(fd);
+ if (!ret)
+ return 0;
+
+ if (errno == EINVAL)
+ return 0;
+
+ return -errno;
+}
static inline int mtd_buf_all_ff(const void *buf, unsigned int len)
{
diff --git a/src/state.h b/src/state.h
index 48c60ea..bc9a574 100644
--- a/src/state.h
+++ b/src/state.h
@@ -11,7 +11,7 @@ int state_backend_raw_file(struct state *state, const char *of_path,
const char *path, off_t offset, size_t size);
struct state *state_new_from_node(struct device_node *node, char *path,
- off_t offset, size_t max_size);
+ off_t offset, size_t max_size, bool readonly);
void state_release(struct state *state);
struct state *state_by_name(const char *name);