[PATCH 1/5] common: machine_id: support /chosen/barebox, machine-id-path override
Ahmad Fatoum
a.fatoum at pengutronix.de
Mon Jun 28 03:11:09 PDT 2021
Hello Basti,
On 28.06.21 11:35, Bastian Krause wrote:
> On 6/28/21 8:40 AM, Ahmad Fatoum wrote:
>> The Kconfig option already warns that the current behavior of
>> machine_id_set_hashable() overriding previous calls can lead to the
>> machine-id changing over updates. We don't yet have this problem in
>> practice, because the only two upstream users are for bsec and ocotp,
>> which are efuse drivers for different SoCs. On the other hand, users
>> may want to get the unique ID from an EEPROM and with deep probe
>> support, the initcall ordering will be independent of the actual probe
>> order.
>>
>> Work around this issue by introducing a way for each board to explicitly
>> reference a nvmem cell that should be hashed to produce the machine-id.
>>
>> If no such device tree property is supplied, the last call to
>> machine_id_set_hashable() will be used as before.
>>
>> Cc: Bastian Krause <bst at pengutronix.de>
>> Cc: Uwe Kleine-König <ukl at pengutronix.de>
>> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
>> ---
>> common/Kconfig | 13 ++++++----
>> common/machine_id.c | 41 ++++++++++++++++++++++++++++---
>> drivers/nvmem/core.c | 44 ++++++++++++++++++++++++----------
>> drivers/of/base.c | 11 +++++++++
>> include/linux/nvmem-consumer.h | 5 ++++
>> include/of.h | 6 +++++
>> 6 files changed, 99 insertions(+), 21 deletions(-)
>>
>> diff --git a/common/Kconfig b/common/Kconfig
>> index 54f1eb633a32..a4a109f04f08 100644
>> --- a/common/Kconfig
>> +++ b/common/Kconfig
>> @@ -1066,13 +1066,16 @@ config MACHINE_ID
>> bool "compute unique machine-id"
>> depends on FLEXIBLE_BOOTARGS
>> depends on SHA1
>> + select NVMEM
>> help
>> Compute a persistent machine-specific id and store it to $global.machine_id.
>> - The id is a hash of device-specific information added via
>> - machine_id_set_hashable(). If multiple sources are available, 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.
>> + The id is a hash of device-specific information added either via
>> + machine_id_set_hashable() or by hashing the nvmem cell referenced by the
>> + /chosen/barebox,machine-id device tree property.
>> +
>> + With machine_id_set_hashable(), the last call prior to the late initcall
>> + set_machine_id() willl be used to generate the machine id. This means
>> + updating barebox may change the machine id!
>>
>> global.bootm.provide_machine_id may be used to automatically set
>> the linux.bootargs.machine_id global variable with a value of
>> diff --git a/common/machine_id.c b/common/machine_id.c
>> index 6480806cd287..fd2f0888a6cd 100644
>> --- a/common/machine_id.c
>> +++ b/common/machine_id.c
>> @@ -10,6 +10,9 @@
>> #include <magicvar.h>
>> #include <crypto/sha.h>
>> #include <machine_id.h>
>> +#include <linux/err.h>
>> +#include <linux/nvmem-consumer.h>
>> +#include <of.h>
>>
>> #define MACHINE_ID_LENGTH 32
>>
>> @@ -24,16 +27,49 @@ void machine_id_set_hashable(const void *hashable, size_t len)
>> __machine_id_hashable_length = len;
>> }
>>
>> +static const void *machine_id_get_hashable(size_t *len)
>> +{
>> + struct device_node *np = of_get_machineidpath();
>> + struct nvmem_cell *cell;
>> + void *ret;
>> +
>> + if (!np)
>> + goto no_cell;
>> +
>> + cell = of_nvmem_cell_get_from_node(np);
>> + if (IS_ERR(cell)) {
>> + pr_err("Invalid barebox,machine-id-path: %pe\n", cell);
>> + goto no_cell;
>> + }
>> +
>> + ret = nvmem_cell_read(cell, len);
>> + nvmem_cell_put(cell);
>> + if (IS_ERR(ret)) {
>> + pr_err("Couldn't read from barebox,machine-id-path: %pe\n", ret);
>> + goto no_cell;
>> + }
>> +
>> + return ret;
>> +
>> +no_cell:
>> + *len = __machine_id_hashable_length;
>> + return __machine_id_hashable;
>> +}
>> +
>> static int machine_id_set_globalvar(void)
>> {
>> struct digest *digest = NULL;
>> unsigned char machine_id[SHA1_DIGEST_SIZE];
>> char hex_machine_id[MACHINE_ID_LENGTH];
>> char *env_machine_id;
>> + const void *hashable;
>> + size_t length;
>> int ret = 0;
>>
>> + hashable = machine_id_get_hashable(&length);
>> +
>> /* nothing to do if no hashable information provided */
>> - if (!__machine_id_hashable)
>> + if (!hashable)
>> goto out;
>>
>> digest = digest_alloc_by_algo(HASH_ALGO_SHA1);
>> @@ -41,8 +77,7 @@ static int machine_id_set_globalvar(void)
>> if (ret)
>> goto out;
>>
>> - ret = digest_update(digest, __machine_id_hashable,
>> - __machine_id_hashable_length);
>> + ret = digest_update(digest, hashable, length);
>> if (ret)
>> goto out;
>>
>> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
>> index 4e558e165063..980304a8078b 100644
>> --- a/drivers/nvmem/core.c
>> +++ b/drivers/nvmem/core.c
>> @@ -361,29 +361,21 @@ static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id)
>>
>> #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OFTREE)
>> /**
>> - * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id
>> + * of_nvmem_cell_get_from_node() - Get a nvmem cell from cell device node
>> *
>> - * @dev node: Device tree node that uses the nvmem cell
>> - * @id: nvmem cell name from nvmem-cell-names property.
>> + * @cell_np: Device tree node of the nvmem cell
>> *
>> * Return: Will be an ERR_PTR() on error or a valid pointer
>> * to a struct nvmem_cell. The nvmem_cell will be freed by the
>> * nvmem_cell_put().
>> */
>> -struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
>> - const char *name)
>> +struct nvmem_cell *of_nvmem_cell_get_from_node(struct device_node *cell_np)
>> {
>> - struct device_node *cell_np, *nvmem_np;
>> + struct device_node *nvmem_np;
>> struct nvmem_cell *cell;
>> struct nvmem_device *nvmem;
>> const __be32 *addr;
>> - int rval, len, index;
>> -
>> - index = of_property_match_string(np, "nvmem-cell-names", name);
>> -
>> - cell_np = of_parse_phandle(np, "nvmem-cells", index);
>> - if (!cell_np)
>> - return ERR_PTR(-EINVAL);
>> + int rval, len;
>>
>> nvmem_np = of_get_parent(cell_np);
>> if (!nvmem_np)
>> @@ -445,6 +437,32 @@ err_mem:
>>
>> return ERR_PTR(rval);
>> }
>> +EXPORT_SYMBOL_GPL(of_nvmem_cell_get_from_node);
>> +
>> +/**
>> + * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id
>> + *
>> + * @dev node: Device tree node that uses the nvmem cell
>> + * @id: nvmem cell name from nvmem-cell-names property.
>> + *
>> + * Return: Will be an ERR_PTR() on error or a valid pointer
>> + * to a struct nvmem_cell. The nvmem_cell will be freed by the
>> + * nvmem_cell_put().
>> + */
>> +struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
>> + const char *name)
>> +{
>> + struct device_node *cell_np;
>> + int index;
>> +
>> + index = of_property_match_string(np, "nvmem-cell-names", name);
>> +
>> + cell_np = of_parse_phandle(np, "nvmem-cells", index);
>> + if (!cell_np)
>> + return ERR_PTR(-EINVAL);
>> +
>> + return of_nvmem_cell_get_from_node(cell_np);
>> +}
>> EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
>> #endif
>
> Shouldn't these changes be part of a separate patch?
For barebox, I usually fold smaller changes into the commit that depends on them.
Sascha was ok with it so far. When the changes get bigger, I split them up,
but here I didn't deem this necessary.
>
> Regards,
> Bastian
>
>>
>> diff --git a/drivers/of/base.c b/drivers/of/base.c
>> index 4104d7589305..a5b74707fc4f 100644
>> --- a/drivers/of/base.c
>> +++ b/drivers/of/base.c
>> @@ -2525,6 +2525,17 @@ int of_device_is_stdout_path(struct device_d *dev, unsigned int *baudrate)
>> return true;
>> }
>>
>> +struct device_node *of_get_machineidpath(void)
>> +{
>> + const char *name;
>> +
>> + name = of_get_property(of_chosen, "barebox,machine-id-path", NULL);
>> + if (!name)
>> + return NULL;
>> +
>> + return of_find_node_by_path_or_alias(NULL, name);
>> +}
>> +
>> /**
>> * of_add_initrd - add initrd properties to the devicetree
>> * @root - the root node of the tree
>> diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
>> index b979f23372a6..639a7ebbabae 100644
>> --- a/include/linux/nvmem-consumer.h
>> +++ b/include/linux/nvmem-consumer.h
>> @@ -122,11 +122,16 @@ static inline int nvmem_device_write(struct nvmem_device *nvmem,
>> #endif /* CONFIG_NVMEM */
>>
>> #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OFTREE)
>> +struct nvmem_cell *of_nvmem_cell_get_from_node(struct device_node *cell_np);
>> struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
>> const char *name);
>> struct nvmem_device *of_nvmem_device_get(struct device_node *np,
>> const char *name);
>> #else
>> +static inline struct nvmem_cell *of_nvmem_cell_get_from_node(struct device_node *cell_np)
>> +{
>> + return ERR_PTR(-ENOSYS);
>> +}
>> static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
>> const char *name)
>> {
>> diff --git a/include/of.h b/include/of.h
>> index d82790c0523e..677f48d0aba1 100644
>> --- a/include/of.h
>> +++ b/include/of.h
>> @@ -290,6 +290,7 @@ int of_fixup_partitions(struct device_node *np, struct cdev *cdev);
>> int of_partitions_register_fixup(struct cdev *cdev);
>> struct device_node *of_get_stdoutpath(unsigned int *);
>> int of_device_is_stdout_path(struct device_d *dev, unsigned int *baudrate);
>> +struct device_node *of_get_machineidpath(void);
>> const char *of_get_model(void);
>> void *of_flatten_dtb(struct device_node *node);
>> int of_add_memory(struct device_node *node, bool dump);
>> @@ -336,6 +337,11 @@ static inline int of_device_is_stdout_path(struct device_d *dev, unsigned int *b
>> return 0;
>> }
>>
>> +static inline struct device_node *of_get_machineidpath(void)
>> +{
>> + return NULL;
>> +}
>> +
>> static inline const char *of_get_model(void)
>> {
>> return NULL;
>>
>
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
More information about the barebox
mailing list