#include <sys/fcntl.h>
#include <sys/mount.h>
#include <pthread.h>
+#include <blkid/blkid.h>
#include "dfu.h"
#include "thor-proto.h"
return 0;
}
-static void mount_dev(const char *dev)
+static void mount_dev(const char *dev, const char *fstype)
{
int ret;
mkdir(DFU_MOUNT_PATH, 0600);
- ret = mount(dev, DFU_MOUNT_PATH, "ext4", 0, NULL);
+ ret = mount(dev, DFU_MOUNT_PATH, fstype, 0, NULL);
if (ret < 0) {
fprintf(stderr, "Failed to mount target partition\n");
rmdir(DFU_MOUNT_PATH);
fprintf(stdout, "finished\n");
}
+static char *get_partition_devname(const char *label)
+{
+ blkid_dev_iterate dev_iter;
+ blkid_tag_iterate tag_iter;
+ blkid_dev dev;
+ blkid_cache cache = NULL;
+ const char *type, *value;
+ int ret;
+
+ ret = blkid_get_cache(&cache, NULL);
+ if (ret < 0)
+ return NULL;
+
+ blkid_probe_all(cache);
+
+ dev_iter = blkid_dev_iterate_begin(cache);
+ blkid_dev_set_search(dev_iter, NULL, NULL);
+ while (blkid_dev_next(dev_iter, &dev) == 0) {
+ dev = blkid_verify(cache, dev);
+ if (!dev)
+ continue;
+
+ tag_iter = blkid_tag_iterate_begin(dev);
+ while (blkid_tag_next(tag_iter, &type, &value) == 0) {
+ if (!strncmp(type, "LABEL", 5) && !strncmp(value, label, strlen(label))) {
+ char *devname = strdup(blkid_dev_devname(dev));
+
+ blkid_tag_iterate_end(tag_iter);
+ blkid_dev_iterate_end(dev_iter);
+ blkid_put_cache(cache);
+ return devname;
+ }
+ }
+ blkid_tag_iterate_end(tag_iter);
+ }
+ blkid_dev_iterate_end(dev_iter);
+ blkid_put_cache(cache);
+
+ return NULL;
+}
+
+static char *get_partition_fstype(const char *devname)
+{
+ blkid_tag_iterate tag_iter;
+ blkid_dev dev;
+ blkid_cache cache = NULL;
+ const char *type, *value;
+ int ret;
+
+ ret = blkid_get_cache(&cache, NULL);
+ if (ret < 0)
+ return NULL;
+
+ blkid_probe_all(cache);
+
+ dev = blkid_get_dev(cache, devname, 0);
+ if (!dev)
+ return NULL;
+
+ dev = blkid_verify(cache, dev);
+ if (!dev)
+ return NULL;
+
+ tag_iter = blkid_tag_iterate_begin(dev);
+ while (blkid_tag_next(tag_iter, &type, &value) == 0) {
+ if (!strncmp(type, "TYPE", 4)) {
+ char *fstype = strdup(value);
+
+ blkid_tag_iterate_end(tag_iter);
+ blkid_put_cache(cache);
+ return fstype;
+ }
+ }
+ blkid_tag_iterate_end(tag_iter);
+ blkid_put_cache(cache);
+
+ return NULL;
+}
+
static int dfu_start_entity(struct tfm_context *ctx, int idx, unsigned long size)
{
char **info = dfu_info[idx];
switch (*info[DFU_INFO_MODE]) {
case 'p':
- file = info[DFU_INFO_DEV];
+ file = get_partition_devname(info[DFU_INFO_LABEL]);
+ if (!file) {
+ fprintf(stderr, "failed to get partition devname: %s", info[DFU_INFO_LABEL]);
+ return -EINVAL;
+ }
break;
case 'f':
- mount_dev(info[DFU_INFO_DEV]);
- file = info[DFU_INFO_PATH];
+ {
+ int path_prefix = strlen(DFU_MOUNT_PATH);
+ int path_suffix = strlen(info[DFU_INFO_PATH]);
+ int path_name = strlen(info[DFU_INFO_NAME]);
+ char *devname, *fstype;
+
+ devname = get_partition_devname(info[DFU_INFO_LABEL]);
+ if (!devname) {
+ fprintf(stderr, "failed to get partition devname: %s", info[DFU_INFO_LABEL]);
+ return -EINVAL;
+ }
+
+ fstype = get_partition_fstype(devname);
+ if (!fstype) {
+ fprintf(stderr, "failed to get partition filesystem type: %s", devname);
+ return -EINVAL;
+ }
+
+ mount_dev(devname, fstype);
+ free(devname);
+ free(fstype);
+
+ file = malloc(path_prefix + path_suffix + path_name + 1);
+ if (!file)
+ return -ENOMEM;
+
+ strncpy(file, DFU_MOUNT_PATH, path_prefix + 1);
+ strncat(file, info[DFU_INFO_PATH], path_suffix);
+ strncat(file, info[DFU_INFO_NAME], path_name);
break;
+ }
default:
fprintf(stderr, "flash entry '%s' has wrong mode\n", info[DFU_INFO_NAME]);
return -EINVAL;
fd = open(file, O_WRONLY);
if (fd < 0) {
fprintf(stderr, "cannot open target: %s\n", info[DFU_INFO_NAME]);
+ free(file);
return -EIO;
}
ctx->dfu_info = info;
ctx->transfer_done = 0;
+ free(file);
+
return 0;
}