summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Kconfig23
-rw-r--r--common/Makefile1
-rw-r--r--common/blspec.c88
-rw-r--r--common/bootm.c19
-rw-r--r--common/console.c3
-rw-r--r--common/console_simple.c12
-rw-r--r--common/filetype.c2
-rw-r--r--common/firmware.c18
-rw-r--r--common/imd.c20
-rw-r--r--common/imx-bbu-nand-fcb.c9
-rw-r--r--common/machine_id.c69
-rw-r--r--common/partitions/efi.c2
-rw-r--r--common/state/backend_bucket_circular.c4
-rw-r--r--common/state/backend_bucket_direct.c3
-rw-r--r--common/state/state.c7
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;