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 */
65 NULL
, /* permission */
70 static struct dentry
*devtree_follow_link(struct dentry
*dentry
,
74 struct inode
*inode
= dentry
->d_inode
;
75 struct proc_dir_entry
* de
;
78 de
= (struct proc_dir_entry
*) inode
->u
.generic_ip
;
79 link
= (char *) de
->data
;
80 return lookup_dentry(link
, base
, follow
);
83 static int devtree_readlink(struct dentry
*dentry
, char *buffer
, int buflen
)
85 struct inode
*inode
= dentry
->d_inode
;
86 struct proc_dir_entry
* de
;
90 de
= (struct proc_dir_entry
*) inode
->u
.generic_ip
;
91 link
= (char *) de
->data
;
92 linklen
= strlen(link
);
95 if (copy_to_user(buffer
, link
, linklen
))
101 * Process a node, adding entries for its children and its properties.
103 static void add_node(struct device_node
*np
, struct proc_dir_entry
*de
)
106 struct proc_dir_entry
*ent
;
107 struct device_node
*child
, *sib
;
110 struct proc_dir_entry
*list
, **lastp
, *al
;
113 for (pp
= np
->properties
; pp
!= 0; pp
= pp
->next
) {
115 * Unfortunately proc_register puts each new entry
116 * at the beginning of the list. So we rearrange them.
118 ent
= kmalloc(sizeof(struct proc_dir_entry
), GFP_KERNEL
);
121 memset(ent
, 0, sizeof(struct proc_dir_entry
));
122 ent
->name
= pp
->name
;
123 ent
->namelen
= strlen(pp
->name
);
124 ent
->mode
= S_IFREG
| S_IRUGO
;
127 ent
->read_proc
= property_read_proc
;
128 ent
->size
= pp
->length
;
129 proc_register(de
, ent
);
133 for (child
= np
->child
; child
!= 0; child
= child
->sibling
) {
134 p
= strrchr(child
->full_name
, '/');
136 p
= child
->full_name
;
139 /* chop off '@0' if the name ends with that */
141 if (l
> 2 && p
[l
-2] == '@' && p
[l
-1] == '0')
143 ent
= kmalloc(sizeof(struct proc_dir_entry
), GFP_KERNEL
);
146 memset(ent
, 0, sizeof(struct proc_dir_entry
));
149 ent
->mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
151 proc_register(de
, ent
);
154 add_node(child
, ent
);
157 * If we left the address part on the name, consider
158 * adding symlinks from the name and address parts.
160 if (p
[l
] != 0 || (at
= strchr(p
, '@')) == 0)
164 * If this is the first node with a given name property,
165 * add a symlink with the name property as its name.
167 for (sib
= np
->child
; sib
!= child
; sib
= sib
->sibling
)
168 if (sib
->name
&& strcmp(sib
->name
, child
->name
) == 0)
170 if (sib
== child
&& strncmp(p
, child
->name
, l
) != 0) {
171 al
= kmalloc(sizeof(struct proc_dir_entry
),
175 memset(al
, 0, sizeof(struct proc_dir_entry
));
176 al
->name
= child
->name
;
177 al
->namelen
= strlen(child
->name
);
178 al
->mode
= S_IFLNK
| S_IRUGO
| S_IXUGO
;
180 al
->data
= (void *) ent
->name
;
181 al
->ops
= &devtree_symlink_inode_operations
;
182 proc_register(de
, al
);
188 * Add another directory with the @address part as its name.
190 al
= kmalloc(sizeof(struct proc_dir_entry
), GFP_KERNEL
);
193 memset(al
, 0, sizeof(struct proc_dir_entry
));
195 al
->namelen
= strlen(at
);
196 al
->mode
= S_IFLNK
| S_IRUGO
| S_IXUGO
;
198 al
->data
= (void *) ent
->name
;
199 al
->ops
= &devtree_symlink_inode_operations
;
200 proc_register(de
, al
);
209 * Called on initialization to set up the /proc/device-tree subtree
211 void proc_device_tree_init(void)
213 struct device_node
*root
;
216 proc_device_tree
= create_proc_entry("device-tree", S_IFDIR
, 0);
217 if (proc_device_tree
== 0)
219 root
= find_path_device("/");
221 printk(KERN_ERR
"/proc/device-tree: can't find root\n");
224 add_node(root
, proc_device_tree
);