summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-01-30 16:30:43 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2018-02-09 10:25:37 +0100
commite5098495d4be465d6a93b4bbd9a59257c48ce068 (patch)
tree963ac6423acedc42a5647d2491f00b7a065d4a6d /drivers
parent31a7e68f1bd45c076262ccba2a5f3f9333c62644 (diff)
downloadbarebox-e5098495d4be465d6a93b4bbd9a59257c48ce068.tar.gz
barebox-e5098495d4be465d6a93b4bbd9a59257c48ce068.tar.xz
usb: gadget: fastboot: Add option to download to a buffer
This adds an option to download the image data to a temporary buffer rather than to a file. While a file is generally the better option, in some special cases a buffer is better for memory usage. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/Kconfig12
-rw-r--r--drivers/usb/gadget/f_fastboot.c102
2 files changed, 88 insertions, 26 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index e2dc7807a0..b0408e3bbe 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -68,4 +68,16 @@ config USB_GADGET_FASTBOOT_SPARSE
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 d349227f08..b851e8d1c3 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -76,11 +76,21 @@ struct f_fastboot {
struct usb_request *in_req, *out_req;
struct file_list *files;
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);
@@ -605,10 +615,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;
@@ -646,10 +660,19 @@ static void cb_download(struct f_fastboot *f_fb, const char *cmd)
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) {
@@ -711,11 +734,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)
@@ -850,7 +875,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,8 +911,16 @@ static void cb_flash(struct f_fastboot *f_fb, const char *cmd)
{
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);
@@ -908,6 +941,11 @@ static void cb_flash(struct f_fastboot *f_fb, const char *cmd)
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)
fastboot_tx_print(f_fb, "FAILwriting sparse image: %s",
@@ -925,17 +963,19 @@ static void cb_flash(struct f_fastboot *f_fb, const char *cmd)
mtd = get_mtd(f_fb, fentry->filename);
- ret = do_ubiformat(f_fb, mtd, FASTBOOT_TMPFILE);
- if (ret)
+ 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));
+ 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,
};
@@ -944,19 +984,22 @@ static void cb_flash(struct f_fastboot *f_fb, const char *cmd)
fastboot_tx_print(f_fb, "INFOThis is a barebox image...");
- ret = read_file_2(data.imagefile, &data.len, &image,
- f_fb->download_size);
- if (ret) {
- fastboot_tx_print(f_fb, "FAILreading barebox");
- goto out;
+ 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)
fastboot_tx_print(f_fb, "FAILupdate barebox: %s", strerror(-ret));
@@ -964,7 +1007,10 @@ static void cb_flash(struct f_fastboot *f_fb, const char *cmd)
}
copy:
- ret = copy_file(FASTBOOT_TMPFILE, filename, 1);
+ 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)
fastboot_tx_print(f_fb, "FAILwrite partition: %s", strerror(-ret));
@@ -973,7 +1019,11 @@ out:
if (!ret)
fastboot_tx_print(f_fb, "OKAY");
- unlink(FASTBOOT_TMPFILE);
+ free(f_fb->buf);
+ f_fb->buf = NULL;
+
+ if (!fastboot_download_to_buf(f_fb))
+ unlink(FASTBOOT_TMPFILE);
}
static void cb_erase(struct f_fastboot *f_fb, const char *cmd)