diff --git a/Documentation/devicetree/bindings/barebox/barebox,state.rst b/Documentation/devicetree/bindings/barebox/barebox,state.rst index 42b2a34..7156084 100644 --- a/Documentation/devicetree/bindings/barebox/barebox,state.rst +++ b/Documentation/devicetree/bindings/barebox/barebox,state.rst @@ -1,4 +1,6 @@ -barebox,state +.. _barebox,state: + +barebox state ============= Overview diff --git a/arch/arm/crypto/.gitignore b/arch/arm/crypto/.gitignore new file mode 100644 index 0000000..b22a068 --- /dev/null +++ b/arch/arm/crypto/.gitignore @@ -0,0 +1 @@ +/sha256-core.S diff --git a/common/oftree.c b/common/oftree.c index 50fc95b..f75d7b4 100644 --- a/common/oftree.c +++ b/common/oftree.c @@ -160,6 +160,25 @@ } /* + * Remove a previously registered fixup. Only the first (if any) is removed. + * Returns 0 if a match was found (and removed), -ENOENT otherwise. + */ +int of_unregister_fixup(int (*fixup)(struct device_node *, void *), + void *context) +{ + struct of_fixup *of_fixup; + + list_for_each_entry(of_fixup, &of_fixup_list, list) { + if (of_fixup->fixup == fixup && of_fixup->context == context) { + list_del(&of_fixup->list); + return 0; + } + } + + return -ENOENT; +} + +/* * Apply registered fixups for the given fdt. The fdt must have * enough free space to apply the fixups. */ diff --git a/common/state.c b/common/state.c index b677a9f..7076f57 100644 --- a/common/state.c +++ b/common/state.c @@ -54,12 +54,14 @@ int (*load)(struct state_backend *backend, struct state *state); int (*save)(struct state_backend *backend, struct state *state); const char *name; + const char *of_path; const char *path; }; enum state_variable_type { STATE_TYPE_INVALID = 0, STATE_TYPE_ENUM, + STATE_TYPE_U8, STATE_TYPE_U32, STATE_TYPE_MAC, }; @@ -74,12 +76,20 @@ void *raw; }; +enum state_convert { + STATE_CONVERT_FROM_NODE, + STATE_CONVERT_FROM_NODE_CREATE, + STATE_CONVERT_TO_NODE, + STATE_CONVERT_FIXUP, +}; + /* 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 *); + int (*export)(struct state_variable *, struct device_node *, + enum state_convert); int (*import)(struct state_variable *, const struct device_node *); struct state_variable *(*create)(struct state *state, const char *name, struct device_node *); @@ -126,15 +136,15 @@ } static int state_uint32_export(struct state_variable *var, - struct device_node *node) + struct device_node *node, enum state_convert conv) { struct state_uint32 *su32 = to_state_uint32(var); int ret; - if (su32->value_default) { + if (su32->value_default || conv == STATE_CONVERT_FIXUP) { ret = of_property_write_u32(node, "default", su32->value_default); - if (ret) + if (ret || conv == STATE_CONVERT_FIXUP) return ret; } @@ -153,7 +163,7 @@ return 0; } -static struct state_variable *state_uint32_create(struct state *state, +static struct state_variable *state_uint8_create(struct state *state, const char *name, struct device_node *node) { struct state_uint32 *su32; @@ -169,6 +179,32 @@ } su32->param = param; + su32->var.size = sizeof(uint8_t); +#ifdef __LITTLE_ENDIAN + su32->var.raw = &su32->value; +#else + su32->var.raw = &su32->value + 3; +#endif + + return &su32->var; +} + +static struct state_variable *state_uint32_create(struct state *state, + const char *name, struct device_node *node) +{ + struct state_uint32 *su32; + struct param_d *param; + + su32 = xzalloc(sizeof(*su32)); + + param = dev_add_param_int(&state->dev, name, state_set_dirty, + NULL, &su32->value, "%u", state); + if (IS_ERR(param)) { + free(su32); + return ERR_CAST(param); + } + + su32->param = param; su32->var.size = sizeof(uint32_t); su32->var.raw = &su32->value; @@ -193,16 +229,16 @@ } static int state_enum32_export(struct state_variable *var, - struct device_node *node) + struct device_node *node, enum state_convert conv) { struct state_enum32 *enum32 = to_state_enum32(var); int ret, i, len; char *prop, *str; - if (enum32->value_default) { + if (enum32->value_default || conv == STATE_CONVERT_FIXUP) { ret = of_property_write_u32(node, "default", enum32->value_default); - if (ret) + if (ret || conv == STATE_CONVERT_FIXUP) return ret; } @@ -309,14 +345,14 @@ } static int state_mac_export(struct state_variable *var, - struct device_node *node) + struct device_node *node, enum state_convert conv) { struct state_mac *mac = to_state_mac(var); int ret; ret = of_property_write_u8_array(node, "default", mac->value_default, ARRAY_SIZE(mac->value_default)); - if (ret) + if (ret || conv == STATE_CONVERT_FIXUP) return ret; return of_property_write_u8_array(node, "value", mac->value, @@ -363,6 +399,12 @@ static struct variable_type types[] = { { + .type = STATE_TYPE_U8, + .type_name = "uint8", + .export = state_uint32_export, + .import = state_uint32_import, + .create = state_uint8_create, + }, { .type = STATE_TYPE_U32, .type_name = "uint32", .export = state_uint32_export, @@ -426,13 +468,6 @@ return state; } -static void state_release(struct state *state) -{ - list_del(&state->list); - unregister_device(&state->dev); - free(state); -} - static struct state_variable *state_find_var(struct state *state, const char *name) { @@ -446,12 +481,6 @@ return ERR_PTR(-ENOENT); } -enum state_convert { - STATE_CONVERT_FROM_NODE, - STATE_CONVERT_FROM_NODE_CREATE, - STATE_CONVERT_TO_NODE, -}; - static int state_convert_node_variable(struct state *state, struct device_node *node, struct device_node *parent, const char *parent_name, enum state_convert conv) @@ -476,7 +505,8 @@ parent_name, parent_name[0] ? "." : "", short_name); free(short_name); - if (conv == STATE_CONVERT_TO_NODE) + if ((conv == STATE_CONVERT_TO_NODE) || + (conv == STATE_CONVERT_FIXUP)) new_node = of_new_node(parent, node->name); for_each_child_of_node(node, child) { @@ -489,6 +519,15 @@ /* parents are allowed to have no type */ ret = of_property_read_string(node, "type", &type_name); if (!list_empty(&node->children) && ret == -EINVAL) { + if (conv == STATE_CONVERT_FIXUP) { + ret = of_property_write_u32(new_node, "#address-cells", 1); + if (ret) + goto out_free; + + ret = of_property_write_u32(new_node, "#size-cells", 1); + if (ret) + goto out_free; + } ret = 0; goto out_free; } else if (ret) { @@ -512,13 +551,16 @@ ret = of_property_read_u32_array(node, "reg", start_size, ARRAY_SIZE(start_size)); - if (ret) + if (ret) { + dev_err(&state->dev, + "%s: reg property not found\n", name); goto out_free; + } if (start_size[1] != sv->size) { dev_err(&state->dev, - "size mismatch: type=%s(size=%u) size=%u\n", - type_name, sv->size, start_size[1]); + "%s: size mismatch: type=%s(size=%u) size=%u\n", + name, type_name, sv->size, start_size[1]); ret = -EOVERFLOW; goto out_free; } @@ -539,7 +581,8 @@ } free(name); - if (conv == STATE_CONVERT_TO_NODE) { + if ((conv == STATE_CONVERT_TO_NODE) || + (conv == STATE_CONVERT_FIXUP)) { ret = of_set_property(new_node, "type", vtype->type_name, strlen(vtype->type_name) + 1, 1); @@ -556,8 +599,9 @@ } } - if (conv == STATE_CONVERT_TO_NODE) - ret = vtype->export(sv, new_node); + if ((conv == STATE_CONVERT_TO_NODE) || + (conv == STATE_CONVERT_FIXUP)) + ret = vtype->export(sv, new_node, conv); else ret = vtype->import(sv, node); @@ -571,20 +615,21 @@ return ret; } -static struct device_node *state_to_node(struct state *state) +static struct device_node *state_to_node(struct state *state, struct device_node *parent, + enum state_convert conv) { struct device_node *child; struct device_node *root; int ret; - root = of_new_node(NULL, NULL); + root = of_new_node(parent, state->root->name); ret = of_property_write_u32(root, "magic", state->magic); if (ret) goto out; for_each_child_of_node(state->root, child) { ret = state_convert_node_variable(state, child, root, "", - STATE_CONVERT_TO_NODE); + conv); if (ret) goto out; } @@ -657,6 +702,101 @@ return ret; } +static int of_state_fixup(struct device_node *root, void *ctx) +{ + struct state *state = ctx; + const char *compatible = "barebox,state"; + struct device_node *new_node, *node, *parent, *backend_node; + struct property *p; + int ret; + phandle phandle; + + node = of_find_node_by_path_from(root, state->root->full_name); + if (node) { + /* replace existing node - it will be deleted later */ + parent = node->parent; + } else { + char *of_path, *c; + + /* look for parent, remove last '/' from path */ + of_path = xstrdup(state->root->full_name); + c = strrchr(of_path, '/'); + if (!c) + return -ENODEV; + *c = '0'; + parent = of_find_node_by_path(of_path); + if (!parent) + parent = root; + + free(of_path); + } + + /* serialize variable definitions */ + new_node = state_to_node(state, parent, STATE_CONVERT_FIXUP); + if (IS_ERR(new_node)) + return PTR_ERR(new_node); + + /* compatible */ + p = of_new_property(new_node, "compatible", compatible, + strlen(compatible) + 1); + if (!p) { + ret = -ENOMEM; + goto out; + } + + /* backend-type */ + if (!state->backend) { + ret = -ENODEV; + goto out; + } + + p = of_new_property(new_node, "backend-type", state->backend->name, + strlen(state->backend->name) + 1); + if (!p) { + ret = -ENOMEM; + goto out; + } + + /* backend phandle */ + backend_node = of_find_node_by_path_from(root, state->backend->of_path); + if (!backend_node) { + ret = -ENODEV; + goto out; + } + + phandle = of_node_create_phandle(backend_node); + ret = of_property_write_u32(new_node, "backend", phandle); + if (ret) + goto out; + + /* address-cells + size-cells */ + ret = of_property_write_u32(new_node, "#address-cells", 1); + if (ret) + goto out; + + ret = of_property_write_u32(new_node, "#size-cells", 1); + if (ret) + goto out; + + /* delete existing node */ + if (node) + of_delete_node(node); + + return 0; + + out: + of_delete_node(new_node); + return ret; +} + +void state_release(struct state *state) +{ + of_unregister_fixup(of_state_fixup, state); + list_del(&state->list); + unregister_device(&state->dev); + free(state); +} + /* * state_new_from_node - create a new state instance from a device_node * @@ -678,27 +818,11 @@ return ERR_PTR(ret); } - return state; -} - -/* - * state_new_from_fdt - create a new state instance from a fdt binary blob - * - * @name The name of the new state instance - * @fdt The fdt binary blob describing the new state instance - */ -struct state *state_new_from_fdt(const char *name, void *fdt) -{ - struct state *state; - struct device_node *root; - - root = of_unflatten_dtb(fdt); - if (!root) - return ERR_PTR(-EINVAL); - - state = state_new_from_node(name, root); - - of_delete_node(root); + ret = of_register_fixup(of_state_fixup, state); + if (ret) { + state_release(state); + return ERR_PTR(ret); + } return state; } @@ -757,10 +881,13 @@ return -ENOSYS; ret = state->backend->load(state->backend, state); - if (ret) + if (ret) { + dev_warn(&state->dev, "load failed\n"); state->dirty = 1; - else + } else { + dev_info(&state->dev, "load successful\n"); state->dirty = 0; + } return ret; } @@ -809,7 +936,7 @@ { int fd, ret; - fd = open(path, O_RDWR); + fd = open(path, O_RDONLY); if (fd < 0) return fd; @@ -863,7 +990,7 @@ struct device_node *root; struct fdt_header *fdt; - root = state_to_node(state); + root = state_to_node(state, NULL, STATE_CONVERT_TO_NODE); if (IS_ERR(root)) return PTR_ERR(root); @@ -906,7 +1033,7 @@ * @state The state instance to work on * @path The path where the state will be stored to */ -int state_backend_dtb_file(struct state *state, const char *path) +int state_backend_dtb_file(struct state *state, const char *of_path, const char *path) { struct state_backend_dtb *backend_dtb; struct state_backend *backend; @@ -921,13 +1048,14 @@ backend->load = state_backend_dtb_load; backend->save = state_backend_dtb_save; + backend->of_path = xstrdup(of_path); backend->path = xstrdup(path); backend->name = "dtb"; state->backend = backend; ret = mtd_get_meminfo(backend->path, &meminfo); - if (!ret && !(meminfo.mtd->flags & MTD_NO_ERASE)) + if (!ret && !(meminfo.flags & MTD_NO_ERASE)) backend_dtb->need_erase = true; return 0; @@ -938,9 +1066,9 @@ */ struct state_backend_raw { struct state_backend backend; - unsigned long size_data; /* The raw data size (without magic and crc) */ - unsigned long size_full; - unsigned long step; /* The step in bytes between two copies */ + unsigned long size_data; /* The raw data size (without header) */ + unsigned long size_full; /* The size header + raw data */ + unsigned long stride; /* The stride size in bytes of the copies */ off_t offset; /* offset in the storage file */ size_t size; /* size of the storage area */ int num_copy_read; /* The first successfully read copy */ @@ -961,16 +1089,23 @@ uint32_t crc; struct state_variable *sv; struct backend_raw_header header = {}; + unsigned long max_len; int ret; void *buf; + max_len = backend_raw->stride; + ret = lseek(fd, offset, SEEK_SET); if (ret < 0) return ret; ret = read_full(fd, &header, sizeof(header)); - if (ret < 0) + max_len -= sizeof(header); + if (ret < 0) { + dev_err(&state->dev, + "cannot read header from backend device"); return ret; + } crc = crc32(0, &header, sizeof(header) - sizeof(uint32_t)); if (crc != header.header_crc) { @@ -987,6 +1122,13 @@ return -EINVAL; } + if (header.data_len > max_len) { + dev_err(&state->dev, + "invalid data_len %u in header, max is %lu\n", + header.data_len, max_len); + return -EINVAL; + } + buf = xzalloc(header.data_len); ret = read_full(fd, buf, header.data_len); @@ -1024,11 +1166,13 @@ int ret = 0, fd, i; fd = open(backend->path, O_RDONLY); - if (fd < 0) + if (fd < 0) { + dev_err(&state->dev, "cannot open %s\n", backend->path); return fd; + } for (i = 0; i < RAW_BACKEND_COPIES; i++) { - off_t offset = backend_raw->offset + i * backend_raw->step; + off_t offset = backend_raw->offset + i * backend_raw->stride; ret = backend_raw_load_one(backend_raw, state, fd, offset); if (!ret) { @@ -1044,11 +1188,11 @@ return ret; } -static int backend_raw_write_one(struct state_backend_raw *backend_raw, +static int backend_raw_save_one(struct state_backend_raw *backend_raw, struct state *state, int fd, int num, void *buf, size_t size) { int ret; - off_t offset = backend_raw->offset + num * backend_raw->step; + off_t offset = backend_raw->offset + num * backend_raw->stride; dev_dbg(&state->dev, "%s: 0x%08lx 0x%08zx\n", __func__, offset, size); @@ -1058,7 +1202,7 @@ return ret; if (backend_raw->need_erase) { - ret = erase(fd, backend_raw->size_full, offset); + ret = erase(fd, backend_raw->stride, offset); if (ret) return ret; } @@ -1075,14 +1219,12 @@ { struct state_backend_raw *backend_raw = container_of(backend, struct state_backend_raw, backend); - int ret = 0, size, fd; + int ret = 0, fd, i; void *buf, *data; struct backend_raw_header *header; struct state_variable *sv; - size = backend_raw->size_data + sizeof(struct backend_raw_header); - - buf = xzalloc(size); + buf = xzalloc(backend_raw->size_full); header = buf; data = buf + sizeof(*header); @@ -1100,13 +1242,20 @@ if (fd < 0) goto out_free; - ret = backend_raw_write_one(backend_raw, state, fd, - !backend_raw->num_copy_read, buf, size); - if (ret) - goto out_close; + /* save other slots first */ + for (i = 0; i < RAW_BACKEND_COPIES; i++) { + if (i == backend_raw->num_copy_read) + continue; - ret = backend_raw_write_one(backend_raw, state, fd, - backend_raw->num_copy_read, buf, size); + ret = backend_raw_save_one(backend_raw, state, fd, + i, buf, backend_raw->size_full); + if (ret) + goto out_close; + + } + + ret = backend_raw_save_one(backend_raw, state, fd, + backend_raw->num_copy_read, buf, backend_raw->size_full); if (ret) goto out_close; @@ -1119,6 +1268,60 @@ return ret; } +#ifdef __BAREBOX__ +#define STAT_GIVES_SIZE(s) (S_ISREG(s.st_mode) || S_ISCHR(s.st_mode)) +#define BLKGET_GIVES_SIZE(s) 0 +#ifndef BLKGETSIZE64 +#define BLKGETSIZE64 -1 +#endif +#else +#define STAT_GIVES_SIZE(s) (S_ISREG(s.st_mode)) +#define BLKGET_GIVES_SIZE(s) (S_ISBLK(s.st_mode)) +#endif + +static int state_backend_raw_file_get_size(const char *path, size_t *out_size) +{ + struct mtd_info_user meminfo; + struct stat s; + int ret; + + ret = stat(path, &s); + if (ret) + return -errno; + + /* + * under Linux, stat() gives the size only on regular files + * under barebox, it works on char dev, too + */ + if (STAT_GIVES_SIZE(s)) { + *out_size = s.st_size; + return 0; + } + + /* this works under Linux on block devs */ + if (BLKGET_GIVES_SIZE(s)) { + int fd; + + fd = open(path, O_RDONLY); + if (fd < 0) + return -errno; + + ret = ioctl(fd, BLKGETSIZE64, out_size); + close(fd); + if (!ret) + return 0; + } + + /* try mtd next */ + ret = mtd_get_meminfo(path, &meminfo); + if (!ret) { + *out_size = meminfo.size; + return 0; + } + + return ret; +} + /* * state_backend_raw_file - create a raw file backend store for a state instance * @@ -1136,32 +1339,34 @@ * device @size may be 0. The two copies are spread to different * eraseblocks if approriate for this device. */ -int state_backend_raw_file(struct state *state, const char *path, off_t offset, - size_t size) +int state_backend_raw_file(struct state *state, const char *of_path, + const char *path, off_t offset, size_t size) { struct state_backend_raw *backend_raw; struct state_backend *backend; struct state_variable *sv; - int ret; - struct stat s; struct mtd_info_user meminfo; + size_t path_size = 0; + int ret; if (state->backend) return -EBUSY; - ret = stat(path, &s); - if (!ret && S_ISCHR(s.st_mode)) { - if (size == 0) - size = s.st_size; - else if (offset + size > s.st_size) - return -EINVAL; - } + ret = state_backend_raw_file_get_size(path, &path_size); + if (ret) + return ret; + + if (size == 0) + size = path_size; + else if (offset + size > path_size) + return -EINVAL; backend_raw = xzalloc(sizeof(*backend_raw)); backend = &backend_raw->backend; backend->load = state_backend_raw_load; backend->save = state_backend_raw_save; + backend->of_path = xstrdup(of_path); backend->path = xstrdup(path); backend->name = "raw"; @@ -1175,18 +1380,21 @@ state->backend = backend; ret = mtd_get_meminfo(backend->path, &meminfo); - if (!ret && !(meminfo.mtd->flags & MTD_NO_ERASE)) { + if (!ret && !(meminfo.flags & MTD_NO_ERASE)) { backend_raw->need_erase = true; - backend_raw->step = ALIGN(backend_raw->size_full, - meminfo.erasesize); + backend_raw->size_full = ALIGN(backend_raw->size_full, + meminfo.writesize); + backend_raw->stride = ALIGN(backend_raw->size_full, + meminfo.erasesize); dev_dbg(&state->dev, "is a mtd, adjust stepsize to %ld\n", - backend_raw->step); + backend_raw->stride); } else { - backend_raw->step = backend_raw->size_full; + backend_raw->stride = backend_raw->size_full; } - if (backend_raw->size / backend_raw->step < RAW_BACKEND_COPIES) { - dev_err(&state->dev, "not enough space for two copies\n"); + if (backend_raw->size / backend_raw->stride < RAW_BACKEND_COPIES) { + dev_err(&state->dev, "not enough space for two copies (%lu each)\n", + backend_raw->stride); ret = -ENOSPC; goto err; } diff --git a/drivers/misc/state.c b/drivers/misc/state.c index 3b07bb9..f3e3664 100644 --- a/drivers/misc/state.c +++ b/drivers/misc/state.c @@ -24,10 +24,12 @@ static int state_probe(struct device_d *dev) { struct device_node *np = dev->device_node; + struct device_node *partition_node; struct state *state; const char *alias; const char *backend_type = NULL; - int ret; + int len, ret; + const char *of_path; char *path; if (!np) @@ -41,28 +43,70 @@ if (IS_ERR(state)) return PTR_ERR(state); - ret = of_find_path(np, "backend", &path, 0); - if (ret) - return ret; + of_path = of_get_property(np, "backend", &len); + if (!of_path) { + ret = -ENODEV; + goto out_release; + } - dev_info(dev, "outpath: %s\n", path); + /* guess if of_path is a path, not a phandle */ + if (of_path[0] == '/' && len > 1) { + ret = of_find_path(np, "backend", &path, 0); + if (ret) + goto out_release; + } else { + struct device_d *dev; + struct cdev *cdev; + + partition_node = of_parse_phandle(np, "backend", 0); + if (!partition_node) { + ret = -ENODEV; + goto out_release; + } + + dev = of_find_device_by_node(partition_node); + if (!list_is_singular(&dev->cdevs)) { + ret = -ENODEV; + goto out_release; + } + + cdev = list_first_entry(&dev->cdevs, struct cdev, devices_list); + if (!cdev) { + ret = -ENODEV; + goto out_release; + } + + path = asprintf("/dev/%s", cdev->name); + of_path = partition_node->full_name; + } ret = of_property_read_string(np, "backend-type", &backend_type); - if (ret) - return ret; - else if (!strcmp(backend_type, "raw")) - ret = state_backend_raw_file(state, path, 0, 0); - else if (!strcmp(backend_type, "dtb")) - ret = state_backend_dtb_file(state, path); - else + if (ret) { + goto out_free; + } else if (!strcmp(backend_type, "raw")) { + ret = state_backend_raw_file(state, of_path, path, 0, 0); + } else if (!strcmp(backend_type, "dtb")) { + ret = state_backend_dtb_file(state, of_path, path); + } else { dev_warn(dev, "invalid backend type: %s\n", backend_type); + ret = -ENODEV; + goto out_free; + } if (ret) - return ret; + goto out_free; + + dev_info(dev, "backend: %s, path: %s, of_path: %s\n", backend_type, path, of_path); + free(path); state_load(state); - return 0; + + out_free: + free(path); + out_release: + state_release(state); + return ret; } static __maybe_unused struct of_device_id state_ids[] = { diff --git a/include/habv4.h b/include/habv4.h index fb6ed99..f9bf74f 100644 --- a/include/habv4.h +++ b/include/habv4.h @@ -21,7 +21,7 @@ #ifdef CONFIG_HABV4 int habv4_get_status(void); #else -static inline int habv4_get_status() +static inline int habv4_get_status(void) { return -EPERM; } diff --git a/include/of.h b/include/of.h index e73cd7a..c02f5f4 100644 --- a/include/of.h +++ b/include/of.h @@ -243,6 +243,7 @@ #define OF_FIND_PATH_FLAGS_BB 1 /* return .bb device if available */ int of_find_path(struct device_node *node, const char *propname, char **outpath, unsigned flags); int of_register_fixup(int (*fixup)(struct device_node *, void *), void *context); +int of_unregister_fixup(int (*fixup)(struct device_node *, void *), void *context); struct device_node *of_find_node_by_alias(struct device_node *root, const char *alias); struct device_node *of_find_node_by_path_or_alias(struct device_node *root, diff --git a/include/state.h b/include/state.h index e96d3bf..08c4e86 100644 --- a/include/state.h +++ b/include/state.h @@ -5,12 +5,13 @@ struct state; -int state_backend_dtb_file(struct state *state, const char *path); -int state_backend_raw_file(struct state *state, const char *path, - off_t offset, size_t size); +int state_backend_dtb_file(struct state *state, const char *of_path, + const char *path); +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_fdt(const char *name, void *fdt); struct state *state_new_from_node(const char *name, struct device_node *node); +void state_release(struct state *state); struct state *state_by_name(const char *name); struct state *state_by_node(const struct device_node *node);