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/openprom_fs.h>
12 #include <linux/init.h>
13 #include <linux/slab.h>
14 #include <linux/seq_file.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 inline struct op_inode_info
*OP_I(struct inode
*inode
)
43 return container_of(inode
, struct op_inode_info
, vfs_inode
);
46 static int is_string(unsigned char *p
, int len
)
50 for (i
= 0; i
< len
; i
++) {
51 unsigned char val
= p
[i
];
54 (val
>= ' ' && val
<= '~'))
63 static int property_show(struct seq_file
*f
, void *v
)
65 struct property
*prop
= f
->private;
72 if (is_string(pval
, len
)) {
76 seq_printf(f
, "%s", (char *) pval
);
78 /* Skip over the NULL byte too. */
90 seq_printf(f
, "%02x.",
91 *(unsigned char *) pval
);
94 *(unsigned char *) pval
);
102 seq_printf(f
, "%08x.",
103 *(unsigned int *) pval
);
105 seq_printf(f
, "%08x",
106 *(unsigned int *) pval
);
116 static void *property_start(struct seq_file
*f
, loff_t
*pos
)
123 static void *property_next(struct seq_file
*f
, void *v
, loff_t
*pos
)
129 static void property_stop(struct seq_file
*f
, void *v
)
134 static struct seq_operations property_op
= {
135 .start
= property_start
,
136 .next
= property_next
,
137 .stop
= property_stop
,
138 .show
= property_show
141 static int property_open(struct inode
*inode
, struct file
*file
)
143 struct op_inode_info
*oi
= OP_I(inode
);
146 BUG_ON(oi
->type
!= op_inode_prop
);
148 ret
= seq_open(file
, &property_op
);
150 struct seq_file
*m
= file
->private_data
;
151 m
->private = oi
->u
.prop
;
156 static const struct file_operations openpromfs_prop_ops
= {
157 .open
= property_open
,
160 .release
= seq_release
,
163 static int openpromfs_readdir(struct file
*, void *, filldir_t
);
165 static const struct file_operations openprom_operations
= {
166 .read
= generic_read_dir
,
167 .readdir
= openpromfs_readdir
,
170 static struct dentry
*openpromfs_lookup(struct inode
*, struct dentry
*, struct nameidata
*);
172 static struct inode_operations openprom_inode_operations
= {
173 .lookup
= openpromfs_lookup
,
176 static struct dentry
*openpromfs_lookup(struct inode
*dir
, struct dentry
*dentry
, struct nameidata
*nd
)
178 struct op_inode_info
*ent_oi
, *oi
= OP_I(dir
);
179 struct device_node
*dp
, *child
;
180 struct property
*prop
;
181 enum op_inode_type ent_type
;
182 union op_inode_data ent_data
;
188 BUG_ON(oi
->type
!= op_inode_node
);
192 name
= dentry
->d_name
.name
;
193 len
= dentry
->d_name
.len
;
195 mutex_lock(&op_mutex
);
199 int n
= strlen(child
->path_component_name
);
202 !strncmp(child
->path_component_name
, name
, len
)) {
203 ent_type
= op_inode_node
;
204 ent_data
.node
= child
;
205 ino
= child
->unique_id
;
208 child
= child
->sibling
;
211 prop
= dp
->properties
;
213 int n
= strlen(prop
->name
);
215 if (len
== n
&& !strncmp(prop
->name
, name
, len
)) {
216 ent_type
= op_inode_prop
;
217 ent_data
.prop
= prop
;
218 ino
= prop
->unique_id
;
225 mutex_unlock(&op_mutex
);
226 return ERR_PTR(-ENOENT
);
229 inode
= iget(dir
->i_sb
, ino
);
230 mutex_unlock(&op_mutex
);
232 return ERR_PTR(-EINVAL
);
233 ent_oi
= OP_I(inode
);
234 ent_oi
->type
= ent_type
;
235 ent_oi
->u
= ent_data
;
239 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
240 inode
->i_op
= &openprom_inode_operations
;
241 inode
->i_fop
= &openprom_operations
;
245 if (!strcmp(dp
->name
, "options") && (len
== 17) &&
246 !strncmp (name
, "security-password", 17))
247 inode
->i_mode
= S_IFREG
| S_IRUSR
| S_IWUSR
;
249 inode
->i_mode
= S_IFREG
| S_IRUGO
;
250 inode
->i_fop
= &openpromfs_prop_ops
;
252 inode
->i_size
= ent_oi
->u
.prop
->length
;
259 d_add(dentry
, inode
);
263 static int openpromfs_readdir(struct file
* filp
, void * dirent
, filldir_t filldir
)
265 struct inode
*inode
= filp
->f_dentry
->d_inode
;
266 struct op_inode_info
*oi
= OP_I(inode
);
267 struct device_node
*dp
= oi
->u
.node
;
268 struct device_node
*child
;
269 struct property
*prop
;
273 mutex_lock(&op_mutex
);
279 if (filldir(dirent
, ".", 1, i
, ino
, DT_DIR
) < 0)
285 if (filldir(dirent
, "..", 2, i
,
286 (dp
->parent
== NULL
?
288 dp
->parent
->unique_id
), DT_DIR
) < 0)
296 /* First, the children nodes as directories. */
299 child
= child
->sibling
;
304 child
->path_component_name
,
305 strlen(child
->path_component_name
),
306 filp
->f_pos
, child
->unique_id
, DT_DIR
) < 0)
310 child
= child
->sibling
;
313 /* Next, the properties as files. */
314 prop
= dp
->properties
;
320 if (filldir(dirent
, prop
->name
, strlen(prop
->name
),
321 filp
->f_pos
, prop
->unique_id
, DT_REG
) < 0)
329 mutex_unlock(&op_mutex
);
333 static kmem_cache_t
*op_inode_cachep
;
335 static struct inode
*openprom_alloc_inode(struct super_block
*sb
)
337 struct op_inode_info
*oi
;
339 oi
= kmem_cache_alloc(op_inode_cachep
, SLAB_KERNEL
);
343 return &oi
->vfs_inode
;
346 static void openprom_destroy_inode(struct inode
*inode
)
348 kmem_cache_free(op_inode_cachep
, OP_I(inode
));
351 static void openprom_read_inode(struct inode
* inode
)
353 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
354 if (inode
->i_ino
== OPENPROM_ROOT_INO
) {
355 inode
->i_op
= &openprom_inode_operations
;
356 inode
->i_fop
= &openprom_operations
;
357 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
361 static int openprom_remount(struct super_block
*sb
, int *flags
, char *data
)
363 *flags
|= MS_NOATIME
;
367 static struct super_operations openprom_sops
= {
368 .alloc_inode
= openprom_alloc_inode
,
369 .destroy_inode
= openprom_destroy_inode
,
370 .read_inode
= openprom_read_inode
,
371 .statfs
= simple_statfs
,
372 .remount_fs
= openprom_remount
,
375 static int openprom_fill_super(struct super_block
*s
, void *data
, int silent
)
377 struct inode
*root_inode
;
378 struct op_inode_info
*oi
;
380 s
->s_flags
|= MS_NOATIME
;
381 s
->s_blocksize
= 1024;
382 s
->s_blocksize_bits
= 10;
383 s
->s_magic
= OPENPROM_SUPER_MAGIC
;
384 s
->s_op
= &openprom_sops
;
386 root_inode
= iget(s
, OPENPROM_ROOT_INO
);
390 oi
= OP_I(root_inode
);
391 oi
->type
= op_inode_node
;
392 oi
->u
.node
= of_find_node_by_path("/");
394 s
->s_root
= d_alloc_root(root_inode
);
400 printk("openprom_fill_super: get root inode failed\n");
405 static int openprom_get_sb(struct file_system_type
*fs_type
,
406 int flags
, const char *dev_name
, void *data
, struct vfsmount
*mnt
)
408 return get_sb_single(fs_type
, flags
, data
, openprom_fill_super
, mnt
);
411 static struct file_system_type openprom_fs_type
= {
412 .owner
= THIS_MODULE
,
413 .name
= "openpromfs",
414 .get_sb
= openprom_get_sb
,
415 .kill_sb
= kill_anon_super
,
418 static void op_inode_init_once(void *data
, kmem_cache_t
* cachep
, unsigned long flags
)
420 struct op_inode_info
*oi
= (struct op_inode_info
*) data
;
422 if ((flags
& (SLAB_CTOR_VERIFY
|SLAB_CTOR_CONSTRUCTOR
)) ==
423 SLAB_CTOR_CONSTRUCTOR
)
424 inode_init_once(&oi
->vfs_inode
);
427 static int __init
init_openprom_fs(void)
431 op_inode_cachep
= kmem_cache_create("op_inode_cache",
432 sizeof(struct op_inode_info
),
434 (SLAB_RECLAIM_ACCOUNT
|
436 op_inode_init_once
, NULL
);
437 if (!op_inode_cachep
)
440 err
= register_filesystem(&openprom_fs_type
);
442 kmem_cache_destroy(op_inode_cachep
);
447 static void __exit
exit_openprom_fs(void)
449 unregister_filesystem(&openprom_fs_type
);
450 kmem_cache_destroy(op_inode_cachep
);
453 module_init(init_openprom_fs
)
454 module_exit(exit_openprom_fs
)
455 MODULE_LICENSE("GPL");