summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2021-05-17 16:23:51 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2021-05-17 16:23:51 +0200
commitdee7a15dfaa640130d0b9bc289e5d55b358a2dbc (patch)
tree8ea7b1c341b1ea5453d1a3576fb238dc21edaa37 /common
parentc5e0e697de769d0e78a00b1cb47fe864fade9974 (diff)
parent7ef2912d40b52202f563806fbffb9f615d2d2220 (diff)
downloadbarebox-dee7a15dfaa640130d0b9bc289e5d55b358a2dbc.tar.gz
barebox-dee7a15dfaa640130d0b9bc289e5d55b358a2dbc.tar.xz
Merge branch 'for-next/usb-gadget'
Diffstat (limited to 'common')
-rw-r--r--common/Kconfig15
-rw-r--r--common/Makefile3
-rw-r--r--common/bbu.c24
-rw-r--r--common/console_common.c20
-rw-r--r--common/fastboot.c28
-rw-r--r--common/file-list.c85
-rw-r--r--common/system-partitions.c44
-rw-r--r--common/usbgadget.c94
8 files changed, 244 insertions, 69 deletions
diff --git a/common/Kconfig b/common/Kconfig
index 758acb751d..db7cc6713a 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -91,9 +91,6 @@ config EFI_GUID
config EFI_DEVICEPATH
bool
-config FILE_LIST
- bool
-
config ARCH_DMA_ADDR_T_64BIT
bool
@@ -117,7 +114,6 @@ config USBGADGET_START
bool
depends on CMD_USBGADGET || USB_GADGET_AUTOSTART
select ENVIRONMENT_VARIABLES
- select FILE_LIST
default y
config BOOT
@@ -728,6 +724,17 @@ config MMCBLKDEV_ROOTARG
config BAREBOX_UPDATE
bool "In-system barebox update infrastructure"
+config SYSTEM_PARTITIONS
+ bool "Generic system partitions support"
+ depends on GLOBALVAR
+ help
+ System partitions are a generic way for boards to specify the
+ partitions that should be exported for flashing.
+ Board drivers that set this directly will select this option
+ automatically.
+ Say y here if this should be configurable over the
+ global.system.partitions device parameter as well.
+
config IMD
select CRC32
bool "barebox metadata support"
diff --git a/common/Makefile b/common/Makefile
index 2c679090a0..382a4f661f 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MACHINE_ID) += machine_id.o
obj-$(CONFIG_AUTO_COMPLETE) += complete.o
obj-y += version.o
obj-$(CONFIG_BAREBOX_UPDATE) += bbu.o
+obj-$(CONFIG_SYSTEM_PARTITIONS) += system-partitions.o
obj-$(CONFIG_BINFMT) += binfmt.o
obj-$(CONFIG_BLOCK) += block.o
obj-$(CONFIG_BLSPEC) += blspec.o
@@ -65,7 +66,7 @@ obj-$(CONFIG_EFI_GUID) += efi-guid.o
obj-$(CONFIG_EFI_DEVICEPATH) += efi-devicepath.o
lwl-$(CONFIG_IMD) += imd-barebox.o
obj-$(CONFIG_IMD) += imd.o
-obj-$(CONFIG_FILE_LIST) += file-list.o
+obj-y += file-list.o
obj-$(CONFIG_FIRMWARE) += firmware.o
obj-$(CONFIG_UBIFORMAT) += ubiformat.o
obj-$(CONFIG_BAREBOX_UPDATE_IMX_NAND_FCB) += imx-bbu-nand-fcb.o
diff --git a/common/bbu.c b/common/bbu.c
index ee9f78ecc9..1a1edda96b 100644
--- a/common/bbu.c
+++ b/common/bbu.c
@@ -16,22 +16,28 @@
#include <malloc.h>
#include <linux/stat.h>
#include <image-metadata.h>
+#include <file-list.h>
static LIST_HEAD(bbu_image_handlers);
-int bbu_handlers_iterate(int (*fn)(struct bbu_handler *, void *), void *ctx)
+static void append_bbu_entry(struct bbu_handler *handler, struct file_list *files)
{
- struct bbu_handler *handler;
+ char *name;
- list_for_each_entry(handler, &bbu_image_handlers, list) {
- int ret;
+ name = basprintf("bbu-%s", handler->name);
- ret = fn(handler, ctx);
- if (ret)
- return ret;
- }
+ if (file_list_add_entry(files, name, handler->devicefile, 0))
+ pr_warn("duplicate partition name %s\n", name);
- return 0;
+ free(name);
+}
+
+void bbu_append_handlers_to_file_list(struct file_list *files)
+{
+ struct bbu_handler *handler;
+
+ list_for_each_entry(handler, &bbu_image_handlers, list)
+ append_bbu_entry(handler, files);
}
int bbu_force(struct bbu_data *data, const char *fmt, ...)
diff --git a/common/console_common.c b/common/console_common.c
index 98ff8d0ef9..91a81e50fa 100644
--- a/common/console_common.c
+++ b/common/console_common.c
@@ -183,6 +183,26 @@ static int console_common_init(void)
}
device_initcall(console_common_init);
+int log_writefile(const char *filepath)
+{
+ int ret = 0, nbytes = 0, fd = -1;
+ struct log_entry *log;
+
+ fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC);
+ if (fd < 0)
+ return -errno;
+
+ list_for_each_entry(log, &barebox_logbuf, list) {
+ ret = dputs(fd, log->msg);
+ if (ret < 0)
+ break;
+ nbytes += ret;
+ }
+
+ close(fd);
+ return ret < 0 ? ret : nbytes;
+}
+
void log_print(unsigned flags, unsigned levels)
{
struct log_entry *log;
diff --git a/common/fastboot.c b/common/fastboot.c
index a394d07e28..75f6691b08 100644
--- a/common/fastboot.c
+++ b/common/fastboot.c
@@ -41,6 +41,7 @@
#include <linux/stat.h>
#include <linux/mtd/mtd.h>
#include <fastboot.h>
+#include <system-partitions.h>
#define FASTBOOT_VERSION "0.4"
@@ -149,21 +150,6 @@ out:
return ret;
}
-static int fastboot_add_bbu_variables(struct bbu_handler *handler, void *ctx)
-{
- struct fastboot *fb = ctx;
- char *name;
- int ret;
-
- name = basprintf("bbu-%s", handler->name);
-
- ret = file_list_add_entry(fb->files, name, handler->devicefile, 0);
-
- free(name);
-
- return ret;
-}
-
int fastboot_generic_init(struct fastboot *fb, bool export_bbu)
{
int ret;
@@ -185,8 +171,8 @@ int fastboot_generic_init(struct fastboot *fb, bool export_bbu)
if (!fb->tempname)
return -ENOMEM;
- if (IS_ENABLED(CONFIG_BAREBOX_UPDATE) && export_bbu)
- bbu_handlers_iterate(fastboot_add_bbu_variables, fb);
+ 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);
@@ -930,9 +916,13 @@ bool get_fastboot_bbu(void)
return fastboot_bbu;
}
-const char *get_fastboot_partitions(void)
+struct file_list *get_fastboot_partitions(void)
{
- return fastboot_partitions;
+ if (fastboot_partitions && *fastboot_partitions)
+ return file_list_parse(fastboot_partitions);
+ if (!system_partitions_empty())
+ return system_partitions_get();
+ return NULL;
}
static int fastboot_globalvars_init(void)
diff --git a/common/file-list.c b/common/file-list.c
index cd52b5e045..05f44514fb 100644
--- a/common/file-list.c
+++ b/common/file-list.c
@@ -6,7 +6,9 @@
#include <malloc.h>
#include <fs.h>
#include <file-list.h>
+#include <stringlist.h>
#include <linux/err.h>
+#include <driver.h>
#define PARSE_DEVICE 0
#define PARSE_NAME 1
@@ -109,6 +111,25 @@ static int file_list_parse_one(struct file_list *files, const char *partstr, con
return file_list_add_entry(files, name, filename, flags);
}
+static const char *flags_to_str(int flags)
+{
+ static char str[sizeof "srcu"];
+ char *s = str;;
+
+ if (flags & FILE_LIST_FLAG_SAFE)
+ *s++ = 's';
+ if (flags & FILE_LIST_FLAG_READBACK)
+ *s++ = 'r';
+ if (flags & FILE_LIST_FLAG_CREATE)
+ *s++ = 'c';
+ if (flags & FILE_LIST_FLAG_UBI)
+ *s++ = 'u';
+
+ *s = '\0';
+
+ return str;
+}
+
struct file_list *file_list_parse(const char *str)
{
struct file_list *files;
@@ -141,6 +162,9 @@ void file_list_free(struct file_list *files)
{
struct file_list_entry *entry, *tmp;
+ if (!files)
+ return;
+
list_for_each_entry_safe(entry, tmp, &files->list, list) {
free(entry->name);
free(entry->filename);
@@ -149,3 +173,64 @@ void file_list_free(struct file_list *files)
free(files);
}
+
+struct file_list *file_list_dup(struct file_list *old)
+{
+ struct file_list_entry *old_entry;
+ struct file_list *new;
+
+ new = xzalloc(sizeof(*new));
+
+ INIT_LIST_HEAD(&new->list);
+
+ list_for_each_entry(old_entry, &old->list, list) {
+ (void)file_list_add_entry(new, old_entry->name, old_entry->filename,
+ old_entry->flags); /* can't fail */
+ new->num_entries++;
+ }
+
+ return new;
+}
+
+char *file_list_to_str(const struct file_list *files)
+{
+ struct file_list_entry *entry;
+ struct string_list sl;
+ char *str;
+
+ if (!files)
+ return strdup("");
+
+ string_list_init(&sl);
+
+ list_for_each_entry(entry, &files->list, list) {
+ int ret = string_list_add_asprintf(&sl, "%s(%s)%s", entry->filename, entry->name,
+ flags_to_str(entry->flags));
+ if (ret) {
+ str = ERR_PTR(ret);
+ goto out;
+ }
+ }
+
+ str = string_list_join(&sl, ",");
+out:
+ string_list_free(&sl);
+
+ return str;
+}
+
+int file_list_detect_all(const struct file_list *files)
+{
+ struct file_list_entry *fentry;
+ struct stat s;
+ int i = 0;
+
+ list_for_each_entry(fentry, &files->list, list) {
+ if (stat(fentry->filename, &s))
+ continue;
+ if (device_detect_by_name(devpath_to_name(fentry->filename)) == 0)
+ i++;
+ }
+
+ return i;
+}
diff --git a/common/system-partitions.c b/common/system-partitions.c
new file mode 100644
index 0000000000..547e08a9f3
--- /dev/null
+++ b/common/system-partitions.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2021 Ahmad Fatoum, Pengutronix
+ */
+
+#include <file-list.h>
+#include <param.h>
+#include <globalvar.h>
+#include <init.h>
+#include <magicvar.h>
+#include <system-partitions.h>
+
+static struct file_list *system_partitions;
+
+bool system_partitions_empty(void)
+{
+ return file_list_empty(system_partitions);
+}
+
+struct file_list *system_partitions_get(void)
+{
+ return file_list_dup(system_partitions);
+}
+
+void system_partitions_set(struct file_list *files)
+{
+ file_list_free(system_partitions);
+ system_partitions = files;
+}
+
+static int system_partitions_var_init(void)
+{
+ struct param_d *param;
+
+ system_partitions = file_list_parse("");
+ param = dev_add_param_file_list(&global_device, "system.partitions",
+ NULL, NULL, &system_partitions, NULL);
+
+ return PTR_ERR_OR_ZERO(param);
+}
+postcore_initcall(system_partitions_var_init);
+
+BAREBOX_MAGICVAR(global.system.partitions,
+ "board-specific list of updatable partitions");
diff --git a/common/usbgadget.c b/common/usbgadget.c
index feec0b6634..d4437b5169 100644
--- a/common/usbgadget.c
+++ b/common/usbgadget.c
@@ -17,6 +17,7 @@
#include <usb/gadget-multi.h>
#include <globalvar.h>
#include <magicvar.h>
+#include <system-partitions.h>
static int autostart;
static int acm;
@@ -24,14 +25,29 @@ static char *dfu_function;
static struct file_list *parse(const char *files)
{
- struct file_list *list = file_list_parse(files);
+ struct file_list *list;
+
+ if (!files)
+ return NULL;
+
+ list = file_list_parse(files);
if (IS_ERR(list)) {
pr_err("Parsing file list \"%s\" failed: %pe\n", files, list);
return NULL;
}
+
return list;
}
+static inline struct file_list *get_dfu_function(void)
+{
+ if (dfu_function && *dfu_function)
+ return file_list_parse(dfu_function);
+ if (!system_partitions_empty())
+ return system_partitions_get();
+ return NULL;
+}
+
int usbgadget_register(bool dfu, const char *dfu_opts,
bool fastboot, const char *fastboot_opts,
bool acm, bool export_bbu)
@@ -39,46 +55,44 @@ int usbgadget_register(bool dfu, const char *dfu_opts,
int ret;
struct device_d *dev;
struct f_multi_opts *opts;
- const char *fastboot_partitions = get_fastboot_partitions();
-
- if (dfu && !dfu_opts && dfu_function && *dfu_function)
- dfu_opts = dfu_function;
-
- if (IS_ENABLED(CONFIG_FASTBOOT_BASE) && fastboot && !fastboot_opts &&
- fastboot_partitions && *fastboot_partitions)
- fastboot_opts = fastboot_partitions;
-
- if (!dfu_opts && !fastboot_opts && !acm)
- return COMMAND_ERROR_USAGE;
-
- /*
- * Creating a gadget with both DFU and Fastboot doesn't work.
- * Both client tools seem to assume that the device only has
- * a single configuration
- */
- if (fastboot_opts && dfu_opts) {
- pr_err("Only one of Fastboot and DFU allowed\n");
- return -EINVAL;
- }
opts = xzalloc(sizeof(*opts));
opts->release = usb_multi_opts_release;
- if (fastboot_opts) {
+ if (dfu) {
+ opts->dfu_opts.files = parse(dfu_opts);
+ if (IS_ENABLED(CONFIG_USB_GADGET_DFU) && file_list_empty(opts->dfu_opts.files)) {
+ file_list_free(opts->dfu_opts.files);
+ opts->dfu_opts.files = get_dfu_function();
+ }
+ }
+
+ if (fastboot) {
opts->fastboot_opts.files = parse(fastboot_opts);
+ if (IS_ENABLED(CONFIG_FASTBOOT_BASE) && file_list_empty(opts->fastboot_opts.files)) {
+ file_list_free(opts->fastboot_opts.files);
+ opts->fastboot_opts.files = get_fastboot_partitions();
+ }
+
opts->fastboot_opts.export_bbu = export_bbu;
}
- if (dfu_opts)
- opts->dfu_opts.files = parse(dfu_opts);
+ opts->create_acm = acm;
- if (!opts->dfu_opts.files && !opts->fastboot_opts.files && !acm) {
+ if (usb_multi_count_functions(opts) == 0) {
pr_warn("No functions to register\n");
- free(opts);
- return 0;
+ ret = COMMAND_ERROR_USAGE;
+ goto err;
}
- opts->create_acm = acm;
+ /*
+ * Creating a gadget with both DFU and Fastboot may not work.
+ * fastboot 1:8.1.0+r23-5 can deal with it, but dfu-util 0.9
+ * seems to assume that the device only has a single configuration
+ * That's not our fault though. Emit a warning and continue
+ */
+ if (!file_list_empty(opts->fastboot_opts.files) && !file_list_empty(opts->dfu_opts.files))
+ pr_warn("Both DFU and Fastboot enabled. dfu-util may not like this!\n");
dev = get_device_by_name("otg");
if (dev)
@@ -86,7 +100,11 @@ int usbgadget_register(bool dfu, const char *dfu_opts,
ret = usb_multi_register(opts);
if (ret)
- usb_multi_opts_release(opts);
+ goto err;
+
+ return 0;
+err:
+ usb_multi_opts_release(opts);
return ret;
}
@@ -97,7 +115,7 @@ static int usbgadget_autostart_set(struct param_d *param, void *ctx)
bool fastboot_bbu = get_fastboot_bbu();
int err;
- if (!IS_ENABLED(CONFIG_USB_GADGET_AUTOSTART) || !autostart || started)
+ if (!autostart || started)
return 0;
err = usbgadget_register(true, NULL, true, NULL, acm, fastboot_bbu);
@@ -109,17 +127,21 @@ static int usbgadget_autostart_set(struct param_d *param, void *ctx)
static int usbgadget_globalvars_init(void)
{
- if (IS_ENABLED(CONFIG_USB_GADGET_AUTOSTART)) {
- globalvar_add_bool("usbgadget.autostart", usbgadget_autostart_set,
- &autostart, NULL);
- globalvar_add_simple_bool("usbgadget.acm", &acm);
- }
+ globalvar_add_simple_bool("usbgadget.acm", &acm);
globalvar_add_simple_string("usbgadget.dfu_function", &dfu_function);
return 0;
}
device_initcall(usbgadget_globalvars_init);
+static int usbgadget_autostart_init(void)
+{
+ if (IS_ENABLED(CONFIG_USB_GADGET_AUTOSTART))
+ globalvar_add_bool("usbgadget.autostart", usbgadget_autostart_set, &autostart, NULL);
+ return 0;
+}
+postenvironment_initcall(usbgadget_autostart_init);
+
BAREBOX_MAGICVAR(global.usbgadget.autostart,
"usbgadget: Automatically start usbgadget on boot");
BAREBOX_MAGICVAR(global.usbgadget.acm,