summaryrefslogtreecommitdiffstats
path: root/common/fastboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/fastboot.c')
-rw-r--r--common/fastboot.c98
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);