X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fdfu%2Fdfu.c;h=a298c2c43999bd0970ba3e7ac55bbb554a97a890;hb=HEAD;hp=318949529b302db73867f4bd311aa6203539fe7b;hpb=282ce6454c45409805e2c470bbec170d21a4bd35;p=oweals%2Fu-boot.git diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 318949529b..a298c2c439 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -7,7 +7,9 @@ */ #include +#include #include +#include #include #include #include @@ -20,6 +22,25 @@ static LIST_HEAD(dfu_list); static int dfu_alt_num; static int alt_num_cnt; static struct hash_algo *dfu_hash_algo; +#ifdef CONFIG_DFU_TIMEOUT +static unsigned long dfu_timeout = 0; +#endif + +/* + * The purpose of the dfu_flush_callback() function is to + * provide callback for dfu user + */ +__weak void dfu_flush_callback(struct dfu_entity *dfu) +{ +} + +/* + * The purpose of the dfu_initiated_callback() function is to + * provide callback for dfu user + */ +__weak void dfu_initiated_callback(struct dfu_entity *dfu) +{ +} /* * The purpose of the dfu_usb_get_reset() function is to @@ -41,6 +62,18 @@ __weak bool dfu_usb_get_reset(void) #endif } +#ifdef CONFIG_DFU_TIMEOUT +void dfu_set_timeout(unsigned long timeout) +{ + dfu_timeout = timeout; +} + +unsigned long dfu_get_timeout(void) +{ + return dfu_timeout; +} +#endif + static int dfu_find_alt_num(const char *s) { int i = 0; @@ -52,6 +85,54 @@ static int dfu_find_alt_num(const char *s) return ++i; } +/* + * treat dfu_alt_info with several interface information + * to allow DFU on several device with one command, + * the string format is + * interface devstring'='alternate list (';' separated) + * and each interface separated by '&' + */ +int dfu_config_interfaces(char *env) +{ + struct dfu_entity *dfu; + char *s, *i, *d, *a, *part; + int ret = -EINVAL; + int n = 1; + + s = env; + for (; *s; s++) { + if (*s == ';') + n++; + if (*s == '&') + n++; + } + ret = dfu_alt_init(n, &dfu); + if (ret) + return ret; + + s = env; + while (s) { + ret = -EINVAL; + i = strsep(&s, " "); + if (!i) + break; + d = strsep(&s, "="); + if (!d) + break; + a = strsep(&s, "&"); + if (!a) + a = s; + do { + part = strsep(&a, ";"); + ret = dfu_alt_add(dfu, i, d, part); + if (ret) + return ret; + } while (a); + } + + return ret; +} + int dfu_init_env_entities(char *interface, char *devstr) { const char *str_env; @@ -68,7 +149,11 @@ int dfu_init_env_entities(char *interface, char *devstr) } env_bkp = strdup(str_env); - ret = dfu_config_entities(env_bkp, interface, devstr); + if (!interface && !devstr) + ret = dfu_config_interfaces(env_bkp); + else + ret = dfu_config_entities(env_bkp, interface, devstr); + if (ret) { pr_err("DFU entities configuration failed!\n"); pr_err("(partition table does not match dfu_alt_info?)\n"); @@ -82,6 +167,7 @@ done: static unsigned char *dfu_buf; static unsigned long dfu_buf_size; +static enum dfu_device_type dfu_buf_device_type; unsigned char *dfu_free_buf(void) { @@ -99,6 +185,10 @@ unsigned char *dfu_get_buf(struct dfu_entity *dfu) { char *s; + /* manage several entity with several contraint */ + if (dfu_buf && dfu->dev_type != dfu_buf_device_type) + dfu_free_buf(); + if (dfu_buf != NULL) return dfu_buf; @@ -117,6 +207,7 @@ unsigned char *dfu_get_buf(struct dfu_entity *dfu) printf("%s: Could not memalign 0x%lx bytes\n", __func__, dfu_buf_size); + dfu_buf_device_type = dfu->dev_type; return dfu_buf; } @@ -204,6 +295,7 @@ int dfu_transaction_initiate(struct dfu_entity *dfu, bool read) } dfu->inited = 1; + dfu_initiated_callback(dfu); return 0; } @@ -223,6 +315,8 @@ int dfu_flush(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num) printf("\nDFU complete %s: 0x%08x\n", dfu_hash_algo->name, dfu->crc); + dfu_flush_callback(dfu); + dfu_transaction_cleanup(dfu); return ret; @@ -337,6 +431,8 @@ static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf, int size) debug("%s: Read error!\n", __func__); return ret; } + if (dfu->b_left == 0) + break; dfu->offset += dfu->b_left; dfu->r_left -= dfu->b_left; @@ -401,6 +497,9 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, if (strcmp(interface, "mmc") == 0) { if (dfu_fill_entity_mmc(dfu, devstr, s)) return -1; + } else if (strcmp(interface, "mtd") == 0) { + if (dfu_fill_entity_mtd(dfu, devstr, s)) + return -1; } else if (strcmp(interface, "nand") == 0) { if (dfu_fill_entity_nand(dfu, devstr, s)) return -1; @@ -410,6 +509,9 @@ static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt, } else if (strcmp(interface, "sf") == 0) { if (dfu_fill_entity_sf(dfu, devstr, s)) return -1; + } else if (strcmp(interface, "virt") == 0) { + if (dfu_fill_entity_virt(dfu, devstr, s)) + return -1; } else { printf("%s: Device %s not (yet) supported!\n", __func__, interface); @@ -438,13 +540,12 @@ void dfu_free_entities(void) alt_num_cnt = 0; } -int dfu_config_entities(char *env, char *interface, char *devstr) +int dfu_alt_init(int num, struct dfu_entity **dfu) { - struct dfu_entity *dfu; - int i, ret; char *s; + int ret; - dfu_alt_num = dfu_find_alt_num(env); + dfu_alt_num = num; debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num); dfu_hash_algo = NULL; @@ -455,21 +556,49 @@ int dfu_config_entities(char *env, char *interface, char *devstr) pr_err("Hash algorithm %s not supported\n", s); } - dfu = calloc(sizeof(*dfu), dfu_alt_num); - if (!dfu) + *dfu = calloc(sizeof(struct dfu_entity), dfu_alt_num); + if (!*dfu) return -1; - for (i = 0; i < dfu_alt_num; i++) { + return 0; +} + +int dfu_alt_add(struct dfu_entity *dfu, char *interface, char *devstr, char *s) +{ + struct dfu_entity *p_dfu; + int ret; + + if (alt_num_cnt >= dfu_alt_num) + return -1; + + p_dfu = &dfu[alt_num_cnt]; + ret = dfu_fill_entity(p_dfu, s, alt_num_cnt, interface, devstr); + if (ret) + return -1; + + list_add_tail(&p_dfu->list, &dfu_list); + alt_num_cnt++; + + return 0; +} + +int dfu_config_entities(char *env, char *interface, char *devstr) +{ + struct dfu_entity *dfu; + int i, ret; + char *s; + + ret = dfu_alt_init(dfu_find_alt_num(env), &dfu); + if (ret) + return -1; + + for (i = 0; i < dfu_alt_num; i++) { s = strsep(&env, ";"); - ret = dfu_fill_entity(&dfu[i], s, alt_num_cnt, interface, - devstr); + ret = dfu_alt_add(dfu, interface, devstr, s); if (ret) { /* We will free "dfu" in dfu_free_entities() */ return -1; } - - list_add_tail(&dfu[i].list, &dfu_list); - alt_num_cnt++; } return 0; @@ -477,14 +606,15 @@ int dfu_config_entities(char *env, char *interface, char *devstr) const char *dfu_get_dev_type(enum dfu_device_type t) { - const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM", "SF" }; + const char *const dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM", + "SF", "MTD", "VIRT"}; return dev_t[t]; } const char *dfu_get_layout(enum dfu_layout l) { - const char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2", - "EXT3", "EXT4", "RAM_ADDR" }; + const char *const dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2", + "EXT3", "EXT4", "RAM_ADDR" }; return dfu_layout[l]; }