This is the format that was initially used during development of the state framework. Some early adopters still stick to this one. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx> --- common/state/Makefile | 1 + common/state/backend_format_rawcompat.c | 145 ++++++++++++++++++++++++++++++++ common/state/state.c | 3 + common/state/state.h | 2 + 4 files changed, 151 insertions(+) create mode 100644 common/state/backend_format_rawcompat.c diff --git a/common/state/Makefile b/common/state/Makefile index fcf9add52cbe..e4357e9c209a 100644 --- a/common/state/Makefile +++ b/common/state/Makefile @@ -2,6 +2,7 @@ obj-y += state.o obj-y += state_variables.o obj-y += backend_format_dtb.o obj-y += backend_format_raw.o +obj-y += backend_format_rawcompat.o obj-y += backend_storage.o obj-y += backend_bucket_direct.o obj-$(CONFIG_MTD) += backend_bucket_circular.o diff --git a/common/state/backend_format_rawcompat.c b/common/state/backend_format_rawcompat.c new file mode 100644 index 000000000000..ffc9b4b0554a --- /dev/null +++ b/common/state/backend_format_rawcompat.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2017 Pengutronix, Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx> + * + * 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 <linux/kernel.h> +#include <malloc.h> +#include <crc.h> +#include <asm/unaligned.h> + +#include "state.h" + +struct state_backend_format_rawcompat { + struct state_backend_format format; + + /* For outputs */ + struct device_d *dev; +}; + +static inline struct state_backend_format_rawcompat *get_format_rawcompat( + struct state_backend_format *format) +{ + return container_of(format, struct state_backend_format_rawcompat, format); +} + +static int backend_format_rawcompat_verify(struct state_backend_format *format, + uint32_t magic, const void *buf, + ssize_t *lenp, enum state_flags flags) +{ + uint32_t crc; + uint32_t tmp; + struct state_backend_format_rawcompat *backend = get_format_rawcompat(format); + + tmp = get_unaligned((uint32_t *)buf); + if (magic && magic != tmp) { + dev_err(backend->dev, + "Error, found invalid magic 0x%08x, should be 0x%08x\n", + tmp, magic); + return -EINVAL; + } + + tmp = get_unaligned((uint32_t *)(buf + *lenp - sizeof(uint32_t))); + crc = crc32(0, buf, *lenp - sizeof(uint32_t)); + if (crc != tmp) { + dev_err(backend->dev, + "Error, invalid header crc in rawcompat format, calculated 0x%08x, found 0x%08x\n", + crc, tmp); + return -EINVAL; + } + + return 0; +} + +static int backend_format_rawcompat_unpack(struct state_backend_format *format, + struct state *state, const void *buf, + ssize_t len) +{ + struct state_variable *sv; + const void *data; + struct state_backend_format_rawcompat *backend = get_format_rawcompat(format); + + data = buf + sizeof(uint32_t); + + list_for_each_entry(sv, &state->variables, list) { + if (sv->start + sv->size > len - 8) { + dev_err(backend->dev, "State variable ends behind valid data, %s\n", + sv->name); + continue; + } + memcpy(sv->raw, data + sv->start, sv->size); + } + + return 0; +} + +static int backend_format_rawcompat_pack(struct state_backend_format *format, + struct state *state, void **buf_out, + ssize_t *len_out) +{ + struct state_backend_format_rawcompat *backend = get_format_rawcompat(format); + void *buf, *data; + struct state_variable *sv; + uint32_t crc; + + *len_out = 0; + list_for_each_entry(sv, &state->variables, list) { + if (*len_out < sv->start + sv->size) + *len_out = sv->start + sv->size; + } + + /* for header and crc */ + *len_out += 2 * sizeof(uint32_t); + + buf = xzalloc(*len_out); + + put_unaligned_le32(state->magic, buf); + + data = buf + sizeof(uint32_t); + + list_for_each_entry(sv, &state->variables, list) { + memcpy(data + sv->start, sv->raw, sv->size); + } + + crc = crc32(0, buf, *len_out - sizeof(uint32_t)); + put_unaligned_le32(crc, buf + *len_out - sizeof(uint32_t)); + + *buf_out = buf; + + return 0; +} + +static void backend_format_rawcompat_free(struct state_backend_format *format) +{ + struct state_backend_format_rawcompat *backend = get_format_rawcompat(format); + + free(backend); +} + +int backend_format_rawcompat_create(struct state_backend_format **format, + struct device_node *node, struct device_d *dev) +{ + struct state_backend_format_rawcompat *rawcompat; + + rawcompat = xzalloc(sizeof(*rawcompat)); + + rawcompat->dev = dev; + + rawcompat->format.pack = backend_format_rawcompat_pack; + rawcompat->format.unpack = backend_format_rawcompat_unpack; + rawcompat->format.verify = backend_format_rawcompat_verify; + rawcompat->format.free = backend_format_rawcompat_free; + rawcompat->format.name = "rawcompat"; + *format = &rawcompat->format; + + return 0; +} diff --git a/common/state/state.c b/common/state/state.c index 121ba0c6d34a..c383c529e973 100644 --- a/common/state/state.c +++ b/common/state/state.c @@ -124,6 +124,9 @@ static int state_format_init(struct state *state, const char *backend_format, if (!backend_format || !strcmp(backend_format, "raw")) { ret = backend_format_raw_create(&state->format, node, state_name, &state->dev); + } else if (!strcmp(backend_format, "rawcompat")) { + ret = backend_format_rawcompat_create(&state->format, node, + &state->dev); } else if (!strcmp(backend_format, "dtb")) { ret = backend_format_dtb_create(&state->format, &state->dev); } else { diff --git a/common/state/state.h b/common/state/state.h index 81aaec23b62b..587bc11e4501 100644 --- a/common/state/state.h +++ b/common/state/state.h @@ -188,6 +188,8 @@ struct device_node *state_to_node(struct state *state, int backend_format_raw_create(struct state_backend_format **format, struct device_node *node, const char *secret_name, struct device_d *dev); +int backend_format_rawcompat_create(struct state_backend_format **format, + struct device_node *node, struct device_d *dev); int backend_format_dtb_create(struct state_backend_format **format, struct device_d *dev); int state_storage_init(struct state *state, const char *path, -- 2.11.0 _______________________________________________ barebox mailing list barebox@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/barebox