diff options
Diffstat (limited to 'common/fastboot.c')
-rw-r--r-- | common/fastboot.c | 98 |
1 files changed, 72 insertions, 26 deletions
diff --git a/common/fastboot.c b/common/fastboot.c index 72e6ba3c40..d8dabd89ab 100644 --- a/common/fastboot.c +++ b/common/fastboot.c @@ -30,7 +30,9 @@ #include <ubiformat.h> #include <unistd.h> #include <magicvar.h> +#include <linux/log2.h> #include <linux/sizes.h> +#include <memory.h> #include <progress.h> #include <environment.h> #include <globalvar.h> @@ -45,7 +47,7 @@ #define FASTBOOT_VERSION "0.4" -static unsigned int fastboot_max_download_size = SZ_8M; +static unsigned int fastboot_max_download_size; static int fastboot_bbu; static char *fastboot_partitions; @@ -64,7 +66,7 @@ static void fb_setvar(struct fb_variable *var, const char *fmt, ...) va_end(ap); } -static struct fb_variable *fb_addvar(struct fastboot *fb, const char *fmt, ...) +static struct fb_variable *fb_addvar(struct fastboot *fb, struct list_head *list, const char *fmt, ...) { struct fb_variable *var = xzalloc(sizeof(*var)); va_list ap; @@ -73,12 +75,12 @@ static struct fb_variable *fb_addvar(struct fastboot *fb, const char *fmt, ...) var->name = bvasprintf(fmt, ap); va_end(ap); - list_add_tail(&var->list, &fb->variables); + list_add_tail(&var->list, list); return var; } -static int fastboot_add_partition_variables(struct fastboot *fb, +static int fastboot_add_partition_variables(struct fastboot *fb, struct list_head *list, struct file_list_entry *fentry) { struct stat s; @@ -95,6 +97,14 @@ static int fastboot_add_partition_variables(struct fastboot *fb, } if (ret) { + if (fentry->flags & FILE_LIST_FLAG_OPTIONAL) { + pr_info("skipping unavailable optional partition %s for fastboot gadget\n", + fentry->filename); + ret = 0; + type = "unavailable"; + goto out; + } + if (fentry->flags & FILE_LIST_FLAG_CREATE) { ret = 0; type = "file"; @@ -142,9 +152,9 @@ out: if (ret) return ret; - var = fb_addvar(fb, "partition-size:%s", fentry->name); + var = fb_addvar(fb, list, "partition-size:%s", fentry->name); fb_setvar(var, "%08zx", size); - var = fb_addvar(fb, "partition-type:%s", fentry->name); + var = fb_addvar(fb, list, "partition-type:%s", fentry->name); fb_setvar(var, "%s", type); return ret; @@ -152,18 +162,16 @@ out: int fastboot_generic_init(struct fastboot *fb, bool export_bbu) { - int ret; - struct file_list_entry *fentry; struct fb_variable *var; INIT_LIST_HEAD(&fb->variables); - var = fb_addvar(fb, "version"); + var = fb_addvar(fb, &fb->variables, "version"); fb_setvar(var, "0.4"); - var = fb_addvar(fb, "bootloader-version"); + var = fb_addvar(fb, &fb->variables, "bootloader-version"); fb_setvar(var, release_string); if (IS_ENABLED(CONFIG_FASTBOOT_SPARSE)) { - var = fb_addvar(fb, "max-download-size"); + var = fb_addvar(fb, &fb->variables, "max-download-size"); fb_setvar(var, "%u", fastboot_max_download_size); } @@ -176,25 +184,24 @@ int fastboot_generic_init(struct fastboot *fb, bool export_bbu) if (export_bbu) bbu_append_handlers_to_file_list(fb->files); - file_list_for_each_entry(fb->files, fentry) { - ret = fastboot_add_partition_variables(fb, fentry); - if (ret) - return ret; - } - return 0; } -void fastboot_generic_free(struct fastboot *fb) +static void fastboot_free_variables(struct list_head *list) { struct fb_variable *var, *tmp; - list_for_each_entry_safe(var, tmp, &fb->variables, list) { + list_for_each_entry_safe(var, tmp, list, list) { free(var->name); free(var->value); list_del(&var->list); free(var); } +} + +void fastboot_generic_free(struct fastboot *fb) +{ + fastboot_free_variables(&fb->variables); free(fb->tempname); @@ -290,26 +297,51 @@ static int strcmp_l1(const char *s1, const char *s2) static void cb_getvar(struct fastboot *fb, const char *cmd) { struct fb_variable *var; + LIST_HEAD(partition_list); + struct file_list_entry *fentry; + + file_list_for_each_entry(fb->files, fentry) { + int ret; + + ret = fastboot_add_partition_variables(fb, &partition_list, fentry); + if (ret) { + pr_warn("Failed to add partition variables: %pe", ERR_PTR(ret)); + return; + } + } pr_debug("getvar: \"%s\"\n", cmd); if (!strcmp_l1(cmd, "all")) { - list_for_each_entry(var, &fb->variables, list) { + list_for_each_entry(var, &fb->variables, list) fastboot_tx_print(fb, FASTBOOT_MSG_INFO, "%s: %s", var->name, var->value); - } + + list_for_each_entry(var, &partition_list, list) + fastboot_tx_print(fb, FASTBOOT_MSG_INFO, "%s: %s", + var->name, var->value); + fastboot_tx_print(fb, FASTBOOT_MSG_OKAY, ""); - return; + goto out; } list_for_each_entry(var, &fb->variables, list) { if (!strcmp(cmd, var->name)) { fastboot_tx_print(fb, FASTBOOT_MSG_OKAY, var->value); - return; + goto out; + } + } + + list_for_each_entry(var, &partition_list, list) { + if (!strcmp(cmd, var->name)) { + fastboot_tx_print(fb, FASTBOOT_MSG_OKAY, var->value); + goto out; } } fastboot_tx_print(fb, FASTBOOT_MSG_OKAY, ""); +out: + fastboot_free_variables(&partition_list); } int fastboot_handle_download_data(struct fastboot *fb, const void *buffer, @@ -588,7 +620,7 @@ static int fastboot_handle_sparse(struct fastboot *fb, pos = lseek(fd, pos, SEEK_SET); if (pos == -1) { - ret = -errno; + ret = errno == EINVAL ? -ENOSPC : -errno; goto out; } @@ -616,7 +648,11 @@ static void cb_flash(struct fastboot *fb, const char *cmd) const char *filename = NULL; enum filetype filetype; - filetype = file_name_detect_type(fb->tempname); + ret = file_name_detect_type(fb->tempname, &filetype); + if (ret) { + fastboot_tx_print(fb, FASTBOOT_MSG_FAIL, "internal error"); + goto out; + } fastboot_tx_print(fb, FASTBOOT_MSG_INFO, "Copying file to %s...", cmd); @@ -919,6 +955,11 @@ bool get_fastboot_bbu(void) return fastboot_bbu; } +void set_fastboot_bbu(unsigned int enable) +{ + fastboot_bbu = enable; +} + struct file_list *get_fastboot_partitions(void) { if (fastboot_partitions && *fastboot_partitions) @@ -928,9 +969,14 @@ struct file_list *get_fastboot_partitions(void) static int fastboot_globalvars_init(void) { - if (IS_ENABLED(CONFIG_FASTBOOT_SPARSE)) + if (IS_ENABLED(CONFIG_FASTBOOT_SPARSE)) { + fastboot_max_download_size + = roundup_pow_of_two(clamp_t(ulong, mem_malloc_size() / 8, + SZ_8M, SZ_128M)); globalvar_add_simple_int("fastboot.max_download_size", &fastboot_max_download_size, "%u"); + } + globalvar_add_simple_bool("fastboot.bbu", &fastboot_bbu); globalvar_add_simple_string("fastboot.partitions", &fastboot_partitions); |