diff --git a/common/Kconfig b/common/Kconfig index d98ea50..b840242 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -982,6 +982,24 @@ 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" diff --git a/common/Makefile b/common/Makefile index a284655..1096016 100644 --- a/common/Makefile +++ b/common/Makefile @@ -11,6 +11,7 @@ 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/bootm.c b/common/bootm.c index b50b76e..366f314 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -51,6 +51,7 @@ } 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 @@ 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 @@ } } + 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 @@ 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_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/machine_id.c b/common/machine_id.c new file mode 100644 index 0000000..e678bb7 --- /dev/null +++ b/common/machine_id.c @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019 Pengutronix, Bastian Krause + */ + +#include +#include +#include +#include +#include +#include +#include + +#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/drivers/nvmem/ocotp.c b/drivers/nvmem/ocotp.c index 3f9f162..79693e2 100644 --- a/drivers/nvmem/ocotp.c +++ b/drivers/nvmem/ocotp.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include /* @@ -77,6 +79,7 @@ #define MAC_OFFSET_1 (0x24 * 4) #define MAX_MAC_OFFSETS 2 #define MAC_BYTES 8 +#define UNIQUE_ID_NUM 2 enum imx_ocotp_format_mac_direction { OCOTP_HW_TO_MAC, @@ -548,6 +551,19 @@ return regmap_bulk_read(priv->map, offset, val, bytes); } +static void imx_ocotp_set_unique_machine_id(void) +{ + uint32_t unique_id_parts[UNIQUE_ID_NUM]; + int i; + + for (i = 0; i < UNIQUE_ID_NUM; i++) + if (imx_ocotp_read_field(OCOTP_UNIQUE_ID(i), + &unique_id_parts[i])) + return; + + machine_id_set_hashable(unique_id_parts, sizeof(unique_id_parts)); +} + static const struct nvmem_bus imx_ocotp_nvmem_bus = { .write = imx_ocotp_write, .read = imx_ocotp_read, @@ -633,6 +649,9 @@ ethaddr->value, ethaddr); } + if (IS_ENABLED(CONFIG_MACHINE_ID)) + imx_ocotp_set_unique_machine_id(); + imx_ocotp_init_dt(priv); dev_add_param_bool(&(priv->dev), "sense_enable", NULL, NULL, &priv->sense_enable, priv); diff --git a/include/bootm.h b/include/bootm.h index 5ce3318..a041aa3 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -26,6 +26,11 @@ * mount the rootfs from the same device as the Kernel comes from. */ bool appendroot; + /* + * provide_machine_id - if true, try to add systemd.machine_id= with + * value of global.machine_id to Kernel. + */ + bool provide_machine_id; unsigned long initrd_address; unsigned long os_address; unsigned long os_entry; diff --git a/include/digest.h b/include/digest.h index 474bdd1..1760841 100644 --- a/include/digest.h +++ b/include/digest.h @@ -20,6 +20,7 @@ #define __DIGEST_H__ #include +#include struct digest; diff --git a/include/machine_id.h b/include/machine_id.h new file mode 100644 index 0000000..31d5e0b --- /dev/null +++ b/include/machine_id.h @@ -0,0 +1,16 @@ +#ifndef __MACHINE_ID_H__ +#define __MACHINE_ID_H__ + +#if IS_ENABLED(CONFIG_MACHINE_ID) + +void machine_id_set_hashable(const void *hashable, size_t len); + +#else + +static inline void machine_id_set_hashable(const void *hashable, size_t len) +{ +} + +#endif /* CONFIG_MACHINE_ID */ + +#endif /* __MACHINE_ID_H__ */