root/drivers/of/kobj.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. of_node_is_initialized
  2. of_node_is_attached
  3. of_node_release
  4. of_node_property_read
  5. safe_name
  6. __of_add_property_sysfs
  7. __of_sysfs_remove_bin_file
  8. __of_remove_property_sysfs
  9. __of_update_property_sysfs
  10. __of_attach_node_sysfs
  11. __of_detach_node_sysfs

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/of.h>
   3 #include <linux/slab.h>
   4 
   5 #include "of_private.h"
   6 
   7 /* true when node is initialized */
   8 static int of_node_is_initialized(struct device_node *node)
   9 {
  10         return node && node->kobj.state_initialized;
  11 }
  12 
  13 /* true when node is attached (i.e. present on sysfs) */
  14 int of_node_is_attached(struct device_node *node)
  15 {
  16         return node && node->kobj.state_in_sysfs;
  17 }
  18 
  19 
  20 #ifndef CONFIG_OF_DYNAMIC
  21 static void of_node_release(struct kobject *kobj)
  22 {
  23         /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */
  24 }
  25 #endif /* CONFIG_OF_DYNAMIC */
  26 
  27 struct kobj_type of_node_ktype = {
  28         .release = of_node_release,
  29 };
  30 
  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)
  34 {
  35         struct property *pp = container_of(bin_attr, struct property, attr);
  36         return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length);
  37 }
  38 
  39 /* always return newly allocated name, caller must free after use */
  40 static const char *safe_name(struct kobject *kobj, const char *orig_name)
  41 {
  42         const char *name = orig_name;
  43         struct kernfs_node *kn;
  44         int i = 0;
  45 
  46         /* don't be a hero. After 16 tries give up */
  47         while (i < 16 && (kn = sysfs_get_dirent(kobj->sd, name))) {
  48                 sysfs_put(kn);
  49                 if (name != orig_name)
  50                         kfree(name);
  51                 name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i);
  52         }
  53 
  54         if (name == orig_name) {
  55                 name = kstrdup(orig_name, GFP_KERNEL);
  56         } else {
  57                 pr_warn("Duplicate name in %s, renamed to \"%s\"\n",
  58                         kobject_name(kobj), name);
  59         }
  60         return name;
  61 }
  62 
  63 int __of_add_property_sysfs(struct device_node *np, struct property *pp)
  64 {
  65         int rc;
  66 
  67         /* Important: Don't leak passwords */
  68         bool secure = strncmp(pp->name, "security-", 9) == 0;
  69 
  70         if (!IS_ENABLED(CONFIG_SYSFS))
  71                 return 0;
  72 
  73         if (!of_kset || !of_node_is_attached(np))
  74                 return 0;
  75 
  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;
  81 
  82         rc = sysfs_create_bin_file(&np->kobj, &pp->attr);
  83         WARN(rc, "error adding attribute %s to node %pOF\n", pp->name, np);
  84         return rc;
  85 }
  86 
  87 void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop)
  88 {
  89         if (!IS_ENABLED(CONFIG_SYSFS))
  90                 return;
  91 
  92         sysfs_remove_bin_file(&np->kobj, &prop->attr);
  93         kfree(prop->attr.attr.name);
  94 }
  95 
  96 void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
  97 {
  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);
 101 }
 102 
 103 void __of_update_property_sysfs(struct device_node *np, struct property *newprop,
 104                 struct property *oldprop)
 105 {
 106         /* At early boot, bail out and defer setup to of_init() */
 107         if (!of_kset)
 108                 return;
 109 
 110         if (oldprop)
 111                 __of_sysfs_remove_bin_file(np, oldprop);
 112         __of_add_property_sysfs(np, newprop);
 113 }
 114 
 115 int __of_attach_node_sysfs(struct device_node *np)
 116 {
 117         const char *name;
 118         struct kobject *parent;
 119         struct property *pp;
 120         int rc;
 121 
 122         if (!of_kset)
 123                 return 0;
 124 
 125         np->kobj.kset = of_kset;
 126         if (!np->parent) {
 127                 /* Nodes without parents are new top level trees */
 128                 name = safe_name(&of_kset->kobj, "base");
 129                 parent = NULL;
 130         } else {
 131                 name = safe_name(&np->parent->kobj, kbasename(np->full_name));
 132                 parent = &np->parent->kobj;
 133         }
 134         if (!name)
 135                 return -ENOMEM;
 136 
 137         of_node_get(np);
 138 
 139         rc = kobject_add(&np->kobj, parent, "%s", name);
 140         kfree(name);
 141         if (rc)
 142                 return rc;
 143 
 144         for_each_property_of_node(np, pp)
 145                 __of_add_property_sysfs(np, pp);
 146 
 147         return 0;
 148 }
 149 
 150 void __of_detach_node_sysfs(struct device_node *np)
 151 {
 152         struct property *pp;
 153 
 154         BUG_ON(!of_node_is_initialized(np));
 155         if (!of_kset)
 156                 return;
 157 
 158         /* only remove properties if on sysfs */
 159         if (of_node_is_attached(np)) {
 160                 for_each_property_of_node(np, pp)
 161                         __of_sysfs_remove_bin_file(np, pp);
 162                 kobject_del(&np->kobj);
 163         }
 164 
 165         of_node_put(np);
 166 }

/* [<][>][^][v][top][bottom][index][help] */