LCOV - code coverage report
Current view: top level - drivers/of - kobj.c (source / functions) Hit Total Coverage
Test: Real Lines: 33 59 55.9 %
Date: 2020-10-17 15:46:16 Functions: 0 9 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       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                 :          0 :         return node && node->kobj.state_initialized;
      11                 :            : }
      12                 :            : 
      13                 :            : /* true when node is attached (i.e. present on sysfs) */
      14                 :          0 : int of_node_is_attached(struct device_node *node)
      15                 :            : {
      16                 :          3 :         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                 :          3 : 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                 :          3 :         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                 :          3 : 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                 :          3 :         while (i < 16 && (kn = sysfs_get_dirent(kobj->sd, name))) {
      48                 :            :                 sysfs_put(kn);
      49                 :          0 :                 if (name != orig_name)
      50                 :          0 :                         kfree(name);
      51                 :          0 :                 name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i);
      52                 :            :         }
      53                 :            : 
      54                 :          3 :         if (name == orig_name) {
      55                 :          3 :                 name = kstrdup(orig_name, GFP_KERNEL);
      56                 :            :         } else {
      57                 :          0 :                 pr_warn("Duplicate name in %s, renamed to \"%s\"\n",
      58                 :            :                         kobject_name(kobj), name);
      59                 :            :         }
      60                 :          3 :         return name;
      61                 :            : }
      62                 :            : 
      63                 :          3 : int __of_add_property_sysfs(struct device_node *np, struct property *pp)
      64                 :            : {
      65                 :            :         int rc;
      66                 :            : 
      67                 :            :         /* Important: Don't leak passwords */
      68                 :          3 :         bool secure = strncmp(pp->name, "security-", 9) == 0;
      69                 :            : 
      70                 :            :         if (!IS_ENABLED(CONFIG_SYSFS))
      71                 :            :                 return 0;
      72                 :            : 
      73                 :          3 :         if (!of_kset || !of_node_is_attached(np))
      74                 :            :                 return 0;
      75                 :            : 
      76                 :            :         sysfs_bin_attr_init(&pp->attr);
      77                 :          3 :         pp->attr.attr.name = safe_name(&np->kobj, pp->name);
      78                 :          3 :         pp->attr.attr.mode = secure ? 0400 : 0444;
      79                 :          3 :         pp->attr.size = secure ? 0 : pp->length;
      80                 :          3 :         pp->attr.read = of_node_property_read;
      81                 :            : 
      82                 :          3 :         rc = sysfs_create_bin_file(&np->kobj, &pp->attr);
      83                 :          3 :         WARN(rc, "error adding attribute %s to node %pOF\n", pp->name, np);
      84                 :          3 :         return rc;
      85                 :            : }
      86                 :            : 
      87                 :          0 : void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop)
      88                 :            : {
      89                 :            :         if (!IS_ENABLED(CONFIG_SYSFS))
      90                 :          0 :                 return;
      91                 :            : 
      92                 :          0 :         sysfs_remove_bin_file(&np->kobj, &prop->attr);
      93                 :          0 :         kfree(prop->attr.attr.name);
      94                 :            : }
      95                 :            : 
      96                 :          0 : 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                 :          0 :         if (of_kset && of_node_is_attached(np))
     100                 :            :                 __of_sysfs_remove_bin_file(np, prop);
     101                 :          0 : }
     102                 :            : 
     103                 :          0 : 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                 :          0 :         if (!of_kset)
     108                 :          0 :                 return;
     109                 :            : 
     110                 :          0 :         if (oldprop)
     111                 :            :                 __of_sysfs_remove_bin_file(np, oldprop);
     112                 :          0 :         __of_add_property_sysfs(np, newprop);
     113                 :            : }
     114                 :            : 
     115                 :          3 : 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                 :          3 :         if (!of_kset)
     123                 :            :                 return 0;
     124                 :            : 
     125                 :          3 :         np->kobj.kset = of_kset;
     126                 :          3 :         if (!np->parent) {
     127                 :            :                 /* Nodes without parents are new top level trees */
     128                 :          3 :                 name = safe_name(&of_kset->kobj, "base");
     129                 :            :                 parent = NULL;
     130                 :            :         } else {
     131                 :          3 :                 name = safe_name(&np->parent->kobj, kbasename(np->full_name));
     132                 :          3 :                 parent = &np->parent->kobj;
     133                 :            :         }
     134                 :          3 :         if (!name)
     135                 :            :                 return -ENOMEM;
     136                 :            : 
     137                 :          3 :         rc = kobject_add(&np->kobj, parent, "%s", name);
     138                 :          3 :         kfree(name);
     139                 :          3 :         if (rc)
     140                 :            :                 return rc;
     141                 :            : 
     142                 :          3 :         for_each_property_of_node(np, pp)
     143                 :          3 :                 __of_add_property_sysfs(np, pp);
     144                 :            : 
     145                 :          3 :         of_node_get(np);
     146                 :          3 :         return 0;
     147                 :            : }
     148                 :            : 
     149                 :          0 : void __of_detach_node_sysfs(struct device_node *np)
     150                 :            : {
     151                 :            :         struct property *pp;
     152                 :            : 
     153                 :          0 :         BUG_ON(!of_node_is_initialized(np));
     154                 :          0 :         if (!of_kset)
     155                 :          0 :                 return;
     156                 :            : 
     157                 :            :         /* only remove properties if on sysfs */
     158                 :          0 :         if (of_node_is_attached(np)) {
     159                 :          0 :                 for_each_property_of_node(np, pp)
     160                 :            :                         __of_sysfs_remove_bin_file(np, pp);
     161                 :          0 :                 kobject_del(&np->kobj);
     162                 :            :         }
     163                 :            : 
     164                 :          0 :         of_node_put(np);
     165                 :            : }
    

Generated by: LCOV version 1.14