diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Kconfig | 23 | ||||
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/blspec.c | 88 | ||||
-rw-r--r-- | common/bootm.c | 19 | ||||
-rw-r--r-- | common/console.c | 3 | ||||
-rw-r--r-- | common/console_simple.c | 12 | ||||
-rw-r--r-- | common/filetype.c | 2 | ||||
-rw-r--r-- | common/firmware.c | 18 | ||||
-rw-r--r-- | common/imd.c | 20 | ||||
-rw-r--r-- | common/imx-bbu-nand-fcb.c | 9 | ||||
-rw-r--r-- | common/machine_id.c | 69 | ||||
-rw-r--r-- | common/partitions/efi.c | 2 | ||||
-rw-r--r-- | common/state/backend_bucket_circular.c | 4 | ||||
-rw-r--r-- | common/state/backend_bucket_direct.c | 3 | ||||
-rw-r--r-- | common/state/state.c | 7 |
15 files changed, 258 insertions, 22 deletions
diff --git a/common/Kconfig b/common/Kconfig index cafaadb3d4..b840242ac9 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -982,6 +982,24 @@ config RESET_SOURCE of the reset and why the bootloader is currently running. It can be useful for any kind of system recovery or repair. +config MACHINE_ID + bool "pass machine-id to kernel" + depends on FLEXIBLE_BOOTARGS + depends on SHA1 + help + Sets the linux.bootargs.machine_id global variable with a value of + systemd.machine_id=UID. The UID is a persistent device-specific + id. It is a hash over device-specific information provided by various + sources. + + Note: if multiple sources provide hashable device-specific information + (via machine_id_set_hashable()) the information provided by the last call + prior to the late initcall set_machine_id() is used to generate the + machine id from. Thus when updating barebox the machine id might change. + + Note: if no hashable information is available no machine id will be passed + to the kernel. + endmenu menu "Debugging" @@ -1274,8 +1292,9 @@ config DEBUG_AT91_UART_BASE default 0xfffff200 if SOC_AT91RM9200 || SOC_AT91SAM9260 \ || SOC_AT91SAM9261 || SOC_AT91SAM9X5 \ || SOC_AT91SAM9N12 - default 0xffffee00 if SOC_AT91SAM9263 || SOC_AT91SAM9G45 || ARCH_SAMA5D3 - default 0xfc069000 if ARCH_SAMA5D4 + default 0xffffee00 if SOC_AT91SAM9263 || SOC_AT91SAM9G45 || SOC_SAMA5D3 + default 0xfc069000 if SOC_SAMA5D4 + default 0xf8020000 if SOC_SAMA5D2 default 0xfffff200 depends on ARCH_AT91 help diff --git a/common/Makefile b/common/Makefile index a284655fc1..10960169f9 100644 --- a/common/Makefile +++ b/common/Makefile @@ -11,6 +11,7 @@ obj-y += bootsource.o obj-$(CONFIG_ELF) += elf.o obj-y += restart.o obj-y += poweroff.o +obj-$(CONFIG_MACHINE_ID) += machine_id.o obj-$(CONFIG_AUTO_COMPLETE) += complete.o obj-y += version.o obj-$(CONFIG_BAREBOX_UPDATE) += bbu.o diff --git a/common/blspec.c b/common/blspec.c index 66e5033e35..7fb62d310f 100644 --- a/common/blspec.c +++ b/common/blspec.c @@ -14,6 +14,7 @@ #include <environment.h> #include <globalvar.h> +#include <firmware.h> #include <readkey.h> #include <common.h> #include <driver.h> @@ -42,6 +43,78 @@ int blspec_entry_var_set(struct blspec_entry *entry, const char *name, val ? strlen(val) + 1 : 0, 1); } +static int blspec_apply_oftree_overlay(char *file, const char *abspath, + int dryrun) +{ + int ret = 0; + struct fdt_header *fdt; + struct device_node *overlay; + char *path; + char *firmware_path; + + path = basprintf("%s/%s", abspath, file); + + fdt = read_file(path, NULL); + if (!fdt) { + pr_warn("unable to read \"%s\"\n", path); + ret = -EINVAL; + goto out; + } + + overlay = of_unflatten_dtb(fdt); + free(fdt); + if (IS_ERR(overlay)) { + ret = PTR_ERR(overlay); + goto out; + } + + if (dryrun) { + pr_info("dry run: skip overlay %s\n", path); + of_delete_node(overlay); + goto out; + } + + /* + * Unfortunately the device tree overlay contains only the filename of + * the firmware and relies on the firmware search paths to find the + * actual file. Use /lib/firmware in the Linux root directory and hope + * for the best. + */ + firmware_path = basprintf("%s/%s", abspath, "/lib/firmware"); + ret = of_firmware_load_overlay(overlay, firmware_path); + free(firmware_path); + if (ret) { + pr_warn("failed to load firmware: skip overlay \"%s\"\n", path); + of_delete_node(overlay); + goto out; + } + + ret = of_register_overlay(overlay); + if (ret) { + pr_warn("cannot register devicetree overlay \"%s\"\n", path); + of_delete_node(overlay); + } + +out: + free(path); + + return ret; +} + +static void blspec_apply_oftree_overlays(const char *overlays, + const char *abspath, int dryrun) +{ + char *overlay; + char *sep, *freep; + + sep = freep = xstrdup(overlays); + + while ((overlay = strsep(&sep, " "))) + blspec_apply_oftree_overlay(overlay, abspath, dryrun); + + free(freep); +} + /* * blspec_boot - boot an entry * @@ -54,6 +127,7 @@ static int blspec_boot(struct bootentry *be, int verbose, int dryrun) struct blspec_entry *entry = container_of(be, struct blspec_entry, entry); int ret; const char *abspath, *devicetree, *options, *initrd, *linuximage; + const char *overlays; const char *appendroot; struct bootm_data data = { .initrd_address = UIMAGE_INVALID_ADDRESS, @@ -73,6 +147,7 @@ static int blspec_boot(struct bootentry *be, int verbose, int dryrun) initrd = blspec_entry_var_get(entry, "initrd"); options = blspec_entry_var_get(entry, "options"); linuximage = blspec_entry_var_get(entry, "linux"); + overlays = blspec_entry_var_get(entry, "devicetree-overlay"); if (entry->rootpath) abspath = entry->rootpath; @@ -92,6 +167,9 @@ static int blspec_boot(struct bootentry *be, int verbose, int dryrun) } } + if (overlays) + blspec_apply_oftree_overlays(overlays, abspath, dryrun); + if (initrd) data.initrd_file = basprintf("%s/%s", abspath, initrd); @@ -229,6 +307,14 @@ static struct blspec_entry *blspec_entry_open(struct bootentries *bootentries, } /* + * is_blspec_entry - check if a bootentry is a blspec entry + */ +static inline bool is_blspec_entry(struct bootentry *entry) +{ + return entry->boot == blspec_boot; +} + +/* * blspec_have_entry - check if we already have an entry with * a certain path */ @@ -238,6 +324,8 @@ static int blspec_have_entry(struct bootentries *bootentries, const char *path) struct blspec_entry *e; list_for_each_entry(be, &bootentries->entries, list) { + if (!is_blspec_entry(be)) + continue; e = container_of(be, struct blspec_entry, entry); if (e->configpath && !strcmp(e->configpath, path)) return 1; diff --git a/common/bootm.c b/common/bootm.c index b50b76ed6f..366f314555 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -51,6 +51,7 @@ static struct image_handler *bootm_find_handler(enum filetype filetype, } static int bootm_appendroot; +static int bootm_provide_machine_id; static int bootm_verbosity; void bootm_data_init_defaults(struct bootm_data *data) @@ -65,6 +66,7 @@ void bootm_data_init_defaults(struct bootm_data *data) data->initrd_file = getenv_nonempty("global.bootm.initrd"); data->verify = bootm_get_verify_mode(); data->appendroot = bootm_appendroot; + data->provide_machine_id = bootm_provide_machine_id; data->verbose = bootm_verbosity; } @@ -646,6 +648,21 @@ int bootm_boot(struct bootm_data *bootm_data) } } + if (bootm_data->provide_machine_id) { + const char *machine_id = getenv_nonempty("global.machine_id"); + char *machine_id_bootarg; + + if (!machine_id) { + printf("Providing machine id is enabled but no machine id set\n"); + ret = -EINVAL; + goto err_out; + } + + machine_id_bootarg = basprintf("systemd.machine_id=%s", machine_id); + globalvar_add_simple("linux.bootargs.machine_id", machine_id_bootarg); + free(machine_id_bootarg); + } + printf("\nLoading %s '%s'", file_type_to_string(os_type), data->os_file); if (os_type == filetype_uimage && @@ -711,6 +728,7 @@ static int bootm_init(void) globalvar_add_simple("bootm.oftree", NULL); globalvar_add_simple("bootm.tee", NULL); globalvar_add_simple_bool("bootm.appendroot", &bootm_appendroot); + globalvar_add_simple_bool("bootm.provide_machine_id", &bootm_provide_machine_id); if (IS_ENABLED(CONFIG_BOOTM_INITRD)) { globalvar_add_simple("bootm.initrd", NULL); globalvar_add_simple("bootm.initrd.loadaddr", NULL); @@ -738,3 +756,4 @@ BAREBOX_MAGICVAR_NAMED(global_bootm_tee, global.bootm.tee, "bootm default tee im BAREBOX_MAGICVAR_NAMED(global_bootm_verify, global.bootm.verify, "bootm default verify level"); BAREBOX_MAGICVAR_NAMED(global_bootm_verbose, global.bootm.verbose, "bootm default verbosity level (0=quiet)"); BAREBOX_MAGICVAR_NAMED(global_bootm_appendroot, global.bootm.appendroot, "Add root= option to Kernel to mount rootfs from the device the Kernel comes from"); +BAREBOX_MAGICVAR_NAMED(global_bootm_provide_machine_id, global.bootm.provide_machine_id, "If true, add systemd.machine_id= with value of global.machine_id to Kernel"); diff --git a/common/console.c b/common/console.c index d04aae58f9..e6e029848d 100644 --- a/common/console.c +++ b/common/console.c @@ -272,6 +272,9 @@ static int fops_open(struct cdev *cdev, unsigned long flags) { struct console_device *priv = cdev->priv; + if ((flags & (O_WRONLY | O_RDWR)) && !priv->puts ) + return -EPERM; + return console_open(priv); } diff --git a/common/console_simple.c b/common/console_simple.c index 385da2fd86..010e0b34c1 100644 --- a/common/console_simple.c +++ b/common/console_simple.c @@ -65,6 +65,9 @@ void console_flush(void) EXPORT_SYMBOL(console_flush); #ifndef ARCH_HAS_CTRLC +void ctrlc_handled(void) +{ +} /* test if ctrl-c was pressed */ int ctrlc (void) { @@ -73,6 +76,15 @@ int ctrlc (void) return 0; } EXPORT_SYMBOL(ctrlc); + +void console_ctrlc_allow(void) +{ +} + +void console_ctrlc_forbid(void) +{ +} + #endif /* ARCH_HAS_CTRC */ int console_register(struct console_device *newcdev) diff --git a/common/filetype.c b/common/filetype.c index 825bf25ad1..4966c5e068 100644 --- a/common/filetype.c +++ b/common/filetype.c @@ -460,6 +460,8 @@ bool filetype_is_barebox_image(enum filetype ft) case filetype_mips_barebox: case filetype_ch_image: case filetype_ch_image_be: + case filetype_layerscape_image: + case filetype_layerscape_qspi_image: return true; default: return false; diff --git a/common/firmware.c b/common/firmware.c index 9d55d73e7a..609cf11822 100644 --- a/common/firmware.c +++ b/common/firmware.c @@ -63,6 +63,24 @@ struct firmware_mgr *firmwaremgr_find(const char *id) } /* + * firmwaremgr_find_by_node - find a firmware device handler + * + * Find a firmware device handler using the device node of the firmware + * handler. This allows to retrieve the firmware handler with a phandle from + * the device tree. + */ +struct firmware_mgr *firmwaremgr_find_by_node(const struct device_node *np) +{ + struct firmware_mgr *mgr; + + list_for_each_entry(mgr, &firmwaremgr_list, list) + if (mgr->handler->dev->parent->device_node == np) + return mgr; + + return NULL; +} + +/* * firmwaremgr_list_handlers - list registered firmware device handlers * in pretty format */ diff --git a/common/imd.c b/common/imd.c index 05e118e773..913a01de87 100644 --- a/common/imd.c +++ b/common/imd.c @@ -337,8 +337,10 @@ int imd_command(int argc, char *argv[]) return -errno; imd_start = imd_get(buf, size); - if (IS_ERR(imd_start)) - return PTR_ERR(imd_start); + if (IS_ERR(imd_start)) { + ret = PTR_ERR(imd_start); + goto out; + } if (type == IMD_TYPE_INVALID) { imd_for_each(imd_start, imd) { @@ -356,7 +358,8 @@ int imd_command(int argc, char *argv[]) imd = imd_find_type(imd_start, type); if (!imd) { debug("No tag of type 0x%08x found\n", type); - return -ENODATA; + ret = -ENODATA; + goto out; } if (imd_is_string(type)) { @@ -370,8 +373,10 @@ int imd_command(int argc, char *argv[]) str = imd_concat_strings(imd); } - if (!str) - return -ENODATA; + if (!str) { + ret = -ENODATA; + goto out; + } if (variable_name) imd_command_setenv(variable_name, str); @@ -384,5 +389,8 @@ int imd_command(int argc, char *argv[]) } } - return 0; + ret = 0; +out: + free(buf); + return ret; } diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c index bb6dd1d4e9..aa3f733912 100644 --- a/common/imx-bbu-nand-fcb.c +++ b/common/imx-bbu-nand-fcb.c @@ -626,8 +626,15 @@ static int imx_bbu_write_firmware(struct mtd_info *mtd, unsigned num, void *buf, continue; ret = mtd_peb_erase(mtd, block + i); - if (ret && ret != -EIO) + if (ret == -EIO) { + newbadblock = 1; + + ret = mtd_peb_mark_bad(mtd, block + i); + if (ret) + return ret; + } else if (ret) { return ret; + } } while (len > 0) { diff --git a/common/machine_id.c b/common/machine_id.c new file mode 100644 index 0000000000..e678bb7fe8 --- /dev/null +++ b/common/machine_id.c @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 Pengutronix, Bastian Krause <kernel@pengutronix.de> + */ + +#include <common.h> +#include <init.h> +#include <digest.h> +#include <globalvar.h> +#include <magicvar.h> +#include <crypto/sha.h> +#include <machine_id.h> + +#define MACHINE_ID_LENGTH 32 + +static void *__machine_id_hashable; +static size_t __machine_id_hashable_length; + + +void machine_id_set_hashable(const void *hashable, size_t len) +{ + + __machine_id_hashable = xmemdup(hashable, len); + __machine_id_hashable_length = len; +} + +static int machine_id_set_bootarg(void) +{ + struct digest *digest = NULL; + unsigned char machine_id[SHA1_DIGEST_SIZE]; + char hex_machine_id[MACHINE_ID_LENGTH]; + char *env_machine_id; + int ret = 0; + + /* nothing to do if no hashable information provided */ + if (!__machine_id_hashable) + goto out; + + digest = digest_alloc_by_algo(HASH_ALGO_SHA1); + ret = digest_init(digest); + if (ret) + goto out; + + ret = digest_update(digest, __machine_id_hashable, + __machine_id_hashable_length); + if (ret) + goto out; + + ret = digest_final(digest, machine_id); + if (ret) + goto out; + + /* use the first 16 bytes of the sha1 hash as the machine id */ + bin2hex(hex_machine_id, machine_id, MACHINE_ID_LENGTH/2); + + env_machine_id = basprintf("%.*s", MACHINE_ID_LENGTH, hex_machine_id); + globalvar_add_simple("machine_id", env_machine_id); + free(env_machine_id); + +out: + globalvar_add_simple("machine_id", NULL); + + digest_free(digest); + return ret; + +} +late_initcall(machine_id_set_bootarg); + +BAREBOX_MAGICVAR_NAMED(global_machine_id, global.machine_id, "Persistent device-specific, hexadecimal, 32-character id"); diff --git a/common/partitions/efi.c b/common/partitions/efi.c index 3c1077fd0c..f20fd0d9b9 100644 --- a/common/partitions/efi.c +++ b/common/partitions/efi.c @@ -369,7 +369,7 @@ static int find_valid_gpt(void *buf, struct block_device *blk, gpt_header **gpt, lastlba = last_lba(blk); if (force_gpt) { /* This will be added to the EFI Spec. per Intel after v1.02. */ - if (file_detect_type(buf, SECTOR_SIZE * 2) != filetype_gpt) + if (file_detect_partition_table(buf, SECTOR_SIZE * 2) != filetype_gpt) goto fail; } diff --git a/common/state/backend_bucket_circular.c b/common/state/backend_bucket_circular.c index 47970b79f3..735510e0d3 100644 --- a/common/state/backend_bucket_circular.c +++ b/common/state/backend_bucket_circular.c @@ -178,10 +178,10 @@ static int state_mtd_peb_read(struct state_backend_storage_bucket_circular *circ if (ret < 0) { dev_err(circ->dev, "Failed to read circular storage len %d, %d\n", len, ret); - free(buf); + return ret; } - return ret; + return 0; } static int state_mtd_peb_write(struct state_backend_storage_bucket_circular *circ, diff --git a/common/state/backend_bucket_direct.c b/common/state/backend_bucket_direct.c index 0dbd334db8..4522f0170f 100644 --- a/common/state/backend_bucket_direct.c +++ b/common/state/backend_bucket_direct.c @@ -115,9 +115,6 @@ static int state_backend_bucket_direct_write(struct state_backend_storage_bucket int ret; struct state_backend_storage_bucket_direct_meta meta; - if (len > direct->max_size - sizeof(meta)) - return -E2BIG; - if (lseek(direct->fd, direct->offset, SEEK_SET) != direct->offset) { dev_err(direct->dev, "Failed to seek file, %d\n", -errno); return -errno; diff --git a/common/state/state.c b/common/state/state.c index 3f5d43ecbf..b168387eef 100644 --- a/common/state/state.c +++ b/common/state/state.c @@ -714,13 +714,6 @@ struct state *state_by_node(const struct device_node *node) return NULL; } -int state_get_name(const struct state *state, char const **name) -{ - *name = xstrdup(state->name); - - return 0; -} - int state_read_mac(struct state *state, const char *name, u8 *buf) { struct state_variable *svar; |