| From a8ecc3ce0fcabb2414a000b7c8bfe3ce46d4392c Mon Sep 17 00:00:00 2001 |
| From: Sughosh Ganu <sughosh.ganu@linaro.org> |
| Date: Thu, 21 Sep 2023 14:13:42 +0100 |
| Subject: [PATCH 33/38] dt: Provide a way to remove non-compliant nodes and |
| properties |
| |
| Add a function which is registered to spy for a EVT_FT_FIXUP event, |
| and removes the non upstreamed nodes and properties from the |
| devicetree before it gets passed to the OS. |
| |
| This allows removing entire nodes, or specific properties under nodes |
| from the devicetree. The required nodes and properties can be |
| registered for removal through the DT_NON_COMPLIANT_PURGE and |
| DT_NON_COMPLIANT_PURGE_LIST macros. |
| |
| Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org> |
| Upstream-Status: Submitted [RFC: https://lore.kernel.org/u-boot/aca7e6fa-2dec-a7c5-e47e-84c5ffa6f9b7@gmx.de/T/#m16d14ee960427cc88066bdcdd76f0a26738bb66d] |
| --- |
| include/dt-structs.h | 11 +++++++ |
| lib/Makefile | 1 + |
| lib/dt_purge.c | 73 ++++++++++++++++++++++++++++++++++++++++++++ |
| 3 files changed, 85 insertions(+) |
| create mode 100644 lib/dt_purge.c |
| |
| diff --git a/include/dt-structs.h b/include/dt-structs.h |
| index fa1622cb1d..f535c60471 100644 |
| --- a/include/dt-structs.h |
| +++ b/include/dt-structs.h |
| @@ -57,3 +57,14 @@ struct phandle_2_arg { |
| #endif |
| |
| #endif |
| + |
| +struct dt_non_compliant_purge { |
| + const char *node_path; |
| + const char *prop; |
| +}; |
| + |
| +#define DT_NON_COMPLIANT_PURGE(__name) \ |
| + ll_entry_declare(struct dt_non_compliant_purge, __name, dt_purge) |
| + |
| +#define DT_NON_COMPLIANT_PURGE_LIST(__name) \ |
| + ll_entry_declare_list(struct dt_non_compliant_purge, __name, dt_purge) |
| diff --git a/lib/Makefile b/lib/Makefile |
| index 8d8ccc8bbc..82a906daa0 100644 |
| --- a/lib/Makefile |
| +++ b/lib/Makefile |
| @@ -37,6 +37,7 @@ endif |
| obj-y += crc8.o |
| obj-y += crc16.o |
| obj-y += crc16-ccitt.o |
| +obj-y += dt_purge.o |
| obj-$(CONFIG_ERRNO_STR) += errno_str.o |
| obj-$(CONFIG_FIT) += fdtdec_common.o |
| obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o |
| diff --git a/lib/dt_purge.c b/lib/dt_purge.c |
| new file mode 100644 |
| index 0000000000..f893ba9796 |
| --- /dev/null |
| +++ b/lib/dt_purge.c |
| @@ -0,0 +1,73 @@ |
| +// SPDX-License-Identifier: GPL-2.0-or-later |
| +/* |
| + * Copyright (c) 2023, Linaro Limited |
| + */ |
| + |
| +#include <dt-structs.h> |
| +#include <event.h> |
| +#include <linker_lists.h> |
| + |
| +#include <linux/libfdt.h> |
| + |
| +/** |
| + * dt_non_compliant_purge() - Remove non-upstreamed nodes and properties |
| + * from the DT |
| + * @ctx: Context for event |
| + * @event: Event to process |
| + * |
| + * Iterate through an array of DT nodes and properties, and remove them |
| + * from the device-tree before the DT gets handed over to the kernel. |
| + * These are nodes and properties which do not have upstream bindings |
| + * and need to be purged before being handed over to the kernel. |
| + * |
| + * If both the node and property are specified, delete the property. If |
| + * only the node is specified, delete the entire node, including it's |
| + * subnodes, if any. |
| + * |
| + * Return: 0 if OK, -ve on error |
| + */ |
| +static int dt_non_compliant_purge(void *ctx, struct event *event) |
| +{ |
| + int nodeoff = 0; |
| + int err = 0; |
| + void *fdt; |
| + const struct event_ft_fixup *fixup = &event->data.ft_fixup; |
| + struct dt_non_compliant_purge *purge_entry; |
| + struct dt_non_compliant_purge *purge_start = |
| + ll_entry_start(struct dt_non_compliant_purge, dt_purge); |
| + int nentries = ll_entry_count(struct dt_non_compliant_purge, dt_purge); |
| + |
| + if (fixup->images) |
| + return 0; |
| + |
| + fdt = fixup->tree.fdt; |
| + for (purge_entry = purge_start; purge_entry != purge_start + nentries; |
| + purge_entry++) { |
| + nodeoff = fdt_path_offset(fdt, purge_entry->node_path); |
| + if (nodeoff < 0) { |
| + log_debug("Error (%d) getting node offset for %s\n", |
| + nodeoff, purge_entry->node_path); |
| + continue; |
| + } |
| + |
| + if (purge_entry->prop) { |
| + err = fdt_delprop(fdt, nodeoff, purge_entry->prop); |
| + if (err < 0 && err != -FDT_ERR_NOTFOUND) { |
| + log_debug("Error (%d) deleting %s\n", |
| + err, purge_entry->prop); |
| + goto out; |
| + } |
| + } else { |
| + err = fdt_del_node(fdt, nodeoff); |
| + if (err) { |
| + log_debug("Error (%d) trying to delete node %s\n", |
| + err, purge_entry->node_path); |
| + goto out; |
| + } |
| + } |
| + } |
| + |
| +out: |
| + return err; |
| +} |
| +EVENT_SPY(EVT_FT_FIXUP, dt_non_compliant_purge); |
| -- |
| 2.25.1 |
| |