xref: /openbsd-src/sys/arch/arm/arm/openprom.c (revision a4a50d9633ad5d32f291ac2e2a431b18d1120b73)
1 /*	$OpenBSD: openprom.c,v 1.4 2021/03/25 04:12:00 jsg Exp $	*/
2 /*	$NetBSD: openprom.c,v 1.4 2002/01/10 06:21:53 briggs Exp $ */
3 
4 /*
5  * Copyright (c) 1992, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This software was developed by the Computer Systems Engineering group
9  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
10  * contributed to Berkeley.
11  *
12  * All advertising materials mentioning features or use of this software
13  * must display the following acknowledgement:
14  *	This product includes software developed by the University of
15  *	California, Lawrence Berkeley Laboratory.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions
19  * are met:
20  * 1. Redistributions of source code must retain the above copyright
21  *    notice, this list of conditions and the following disclaimer.
22  * 2. Redistributions in binary form must reproduce the above copyright
23  *    notice, this list of conditions and the following disclaimer in the
24  *    documentation and/or other materials provided with the distribution.
25  * 3. Neither the name of the University nor the names of its contributors
26  *    may be used to endorse or promote products derived from this software
27  *    without specific prior written permission.
28  *
29  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39  * SUCH DAMAGE.
40  *
41  *	@(#)openprom.c	8.1 (Berkeley) 6/11/93
42  */
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/errno.h>
47 #include <sys/fcntl.h>
48 #include <sys/ioctl.h>
49 #include <sys/malloc.h>
50 
51 #include <machine/openpromio.h>
52 #include <machine/conf.h>
53 
54 #include <dev/ofw/openfirm.h>
55 
56 static int lastnode;			/* speed hack */
57 static int optionsnode;			/* node ID of ROM's options */
58 
59 int	openpromcheckid(int, int);
60 int	openpromgetstr(int, char *, char **);
61 void    openpromattach(int);
62 
63 void
openpromattach(int num)64 openpromattach(int num)
65 {
66 }
67 
68 int
openpromopen(dev_t dev,int flags,int mode,struct proc * p)69 openpromopen(dev_t dev, int flags, int mode, struct proc *p)
70 {
71 	return (0);
72 }
73 
74 int
openpromclose(dev_t dev,int flags,int mode,struct proc * p)75 openpromclose(dev_t dev, int flags, int mode, struct proc *p)
76 {
77 	return (0);
78 }
79 
80 /*
81  * Verify target ID is valid (exists in the OPENPROM tree), as
82  * listed from node ID sid forward.
83  */
84 int
openpromcheckid(int sid,int tid)85 openpromcheckid(int sid, int tid)
86 {
87 	for (; sid != 0; sid = OF_peer(sid))
88 		if (sid == tid || openpromcheckid(OF_child(sid), tid))
89 			return (1);
90 
91 	return (0);
92 }
93 
94 int
openpromgetstr(int len,char * user,char ** cpp)95 openpromgetstr(int len, char *user, char **cpp)
96 {
97 	int error;
98 	char *cp;
99 
100 	/* Reject obvious bogus requests */
101 	if ((u_int)len > (8 * 1024) - 1)
102 		return (ENAMETOOLONG);
103 
104 	*cpp = cp = malloc(len + 1, M_TEMP, M_WAITOK);
105 	error = copyin(user, cp, len);
106 	cp[len] = '\0';
107 	return (error);
108 }
109 
110 int
openpromioctl(dev_t dev,u_long cmd,caddr_t data,int flags,struct proc * p)111 openpromioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
112 {
113 	struct opiocdesc *op;
114 	int node, len, ok, error;
115 	char *name, *value, *nextprop;
116 
117 	if (optionsnode == 0)
118 		optionsnode = OF_getnodebyname(0, "options");
119 
120 	/* All too easy... */
121 	if (cmd == OPIOCGETOPTNODE) {
122 		*(int *)data = optionsnode;
123 		return (0);
124 	}
125 
126 	/* Verify node id */
127 	op = (struct opiocdesc *)data;
128 	node = op->op_nodeid;
129 	if (node != 0 && node != lastnode && node != optionsnode) {
130 		/* Not an easy one, must search for it */
131 		ok = openpromcheckid(OF_peer(0), node);
132 		if (!ok)
133 			return (EINVAL);
134 		lastnode = node;
135 	}
136 
137 	name = value = NULL;
138 	error = 0;
139 	switch (cmd) {
140 
141 	case OPIOCGET:
142 		if ((flags & FREAD) == 0)
143 			return (EBADF);
144 		if (node == 0)
145 			return (EINVAL);
146 		error = openpromgetstr(op->op_namelen, op->op_name, &name);
147 		if (error)
148 			break;
149 		len = OF_getproplen(node, name);
150 		if (len > op->op_buflen) {
151 			error = ENOMEM;
152 			break;
153 		}
154 		op->op_buflen = len;
155 		/* -1 means no entry; 0 means no value */
156 		if (len <= 0)
157 			break;
158 		value = malloc(len, M_TEMP, M_WAITOK);
159 		OF_getprop(node, name, value, len);
160 		error = copyout(value, op->op_buf, len);
161 		break;
162 
163 	case OPIOCNEXTPROP:
164 		if ((flags & FREAD) == 0)
165 			return (EBADF);
166 		if (node == 0)
167 			return (EINVAL);
168 		error = openpromgetstr(op->op_namelen, op->op_name, &name);
169 		if (error)
170 			break;
171 		if (op->op_buflen <= 0) {
172 			error = ENAMETOOLONG;
173 			break;
174 		}
175 		value = nextprop = malloc(OFMAXPARAM, M_TEMP,
176 		    M_WAITOK | M_CANFAIL);
177 		if (nextprop == NULL) {
178 			error = ENOMEM;
179 			break;
180 		}
181 		error = OF_nextprop(node, name, nextprop);
182 		if (error == -1) {
183 			error = EINVAL;
184 			break;
185 		}
186 		if (error == 0) {
187 			char nul = '\0';
188 
189 			op->op_buflen = 0;
190 			error = copyout(&nul, op->op_buf, sizeof(char));
191 			break;
192 		}
193 		len = strlen(nextprop);
194 		if (len > op->op_buflen)
195 			len = op->op_buflen;
196 		else
197 			op->op_buflen = len;
198 		error = copyout(nextprop, op->op_buf, len);
199 		break;
200 
201 	case OPIOCGETNEXT:
202 		if ((flags & FREAD) == 0)
203 			return (EBADF);
204 		node = OF_peer(node);
205 		*(int *)data = lastnode = node;
206 		break;
207 
208 	case OPIOCGETCHILD:
209 		if ((flags & FREAD) == 0)
210 			return (EBADF);
211 		if (node == 0)
212 			return (EINVAL);
213 		node = OF_child(node);
214 		*(int *)data = lastnode = node;
215 		break;
216 
217 	default:
218 		return (ENOTTY);
219 	}
220 
221 	free(name, M_TEMP, 0);
222 	free(value, M_TEMP, 0);
223 
224 	return (error);
225 }
226