mirror of
https://github.com/openwrt/openwrt.git
synced 2025-03-14 16:26:34 +00:00
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_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
|
||||
|
@ -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