1 /* $Id: inode.c,v 1.5 2000/02/10 21:16:06 davem Exp $
2 * openpromfs.c: /proc/openprom handling routines
4 * Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com)
5 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
8 #include <linux/module.h>
9 #include <linux/types.h>
10 #include <linux/string.h>
12 #include <linux/openprom_fs.h>
13 #include <linux/locks.h>
14 #include <linux/init.h>
15 #include <linux/malloc.h>
17 #include <asm/openprom.h>
18 #include <asm/oplib.h>
19 #include <asm/uaccess.h>
21 #define ALIASES_NNODES 64
32 #define OPP_STRING 0x10
33 #define OPP_STRINGLIST 0x20
34 #define OPP_BINARY 0x40
35 #define OPP_HEXSTRING 0x80
36 #define OPP_DIRTY 0x01
37 #define OPP_QUOTED 0x02
38 #define OPP_NOTQUOTED 0x04
39 #define OPP_ASCIIZ 0x08
47 static openpromfs_node
*nodes
= NULL
;
48 static int alloced
= 0;
49 static u16 last_node
= 0;
50 static u16 first_prop
= 0;
51 static u16 options
= 0xffff;
52 static u16 aliases
= 0xffff;
53 static int aliases_nodes
= 0;
54 static char *alias_names
[ALIASES_NNODES
];
56 #define OPENPROM_ROOT_INO 16
57 #define OPENPROM_FIRST_INO OPENPROM_ROOT_INO
58 #define NODE(ino) nodes[ino - OPENPROM_FIRST_INO]
59 #define NODE2INO(node) (node + OPENPROM_FIRST_INO)
60 #define NODEP2INO(no) (no + OPENPROM_FIRST_INO + last_node)
62 static int openpromfs_create (struct inode
*, struct dentry
*, int);
63 static int openpromfs_readdir(struct file
*, void *, filldir_t
);
64 static struct dentry
*openpromfs_lookup(struct inode
*, struct dentry
*dentry
);
65 static int openpromfs_unlink (struct inode
*, struct dentry
*dentry
);
67 static ssize_t
nodenum_read(struct file
*file
, char *buf
,
68 size_t count
, loff_t
*ppos
)
70 struct inode
*inode
= file
->f_dentry
->d_inode
;
73 if (count
< 0 || !inode
->u
.generic_ip
)
75 sprintf (buffer
, "%8.8x\n", (u32
)(long)(inode
->u
.generic_ip
));
78 if (count
> 9 - file
->f_pos
)
79 count
= 9 - file
->f_pos
;
80 copy_to_user(buf
, buffer
+ file
->f_pos
, count
);
85 static ssize_t
property_read(struct file
*filp
, char *buf
,
86 size_t count
, loff_t
*ppos
)
88 struct inode
*inode
= filp
->f_dentry
->d_inode
;
93 openprom_property
*op
;
96 if (filp
->f_pos
>= 0xffffff)
98 if (!filp
->private_data
) {
99 node
= nodes
[(u16
)((long)inode
->u
.generic_ip
)].node
;
100 i
= ((u32
)(long)inode
->u
.generic_ip
) >> 16;
101 if ((u16
)((long)inode
->u
.generic_ip
) == aliases
) {
102 if (i
>= aliases_nodes
)
107 for (p
= prom_firstprop (node
, buffer
);
109 p
= prom_nextprop (node
, p
, buffer
), i
--)
113 i
= prom_getproplen (node
, p
);
115 if ((u16
)((long)inode
->u
.generic_ip
) == aliases
)
122 filp
->private_data
= kmalloc (sizeof (openprom_property
)
123 + (j
= strlen (p
)) + 2 * i
,
125 if (!filp
->private_data
)
127 op
= (openprom_property
*)filp
->private_data
;
129 op
->alloclen
= 2 * i
;
130 strcpy (op
->name
, p
);
131 op
->value
= (char *)(((unsigned long)(op
->name
+ j
+ 4)) & ~3);
133 if (k
&& prom_getproperty (node
, p
, op
->value
, i
) < 0)
137 for (s
= 0, p
= op
->value
; p
< op
->value
+ k
; p
++) {
138 if ((*p
>= ' ' && *p
<= '~') || *p
== '\n') {
139 op
->flag
|= OPP_STRING
;
143 if (p
> op
->value
&& !*p
&& s
== p
- 1) {
144 if (p
< op
->value
+ k
- 1)
145 op
->flag
|= OPP_STRINGLIST
;
147 op
->flag
|= OPP_ASCIIZ
;
151 op
->flag
|= (OPP_STRING
|OPP_ASCIIZ
);
154 op
->flag
&= ~(OPP_STRING
|OPP_STRINGLIST
);
156 op
->flag
|= OPP_HEXSTRING
;
158 op
->flag
|= OPP_BINARY
;
161 if (op
->flag
& OPP_STRINGLIST
)
162 op
->flag
&= ~(OPP_STRING
);
163 if (op
->flag
& OPP_ASCIIZ
)
167 op
= (openprom_property
*)filp
->private_data
;
168 if (!count
|| !(op
->len
|| (op
->flag
& OPP_ASCIIZ
)))
170 if (op
->flag
& OPP_STRINGLIST
) {
171 for (k
= 0, p
= op
->value
; p
< op
->value
+ op
->len
; p
++)
174 i
= op
->len
+ 4 * k
+ 3;
175 } else if (op
->flag
& OPP_STRING
) {
177 } else if (op
->flag
& OPP_BINARY
) {
178 i
= (op
->len
* 9) >> 2;
180 i
= (op
->len
<< 1) + 1;
183 if (k
>= i
) return 0;
184 if (count
> i
- k
) count
= i
- k
;
185 if (op
->flag
& OPP_STRING
) {
187 __put_user('\'', buf
);
192 if (k
+ count
>= i
- 2)
198 copy_to_user(buf
+ k
- filp
->f_pos
,
199 op
->value
+ k
- 1, j
);
205 __put_user('\'', &buf
[k
++ - filp
->f_pos
]);
207 __put_user('\n', &buf
[k
++ - filp
->f_pos
]);
209 } else if (op
->flag
& OPP_STRINGLIST
) {
212 tmp
= kmalloc (i
, GFP_KERNEL
);
218 for (p
= op
->value
; p
< op
->value
+ op
->len
; p
++) {
228 copy_to_user(buf
, tmp
+ k
, count
);
233 } else if (op
->flag
& OPP_BINARY
) {
236 int first_off
, last_cnt
;
238 first
= ((u32
*)op
->value
) + k
/ 9;
240 last
= ((u32
*)op
->value
) + (k
+ count
- 1) / 9;
241 last_cnt
= (k
+ count
) % 9;
242 if (!last_cnt
) last_cnt
= 9;
245 sprintf (buffer
, "%08x.", *first
);
246 copy_to_user (buf
, buffer
+ first_off
, last_cnt
- first_off
);
247 buf
+= last_cnt
- first_off
;
249 for (q
= first
; q
<= last
; q
++) {
250 sprintf (buffer
, "%08x.", *q
);
252 copy_to_user (buf
, buffer
+ first_off
,
254 buf
+= 9 - first_off
;
255 } else if (q
== last
) {
256 copy_to_user (buf
, buffer
, last_cnt
);
259 copy_to_user (buf
, buffer
, 9);
265 if (last
== (u32
*)(op
->value
+ op
->len
- 4) && last_cnt
== 9)
266 __put_user('\n', (buf
- 1));
270 } else if (op
->flag
& OPP_HEXSTRING
) {
273 if ((k
< i
- 1) && (k
& 1)) {
274 sprintf (buffer
, "%02x", *(op
->value
+ (k
>> 1)));
275 __put_user(buffer
[1], &buf
[k
++ - filp
->f_pos
]);
279 for (; (count
> 1) && (k
< i
- 1); k
+= 2) {
280 sprintf (buffer
, "%02x", *(op
->value
+ (k
>> 1)));
281 copy_to_user (buf
+ k
- filp
->f_pos
, buffer
, 2);
285 if (count
&& (k
< i
- 1)) {
286 sprintf (buffer
, "%02x", *(op
->value
+ (k
>> 1)));
287 __put_user(buffer
[0], &buf
[k
++ - filp
->f_pos
]);
292 __put_user('\n', &buf
[k
++ - filp
->f_pos
]);
294 count
= k
- filp
->f_pos
;
299 static ssize_t
property_write(struct file
*filp
, const char *buf
,
300 size_t count
, loff_t
*ppos
)
306 openprom_property
*op
;
308 if (filp
->f_pos
>= 0xffffff)
310 if (!filp
->private_data
) {
311 i
= property_read (filp
, NULL
, 0, 0);
316 op
= (openprom_property
*)filp
->private_data
;
317 if (!(op
->flag
& OPP_STRING
)) {
319 int first_off
, last_cnt
;
325 for (i
= 0; i
< count
; i
++, j
++) {
329 __get_user(ctmp
, &buf
[i
]);
332 if (op
->flag
& OPP_BINARY
)
335 goto write_try_string
;
344 __get_user(ctmp
, &buf
[i
]);
346 (ctmp
> '9' && ctmp
< 'A') ||
347 (ctmp
> 'F' && ctmp
< 'a') ||
349 if (op
->flag
& OPP_BINARY
)
352 goto write_try_string
;
356 op
->flag
|= OPP_BINARY
;
358 i
= ((count
+ k
+ 8) / 9) << 2;
359 if (op
->alloclen
<= i
) {
360 b
= kmalloc (sizeof (openprom_property
) + 2 * i
,
364 memcpy (b
, filp
->private_data
,
365 sizeof (openprom_property
)
366 + strlen (op
->name
) + op
->alloclen
);
367 memset (((char *)b
) + sizeof (openprom_property
)
368 + strlen (op
->name
) + op
->alloclen
,
369 0, 2 * i
- op
->alloclen
);
370 op
= (openprom_property
*)b
;
372 b
= filp
->private_data
;
373 filp
->private_data
= (void *)op
;
376 first
= ((u32
*)op
->value
) + (k
/ 9);
378 last
= (u32
*)(op
->value
+ i
);
379 last_cnt
= (k
+ count
) % 9;
380 if (first
+ 1 == last
) {
381 memset (tmp
, '0', 8);
382 copy_from_user (tmp
+ first_off
, buf
,
383 (count
+ first_off
> 8) ? 8 - first_off
: count
);
386 for (j
= 0; j
< first_off
; j
++)
388 for (j
= 8 - count
- first_off
; j
> 0; j
--)
393 *first
|= simple_strtoul (tmp
, 0, 16);
394 op
->flag
|= OPP_DIRTY
;
397 op
->flag
|= OPP_DIRTY
;
398 for (q
= first
; q
< last
; q
++) {
401 memset (tmp
, '0', 8);
402 copy_from_user (tmp
+ first_off
, buf
,
405 for (j
= 0; j
< first_off
; j
++)
408 *q
|= simple_strtoul (tmp
,0,16);
411 } else if ((q
== last
- 1) && last_cnt
413 memset (tmp
, '0', 8);
414 copy_from_user (tmp
, buf
, last_cnt
);
416 for (j
= 0; j
< 8 - last_cnt
; j
++)
419 *q
|= simple_strtoul (tmp
, 0, 16);
422 char tchars
[17]; /* XXX yuck... */
424 copy_from_user(tchars
, buf
, 16);
425 *q
= simple_strtoul (tchars
, 0, 16);
435 filp
->f_pos
+= count
;
438 if (!(op
->flag
& OPP_BINARY
)) {
439 if (!(op
->flag
& (OPP_QUOTED
| OPP_NOTQUOTED
))) {
442 /* No way, if somebody starts writing from the middle,
443 * we don't know whether he uses quotes around or not
447 __get_user(ctmp
, buf
);
449 op
->flag
|= OPP_QUOTED
;
454 op
->flag
|= OPP_STRING
;
458 op
->flag
|= OPP_NOTQUOTED
;
460 op
->flag
|= OPP_STRING
;
461 if (op
->alloclen
<= count
+ filp
->f_pos
) {
462 b
= kmalloc (sizeof (openprom_property
)
463 + 2 * (count
+ filp
->f_pos
), GFP_KERNEL
);
466 memcpy (b
, filp
->private_data
,
467 sizeof (openprom_property
)
468 + strlen (op
->name
) + op
->alloclen
);
469 memset (((char *)b
) + sizeof (openprom_property
)
470 + strlen (op
->name
) + op
->alloclen
,
471 0, 2*(count
- filp
->f_pos
) - op
->alloclen
);
472 op
= (openprom_property
*)b
;
473 op
->alloclen
= 2*(count
+ filp
->f_pos
);
474 b
= filp
->private_data
;
475 filp
->private_data
= (void *)op
;
478 p
= op
->value
+ filp
->f_pos
- ((op
->flag
& OPP_QUOTED
) ? 1 : 0);
479 copy_from_user (p
, buf
, count
);
480 op
->flag
|= OPP_DIRTY
;
481 for (i
= 0; i
< count
; i
++, p
++)
487 op
->len
= p
- op
->value
;
488 filp
->f_pos
+= i
+ 1;
489 if ((p
> op
->value
) && (op
->flag
& OPP_QUOTED
)
490 && (*(p
- 1) == '\''))
493 if (p
- op
->value
> op
->len
)
494 op
->len
= p
- op
->value
;
495 filp
->f_pos
+= count
;
498 return filp
->f_pos
- k
;
501 int property_release (struct inode
*inode
, struct file
*filp
)
503 openprom_property
*op
= (openprom_property
*)filp
->private_data
;
510 node
= nodes
[(u16
)((long)inode
->u
.generic_ip
)].node
;
511 if ((u16
)((long)inode
->u
.generic_ip
) == aliases
) {
512 if ((op
->flag
& OPP_DIRTY
) && (op
->flag
& OPP_STRING
)) {
514 int i
= (op
->value
- op
->name
) - strlen (op
->name
) - 1;
515 op
->value
[op
->len
] = 0;
516 *(op
->value
- 1) = ' ';
518 for (p
= op
->value
- i
- 2; p
>= op
->name
; p
--)
522 memcpy (p
- 8, "nvalias ", 8);
525 } else if (op
->flag
& OPP_DIRTY
) {
526 if (op
->flag
& OPP_STRING
) {
527 op
->value
[op
->len
] = 0;
528 save_and_cli (flags
);
529 error
= prom_setprop (node
, op
->name
,
530 op
->value
, op
->len
+ 1);
531 restore_flags (flags
);
533 printk (KERN_WARNING
"openpromfs: "
534 "Couldn't write property %s\n",
536 } else if ((op
->flag
& OPP_BINARY
) || !op
->len
) {
537 save_and_cli (flags
);
538 error
= prom_setprop (node
, op
->name
,
540 restore_flags (flags
);
542 printk (KERN_WARNING
"openpromfs: "
543 "Couldn't write property %s\n",
546 printk (KERN_WARNING
"openpromfs: "
547 "Unknown property type of %s\n",
551 kfree (filp
->private_data
);
555 static struct file_operations openpromfs_prop_ops
= {
557 write
: property_write
,
558 release
: property_release
,
561 static struct file_operations openpromfs_nodenum_ops
= {
565 static struct file_operations openprom_operations
= {
566 read
: generic_read_dir
,
567 readdir
: openpromfs_readdir
,
570 static struct inode_operations openprom_alias_inode_operations
= {
571 create
: openpromfs_create
,
572 lookup
: openpromfs_lookup
,
573 unlink
: openpromfs_unlink
,
576 static struct inode_operations openprom_inode_operations
= {
577 lookup
: openpromfs_lookup
,
580 static int lookup_children(u16 n
, const char * name
, int len
)
584 for (; n
!= 0xffff; n
= nodes
[n
].next
) {
585 node
= nodes
[n
].child
;
586 if (node
!= 0xffff) {
591 while (node
!= 0xffff) {
592 if (prom_getname (nodes
[node
].node
,
596 && !strncmp (buffer
, name
, len
))
597 return NODE2INO(node
);
598 p
= strchr (buffer
, '@');
599 if (p
&& (len
== p
- buffer
)
600 && !strncmp (buffer
, name
, len
))
601 return NODE2INO(node
);
603 node
= nodes
[node
].next
;
607 ret
= lookup_children (nodes
[n
].child
, name
, len
);
613 static struct dentry
*openpromfs_lookup(struct inode
* dir
, struct dentry
*dentry
)
617 #define OPFSL_PROPERTY 1
618 #define OPFSL_NODENUM 2
631 name
= dentry
->d_name
.name
;
632 len
= dentry
->d_name
.len
;
633 if (name
[0] == '.' && len
== 5 && !strncmp (name
+ 1, "node", 4)) {
634 ino
= NODEP2INO(NODE(dir
->i_ino
).first_prop
);
635 type
= OPFSL_NODENUM
;
638 u16 node
= NODE(dir
->i_ino
).child
;
639 while (node
!= 0xffff) {
640 if (prom_getname (nodes
[node
].node
, buffer
, 128) >= 0) {
642 if (len
== i
&& !strncmp (buffer
, name
, len
)) {
643 ino
= NODE2INO(node
);
647 p
= strchr (buffer
, '@');
648 if (p
&& (len
== p
- buffer
)
649 && !strncmp (buffer
, name
, len
)) {
650 ino
= NODE2INO(node
);
655 node
= nodes
[node
].next
;
658 n
= NODE(dir
->i_ino
).node
;
659 dirnode
= dir
->i_ino
- OPENPROM_FIRST_INO
;
661 int j
= NODEP2INO(NODE(dir
->i_ino
).first_prop
);
662 if (dirnode
!= aliases
) {
663 for (p
= prom_firstprop (n
, buffer2
);
665 p
= prom_nextprop (n
, p
, buffer2
)) {
667 if ((len
== strlen (p
))
668 && !strncmp (p
, name
, len
)) {
670 type
= OPFSL_PROPERTY
;
676 for (k
= 0; k
< aliases_nodes
; k
++) {
679 && (len
== strlen (alias_names
[k
]))
680 && !strncmp (alias_names
[k
], name
, len
)) {
682 type
= OPFSL_PROPERTY
;
689 ino
= lookup_children (NODE(dir
->i_ino
).child
, name
, len
);
693 return ERR_PTR(-ENOENT
);
695 inode
= iget (dir
->i_sb
, ino
);
697 return ERR_PTR(-EINVAL
);
700 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
701 if (ino
== OPENPROM_FIRST_INO
+ aliases
) {
702 inode
->i_mode
|= S_IWUSR
;
703 inode
->i_op
= &openprom_alias_inode_operations
;
705 inode
->i_op
= &openprom_inode_operations
;
706 inode
->i_fop
= &openprom_operations
;
710 inode
->i_mode
= S_IFREG
| S_IRUGO
;
711 inode
->i_fop
= &openpromfs_nodenum_ops
;
713 inode
->u
.generic_ip
= (void *)(long)(n
);
716 if ((dirnode
== options
) && (len
== 17)
717 && !strncmp (name
, "security-password", 17))
718 inode
->i_mode
= S_IFREG
| S_IRUSR
| S_IWUSR
;
720 inode
->i_mode
= S_IFREG
| S_IRUGO
;
721 if (dirnode
== options
|| dirnode
== aliases
) {
722 if (len
!= 4 || strncmp (name
, "name", 4))
723 inode
->i_mode
|= S_IWUSR
;
726 inode
->i_fop
= &openpromfs_prop_ops
;
728 if (inode
->i_size
< 0)
730 inode
->u
.generic_ip
= (void *)(long)(((u16
)dirnode
) |
731 (((u16
)(ino
- NODEP2INO(NODE(dir
->i_ino
).first_prop
) - 1)) << 16));
738 d_add(dentry
, inode
);
742 static int openpromfs_readdir(struct file
* filp
, void * dirent
, filldir_t filldir
)
744 struct inode
*inode
= filp
->f_dentry
->d_inode
;
757 if (filldir(dirent
, ".", 1, i
, ino
) < 0) return 0;
762 if (filldir(dirent
, "..", 2, i
,
763 (NODE(ino
).parent
== 0xffff) ?
764 OPENPROM_ROOT_INO
: NODE2INO(NODE(ino
).parent
)) < 0)
771 node
= NODE(ino
).child
;
772 while (i
&& node
!= 0xffff) {
773 node
= nodes
[node
].next
;
776 while (node
!= 0xffff) {
777 if (prom_getname (nodes
[node
].node
, buffer
, 128) < 0)
779 if (filldir(dirent
, buffer
, strlen(buffer
),
780 filp
->f_pos
, NODE2INO(node
)) < 0)
783 node
= nodes
[node
].next
;
785 j
= NODEP2INO(NODE(ino
).first_prop
);
787 if (filldir(dirent
, ".node", 5, filp
->f_pos
, j
) < 0)
793 if (ino
== OPENPROM_FIRST_INO
+ aliases
) {
794 for (j
++; i
< aliases_nodes
; i
++, j
++) {
795 if (alias_names
[i
]) {
796 if (filldir (dirent
, alias_names
[i
],
797 strlen (alias_names
[i
]),
798 filp
->f_pos
, j
) < 0) return 0;
803 for (p
= prom_firstprop (n
, buffer2
);
805 p
= prom_nextprop (n
, p
, buffer2
)) {
809 if (filldir(dirent
, p
, strlen(p
),
820 static int openpromfs_create (struct inode
*dir
, struct dentry
*dentry
, int mode
)
827 if (dentry
->d_name
.len
> 256)
829 if (aliases_nodes
== ALIASES_NNODES
)
831 p
= kmalloc (dentry
->d_name
.len
+ 1, GFP_KERNEL
);
834 strncpy (p
, dentry
->d_name
.name
, dentry
->d_name
.len
);
835 p
[dentry
->d_name
.len
] = 0;
836 alias_names
[aliases_nodes
++] = p
;
837 inode
= iget (dir
->i_sb
,
838 NODEP2INO(NODE(dir
->i_ino
).first_prop
) + aliases_nodes
);
841 inode
->i_mode
= S_IFREG
| S_IRUGO
| S_IWUSR
;
842 inode
->i_fop
= &openpromfs_prop_ops
;
844 if (inode
->i_size
< 0) inode
->i_size
= 0;
845 inode
->u
.generic_ip
= (void *)(long)(((u16
)aliases
) |
846 (((u16
)(aliases_nodes
- 1)) << 16));
847 d_instantiate(dentry
, inode
);
851 static int openpromfs_unlink (struct inode
*dir
, struct dentry
*dentry
)
858 name
= dentry
->d_name
.name
;
859 len
= dentry
->d_name
.len
;
860 for (i
= 0; i
< aliases_nodes
; i
++)
861 if ((strlen (alias_names
[i
]) == len
)
862 && !strncmp (name
, alias_names
[i
], len
)) {
866 alias_names
[i
] = NULL
;
868 strcpy (buffer
, "nvunalias ");
869 memcpy (buffer
+ 10, name
, len
);
870 buffer
[10 + len
] = 0;
877 /* {{{ init section */
879 static int __init
check_space (u16 n
)
881 static int check_space (u16 n
)
886 if ((1 << alloced
) * PAGE_SIZE
< (n
+ 2) * sizeof(openpromfs_node
)) {
887 pages
= __get_free_pages (GFP_KERNEL
, alloced
+ 1);
892 memcpy ((char *)pages
, (char *)nodes
,
893 (1 << alloced
) * PAGE_SIZE
);
894 free_pages ((unsigned long)nodes
, alloced
);
897 nodes
= (openpromfs_node
*)pages
;
903 static u16 __init
get_nodes (u16 parent
, u32 node
)
905 static u16
get_nodes (u16 parent
, u32 node
)
909 u16 n
= last_node
++, i
;
912 if (check_space (n
) < 0)
914 nodes
[n
].parent
= parent
;
915 nodes
[n
].node
= node
;
916 nodes
[n
].next
= 0xffff;
917 nodes
[n
].child
= 0xffff;
918 nodes
[n
].first_prop
= first_prop
++;
923 if ((j
= prom_getproperty (node
, "name", buffer
, 8)) >= 0) {
925 if (!strcmp (buffer
, "options"))
927 else if (!strcmp (buffer
, "aliases"))
932 for (p
= prom_firstprop (node
, buffer
);
933 p
&& p
!= (char *)-1 && *p
;
934 p
= prom_nextprop (node
, p
, buffer
))
938 for (p
= prom_firstprop (node
, buffer
);
939 p
&& p
!= (char *)-1 && *p
;
940 p
= prom_nextprop (node
, p
, buffer
)) {
941 if (aliases_nodes
== ALIASES_NNODES
)
943 for (i
= 0; i
< aliases_nodes
; i
++)
944 if (!strcmp (p
, alias_names
[i
]))
946 if (i
< aliases_nodes
)
948 q
= kmalloc (strlen (p
) + 1, GFP_KERNEL
);
952 alias_names
[aliases_nodes
++] = q
;
954 first_prop
+= ALIASES_NNODES
;
956 node
= prom_getchild (node
);
958 parent
= get_nodes (n
, node
);
959 if (parent
== 0xffff)
961 nodes
[n
].child
= parent
;
962 while ((node
= prom_getsibling (node
)) != 0) {
963 i
= get_nodes (n
, node
);
966 nodes
[parent
].next
= i
;
973 static void openprom_read_inode(struct inode
* inode
)
975 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
976 if (inode
->i_ino
== OPENPROM_ROOT_INO
) {
977 inode
->i_op
= &openprom_inode_operations
;
978 inode
->i_fop
= &openprom_operations
;
979 inode
->i_mode
= S_IFDIR
| S_IRUGO
| S_IXUGO
;
983 static void openprom_put_super(struct super_block
*sb
)
988 static int openprom_statfs(struct super_block
*sb
, struct statfs
*buf
, int bufsiz
)
992 tmp
.f_type
= OPENPROM_SUPER_MAGIC
;
993 tmp
.f_bsize
= PAGE_SIZE
/sizeof(long); /* ??? */
999 tmp
.f_namelen
= NAME_MAX
;
1000 return copy_to_user(buf
, &tmp
, bufsiz
) ? -EFAULT
: 0;
1003 static struct super_operations openprom_sops
= {
1004 read_inode
: openprom_read_inode
,
1005 put_super
: openprom_put_super
,
1006 statfs
: openprom_statfs
,
1009 struct super_block
*openprom_read_super(struct super_block
*s
,void *data
,
1012 struct inode
* root_inode
;
1016 s
->s_blocksize
= 1024;
1017 s
->s_blocksize_bits
= 10;
1018 s
->s_magic
= OPENPROM_SUPER_MAGIC
;
1019 s
->s_op
= &openprom_sops
;
1020 root_inode
= iget(s
, OPENPROM_ROOT_INO
);
1023 s
->s_root
= d_alloc_root(root_inode
);
1030 printk("openprom_read_super: get root inode failed\n");
1038 static struct file_system_type openprom_fs_type
= {
1041 openprom_read_super
,
1045 int init_openprom_fs(void)
1047 nodes
= (openpromfs_node
*)__get_free_pages(GFP_KERNEL
, 0);
1049 printk (KERN_WARNING
"openpromfs: can't get free page\n");
1052 if (get_nodes (0xffff, prom_root_node
) == 0xffff) {
1053 printk (KERN_WARNING
"openpromfs: couldn't setup tree\n");
1056 nodes
[last_node
].first_prop
= first_prop
;
1057 return register_filesystem(&openprom_fs_type
);
1064 int init_module (void)
1066 return init_openprom_fs();
1071 void __init
openpromfs_init (void)
1078 void cleanup_module (void)
1081 unregister_filesystem(&openprom_fs_type
);
1082 free_pages ((unsigned long)nodes
, alloced
);
1083 for (i
= 0; i
< aliases_nodes
; i
++)
1084 if (alias_names
[i
])
1085 kfree (alias_names
[i
]);