#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)
{
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;
}
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;
}
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)
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;
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);
}
#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)
{
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;
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;
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;
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) {
}
break;
case RQT_CMD_POWEROFF:
- thor_send_rsp(conn, &rsp);
+ thor_send_rsp(tctx, &rsp);
break;
default:
fprintf(stderr, "Not supported command request: %d",
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;
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);
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");
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;
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");
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 {
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)",
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);
+}