1 /* $NetBSD: openfirmio.c,v 1.10 2007/02/28 20:33:50 macallan Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This software was developed by the Computer Systems Engineering group
8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
9 * contributed to Berkeley.
11 * All advertising materials mentioning features or use of this software
12 * must display the following acknowledgement:
13 * This product includes software developed by the University of
14 * California, Lawrence Berkeley Laboratory.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * @(#)openfirm.c 8.1 (Berkeley) 6/11/93
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: openfirmio.c,v 1.10 2007/02/28 20:33:50 macallan Exp $");
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/errno.h>
49 #include <sys/fcntl.h>
50 #include <sys/ioctl.h>
51 #include <sys/malloc.h>
53 #include <sys/device.h>
54 #include <sys/event.h>
56 #include <dev/ofw/openfirm.h>
57 #include <dev/ofw/openfirmio.h>
59 static int lastnode
; /* speed hack */
61 static int openfirmcheckid (int, int);
62 static int openfirmgetstr (int, char *, char **);
64 void openfirmattach (int);
66 dev_type_ioctl(openfirmioctl
);
68 const struct cdevsw openfirm_cdevsw
= {
69 nullopen
, nullclose
, noread
, nowrite
, openfirmioctl
,
70 nostop
, notty
, nopoll
, nommap
, nokqfilter
,
74 openfirmattach(int num
)
80 * Verify target ID is valid (exists in the OPENPROM tree), as
81 * listed from node ID sid forward.
84 openfirmcheckid(int sid
, int tid
)
87 for (; sid
!= 0; sid
= OF_peer(sid
))
88 if (sid
== tid
|| openfirmcheckid(OF_child(sid
), tid
))
95 openfirmgetstr(int len
, char *user
, char **cpp
)
100 /* Reject obvious bogus requests */
101 if ((u_int
)len
> (8 * 1024) - 1)
102 return (ENAMETOOLONG
);
104 *cpp
= cp
= malloc(len
+ 1, M_TEMP
, M_WAITOK
);
105 error
= copyin(user
, cp
, len
);
111 openfirmioctl(dev_t dev
, u_long cmd
, void *data
, int flags
, struct lwp
*l
)
113 struct ofiocdesc
*of
;
114 int node
, len
, ok
, error
, s
;
117 if (cmd
== OFIOCGETOPTNODE
) {
119 *(int *) data
= OF_finddevice("/options");
125 of
= (struct ofiocdesc
*)data
;
126 node
= of
->of_nodeid
;
127 if (node
!= 0 && node
!= lastnode
) {
128 /* Not an easy one, must search for it */
130 ok
= openfirmcheckid(OF_peer(0), node
);
142 if ((flags
& FREAD
) == 0)
146 error
= openfirmgetstr(of
->of_namelen
, of
->of_name
, &name
);
150 len
= OF_getproplen(node
, name
);
152 if (len
> of
->of_buflen
) {
157 /* -1 means no entry; 0 means no value */
160 value
= malloc(len
, M_TEMP
, M_WAITOK
);
166 len
= OF_getprop(node
, name
, (void *)value
, len
);
168 error
= copyout(value
, of
->of_buf
, len
);
173 if ((flags
& FWRITE
) == 0)
177 error
= openfirmgetstr(of
->of_namelen
, of
->of_name
, &name
);
180 error
= openfirmgetstr(of
->of_buflen
, of
->of_buf
, &value
);
184 len
= OF_setprop(node
, name
, value
, of
->of_buflen
+ 1);
189 * some OF implementations return the buffer length including
190 * the trailing zero ( like macppc ) and some without ( like
191 * FirmWorks OF used in Shark )
193 if ((len
!= (of
->of_buflen
+ 1)) && (len
!= of
->of_buflen
))
197 case OFIOCNEXTPROP
: {
199 if ((flags
& FREAD
) == 0)
203 if (of
->of_namelen
!= 0) {
204 error
= openfirmgetstr(of
->of_namelen
, of
->of_name
,
210 ok
= OF_nextprop(node
, name
, newname
);
220 len
= strlen(newname
);
221 if (len
> of
->of_buflen
)
225 error
= copyout(newname
, of
->of_buf
, len
);
230 if ((flags
& FREAD
) == 0)
233 node
= OF_peer(node
);
235 *(int *)data
= lastnode
= node
;
239 if ((flags
& FREAD
) == 0)
244 node
= OF_child(node
);
246 *(int *)data
= lastnode
= node
;
249 case OFIOCFINDDEVICE
:
250 if ((flags
& FREAD
) == 0)
252 error
= openfirmgetstr(of
->of_namelen
, of
->of_name
, &name
);
255 node
= OF_finddevice(name
);
256 if (node
== 0 || node
== -1) {
260 of
->of_nodeid
= lastnode
= node
;