summaryrefslogtreecommitdiffstats
path: root/common/state/state.h
diff options
context:
space:
mode:
Diffstat (limited to 'common/state/state.h')
-rw-r--r--common/state/state.h275
1 files changed, 275 insertions, 0 deletions
diff --git a/common/state/state.h b/common/state/state.h
new file mode 100644
index 0000000..cd54767
--- /dev/null
+++ b/common/state/state.h
@@ -0,0 +1,275 @@
+#include <linux/types.h>
+#include <linux/list.h>
+#include <driver.h>
+
+struct state;
+struct mtd_info_user;
+
+/**
+ * state_backend_storage_bucket - This class describes a single backend storage
+ * object copy
+ *
+ * @init Optional, initiates the given bucket
+ * @write Required, writes the given data to the storage in any form. Returns 0
+ * on success
+ * @read Required, reads the last successfully written data from the backend
+ * storage. Returns 0 on success and allocates a matching memory area to buf.
+ * len_hint can be a hint of the storage format how large the data to be read
+ * is. After the operation len_hint contains the size of the allocated buffer.
+ * @free Required, Frees all internally used memory
+ * @bucket_list A list element struct to attach this bucket to a list
+ */
+struct state_backend_storage_bucket {
+ int (*init) (struct state_backend_storage_bucket * bucket);
+ int (*write) (struct state_backend_storage_bucket * bucket,
+ const uint8_t * buf, ssize_t len);
+ int (*read) (struct state_backend_storage_bucket * bucket,
+ uint8_t ** buf, ssize_t * len_hint);
+ void (*free) (struct state_backend_storage_bucket * bucket);
+
+ bool initialized;
+ struct list_head bucket_list;
+};
+
+/**
+ * state_backend_format - This class describes a data format.
+ *
+ * @verify Required, Verifies the validity of the given data. The buffer that is
+ * passed into this function may be larger than the actual data in the buffer.
+ * The magic is supplied by the state to verify that this is an expected state
+ * entity. The function should return 0 on success or a negative errno otherwise.
+ * @pack Required, Packs data from the given state into a newly created buffer.
+ * The buffer and its length are stored in the given argument pointers. Returns
+ * 0 on success, -errno otherwise.
+ * @unpack Required, Unpacks the data from the given buffer into the state. Do
+ * not free the buffer.
+ * @free Optional, Frees all allocated memory and structures.
+ * @name Name of this backend.
+ */
+struct state_backend_format {
+ int (*verify) (struct state_backend_format * format, uint32_t magic,
+ const uint8_t * buf, ssize_t len);
+ int (*pack) (struct state_backend_format * format, struct state * state,
+ uint8_t ** buf, ssize_t * len);
+ int (*unpack) (struct state_backend_format * format,
+ struct state * state, const uint8_t * buf, ssize_t len);
+ ssize_t(*get_packed_len) (struct state_backend_format * format,
+ struct state * state);
+ void (*free) (struct state_backend_format * format);
+ const char *name;
+};
+
+/**
+ * state_backend_storage - Storage backend of the state.
+ *
+ * @buckets List of storage buckets that are available
+ */
+struct state_backend_storage {
+ struct list_head buckets;
+
+ /* For outputs */
+ struct device_d *dev;
+
+ const char *name;
+
+ bool readonly;
+};
+
+/**
+ * state_backend - State Backend object
+ *
+ * @format Backend format object
+ * @storage Backend storage object
+ * @of_path Path to the DT node
+ */
+struct state_backend {
+ struct state_backend_format *format;
+ struct state_backend_storage storage;
+ const char *of_path;
+};
+
+struct state {
+ struct list_head list; /* Entry to enqueue on list of states */
+
+ struct device_d dev;
+ struct device_node *root;
+ const char *name;
+ uint32_t magic;
+
+ struct list_head variables; /* Sorted list of variables */
+ unsigned int dirty;
+
+ struct state_backend backend;
+};
+
+enum state_convert {
+ STATE_CONVERT_FROM_NODE,
+ STATE_CONVERT_FROM_NODE_CREATE,
+ STATE_CONVERT_TO_NODE,
+ STATE_CONVERT_FIXUP,
+};
+
+enum state_variable_type {
+ STATE_TYPE_INVALID = 0,
+ STATE_TYPE_ENUM,
+ STATE_TYPE_U8,
+ STATE_TYPE_U32,
+ STATE_TYPE_MAC,
+ STATE_TYPE_STRING,
+};
+
+struct state_variable;
+
+/* A variable type (uint32, enum32) */
+struct variable_type {
+ enum state_variable_type type;
+ const char *type_name;
+ struct list_head list;
+ int (*export) (struct state_variable *, struct device_node *,
+ enum state_convert);
+ int (*import) (struct state_variable *, struct device_node *);
+ struct state_variable *(*create) (struct state * state,
+ const char *name,
+ struct device_node *);
+};
+
+/* instance of a single variable */
+struct state_variable {
+ enum state_variable_type type;
+ struct list_head list;
+ const char *name;
+ unsigned int start;
+ unsigned int size;
+ void *raw;
+};
+
+/*
+ * uint32
+ */
+struct state_uint32 {
+ struct state_variable var;
+ struct param_d *param;
+ struct state *state;
+ uint32_t value;
+ uint32_t value_default;
+};
+
+/*
+ * enum32
+ */
+struct state_enum32 {
+ struct state_variable var;
+ struct param_d *param;
+ uint32_t value;
+ uint32_t value_default;
+ const char **names;
+ int num_names;
+};
+
+/*
+ * MAC address
+ */
+struct state_mac {
+ struct state_variable var;
+ struct param_d *param;
+ uint8_t value[6];
+ uint8_t value_default[6];
+};
+
+/*
+ * string
+ */
+struct state_string {
+ struct state_variable var;
+ struct param_d *param;
+ struct state *state;
+ char *value;
+ const char *value_default;
+ char raw[];
+};
+
+int state_set_dirty(struct param_d *p, void *priv);
+int state_from_node(struct state *state, struct device_node *node, bool create);
+struct device_node *state_to_node(struct state *state,
+ struct device_node *parent,
+ 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);
+int backend_format_dtb_create(struct state_backend_format **format,
+ struct device_d *dev);
+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,
+ ssize_t writesize,
+ 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);
+int state_backend_init(struct state_backend *backend, struct device_d *dev,
+ struct device_node *node, const char *backend_format,
+ 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,
+ struct state_backend_storage_bucket **bucket,
+ off_t offset, ssize_t max_size);
+int state_storage_write(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);
+int state_storage_read(struct state_backend_storage *storage,
+ struct state_backend_format *format,
+ uint32_t magic, uint8_t **buf, ssize_t *len,
+ ssize_t len_hint);
+
+static inline struct state_uint32 *to_state_uint32(struct state_variable *s)
+{
+ return container_of(s, struct state_uint32, var);
+}
+
+static inline struct state_enum32 *to_state_enum32(struct state_variable *s)
+{
+ return container_of(s, struct state_enum32, var);
+}
+
+static inline struct state_mac *to_state_mac(struct state_variable *s)
+{
+ return container_of(s, struct state_mac, var);
+}
+
+static inline struct state_string *to_state_string(struct state_variable *s)
+{
+ return container_of(s, struct state_string, var);
+}
+
+static inline int state_string_copy_to_raw(struct state_string *string,
+ const char *src)
+{
+ size_t len;
+
+ len = strlen(src);
+ if (len > string->var.size)
+ return -EILSEQ;
+
+ /* copy string and clear remaining contents of buffer */
+ memcpy(string->raw, src, len);
+ memset(string->raw + len, 0x0, string->var.size - len);
+
+ return 0;
+}