[PATCH v1 3/7] commands: nvmem: Add support for creating dynamic rmem devices

Sascha Hauer s.hauer at pengutronix.de
Mon Jun 2 02:41:55 PDT 2025


On Fri, May 30, 2025 at 01:41:02PM +0200, Oleksij Rempel wrote:
> The 'nvmem' command is extended to allow the creation of dynamic
> RAM-backed NVMEM devices (rmem). This functionality is useful for
> testing NVMEM operations, for scripts that require temporary, writable
> NVMEM areas, or when a persistent NVMEM device is not available or
> necessary.
> 
> This patch introduces the following new options to the 'nvmem' command:
> 
> -c : Creates a new rmem NVMEM device of the specified . The size can be
> given with common suffixes (e.g., K, M). The command enforces that the
> size is non-zero and does not exceed a defined maximum (NVMEM_MAX_SIZE,
> defaulting to 1MB). This option requires CONFIG_NVMEM_RMEM to be
> enabled.
> 
> -v : When used in conjunction with the -c option, this stores the name
> of the newly created rmem device (e.g., "rmem0") into the environment
> variable specified by . This allows subsequent commands or scripts to
> easily reference the dynamic NVMEM device.
> 
> If invoked without any options, the 'nvmem' command retains its original
> behavior of listing all currently available NVMEM devices.
> 
> Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
> ---
>  commands/nvmem.c | 124 ++++++++++++++++++++++++++++++++++++++++++++---
>  1 file changed, 118 insertions(+), 6 deletions(-)
> 
> diff --git a/commands/nvmem.c b/commands/nvmem.c
> index a0e3d092e3cf..5f60e70e62c3 100644
> --- a/commands/nvmem.c
> +++ b/commands/nvmem.c
> @@ -1,24 +1,136 @@
>  // SPDX-License-Identifier: GPL-2.0
>  // SPDX-FileCopyrightText: © 2021 Ahmad Fatoum, Pengutronix
>  
> -#include <common.h>
>  #include <command.h>
> +#include <common.h>
> +#include <environment.h>
> +#include <getopt.h>
>  #include <linux/nvmem-consumer.h>
> +#include <linux/sizes.h>
>  
> -static int do_nvmem(int argc, char *argv[])
> +/* Maximum size for dynamically created NVMEM devices.
> + * This is a reasonable limit for RAM-backed devices, but can be adjusted
> + * based on system capabilities and requirements.
> + */
> +#define NVMEM_MAX_SIZE		SZ_1M
> +
> +/* Static counter to ensure unique device IDs for dynamically created rmem
> + * devices
> + */
> +static int dynamic_rmem_idx;
> +
> +/**
> + * nvmem_create_dynamic_rmem - Creates a dynamic RAM-backed NVMEM device.
> + * @create_size: Size of the NVMEM device to create.
> + * @var_name: Optional environment variable name to store the created device's
> + *            name.
> + *
> + * Return: 0 on success, negative error code on failure.
> + */
> +static int nvmem_create_dynamic_rmem(unsigned long create_size,
> +				     const char *var_name)
> +{
> +	struct device *dev;
> +	void *buffer;
> +	int ret = 0;
> +
> +	buffer = xzalloc(create_size);
> +	if (!buffer)
> +		return -ENOMEM;

xzalloc does not fail.

> +
> +	dev = add_generic_device("rmem", dynamic_rmem_idx, NULL,
> +				 (resource_size_t)(uintptr_t)buffer,
> +				 (resource_size_t)create_size,
> +				 IORESOURCE_MEM, NULL);
> +
> +	if (var_name)
> +		ret = setenv(var_name, dev_name(dev));
> +
> +	dynamic_rmem_idx++;
> +
> +	return ret;
> +}
> +
> +static int nvmem_parse_and_validate_create_size(const char *size_arg,
> +						unsigned long *out_size)
>  {
> -	nvmem_devices_print();
> +
> +	if (!IS_ENABLED(CONFIG_NVMEM_RMEM)) {
> +		printf("Error: rmem NVMEM driver (CONFIG_NVMEM_RMEM) is not enabled in this build.\n");
> +		return -EINVAL;
> +	}
> +
> +	*out_size = strtoul_suffix(optarg, NULL, 0);
> +	if (!*out_size) {
> +		printf("Error: Invalid size '%s' for -c option. Must be non-zero.\n",
> +		       optarg);
> +		return COMMAND_ERROR_USAGE;
> +	}
> +
> +	if (*out_size > NVMEM_MAX_SIZE) {
> +		printf("Error: Size '%lu' exceeds maximum allowed size of %d bytes.\n",
> +		       *out_size, NVMEM_MAX_SIZE);
> +		return COMMAND_ERROR_USAGE;
> +	}
>  
>  	return 0;
>  }
>  
> +static int do_nvmem(int argc, char *argv[])
> +{
> +	unsigned long create_size = 0;
> +	char *optarg_v = NULL;
> +	int ret = 0;
> +	int opt;
> +
> +	while ((opt = getopt(argc, argv, "c:v:h")) != -1) {
> +		switch (opt) {
> +		case 'c':
> +			ret = nvmem_parse_and_validate_create_size(optarg,
> +								&create_size);
> +			if (ret < 0)
> +				return ret;

You return COMMAND_ERROR_USAGE from
nvmem_parse_and_validate_create_size() which is > 0, so the error check
won't trigger in this case.

Sascha

-- 
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