1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/slab.h>
5 #include "of_private.h"
7 /* true when node is initialized */
8 static int of_node_is_initialized(struct device_node
*node
)
10 return node
&& node
->kobj
.state_initialized
;
13 /* true when node is attached (i.e. present on sysfs) */
14 int of_node_is_attached(struct device_node
*node
)
16 return node
&& node
->kobj
.state_in_sysfs
;
20 #ifndef CONFIG_OF_DYNAMIC
21 static void of_node_release(struct kobject
*kobj
)
23 /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */
25 #endif /* CONFIG_OF_DYNAMIC */
27 struct kobj_type of_node_ktype
= {
28 .release
= of_node_release
,
31 static ssize_t
of_node_property_read(struct file
*filp
, struct kobject
*kobj
,
32 struct bin_attribute
*bin_attr
, char *buf
,
33 loff_t offset
, size_t count
)
35 struct property
*pp
= container_of(bin_attr
, struct property
, attr
);
36 return memory_read_from_buffer(buf
, count
, &offset
, pp
->value
, pp
->length
);
39 /* always return newly allocated name, caller must free after use */
40 static const char *safe_name(struct kobject
*kobj
, const char *orig_name
)
42 const char *name
= orig_name
;
43 struct kernfs_node
*kn
;
46 /* don't be a hero. After 16 tries give up */
47 while (i
< 16 && (kn
= sysfs_get_dirent(kobj
->sd
, name
))) {
49 if (name
!= orig_name
)
51 name
= kasprintf(GFP_KERNEL
, "%s#%i", orig_name
, ++i
);
54 if (name
== orig_name
) {
55 name
= kstrdup(orig_name
, GFP_KERNEL
);
57 pr_warn("Duplicate name in %s, renamed to \"%s\"\n",
58 kobject_name(kobj
), name
);
63 int __of_add_property_sysfs(struct device_node
*np
, struct property
*pp
)
67 /* Important: Don't leak passwords */
68 bool secure
= strncmp(pp
->name
, "security-", 9) == 0;
70 if (!IS_ENABLED(CONFIG_SYSFS
))
73 if (!of_kset
|| !of_node_is_attached(np
))
76 sysfs_bin_attr_init(&pp
->attr
);
77 pp
->attr
.attr
.name
= safe_name(&np
->kobj
, pp
->name
);
78 pp
->attr
.attr
.mode
= secure
? 0400 : 0444;
79 pp
->attr
.size
= secure
? 0 : pp
->length
;
80 pp
->attr
.read
= of_node_property_read
;
82 rc
= sysfs_create_bin_file(&np
->kobj
, &pp
->attr
);
83 WARN(rc
, "error adding attribute %s to node %pOF\n", pp
->name
, np
);
87 void __of_sysfs_remove_bin_file(struct device_node
*np
, struct property
*prop
)
89 if (!IS_ENABLED(CONFIG_SYSFS
))
92 sysfs_remove_bin_file(&np
->kobj
, &prop
->attr
);
93 kfree(prop
->attr
.attr
.name
);
96 void __of_remove_property_sysfs(struct device_node
*np
, struct property
*prop
)
98 /* at early boot, bail here and defer setup to of_init() */
99 if (of_kset
&& of_node_is_attached(np
))
100 __of_sysfs_remove_bin_file(np
, prop
);
103 void __of_update_property_sysfs(struct device_node
*np
, struct property
*newprop
,
104 struct property
*oldprop
)
106 /* At early boot, bail out and defer setup to of_init() */
111 __of_sysfs_remove_bin_file(np
, oldprop
);
112 __of_add_property_sysfs(np
, newprop
);
115 int __of_attach_node_sysfs(struct device_node
*np
)
118 struct kobject
*parent
;
125 np
->kobj
.kset
= of_kset
;
127 /* Nodes without parents are new top level trees */
128 name
= safe_name(&of_kset
->kobj
, "base");
131 name
= safe_name(&np
->parent
->kobj
, kbasename(np
->full_name
));
132 parent
= &np
->parent
->kobj
;
136 rc
= kobject_add(&np
->kobj
, parent
, "%s", name
);
141 for_each_property_of_node(np
, pp
)
142 __of_add_property_sysfs(np
, pp
);
147 void __of_detach_node_sysfs(struct device_node
*np
)
151 BUG_ON(!of_node_is_initialized(np
));
155 /* only remove properties if on sysfs */
156 if (of_node_is_attached(np
)) {
157 for_each_property_of_node(np
, pp
)
158 __of_sysfs_remove_bin_file(np
, pp
);
159 kobject_del(&np
->kobj
);
162 /* finally remove the kobj_init ref */