872e6069d5
Caching pointers to device tree nodes or names is not safe. The barebox internal device tree may be changed by loading a new device tree or through fixup handlers. As a result, the string may be deleted. Use local copies of the full path instead. Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
279 lines
8.3 KiB
C
279 lines
8.3 KiB
C
#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;
|
|
|
|
uint32_t stridesize;
|
|
|
|
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;
|
|
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;
|
|
unsigned int save_on_shutdown;
|
|
|
|
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;
|
|
}
|