From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Martin Ayotte Date: Wed, 20 Jul 2016 10:56:30 -0400 Subject: [ARCHEOLOGY] Add ConfigFS for overlays support in v4.6.x > X-Git-Archeology: - Revision 7eb8428bb65aedbd9ef506d942a0a7420c8becd6: https://github.com/armbian/build/commit/7eb8428bb65aedbd9ef506d942a0a7420c8becd6 > X-Git-Archeology: Date: Wed, 20 Jul 2016 10:56:30 -0400 > X-Git-Archeology: From: Martin Ayotte > X-Git-Archeology: Subject: Add ConfigFS for overlays support in v4.6.x > X-Git-Archeology: > X-Git-Archeology: - Revision 12c0a8a81224224d3fd9b487bf2e178fcb0cb9bd: https://github.com/armbian/build/commit/12c0a8a81224224d3fd9b487bf2e178fcb0cb9bd > X-Git-Archeology: Date: Wed, 20 Jul 2016 11:19:44 -0400 > X-Git-Archeology: From: Martin Ayotte > X-Git-Archeology: Subject: move the add_configfs_overlay_for_v4.6.x.patch into sun8i-dev > X-Git-Archeology: > X-Git-Archeology: - Revision 536c9d795d9d5fe491795b4fff6bd1676b229688: https://github.com/armbian/build/commit/536c9d795d9d5fe491795b4fff6bd1676b229688 > X-Git-Archeology: Date: Fri, 22 Jul 2016 17:24:12 -0400 > X-Git-Archeology: From: Martin Ayotte > X-Git-Archeology: Subject: fix Makefile in add_configfs_overlay_for_v4.6.x.patch > X-Git-Archeology: > X-Git-Archeology: - Revision 023b2e10a58d5090d6c1a6e1e34fdf2348900e0a: https://github.com/armbian/build/commit/023b2e10a58d5090d6c1a6e1e34fdf2348900e0a > X-Git-Archeology: Date: Sun, 24 Jul 2016 16:50:16 -0400 > X-Git-Archeology: From: Martin Ayotte > X-Git-Archeology: Subject: remove debugging message > X-Git-Archeology: > X-Git-Archeology: - Revision a659f1769e5a08e780db9cb7a8aa35a49e90c917: https://github.com/armbian/build/commit/a659f1769e5a08e780db9cb7a8aa35a49e90c917 > X-Git-Archeology: Date: Fri, 12 Aug 2016 15:13:23 -0400 > X-Git-Archeology: From: Martin Ayotte > X-Git-Archeology: Subject: add modified ConfigFS patches for kernel 4.8.x in sunxi-dev > X-Git-Archeology: > X-Git-Archeology: - Revision 2def4ca6d90a8bba0df71a395ea08d9811169c24: https://github.com/armbian/build/commit/2def4ca6d90a8bba0df71a395ea08d9811169c24 > X-Git-Archeology: Date: Mon, 09 Jan 2017 10:54:22 -0500 > X-Git-Archeology: From: Martin Ayotte > X-Git-Archeology: Subject: remove useless part of the patch for 4.10.x > X-Git-Archeology: > X-Git-Archeology: - Revision 43f9fe3debf8061be55dc51d0069973a61c707d4: https://github.com/armbian/build/commit/43f9fe3debf8061be55dc51d0069973a61c707d4 > X-Git-Archeology: Date: Mon, 09 Jan 2017 10:55:14 -0500 > X-Git-Archeology: From: Martin Ayotte > X-Git-Archeology: Subject: rename patch for 4.10.x > X-Git-Archeology: > X-Git-Archeology: - Revision b0fcb64aaca589359338a500e7bc07eb7ca1cb71: https://github.com/armbian/build/commit/b0fcb64aaca589359338a500e7bc07eb7ca1cb71 > X-Git-Archeology: Date: Thu, 07 Dec 2017 07:09:10 +0100 > X-Git-Archeology: From: Igor Pecovnik > X-Git-Archeology: Subject: Temporally disabling broken patches on sunxi DEV branch > X-Git-Archeology: > X-Git-Archeology: - Revision 2c08ec8f5a210de35f9482f482ac01ea15381792: https://github.com/armbian/build/commit/2c08ec8f5a210de35f9482f482ac01ea15381792 > X-Git-Archeology: Date: Thu, 24 May 2018 13:32:29 +0200 > X-Git-Archeology: From: Igor Pecovnik > X-Git-Archeology: Subject: Merge sunxi family into stable > X-Git-Archeology: > X-Git-Archeology: - Revision 8bc9d032a372ebd1b8f8126e439658a9879789d4: https://github.com/armbian/build/commit/8bc9d032a372ebd1b8f8126e439658a9879789d4 > X-Git-Archeology: Date: Wed, 27 Jun 2018 11:24:34 -0400 > X-Git-Archeology: From: Martin Ayotte > X-Git-Archeology: Subject: fix pantoniou configfs using pelwell patch for new OF API > X-Git-Archeology: > X-Git-Archeology: - Revision 1a12994e79b6ef173dc58efe4df8919cb6cc7781: https://github.com/armbian/build/commit/1a12994e79b6ef173dc58efe4df8919cb6cc7781 > X-Git-Archeology: Date: Tue, 17 Jul 2018 15:53:30 +0200 > X-Git-Archeology: From: Igor Pecovnik > X-Git-Archeology: Subject: Moving sunxi-next to 4.17.y (#1049) > X-Git-Archeology: > X-Git-Archeology: - Revision a57ce78b37f8dd2eb94a3836f4a7f6969f2ffd72: https://github.com/armbian/build/commit/a57ce78b37f8dd2eb94a3836f4a7f6969f2ffd72 > X-Git-Archeology: Date: Tue, 21 Aug 2018 10:41:10 +0200 > X-Git-Archeology: From: Igor Pecovnik > X-Git-Archeology: Subject: Reverting sunxi/sunxi64 NEXT to 4.14. (#1087) > X-Git-Archeology: > X-Git-Archeology: - Revision 0aec4b058834e16d12ddff68c90ecbed946b19a3: https://github.com/armbian/build/commit/0aec4b058834e16d12ddff68c90ecbed946b19a3 > X-Git-Archeology: Date: Tue, 04 Dec 2018 15:10:36 -0500 > X-Git-Archeology: From: Martin Ayotte > X-Git-Archeology: Subject: add configfs for overlay on meson64-dev > X-Git-Archeology: > X-Git-Archeology: - Revision 150ac0c2afa147d9e3b036c8ecd8238fe5648cf3: https://github.com/armbian/build/commit/150ac0c2afa147d9e3b036c8ecd8238fe5648cf3 > X-Git-Archeology: Date: Tue, 19 Nov 2019 23:25:39 +0100 > X-Git-Archeology: From: Igor Pecovnik > X-Git-Archeology: Subject: Remove K<4, change branches, new features (#1586) > X-Git-Archeology: > X-Git-Archeology: - Revision 2c439b921988b4f5210866ed484304d804cca60f: https://github.com/armbian/build/commit/2c439b921988b4f5210866ed484304d804cca60f > X-Git-Archeology: Date: Mon, 30 Dec 2019 21:25:03 +0100 > X-Git-Archeology: From: Piotr Szczepanik > X-Git-Archeology: Subject: Overlay configfs support for rockchip64-current (#1699) > X-Git-Archeology: > X-Git-Archeology: - Revision 20d17a7c9556b6eb39c2557b4a17fa0181f763fc: https://github.com/armbian/build/commit/20d17a7c9556b6eb39c2557b4a17fa0181f763fc > X-Git-Archeology: Date: Fri, 19 Jun 2020 09:47:44 +0200 > X-Git-Archeology: From: m][sko > X-Git-Archeology: Subject: Switch meson to linux 5.7 (#2024) > X-Git-Archeology: > X-Git-Archeology: - Revision 23604e8a0dcdf81ec6c28ccd4b2a64b90816d8e7: https://github.com/armbian/build/commit/23604e8a0dcdf81ec6c28ccd4b2a64b90816d8e7 > X-Git-Archeology: Date: Fri, 19 Jun 2020 17:27:27 +0200 > X-Git-Archeology: From: Paolo > X-Git-Archeology: Subject: Introducing Rockchip RK322X SoC support (#2032) > X-Git-Archeology: > X-Git-Archeology: - Revision 0cdffb29b07305209efb12cf3b5ac6032d3a1153: https://github.com/armbian/build/commit/0cdffb29b07305209efb12cf3b5ac6032d3a1153 > X-Git-Archeology: Date: Wed, 24 Mar 2021 19:01:53 +0100 > X-Git-Archeology: From: Igor Pecovnik > X-Git-Archeology: Subject: Renaming DEV branch to EDGE (#2704) > X-Git-Archeology: > X-Git-Archeology: - Revision 1e37959e5381a0a1d1eaf0629cdc19658f30df9a: https://github.com/armbian/build/commit/1e37959e5381a0a1d1eaf0629cdc19658f30df9a > X-Git-Archeology: Date: Thu, 10 Feb 2022 20:32:58 +0100 > X-Git-Archeology: From: Igor Pecovnik > X-Git-Archeology: Subject: Bumping sunxi/64, xu4, rockchip and mvebu64 to 5.16.y (#3453) > X-Git-Archeology: > X-Git-Archeology: - Revision f08dcd48677d2a34f349bf571c979cd422bffcc3: https://github.com/armbian/build/commit/f08dcd48677d2a34f349bf571c979cd422bffcc3 > X-Git-Archeology: Date: Tue, 31 Oct 2023 08:13:23 +0100 > X-Git-Archeology: From: Paolo > X-Git-Archeology: Subject: rockchip,rk322x: bump edge kernel to 6.6 (#5875) > X-Git-Archeology: > X-Git-Archeology: - Revision 562d96128ba6a511a8a06c0f4d29946ab80b8969: https://github.com/armbian/build/commit/562d96128ba6a511a8a06c0f4d29946ab80b8969 > X-Git-Archeology: Date: Tue, 26 Dec 2023 16:45:30 +0100 > X-Git-Archeology: From: Paolo Sabatino > X-Git-Archeology: Subject: consolidate rk322x and rockchip 32 bit families > X-Git-Archeology: > X-Git-Archeology: - Revision 54628d7d3e11824e560b77e905f69d52feb0fbd0: https://github.com/armbian/build/commit/54628d7d3e11824e560b77e905f69d52feb0fbd0 > X-Git-Archeology: Date: Wed, 01 Jan 2025 19:38:55 +0100 > X-Git-Archeology: From: Paolo Sabatino > X-Git-Archeology: Subject: rockchip: bump edge kernel to 6.13-rc5 > X-Git-Archeology: > X-Git-Archeology: - Revision 7c55b4fce91f38383398a7498dde1c6d69a70495: https://github.com/armbian/build/commit/7c55b4fce91f38383398a7498dde1c6d69a70495 > X-Git-Archeology: Date: Wed, 26 Mar 2025 22:23:29 +0100 > X-Git-Archeology: From: Paolo Sabatino > X-Git-Archeology: Subject: bump rockchip 32bit edge kernel to v6.14 > X-Git-Archeology: > X-Git-Archeology: - Revision cc4cb72d4069147ea1b5e6936de3b49aace21967: https://github.com/armbian/build/commit/cc4cb72d4069147ea1b5e6936de3b49aace21967 > X-Git-Archeology: Date: Tue, 03 Jun 2025 09:53:37 +0200 > X-Git-Archeology: From: Paolo Sabatino > X-Git-Archeology: Subject: bump rockchip 32 bit edge kernel to 6.15 > X-Git-Archeology: > X-Git-Archeology: - Revision 96fe7dee19eaec6d9c5159a5cc50e33ca9c96096: https://github.com/armbian/build/commit/96fe7dee19eaec6d9c5159a5cc50e33ca9c96096 > X-Git-Archeology: Date: Mon, 28 Jul 2025 20:45:52 +0800 > X-Git-Archeology: From: Paolo Sabatino > X-Git-Archeology: Subject: bump rockchip edge to kernel 6.16 > X-Git-Archeology: > X-Git-Archeology: - Revision 29317c6f7e33f2cc509acc0da23b615a7d9d8c31: https://github.com/armbian/build/commit/29317c6f7e33f2cc509acc0da23b615a7d9d8c31 > X-Git-Archeology: Date: Thu, 18 Sep 2025 22:48:06 +0200 > X-Git-Archeology: From: Paolo Sabatino > X-Git-Archeology: Subject: update rockchip 32 bit edge kernel to 6.17 > X-Git-Archeology: --- Documentation/devicetree/configfs-overlays.txt | 31 + drivers/of/Kconfig | 7 + drivers/of/Makefile | 1 + drivers/of/configfs.c | 290 ++++++++++ 4 files changed, 329 insertions(+) diff --git a/Documentation/devicetree/configfs-overlays.txt b/Documentation/devicetree/configfs-overlays.txt new file mode 100644 index 000000000000..111111111111 --- /dev/null +++ b/Documentation/devicetree/configfs-overlays.txt @@ -0,0 +1,31 @@ +Howto use the configfs overlay interface. + +A device-tree configfs entry is created in /config/device-tree/overlays +and and it is manipulated using standard file system I/O. +Note that this is a debug level interface, for use by developers and +not necessarily something accessed by normal users due to the +security implications of having direct access to the kernel's device tree. + +* To create an overlay you mkdir the directory: + + # mkdir /config/device-tree/overlays/foo + +* Either you echo the overlay firmware file to the path property file. + + # echo foo.dtbo >/config/device-tree/overlays/foo/path + +* Or you cat the contents of the overlay to the dtbo file + + # cat foo.dtbo >/config/device-tree/overlays/foo/dtbo + +The overlay file will be applied, and devices will be created/destroyed +as required. + +To remove it simply rmdir the directory. + + # rmdir /config/device-tree/overlays/foo + +The rationalle of the dual interface (firmware & direct copy) is that each is +better suited to different use patterns. The firmware interface is what's +intended to be used by hardware managers in the kernel, while the copy interface +make sense for developers (since it avoids problems with namespaces). diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 111111111111..222222222222 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -126,4 +126,11 @@ config OF_OVERLAY_KUNIT_TEST config OF_NUMA bool +config OF_CONFIGFS + bool "Device Tree Overlay ConfigFS interface" + select CONFIGFS_FS + select OF_OVERLAY + help + Enable a simple user-space driven DT overlay interface. + endif # OF diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 111111111111..222222222222 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -1,6 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-y = base.o cpu.o device.o module.o platform.o property.o obj-$(CONFIG_OF_KOBJ) += kobj.o +obj-$(CONFIG_OF_CONFIGFS) += configfs.o obj-$(CONFIG_OF_DYNAMIC) += dynamic.o obj-$(CONFIG_OF_FLATTREE) += fdt.o empty_root.dtb.o obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o diff --git a/drivers/of/configfs.c b/drivers/of/configfs.c new file mode 100644 index 000000000000..111111111111 --- /dev/null +++ b/drivers/of/configfs.c @@ -0,0 +1,290 @@ +/* + * Configfs entries for device-tree + * + * Copyright (C) 2013 - Pantelis Antoniou + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "of_private.h" + +struct cfs_overlay_item { + struct config_item item; + + char path[PATH_MAX]; + + const struct firmware *fw; + struct device_node *overlay; + int ov_id; + + void *dtbo; + int dtbo_size; +}; + +static int create_overlay(struct cfs_overlay_item *overlay, void *blob, u32 blob_size) +{ + int err; + + err = of_overlay_fdt_apply(blob, blob_size, &overlay->ov_id, NULL); + if (err < 0) { + pr_err("%s: Failed to create overlay (err=%d)\n", + __func__, err); + goto out_err; + } + +out_err: + return err; +} + +static inline struct cfs_overlay_item *to_cfs_overlay_item( + struct config_item *item) +{ + return item ? container_of(item, struct cfs_overlay_item, item) : NULL; +} + +static ssize_t cfs_overlay_item_path_show(struct config_item *item, + char *page) +{ + struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); + return sprintf(page, "%s\n", overlay->path); +} + +static ssize_t cfs_overlay_item_path_store(struct config_item *item, + const char *page, size_t count) +{ + struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); + const char *p = page; + char *s; + int err; + + /* if it's set do not allow changes */ + if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) + return -EPERM; + + /* copy to path buffer (and make sure it's always zero terminated */ + count = snprintf(overlay->path, sizeof(overlay->path) - 1, "%s", p); + overlay->path[sizeof(overlay->path) - 1] = '\0'; + + /* strip trailing newlines */ + s = overlay->path + strlen(overlay->path); + while (s > overlay->path && *--s == '\n') + *s = '\0'; + + pr_debug("%s: path is '%s'\n", __func__, overlay->path); + + err = request_firmware(&overlay->fw, overlay->path, NULL); + if (err != 0) + goto out_err; + + err = create_overlay(overlay, (void *)overlay->fw->data, overlay->fw->size); + if (err != 0) + goto out_err; + + return count; + +out_err: + + release_firmware(overlay->fw); + overlay->fw = NULL; + + overlay->path[0] = '\0'; + return err; +} + +static ssize_t cfs_overlay_item_status_show(struct config_item *item, + char *page) +{ + struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); + + return sprintf(page, "%s\n", + overlay->ov_id >= 0 ? "applied" : "unapplied"); +} + +CONFIGFS_ATTR(cfs_overlay_item_, path); +CONFIGFS_ATTR_RO(cfs_overlay_item_, status); + +static struct configfs_attribute *cfs_overlay_attrs[] = { + &cfs_overlay_item_attr_path, + &cfs_overlay_item_attr_status, + NULL, +}; + +ssize_t cfs_overlay_item_dtbo_read(struct config_item *item, + void *buf, size_t max_count) +{ + struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); + + pr_debug("%s: buf=%p max_count=%zu\n", __func__, + buf, max_count); + + if (overlay->dtbo == NULL) + return 0; + + /* copy if buffer provided */ + if (buf != NULL) { + /* the buffer must be large enough */ + if (overlay->dtbo_size > max_count) + return -ENOSPC; + + memcpy(buf, overlay->dtbo, overlay->dtbo_size); + } + + return overlay->dtbo_size; +} + +ssize_t cfs_overlay_item_dtbo_write(struct config_item *item, + const void *buf, size_t count) +{ + struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); + int err; + + /* if it's set do not allow changes */ + if (overlay->path[0] != '\0' || overlay->dtbo_size > 0) + return -EPERM; + + /* copy the contents */ + overlay->dtbo = kmemdup(buf, count, GFP_KERNEL); + if (overlay->dtbo == NULL) + return -ENOMEM; + + overlay->dtbo_size = count; + + err = create_overlay(overlay, overlay->dtbo, overlay->dtbo_size); + if (err != 0) + goto out_err; + + return count; + +out_err: + kfree(overlay->dtbo); + overlay->dtbo = NULL; + overlay->dtbo_size = 0; + + return err; +} + +CONFIGFS_BIN_ATTR(cfs_overlay_item_, dtbo, NULL, SZ_1M); + +static struct configfs_bin_attribute *cfs_overlay_bin_attrs[] = { + &cfs_overlay_item_attr_dtbo, + NULL, +}; + +static void cfs_overlay_release(struct config_item *item) +{ + struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); + + if (overlay->ov_id >= 0) + of_overlay_remove(&overlay->ov_id); + if (overlay->fw) + release_firmware(overlay->fw); + /* kfree with NULL is safe */ + kfree(overlay->dtbo); + kfree(overlay); +} + +static struct configfs_item_operations cfs_overlay_item_ops = { + .release = cfs_overlay_release, +}; + +static struct config_item_type cfs_overlay_type = { + .ct_item_ops = &cfs_overlay_item_ops, + .ct_attrs = cfs_overlay_attrs, + .ct_bin_attrs = cfs_overlay_bin_attrs, + .ct_owner = THIS_MODULE, +}; + +static struct config_item *cfs_overlay_group_make_item( + struct config_group *group, const char *name) +{ + struct cfs_overlay_item *overlay; + + overlay = kzalloc(sizeof(*overlay), GFP_KERNEL); + if (!overlay) + return ERR_PTR(-ENOMEM); + overlay->ov_id = -1; + + config_item_init_type_name(&overlay->item, name, &cfs_overlay_type); + return &overlay->item; +} + +static void cfs_overlay_group_drop_item(struct config_group *group, + struct config_item *item) +{ + struct cfs_overlay_item *overlay = to_cfs_overlay_item(item); + + config_item_put(&overlay->item); +} + +static struct configfs_group_operations overlays_ops = { + .make_item = cfs_overlay_group_make_item, + .drop_item = cfs_overlay_group_drop_item, +}; + +static struct config_item_type overlays_type = { + .ct_group_ops = &overlays_ops, + .ct_owner = THIS_MODULE, +}; + +static struct configfs_group_operations of_cfs_ops = { + /* empty - we don't allow anything to be created */ +}; + +static struct config_item_type of_cfs_type = { + .ct_group_ops = &of_cfs_ops, + .ct_owner = THIS_MODULE, +}; + +struct config_group of_cfs_overlay_group; + +static struct configfs_subsystem of_cfs_subsys = { + .su_group = { + .cg_item = { + .ci_namebuf = "device-tree", + .ci_type = &of_cfs_type, + }, + }, + .su_mutex = __MUTEX_INITIALIZER(of_cfs_subsys.su_mutex), +}; + +static int __init of_cfs_init(void) +{ + int ret; + + pr_info("%s\n", __func__); + + config_group_init(&of_cfs_subsys.su_group); + config_group_init_type_name(&of_cfs_overlay_group, "overlays", + &overlays_type); + configfs_add_default_group(&of_cfs_overlay_group, + &of_cfs_subsys.su_group); + + ret = configfs_register_subsystem(&of_cfs_subsys); + if (ret != 0) { + pr_err("%s: failed to register subsys\n", __func__); + goto out; + } + pr_info("%s: OK\n", __func__); +out: + return ret; +} +late_initcall(of_cfs_init); -- Armbian