2 * proc_devtree.c - handles /proc/device-tree
4 * Copyright 1997 Paul Mackerras
6 #include <linux/errno.h>
7 #include <linux/sched.h>
8 #include <linux/proc_fs.h>
9 #include <linux/stat.h>
10 #include <linux/string.h>
12 #include <asm/uaccess.h>
14 static struct proc_dir_entry
*proc_device_tree
;
17 * Supply data on a read from /proc/device-tree/node/property.
19 static int property_read_proc(char *page
, char **start
, off_t off
,
20 int count
, int *eof
, void *data
)
22 struct property
*pp
= data
;
25 if (off
>= pp
->length
) {
34 memcpy(page
, pp
->value
+ off
, n
);
40 * For a node with a name like "gc@10", we make symlinks called "gc"
44 static int devtree_readlink(struct dentry
*, char *, int);
45 static struct dentry
*devtree_follow_link(struct dentry
*, struct dentry
*, unsigned int);
47 struct inode_operations devtree_symlink_inode_operations
= {
48 NULL
, /* no file-operations */
58 devtree_readlink
, /* readlink */
59 devtree_follow_link
, /* follow_link */
64 NULL
, /* permission */
68 static struct dentry
*devtree_follow_link(struct dentry
*dentry
,
72 struct inode
*inode
= dentry
->d_inode
;
73 struct proc_dir_entry
* de
;
76 de
= (struct proc_dir_entry
*) inode
->u
.generic_ip
;
77 link
= (char *) de
->data
;
78 return lookup_dentry(link
, base
, follow
);
81 static int devtree_readlink(struct dentry
*dentry
, char *buffer
, int buflen
)
83 struct inode
*inode
= dentry
->d_inode
;
84 struct proc_dir_entry
* de
;
88 de
= (struct proc_dir_entry
*) inode
->u
.generic_ip
;
89 link
= (char *) de
->data
;
90 linklen
= strlen(link
);
93 if (copy_to_user(buffer
, link
, linklen
))
99 * Process a node, adding entries for its children and its properties.
101 static void add_node(struct device_node
*np
, struct proc_dir_entry
*de
)
104 struct proc_dir_entry
*ent
;
105 struct device_node
*child
, *sib
;
108 struct proc_dir_entry
*list
, **lastp
, *al
;
111 for (pp
= np
->properties
; pp
!= 0; pp
= pp
->next
) {
113 * Unfortunately proc_register puts each new entry
114 * at the beginning of the list. So we rearrange them.
116 ent
= kmalloc(sizeof(struct proc_dir_entry
), GFP_KERNEL
);
119 memset(ent
, 0, sizeof(struct proc_dir_entry
));
120 ent
->name
= pp
->name
;
121 ent
->namelen
= strlen(pp
->name
);
122 ent
->mode
= S_IFREG
| S_IRUGO
;
125 ent
->read_proc
= property_read_proc
;
126 ent
->size
= pp
->length
;
127 proc_register(de
, ent
);
131 for (child
= np
->child
; child
!= 0; child
= child
->sibling
) {
132 p
= strrchr(child
->full_name
, '/');
134 p
= child
->full_name
;
137 /* chop off '@0' if the name ends with that */
139 if (l
> 2 && p
[l
-2] == '@' && p
[l
-1] == '0')
141 ent
= kmalloc(sizeof(struct proc_dir_entry
), GFP_KERNEL
);
144 memset(ent
, 0, sizeof(struct proc_dir_entry
));
147 ent
->mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
149 proc_register(de
, ent
);
152 add_node(child
, ent
);
155 * If we left the address part on the name, consider
156 * adding symlinks from the name and address parts.
158 if (p
[l
] != 0 || (at
= strchr(p
, '@')) == 0)
162 * If this is the first node with a given name property,
163 * add a symlink with the name property as its name.
165 for (sib
= np
->child
; sib
!= child
; sib
= sib
->sibling
)
166 if (strcmp(sib
->name
, child
->name
) == 0)
168 if (sib
== child
&& strncmp(p
, child
->name
, l
) != 0) {
169 al
= kmalloc(sizeof(struct proc_dir_entry
),
173 memset(al
, 0, sizeof(struct proc_dir_entry
));
174 al
->name
= child
->name
;
175 al
->namelen
= strlen(child
->name
);
176 al
->mode
= S_IFLNK
| S_IRUGO
| S_IXUGO
;
178 al
->data
= (void *) ent
->name
;
179 al
->ops
= &devtree_symlink_inode_operations
;
180 proc_register(de
, al
);
186 * Add another directory with the @address part as its name.
188 al
= kmalloc(sizeof(struct proc_dir_entry
), GFP_KERNEL
);
191 memset(al
, 0, sizeof(struct proc_dir_entry
));
193 al
->namelen
= strlen(at
);
194 al
->mode
= S_IFLNK
| S_IRUGO
| S_IXUGO
;
196 al
->data
= (void *) ent
->name
;
197 al
->ops
= &devtree_symlink_inode_operations
;
198 proc_register(de
, al
);
207 * Called on initialization to set up the /proc/device-tree subtree
209 void proc_device_tree_init(void)
211 struct device_node
*root
;
214 proc_device_tree
= create_proc_entry("device-tree", S_IFDIR
, 0);
215 if (proc_device_tree
== 0)
217 root
= find_path_device("/");
219 printk(KERN_ERR
"/proc/device-tree: can't find root\n");
222 add_node(root
, proc_device_tree
);