# \[PATCH 0/5\] of: overlay: Assorted fixes

- Subsystems: OPEN FIRMWARE AND FLATTENED DEVICE TREE, THE REST
- Maintainers: Rob Herring, Saravana Kannan, Linus Torvalds
- Series: 5 patches touching 6 files, +209/-3
- Status: SUPERSEDED (Superseded by v2 posted 2015-04-07)
- Superseded by v2 (posted 2015-04-07).
- Revision v1 (2 revisions archived).
- List: linux-api
- 13 messages, 3 authors
- Page: https://ratatoskr.run/linux-api/2015/03/4453371/t

## \[PATCH 0/5\] of: overlay: Assorted fixes

- From: Pantelis Antoniou \<hidden\>
- Date: 2015-03-17 20:31:08 
- Message: https://ratatoskr.run/linux-api/2015/03/4453371.md

```text
The first patch makes sure that no overlays are being left over from
the unit tests.

The second puts the overlays as objects in the sysfs in
/sys/firmware/devicetree/overlays while the next one adds a master
overlay enable switch (that once is set to disabled can't be re-enabled)

The next updates the ABI docs and the final one adds me as the
maintainer for device tree overlays.

Pantelis Antoniou (5):
  of: unittest: overlay: Keep track of created overlays
  of: overlay: kobjectify overlay objects
  of: overlay: Master enable switch
  Documentation: ABI: /sys/firmware/devicetree/overlays
  MAINTAINERS: Pantelis Antoniou device tree overlay maintainer

 .../ABI/testing/sysfs-firmware-devicetree-overlays |   9 ++
 MAINTAINERS                                        |   9 ++
 drivers/of/base.c                                  |   5 +
 drivers/of/of_private.h                            |   9 ++
 drivers/of/overlay.c                               | 116 ++++++++++++++++++++-
 drivers/of/unittest.c                              |  62 +++++++++++
 6 files changed, 208 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-firmware-devicetree-overlays

-- 
1.7.12
```

## \[PATCH 2/5\] of: overlay: kobjectify overlay objects

- From: Pantelis Antoniou \<hidden\>
- Date: 2015-03-17 20:31:14 
- Message: https://ratatoskr.run/linux-api/2015/03/4453373.md

```text
We are going to need the overlays to appear on sysfs with runtime
global properties (like master enable) so turn them into kobjects.

Signed-off-by: Pantelis Antoniou <redacted>
---
 drivers/of/base.c       |  5 +++++
 drivers/of/of_private.h |  9 +++++++++
 drivers/of/overlay.c    | 52 +++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index adb8764..9b4d6f9 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -192,6 +192,7 @@ int __of_attach_node_sysfs(struct device_node *np)
 static int __init of_init(void)
 {
 	struct device_node *np;
+	int ret;
 
 	/* Create the kset, and register existing nodes */
 	mutex_lock(&of_mutex);
@@ -208,6 +209,10 @@ static int __init of_init(void)
 	if (of_root)
 		proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
 
+	ret = of_overlay_init();
+	if (ret != 0)
+		pr_warn("of_init: of_overlay_init failed!\n");
+
 	return 0;
 }
 core_initcall(of_init);
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 8e882e7..120eb44 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -90,4 +90,13 @@ extern void __of_detach_node_sysfs(struct device_node *np);
 #define for_each_transaction_entry_reverse(_oft, _te) \
 	list_for_each_entry_reverse(_te, &(_oft)->te_list, node)
 
+#if defined(CONFIG_OF_OVERLAY)
+extern int of_overlay_init(void);
+#else
+static inline int of_overlay_init(void)
+{
+	return 0;
+}
+#endif
+
 #endif /* _LINUX_OF_PRIVATE_H */
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index dee9270..f17f5ef 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/idr.h>
+#include <linux/sysfs.h>
 
 #include "of_private.h"
 
@@ -51,6 +52,7 @@ struct of_overlay {
 	int count;
 	struct of_overlay_info *ovinfo_tab;
 	struct of_changeset cset;
+	struct kobject kobj;
 };
 
 static int of_overlay_apply_one(struct of_overlay *ov,
@@ -325,6 +327,24 @@ static int of_free_overlay_info(struct of_overlay *ov)
 static LIST_HEAD(ov_list);
 static DEFINE_IDR(ov_idr);
 
+static inline struct of_overlay *kobj_to_overlay(struct kobject *kobj)
+{
+	return container_of(kobj, struct of_overlay, kobj);
+}
+
+void of_overlay_release(struct kobject *kobj)
+{
+	struct of_overlay *ov = kobj_to_overlay(kobj);
+
+	kfree(ov);
+}
+
+static struct kobj_type of_overlay_ktype = {
+	.release = of_overlay_release,
+};
+
+static struct kset *ov_kset;
+
 /**
  * of_overlay_create() - Create and apply an overlay
  * @tree:	Device node containing all the overlays
@@ -350,6 +370,9 @@ int of_overlay_create(struct device_node *tree)
 
 	of_changeset_init(&ov->cset);
 
+	/* initialize kobject */
+	kobject_init(&ov->kobj, &of_overlay_ktype);
+
 	mutex_lock(&of_mutex);
 
 	id = idr_alloc(&ov_idr, ov, 0, 0, GFP_KERNEL);
@@ -385,6 +408,14 @@ int of_overlay_create(struct device_node *tree)
 		goto err_revert_overlay;
 	}
 
+	ov->kobj.kset = ov_kset;
+	err = kobject_add(&ov->kobj, NULL, "%d", id);
+	if (err != 0) {
+		pr_err("%s: kobject_add() failed for tree@%s\n",
+				__func__, tree->full_name);
+		goto err_cancel_overlay;
+	}
+
 	/* add to the tail of the overlay list */
 	list_add_tail(&ov->node, &ov_list);
 
@@ -392,6 +423,8 @@ int of_overlay_create(struct device_node *tree)
 
 	return id;
 
+err_cancel_overlay:
+	of_changeset_revert(&ov->cset);
 err_revert_overlay:
 err_abort_trans:
 	of_free_overlay_info(ov);
@@ -512,7 +545,9 @@ int of_overlay_destroy(int id)
 	of_free_overlay_info(ov);
 	idr_remove(&ov_idr, id);
 	of_changeset_destroy(&ov->cset);
-	kfree(ov);
+
+	kobject_del(&ov->kobj);
+	kobject_put(&ov->kobj);
 
 	err = 0;
 
@@ -542,7 +577,8 @@ int of_overlay_destroy_all(void)
 		of_changeset_revert(&ov->cset);
 		of_free_overlay_info(ov);
 		idr_remove(&ov_idr, ov->id);
-		kfree(ov);
+		kobject_del(&ov->kobj);
+		kobject_put(&ov->kobj);
 	}
 
 	mutex_unlock(&of_mutex);
@@ -550,3 +586,15 @@ int of_overlay_destroy_all(void)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(of_overlay_destroy_all);
+
+/* called from of_init() */
+int of_overlay_init(void)
+{
+	int rc;
+
+	ov_kset = kset_create_and_add("overlays", NULL, &of_kset->kobj);
+	if (!ov_kset)
+		return -ENOMEM;
+
+	return 0;
+}
-- 
1.7.12
```

## \[PATCH 3/5\] of: overlay: Master enable switch

- From: Pantelis Antoniou \<hidden\>
- Date: 2015-03-17 20:31:18 
- Message: https://ratatoskr.run/linux-api/2015/03/4453374.md

```text
Implement a throw once master enable switch to protect against any
further overlay applications if the administrator desires so.

Signed-off-by: Pantelis Antoniou <redacted>
---
 drivers/of/overlay.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 65 insertions(+), 1 deletion(-)

diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index f17f5ef..6688797 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -21,6 +21,7 @@
 #include <linux/err.h>
 #include <linux/idr.h>
 #include <linux/sysfs.h>
+#include <linux/atomic.h>
 
 #include "of_private.h"
 
@@ -55,6 +56,9 @@ struct of_overlay {
 	struct kobject kobj;
 };
 
+/* master enable switch; once set to 0 can't be re-enabled */
+static atomic_t ov_enable = ATOMIC_INIT(1);
+
 static int of_overlay_apply_one(struct of_overlay *ov,
 		struct device_node *target, const struct device_node *overlay);
 
@@ -345,6 +349,60 @@ static struct kobj_type of_overlay_ktype = {
 
 static struct kset *ov_kset;
 
+static ssize_t enable_read(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *bin_attr, char *buf,
+		loff_t offset, size_t count)
+{
+	char tbuf[3];
+
+	if (offset < 0)
+		return -EINVAL;
+
+	if (offset >= sizeof(tbuf))
+		return 0;
+
+	if (count > sizeof(tbuf) - offset)
+		count = sizeof(tbuf) - offset;
+
+	/* fill in temp */
+	tbuf[0] = '0' + atomic_read(&ov_enable);
+	tbuf[1] = '\n';
+	tbuf[2] = '\0';
+
+	/* copy to buffer */
+	memcpy(buf, tbuf + offset, count);
+
+	return count;
+}
+
+static ssize_t enable_write(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *bin_attr, char *buf,
+		loff_t off, size_t count)
+{
+	int new_enable;
+
+	if (off != 0 || (buf[0] != '0' && buf[1] != '1'))
+		return -EINVAL;
+
+	new_enable = buf[0] - '0';
+	if (new_enable != 0 && new_enable != 1)
+		return -EINVAL;
+
+	/* NOP for same value */
+	if (new_enable == atomic_read(&ov_enable))
+		return count;
+
+	/* if we've disabled it, no going back */
+	if (atomic_read(&ov_enable) == 0)
+		return -EPERM;
+
+	atomic_set(&ov_enable, new_enable);
+	return count;
+}
+
+/* just a single char + '\n' + '\0' */
+static BIN_ATTR_RW(enable, 3);
+
 /**
  * of_overlay_create() - Create and apply an overlay
  * @tree:	Device node containing all the overlays
@@ -360,6 +418,10 @@ int of_overlay_create(struct device_node *tree)
 	struct of_overlay *ov;
 	int err, id;
 
+	/* administratively disabled */
+	if (!atomic_read(&ov_enable))
+		return -EPERM;
+
 	/* allocate the overlay structure */
 	ov = kzalloc(sizeof(*ov), GFP_KERNEL);
 	if (ov == NULL)
@@ -596,5 +658,7 @@ int of_overlay_init(void)
 	if (!ov_kset)
 		return -ENOMEM;
 
-	return 0;
+	rc = sysfs_create_bin_file(&ov_kset->kobj, &bin_attr_enable);
+	WARN(rc, "%s: error adding enable attribute\n", __func__);
+	return rc;
 }
-- 
1.7.12
```

## \[PATCH 5/5\] MAINTAINERS: Pantelis Antoniou device tree overlay maintainer

- From: Pantelis Antoniou \<hidden\>
- Date: 2015-03-17 20:31:25 
- Message: https://ratatoskr.run/linux-api/2015/03/4453376.md

```text
Add me as the device tree overlays maintainer.

Signed-off-by: Pantelis Antoniou <redacted>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0e1abe8..24aa339 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7187,6 +7187,15 @@ F:	Documentation/devicetree/
 F:	arch/*/boot/dts/
 F:	include/dt-bindings/
 
+OPEN FIRMWARE AND DEVICE TREE OVERLAYS
+M:	Pantelis Antoniou <pantelis.antoniou@konsulko.com>
+L:	devicetree@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/dynamic-resolution-notes.txt
+F:	Documentation/devicetree/overlay-notes.txt
+F:	drivers/of/overlay.c
+F:	drivers/of/resolver.c
+
 OPENRISC ARCHITECTURE
 M:	Jonas Bonn <jonas@southpole.se>
 W:	http://openrisc.net
-- 
1.7.12
```

## \[PATCH 4/5\] Documentation: ABI: /sys/firmware/devicetree/overlays

- From: Pantelis Antoniou \<hidden\>
- Date: 2015-03-17 20:31:54 
- Message: https://ratatoskr.run/linux-api/2015/03/4453375.md

```text
Documentation ABI entry for overlays sysfs entries.

Signed-off-by: Pantelis Antoniou <redacted>
---
 Documentation/ABI/testing/sysfs-firmware-devicetree-overlays | 9 +++++++++
 1 file changed, 9 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-firmware-devicetree-overlays

diff --git a/Documentation/ABI/testing/sysfs-firmware-devicetree-overlays b/Documentation/ABI/testing/sysfs-firmware-devicetree-overlays
new file mode 100644
index 0000000..5a07499
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-firmware-devicetree-overlays
@@ -0,0 +1,9 @@
+What:		/sys/firmware/devicetree/overlays/
+Date:		March 2015
+Contact:	Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
+Description:
+		This directory contains the applied device tree overlays of
+		the running system, as directories of the overlay id.
+
+		enable: The master enable switch, by default is 1, and when
+		        set to 0 it cannot be re-enabled for security reasons.
-- 
1.7.12
```

## \[PATCH 1/5\] of: unittest: overlay: Keep track of created overlays

- From: Pantelis Antoniou \<hidden\>
- Date: 2015-03-17 20:32:23 
- Message: https://ratatoskr.run/linux-api/2015/03/4453372.md

```text
During the course of the overlay selftests some of them remain
applied. While this does not pose a real problem, make sure you track
them and destroy them at the end of the test.

Signed-off-by: Pantelis Antoniou <redacted>
---
 drivers/of/unittest.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 4e60682..c711534 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -23,6 +23,8 @@
 #include <linux/i2c.h>
 #include <linux/i2c-mux.h>
 
+#include <linux/bitops.h>
+
 #include "of_private.h"
 
 static struct selftest_results {
@@ -1115,6 +1117,59 @@ static const char *overlay_path(int nr)
 
 static const char *bus_path = "/testcase-data/overlay-node/test-bus";
 
+/* it is guaranteed that overlay ids are assigned in sequence */
+#define MAX_SELFTEST_OVERLAYS	256
+static unsigned long overlay_id_bits[BITS_TO_LONGS(MAX_SELFTEST_OVERLAYS)];
+static int overlay_first_id = -1;
+
+static void of_selftest_track_overlay(int id)
+{
+	if (overlay_first_id < 0)
+		overlay_first_id = id;
+	id -= overlay_first_id;
+
+	/* we shouldn't need that many */
+	BUG_ON(id >= MAX_SELFTEST_OVERLAYS);
+	overlay_id_bits[BIT_WORD(id)] |= BIT_MASK(id);
+}
+
+static void of_selftest_untrack_overlay(int id)
+{
+	if (overlay_first_id < 0)
+		return;
+	id -= overlay_first_id;
+	BUG_ON(id >= MAX_SELFTEST_OVERLAYS);
+	overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);
+}
+
+static void of_selftest_destroy_tracked_overlays(void)
+{
+	int id, ret, defers;
+
+	if (overlay_first_id < 0)
+		return;
+
+	/* try until no defers */
+	do {
+		defers = 0;
+		/* remove in reverse order */
+		for (id = MAX_SELFTEST_OVERLAYS - 1; id >= 0; id--) {
+			if (!(overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id)))
+				continue;
+
+			ret = of_overlay_destroy(id + overlay_first_id);
+			if (ret != 0) {
+				defers++;
+				pr_warn("%s: overlay destroy failed for #%d\n",
+					__func__, id + overlay_first_id);
+				continue;
+			}
+
+			overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);
+		}
+	} while (defers > 0);
+}
+
 static int of_selftest_apply_overlay(int selftest_nr, int overlay_nr,
 		int *overlay_id)
 {
@@ -1136,6 +1191,7 @@ static int of_selftest_apply_overlay(int selftest_nr, int overlay_nr,
 		goto out;
 	}
 	id = ret;
+	of_selftest_track_overlay(id);
 
 	ret = 0;
 
@@ -1349,6 +1405,7 @@ static void of_selftest_overlay_6(void)
 			return;
 		}
 		ov_id[i] = ret;
+		of_selftest_track_overlay(ov_id[i]);
 	}
 
 	for (i = 0; i < 2; i++) {
@@ -1373,6 +1430,7 @@ static void of_selftest_overlay_6(void)
 						PDEV_OVERLAY));
 			return;
 		}
+		of_selftest_untrack_overlay(ov_id[i]);
 	}
 
 	for (i = 0; i < 2; i++) {
@@ -1417,6 +1475,7 @@ static void of_selftest_overlay_8(void)
 			return;
 		}
 		ov_id[i] = ret;
+		of_selftest_track_overlay(ov_id[i]);
 	}
 
 	/* now try to remove first overlay (it should fail) */
@@ -1439,6 +1498,7 @@ static void of_selftest_overlay_8(void)
 						PDEV_OVERLAY));
 			return;
 		}
+		of_selftest_untrack_overlay(ov_id[i]);
 	}
 
 	selftest(1, "overlay test %d passed\n", 8);
@@ -1861,6 +1921,8 @@ static void __init of_selftest_overlay(void)
 	of_selftest_overlay_i2c_cleanup();
 #endif
 
+	of_selftest_destroy_tracked_overlays();
+
 out:
 	of_node_put(bus_np);
 }
-- 
1.7.12

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
```

## Re: \[PATCH 0/5\] of: overlay: Assorted fixes

- From: Rob Herring \<hidden\>
- Date: 2015-03-17 20:38:08 
- Message: https://ratatoskr.run/linux-api/2015/03/4453381.md

```text
On Tue, Mar 17, 2015 at 3:30 PM, Pantelis Antoniou
[ref] wrote:
> The first patch makes sure that no overlays are being left over from
> the unit tests.
>
> The second puts the overlays as objects in the sysfs in
> /sys/firmware/devicetree/overlays while the next one adds a master
> overlay enable switch (that once is set to disabled can't be re-enabled)
>
> The next updates the ABI docs and the final one adds me as the
> maintainer for device tree overlays.

You call this fixes, but it looks like new functionality to me. So
this looks like 4.1 material.

Rob

>
> Pantelis Antoniou (5):
>   of: unittest: overlay: Keep track of created overlays
>   of: overlay: kobjectify overlay objects
>   of: overlay: Master enable switch
>   Documentation: ABI: /sys/firmware/devicetree/overlays
>   MAINTAINERS: Pantelis Antoniou device tree overlay maintainer
>
>  .../ABI/testing/sysfs-firmware-devicetree-overlays |   9 ++
>  MAINTAINERS                                        |   9 ++
>  drivers/of/base.c                                  |   5 +
>  drivers/of/of_private.h                            |   9 ++
>  drivers/of/overlay.c                               | 116 ++++++++++++++++++++-
>  drivers/of/unittest.c                              |  62 +++++++++++
>  6 files changed, 208 insertions(+), 2 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-firmware-devicetree-overlays
>
> --
> 1.7.12
>
```

## Re: \[PATCH 0/5\] of: overlay: Assorted fixes

- From: Pantelis Antoniou \<hidden\>
- Date: 2015-03-17 20:39:57 
- Message: https://ratatoskr.run/linux-api/2015/03/4453382.md

```text

> On Mar 17, 2015, at 22:37 , Rob Herring [ref] wrote:
> 
> On Tue, Mar 17, 2015 at 3:30 PM, Pantelis Antoniou
> [ref] wrote:
>> The first patch makes sure that no overlays are being left over from
>> the unit tests.
>> 
>> The second puts the overlays as objects in the sysfs in
>> /sys/firmware/devicetree/overlays while the next one adds a master
>> overlay enable switch (that once is set to disabled can't be re-enabled)
>> 
>> The next updates the ABI docs and the final one adds me as the
>> maintainer for device tree overlays.
> 
> You call this fixes, but it looks like new functionality to me. So
> this looks like 4.1 material.
> 

Yep, they are not 4.0 material. They are not major functional changes though.

> Rob
> 

Regards

— Pantelis

>> 
>> Pantelis Antoniou (5):
>>  of: unittest: overlay: Keep track of created overlays
>>  of: overlay: kobjectify overlay objects
>>  of: overlay: Master enable switch
>>  Documentation: ABI: /sys/firmware/devicetree/overlays
>>  MAINTAINERS: Pantelis Antoniou device tree overlay maintainer
>> 
>> .../ABI/testing/sysfs-firmware-devicetree-overlays |   9 ++
>> MAINTAINERS                                        |   9 ++
>> drivers/of/base.c                                  |   5 +
>> drivers/of/of_private.h                            |   9 ++
>> drivers/of/overlay.c                               | 116 ++++++++++++++++++++-
>> drivers/of/unittest.c                              |  62 +++++++++++
>> 6 files changed, 208 insertions(+), 2 deletions(-)
>> create mode 100644 Documentation/ABI/testing/sysfs-firmware-devicetree-overlays
>> 
>> --
>> 1.7.12
>> 
```

## Re: \[PATCH 1/5\] of: unittest: overlay: Keep track of created overlays

- From: Rob Herring \<hidden\>
- Date: 2015-03-25 04:53:29 
- Message: https://ratatoskr.run/linux-api/2015/03/4458686.md

```text
On Tue, Mar 17, 2015 at 3:30 PM, Pantelis Antoniou
[ref] wrote:
> During the course of the overlay selftests some of them remain
> applied. While this does not pose a real problem, make sure you track
> them and destroy them at the end of the test.

This is going to need to be rebased on my tree as there has been some
selftest->unitest renaming.

Rob

>
> Signed-off-by: Pantelis Antoniou <redacted>
> ---
>  drivers/of/unittest.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 62 insertions(+)
>
> diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
> index 4e60682..c711534 100644
> --- a/drivers/of/unittest.c
> +++ b/drivers/of/unittest.c
> @@ -23,6 +23,8 @@
>  #include <linux/i2c.h>
>  #include <linux/i2c-mux.h>
>
> +#include <linux/bitops.h>
> +
>  #include "of_private.h"
>
>  static struct selftest_results {
> @@ -1115,6 +1117,59 @@ static const char *overlay_path(int nr)
>
>  static const char *bus_path = "/testcase-data/overlay-node/test-bus";
>
> +/* it is guaranteed that overlay ids are assigned in sequence */
> +#define MAX_SELFTEST_OVERLAYS  256
> +static unsigned long overlay_id_bits[BITS_TO_LONGS(MAX_SELFTEST_OVERLAYS)];
> +static int overlay_first_id = -1;
> +
> +static void of_selftest_track_overlay(int id)
> +{
> +       if (overlay_first_id < 0)
> +               overlay_first_id = id;
> +       id -= overlay_first_id;
> +
> +       /* we shouldn't need that many */
> +       BUG_ON(id >= MAX_SELFTEST_OVERLAYS);
> +       overlay_id_bits[BIT_WORD(id)] |= BIT_MASK(id);
> +}
> +
> +static void of_selftest_untrack_overlay(int id)
> +{
> +       if (overlay_first_id < 0)
> +               return;
> +       id -= overlay_first_id;
> +       BUG_ON(id >= MAX_SELFTEST_OVERLAYS);
> +       overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);
> +}
> +
> +static void of_selftest_destroy_tracked_overlays(void)
> +{
> +       int id, ret, defers;
> +
> +       if (overlay_first_id < 0)
> +               return;
> +
> +       /* try until no defers */
> +       do {
> +               defers = 0;
> +               /* remove in reverse order */
> +               for (id = MAX_SELFTEST_OVERLAYS - 1; id >= 0; id--) {
> +                       if (!(overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id)))
> +                               continue;
> +
> +                       ret = of_overlay_destroy(id + overlay_first_id);
> +                       if (ret != 0) {
> +                               defers++;
> +                               pr_warn("%s: overlay destroy failed for #%d\n",
> +                                       __func__, id + overlay_first_id);
> +                               continue;
> +                       }
> +
> +                       overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);
> +               }
> +       } while (defers > 0);
> +}
> +
>  static int of_selftest_apply_overlay(int selftest_nr, int overlay_nr,
>                 int *overlay_id)
>  {
> @@ -1136,6 +1191,7 @@ static int of_selftest_apply_overlay(int selftest_nr, int overlay_nr,
>                 goto out;
>         }
>         id = ret;
> +       of_selftest_track_overlay(id);
>
>         ret = 0;
>
> @@ -1349,6 +1405,7 @@ static void of_selftest_overlay_6(void)
>                         return;
>                 }
>                 ov_id[i] = ret;
> +               of_selftest_track_overlay(ov_id[i]);
>         }
>
>         for (i = 0; i < 2; i++) {
> @@ -1373,6 +1430,7 @@ static void of_selftest_overlay_6(void)
>                                                 PDEV_OVERLAY));
>                         return;
>                 }
> +               of_selftest_untrack_overlay(ov_id[i]);
>         }
>
>         for (i = 0; i < 2; i++) {
> @@ -1417,6 +1475,7 @@ static void of_selftest_overlay_8(void)
>                         return;
>                 }
>                 ov_id[i] = ret;
> +               of_selftest_track_overlay(ov_id[i]);
>         }
>
>         /* now try to remove first overlay (it should fail) */
> @@ -1439,6 +1498,7 @@ static void of_selftest_overlay_8(void)
>                                                 PDEV_OVERLAY));
>                         return;
>                 }
> +               of_selftest_untrack_overlay(ov_id[i]);
>         }
>
>         selftest(1, "overlay test %d passed\n", 8);
> @@ -1861,6 +1921,8 @@ static void __init of_selftest_overlay(void)
>         of_selftest_overlay_i2c_cleanup();
>  #endif
>
> +       of_selftest_destroy_tracked_overlays();
> +
>  out:
>         of_node_put(bus_np);
>  }
> --
> 1.7.12
>
```

## Re: \[PATCH 3/5\] of: overlay: Master enable switch

- From: Rob Herring \<hidden\>
- Date: 2015-03-25 05:25:52 
- Message: https://ratatoskr.run/linux-api/2015/03/4458692.md

```text
On Tue, Mar 17, 2015 at 3:30 PM, Pantelis Antoniou
[ref] wrote:
> Implement a throw once master enable switch to protect against any
> further overlay applications if the administrator desires so.

sysfs documentation?

> Signed-off-by: Pantelis Antoniou <redacted>
> ---
>  drivers/of/overlay.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 65 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
> index f17f5ef..6688797 100644
> --- a/drivers/of/overlay.c
> +++ b/drivers/of/overlay.c
> @@ -21,6 +21,7 @@
>  #include <linux/err.h>
>  #include <linux/idr.h>
>  #include <linux/sysfs.h>
> +#include <linux/atomic.h>
>
>  #include "of_private.h"
>
> @@ -55,6 +56,9 @@ struct of_overlay {
>         struct kobject kobj;
>  };
>
> +/* master enable switch; once set to 0 can't be re-enabled */
> +static atomic_t ov_enable = ATOMIC_INIT(1);
> +
>  static int of_overlay_apply_one(struct of_overlay *ov,
>                 struct device_node *target, const struct device_node *overlay);
>
> @@ -345,6 +349,60 @@ static struct kobj_type of_overlay_ktype = {
>
>  static struct kset *ov_kset;
>
> +static ssize_t enable_read(struct file *filp, struct kobject *kobj,
> +               struct bin_attribute *bin_attr, char *buf,
> +               loff_t offset, size_t count)
> +{
> +       char tbuf[3];
> +
> +       if (offset < 0)
> +               return -EINVAL;
> +
> +       if (offset >= sizeof(tbuf))
> +               return 0;
> +
> +       if (count > sizeof(tbuf) - offset)
> +               count = sizeof(tbuf) - offset;
> +
> +       /* fill in temp */
> +       tbuf[0] = '0' + atomic_read(&ov_enable);
> +       tbuf[1] = '\n';
> +       tbuf[2] = '\0';
> +
> +       /* copy to buffer */
> +       memcpy(buf, tbuf + offset, count);
> +
> +       return count;
> +}
> +
> +static ssize_t enable_write(struct file *filp, struct kobject *kobj,
> +               struct bin_attribute *bin_attr, char *buf,
> +               loff_t off, size_t count)
> +{
> +       int new_enable;
> +
> +       if (off != 0 || (buf[0] != '0' && buf[1] != '1'))

Is buf[1] correct here?

> +               return -EINVAL;
> +
> +       new_enable = buf[0] - '0';
> +       if (new_enable != 0 && new_enable != 1)

Make unsigned just "if (new_enable > 1)".

> +               return -EINVAL;
> +
> +       /* NOP for same value */
> +       if (new_enable == atomic_read(&ov_enable))
> +               return count;
> +
> +       /* if we've disabled it, no going back */
> +       if (atomic_read(&ov_enable) == 0)
> +               return -EPERM;
> +
> +       atomic_set(&ov_enable, new_enable);
> +       return count;
> +}
> +
> +/* just a single char + '\n' + '\0' */
> +static BIN_ATTR_RW(enable, 3);
> +
>  /**
>   * of_overlay_create() - Create and apply an overlay
>   * @tree:      Device node containing all the overlays
> @@ -360,6 +418,10 @@ int of_overlay_create(struct device_node *tree)
>         struct of_overlay *ov;
>         int err, id;
>
> +       /* administratively disabled */
> +       if (!atomic_read(&ov_enable))
> +               return -EPERM;
> +
>         /* allocate the overlay structure */
>         ov = kzalloc(sizeof(*ov), GFP_KERNEL);
>         if (ov == NULL)
> @@ -596,5 +658,7 @@ int of_overlay_init(void)
>         if (!ov_kset)
>                 return -ENOMEM;
>
> -       return 0;
> +       rc = sysfs_create_bin_file(&ov_kset->kobj, &bin_attr_enable);
> +       WARN(rc, "%s: error adding enable attribute\n", __func__);
> +       return rc;
>  }
> --
> 1.7.12
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
```

## Re: \[PATCH 5/5\] MAINTAINERS: Pantelis Antoniou device tree overlay maintainer

- From: Rob Herring \<hidden\>
- Date: 2015-03-25 05:31:52 
- Message: https://ratatoskr.run/linux-api/2015/03/4458694.md

```text
On Tue, Mar 17, 2015 at 3:30 PM, Pantelis Antoniou
[ref] wrote:
> Add me as the device tree overlays maintainer.
>
> Signed-off-by: Pantelis Antoniou <redacted>

Applied. Thanks.

Rob

> ---
>  MAINTAINERS | 9 +++++++++
>  1 file changed, 9 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 0e1abe8..24aa339 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -7187,6 +7187,15 @@ F:       Documentation/devicetree/
>  F:     arch/*/boot/dts/
>  F:     include/dt-bindings/
>
> +OPEN FIRMWARE AND DEVICE TREE OVERLAYS
> +M:     Pantelis Antoniou [ref]
> +L:     devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> +S:     Maintained
> +F:     Documentation/devicetree/dynamic-resolution-notes.txt
> +F:     Documentation/devicetree/overlay-notes.txt
> +F:     drivers/of/overlay.c
> +F:     drivers/of/resolver.c
> +
>  OPENRISC ARCHITECTURE
>  M:     Jonas Bonn [ref]
>  W:     http://openrisc.net
> --
> 1.7.12
>
```

## Re: \[PATCH 1/5\] of: unittest: overlay: Keep track of created overlays

- From: Pantelis Antoniou \<hidden\>
- Date: 2015-03-27 18:24:47 
- Message: https://ratatoskr.run/linux-api/2015/03/4460943.md

```text
Hi Rob,

> On Mar 24, 2015, at 21:53 , Rob Herring [ref] wrote:
> 
> On Tue, Mar 17, 2015 at 3:30 PM, Pantelis Antoniou
> [ref] wrote:
>> During the course of the overlay selftests some of them remain
>> applied. While this does not pose a real problem, make sure you track
>> them and destroy them at the end of the test.
> 
> This is going to need to be rebased on my tree as there has been some
> selftest->unitest renaming.
> 

Ok, will do so first thing next week.

> Rob
> 

Regards

— Pantelis

>> 
>> Signed-off-by: Pantelis Antoniou <redacted>
>> ---
>> drivers/of/unittest.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 62 insertions(+)
>> 
>> diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
>> index 4e60682..c711534 100644
>> --- a/drivers/of/unittest.c
>> +++ b/drivers/of/unittest.c
>> @@ -23,6 +23,8 @@
>> #include <linux/i2c.h>
>> #include <linux/i2c-mux.h>
>> 
>> +#include <linux/bitops.h>
>> +
>> #include "of_private.h"
>> 
>> static struct selftest_results {
>> @@ -1115,6 +1117,59 @@ static const char *overlay_path(int nr)
>> 
>> static const char *bus_path = "/testcase-data/overlay-node/test-bus";
>> 
>> +/* it is guaranteed that overlay ids are assigned in sequence */
>> +#define MAX_SELFTEST_OVERLAYS  256
>> +static unsigned long overlay_id_bits[BITS_TO_LONGS(MAX_SELFTEST_OVERLAYS)];
>> +static int overlay_first_id = -1;
>> +
>> +static void of_selftest_track_overlay(int id)
>> +{
>> +       if (overlay_first_id < 0)
>> +               overlay_first_id = id;
>> +       id -= overlay_first_id;
>> +
>> +       /* we shouldn't need that many */
>> +       BUG_ON(id >= MAX_SELFTEST_OVERLAYS);
>> +       overlay_id_bits[BIT_WORD(id)] |= BIT_MASK(id);
>> +}
>> +
>> +static void of_selftest_untrack_overlay(int id)
>> +{
>> +       if (overlay_first_id < 0)
>> +               return;
>> +       id -= overlay_first_id;
>> +       BUG_ON(id >= MAX_SELFTEST_OVERLAYS);
>> +       overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);
>> +}
>> +
>> +static void of_selftest_destroy_tracked_overlays(void)
>> +{
>> +       int id, ret, defers;
>> +
>> +       if (overlay_first_id < 0)
>> +               return;
>> +
>> +       /* try until no defers */
>> +       do {
>> +               defers = 0;
>> +               /* remove in reverse order */
>> +               for (id = MAX_SELFTEST_OVERLAYS - 1; id >= 0; id--) {
>> +                       if (!(overlay_id_bits[BIT_WORD(id)] & BIT_MASK(id)))
>> +                               continue;
>> +
>> +                       ret = of_overlay_destroy(id + overlay_first_id);
>> +                       if (ret != 0) {
>> +                               defers++;
>> +                               pr_warn("%s: overlay destroy failed for #%d\n",
>> +                                       __func__, id + overlay_first_id);
>> +                               continue;
>> +                       }
>> +
>> +                       overlay_id_bits[BIT_WORD(id)] &= ~BIT_MASK(id);
>> +               }
>> +       } while (defers > 0);
>> +}
>> +
>> static int of_selftest_apply_overlay(int selftest_nr, int overlay_nr,
>>                int *overlay_id)
>> {
>> @@ -1136,6 +1191,7 @@ static int of_selftest_apply_overlay(int selftest_nr, int overlay_nr,
>>                goto out;
>>        }
>>        id = ret;
>> +       of_selftest_track_overlay(id);
>> 
>>        ret = 0;
>> 
>> @@ -1349,6 +1405,7 @@ static void of_selftest_overlay_6(void)
>>                        return;
>>                }
>>                ov_id[i] = ret;
>> +               of_selftest_track_overlay(ov_id[i]);
>>        }
>> 
>>        for (i = 0; i < 2; i++) {
>> @@ -1373,6 +1430,7 @@ static void of_selftest_overlay_6(void)
>>                                                PDEV_OVERLAY));
>>                        return;
>>                }
>> +               of_selftest_untrack_overlay(ov_id[i]);
>>        }
>> 
>>        for (i = 0; i < 2; i++) {
>> @@ -1417,6 +1475,7 @@ static void of_selftest_overlay_8(void)
>>                        return;
>>                }
>>                ov_id[i] = ret;
>> +               of_selftest_track_overlay(ov_id[i]);
>>        }
>> 
>>        /* now try to remove first overlay (it should fail) */
>> @@ -1439,6 +1498,7 @@ static void of_selftest_overlay_8(void)
>>                                                PDEV_OVERLAY));
>>                        return;
>>                }
>> +               of_selftest_untrack_overlay(ov_id[i]);
>>        }
>> 
>>        selftest(1, "overlay test %d passed\n", 8);
>> @@ -1861,6 +1921,8 @@ static void __init of_selftest_overlay(void)
>>        of_selftest_overlay_i2c_cleanup();
>> #endif
>> 
>> +       of_selftest_destroy_tracked_overlays();
>> +
>> out:
>>        of_node_put(bus_np);
>> }
>> --
>> 1.7.12
```

## Re: \[PATCH 3/5\] of: overlay: Master enable switch

- From: Pantelis Antoniou \<hidden\>
- Date: 2015-03-27 18:25:56 
- Message: https://ratatoskr.run/linux-api/2015/03/4460944.md

```text
Hi Rob,

> On Mar 24, 2015, at 22:25 , Rob Herring [ref] wrote:
> 
> On Tue, Mar 17, 2015 at 3:30 PM, Pantelis Antoniou
> [ref] wrote:
>> Implement a throw once master enable switch to protect against any
>> further overlay applications if the administrator desires so.
> 
> sysfs documentation?
> 

OK, coming up.

>> Signed-off-by: Pantelis Antoniou <redacted>
>> ---
>> drivers/of/overlay.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++-
>> 1 file changed, 65 insertions(+), 1 deletion(-)
>> 
>> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
>> index f17f5ef..6688797 100644
>> --- a/drivers/of/overlay.c
>> +++ b/drivers/of/overlay.c
>> @@ -21,6 +21,7 @@
>> #include <linux/err.h>
>> #include <linux/idr.h>
>> #include <linux/sysfs.h>
>> +#include <linux/atomic.h>
>> 
>> #include "of_private.h"
>> 
>> @@ -55,6 +56,9 @@ struct of_overlay {
>>        struct kobject kobj;
>> };
>> 
>> +/* master enable switch; once set to 0 can't be re-enabled */
>> +static atomic_t ov_enable = ATOMIC_INIT(1);
>> +
>> static int of_overlay_apply_one(struct of_overlay *ov,
>>                struct device_node *target, const struct device_node *overlay);
>> 
>> @@ -345,6 +349,60 @@ static struct kobj_type of_overlay_ktype = {
>> 
>> static struct kset *ov_kset;
>> 
>> +static ssize_t enable_read(struct file *filp, struct kobject *kobj,
>> +               struct bin_attribute *bin_attr, char *buf,
>> +               loff_t offset, size_t count)
>> +{
>> +       char tbuf[3];
>> +
>> +       if (offset < 0)
>> +               return -EINVAL;
>> +
>> +       if (offset >= sizeof(tbuf))
>> +               return 0;
>> +
>> +       if (count > sizeof(tbuf) - offset)
>> +               count = sizeof(tbuf) - offset;
>> +
>> +       /* fill in temp */
>> +       tbuf[0] = '0' + atomic_read(&ov_enable);
>> +       tbuf[1] = '\n';
>> +       tbuf[2] = '\0';
>> +
>> +       /* copy to buffer */
>> +       memcpy(buf, tbuf + offset, count);
>> +
>> +       return count;
>> +}
>> +
>> +static ssize_t enable_write(struct file *filp, struct kobject *kobj,
>> +               struct bin_attribute *bin_attr, char *buf,
>> +               loff_t off, size_t count)
>> +{
>> +       int new_enable;
>> +
>> +       if (off != 0 || (buf[0] != '0' && buf[1] != '1'))
> 
> Is buf[1] correct here?
> 

Nope.

>> +               return -EINVAL;
>> +
>> +       new_enable = buf[0] - '0';
>> +       if (new_enable != 0 && new_enable != 1)
> 
> Make unsigned just "if (new_enable > 1)”.
> 

OK.

>> +               return -EINVAL;
>> +
>> +       /* NOP for same value */
>> +       if (new_enable == atomic_read(&ov_enable))
>> +               return count;
>> +
>> +       /* if we've disabled it, no going back */
>> +       if (atomic_read(&ov_enable) == 0)
>> +               return -EPERM;
>> +
>> +       atomic_set(&ov_enable, new_enable);
>> +       return count;
>> +}
>> +
>> +/* just a single char + '\n' + '\0' */
>> +static BIN_ATTR_RW(enable, 3);
>> +
>> /**
>>  * of_overlay_create() - Create and apply an overlay
>>  * @tree:      Device node containing all the overlays
>> @@ -360,6 +418,10 @@ int of_overlay_create(struct device_node *tree)
>>        struct of_overlay *ov;
>>        int err, id;
>> 
>> +       /* administratively disabled */
>> +       if (!atomic_read(&ov_enable))
>> +               return -EPERM;
>> +
>>        /* allocate the overlay structure */
>>        ov = kzalloc(sizeof(*ov), GFP_KERNEL);
>>        if (ov == NULL)
>> @@ -596,5 +658,7 @@ int of_overlay_init(void)
>>        if (!ov_kset)
>>                return -ENOMEM;
>> 
>> -       return 0;
>> +       rc = sysfs_create_bin_file(&ov_kset->kobj, &bin_attr_enable);
>> +       WARN(rc, "%s: error adding enable attribute\n", __func__);
>> +       return rc;
>> }
>> --
>> 1.7.12

Regards

— Pantelis
```
