diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2015-06-30 08:23:42 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2015-07-01 09:04:22 +0200 |
commit | 74ac4489cf058d5c466765418de8fd89306fefa2 (patch) | |
tree | 61fdfbee398b38732e730041c79b93561ce4a54b /common/bbu.c | |
parent | fc6cb7aeaf6f96505ba15a99b5d02102377ee79a (diff) | |
download | barebox-74ac4489cf058d5c466765418de8fd89306fefa2.tar.gz barebox-74ac4489cf058d5c466765418de8fd89306fefa2.tar.xz |
bbu: Add a standard file-to-device-copy handler
The most standard update handler will simply copy a file to a device.
This can be shared across several users, so add a standard handler for
this operation.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'common/bbu.c')
-rw-r--r-- | common/bbu.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/common/bbu.c b/common/bbu.c index 7fb154a230..4d71fa4a87 100644 --- a/common/bbu.c +++ b/common/bbu.c @@ -20,6 +20,12 @@ #include <linux/list.h> #include <errno.h> #include <readkey.h> +#include <filetype.h> +#include <libfile.h> +#include <fs.h> +#include <fcntl.h> +#include <malloc.h> +#include <linux/stat.h> static LIST_HEAD(bbu_image_handlers); @@ -153,3 +159,110 @@ int bbu_register_handler(struct bbu_handler *handler) return 0; } + +struct bbu_std { + struct bbu_handler handler; + enum filetype filetype; +}; + +static int bbu_std_file_handler(struct bbu_handler *handler, + struct bbu_data *data) +{ + struct bbu_std *std = container_of(handler, struct bbu_std, handler); + int fd, ret; + enum filetype filetype; + struct stat s; + unsigned oflags = O_WRONLY; + + filetype = file_detect_type(data->image, data->len); + if (filetype != std->filetype) { + if (!bbu_force(data, "incorrect image type. Expected: %s, got %s", + file_type_to_string(std->filetype), + file_type_to_string(filetype))) + return -EINVAL; + } + + ret = stat(data->devicefile, &s); + if (ret) { + oflags |= O_CREAT; + } else { + if (!S_ISREG(s.st_mode) && s.st_size < data->len) { + printf("Image (%lld) is too big for device (%d)\n", + s.st_size, data->len); + } + } + + ret = bbu_confirm(data); + if (ret) + return ret; + + fd = open(data->devicefile, oflags); + if (fd < 0) + return fd; + + ret = protect(fd, data->len, 0, 0); + if (ret && ret != -ENOSYS) { + printf("unprotecting %s failed with %s\n", data->devicefile, + strerror(-ret)); + goto err_close; + } + + ret = erase(fd, data->len, 0); + if (ret && ret != -ENOSYS) { + printf("erasing %s failed with %s\n", data->devicefile, + strerror(-ret)); + goto err_close; + } + + ret = write_full(fd, data->image, data->len); + if (ret < 0) + goto err_close; + + protect(fd, data->len, 0, 1); + + ret = 0; + +err_close: + close(fd); + + return ret; +} + +/** + * bbu_register_std_file_update() - register a barebox update handler for a + * standard file-to-device-copy operation + * @name: Name of the handler + * @flags: BBU_HANDLER_FLAG_* flags + * @devicefile: the file to write the update image to + * @imagetype: The filetype that the update image must have + * + * This update handler us suitable for a standard file-to-device copy operation. + * The handler checks for a filetype and unprotects/erases the device if + * necessary. If devicefile belongs to a device then the device is checkd for + * enough space before touching it. + * + * Return: 0 if successful, negative error code otherwise + */ +int bbu_register_std_file_update(const char *name, unsigned long flags, + char *devicefile, enum filetype imagetype) +{ + struct bbu_std *std; + struct bbu_handler *handler; + int ret; + + std = xzalloc(sizeof(*std)); + std->filetype = imagetype; + + handler = &std->handler; + + handler->flags = flags; + handler->devicefile = devicefile; + handler->name = name; + handler->handler = bbu_std_file_handler; + + ret = bbu_register_handler(handler); + if (ret) + free(std); + + return ret; +} |