From: Christian Marangi Date: Mon, 3 Feb 2025 00:08:35 +0000 (+0100) Subject: generic: add pending support for NVMEM ASCII ENV layout driver X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=73a6cb983c46cbe2e3a603dd5b8ec3155547f8d5;p=openwrt%2Fopenwrt.git 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 --- 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 +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 +--- + 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 +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 +--- + 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 ++ * ++ * This borrow some parse logic from u-boot-env. ++ */ ++#include ++#include ++#include ++#include ++ ++/* ++ * 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 "); ++MODULE_LICENSE("GPL"); ++MODULE_DEVICE_TABLE(of, ascii_env_of_match_table); ++MODULE_DESCRIPTION("NVMEM layout driver for ASCII environment variables");