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
,
170 .llseek
= generic_file_llseek
,
173 static struct dentry
*openpromfs_lookup(struct inode
*, struct dentry
*, struct nameidata
*);
175 static const struct inode_operations openprom_inode_operations
= {
176 .lookup
= openpromfs_lookup
,
179 static struct dentry
*openpromfs_lookup(struct inode
*dir
, struct dentry
*dentry
, struct nameidata
*nd
)
181 struct op_inode_info
*ent_oi
, *oi
= OP_I(dir
);
182 struct device_node
*dp
, *child
;
183 struct property
*prop
;
184 enum op_inode_type ent_type
;
185 union op_inode_data ent_data
;
191 BUG_ON(oi
->type
!= op_inode_node
);
195 name
= dentry
->d_name
.name
;
196 len
= dentry
->d_name
.len
;
198 mutex_lock(&op_mutex
);
202 int n
= strlen(child
->path_component_name
);
205 !strncmp(child
->path_component_name
, name
, len
)) {
206 ent_type
= op_inode_node
;
207 ent_data
.node
= child
;
208 ino
= child
->unique_id
;
211 child
= child
->sibling
;
214 prop
= dp
->properties
;
216 int n
= strlen(prop
->name
);
218 if (len
== n
&& !strncmp(prop
->name
, name
, len
)) {
219 ent_type
= op_inode_prop
;
220 ent_data
.prop
= prop
;
221 ino
= prop
->unique_id
;
228 mutex_unlock(&op_mutex
);
229 return ERR_PTR(-ENOENT
);
232 inode
= openprom_iget(dir
->i_sb
, ino
);
233 mutex_unlock(&op_mutex
);
235 return ERR_CAST(inode
);
236 ent_oi
= OP_I(inode
);
237 ent_oi
->type
= ent_type
;
238 ent_oi
->u
= ent_data
;
242 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
243 inode
->i_op
= &openprom_inode_operations
;
244 inode
->i_fop
= &openprom_operations
;
248 if (!strcmp(dp
->name
, "options") && (len
== 17) &&
249 !strncmp (name
, "security-password", 17))
250 inode
->i_mode
= S_IFREG
| S_IRUSR
| S_IWUSR
;
252 inode
->i_mode
= S_IFREG
| S_IRUGO
;
253 inode
->i_fop
= &openpromfs_prop_ops
;
255 inode
->i_size
= ent_oi
->u
.prop
->length
;
262 d_add(dentry
, inode
);
266 static int openpromfs_readdir(struct file
* filp
, void * dirent
, filldir_t filldir
)
268 struct inode
*inode
= filp
->f_path
.dentry
->d_inode
;
269 struct op_inode_info
*oi
= OP_I(inode
);
270 struct device_node
*dp
= oi
->u
.node
;
271 struct device_node
*child
;
272 struct property
*prop
;
276 mutex_lock(&op_mutex
);
282 if (filldir(dirent
, ".", 1, i
, ino
, DT_DIR
) < 0)
288 if (filldir(dirent
, "..", 2, i
,
289 (dp
->parent
== NULL
?
291 dp
->parent
->unique_id
), DT_DIR
) < 0)
299 /* First, the children nodes as directories. */
302 child
= child
->sibling
;
307 child
->path_component_name
,
308 strlen(child
->path_component_name
),
309 filp
->f_pos
, child
->unique_id
, DT_DIR
) < 0)
313 child
= child
->sibling
;
316 /* Next, the properties as files. */
317 prop
= dp
->properties
;
323 if (filldir(dirent
, prop
->name
, strlen(prop
->name
),
324 filp
->f_pos
, prop
->unique_id
, DT_REG
) < 0)
332 mutex_unlock(&op_mutex
);
336 static struct kmem_cache
*op_inode_cachep
;
338 static struct inode
*openprom_alloc_inode(struct super_block
*sb
)
340 struct op_inode_info
*oi
;
342 oi
= kmem_cache_alloc(op_inode_cachep
, GFP_KERNEL
);
346 return &oi
->vfs_inode
;
349 static void openprom_destroy_inode(struct inode
*inode
)
351 kmem_cache_free(op_inode_cachep
, OP_I(inode
));
354 static struct inode
*openprom_iget(struct super_block
*sb
, ino_t ino
)
358 inode
= iget_locked(sb
, ino
);
360 return ERR_PTR(-ENOMEM
);
361 if (inode
->i_state
& I_NEW
) {
362 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
363 if (inode
->i_ino
== OPENPROM_ROOT_INO
) {
364 inode
->i_op
= &openprom_inode_operations
;
365 inode
->i_fop
= &openprom_operations
;
366 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
368 unlock_new_inode(inode
);
373 static int openprom_remount(struct super_block
*sb
, int *flags
, char *data
)
375 *flags
|= MS_NOATIME
;
379 static const struct super_operations openprom_sops
= {
380 .alloc_inode
= openprom_alloc_inode
,
381 .destroy_inode
= openprom_destroy_inode
,
382 .statfs
= simple_statfs
,
383 .remount_fs
= openprom_remount
,
386 static int openprom_fill_super(struct super_block
*s
, void *data
, int silent
)
388 struct inode
*root_inode
;
389 struct op_inode_info
*oi
;
392 s
->s_flags
|= MS_NOATIME
;
393 s
->s_blocksize
= 1024;
394 s
->s_blocksize_bits
= 10;
395 s
->s_magic
= OPENPROM_SUPER_MAGIC
;
396 s
->s_op
= &openprom_sops
;
398 root_inode
= openprom_iget(s
, OPENPROM_ROOT_INO
);
399 if (IS_ERR(root_inode
)) {
400 ret
= PTR_ERR(root_inode
);
404 oi
= OP_I(root_inode
);
405 oi
->type
= op_inode_node
;
406 oi
->u
.node
= of_find_node_by_path("/");
408 s
->s_root
= d_alloc_root(root_inode
);
410 goto out_no_root_dentry
;
417 printk("openprom_fill_super: get root inode failed\n");
421 static int openprom_get_sb(struct file_system_type
*fs_type
,
422 int flags
, const char *dev_name
, void *data
, struct vfsmount
*mnt
)
424 return get_sb_single(fs_type
, flags
, data
, openprom_fill_super
, mnt
);
427 static struct file_system_type openprom_fs_type
= {
428 .owner
= THIS_MODULE
,
429 .name
= "openpromfs",
430 .get_sb
= openprom_get_sb
,
431 .kill_sb
= kill_anon_super
,
434 static void op_inode_init_once(void *data
)
436 struct op_inode_info
*oi
= (struct op_inode_info
*) data
;
438 inode_init_once(&oi
->vfs_inode
);
441 static int __init
init_openprom_fs(void)
445 op_inode_cachep
= kmem_cache_create("op_inode_cache",
446 sizeof(struct op_inode_info
),
448 (SLAB_RECLAIM_ACCOUNT
|
451 if (!op_inode_cachep
)
454 err
= register_filesystem(&openprom_fs_type
);
456 kmem_cache_destroy(op_inode_cachep
);
461 static void __exit
exit_openprom_fs(void)
463 unregister_filesystem(&openprom_fs_type
);
464 kmem_cache_destroy(op_inode_cachep
);
467 module_init(init_openprom_fs
)
468 module_exit(exit_openprom_fs
)
469 MODULE_LICENSE("GPL");