From 48e7b8ae0de2e3a7ec08286e764c46768da9b2bf Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 20 Dec 2017 11:36:44 +0100 Subject: string.h: Implement strndup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I implemented this while trying to import mmc-utils into barebox. While I didn't finish this import this function might still be useful for someone?! Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer --- include/linux/string.h | 3 +++ lib/string.c | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/include/linux/string.h b/include/linux/string.h index 5df8c50e57..ed4eeb5519 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -80,6 +80,9 @@ extern __kernel_size_t strnlen(const char *,__kernel_size_t); #ifndef __HAVE_ARCH_STRDUP extern char * strdup(const char *); #endif +#ifndef __HAVE_ARCH_STRNDUP +extern char *strndup(const char *, size_t); +#endif #ifndef __HAVE_ARCH_STRSWAB extern char * strswab(const char *); #endif diff --git a/lib/string.c b/lib/string.c index 1d491c9c2f..f588933e81 100644 --- a/lib/string.c +++ b/lib/string.c @@ -323,6 +323,26 @@ char * strdup(const char *s) #endif EXPORT_SYMBOL(strdup); +#ifndef __HAVE_ARCH_STRNDUP +char *strndup(const char *s, size_t n) +{ + char *new; + size_t len = strnlen(s, n); + + if ((s == NULL) || + ((new = malloc(len + 1)) == NULL)) { + return NULL; + } + + memcpy(new, s, len); + new[len] = '\0'; + + return new; +} + +#endif +EXPORT_SYMBOL(strndup); + #ifndef __HAVE_ARCH_STRSPN /** * strspn - Calculate the length of the initial substring of @s which only -- cgit v1.2.3 From aa7a10e6dc9366e3962cf8a9912b25f25d63177e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 21 Dec 2017 13:30:35 +0900 Subject: linux/kernel.h: move ALIGN_DOWN() to include/linux/kernel.h Linux commit ed067d4a859f ("linux/kernel.h: Add ALIGN_DOWN macro") moved ALIGN_DOWN to include/linux/kernel.h. Let's do likewise. Signed-off-by: Masahiro Yamada Signed-off-by: Sascha Hauer --- include/common.h | 2 -- include/linux/kernel.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/common.h b/include/common.h index dd7445e9b6..54c76d4641 100644 --- a/include/common.h +++ b/include/common.h @@ -93,8 +93,6 @@ extern int (*barebox_main)(void); void __noreturn start_barebox(void); void shutdown_barebox(void); -#define ALIGN_DOWN(x, a) ((x) & ~((typeof(x))(a) - 1)) - #define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) /* diff --git a/include/linux/kernel.h b/include/linux/kernel.h index b4d2f09081..ab713f20e9 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -33,6 +33,7 @@ #define S64_MIN ((s64)(-S64_MAX - 1)) #define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1) +#define ALIGN_DOWN(x, a) ALIGN((x) - ((a) - 1), (a)) #define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) #define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) #define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) -- cgit v1.2.3 From a433e04e79a096dbbb660c3a50a8317ccc052316 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 9 Jan 2018 16:00:04 +0100 Subject: device parameters: Allow dots in device names for setenv aswell Since f5d77d80f5 Allow device parameters for devices with dots in name Devices can have dots in their name and we can still read its device parameters. Do the same change for writing parameters so they can be written aswell. Signed-off-by: Sascha Hauer --- common/env.c | 54 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/common/env.c b/common/env.c index df8a4dff60..80d3f7ab50 100644 --- a/common/env.c +++ b/common/env.c @@ -223,34 +223,50 @@ static int setenv_raw(struct list_head *l, const char *name, const char *value) return 0; } -int setenv(const char *_name, const char *value) +static int dev_setenv(const char *name, const char *val) { - char *name = strdup(_name); - char *par; - int ret = 0; - struct list_head *list; + const char *pos, *dot, *varname; + char *devname; + struct device_d *dev; - if (value && !*value) - value = NULL; + pos = name; + + while (1) { + dot = strchr(pos, '.'); + if (!dot) + break; + + devname = xstrndup(name, dot - name); + varname = dot + 1; + dev = get_device_by_name(devname); - if ((par = strchr(name, '.'))) { - struct device_d *dev; + free(devname); - *par++ = 0; - dev = get_device_by_name(name); if (dev) { - ret = dev_set_param(dev, par, value); - if (ret) - eprintf("%s: set parameter %s: %s\n", - dev_name(dev), par, strerror(-ret)); - } else { - ret = -ENODEV; - eprintf("set parameter: no such device %s\n", name); + if (get_param_by_name(dev, varname)) + return dev_set_param(dev, varname, val); } - errno = -ret; + pos = dot + 1; + } + + return -ENODEV; +} + +int setenv(const char *_name, const char *value) +{ + char *name = strdup(_name); + int ret = 0; + struct list_head *list; + + if (value && !*value) + value = NULL; + if (strchr(name, '.')) { + ret = dev_setenv(name, value); + if (ret) + eprintf("Cannot set parameter: %s\n", strerror(-ret)); goto out; } -- cgit v1.2.3 From d4adaf8c095eadd51528fefa486ff10c907386ed Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 10 Jan 2018 14:18:51 +0100 Subject: ubiformat: Lower message printing frequency During scanning and formatting printing the messages on a serial line has significant overhead up to the point where it takes longer to print the messages than it takes to do the work. Lower the message printing frequency to improve performance. Signed-off-by: Sascha Hauer --- common/ubiformat.c | 18 ++++++++++++++---- lib/libscan.c | 9 +++++++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/common/ubiformat.c b/common/ubiformat.c index aaa1f5d6bc..0f05f09c0f 100644 --- a/common/ubiformat.c +++ b/common/ubiformat.c @@ -190,6 +190,7 @@ static int flash_image(struct ubiformat_args *args, struct mtd_info *mtd, int fd, img_ebs, eb, written_ebs = 0, ret = -1, eb_cnt; off_t st_size; char *buf = NULL; + uint64_t lastprint = 0; eb_cnt = mtd_num_pebs(mtd); @@ -229,8 +230,12 @@ static int flash_image(struct ubiformat_args *args, struct mtd_info *mtd, long long ec; if (!args->quiet && !args->verbose) { - printf("\rubiformat: flashing eraseblock %d -- %2u %% complete ", - eb, (eb + 1) * 100 / eb_cnt); + if (is_timeout(lastprint, 300 * MSECOND) || + eb == eb_cnt - 1) { + printf("\rubiformat: flashing eraseblock %d -- %2u %% complete ", + eb, (eb + 1) * 100 / eb_cnt); + lastprint = get_time_ns(); + } } if (si->ec[eb] == EB_BAD) @@ -325,6 +330,7 @@ static int format(struct ubiformat_args *args, struct mtd_info *mtd, struct ubi_vtbl_record *vtbl; int eb1 = -1, eb2 = -1; long long ec1 = -1, ec2 = -1; + uint64_t lastprint = 0; eb_cnt = mtd_num_pebs(mtd); @@ -340,8 +346,12 @@ static int format(struct ubiformat_args *args, struct mtd_info *mtd, long long ec; if (!args->quiet && !args->verbose) { - printf("\rubiformat: formatting eraseblock %d -- %2u %% complete ", - eb, (eb + 1 - start_eb) * 100 / (eb_cnt - start_eb)); + if (is_timeout(lastprint, 300 * MSECOND) || + eb == eb_cnt - 1) { + printf("\rubiformat: formatting eraseblock %d -- %2u %% complete ", + eb, (eb + 1 - start_eb) * 100 / (eb_cnt - start_eb)); + lastprint = get_time_ns(); + } } if (si->ec[eb] == EB_BAD) diff --git a/lib/libscan.c b/lib/libscan.c index 74a24b5011..c4139e69d1 100644 --- a/lib/libscan.c +++ b/lib/libscan.c @@ -39,6 +39,7 @@ int libscan_ubi_scan(struct mtd_info *mtd, struct ubi_scan_info **info, int eb, v = (verbose == 2), pr = (verbose == 1), eb_cnt; struct ubi_scan_info *si; unsigned long long sum = 0; + uint64_t lastprint = 0; eb_cnt = mtd_div_by_eb(mtd->size, mtd); @@ -66,8 +67,12 @@ int libscan_ubi_scan(struct mtd_info *mtd, struct ubi_scan_info **info, if (v) normsg_cont("scanning eraseblock %d", eb); if (pr) { - printf("\r" PROGRAM_NAME ": scanning eraseblock %d -- %2u %% complete ", - eb, (eb + 1) * 100 / eb_cnt); + if (is_timeout(lastprint, 300 * MSECOND) || + eb == eb_cnt - 1) { + printf("\r" PROGRAM_NAME ": scanning eraseblock %d -- %2u %% complete ", + eb, (eb + 1) * 100 / eb_cnt); + lastprint = get_time_ns(); + } } ret = mtd_peb_is_bad(mtd, eb); -- cgit v1.2.3 From eec0140e6cc061c46ad9abbfa2633f23d4ba8694 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 10 Jan 2018 10:14:48 +0100 Subject: usbgadget: Update command help text - Do not use BAREBOX_CMD_HELP_OPT with an empty option to extend the previous option text. It confuses the rst converter - Add a '\t' to the options to align the option help texts in the barebox command help Signed-off-by: Sascha Hauer --- commands/usbgadget.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/commands/usbgadget.c b/commands/usbgadget.c index 507871edd2..a1744cbe13 100644 --- a/commands/usbgadget.c +++ b/commands/usbgadget.c @@ -119,13 +119,13 @@ BAREBOX_CMD_HELP_START(usbgadget) BAREBOX_CMD_HELP_TEXT("Enable / disable a USB composite gadget on the USB device interface.") BAREBOX_CMD_HELP_TEXT("") BAREBOX_CMD_HELP_TEXT("Options:") -BAREBOX_CMD_HELP_OPT ("-a", "Create CDC ACM function") -BAREBOX_CMD_HELP_OPT ("-s", "Create Generic Serial function") -BAREBOX_CMD_HELP_OPT ("-A [desc]", "Create Android Fastboot function. If 'desc' is not provided,") -BAREBOX_CMD_HELP_OPT ("", "trying to use 'global.usbgadget.fastboot_function' variable.") -BAREBOX_CMD_HELP_OPT ("-b", "include registered barebox update handlers (fastboot specific)") -BAREBOX_CMD_HELP_OPT ("-D ", "Create DFU function") -BAREBOX_CMD_HELP_OPT ("-d", "Disable the currently running gadget") +BAREBOX_CMD_HELP_OPT ("-a\t", "Create CDC ACM function") +BAREBOX_CMD_HELP_OPT ("-s\t", "Create Generic Serial function") +BAREBOX_CMD_HELP_OPT ("-A ", "Create Android Fastboot function. If 'desc' is not provided, " + "try to use 'global.usbgadget.fastboot_function' variable.") +BAREBOX_CMD_HELP_OPT ("-b\t", "include registered barebox update handlers (fastboot specific)") +BAREBOX_CMD_HELP_OPT ("-D ", "Create DFU function") +BAREBOX_CMD_HELP_OPT ("-d\t", "Disable the currently running gadget") BAREBOX_CMD_HELP_END BAREBOX_CMD_START(usbgadget) -- cgit v1.2.3 From 78936cb9411f7c7ecbebdc8d46d8dbfe981bbba6 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Wed, 10 Jan 2018 15:21:36 +0300 Subject: Kconfig: drop unused HAS_POWEROFF Signed-off-by: Antony Pavlov Cc: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- drivers/efi/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/efi/Kconfig b/drivers/efi/Kconfig index d6beeb07ce..cca1a2e1d6 100644 --- a/drivers/efi/Kconfig +++ b/drivers/efi/Kconfig @@ -1,5 +1,4 @@ config EFI_BOOTUP bool - select HAS_POWEROFF select BLOCK select PARTITION_DISK -- cgit v1.2.3 From fd569c747ead69a5a6930d4cd6493e6d899a79df Mon Sep 17 00:00:00 2001 From: Peter Mamonov Date: Mon, 15 Jan 2018 14:32:31 +0300 Subject: lib: parse_area_spec: don't modify *start value if parse failed Signed-off-by: Peter Mamonov Signed-off-by: Sascha Hauer --- lib/misc.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/misc.c b/lib/misc.c index 62ddd66779..7a1ac257f3 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -79,38 +79,42 @@ EXPORT_SYMBOL(strtoul_suffix); int parse_area_spec(const char *str, loff_t *start, loff_t *size) { char *endp; - loff_t end; + loff_t end, _start; if (!isdigit(*str)) return -1; - *start = strtoull_suffix(str, &endp, 0); + _start = strtoull_suffix(str, &endp, 0); str = endp; if (!*str) { /* beginning given, but no size, assume maximum size */ *size = ~0; - return 0; + goto success; } if (*str == '-') { /* beginning and end given */ end = strtoull_suffix(str + 1, NULL, 0); - if (end < *start) { + if (end < _start) { printf("end < start\n"); return -1; } - *size = end - *start + 1; - return 0; + *size = end - _start + 1; + goto success; } if (*str == '+') { /* beginning and size given */ *size = strtoull_suffix(str + 1, NULL, 0); - return 0; + goto success; } return -1; + +success: + *start = _start; + return 0; } EXPORT_SYMBOL(parse_area_spec); -- cgit v1.2.3 From 5edc75f7a4961fd900796a52151d5a330c241fa2 Mon Sep 17 00:00:00 2001 From: Peter Mamonov Date: Mon, 15 Jan 2018 14:32:32 +0300 Subject: lib: parse_area_spec: part of the area spec after -/+ should start with a digit Signed-off-by: Peter Mamonov Signed-off-by: Sascha Hauer --- lib/misc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/misc.c b/lib/misc.c index 7a1ac257f3..31c44a3f64 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -96,6 +96,9 @@ int parse_area_spec(const char *str, loff_t *start, loff_t *size) if (*str == '-') { /* beginning and end given */ + if (!isdigit(*(str + 1))) + return -1; + end = strtoull_suffix(str + 1, NULL, 0); if (end < _start) { printf("end < start\n"); @@ -107,6 +110,9 @@ int parse_area_spec(const char *str, loff_t *start, loff_t *size) if (*str == '+') { /* beginning and size given */ + if (!isdigit(*(str + 1))) + return -1; + *size = strtoull_suffix(str + 1, NULL, 0); goto success; } -- cgit v1.2.3 From 6a91cea016ba0ede7c6c22ee644291e19da05785 Mon Sep 17 00:00:00 2001 From: Peter Mamonov Date: Mon, 15 Jan 2018 14:32:33 +0300 Subject: lib: parse_area_spec: no extra symbols after area spec are allowed except for spaces Signed-off-by: Peter Mamonov Signed-off-by: Sascha Hauer --- lib/misc.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/misc.c b/lib/misc.c index 31c44a3f64..1d20e1b092 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -79,7 +79,7 @@ EXPORT_SYMBOL(strtoul_suffix); int parse_area_spec(const char *str, loff_t *start, loff_t *size) { char *endp; - loff_t end, _start; + loff_t end, _start, _size; if (!isdigit(*str)) return -1; @@ -90,7 +90,7 @@ int parse_area_spec(const char *str, loff_t *start, loff_t *size) if (!*str) { /* beginning given, but no size, assume maximum size */ - *size = ~0; + _size = ~0; goto success; } @@ -99,12 +99,13 @@ int parse_area_spec(const char *str, loff_t *start, loff_t *size) if (!isdigit(*(str + 1))) return -1; - end = strtoull_suffix(str + 1, NULL, 0); + end = strtoull_suffix(str + 1, &endp, 0); + str = endp; if (end < _start) { printf("end < start\n"); return -1; } - *size = end - _start + 1; + _size = end - _start + 1; goto success; } @@ -113,14 +114,18 @@ int parse_area_spec(const char *str, loff_t *start, loff_t *size) if (!isdigit(*(str + 1))) return -1; - *size = strtoull_suffix(str + 1, NULL, 0); + _size = strtoull_suffix(str + 1, &endp, 0); + str = endp; goto success; } return -1; success: + if (*str && !isspace(*str)) + return -1; *start = _start; + *size = _size; return 0; } EXPORT_SYMBOL(parse_area_spec); -- cgit v1.2.3 From 76759ec94eb3a32d71c32550b6b50965125afd92 Mon Sep 17 00:00:00 2001 From: Oleksij Rempel Date: Thu, 30 Nov 2017 11:56:20 +0100 Subject: of: base: use root_node compatible as suggestion for a hostname on some SoCs we can use generic PLL and RAM initialization. In this cases we create board file only to provide a host name. With this patch host name will be created from device tree compatible. For example: compatible = "board_vendor,board", "chip_vendor,soc" the host name will be: "board" This function will not overwrite a host name which is already set by board or machine code. Signed-off-by: Oleksij Rempel Signed-off-by: Sascha Hauer --- common/misc.c | 7 +++++++ drivers/of/base.c | 32 ++++++++++++++++++++++++++++++++ include/common.h | 1 + include/of.h | 1 + 4 files changed, 41 insertions(+) diff --git a/common/misc.c b/common/misc.c index c5d3704c82..0888f1f4f6 100644 --- a/common/misc.c +++ b/common/misc.c @@ -187,6 +187,13 @@ const char *barebox_get_hostname(void) } EXPORT_SYMBOL(barebox_get_hostname); +void barebox_set_hostname_no_overwrite(const char *__hostname) +{ + if (!barebox_get_hostname()) + barebox_set_hostname(__hostname); +} +EXPORT_SYMBOL(barebox_set_hostname_no_overwrite); + BAREBOX_MAGICVAR_NAMED(global_hostname, global.hostname, "shortname of the board. Also used as hostname for DHCP requests"); diff --git a/drivers/of/base.c b/drivers/of/base.c index eabbf3d957..6a582177bf 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -2360,3 +2360,35 @@ int of_graph_port_is_available(struct device_node *node) return available; } EXPORT_SYMBOL(of_graph_port_is_available); + +/** + * of_get_machine_compatible - get first compatible string from the root node. + * + * Returns the string or NULL. + */ +const char *of_get_machine_compatible(void) +{ + struct property *prop; + const char *name, *p; + + if (!root_node) + return NULL; + + prop = of_find_property(root_node, "compatible", NULL); + name = of_prop_next_string(prop, NULL); + + p = strchr(name, ','); + return p ? p + 1 : name; +} +EXPORT_SYMBOL(of_get_machine_compatible); + +static int of_init_hostname(void) +{ + const char *name; + + name = of_get_machine_compatible(); + barebox_set_hostname_no_overwrite(name ?: "barebox"); + + return 0; +} +late_initcall(of_init_hostname); diff --git a/include/common.h b/include/common.h index 54c76d4641..60e5005b8e 100644 --- a/include/common.h +++ b/include/common.h @@ -137,6 +137,7 @@ const char *barebox_get_model(void); void barebox_set_model(const char *); const char *barebox_get_hostname(void); void barebox_set_hostname(const char *); +void barebox_set_hostname_no_overwrite(const char *); #if defined(CONFIG_MIPS) #include diff --git a/include/of.h b/include/of.h index 9bdbbb5ed2..1b9719d603 100644 --- a/include/of.h +++ b/include/of.h @@ -148,6 +148,7 @@ extern struct device_node *of_copy_node(struct device_node *parent, const struct device_node *other); extern void of_delete_node(struct device_node *node); +extern const char *of_get_machine_compatible(void); extern int of_machine_is_compatible(const char *compat); extern int of_device_is_compatible(const struct device_node *device, const char *compat); -- cgit v1.2.3 From ac9d377b90d6b6638c1e5e626d8da047b5c1274a Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Mon, 15 Jan 2018 00:22:49 +0300 Subject: move parseopt to lib/ Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- fs/Makefile | 2 +- fs/fs.c | 3 +-- fs/nfs.c | 3 +-- fs/parseopt.c | 60 ------------------------------------------------------ fs/parseopt.h | 2 -- include/parseopt.h | 2 ++ lib/Makefile | 1 + lib/parseopt.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 66 insertions(+), 67 deletions(-) delete mode 100644 fs/parseopt.c delete mode 100644 fs/parseopt.h create mode 100644 include/parseopt.h create mode 100644 lib/parseopt.c diff --git a/fs/Makefile b/fs/Makefile index b3f929f506..8e3fd78e92 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_FS_RAMFS) += ramfs.o obj-y += devfs-core.o obj-$(CONFIG_FS_DEVFS) += devfs.o obj-$(CONFIG_FS_FAT) += fat/ -obj-y += fs.o parseopt.o +obj-y += fs.o obj-$(CONFIG_FS_UBIFS) += ubifs/ obj-$(CONFIG_FS_TFTP) += tftp.o obj-$(CONFIG_FS_OMAP4_USBBOOT) += omap4_usbbootfs.o diff --git a/fs/fs.c b/fs/fs.c index f61ee091b5..ccb4943669 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -35,8 +35,7 @@ #include #include #include - -#include "parseopt.h" +#include char *mkmodestr(unsigned long mode, char *str) { diff --git a/fs/nfs.c b/fs/nfs.c index 97f01cfb34..75cd127eeb 100644 --- a/fs/nfs.c +++ b/fs/nfs.c @@ -36,8 +36,7 @@ #include #include #include - -#include "parseopt.h" +#include #define SUNRPC_PORT 111 diff --git a/fs/parseopt.c b/fs/parseopt.c deleted file mode 100644 index 8ff83019a7..0000000000 --- a/fs/parseopt.c +++ /dev/null @@ -1,60 +0,0 @@ -#include - -#include "parseopt.h" - -void parseopt_b(const char *options, const char *opt, bool *val) -{ - const char *start; - size_t optlen = strlen(opt); - -again: - start = strstr(options, opt); - - if (!start) { - *val = false; - return; - } - - if (start > options && start[-1] != ',') { - options = start; - goto again; - } - - if (start[optlen] != ',' && start[optlen] != '\0') { - options = start; - goto again; - } - - *val = true; -} - -void parseopt_hu(const char *options, const char *opt, unsigned short *val) -{ - const char *start; - size_t optlen = strlen(opt); - ulong v; - char *endp; - -again: - start = strstr(options, opt); - - if (!start) - return; - - if (start > options && start[-1] != ',') { - options = start; - goto again; - } - - if (start[optlen] != '=') { - options = start; - goto again; - } - - v = simple_strtoul(start + optlen + 1, &endp, 0); - if (v > USHRT_MAX) - return; - - if (*endp == ',' || *endp == '\0') - *val = v; -} diff --git a/fs/parseopt.h b/fs/parseopt.h deleted file mode 100644 index abf3be3f35..0000000000 --- a/fs/parseopt.h +++ /dev/null @@ -1,2 +0,0 @@ -void parseopt_b(const char *options, const char *opt, bool *val); -void parseopt_hu(const char *options, const char *opt, unsigned short *val); diff --git a/include/parseopt.h b/include/parseopt.h new file mode 100644 index 0000000000..abf3be3f35 --- /dev/null +++ b/include/parseopt.h @@ -0,0 +1,2 @@ +void parseopt_b(const char *options, const char *opt, bool *val); +void parseopt_hu(const char *options, const char *opt, unsigned short *val); diff --git a/lib/Makefile b/lib/Makefile index 1be1742499..8f7ef4e4ed 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -59,3 +59,4 @@ obj-y += reed_solomon/ obj-$(CONFIG_RATP) += ratp.o obj-y += list_sort.o obj-y += int_sqrt.o +obj-y += parseopt.o diff --git a/lib/parseopt.c b/lib/parseopt.c new file mode 100644 index 0000000000..8ff83019a7 --- /dev/null +++ b/lib/parseopt.c @@ -0,0 +1,60 @@ +#include + +#include "parseopt.h" + +void parseopt_b(const char *options, const char *opt, bool *val) +{ + const char *start; + size_t optlen = strlen(opt); + +again: + start = strstr(options, opt); + + if (!start) { + *val = false; + return; + } + + if (start > options && start[-1] != ',') { + options = start; + goto again; + } + + if (start[optlen] != ',' && start[optlen] != '\0') { + options = start; + goto again; + } + + *val = true; +} + +void parseopt_hu(const char *options, const char *opt, unsigned short *val) +{ + const char *start; + size_t optlen = strlen(opt); + ulong v; + char *endp; + +again: + start = strstr(options, opt); + + if (!start) + return; + + if (start > options && start[-1] != ',') { + options = start; + goto again; + } + + if (start[optlen] != '=') { + options = start; + goto again; + } + + v = simple_strtoul(start + optlen + 1, &endp, 0); + if (v > USHRT_MAX) + return; + + if (*endp == ',' || *endp == '\0') + *val = v; +} -- cgit v1.2.3 From e1ac1912755a8999bc110f2e6cf6e17965bece3d Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Mon, 15 Jan 2018 00:22:50 +0300 Subject: include/parseopt.h: add guard macro Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- include/parseopt.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/parseopt.h b/include/parseopt.h index abf3be3f35..becc734c2b 100644 --- a/include/parseopt.h +++ b/include/parseopt.h @@ -1,2 +1,7 @@ +#ifndef __PARSEOPT_H__ +#define __PARSEOPT_H__ + void parseopt_b(const char *options, const char *opt, bool *val); void parseopt_hu(const char *options, const char *opt, unsigned short *val); + +#endif /* __PARSEOPT_H__ */ -- cgit v1.2.3 From ee8e839569db30fc1d1a7fb712c4a81f6c0089b7 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Mon, 15 Jan 2018 00:22:51 +0300 Subject: parseopt: introduce parseopt_u16() and parseopt_str() Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- include/parseopt.h | 2 ++ lib/parseopt.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/include/parseopt.h b/include/parseopt.h index becc734c2b..1f9763f8c9 100644 --- a/include/parseopt.h +++ b/include/parseopt.h @@ -3,5 +3,7 @@ void parseopt_b(const char *options, const char *opt, bool *val); void parseopt_hu(const char *options, const char *opt, unsigned short *val); +void parseopt_u16(const char *options, const char *opt, uint16_t *val); +void parseopt_str(const char *options, const char *opt, char **val); #endif /* __PARSEOPT_H__ */ diff --git a/lib/parseopt.c b/lib/parseopt.c index 8ff83019a7..8211733e3b 100644 --- a/lib/parseopt.c +++ b/lib/parseopt.c @@ -58,3 +58,67 @@ again: if (*endp == ',' || *endp == '\0') *val = v; } + +void parseopt_u16(const char *options, const char *opt, uint16_t *val) +{ + const char *start; + size_t optlen = strlen(opt); + ulong v; + char *endp; + +again: + start = strstr(options, opt); + + if (!start) + return; + + if (start > options && start[-1] != ',') { + options = start; + goto again; + } + + if (start[optlen] != '=') { + options = start; + goto again; + } + + v = simple_strtoul(start + optlen + 1, &endp, 0); + if (v > U16_MAX) + return; + + if (*endp == ',' || *endp == '\0') + *val = v; +} + +void parseopt_str(const char *options, const char *opt, char **val) +{ + const char *start; + size_t optlen = strlen(opt); + char *endp; + char *parsed; + +again: + start = strstr(options, opt); + + if (!start) + return; + + if (start > options && start[-1] != ',') { + options = start; + goto again; + } + + if (start[optlen] != '=') { + options = start; + goto again; + } + + parsed = (char *)start + optlen + 1; + endp = parsed; + while (*endp != '\0' && *endp != ',') { + + endp++; + } + + *val = xstrndup(parsed, endp - parsed); +} -- cgit v1.2.3 From bc0851db17676c3b79e7be1da14b28c679b87565 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 12 Jan 2018 13:42:42 +0100 Subject: FIT: export fit_open_configuration() and fit_open_image() Currently only fit_open() is exported which only opens the predefined images "kernel", "dtb" and "ramdisk". To make the FIT code more usable for other code which may want to open other images export fit_open_configuration() and fit_open_image(). Signed-off-by: Sascha Hauer --- common/bootm.c | 9 ++++++- common/image-fit.c | 77 ++++++++++++++++++++++++++++++++++++++--------------- include/image-fit.h | 8 +++++- 3 files changed, 71 insertions(+), 23 deletions(-) diff --git a/common/bootm.c b/common/bootm.c index c23898bea7..05314a0a10 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -568,7 +568,7 @@ int bootm_boot(struct bootm_data *bootm_data) if (IS_ENABLED(CONFIG_FITIMAGE) && os_type == filetype_oftree) { struct fit_handle *fit; - fit = fit_open(data->os_file, data->os_part, data->verbose, data->verify); + fit = fit_open(data->os_file, data->verbose, data->verify); if (IS_ERR(fit)) { printf("Loading FIT image %s failed with: %s\n", data->os_file, strerrorp(fit)); @@ -577,6 +577,13 @@ int bootm_boot(struct bootm_data *bootm_data) } data->os_fit = fit; + + ret = fit_open_configuration(data->os_fit, data->os_part); + if (ret) { + printf("Cannot open FIT image configuration '%s'\n", + data->os_part ? data->os_part : "default"); + goto err_out; + } } if (os_type == filetype_uimage) { diff --git a/common/image-fit.c b/common/image-fit.c index 81433e6ecf..4d4b29ac26 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -397,14 +397,37 @@ err_digest_free: return ret; } -static int fit_open_image(struct fit_handle *handle, const char *unit, const void **outdata, - unsigned long *outsize) +int fit_has_image(struct fit_handle *handle, const char *name) +{ + const char *unit; + struct device_node *conf_node = handle->conf_node; + + if (!conf_node) + return -EINVAL; + + if (of_property_read_string(conf_node, name, &unit)) + return 0; + + return 1; +} + +int fit_open_image(struct fit_handle *handle, const char *name, + const void **outdata, unsigned long *outsize) { struct device_node *image = NULL, *hash; - const char *type = NULL, *desc= "(no description)"; + const char *unit, *type = NULL, *desc= "(no description)"; const void *data; int data_len; int ret = 0; + struct device_node *conf_node = handle->conf_node; + + if (!conf_node) + return -EINVAL; + + if (of_property_read_string(conf_node, name, &unit)) { + pr_err("No image named '%s'\n", name); + return -ENOENT; + } image = of_get_child_by_name(handle->root, "images"); if (!image) @@ -523,7 +546,7 @@ default_unit: return -ENOENT; } -static int fit_open_configuration(struct fit_handle *handle, const char *name) +int fit_open_configuration(struct fit_handle *handle, const char *name) { struct device_node *conf_node = NULL; const char *unit, *desc = "(no description)"; @@ -556,22 +579,25 @@ static int fit_open_configuration(struct fit_handle *handle, const char *name) if (ret) return ret; - if (of_property_read_string(conf_node, "kernel", &unit) == 0) { - ret = fit_open_image(handle, unit, &handle->kernel, &handle->kernel_size); + handle->conf_node = conf_node; + + if (fit_has_image(handle, "kernel")) { + ret = fit_open_image(handle, "kernel", &handle->kernel, + &handle->kernel_size); if (ret) return ret; - } else { - return -ENOENT; } - if (of_property_read_string(conf_node, "fdt", &unit) == 0) { - ret = fit_open_image(handle, unit, &handle->oftree, &handle->oftree_size); + if (fit_has_image(handle, "ramdisk")) { + ret = fit_open_image(handle, "ramdisk", &handle->initrd, + &handle->initrd_size); if (ret) return ret; } - if (of_property_read_string(conf_node, "ramdisk", &unit) == 0) { - ret = fit_open_image(handle, unit, &handle->initrd, &handle->initrd_size); + if (fit_has_image(handle, "fdt")) { + ret = fit_open_image(handle, "fdt", &handle->oftree, + &handle->oftree_size); if (ret) return ret; } @@ -579,7 +605,7 @@ static int fit_open_configuration(struct fit_handle *handle, const char *name) return 0; } -struct fit_handle *fit_open(const char *filename, const char *config, bool verbose, +struct fit_handle *fit_open(const char *filename, bool verbose, enum bootm_verify verify) { struct fit_handle *handle = NULL; @@ -607,10 +633,6 @@ struct fit_handle *fit_open(const char *filename, const char *config, bool verbo of_property_read_string(handle->root, "description", &desc); pr_info("'%s': %s\n", filename, desc); - ret = fit_open_configuration(handle, config); - if (ret) - goto err; - return handle; err: if (handle->root) @@ -634,10 +656,23 @@ void fit_close(struct fit_handle *handle) static int do_bootm_sandbox_fit(struct image_data *data) { struct fit_handle *handle; - handle = fit_open(data->os_file, data->os_part, data->verbose); - if (handle) - fit_close(handle); - return 0; + int ret; + void *kernel; + unsigned long kernel_size; + + handle = fit_open(data->os_file, data->verbose); + if (IS_ERR(handle)) + return PTR_ERR(handle); + + ret = fit_open_configuration(handle, data->os_part); + if (ret) + goto out; + + ret = 0; +out: + fit_close(handle); + + return ret; } static struct image_handler sandbox_fit_handler = { diff --git a/include/image-fit.h b/include/image-fit.h index c49f958268..62f44dcc8d 100644 --- a/include/image-fit.h +++ b/include/image-fit.h @@ -29,6 +29,7 @@ struct fit_handle { enum bootm_verify verify; struct device_node *root; + struct device_node *conf_node; const void *kernel; unsigned long kernel_size; @@ -38,8 +39,13 @@ struct fit_handle { unsigned long initrd_size; }; -struct fit_handle *fit_open(const char *filename, const char *config, bool verbose, +struct fit_handle *fit_open(const char *filename, bool verbose, enum bootm_verify verify); +int fit_open_configuration(struct fit_handle *handle, const char *name); +int fit_has_image(struct fit_handle *handle, const char *name); +int fit_open_image(struct fit_handle *handle, const char *name, + const void **outdata, unsigned long *outsize); + void fit_close(struct fit_handle *handle); #endif /* __IMAGE_FIT_H__ */ -- cgit v1.2.3 From c9c58efe41b4cdd0633c86064e7059225fbdd7fd Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Wed, 17 Jan 2018 07:49:41 -0800 Subject: partitions: dos: Treat all extended partition types equally Creating logical DOS partitions with fdisk (Fedora 27, fdisk from util-linux 2.30.2) results in extended partition of type 0x05 being created on the device. Partitioned like this, device is succesfully recognized by Linux, but, due to algorithm in dos_partition(), not Barebox. Looking closer at the actual contents of MBR shows that while marked as "Extended partition with CHS addressing" that partition still have all of the LBA adressed fields filled correctly. Given the above and the fact that similar code in Linux kernel (block/partitions/msdos.c) does not make a distinction between types 0x0f and 0x05, port Linux's is_extended_partition() and convert the code to treat types 0x05, 0x0f and 0x85 the same way. Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- common/partitions/dos.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/common/partitions/dos.c b/common/partitions/dos.c index 91b5399079..488c2936f7 100644 --- a/common/partitions/dos.c +++ b/common/partitions/dos.c @@ -21,6 +21,22 @@ #include "parser.h" + +enum { +/* These three have identical behaviour; use the second one if DOS FDISK gets + confused about extended/logical partitions starting past cylinder 1023. */ + DOS_EXTENDED_PARTITION = 5, + LINUX_EXTENDED_PARTITION = 0x85, + WIN98_EXTENDED_PARTITION = 0x0f, +}; + +static inline int is_extended_partition(struct partition *p) +{ + return (p->dos_partition_type == DOS_EXTENDED_PARTITION || + p->dos_partition_type == WIN98_EXTENDED_PARTITION || + p->dos_partition_type == LINUX_EXTENDED_PARTITION); +} + /** * Guess the size of the disk, based on the partition table entries * @param dev device to create partitions for @@ -212,13 +228,8 @@ static void dos_partition(void *buf, struct block_device *blk, sprintf(pd->parts[n].partuuid, "%08x-%02d", signature, i + 1); pd->used_entries++; - /* - * Partitions of type 0x05 and 0x0f (and some more) - * contain extended partitions. Only check for type 0x0f - * here as this is the easiest to parse and common - * enough. - */ - if (pentry.dos_partition_type == 0x0f) { + + if (is_extended_partition(&pentry)) { if (!extended_partition) extended_partition = &pd->parts[n]; else -- cgit v1.2.3 From 2f9b25f41362e99e2b31684b5c9a1a02abc1ae8b Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 19 Jan 2018 14:28:24 +0100 Subject: mci: drop unused parameter from mci_switch() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SWITCH command has two purposes: a) switch the command set b) Write to the EXT_CSD register If the access field (bits [25:24]) in the argument are b00, we're in case a), otherwise in b). As mci_switch() always passes MMC_SWITCH_MODE_WRITE_BYTE (0b3) in the access field, only case b) is relevant here. According to the eMMC specification[1] the command set field is ignored in case b) and so the respective parameter (that is unused already now) can be dropped. [1] Embedded Multi-Media Card (e•MMC) Electrical Standard (5.1), February 2015; paragraph 6.6.1 Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer --- commands/mmc_extcsd.c | 2 +- drivers/mci/mci-core.c | 16 ++++++---------- include/mci.h | 3 +-- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/commands/mmc_extcsd.c b/commands/mmc_extcsd.c index 7a6d39075d..acd23a466b 100644 --- a/commands/mmc_extcsd.c +++ b/commands/mmc_extcsd.c @@ -2357,7 +2357,7 @@ static void write_field(struct mci *mci, u8 *reg, u16 index, u8 value, break; } - mci_switch(mci, 0, index, value); + mci_switch(mci, index, value); out: return; diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 208b7666d6..c6b4e02cbc 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -396,8 +396,7 @@ int mci_send_ext_csd(struct mci *mci, char *ext_csd) * @param value FIXME * @return Transaction status (0 on success) */ -int mci_switch(struct mci *mci, unsigned set, unsigned index, - unsigned value) +int mci_switch(struct mci *mci, unsigned index, unsigned value) { struct mci_cmd cmd; @@ -471,7 +470,7 @@ static int mmc_change_freq(struct mci *mci) cardtype = mci->ext_csd[EXT_CSD_DEVICE_TYPE] & EXT_CSD_CARD_TYPE_MASK; - err = mci_switch(mci, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1); + err = mci_switch(mci, EXT_CSD_HS_TIMING, 1); if (err) { dev_dbg(&mci->dev, "MMC frequency changing failed: %d\n", err); @@ -1044,9 +1043,7 @@ static int mci_startup_mmc(struct mci *mci) * 4bit transfer mode. On success set the corresponding * bus width on the host. */ - err = mci_switch(mci, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_BUS_WIDTH, - ext_csd_bits[idx]); + err = mci_switch(mci, EXT_CSD_BUS_WIDTH, ext_csd_bits[idx]); if (err) { if (idx == 0) dev_warn(&mci->dev, "Changing MMC bus width failed: %d\n", err); @@ -1253,8 +1250,7 @@ static int mci_blk_part_switch(struct mci_part *part) part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK; part_config |= part->part_cfg; - ret = mci_switch(mci, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_PARTITION_CONFIG, part_config); + ret = mci_switch(mci, EXT_CSD_PARTITION_CONFIG, part_config); if (ret) return ret; @@ -1568,8 +1564,8 @@ static int mci_set_boot(struct param_d *param, void *priv) mci->ext_csd_part_config &= ~(7 << 3); mci->ext_csd_part_config |= mci->bootpart << 3; - return mci_switch(mci, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_PARTITION_CONFIG, mci->ext_csd_part_config); + return mci_switch(mci, + EXT_CSD_PARTITION_CONFIG, mci->ext_csd_part_config); } static const char *mci_boot_names[] = { diff --git a/include/mci.h b/include/mci.h index 1f6533391a..072008ef9d 100644 --- a/include/mci.h +++ b/include/mci.h @@ -478,8 +478,7 @@ void mci_of_parse(struct mci_host *host); void mci_of_parse_node(struct mci_host *host, struct device_node *np); int mci_detect_card(struct mci_host *); int mci_send_ext_csd(struct mci *mci, char *ext_csd); -int mci_switch(struct mci *mci, unsigned set, unsigned index, - unsigned value); +int mci_switch(struct mci *mci, unsigned index, unsigned value); static inline int mmc_host_is_spi(struct mci_host *host) { -- cgit v1.2.3