summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-03-05 08:53:56 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2018-03-05 08:53:56 +0100
commit438f66ad739298e2c284f8af92be3a9a71e3cd81 (patch)
tree7bf89477962fa916466fa4d8252cec9fabc81f42
parent4160c616e2c7b89920e4af251818133990404565 (diff)
parented1dded0898faa1f917309172f2065014756c59f (diff)
downloadbarebox-438f66ad739298e2c284f8af92be3a9a71e3cd81.tar.gz
barebox-438f66ad739298e2c284f8af92be3a9a71e3cd81.tar.xz
Merge branch 'for-next/fastboot'
-rw-r--r--common/ubiformat.c55
-rw-r--r--drivers/usb/gadget/Kconfig22
-rw-r--r--drivers/usb/gadget/f_fastboot.c216
-rw-r--r--drivers/usb/gadget/multi.c2
-rw-r--r--include/ubiformat.h7
-rw-r--r--include/usb/fastboot.h17
6 files changed, 222 insertions, 97 deletions
diff --git a/common/ubiformat.c b/common/ubiformat.c
index f728119b9a..9fe1c7c501 100644
--- a/common/ubiformat.c
+++ b/common/ubiformat.c
@@ -187,16 +187,22 @@ static int mark_bad(struct ubiformat_args *args, struct mtd_info *mtd,
static int flash_image(struct ubiformat_args *args, struct mtd_info *mtd,
const struct ubigen_info *ui, struct ubi_scan_info *si)
{
- int fd, img_ebs, eb, written_ebs = 0, ret = -1, eb_cnt;
+ int fd = 0, img_ebs, eb, written_ebs = 0, ret = -1, eb_cnt;
off_t st_size;
char *buf = NULL;
uint64_t lastprint = 0;
+ const void *inbuf = NULL;
eb_cnt = mtd_num_pebs(mtd);
- fd = open_file(args->image, &st_size);
- if (fd < 0)
- return fd;
+ if (args->image) {
+ fd = open_file(args->image, &st_size);
+ if (fd < 0)
+ return fd;
+ } else {
+ inbuf = args->image_buf;
+ st_size = args->image_size;
+ }
buf = malloc(mtd->erasesize);
if (!buf) {
@@ -207,20 +213,20 @@ static int flash_image(struct ubiformat_args *args, struct mtd_info *mtd,
img_ebs = st_size / mtd->erasesize;
if (img_ebs > si->good_cnt) {
- sys_errmsg("file \"%s\" is too large (%lld bytes)",
- args->image, (long long)st_size);
+ sys_errmsg("image is too large (%lld bytes)",
+ (long long)st_size);
goto out_close;
}
if (st_size % mtd->erasesize) {
- sys_errmsg("file \"%s\" (size %lld bytes) is not multiple of "
+ sys_errmsg("image (size %lld bytes) is not multiple of "
"eraseblock size (%d bytes)",
- args->image, (long long)st_size, mtd->erasesize);
+ (long long)st_size, mtd->erasesize);
goto out_close;
}
if (st_size == 0) {
- sys_errmsg("file \"%s\" has size 0 bytes", args->image);
+ sys_errmsg("image has size 0 bytes");
goto out_close;
}
@@ -260,11 +266,16 @@ static int flash_image(struct ubiformat_args *args, struct mtd_info *mtd,
continue;
}
- err = read_full(fd, buf, mtd->erasesize);
- if (err < 0) {
- sys_errmsg("failed to read eraseblock %d from \"%s\"",
- written_ebs, args->image);
- goto out_close;
+ if (args->image) {
+ err = read_full(fd, buf, mtd->erasesize);
+ if (err < 0) {
+ sys_errmsg("failed to read eraseblock %d from image",
+ written_ebs);
+ goto out_close;
+ }
+ } else {
+ memcpy(buf, inbuf, mtd->erasesize);
+ inbuf += mtd->erasesize;
}
if (args->override_ec)
@@ -280,8 +291,8 @@ static int flash_image(struct ubiformat_args *args, struct mtd_info *mtd,
err = change_ech((struct ubi_ec_hdr *)buf, ui->image_seq, ec);
if (err) {
- errmsg("bad EC header at eraseblock %d of \"%s\"",
- written_ebs, args->image);
+ errmsg("bad EC header at eraseblock %d of image",
+ written_ebs);
goto out_close;
}
@@ -317,7 +328,8 @@ static int flash_image(struct ubiformat_args *args, struct mtd_info *mtd,
out_close:
free(buf);
- close(fd);
+ if (args->image)
+ close(fd);
return ret;
}
@@ -454,6 +466,11 @@ out_free:
return -1;
}
+static bool ubiformat_has_image(struct ubiformat_args *args)
+{
+ return args->image || args->image_buf;
+}
+
int ubiformat(struct mtd_info *mtd, struct ubiformat_args *args)
{
int err, verbose, eb_cnt;
@@ -555,7 +572,7 @@ int ubiformat(struct mtd_info *mtd, struct ubiformat_args *args)
goto out_free;
}
- if (si->good_cnt < 2 && (!args->novtbl || args->image)) {
+ if (si->good_cnt < 2 && (!args->novtbl || ubiformat_has_image(args))) {
errmsg("too few non-bad eraseblocks (%d) on %s",
si->good_cnt, mtd->name);
err = -EINVAL;
@@ -654,7 +671,7 @@ int ubiformat(struct mtd_info *mtd, struct ubiformat_args *args)
}
}
- if (args->image) {
+ if (ubiformat_has_image(args)) {
err = flash_image(args, mtd, &ui, si);
if (err < 0)
goto out_free;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index b612d39a8e..b0408e3bbe 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -57,7 +57,27 @@ config USB_GADGET_FASTBOOT
bool
select BANNER
select FILE_LIST
- select IMAGE_SPARSE
prompt "Android Fastboot support"
+config USB_GADGET_FASTBOOT_SPARSE
+ bool
+ select IMAGE_SPARSE
+ prompt "Enable Fastboot sparse image support"
+ help
+ Sparse images are a way for the fastboot protocol to write
+ images that are bigger than the available memory. If unsure,
+ say yes here.
+
+config USB_GADGET_FASTBOOT_BUF
+ bool
+ depends on USB_GADGET_FASTBOOT
+ prompt "Download files to temporary buffer instead of file"
+ help
+ With this option enabled the fastboot code will download files to a
+ temporary buffer instead of a temporary file. Normally you want to
+ use a file as this also works when your memory is fragmented. However,
+ in some special cases, when the file consumer also better copes with
+ a buffer, then using a buffer might be better.
+
+ Say no here unless you know what you are doing.
endif
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 87a43cc60e..787b1205ec 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -71,16 +71,29 @@ struct fb_variable {
struct f_fastboot {
struct usb_function func;
- /* IN/OUT EP's and correspoinding requests */
+ /* IN/OUT EP's and corresponding requests */
struct usb_ep *in_ep, *out_ep;
struct usb_request *in_req, *out_req;
struct file_list *files;
+ int (*cmd_exec)(struct f_fastboot *, const char *cmd);
+ int (*cmd_flash)(struct f_fastboot *, struct file_list_entry *entry,
+ const char *filename, const void *buf, size_t len);
int download_fd;
+ void *buf;
+
size_t download_bytes;
size_t download_size;
struct list_head variables;
};
+static inline bool fastboot_download_to_buf(struct f_fastboot *f_fb)
+{
+ if (IS_ENABLED(CONFIG_USB_GADGET_FASTBOOT_BUF))
+ return true;
+ else
+ return false;
+}
+
static inline struct f_fastboot *func_to_fastboot(struct usb_function *f)
{
return container_of(f, struct f_fastboot, func);
@@ -317,13 +330,17 @@ static int fastboot_bind(struct usb_configuration *c, struct usb_function *f)
struct fb_variable *var;
f_fb->files = opts->files;
+ f_fb->cmd_exec = opts->cmd_exec;
+ f_fb->cmd_flash = opts->cmd_flash;
var = fb_addvar(f_fb, "version");
fb_setvar(var, "0.4");
var = fb_addvar(f_fb, "bootloader-version");
fb_setvar(var, release_string);
- var = fb_addvar(f_fb, "max-download-size");
- fb_setvar(var, "%u", fastboot_max_download_size);
+ if (IS_ENABLED(USB_GADGET_FASTBOOT_SPARSE)) {
+ var = fb_addvar(f_fb, "max-download-size");
+ fb_setvar(var, "%u", fastboot_max_download_size);
+ }
if (IS_ENABLED(CONFIG_BAREBOX_UPDATE) && opts->export_bbu)
bbu_handlers_iterate(fastboot_add_bbu_variables, f_fb);
@@ -555,10 +572,8 @@ static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
restart_machine();
}
-static void cb_reboot(struct usb_ep *ep, struct usb_request *req, const char *cmd)
+static void cb_reboot(struct f_fastboot *f_fb, const char *cmd)
{
- struct f_fastboot *f_fb = req->context;
-
f_fb->in_req->complete = compl_do_reset;
fastboot_tx_print(f_fb, "OKAY");
}
@@ -570,9 +585,8 @@ static int strcmp_l1(const char *s1, const char *s2)
return strncmp(s1, s2, strlen(s1));
}
-static void cb_getvar(struct usb_ep *ep, struct usb_request *req, const char *cmd)
+static void cb_getvar(struct f_fastboot *f_fb, const char *cmd)
{
- struct f_fastboot *f_fb = req->context;
struct fb_variable *var;
pr_debug("getvar: \"%s\"\n", cmd);
@@ -606,10 +620,14 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
return;
}
- ret = write(f_fb->download_fd, buffer, req->actual);
- if (ret < 0) {
- fastboot_tx_print(f_fb, "FAIL%s", strerror(-ret));
- return;
+ if (fastboot_download_to_buf(f_fb)) {
+ memcpy(f_fb->buf + f_fb->download_bytes, buffer, req->actual);
+ } else {
+ ret = write(f_fb->download_fd, buffer, req->actual);
+ if (ret < 0) {
+ fastboot_tx_print(f_fb, "FAIL%s", strerror(-ret));
+ return;
+ }
}
f_fb->download_bytes += req->actual;
@@ -638,10 +656,8 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
usb_ep_queue(ep, req);
}
-static void cb_download(struct usb_ep *ep, struct usb_request *req, const char *cmd)
+static void cb_download(struct f_fastboot *f_fb, const char *cmd)
{
- struct f_fastboot *f_fb = req->context;
-
f_fb->download_size = simple_strtoul(cmd, NULL, 16);
f_fb->download_bytes = 0;
@@ -649,15 +665,26 @@ static void cb_download(struct usb_ep *ep, struct usb_request *req, const char *
init_progression_bar(f_fb->download_size);
- f_fb->download_fd = open(FASTBOOT_TMPFILE, O_WRONLY | O_CREAT | O_TRUNC);
- if (f_fb->download_fd < 0) {
- fastboot_tx_print(f_fb, "FAILInternal Error");
- return;
+ if (fastboot_download_to_buf(f_fb)) {
+ free(f_fb->buf);
+ f_fb->buf = malloc(f_fb->download_size);
+ if (!f_fb->buf) {
+ fastboot_tx_print(f_fb, "FAILnot enough memory");
+ return;
+ }
+ } else {
+ f_fb->download_fd = open(FASTBOOT_TMPFILE, O_WRONLY | O_CREAT | O_TRUNC);
+ if (f_fb->download_fd < 0) {
+ fastboot_tx_print(f_fb, "FAILInternal Error");
+ return;
+ }
}
if (!f_fb->download_size) {
fastboot_tx_print(f_fb, "FAILdata invalid size");
} else {
+ struct usb_request *req = f_fb->out_req;
+ struct usb_ep *ep = f_fb->out_ep;
fastboot_tx_print(f_fb, "DATA%08x", f_fb->download_size);
req->complete = rx_handler_dl_image;
req->length = EP_BUFFER_SIZE;
@@ -686,11 +713,8 @@ static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req)
pr_err("Booting failed\n");
}
-static void __maybe_unused cb_boot(struct usb_ep *ep, struct usb_request *req,
- const char *opt)
+static void __maybe_unused cb_boot(struct f_fastboot *f_fb, const char *opt)
{
- struct f_fastboot *f_fb = req->context;
-
f_fb->in_req->complete = do_bootm_on_complete;
fastboot_tx_print(f_fb, "OKAY");
}
@@ -715,11 +739,13 @@ static struct mtd_info *get_mtd(struct f_fastboot *f_fb, const char *filename)
}
static int do_ubiformat(struct f_fastboot *f_fb, struct mtd_info *mtd,
- const char *file)
+ const char *file, const void *buf, size_t len)
{
struct ubiformat_args args = {
.yes = 1,
.image = file,
+ .image_buf = buf,
+ .image_size = len,
};
if (!file)
@@ -854,7 +880,7 @@ static int fastboot_handle_sparse(struct f_fastboot *f_fb,
}
if (pos == 0) {
- ret = do_ubiformat(f_fb, mtd, NULL);
+ ret = do_ubiformat(f_fb, mtd, NULL, NULL, 0);
if (ret)
goto out;
}
@@ -886,13 +912,20 @@ out_close_fd:
return ret;
}
-static void cb_flash(struct usb_ep *ep, struct usb_request *req, const char *cmd)
+static void cb_flash(struct f_fastboot *f_fb, const char *cmd)
{
- struct f_fastboot *f_fb = req->context;
struct file_list_entry *fentry;
int ret;
- const char *filename = NULL;
- enum filetype filetype = file_name_detect_type(FASTBOOT_TMPFILE);
+ const char *filename = NULL, *sourcefile;
+ enum filetype filetype;
+
+ if (fastboot_download_to_buf(f_fb)) {
+ sourcefile = NULL;
+ filetype = file_detect_type(f_fb->buf, f_fb->download_bytes);
+ } else {
+ sourcefile = FASTBOOT_TMPFILE;
+ filetype = file_name_detect_type(FASTBOOT_TMPFILE);
+ }
fastboot_tx_print(f_fb, "INFOCopying file to %s...", cmd);
@@ -900,45 +933,61 @@ static void cb_flash(struct usb_ep *ep, struct usb_request *req, const char *cmd
if (!fentry) {
fastboot_tx_print(f_fb, "FAILNo such partition: %s", cmd);
- return;
+ ret = -ENOENT;
+ goto out;
+ }
+
+ if (f_fb->cmd_flash) {
+ ret = f_fb->cmd_flash(f_fb, fentry, sourcefile, f_fb->buf,
+ f_fb->download_size);
+ if (ret != FASTBOOT_CMD_FALLTHROUGH)
+ goto out;
}
filename = fentry->filename;
if (filetype == filetype_android_sparse) {
+ if (!IS_ENABLED(USB_GADGET_FASTBOOT_SPARSE)) {
+ fastboot_tx_print(f_fb, "FAILsparse image not supported");
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (fastboot_download_to_buf(f_fb)) {
+ fastboot_tx_print(f_fb, "FAILsparse image not supported");
+ goto out;
+ }
+
ret = fastboot_handle_sparse(f_fb, fentry);
- if (ret) {
+ if (ret)
fastboot_tx_print(f_fb, "FAILwriting sparse image: %s",
strerror(-ret));
- return;
- }
goto out;
}
ret = check_ubi(f_fb, fentry, filetype);
if (ret < 0)
- return;
+ goto out;
if (ret > 0) {
struct mtd_info *mtd;
mtd = get_mtd(f_fb, fentry->filename);
- ret = do_ubiformat(f_fb, mtd, FASTBOOT_TMPFILE);
+ ret = do_ubiformat(f_fb, mtd, sourcefile, f_fb->buf,
+ f_fb->download_size);
if (ret) {
fastboot_tx_print(f_fb, "FAILwrite partition: %s", strerror(-ret));
- return;
+ goto out;
}
goto out;
}
if (IS_ENABLED(CONFIG_BAREBOX_UPDATE) && filetype_is_barebox_image(filetype)) {
- void *image;
struct bbu_data data = {
.devicefile = filename,
- .imagefile = FASTBOOT_TMPFILE,
.flags = BBU_FLAG_YES,
};
@@ -947,43 +996,50 @@ static void cb_flash(struct usb_ep *ep, struct usb_request *req, const char *cmd
fastboot_tx_print(f_fb, "INFOThis is a barebox image...");
- image = read_file(data.imagefile, &data.len);
- if (!image) {
- fastboot_tx_print(f_fb, "FAILreading barebox");
- return;
+ if (fastboot_download_to_buf(f_fb)) {
+ data.len = f_fb->download_size;
+ } else {
+ ret = read_file_2(data.imagefile, &data.len, &f_fb->buf,
+ f_fb->download_size);
+ if (ret) {
+ fastboot_tx_print(f_fb, "FAILreading barebox");
+ goto out;
+ }
}
- data.image = image;
+ data.image = f_fb->buf;
+ data.imagefile = sourcefile;
ret = barebox_update(&data);
- free(image);
-
- if (ret) {
+ if (ret)
fastboot_tx_print(f_fb, "FAILupdate barebox: %s", strerror(-ret));
- return;
- }
goto out;
}
copy:
- ret = copy_file(FASTBOOT_TMPFILE, filename, 1);
-
- unlink(FASTBOOT_TMPFILE);
+ if (fastboot_download_to_buf(f_fb))
+ ret = write_file(filename, f_fb->buf, f_fb->download_size);
+ else
+ ret = copy_file(FASTBOOT_TMPFILE, filename, 1);
- if (ret) {
+ if (ret)
fastboot_tx_print(f_fb, "FAILwrite partition: %s", strerror(-ret));
- return;
- }
out:
- fastboot_tx_print(f_fb, "OKAY");
+ if (!ret)
+ fastboot_tx_print(f_fb, "OKAY");
+
+ free(f_fb->buf);
+ f_fb->buf = NULL;
+
+ if (!fastboot_download_to_buf(f_fb))
+ unlink(FASTBOOT_TMPFILE);
}
-static void cb_erase(struct usb_ep *ep, struct usb_request *req, const char *cmd)
+static void cb_erase(struct f_fastboot *f_fb, const char *cmd)
{
- struct f_fastboot *f_fb = req->context;
struct file_list_entry *fentry;
int ret;
const char *filename = NULL;
@@ -1020,33 +1076,32 @@ static void cb_erase(struct usb_ep *ep, struct usb_request *req, const char *cmd
struct cmd_dispatch_info {
char *cmd;
- void (*cb)(struct usb_ep *ep, struct usb_request *req, const char *opt);
+ void (*cb)(struct f_fastboot *f_fb, const char *opt);
};
-static void fb_run_command(struct usb_ep *ep, struct usb_request *req, const char *cmd,
+static void fb_run_command(struct f_fastboot *f_fb, const char *cmdbuf,
const struct cmd_dispatch_info *cmds, int num_commands)
{
- void (*func_cb)(struct usb_ep *ep, struct usb_request *req, const char *cmd) = NULL;
- struct f_fastboot *f_fb = req->context;
+ const struct cmd_dispatch_info *cmd;
int i;
console_countdown_abort();
for (i = 0; i < num_commands; i++) {
- if (!strcmp_l1(cmds[i].cmd, cmd)) {
- func_cb = cmds[i].cb;
- cmd += strlen(cmds[i].cmd);
- func_cb(ep, req, cmd);
+ cmd = &cmds[i];
+
+ if (!strcmp_l1(cmd->cmd, cmdbuf)) {
+ cmd->cb(f_fb, cmdbuf + strlen(cmd->cmd));
+
return;
}
}
- fastboot_tx_print(f_fb, "FAILunknown command %s", cmd);
+ fastboot_tx_print(f_fb, "FAILunknown command %s", cmdbuf);
}
-static void cb_oem_getenv(struct usb_ep *ep, struct usb_request *req, const char *cmd)
+static void cb_oem_getenv(struct f_fastboot *f_fb, const char *cmd)
{
- struct f_fastboot *f_fb = req->context;
const char *value;
pr_debug("%s: \"%s\"\n", __func__, cmd);
@@ -1057,9 +1112,8 @@ static void cb_oem_getenv(struct usb_ep *ep, struct usb_request *req, const char
fastboot_tx_print(f_fb, "OKAY");
}
-static void cb_oem_setenv(struct usb_ep *ep, struct usb_request *req, const char *cmd)
+static void cb_oem_setenv(struct f_fastboot *f_fb, const char *cmd)
{
- struct f_fastboot *f_fb = req->context;
char *var = xstrdup(cmd);
char *value;
int ret;
@@ -1086,9 +1140,8 @@ out:
fastboot_tx_print(f_fb, "FAIL%s", strerror(-ret));
}
-static void cb_oem_exec(struct usb_ep *ep, struct usb_request *req, const char *cmd)
+static void cb_oem_exec(struct f_fastboot *f_fb, const char *cmd)
{
- struct f_fastboot *f_fb = req->context;
int ret;
if (!IS_ENABLED(CONFIG_COMMAND_SUPPORT)) {
@@ -1118,11 +1171,11 @@ static const struct cmd_dispatch_info cmd_oem_dispatch_info[] = {
},
};
-static void cb_oem(struct usb_ep *ep, struct usb_request *req, const char *cmd)
+static void cb_oem(struct f_fastboot *f_fb, const char *cmd)
{
pr_debug("%s: \"%s\"\n", __func__, cmd);
- fb_run_command(ep, req, cmd, cmd_oem_dispatch_info, ARRAY_SIZE(cmd_oem_dispatch_info));
+ fb_run_command(f_fb, cmd, cmd_oem_dispatch_info, ARRAY_SIZE(cmd_oem_dispatch_info));
}
static const struct cmd_dispatch_info cmd_dispatch_info[] = {
@@ -1155,15 +1208,23 @@ static const struct cmd_dispatch_info cmd_dispatch_info[] = {
static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
{
char *cmdbuf = req->buf;
+ struct f_fastboot *f_fb = req->context;
+ int ret;
if (req->status != 0)
return;
*(cmdbuf + req->actual) = 0;
- fb_run_command(ep, req, cmdbuf, cmd_dispatch_info,
- ARRAY_SIZE(cmd_dispatch_info));
+ if (f_fb->cmd_exec) {
+ ret = f_fb->cmd_exec(f_fb, cmdbuf);
+ if (ret != FASTBOOT_CMD_FALLTHROUGH)
+ goto done;
+ }
+ fb_run_command(f_fb, cmdbuf, cmd_dispatch_info,
+ ARRAY_SIZE(cmd_dispatch_info));
+done:
*cmdbuf = '\0';
req->actual = 0;
memset(req->buf, 0, EP_BUFFER_SIZE);
@@ -1172,7 +1233,8 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
static int fastboot_globalvars_init(void)
{
- globalvar_add_simple_int("usbgadget.fastboot_max_download_size",
+ if (IS_ENABLED(USB_GADGET_FASTBOOT_SPARSE))
+ globalvar_add_simple_int("usbgadget.fastboot_max_download_size",
&fastboot_max_download_size, "%u");
return 0;
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c
index 44969be0c9..d6edfb8cf2 100644
--- a/drivers/usb/gadget/multi.c
+++ b/drivers/usb/gadget/multi.c
@@ -128,6 +128,8 @@ static int multi_bind_fastboot(struct usb_composite_dev *cdev)
opts = container_of(fi_fastboot, struct f_fastboot_opts, func_inst);
opts->files = gadget_multi_opts->fastboot_opts.files;
+ opts->cmd_exec = gadget_multi_opts->fastboot_opts.cmd_exec;
+ opts->cmd_flash = gadget_multi_opts->fastboot_opts.cmd_flash;
opts->export_bbu = gadget_multi_opts->fastboot_opts.export_bbu;
f_fastboot = usb_get_function(fi_fastboot);
diff --git a/include/ubiformat.h b/include/ubiformat.h
index 8305a853c7..8a7a16ac18 100644
--- a/include/ubiformat.h
+++ b/include/ubiformat.h
@@ -15,7 +15,14 @@ struct ubiformat_args {
int ubi_ver;
uint32_t image_seq;
long long ec;
+
+ /*
+ * Either set image if you have a file or set image_buf / image_size
+ * if you have a buffer.
+ */
const char *image;
+ const void *image_buf;
+ loff_t image_size;
};
int ubiformat(struct mtd_info *mtd, struct ubiformat_args *args);
diff --git a/include/usb/fastboot.h b/include/usb/fastboot.h
index ced890c9ab..00c9d00df5 100644
--- a/include/usb/fastboot.h
+++ b/include/usb/fastboot.h
@@ -5,6 +5,8 @@
#include <file-list.h>
#include <usb/composite.h>
+struct f_fastboot;
+
/**
* struct f_fastboot_opts - options to configure the fastboot gadget
* @func_inst: The USB function instance to register on
@@ -15,6 +17,21 @@ struct f_fastboot_opts {
struct usb_function_instance func_inst;
struct file_list *files;
bool export_bbu;
+ int (*cmd_exec)(struct f_fastboot *, const char *cmd);
+ int (*cmd_flash)(struct f_fastboot *, struct file_list_entry *entry,
+ const char *filename, const void *buf, size_t len);
};
+/*
+ * Return codes for the exec_cmd callback above:
+ *
+ * FASTBOOT_CMD_FALLTHROUGH - Not handled by the external command dispatcher,
+ * handle it with internal dispatcher
+ * Other than these negative error codes mean errors handling the command and
+ * zero means the command has been successfully handled.
+ */
+#define FASTBOOT_CMD_FALLTHROUGH 1
+
+int fastboot_tx_print(struct f_fastboot *f_fb, const char *fmt, ...);
+
#endif /* _USB_FASTBOOT_H */