+// SPDX-License-Identifier: GPL-2.0+
/*
* dfu.c -- DFU back-end routines
*
* Copyright (C) 2012 Samsung Electronics
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
*/
__weak bool dfu_usb_get_reset(void)
{
+#ifdef CONFIG_SPL_DFU_NO_RESET
+ return false;
+#else
return true;
+#endif
}
static int dfu_find_alt_num(const char *s)
{
const char *str_env;
char *env_bkp;
- int ret;
+ int ret = 0;
#ifdef CONFIG_SET_DFU_ALT_INFO
set_dfu_alt_info(interface, devstr);
#endif
- str_env = getenv("dfu_alt_info");
+ str_env = env_get("dfu_alt_info");
if (!str_env) {
- error("\"dfu_alt_info\" env variable not defined!\n");
+ pr_err("\"dfu_alt_info\" env variable not defined!\n");
return -EINVAL;
}
env_bkp = strdup(str_env);
ret = dfu_config_entities(env_bkp, interface, devstr);
if (ret) {
- error("DFU entities configuration failed!\n");
- return ret;
+ pr_err("DFU entities configuration failed!\n");
+ pr_err("(partition table does not match dfu_alt_info?)\n");
+ goto done;
}
+done:
free(env_bkp);
- return 0;
+ return ret;
}
static unsigned char *dfu_buf;
if (dfu_buf != NULL)
return dfu_buf;
- s = getenv("dfu_bufsiz");
+ s = env_get("dfu_bufsiz");
if (s)
dfu_buf_size = (unsigned long)simple_strtol(s, NULL, 0);
{
char *s;
- s = getenv("dfu_hash_algo");
+ s = env_get("dfu_hash_algo");
if (!s)
return NULL;
return s;
}
- error("DFU hash method: %s not supported!\n", s);
+ pr_err("DFU hash method: %s not supported!\n", s);
return NULL;
}
return ret;
}
-void dfu_write_transaction_cleanup(struct dfu_entity *dfu)
+void dfu_transaction_cleanup(struct dfu_entity *dfu)
{
/* clear everything */
dfu->crc = 0;
dfu->offset = 0;
dfu->i_blk_seq_num = 0;
- dfu->i_buf_start = dfu_buf;
- dfu->i_buf_end = dfu_buf;
+ dfu->i_buf_start = dfu_get_buf(dfu);
+ dfu->i_buf_end = dfu->i_buf_start;
dfu->i_buf = dfu->i_buf_start;
+ dfu->r_left = 0;
+ dfu->b_left = 0;
+ dfu->bad_skip = 0;
+
dfu->inited = 0;
}
+int dfu_transaction_initiate(struct dfu_entity *dfu, bool read)
+{
+ int ret = 0;
+
+ if (dfu->inited)
+ return 0;
+
+ dfu_transaction_cleanup(dfu);
+
+ if (dfu->i_buf_start == NULL)
+ return -ENOMEM;
+
+ dfu->i_buf_end = dfu->i_buf_start + dfu_get_buf_size();
+
+ if (read) {
+ ret = dfu->get_medium_size(dfu, &dfu->r_left);
+ if (ret < 0)
+ return ret;
+ debug("%s: %s %lld [B]\n", __func__, dfu->name, dfu->r_left);
+ }
+
+ dfu->inited = 1;
+
+ return 0;
+}
+
int dfu_flush(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
{
int ret = 0;
printf("\nDFU complete %s: 0x%08x\n", dfu_hash_algo->name,
dfu->crc);
- dfu_write_transaction_cleanup(dfu);
+ dfu_transaction_cleanup(dfu);
return ret;
}
__func__, dfu->name, buf, size, blk_seq_num, dfu->offset,
(unsigned long)(dfu->i_buf - dfu->i_buf_start));
- if (!dfu->inited) {
- /* initial state */
- dfu->crc = 0;
- dfu->offset = 0;
- dfu->bad_skip = 0;
- dfu->i_blk_seq_num = 0;
- dfu->i_buf_start = dfu_get_buf(dfu);
- if (dfu->i_buf_start == NULL)
- return -ENOMEM;
- dfu->i_buf_end = dfu_get_buf(dfu) + dfu_buf_size;
- dfu->i_buf = dfu->i_buf_start;
-
- dfu->inited = 1;
- }
+ ret = dfu_transaction_initiate(dfu, false);
+ if (ret < 0)
+ return ret;
if (dfu->i_blk_seq_num != blk_seq_num) {
printf("%s: Wrong sequence number! [%d] [%d]\n",
__func__, dfu->i_blk_seq_num, blk_seq_num);
- dfu_write_transaction_cleanup(dfu);
+ dfu_transaction_cleanup(dfu);
return -1;
}
if ((dfu->i_buf + size) > dfu->i_buf_end) {
ret = dfu_write_buffer_drain(dfu);
if (ret) {
- dfu_write_transaction_cleanup(dfu);
+ dfu_transaction_cleanup(dfu);
return ret;
}
}
/* we should be in buffer now (if not then size too large) */
if ((dfu->i_buf + size) > dfu->i_buf_end) {
- error("Buffer overflow! (0x%p + 0x%x > 0x%p)\n", dfu->i_buf,
+ pr_err("Buffer overflow! (0x%p + 0x%x > 0x%p)\n", dfu->i_buf,
size, dfu->i_buf_end);
- dfu_write_transaction_cleanup(dfu);
+ dfu_transaction_cleanup(dfu);
return -1;
}
if (size == 0 || (dfu->i_buf + size) > dfu->i_buf_end) {
ret = dfu_write_buffer_drain(dfu);
if (ret) {
- dfu_write_transaction_cleanup(dfu);
+ dfu_transaction_cleanup(dfu);
return ret;
}
}
debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
__func__, dfu->name, buf, size, blk_seq_num, dfu->i_buf);
- if (!dfu->inited) {
- dfu->i_buf_start = dfu_get_buf(dfu);
- if (dfu->i_buf_start == NULL)
- return -ENOMEM;
-
- dfu->r_left = dfu->get_medium_size(dfu);
- if (dfu->r_left < 0)
- return dfu->r_left;
-
- debug("%s: %s %ld [B]\n", __func__, dfu->name, dfu->r_left);
-
- dfu->i_blk_seq_num = 0;
- dfu->crc = 0;
- dfu->offset = 0;
- dfu->i_buf_end = dfu_get_buf(dfu) + dfu_buf_size;
- dfu->i_buf = dfu->i_buf_start;
- dfu->b_left = 0;
-
- dfu->bad_skip = 0;
-
- dfu->inited = 1;
- }
+ ret = dfu_transaction_initiate(dfu, true);
+ if (ret < 0)
+ return ret;
if (dfu->i_blk_seq_num != blk_seq_num) {
printf("%s: Wrong sequence number! [%d] [%d]\n",
dfu_hash_algo->name, dfu->crc);
puts("\nUPLOAD ... done\nCtrl+C to exit ...\n");
- dfu->i_blk_seq_num = 0;
- dfu->crc = 0;
- dfu->offset = 0;
- dfu->i_buf_start = dfu_buf;
- dfu->i_buf_end = dfu_buf;
- dfu->i_buf = dfu->i_buf_start;
- dfu->b_left = 0;
-
- dfu->bad_skip = 0;
-
- dfu->inited = 0;
+ dfu_transaction_cleanup(dfu);
}
return ret;
if (s) {
ret = hash_lookup_algo(s, &dfu_hash_algo);
if (ret)
- error("Hash algorithm %s not supported\n", s);
+ pr_err("Hash algorithm %s not supported\n", s);
}
dfu = calloc(sizeof(*dfu), dfu_alt_num);
s = strsep(&env, ";");
ret = dfu_fill_entity(&dfu[i], s, alt_num_cnt, interface,
devstr);
- if (ret)
+ if (ret) {
+ /* We will free "dfu" in dfu_free_entities() */
return -1;
+ }
list_add_tail(&dfu[i].list, &dfu_list);
alt_num_cnt++;
const char *dfu_get_dev_type(enum dfu_device_type t)
{
- const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM" };
+ const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND", "RAM", "SF" };
return dev_t[t];
}
dp, left, write);
ret = dfu_write(dfu, dp, write, i);
if (ret) {
- error("DFU write failed\n");
+ pr_err("DFU write failed\n");
return ret;
}
ret = dfu_flush(dfu, NULL, 0, i);
if (ret)
- error("DFU flush failed!");
+ pr_err("DFU flush failed!");
return ret;
}