/src/barebox/commands/nvmem.c
Line | Count | Source |
1 | | // SPDX-License-Identifier: GPL-2.0 |
2 | | // SPDX-FileCopyrightText: © 2021 Ahmad Fatoum, Pengutronix |
3 | | |
4 | | #include <command.h> |
5 | | #include <common.h> |
6 | | #include <environment.h> |
7 | | #include <getopt.h> |
8 | | #include <linux/nvmem-consumer.h> |
9 | | #include <linux/sizes.h> |
10 | | |
11 | | /* Maximum size for dynamically created NVMEM devices. |
12 | | * This is a reasonable limit for RAM-backed devices, but can be adjusted |
13 | | * based on system capabilities and requirements. |
14 | | */ |
15 | 0 | #define NVMEM_MAX_SIZE SZ_1M |
16 | | |
17 | | /* Static counter to ensure unique device IDs for dynamically created rmem |
18 | | * devices |
19 | | */ |
20 | | static int dynamic_rmem_idx; |
21 | | |
22 | | /** |
23 | | * nvmem_create_dynamic_rmem - Creates a dynamic RAM-backed NVMEM device. |
24 | | * @create_size: Size of the NVMEM device to create. |
25 | | * @var_name: Optional environment variable name to store the created device's |
26 | | * name. |
27 | | * |
28 | | * Return: 0 on success, negative error code on failure. |
29 | | */ |
30 | | static int nvmem_create_dynamic_rmem(unsigned long create_size, |
31 | | const char *var_name) |
32 | 0 | { |
33 | 0 | struct device *dev; |
34 | 0 | void *buffer; |
35 | 0 | int ret = 0; |
36 | |
|
37 | 0 | buffer = xzalloc(create_size); |
38 | 0 | dev = add_generic_device("nvmem-rmem", dynamic_rmem_idx, NULL, |
39 | 0 | (resource_size_t)(uintptr_t)buffer, |
40 | 0 | (resource_size_t)create_size, |
41 | 0 | IORESOURCE_MEM, NULL); |
42 | 0 | if (!dev) { |
43 | 0 | free(buffer); |
44 | 0 | return -ENODEV; |
45 | 0 | } |
46 | | |
47 | 0 | if (var_name) |
48 | 0 | ret = pr_setenv(var_name, "rmem%u", dynamic_rmem_idx); |
49 | |
|
50 | 0 | dynamic_rmem_idx++; |
51 | |
|
52 | 0 | return ret; |
53 | 0 | } |
54 | | |
55 | | static int nvmem_parse_and_validate_create_size(const char *size_arg, |
56 | | unsigned long *out_size) |
57 | 0 | { |
58 | |
|
59 | 0 | if (!IS_ENABLED(CONFIG_NVMEM_RMEM)) { |
60 | 0 | printf("Error: rmem NVMEM driver (CONFIG_NVMEM_RMEM) is not enabled in this build.\n"); |
61 | 0 | return -EINVAL; |
62 | 0 | } |
63 | | |
64 | 0 | *out_size = strtoul_suffix(optarg, NULL, 0); |
65 | 0 | if (!*out_size) { |
66 | 0 | printf("Error: Invalid size '%s' for -c option. Must be non-zero.\n", |
67 | 0 | optarg); |
68 | 0 | return COMMAND_ERROR_USAGE; |
69 | 0 | } |
70 | | |
71 | 0 | if (*out_size > NVMEM_MAX_SIZE) { |
72 | 0 | printf("Error: Size '%lu' exceeds maximum allowed size of %d bytes.\n", |
73 | 0 | *out_size, NVMEM_MAX_SIZE); |
74 | 0 | return COMMAND_ERROR_USAGE; |
75 | 0 | } |
76 | | |
77 | 0 | return 0; |
78 | 0 | } |
79 | | |
80 | | static int do_nvmem(int argc, char *argv[]) |
81 | 0 | { |
82 | 0 | unsigned long create_size = 0; |
83 | 0 | char *optarg_v = NULL; |
84 | 0 | int ret = 0; |
85 | 0 | int opt; |
86 | |
|
87 | 0 | while ((opt = getopt(argc, argv, "c:v:h")) != -1) { |
88 | 0 | switch (opt) { |
89 | 0 | case 'c': |
90 | 0 | ret = nvmem_parse_and_validate_create_size(optarg, |
91 | 0 | &create_size); |
92 | 0 | if (ret) |
93 | 0 | return ret; |
94 | 0 | break; |
95 | 0 | case 'v': |
96 | 0 | optarg_v = optarg; |
97 | 0 | break; |
98 | 0 | case 'h': /* fallthrough */ |
99 | 0 | default: |
100 | 0 | return COMMAND_ERROR_USAGE; |
101 | 0 | } |
102 | 0 | } |
103 | | |
104 | 0 | if (optarg_v && !create_size) { |
105 | 0 | printf("Error: -v <VARNAME> option requires -c <SIZE> to create a device.\n"); |
106 | 0 | return COMMAND_ERROR_USAGE; |
107 | 0 | } |
108 | | |
109 | 0 | if (create_size > 0) |
110 | 0 | ret = nvmem_create_dynamic_rmem(create_size, optarg_v); |
111 | 0 | else |
112 | 0 | nvmem_devices_print(); |
113 | |
|
114 | 0 | return ret; |
115 | 0 | } |
116 | | |
117 | | BAREBOX_CMD_HELP_START(nvmem) |
118 | | BAREBOX_CMD_HELP_TEXT("List NVMEM devices or create dynamic RAM-backed NVMEM") |
119 | | BAREBOX_CMD_HELP_TEXT("devices. If no arguments are provided, it lists all") |
120 | | BAREBOX_CMD_HELP_TEXT("available NVMEM devices.") |
121 | | BAREBOX_CMD_HELP_TEXT("") |
122 | | BAREBOX_CMD_HELP_TEXT("Options:") |
123 | | BAREBOX_CMD_HELP_OPT("-c <size>", "Create a new RAM-backed NVMEM device of") |
124 | | BAREBOX_CMD_HELP_OPT(" ", "<size> bytes. (Requires CONFIG_NVMEM_RMEM") |
125 | | BAREBOX_CMD_HELP_OPT(" ", "to be enabled). <size> must be non-zero.") |
126 | | BAREBOX_CMD_HELP_OPT("-v <variable>", "When using -c, set environment variable") |
127 | | BAREBOX_CMD_HELP_OPT(" ", "<variable> to the name of the created") |
128 | | BAREBOX_CMD_HELP_OPT(" ", "NVMEM device (e.g., rmem0).") |
129 | | BAREBOX_CMD_HELP_END; |
130 | | |
131 | | BAREBOX_CMD_START(nvmem) |
132 | | .cmd = do_nvmem, |
133 | | BAREBOX_CMD_DESC("list or create NVMEM devices") |
134 | | BAREBOX_CMD_OPTS("[-c <size> [-v <varname>]]") |
135 | | BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP) |
136 | | BAREBOX_CMD_HELP(cmd_nvmem_help) |
137 | | BAREBOX_CMD_END |