dfu: Support the image flashing about A/B slot 60/312960/3 accepted/tizen/unified/20240618.195747 accepted/tizen/unified/dev/20240620.005725 accepted/tizen/unified/x/20240619.013445
authorJaehoon Chung <jh80.chung@samsung.com>
Mon, 17 Jun 2024 23:33:35 +0000 (08:33 +0900)
committerJaehoon Chung <jh80.chung@samsung.com>
Tue, 18 Jun 2024 00:04:58 +0000 (09:04 +0900)
Tizen is using A/B partition. So it needs to update the image about both partitions.
This patch supports the image flashing about a/b slot.
The Entire time of flashing images (Headed)
- Before : 3m 50s
- After  : 6m 40s

Change-Id: I9a3648cc958ba532734c3ea690c7362e173b1bdc
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
src/dfu.c
src/dfu.h

index 3e62006c508b5c85eec3eeef050df47a910762bc..d365b8ad0392a78c1e611e5a5f94c39c1168fbc9 100644 (file)
--- a/src/dfu.c
+++ b/src/dfu.c
@@ -37,6 +37,8 @@
 
 #define DFU_INFO_MODE_PARTITION        'p'
 #define DFU_INFO_MODE_FILE     'f'
+#define DFU_INFO_PART_A                "a"
+#define DFU_INFO_PART_B                "b"
 
 #define DFU_IOQ_MAXLEN         5
 
@@ -48,6 +50,7 @@ enum dfu_entry_attr {
        DFU_INFO_PARTITION,
        DFU_INFO_NAME,
        DFU_INFO_PATH,
+       DFU_INFO_AB,
        DFU_INFO_MAX,
 };
 
@@ -388,9 +391,20 @@ static void *dfu_thread_main(void *ptr)
                        state = DFU_THREAD_STATE_ERROR;
                }
 
+               if (e->fd_b > 0) {
+                       ret = write(e->fd_b, frame->buf, frame->len);
+                       if (ret < frame->len) {
+                               fprintf(stderr, "Error occurs while flashing\n");
+                               state = DFU_THREAD_STATE_ERROR;
+                       }
+               }
+
+
                progress += frame->len;
 
                fsync(e->fd);
+               if (e->fd_b > 0)
+                       fsync(e->fd_b);
 
                pthread_mutex_lock(&ctx->mutex);
                TAILQ_REMOVE(&ctx->ioq, frame, entry);
@@ -425,6 +439,72 @@ static void *dfu_thread_main(void *ptr)
        return NULL;
 }
 
+static int find_slot_b(struct dfu_context *ctx, char *name) {
+       int fd = -1;
+       char *file = NULL;
+       int i, ret = 0;
+
+       for (i = 0; i < DFU_ENTRY_LIST_MAXLEN; i++) {
+               char *entry_name = ctx->dfu_entry_list[i][DFU_INFO_NAME];
+               char *entry_ab = ctx->dfu_entry_list[i][DFU_INFO_AB];
+
+               if (entry_ab && strncmp(entry_ab, DFU_INFO_PART_B, strlen(entry_ab)) == 0) {
+                       if (entry_name && !strncmp(entry_name, name, strlen(entry_name))) {
+                               char **entry = ctx->dfu_entry_list[i];
+                               switch (*entry[DFU_INFO_MODE]) {
+                               case DFU_INFO_MODE_PARTITION:
+                                       file = strdup(entry[DFU_INFO_PARTITION]);
+                                       break;
+                               case DFU_INFO_MODE_FILE:
+                               {
+                                       int path_prefix = strlen(DFU_MOUNT_PATH);
+                                       int path_suffix = strlen(entry[DFU_INFO_PATH]);
+                                       int path_name = strlen(entry[DFU_INFO_NAME]);
+
+                                       ret = mount_dev(entry[DFU_INFO_PARTITION]);
+                                       if (ret < 0)
+                                               return -EINVAL;
+
+                                       file = malloc(path_prefix + path_suffix + path_name + 1);
+                                       if (!file) {
+                                               umount_dev();
+                                               return -ENOMEM;
+                                       }
+
+                                       strncpy(file, DFU_MOUNT_PATH, path_prefix + 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",
+                                               entry_name);
+                                       return -EINVAL;
+                               }
+                       }
+               }
+
+               if (file)
+                       break;
+       }
+
+       if (!file)
+               return -EINVAL;
+
+       fd = open(file, O_WRONLY);
+       if (fd < 0) {
+               fprintf(stderr,
+                       "cannot open target: %s\n", name);
+               fd = -EIO;
+       }
+
+       free(file);
+
+       return fd;
+}
+
+/* Set entry values for dfu */
 static int dfu_start_entry(struct dfu_entry *e, char **entry, uint64_t size)
 {
        char *file;
@@ -480,6 +560,8 @@ static int dfu_start_entry(struct dfu_entry *e, char **entry, uint64_t size)
        e->buf_len = 0;
        e->transfer_done = 0;
 
+       /* Check if there is the slot B */
+       e->fd_b = find_slot_b(e->ctx, entry[DFU_INFO_NAME]);
 err:
        free(file);
 
@@ -515,6 +597,8 @@ struct dfu_entry *dfu_start(struct dfu_context *ctx,
        if (!e)
                return NULL;
 
+       e->ctx = ctx;
+
        ret = dfu_start_entry(e, entry, size);
        if (ret < 0) {
                fprintf(stderr, "Cannot start download: %s\n", filename);
@@ -527,7 +611,6 @@ struct dfu_entry *dfu_start(struct dfu_context *ctx,
        else
                fprintf(stdout, "\n%s", filename);
 
-       e->ctx = ctx;
        pthread_create(&ctx->thread, NULL, dfu_thread_main, e);
 
        return e;
@@ -544,6 +627,7 @@ void dfu_sync(struct dfu_entry *e)
        pthread_mutex_unlock(&ctx->sync_mutex);
 
        close(e->fd);
+       close(e->fd_b);
 
        if (*info[DFU_INFO_MODE] == DFU_INFO_MODE_FILE)
                umount_dev();
index adceb714ee462e08bc261075f90936bc3b19fa9c..7daf8286096870b351309ce5cb32df52ccd1894e 100644 (file)
--- a/src/dfu.h
+++ b/src/dfu.h
@@ -25,7 +25,8 @@ struct dfu_context;
 struct dfu_entry {
        struct dfu_context *ctx;
        char **entry;
-       int fd;
+       int fd;                 /* FD of slot A */
+       int fd_b;               /* FD of Slot B */
        uint64_t file_size;     /* size of a flashing file */
        void *buffer;           /* receive buffer for flashing */
        unsigned long buf_len;  /* filled size of buffer */