tfm: Refactor code structure 34/223034/9
authorDongwoo Lee <dwoo08.lee@samsung.com>
Tue, 17 Mar 2020 04:29:24 +0000 (13:29 +0900)
committerDongwoo Lee <dwoo08.lee@samsung.com>
Wed, 18 Mar 2020 07:18:04 +0000 (16:18 +0900)
To cleanup code and resolve dependency on each module, this just
refactors code structure without functional changes.

Change-Id: I0c9e4b50d1054255c4f33f2a0218469c0647d2c7
Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
src/dfu.c
src/dfu.h
src/main.c
src/tfm.h
src/thor.c

index 0a1b297..4ae9145 100644 (file)
--- a/src/dfu.c
+++ b/src/dfu.c
 #include "dfu.h"
 #include "thor-proto.h"
 
-static char *dfu_info[DFU_INFO_NUM][DFU_INFO_MAX] = {NULL,};
+#define DFU_DELIMITER          " :,\t\n"
+#define DFU_ENTRY_LIST_MAXLEN  100
+#define DFU_MOUNT_PATH         "/mnt/tfm-temp"
+
+#define DFU_INFO_MODE_PARTITION        'p'
+#define DFU_INFO_MODE_FILE     'f'
+
+enum dfu_entry_attr {
+       DFU_INFO_MODE = 0,
+       DFU_INFO_PARTITION,
+       DFU_INFO_NAME,
+       DFU_INFO_PATH,
+       DFU_INFO_MAX,
+};
+
+enum dfu_thread_state {
+       DFU_THREAD_STATE_ERROR = -1,
+       DFU_THREAD_STATE_IDLE,
+       DFU_THREAD_STATE_FLASHING,
+};
+
+struct dfu_frame {
+       void *buf;
+       unsigned long len;
+       TAILQ_ENTRY(dfu_frame) entry;
+};
+
+struct dfu_context {
+       pthread_t thread;
+       pthread_mutex_t mutex;
+       pthread_mutex_t sync_mutex;
+       pthread_cond_t data_arrived;
+       pthread_cond_t write_done;
+       pthread_cond_t sync_done;
+       TAILQ_HEAD(tailhead, dfu_frame) ioq;
+
+       char *dfu_entry_list[DFU_ENTRY_LIST_MAXLEN][DFU_INFO_MAX];
+};
 
 void *dfu_get_buffer(unsigned long size)
 {
@@ -55,44 +92,45 @@ void dfu_put_buffer(void *ptr)
        free(ptr);
 }
 
-static int find_match(const char *name)
+static char **find_entry_match(struct dfu_context *ctx, const char *name)
 {
        int i;
 
-       for (i = 0; i < DFU_INFO_NUM; i++) {
-               char *entry = dfu_info[i][DFU_INFO_NAME];
+       for (i = 0; i < DFU_ENTRY_LIST_MAXLEN; i++) {
+               char *entry = ctx->dfu_entry_list[i][DFU_INFO_NAME];
 
                if (entry && !strncmp(entry, name, strlen(entry)))
-                       return i;
+                       return ctx->dfu_entry_list[i];
        }
 
-       return -ENOENT;
+       return NULL;
 }
 
-int dfu_request_io(struct tfm_context *ctx, unsigned long len)
+int dfu_request_io(struct dfu_entry *e, void *buffer, unsigned long len)
 {
-       int notify = 0;
+       struct dfu_context *ctx = e->ctx;
        struct dfu_frame *frame;
+       int notify = 0;
 
        frame = malloc(sizeof(*frame));
        if (!frame)
                return -ENOMEM;
 
-       frame->buf = ctx->transfer_buffer;
+       frame->buf = buffer;
        frame->len = len;
 
-       pthread_mutex_lock(&ctx->dfu_mutex);
+       pthread_mutex_lock(&ctx->mutex);
 
-       if (TAILQ_EMPTY(&ctx->dfu_ioq_head))
+       if (TAILQ_EMPTY(&ctx->ioq))
                notify = 1;
 
        /* dfu_thread_main() de-queues i/o request and processes it */
-       TAILQ_INSERT_TAIL(&ctx->dfu_ioq_head, frame, entry);
+       TAILQ_INSERT_TAIL(&ctx->ioq, frame, entry);
 
-       pthread_mutex_unlock(&ctx->dfu_mutex);
+       pthread_mutex_unlock(&ctx->mutex);
 
        if (notify)
-               pthread_cond_signal(&ctx->dfu_data_arrive);
+               pthread_cond_signal(&ctx->data_arrived);
 
        return 0;
 }
@@ -179,53 +217,112 @@ static void umount_dev(void)
        rmdir(DFU_MOUNT_PATH);
 }
 
-void dfu_sync(struct tfm_context *ctx)
+static void dfu_thread_cleanup(void *ptr)
 {
-       char **info = ctx->dfu_info;
+       struct dfu_entry *e = ptr;
+       struct dfu_context *ctx = e->ctx;
+       struct dfu_frame *frame;
 
-       pthread_mutex_lock(&ctx->dfu_sync_mutex);
-       if (!ctx->transfer_done)
-               pthread_cond_wait(&ctx->dfu_write_done, &ctx->dfu_sync_mutex);
-       pthread_mutex_unlock(&ctx->dfu_sync_mutex);
+       while (!TAILQ_EMPTY(&ctx->ioq)) {
+               frame = TAILQ_FIRST(&ctx->ioq);
 
-       switch (*info[DFU_INFO_MODE]) {
-       case DFU_INFO_MODE_FILE:
-               fsync(ctx->dfu_fd);
-               close(ctx->dfu_fd);
-               umount_dev();
-               break;
-       case DFU_INFO_MODE_PARTITION:
-               close(ctx->dfu_fd);
-               break;
-       default:
-               break;
+               TAILQ_REMOVE(&ctx->ioq, frame, entry);
+
+               dfu_put_buffer(frame->buf);
+               free(frame);
        }
 
-       pthread_cond_signal(&ctx->dfu_sync_done);
+       free(e);
+}
 
-       fprintf(stdout, "finished\n");
+static void *dfu_thread_main(void *ptr)
+{
+       struct dfu_entry *e = ptr;
+       struct dfu_context *ctx = e->ctx;
+       struct dfu_frame *frame;
+       int state = DFU_THREAD_STATE_IDLE;
+       uint64_t progress = 0;
+       int ret;
+
+       pthread_cleanup_push(dfu_thread_cleanup, ptr);
+       pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+       while (state != DFU_THREAD_STATE_ERROR) {
+               pthread_mutex_lock(&ctx->mutex);
+
+               while (TAILQ_EMPTY(&ctx->ioq)) {
+                       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+                       state = DFU_THREAD_STATE_IDLE;
+                       pthread_cond_wait(&ctx->data_arrived, &ctx->mutex);
+               }
+
+               if (state == DFU_THREAD_STATE_IDLE) {
+                       state = DFU_THREAD_STATE_FLASHING;
+                       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+               }
+
+               frame = TAILQ_FIRST(&ctx->ioq);
+
+               TAILQ_REMOVE(&ctx->ioq, frame, entry);
+
+               pthread_mutex_unlock(&ctx->mutex);
+
+               ret = write(e->fd, frame->buf, frame->len);
+
+               if (ret < frame->len) {
+                       fprintf(stderr, "Error occurs while flashing\n");
+                       state = DFU_THREAD_STATE_ERROR;
+               }
+
+               progress += frame->len;
+
+               fprintf(stdout, "#");
+               fflush(stdout);
+
+               dfu_put_buffer(frame->buf);
+               free(frame);
+
+               /* transfer finished */
+               if (state != DFU_THREAD_STATE_ERROR
+                               && progress >= e->file_size) {
+                       e->transfer_done = 1;
+
+                       state = DFU_THREAD_STATE_IDLE;
+                       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+
+                       pthread_cond_signal(&ctx->write_done);
+
+                       pthread_mutex_lock(&ctx->sync_mutex);
+                       pthread_cond_wait(&ctx->sync_done,
+                                       &ctx->sync_mutex);
+                       pthread_mutex_unlock(&ctx->sync_mutex);
+                       break;
+               }
+       }
+
+       pthread_cleanup_pop(1);
+
+       return NULL;
 }
 
-static int dfu_start_entity(struct tfm_context *ctx, int idx, unsigned long size)
+static int dfu_start_entry(struct dfu_entry *e, char **entry, uint64_t size)
 {
-       char **info = dfu_info[idx];
        char *file;
-       int fd;
+       int fd, ret = 0;
 
-       switch (*info[DFU_INFO_MODE]) {
+       switch (*entry[DFU_INFO_MODE]) {
        case DFU_INFO_MODE_PARTITION:
-               file = strdup(info[DFU_INFO_PARTITION]);
+               file = strdup(entry[DFU_INFO_PARTITION]);
                if (!file)
                        return -ENOMEM;
                break;
        case DFU_INFO_MODE_FILE:
        {
-               int ret;
                int path_prefix = strlen(DFU_MOUNT_PATH);
-               int path_suffix = strlen(info[DFU_INFO_PATH]);
-               int path_name = strlen(info[DFU_INFO_NAME]);
+               int path_suffix = strlen(entry[DFU_INFO_PATH]);
+               int path_name = strlen(entry[DFU_INFO_NAME]);
 
-               ret = mount_dev(info[DFU_INFO_PARTITION]);
+               ret = mount_dev(entry[DFU_INFO_PARTITION]);
                if (ret < 0)
                        return -EINVAL;
 
@@ -236,138 +333,98 @@ static int dfu_start_entity(struct tfm_context *ctx, int idx, unsigned long size
                }
 
                strncpy(file, DFU_MOUNT_PATH, path_prefix + 1);
-               strncat(file, info[DFU_INFO_PATH], path_suffix + 1);
-               strncat(file, info[DFU_INFO_NAME], path_name + 1);
+               strncat(file, entry[DFU_INFO_PATH], path_suffix + 1);
+               strncat(file, entry[DFU_INFO_NAME], path_name + 1);
                break;
        }
        default:
-               fprintf(stderr, "flash entry '%s' has wrong mode\n", info[DFU_INFO_NAME]);
+               fprintf(stderr,
+                       "flash entry '%s' has wrong mode\n",
+                       entry[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;
+               fprintf(stderr,
+                       "cannot open target: %s\n",
+                       entry[DFU_INFO_NAME]);
+               ret = -EIO;
+               goto err;
        }
 
-       ctx->dfu_fd = fd;
-
-       ctx->dfu_info = info;
-       ctx->transfer_done = 0;
+       e->entry = entry;
+       e->fd = fd;
+       e->file_size = size;
+       e->transfer_done = 0;
 
+err:
        free(file);
 
-       return 0;
+       return ret;
 }
 
-int dfu_start(struct tfm_context *ctx, const char *entity)
+struct dfu_entry *dfu_start(struct dfu_context *ctx,
+                           uint64_t size, const char *filename)
 {
-       unsigned long size = ctx->thor_file_size;
-       int idx, ret;
 
-       idx = find_match(entity);
-       if (idx < 0) {
-               fprintf(stderr, "Cannot find dfu info for %s\n", entity);
-               return -EINVAL;
-       }
+       struct dfu_entry *e;
+       char **entry;
+       int ret;
 
-       ret = dfu_start_entity(ctx, idx, size);
-       if (ret < 0) {
-               fprintf(stderr, "Cannot start download: %s\n", entity);
-               return -EINVAL;
+       entry = find_entry_match(ctx, filename);
+       if (!entry) {
+               fprintf(stderr, "Cannot find dfu info for %s\n", filename);
+               return NULL;
        }
 
-       fprintf(stdout, "Start download: %s...", entity);
-       fflush(stdout);
+       e = (struct dfu_entry *)malloc(sizeof(*e));
+       if (!e)
+               return NULL;
 
-       return 0;
-}
+       ret = dfu_start_entry(e, entry, size);
+       if (ret < 0) {
+               fprintf(stderr, "Cannot start download: %s\n", filename);
+               free(e);
+               return NULL;
+       }
 
-static void dfu_thread_cleanup(void *ptr)
-{
-       struct tfm_context *ctx = ptr;
-       struct dfu_frame *frame;
+       pthread_create(&ctx->thread, NULL, dfu_thread_main, e);
 
-       while (!TAILQ_EMPTY(&ctx->dfu_ioq_head)) {
-               frame = TAILQ_FIRST(&ctx->dfu_ioq_head);
+       e->ctx = ctx;
 
-               TAILQ_REMOVE(&ctx->dfu_ioq_head, frame, entry);
+       fprintf(stdout, "Start download: %s...", filename);
+       fflush(stdout);
 
-               dfu_put_buffer(frame->buf);
-               free(frame);
-       }
+       return e;
 }
 
-static void *dfu_thread_main(void *ptr)
+void dfu_sync(struct dfu_entry *e)
 {
-       struct tfm_context *ctx = ptr;
-       struct dfu_frame *frame;
-       int state = DFU_THREAD_STATE_IDLE;
-       uint64_t progress = 0;
-       int ret;
-
-       pthread_cleanup_push(dfu_thread_cleanup, ptr);
-
-       while (state != DFU_THREAD_STATE_ERROR) {
-               pthread_mutex_lock(&ctx->dfu_mutex);
-
-               while (TAILQ_EMPTY(&ctx->dfu_ioq_head)) {
-                       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
-                       state = DFU_THREAD_STATE_IDLE;
-                       pthread_cond_wait(&ctx->dfu_data_arrive, &ctx->dfu_mutex);
-               }
-
-               if (state == DFU_THREAD_STATE_IDLE) {
-                       state = DFU_THREAD_STATE_FLASHING;
-                       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
-               }
-
-               frame = TAILQ_FIRST(&ctx->dfu_ioq_head);
-
-               TAILQ_REMOVE(&ctx->dfu_ioq_head, frame, entry);
-
-               pthread_mutex_unlock(&ctx->dfu_mutex);
+       struct dfu_context *ctx = e->ctx;
+       char **info = e->entry;
 
-               ret = write(ctx->dfu_fd, frame->buf, frame->len);
-
-               if (ret < frame->len) {
-                       fprintf(stderr, "Error occurs while flashing\n");
-                       state = DFU_THREAD_STATE_ERROR;
-               }
+       pthread_mutex_lock(&ctx->sync_mutex);
+       if (!e->transfer_done)
+               pthread_cond_wait(&ctx->write_done, &ctx->sync_mutex);
+       pthread_mutex_unlock(&ctx->sync_mutex);
 
-               progress += frame->len;
-
-               fprintf(stdout, "#");
-               fflush(stdout);
-
-               dfu_put_buffer(frame->buf);
-               free(frame);
-
-               /* transfer finished */
-               if (state != DFU_THREAD_STATE_ERROR && progress >= ctx->thor_file_size) {
-                       progress = 0;
-                       ctx->transfer_done = 1;
-
-                       fprintf(stdout, "\nTransfer completed. Please wait for sync...");
-                       fflush(stdout);
-
-                       state = DFU_THREAD_STATE_IDLE;
-                       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
-
-                       pthread_cond_signal(&ctx->dfu_write_done);
-
-                       pthread_mutex_lock(&ctx->dfu_sync_mutex);
-                       pthread_cond_wait(&ctx->dfu_sync_done,
-                                       &ctx->dfu_sync_mutex);
-                       pthread_mutex_unlock(&ctx->dfu_sync_mutex);
-               }
+       switch (*info[DFU_INFO_MODE]) {
+       case DFU_INFO_MODE_FILE:
+               fsync(e->fd);
+               close(e->fd);
+               umount_dev();
+               break;
+       case DFU_INFO_MODE_PARTITION:
+               close(e->fd);
+               break;
+       default:
+               break;
        }
 
-       pthread_cleanup_pop(1);
+       pthread_cond_signal(&ctx->sync_done);
 
-       return NULL;
+       fprintf(stdout, "finished\n");
 }
 
 static int parse_dfu_info(char *buf, char **info)
@@ -388,36 +445,35 @@ static int parse_dfu_info(char *buf, char **info)
        return 0;
 }
 
-static void destroy_dfu_info(void)
+static void destroy_dfu_info(struct dfu_context *ctx)
 {
        int i, j;
 
-       for (i = 0; i < DFU_INFO_NUM; i++) {
+       for (i = 0; i < DFU_ENTRY_LIST_MAXLEN; i++) {
                for (j = 0; j < DFU_INFO_MAX; j++)
-                       if (dfu_info[i][j]) {
-                               free(dfu_info[i][j]);
-                               dfu_info[i][j] = NULL;
+                       if (ctx->dfu_entry_list[i][j]) {
+                               free(ctx->dfu_entry_list[i][j]);
+                               ctx->dfu_entry_list[i][j] = NULL;
                        }
        }
 }
 
-
-static int init_dfu_info(const char *dfu_info_file)
+int dfu_init_entry(struct dfu_context *ctx, const char *entry_file)
 {
        FILE *fp;
        char buf[1024];
        int i = 0;
        int ret;
 
-       fp = fopen(dfu_info_file, "r");
+       fp = fopen(entry_file, "r");
        if (!fp)
                return -ENOENT;
 
-       while (i < DFU_INFO_NUM && !feof(fp)) {
+       while (i < DFU_ENTRY_LIST_MAXLEN && !feof(fp)) {
                if (fgets(buf, 1024, fp) == NULL)
                        break;
 
-               ret = parse_dfu_info(buf, dfu_info[i++]);
+               ret = parse_dfu_info(buf, ctx->dfu_entry_list[i++]);
                if (ret < 0) {
                        fprintf(stderr, "cannot parse dfu info");
                        goto err_free_all;
@@ -430,45 +486,39 @@ static int init_dfu_info(const char *dfu_info_file)
 
 err_free_all:
        fclose(fp);
-       destroy_dfu_info();
+       destroy_dfu_info(ctx);
 
        return ret;
 }
 
-int dfu_init(struct tfm_context *ctx, const char *dfu_info_file)
+struct dfu_context *dfu_alloc_context(void)
 {
-       int ret;
+       struct dfu_context *ctx;
 
-       ret = init_dfu_info(dfu_info_file);
-       if (ret < 0) {
-               fprintf(stderr, "failed to get flash entries\n");
-               return ret;
-       }
+       ctx = (struct dfu_context *)malloc(sizeof(*ctx));
+       if (!ctx)
+               return NULL;
 
-       TAILQ_INIT(&ctx->dfu_ioq_head);
+       ctx->thread = 0;
+       TAILQ_INIT(&ctx->ioq);
 
-       pthread_mutex_init(&ctx->dfu_mutex, NULL);
-       pthread_mutex_init(&ctx->dfu_sync_mutex, NULL);
-       pthread_cond_init(&ctx->dfu_data_arrive, NULL);
-       pthread_cond_init(&ctx->dfu_write_done, NULL);
-       pthread_cond_init(&ctx->dfu_sync_done, NULL);
+       pthread_mutex_init(&ctx->mutex, NULL);
+       pthread_mutex_init(&ctx->sync_mutex, NULL);
+       pthread_cond_init(&ctx->data_arrived, NULL);
+       pthread_cond_init(&ctx->write_done, NULL);
+       pthread_cond_init(&ctx->sync_done, NULL);
 
-       ret = pthread_create(&ctx->dfu_thread, NULL, dfu_thread_main, ctx);
-       if (ret < 0) {
-               fprintf(stderr, "failed to create thread for dfu\n");
-               return ret;
-       }
+       memset(ctx->dfu_entry_list, 0, sizeof(ctx->dfu_entry_list));
 
-       return 0;
+       return ctx;
 }
 
-void dfu_exit(struct tfm_context *ctx)
+void dfu_free_context(struct dfu_context *ctx)
 {
-       pthread_cancel(ctx->dfu_thread);
-       pthread_join(ctx->dfu_thread, NULL);
-       destroy_dfu_info();
-       if (ctx->connect) {
-               free(ctx->connect);
-               ctx->connect = NULL;
-       }
+       if (!ctx)
+               return;
+
+       pthread_cancel(ctx->thread);
+       destroy_dfu_info(ctx);
+       free(ctx);
 }
index 589a9a1..0d35883 100644 (file)
--- a/src/dfu.h
+++ b/src/dfu.h
 #define __DFU_H
 
 #include <sys/queue.h>
-#include "tfm.h"
+#include <stdint.h>
 
-#define DFU_DELIMITER          " :,\t\n"
-#define DFU_INFO_NUM           100
-#define DFU_MOUNT_PATH         "/mnt/tfm-temp"
+struct dfu_context;
 
-#define DFU_INFO_MODE_PARTITION        'p'
-#define DFU_INFO_MODE_FILE     'f'
-
-enum dfu_info_entry {
-       DFU_INFO_MODE = 0,
-       DFU_INFO_PARTITION,
-       DFU_INFO_NAME,
-       DFU_INFO_PATH,
-       DFU_INFO_MAX,
-};
-
-enum dfu_thread_state {
-       DFU_THREAD_STATE_ERROR = -1,
-       DFU_THREAD_STATE_IDLE,
-       DFU_THREAD_STATE_FLASHING,
-};
-
-struct dfu_frame {
-       void *buf;
-       unsigned long len;
-       TAILQ_ENTRY(dfu_frame) entry;
+struct dfu_entry {
+       struct dfu_context *ctx;
+       char **entry;
+       int fd;
+       uint64_t file_size;
+       int transfer_done;
 };
 
 void *dfu_get_buffer(unsigned long size);
 void dfu_put_buffer(void *ptr);
-int dfu_init(struct tfm_context *ctx, const char *dfu_info_file);
-void dfu_exit(struct tfm_context *ctx);
-int dfu_start(struct tfm_context *ctx, const char *entity);
-int dfu_request_io(struct tfm_context *ctx, unsigned long len);
-void dfu_sync(struct tfm_context *ctx);
+struct dfu_context *dfu_alloc_context(void);
+void dfu_free_context(struct dfu_context *ctx);
+int dfu_init_entry(struct dfu_context *ctx, const char *entry_file);
+struct dfu_entry *dfu_start(struct dfu_context *ctx,
+                           uint64_t size, const char *filename);
+void dfu_sync(struct dfu_entry *e);
+int dfu_request_io(struct dfu_entry *e, void *buffer, unsigned long len);
+
 
 #endif
index 32c2473..376d8be 100644 (file)
 
 int _main(int argc, char *argv[])
 {
-       struct tfm_context ctx;
+       struct tfm_context tfm;
+       struct dfu_context *dfu;
        const char *part_table = "/usr/share/partition.info";
        char *opt_table = NULL;
        int ret, opt;
 
-       memset(&ctx, 0, sizeof(ctx));
+       memset(&tfm, 0, sizeof(tfm));
 
        while ((opt = getopt(argc, argv, "p:i:")) != -1) {
                switch (opt) {
@@ -65,7 +66,7 @@ int _main(int argc, char *argv[])
                                ret = -1;
                                goto out_optfree;
                        }
-                       ctx.port = (int)val;
+                       tfm.port = (int)val;
                        break;
                }
                default:
@@ -74,35 +75,41 @@ int _main(int argc, char *argv[])
                }
        }
 
-       ret = dfu_init(&ctx, part_table);
-       if (ret < 0) {
+       dfu = dfu_alloc_context();
+       if (!dfu) {
                ret = -1;
                goto out_optfree;
        }
 
-       ret = net_connect(&ctx);
+       ret = dfu_init_entry(dfu, part_table);
+       if (ret < 0) {
+               ret = -1;
+               goto out_dfuexit;
+       }
+
+       ret = net_connect(&tfm);
        if (ret < 0) {
                ret = -1;
                goto out_dfuexit;
        }
 
-       ret = thor_init(&ctx);
+       ret = thor_setup(&tfm);
        if (ret < 0) {
                ret = -1;
                goto out_netdisconn;
        }
 
-       ret = thor_process(&ctx);
+       ret = thor_process(&tfm, dfu);
        if (ret < 0) {
                ret = -1;
                goto out_netdisconn;
        }
 
 out_netdisconn:
-       net_disconnect(&ctx);
+       net_disconnect(&tfm);
 
 out_dfuexit:
-       dfu_exit(&ctx);
+       dfu_free_context(dfu);
 
 out_optfree:
        if (opt_table)
index 747de2d..8760e35 100644 (file)
--- a/src/tfm.h
+++ b/src/tfm.h
 
 #include <string.h>
 #include <pthread.h>
-#include <stdint.h>
 #include <sys/queue.h>
 
+#include "dfu.h"
+
 struct tfm_connect {
        int fd;
        ssize_t (*rx_data)(int fd, void *buf, ssize_t len);
@@ -29,26 +30,11 @@ struct tfm_connect {
 };
 
 struct tfm_context {
-       char **dfu_info;
-       int dfu_fd;
-       pthread_t dfu_thread;
-       pthread_mutex_t dfu_mutex;
-       pthread_mutex_t dfu_sync_mutex;
-       pthread_cond_t dfu_data_arrive;
-       pthread_cond_t dfu_write_done;
-       pthread_cond_t dfu_sync_done;
-       TAILQ_HEAD(tailhead, dfu_frame) dfu_ioq_head;
-
        struct tfm_connect *connect;
-       uint64_t thor_file_size;
-       uint64_t remain;
-       void *transfer_buffer;
-       int transfer_done;
-
        int port;
 };
 
-int thor_init(struct tfm_context *ctx);
-int thor_process(struct tfm_context *ctx);
+int thor_setup(struct tfm_context *tfm);
+int thor_process(struct tfm_context *tfm, struct dfu_context *dfu);
 
 #endif
index e19d33f..1c255d2 100644 (file)
 #include <stdlib.h>
 #include <sys/reboot.h>
 
+#include "tfm.h"
 #include "dfu.h"
 #include "thor-proto.h"
 
-static inline ssize_t thor_rx_data(struct tfm_connect *conn, void *buf, ssize_t len)
-{
-       return conn->rx_data(conn->fd, buf, len);
-}
+struct thor_context {
+       struct rqt_pkt *rqt;
+       struct tfm_connect *intf;
+       struct dfu_context *dfu;
+       struct dfu_entry *dfu_entry;
 
-static inline ssize_t thor_tx_data(struct tfm_connect *conn, void *buf, ssize_t len)
-{
-       return conn->tx_data(conn->fd, buf, len);
-}
+       void *buffer;
+       uint64_t file_size;
+       uint64_t remain;
+};
 
 static unsigned int _checkboard(void)
 {
@@ -48,19 +50,21 @@ static unsigned int _checkboard(void)
        return -1;
 }
 
-static int thor_send_rsp(struct tfm_connect *conn, const struct res_pkt *rsp)
+static int thor_send_rsp(struct thor_context *tctx, struct res_pkt *rsp)
 {
+       struct tfm_connect *intf = tctx->intf;
        ssize_t n;
 
-       n = thor_tx_data(conn, (void *)rsp, RES_PKT_SIZE);
+       n = intf->tx_data(intf->fd, (void *)rsp, RES_PKT_SIZE);
        if (n < sizeof(*rsp))
                return -EIO;
 
        return 0;
 }
 
-static int thor_process_rqt_info(struct tfm_context *ctx, struct rqt_pkt *rqt)
+static int thor_process_rqt_info(struct thor_context *tctx)
 {
+       struct rqt_pkt *rqt = tctx->rqt;
        struct res_pkt rsp;
        int ret;
 
@@ -89,7 +93,7 @@ static int thor_process_rqt_info(struct tfm_context *ctx, struct rqt_pkt *rqt)
                return -EINVAL;
        }
 
-       ret = thor_send_rsp(ctx->connect, &rsp);
+       ret = thor_send_rsp(tctx, &rsp);
        if (ret < 0) {
                fprintf(stderr, "failed to send response of REQUEST_INFO\n");
                return ret;
@@ -98,9 +102,9 @@ static int thor_process_rqt_info(struct tfm_context *ctx, struct rqt_pkt *rqt)
        return 0;
 }
 
-static int thor_process_rqt_cmd(struct tfm_context *ctx, struct rqt_pkt *rqt)
+static int thor_process_rqt_cmd(struct thor_context *tctx)
 {
-       struct tfm_connect *conn = ctx->connect;
+       struct rqt_pkt *rqt = tctx->rqt;
        struct res_pkt rsp;
        int ret;
 
@@ -111,7 +115,7 @@ static int thor_process_rqt_cmd(struct tfm_context *ctx, struct rqt_pkt *rqt)
 
        switch (rqt->sub_id) {
        case RQT_CMD_REBOOT:
-               thor_send_rsp(conn, &rsp);
+               thor_send_rsp(tctx, &rsp);
 
                ret = reboot(RB_AUTOBOOT);
                if (ret < 0) {
@@ -120,7 +124,7 @@ static int thor_process_rqt_cmd(struct tfm_context *ctx, struct rqt_pkt *rqt)
                }
                break;
        case RQT_CMD_POWEROFF:
-               thor_send_rsp(conn, &rsp);
+               thor_send_rsp(tctx, &rsp);
                break;
        default:
                fprintf(stderr, "Not supported command request: %d",
@@ -131,29 +135,32 @@ static int thor_process_rqt_cmd(struct tfm_context *ctx, struct rqt_pkt *rqt)
        return 0;
 }
 
-static void thor_send_data_rsp(struct tfm_connect *conn, int ack, int count)
+static void thor_send_data_rsp(struct thor_context *tctx, int ack, int count)
 {
+       struct tfm_connect *intf = tctx->intf;
        struct data_res_pkt rsp;
 
        rsp.ack = ack;
        rsp.cnt = count;
 
-       thor_tx_data(conn, &rsp, DATA_RES_PKT_SIZE);
+       intf->tx_data(intf->fd, &rsp, DATA_RES_PKT_SIZE);
 }
 
-static int thor_download_head(struct tfm_context *ctx, unsigned int packet_size)
+static int
+thor_download_head(struct thor_context *tctx, unsigned int packet_size)
 {
-       struct tfm_connect *conn = ctx->connect;
+       struct tfm_connect *intf = tctx->intf;
+       struct dfu_entry *e = tctx->dfu_entry;
        uint64_t recv = 0;
-       uint64_t total = ctx->thor_file_size;
+       uint64_t total = tctx->file_size;
        void *buf;
        int usb_pkt_cnt = 0, n;
        int ret;
 
-       ctx->transfer_buffer = buf = dfu_get_buffer(FLASH_UNIT_SIZE);
+       tctx->buffer = buf = dfu_get_buffer(FLASH_UNIT_SIZE);
 
        while (total - recv >= packet_size) {
-               n = thor_rx_data(conn, buf, packet_size);
+               n = intf->rx_data(intf->fd, buf, packet_size);
 
                if (n < packet_size)
                        return -EIO;
@@ -162,52 +169,52 @@ static int thor_download_head(struct tfm_context *ctx, unsigned int packet_size)
                buf += packet_size;
 
                if ((recv % FLASH_UNIT_SIZE) == 0) {
-                       ret = dfu_request_io(ctx, FLASH_UNIT_SIZE);
+                       ret = dfu_request_io(e, tctx->buffer, FLASH_UNIT_SIZE);
                        if (ret < 0)
                                return -EIO;
 
-                       ctx->transfer_buffer = buf = dfu_get_buffer(FLASH_UNIT_SIZE);
+                       tctx->buffer = buf = dfu_get_buffer(FLASH_UNIT_SIZE);
                }
-               thor_send_data_rsp(conn, 0, ++usb_pkt_cnt);
+               thor_send_data_rsp(tctx, 0, ++usb_pkt_cnt);
        }
 
-       ctx->remain = (total - recv) + (uint64_t)(buf - ctx->transfer_buffer);
+       tctx->remain = (total - recv) + (uint64_t)(buf - tctx->buffer);
 
        if ((total - recv) > 0) {
-               n = thor_rx_data(conn, buf, packet_size);
+               n = intf->rx_data(intf->fd, buf, packet_size);
                if (n < packet_size)
                        return -EIO;
                recv += n;
-               thor_send_data_rsp(conn, 0, ++usb_pkt_cnt);
+               thor_send_data_rsp(tctx, 0, ++usb_pkt_cnt);
        }
 
        return 0;
 }
 
-static int thor_download_tail(struct tfm_context *ctx)
+static int thor_download_tail(struct thor_context *tctx)
 {
+       struct dfu_entry *e = tctx->dfu_entry;
        int ret;
 
-       if (ctx->remain) {
-               ret = dfu_request_io(ctx, ctx->remain);
+       if (tctx->remain) {
+               ret = dfu_request_io(e, tctx->buffer, tctx->remain);
                if (ret < 0)
                        return -EIO;
        } else {
                /* if there is no remain, buffer should be freed */
-               dfu_put_buffer(ctx->transfer_buffer);
+               dfu_put_buffer(tctx->buffer);
        }
 
-       dfu_sync(ctx);
+       dfu_sync(e);
 
        return 0;
 }
 
-static int thor_process_rqt_download(struct tfm_context *ctx, struct rqt_pkt *rqt)
+static int thor_process_rqt_download(struct thor_context *tctx)
 {
-       struct tfm_connect *conn = ctx->connect;
-       char f_name[FILE_NAME_MAXLEN + 1] = {0,};
+       struct rqt_pkt *rqt = tctx->rqt;
        struct res_pkt rsp;
-       int ret = 0, head, file_type;
+       int ret = 0;
 
        memset(&rsp, 0, RES_PKT_SIZE);
 
@@ -216,10 +223,16 @@ static int thor_process_rqt_download(struct tfm_context *ctx, struct rqt_pkt *rq
 
        switch (rqt->sub_id) {
        case RQT_DL_INIT:
-               ctx->thor_file_size = (uint64_t)rqt->int_data[0]
+               tctx->file_size = (uint64_t)rqt->int_data[0]
                                        + ((uint64_t)rqt->int_data[1] << 32);
                break;
        case RQT_DL_FILE_INFO:
+       {
+               struct dfu_context *dfu = tctx->dfu;
+               struct dfu_entry *e;
+               char f_name[FILE_NAME_MAXLEN + 1] = {0,};
+               int file_type;
+
                file_type = rqt->int_data[0];
                if (file_type != BINARY_TYPE_NORMAL) {
                        fprintf(stderr, "Currently only NORMAL_FILE is supported\n");
@@ -227,34 +240,45 @@ static int thor_process_rqt_download(struct tfm_context *ctx, struct rqt_pkt *rq
                        break;
                }
 
-               ctx->thor_file_size = (uint64_t)rqt->int_data[1]
+               tctx->file_size = (uint64_t)rqt->int_data[1]
                                        + ((uint64_t)rqt->int_data[2] << 32);
+
                memcpy(f_name, rqt->str_data[0], FILE_NAME_MAXLEN);
 
                rsp.int_data[0] = DATA_PKT_SIZE;
 
-               ret = dfu_start(ctx, f_name);
-               if (ret < 0) {
+               e = dfu_start(dfu, tctx->file_size, f_name);
+               if (!e) {
                        fprintf(stderr, "failed to start dfu\n");
                        ret = -EINVAL;
                }
+
+               tctx->dfu_entry = e;
                break;
+       }
        case RQT_DL_FILE_START:
-               ret = thor_send_rsp(conn, &rsp);
+               ret = thor_send_rsp(tctx, &rsp);
                if (ret < 0) {
                        fprintf(stderr, "failed to send response\n");
                        ret = rsp.ack = -EINVAL;
                        break;
                }
-               head = thor_download_head(ctx, DATA_PKT_SIZE);
-               if (head < 0)
-                       ctx->remain = 0;
+               ret = thor_download_head(tctx, DATA_PKT_SIZE);
+               if (ret < 0)
+                       tctx->remain = 0;
 
-               return head;
+               return ret;
        case RQT_DL_FILE_END:
-               rsp.ack = thor_download_tail(ctx);
+               rsp.ack = thor_download_tail(tctx);
                ret = rsp.ack;
-               ctx->remain = 0;
+               tctx->remain = 0;
+               tctx->file_size = 0;
+               /*
+                * dfu_entry and buffer will be freed by dfu_thread_cleanup,
+                * so just make it NULL here.
+                */
+               tctx->dfu_entry = NULL;
+               tctx->buffer = NULL;
                break;
        case RQT_DL_EXIT:
                break;
@@ -264,23 +288,24 @@ static int thor_process_rqt_download(struct tfm_context *ctx, struct rqt_pkt *rq
                ret = -EINVAL;
        }
 
-       thor_send_rsp(conn, &rsp);
+       thor_send_rsp(tctx, &rsp);
        return ret;
 }
 
-static int thor_do_request(struct tfm_context *ctx, struct rqt_pkt *rqt)
+static int thor_do_request(struct thor_context *tctx)
 {
+       struct rqt_pkt *rqt = tctx->rqt;
        int ret;
 
        switch (rqt->id) {
        case RQT_INFO:
-               ret = thor_process_rqt_info(ctx, rqt);
+               ret = thor_process_rqt_info(tctx);
                break;
        case RQT_CMD:
-               ret = thor_process_rqt_cmd(ctx, rqt);
+               ret = thor_process_rqt_cmd(tctx);
                break;
        case RQT_DL:
-               ret = thor_process_rqt_download(ctx, rqt);
+               ret = thor_process_rqt_download(tctx);
                break;
        case RQT_UL:
                fprintf(stderr, "Request \"UPLOAD\" is not supported\n");
@@ -294,17 +319,17 @@ static int thor_do_request(struct tfm_context *ctx, struct rqt_pkt *rqt)
        return ret;
 }
 
-static int thor_handshake(struct tfm_connect *conn)
+static int thor_handshake(struct tfm_connect *intf)
 {
        char buf[5];
        ssize_t n;
 
-       n = thor_rx_data(conn, buf, 4/* strlen("THOR") */);
+       n = intf->rx_data(intf->fd, buf, 4/* strlen("THOR") */);
        if (n < 4)
                return -EIO;
 
        if (!strncmp(buf, "THOR", 4)) {
-               n = thor_tx_data(conn, "ROHT", 4);
+               n = intf->tx_data(intf->fd, "ROHT", 4);
                if (n < 4)
                        return -EIO;
        } else {
@@ -315,20 +340,21 @@ static int thor_handshake(struct tfm_connect *conn)
        return 0;
 }
 
-int thor_init(struct tfm_context *ctx)
+int thor_process(struct tfm_context *tfm, struct dfu_context *dfu)
 {
-       return thor_handshake(ctx->connect);
-}
-
-int thor_process(struct tfm_context *ctx)
-{
-       struct tfm_connect *conn = ctx->connect;
+       struct tfm_connect *intf = tfm->connect;
+       struct thor_context tctx;
        struct rqt_pkt rqt;
        ssize_t n;
        int ret;
 
+       memset(&tctx, 0, sizeof(tctx));
+
+       tctx.intf = intf;
+       tctx.dfu = dfu;
+
        for (;;) {
-               n = thor_rx_data(conn, &rqt, RQT_PKT_SIZE);
+               n = intf->rx_data(intf->fd, &rqt, RQT_PKT_SIZE);
                if (n < sizeof(rqt)) {
                        fprintf(stderr,
                                "Failed to receive data from the host(%zd:%zu)",
@@ -336,10 +362,22 @@ int thor_process(struct tfm_context *ctx)
                        return -EIO;
                }
 
-               ret = thor_do_request(ctx, &rqt);
+               tctx.rqt = &rqt;
+
+               ret = thor_do_request(&tctx);
                if (ret < 0)
                        return ret;
        }
 
        return 0;
 }
+
+int thor_setup(struct tfm_context *tfm)
+{
+       if (!tfm->connect) {
+               fprintf(stderr, "Invalid connection\n");
+               return -EINVAL;
+       }
+
+       return thor_handshake(tfm->connect);
+}