1 /* inode.c: /proc/openprom handling routines
3 * Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com)
4 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
7 #include <linux/module.h>
8 #include <linux/types.h>
9 #include <linux/string.h>
11 #include <linux/init.h>
12 #include <linux/slab.h>
13 #include <linux/seq_file.h>
14 #include <linux/magic.h>
16 #include <asm/openprom.h>
17 #include <asm/oplib.h>
19 #include <asm/uaccess.h>
21 static DEFINE_MUTEX(op_mutex
);
23 #define OPENPROM_ROOT_INO 0
31 struct device_node
*node
;
32 struct property
*prop
;
35 struct op_inode_info
{
36 struct inode vfs_inode
;
37 enum op_inode_type type
;
38 union op_inode_data u
;
41 static struct inode
*openprom_iget(struct super_block
*sb
, ino_t ino
);
43 static inline struct op_inode_info
*OP_I(struct inode
*inode
)
45 return container_of(inode
, struct op_inode_info
, vfs_inode
);
48 static int is_string(unsigned char *p
, int len
)
52 for (i
= 0; i
< len
; i
++) {
53 unsigned char val
= p
[i
];
56 (val
>= ' ' && val
<= '~'))
65 static int property_show(struct seq_file
*f
, void *v
)
67 struct property
*prop
= f
->private;
74 if (is_string(pval
, len
)) {
78 seq_printf(f
, "%s", (char *) pval
);
80 /* Skip over the NULL byte too. */
92 seq_printf(f
, "%02x.",
93 *(unsigned char *) pval
);
96 *(unsigned char *) pval
);
104 seq_printf(f
, "%08x.",
105 *(unsigned int *) pval
);
107 seq_printf(f
, "%08x",
108 *(unsigned int *) pval
);
118 static void *property_start(struct seq_file
*f
, loff_t
*pos
)
125 static void *property_next(struct seq_file
*f
, void *v
, loff_t
*pos
)
131 static void property_stop(struct seq_file
*f
, void *v
)
136 static const struct seq_operations property_op
= {
137 .start
= property_start
,
138 .next
= property_next
,
139 .stop
= property_stop
,
140 .show
= property_show
143 static int property_open(struct inode
*inode
, struct file
*file
)
145 struct op_inode_info
*oi
= OP_I(inode
);
148 BUG_ON(oi
->type
!= op_inode_prop
);
150 ret
= seq_open(file
, &property_op
);
152 struct seq_file
*m
= file
->private_data
;
153 m
->private = oi
->u
.prop
;
158 static const struct file_operations openpromfs_prop_ops
= {
159 .open
= property_open
,
162 .release
= seq_release
,
165 static int openpromfs_readdir(struct file
*, void *, filldir_t
);
167 static const struct file_operations openprom_operations
= {
168 .read
= generic_read_dir
,
169 .readdir
= openpromfs_readdir
,
172 static struct dentry
*openpromfs_lookup(struct inode
*, struct dentry
*, struct nameidata
*);
174 static const struct inode_operations openprom_inode_operations
= {
175 .lookup
= openpromfs_lookup
,
178 static struct dentry
*openpromfs_lookup(struct inode
*dir
, struct dentry
*dentry
, struct nameidata
*nd
)
180 struct op_inode_info
*ent_oi
, *oi
= OP_I(dir
);
181 struct device_node
*dp
, *child
;
182 struct property
*prop
;
183 enum op_inode_type ent_type
;
184 union op_inode_data ent_data
;
190 BUG_ON(oi
->type
!= op_inode_node
);
194 name
= dentry
->d_name
.name
;
195 len
= dentry
->d_name
.len
;
197 mutex_lock(&op_mutex
);
201 int n
= strlen(child
->path_component_name
);
204 !strncmp(child
->path_component_name
, name
, len
)) {
205 ent_type
= op_inode_node
;
206 ent_data
.node
= child
;
207 ino
= child
->unique_id
;
210 child
= child
->sibling
;
213 prop
= dp
->properties
;
215 int n
= strlen(prop
->name
);
217 if (len
== n
&& !strncmp(prop
->name
, name
, len
)) {
218 ent_type
= op_inode_prop
;
219 ent_data
.prop
= prop
;
220 ino
= prop
->unique_id
;
227 mutex_unlock(&op_mutex
);
228 return ERR_PTR(-ENOENT
);
231 inode
= openprom_iget(dir
->i_sb
, ino
);
232 mutex_unlock(&op_mutex
);
234 return ERR_CAST(inode
);
235 ent_oi
= OP_I(inode
);
236 ent_oi
->type
= ent_type
;
237 ent_oi
->u
= ent_data
;
241 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
242 inode
->i_op
= &openprom_inode_operations
;
243 inode
->i_fop
= &openprom_operations
;
247 if (!strcmp(dp
->name
, "options") && (len
== 17) &&
248 !strncmp (name
, "security-password", 17))
249 inode
->i_mode
= S_IFREG
| S_IRUSR
| S_IWUSR
;
251 inode
->i_mode
= S_IFREG
| S_IRUGO
;
252 inode
->i_fop
= &openpromfs_prop_ops
;
254 inode
->i_size
= ent_oi
->u
.prop
->length
;
261 d_add(dentry
, inode
);
265 static int openpromfs_readdir(struct file
* filp
, void * dirent
, filldir_t filldir
)
267 struct inode
*inode
= filp
->f_path
.dentry
->d_inode
;
268 struct op_inode_info
*oi
= OP_I(inode
);
269 struct device_node
*dp
= oi
->u
.node
;
270 struct device_node
*child
;
271 struct property
*prop
;
275 mutex_lock(&op_mutex
);
281 if (filldir(dirent
, ".", 1, i
, ino
, DT_DIR
) < 0)
287 if (filldir(dirent
, "..", 2, i
,
288 (dp
->parent
== NULL
?
290 dp
->parent
->unique_id
), DT_DIR
) < 0)
298 /* First, the children nodes as directories. */
301 child
= child
->sibling
;
306 child
->path_component_name
,
307 strlen(child
->path_component_name
),
308 filp
->f_pos
, child
->unique_id
, DT_DIR
) < 0)
312 child
= child
->sibling
;
315 /* Next, the properties as files. */
316 prop
= dp
->properties
;
322 if (filldir(dirent
, prop
->name
, strlen(prop
->name
),
323 filp
->f_pos
, prop
->unique_id
, DT_REG
) < 0)
331 mutex_unlock(&op_mutex
);
335 static struct kmem_cache
*op_inode_cachep
;
337 static struct inode
*openprom_alloc_inode(struct super_block
*sb
)
339 struct op_inode_info
*oi
;
341 oi
= kmem_cache_alloc(op_inode_cachep
, GFP_KERNEL
);
345 return &oi
->vfs_inode
;
348 static void openprom_destroy_inode(struct inode
*inode
)
350 kmem_cache_free(op_inode_cachep
, OP_I(inode
));
353 static struct inode
*openprom_iget(struct super_block
*sb
, ino_t ino
)
357 inode
= iget_locked(sb
, ino
);
359 return ERR_PTR(-ENOMEM
);
360 if (inode
->i_state
& I_NEW
) {
361 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
362 if (inode
->i_ino
== OPENPROM_ROOT_INO
) {
363 inode
->i_op
= &openprom_inode_operations
;
364 inode
->i_fop
= &openprom_operations
;
365 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
367 unlock_new_inode(inode
);
372 static int openprom_remount(struct super_block
*sb
, int *flags
, char *data
)
374 *flags
|= MS_NOATIME
;
378 static const struct super_operations openprom_sops
= {
379 .alloc_inode
= openprom_alloc_inode
,
380 .destroy_inode
= openprom_destroy_inode
,
381 .statfs
= simple_statfs
,
382 .remount_fs
= openprom_remount
,
385 static int openprom_fill_super(struct super_block
*s
, void *data
, int silent
)
387 struct inode
*root_inode
;
388 struct op_inode_info
*oi
;
391 s
->s_flags
|= MS_NOATIME
;
392 s
->s_blocksize
= 1024;
393 s
->s_blocksize_bits
= 10;
394 s
->s_magic
= OPENPROM_SUPER_MAGIC
;
395 s
->s_op
= &openprom_sops
;
397 root_inode
= openprom_iget(s
, OPENPROM_ROOT_INO
);
398 if (IS_ERR(root_inode
)) {
399 ret
= PTR_ERR(root_inode
);
403 oi
= OP_I(root_inode
);
404 oi
->type
= op_inode_node
;
405 oi
->u
.node
= of_find_node_by_path("/");
407 s
->s_root
= d_alloc_root(root_inode
);
409 goto out_no_root_dentry
;
416 printk("openprom_fill_super: get root inode failed\n");
420 static int openprom_get_sb(struct file_system_type
*fs_type
,
421 int flags
, const char *dev_name
, void *data
, struct vfsmount
*mnt
)
423 return get_sb_single(fs_type
, flags
, data
, openprom_fill_super
, mnt
);
426 static struct file_system_type openprom_fs_type
= {
427 .owner
= THIS_MODULE
,
428 .name
= "openpromfs",
429 .get_sb
= openprom_get_sb
,
430 .kill_sb
= kill_anon_super
,
433 static void op_inode_init_once(void *data
)
435 struct op_inode_info
*oi
= (struct op_inode_info
*) data
;
437 inode_init_once(&oi
->vfs_inode
);
440 static int __init
init_openprom_fs(void)
444 op_inode_cachep
= kmem_cache_create("op_inode_cache",
445 sizeof(struct op_inode_info
),
447 (SLAB_RECLAIM_ACCOUNT
|
450 if (!op_inode_cachep
)
453 err
= register_filesystem(&openprom_fs_type
);
455 kmem_cache_destroy(op_inode_cachep
);
460 static void __exit
exit_openprom_fs(void)
462 unregister_filesystem(&openprom_fs_type
);
463 kmem_cache_destroy(op_inode_cachep
);
466 module_init(init_openprom_fs
)
467 module_exit(exit_openprom_fs
)
468 MODULE_LICENSE("GPL");