[openwrt/openwrt] generic: add pending support for NVMEM ASCII ENV layout driver

LEDE Commits lede-commits at lists.infradead.org
Sun Feb 2 16:54:36 PST 2025


ansuel pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/73a6cb983c46cbe2e3a603dd5b8ec3155547f8d5

commit 73a6cb983c46cbe2e3a603dd5b8ec3155547f8d5
Author: Christian Marangi <ansuelsmth at gmail.com>
AuthorDate: Mon Feb 3 01:08:35 2025 +0100

    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 at gmail.com>
---
 target/linux/generic/config-6.6                    |   1 +
 ...m-core-generalize-mac-base-cells-handling.patch |  98 +++++++++++
 ...-layouts-add-support-for-ascii-env-driver.patch | 187 +++++++++++++++++++++
 3 files changed, 286 insertions(+)

diff --git a/target/linux/generic/config-6.6 b/target/linux/generic/config-6.6
index a92151700d..b83aecdc88 100644
--- a/target/linux/generic/config-6.6
+++ b/target/linux/generic/config-6.6
@@ -4346,6 +4346,7 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NVMEM_LAYOUT_ONIE_TLV is not set
 # CONFIG_NVMEM_LAYOUT_SL28_VPD 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_RMEM is not set
 # CONFIG_NVMEM_SYSFS is not set
diff --git a/target/linux/generic/pending-6.6/809-01-nvmem-core-generalize-mac-base-cells-handling.patch b/target/linux/generic/pending-6.6/809-01-nvmem-core-generalize-mac-base-cells-handling.patch
new file mode 100644
index 0000000000..9cdee61edb
--- /dev/null
+++ b/target/linux/generic/pending-6.6/809-01-nvmem-core-generalize-mac-base-cells-handling.patch
@@ -0,0 +1,98 @@
+From 995a6e0d3fdd1e4fb38465f224db8a4c7b1e279d Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth at 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 at 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;
diff --git a/target/linux/generic/pending-6.6/809-02-nvmem-layouts-add-support-for-ascii-env-driver.patch b/target/linux/generic/pending-6.6/809-02-nvmem-layouts-add-support-for-ascii-env-driver.patch
new file mode 100644
index 0000000000..dd4af0f296
--- /dev/null
+++ b/target/linux/generic/pending-6.6/809-02-nvmem-layouts-add-support-for-ascii-env-driver.patch
@@ -0,0 +1,187 @@
+From 38287e8ec5c0281377fc70f11f20bcd9986a05f5 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth at 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 at 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 at 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 at gmail.com>");
++MODULE_LICENSE("GPL");
++MODULE_DEVICE_TABLE(of, ascii_env_of_match_table);
++MODULE_DESCRIPTION("NVMEM layout driver for ASCII environment variables");




More information about the lede-commits mailing list