generic: add pending support for NVMEM ASCII ENV layout driver
Add pending patch to support NVMEM ASCII ENV layout driver. This is a generic driver to handle simple NVMEM partition that store environment in a simple text format. This is the case for Linksys devinfo partition that are litterally txt file with format "name=value\n" Such driver works similar to u-boot,env with a similar format. While at it also introduce a patch to generalize mac-base handling for also other layout driver. Link: https://github.com/openwrt/openwrt/pull/17839 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
parent
eba2fbf638
commit
73a6cb983c
@ -4346,6 +4346,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
|
|||||||
# CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set
|
# CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set
|
||||||
# CONFIG_NVMEM_LAYOUT_SL28_VPD is not set
|
# CONFIG_NVMEM_LAYOUT_SL28_VPD is not set
|
||||||
# CONFIG_NVMEM_LAYOUT_U_BOOT_ENV is not set
|
# CONFIG_NVMEM_LAYOUT_U_BOOT_ENV is not set
|
||||||
|
# CONFIG_NVMEM_LAYOUT_ASCII_ENV is not set
|
||||||
# CONFIG_NVMEM_REBOOT_MODE is not set
|
# CONFIG_NVMEM_REBOOT_MODE is not set
|
||||||
# CONFIG_NVMEM_RMEM is not set
|
# CONFIG_NVMEM_RMEM is not set
|
||||||
# CONFIG_NVMEM_SYSFS is not set
|
# CONFIG_NVMEM_SYSFS is not set
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
From 995a6e0d3fdd1e4fb38465f224db8a4c7b1e279d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
|
Date: Mon, 3 Feb 2025 00:10:18 +0100
|
||||||
|
Subject: [PATCH 1/2] nvmem: core: generalize "mac-base" cells handling
|
||||||
|
|
||||||
|
Generalize support of "mac-base" nvmem cells and provide a GPL symbol to
|
||||||
|
permit also other NVMEM layout driver to parse mac-base cells.
|
||||||
|
|
||||||
|
It's VERY COMMON for some specially formatted NVMEM to expose a mac
|
||||||
|
address in ASCII format or HEX format hence prevent code duplication by
|
||||||
|
exposing a common helper.
|
||||||
|
|
||||||
|
Such helper will change the nvmem_info_cell and apply the correct post
|
||||||
|
process function to correctly parse the mac address.
|
||||||
|
|
||||||
|
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/nvmem/core.c | 41 +++++++++++++++++++---------------
|
||||||
|
include/linux/nvmem-provider.h | 4 ++++
|
||||||
|
2 files changed, 27 insertions(+), 18 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/nvmem/core.c
|
||||||
|
+++ b/drivers/nvmem/core.c
|
||||||
|
@@ -855,6 +855,27 @@ static int nvmem_mac_base_hex_read(void
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+void nvmem_layout_parse_mac_base(struct nvmem_cell_info *info)
|
||||||
|
+{
|
||||||
|
+ if (!of_device_is_compatible(info->np, "mac-base"))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ if (info->bytes == ETH_ALEN) {
|
||||||
|
+ info->raw_len = info->bytes;
|
||||||
|
+ info->bytes = ETH_ALEN;
|
||||||
|
+ info->read_post_process = nvmem_mac_base_raw_read;
|
||||||
|
+ } else if (info->bytes == 2 * ETH_ALEN) {
|
||||||
|
+ info->raw_len = info->bytes;
|
||||||
|
+ info->bytes = ETH_ALEN;
|
||||||
|
+ info->read_post_process = nvmem_mac_base_hex_read;
|
||||||
|
+ } else if (info->bytes == 3 * ETH_ALEN - 1) {
|
||||||
|
+ info->raw_len = info->bytes;
|
||||||
|
+ info->bytes = ETH_ALEN;
|
||||||
|
+ info->read_post_process = nvmem_mac_base_ascii_read;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(nvmem_layout_parse_mac_base);
|
||||||
|
+
|
||||||
|
static int nvmem_add_cells_from_dt(struct nvmem_device *nvmem, struct device_node *np)
|
||||||
|
{
|
||||||
|
struct device *dev = &nvmem->dev;
|
||||||
|
@@ -894,24 +915,8 @@ static int nvmem_add_cells_from_dt(struc
|
||||||
|
if (nvmem->fixup_dt_cell_info)
|
||||||
|
nvmem->fixup_dt_cell_info(nvmem, &info);
|
||||||
|
|
||||||
|
- if (of_device_is_compatible(np, "fixed-layout")) {
|
||||||
|
- if (of_device_is_compatible(child, "mac-base")) {
|
||||||
|
- if (info.bytes == ETH_ALEN) {
|
||||||
|
- info.raw_len = info.bytes;
|
||||||
|
- info.bytes = ETH_ALEN;
|
||||||
|
- info.read_post_process = nvmem_mac_base_raw_read;
|
||||||
|
- } else if (info.bytes == 2 * ETH_ALEN) {
|
||||||
|
- info.raw_len = info.bytes;
|
||||||
|
- info.bytes = ETH_ALEN;
|
||||||
|
- info.read_post_process = nvmem_mac_base_hex_read;
|
||||||
|
- } else if (info.bytes == 3 * ETH_ALEN - 1) {
|
||||||
|
- info.raw_len = info.bytes;
|
||||||
|
- info.bytes = ETH_ALEN;
|
||||||
|
- info.read_post_process = nvmem_mac_base_ascii_read;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ if (of_device_is_compatible(np, "fixed-layout"))
|
||||||
|
+ nvmem_layout_parse_mac_base(&info);
|
||||||
|
|
||||||
|
ret = nvmem_add_one_cell(nvmem, &info);
|
||||||
|
kfree(info.name);
|
||||||
|
--- a/include/linux/nvmem-provider.h
|
||||||
|
+++ b/include/linux/nvmem-provider.h
|
||||||
|
@@ -242,6 +242,8 @@ static inline void nvmem_layout_unregist
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
|
||||||
|
|
||||||
|
+void nvmem_layout_parse_mac_base(struct nvmem_cell_info *info);
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* of_nvmem_layout_get_container() - Get OF node of layout container
|
||||||
|
*
|
||||||
|
@@ -254,6 +256,8 @@ struct device_node *of_nvmem_layout_get_
|
||||||
|
|
||||||
|
#else /* CONFIG_NVMEM && CONFIG_OF */
|
||||||
|
|
||||||
|
+static inline void nvmem_layout_parse_mac_base(void) {}
|
||||||
|
+
|
||||||
|
static inline struct device_node *of_nvmem_layout_get_container(struct nvmem_device *nvmem)
|
||||||
|
{
|
||||||
|
return NULL;
|
@ -0,0 +1,187 @@
|
|||||||
|
From 38287e8ec5c0281377fc70f11f20bcd9986a05f5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
|
Date: Mon, 3 Feb 2025 00:36:12 +0100
|
||||||
|
Subject: [PATCH 2/2] nvmem: layouts: add support for ascii-env driver
|
||||||
|
|
||||||
|
Add support for simple ASCII envirorment driver for NVMEM layouts.
|
||||||
|
|
||||||
|
It's very common for devices to store simple text file format in
|
||||||
|
partition for environment varibles. The most common pattern is variable
|
||||||
|
name, a delimiter and variable value all separated by a new line
|
||||||
|
character (\n).
|
||||||
|
|
||||||
|
This driver adds support for exporting such data and expose NVMEM cells
|
||||||
|
so they can be referenced by other drivers. This driver also supports
|
||||||
|
parsing mac-base NVMEM cells to parse ASCII or HEX mac address.
|
||||||
|
|
||||||
|
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||||
|
---
|
||||||
|
drivers/nvmem/layouts/Kconfig | 13 +++
|
||||||
|
drivers/nvmem/layouts/Makefile | 1 +
|
||||||
|
drivers/nvmem/layouts/ascii-env.c | 131 ++++++++++++++++++++++++++++++
|
||||||
|
3 files changed, 145 insertions(+)
|
||||||
|
create mode 100644 drivers/nvmem/layouts/ascii-env.c
|
||||||
|
|
||||||
|
--- a/drivers/nvmem/layouts/Kconfig
|
||||||
|
+++ b/drivers/nvmem/layouts/Kconfig
|
||||||
|
@@ -37,6 +37,19 @@ config NVMEM_LAYOUT_U_BOOT_ENV
|
||||||
|
|
||||||
|
If unsure, say N.
|
||||||
|
|
||||||
|
+config NVMEM_LAYOUT_ASCII_ENV
|
||||||
|
+ tristate "ASCII environment variables layout"
|
||||||
|
+ help
|
||||||
|
+ It's very common for devices to store simple text file format in
|
||||||
|
+ partition for environment varibles. The most common pattern is variable
|
||||||
|
+ name, a delimiter and variable value all separated by a new line
|
||||||
|
+ character (\n).
|
||||||
|
+ This driver adds support for exporting such data and expose NVMEM cells
|
||||||
|
+ so they can be referenced by other drivers. This driver also supports
|
||||||
|
+ parsing mac-base NVMEM cells to parse ASCII or HEX mac address.
|
||||||
|
+
|
||||||
|
+ If unsure, say N.
|
||||||
|
+
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
endif
|
||||||
|
--- a/drivers/nvmem/layouts/Makefile
|
||||||
|
+++ b/drivers/nvmem/layouts/Makefile
|
||||||
|
@@ -6,3 +6,4 @@
|
||||||
|
obj-$(CONFIG_NVMEM_LAYOUT_SL28_VPD) += sl28vpd.o
|
||||||
|
obj-$(CONFIG_NVMEM_LAYOUT_ONIE_TLV) += onie-tlv.o
|
||||||
|
obj-$(CONFIG_NVMEM_LAYOUT_U_BOOT_ENV) += u-boot-env.o
|
||||||
|
+obj-$(CONFIG_NVMEM_LAYOUT_ASCII_ENV) += ascii-env.o
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/nvmem/layouts/ascii-env.c
|
||||||
|
@@ -0,0 +1,131 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
+/*
|
||||||
|
+ * Copyright (C) 2024 Christian Marangi <ansuelsmth@gmail.com>
|
||||||
|
+ *
|
||||||
|
+ * This borrow some parse logic from u-boot-env.
|
||||||
|
+ */
|
||||||
|
+#include <linux/nvmem-consumer.h>
|
||||||
|
+#include <linux/nvmem-provider.h>
|
||||||
|
+#include <linux/of.h>
|
||||||
|
+#include <linux/slab.h>
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Parse a buffer as an ASCII text with name delimiter value and each pattern separated
|
||||||
|
+ * with a new line char '\n'
|
||||||
|
+ * Example: (delimiter '=')
|
||||||
|
+ * name=value\nname2=value2\n
|
||||||
|
+ * 2 Cell:
|
||||||
|
+ * - name: value
|
||||||
|
+ * - name2: value2
|
||||||
|
+ */
|
||||||
|
+static int ascii_env_parse_cells(struct device *dev, struct nvmem_device *nvmem, uint8_t *buf,
|
||||||
|
+ size_t data_len, const char delim)
|
||||||
|
+{
|
||||||
|
+ char *var, *value, *eq, *lf;
|
||||||
|
+ char *data = buf;
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * Warning the inner loop take care of replacing '\n'
|
||||||
|
+ * with '\0', hence we can use strlen on value.
|
||||||
|
+ */
|
||||||
|
+ for (var = data; var < data + data_len && *var;
|
||||||
|
+ var = value + strlen(value) + 1) {
|
||||||
|
+ struct nvmem_cell_info info = {};
|
||||||
|
+
|
||||||
|
+ eq = strchr(var, delim);
|
||||||
|
+ if (!eq)
|
||||||
|
+ break;
|
||||||
|
+ *eq = '\0';
|
||||||
|
+ value = eq + 1;
|
||||||
|
+
|
||||||
|
+ /* Replace '\n' with '\0' to use strlen for value */
|
||||||
|
+ lf = strchr(value, '\n');
|
||||||
|
+ if (!lf)
|
||||||
|
+ break;
|
||||||
|
+ *lf = '\0';
|
||||||
|
+
|
||||||
|
+ info.name = devm_kstrdup(dev, var, GFP_KERNEL);
|
||||||
|
+ if (!info.name)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ info.offset = value - data;
|
||||||
|
+ info.bytes = strlen(value);
|
||||||
|
+ info.np = of_get_child_by_name(dev->of_node, info.name);
|
||||||
|
+
|
||||||
|
+ nvmem_layout_parse_mac_base(&info);
|
||||||
|
+
|
||||||
|
+ nvmem_add_one_cell(nvmem, &info);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ascii_env_add_cells(struct nvmem_layout *layout)
|
||||||
|
+{
|
||||||
|
+ struct nvmem_device *nvmem = layout->nvmem;
|
||||||
|
+ struct device *dev = &layout->dev;
|
||||||
|
+ size_t dev_size;
|
||||||
|
+ uint8_t *buf;
|
||||||
|
+ char delim;
|
||||||
|
+ int bytes;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ /* Get the delimiter for name value pattern */
|
||||||
|
+ delim = device_get_match_data(dev);
|
||||||
|
+
|
||||||
|
+ dev_size = nvmem_dev_size(nvmem);
|
||||||
|
+
|
||||||
|
+ buf = kzalloc(dev_size, GFP_KERNEL);
|
||||||
|
+ if (!buf) {
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ goto err_out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ bytes = nvmem_device_read(nvmem, 0, dev_size, buf);
|
||||||
|
+ if (bytes < 0) {
|
||||||
|
+ ret = bytes;
|
||||||
|
+ goto err_kfree;
|
||||||
|
+ } else if (bytes != dev_size) {
|
||||||
|
+ ret = -EIO;
|
||||||
|
+ goto err_kfree;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ buf[dev_size - 1] = '\0';
|
||||||
|
+ ret = ascii_env_parse_cells(dev, nvmem, buf, dev_size, delim);
|
||||||
|
+
|
||||||
|
+err_kfree:
|
||||||
|
+ kfree(buf);
|
||||||
|
+err_out:
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ascii_env_probe(struct nvmem_layout *layout)
|
||||||
|
+{
|
||||||
|
+ layout->add_cells = ascii_env_add_cells;
|
||||||
|
+
|
||||||
|
+ return nvmem_layout_register(layout);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void ascii_env_remove(struct nvmem_layout *layout)
|
||||||
|
+{
|
||||||
|
+ nvmem_layout_unregister(layout);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct of_device_id ascii_env_of_match_table[] = {
|
||||||
|
+ { .compatible = "ascii-eq-delim-env", .data = (void *)'=', },
|
||||||
|
+ {},
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct nvmem_layout_driver ascii_env_layout = {
|
||||||
|
+ .driver = {
|
||||||
|
+ .name = "ascii-env-layout",
|
||||||
|
+ .of_match_table = ascii_env_of_match_table,
|
||||||
|
+ },
|
||||||
|
+ .probe = ascii_env_probe,
|
||||||
|
+ .remove = ascii_env_remove,
|
||||||
|
+};
|
||||||
|
+module_nvmem_layout_driver(ascii_env_layout);
|
||||||
|
+
|
||||||
|
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
|
||||||
|
+MODULE_LICENSE("GPL");
|
||||||
|
+MODULE_DEVICE_TABLE(of, ascii_env_of_match_table);
|
||||||
|
+MODULE_DESCRIPTION("NVMEM layout driver for ASCII environment variables");
|
Loading…
x
Reference in New Issue
Block a user