xref: /openbsd-src/sys/arch/macppc/macppc/openfirm.c (revision dcf4ae464a86e5db93d44470be68e8d1ed809829)
1 /*	$OpenBSD: openfirm.c,v 1.13 2020/04/02 19:27:51 gkoehler Exp $	*/
2 /*	$NetBSD: openfirm.c,v 1.1 1996/09/30 16:34:52 ws Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
6  * Copyright (C) 1995, 1996 TooLs GmbH.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by TooLs GmbH.
20  * 4. The name of TooLs GmbH may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/stdarg.h>
37 #include <machine/cpu.h>
38 #include <machine/psl.h>
39 
40 #include <dev/ofw/openfirm.h>
41 #include "ofw_machdep.h"
42 
43 extern void ofbcopy(const void *, void *, size_t);
44 
45 int
OF_peer(int phandle)46 OF_peer(int phandle)
47 {
48 	static struct {
49 		char *name;
50 		int nargs;
51 		int nreturns;
52 		int phandle;
53 		int sibling;
54 	} args = {
55 		"peer",
56 		1,
57 		1,
58 	};
59 	uint32_t s;
60 	int ret;
61 
62 	s = ofw_msr();
63 	args.phandle = phandle;
64 	if (openfirmware(&args) == -1)
65 		ret = 0;
66 	else
67 		ret = args.sibling;
68 	ppc_mtmsr(s);
69 	return ret;
70 }
71 
72 int
OF_child(int phandle)73 OF_child(int phandle)
74 {
75 	static struct {
76 		char *name;
77 		int nargs;
78 		int nreturns;
79 		int phandle;
80 		int child;
81 	} args = {
82 		"child",
83 		1,
84 		1,
85 	};
86 	uint32_t s;
87 	int ret;
88 
89 	s = ofw_msr();
90 	args.phandle = phandle;
91 	if (openfirmware(&args) == -1)
92 		ret = 0;
93 	else
94 		ret = args.child;
95 	ppc_mtmsr(s);
96 	return ret;
97 }
98 
99 int
OF_parent(int phandle)100 OF_parent(int phandle)
101 {
102 	static struct {
103 		char *name;
104 		int nargs;
105 		int nreturns;
106 		int phandle;
107 		int parent;
108 	} args = {
109 		"parent",
110 		1,
111 		1,
112 	};
113 	uint32_t s;
114 	int ret;
115 
116 	s = ofw_msr();
117 	args.phandle = phandle;
118 	if (openfirmware(&args) == -1)
119 		ret = 0;
120 	else
121 		ret = args.parent;
122 	ppc_mtmsr(s);
123 	return ret;
124 }
125 
126 int
OF_getproplen(int handle,char * prop)127 OF_getproplen(int handle, char *prop)
128 {
129 	static struct {
130 		char *name;
131 		int nargs;
132 		int nreturns;
133 		int phandle;
134 		char *prop;
135 		int size;
136 	} args = {
137 		"getproplen",
138 		2,
139 		1,
140 	};
141 	uint32_t s;
142 	int ret;
143 
144 	s = ofw_msr();
145 	args.phandle = handle;
146 	args.prop = prop;
147 	if (openfirmware(&args) == -1)
148 		ret = -1;
149 	else
150 		ret = args.size;
151 	ppc_mtmsr(s);
152 	return ret;
153 }
154 
155 int
OF_getprop(int handle,char * prop,void * buf,int buflen)156 OF_getprop(int handle, char *prop, void *buf, int buflen)
157 {
158 	static struct {
159 		char *name;
160 		int nargs;
161 		int nreturns;
162 		int phandle;
163 		char *prop;
164 		void *buf;
165 		int buflen;
166 		int size;
167 	} args = {
168 		"getprop",
169 		4,
170 		1,
171 	};
172 	uint32_t s;
173 	int ret;
174 
175 	if (buflen > NBPG)
176 		return -1;
177 	s = ofw_msr();
178 	args.phandle = handle;
179 	args.prop = prop;
180 	args.buf = OF_buf;
181 	args.buflen = buflen;
182 	if (openfirmware(&args) == -1)
183 		ret = -1;
184 	else {
185 		if (args.size > 0)
186 			ofbcopy(OF_buf, buf, args.size);
187 		ret = args.size;
188 	}
189 	ppc_mtmsr(s);
190 	return ret;
191 }
192 
193 int
OF_setprop(int handle,char * prop,const void * buf,int buflen)194 OF_setprop(int handle, char *prop, const void *buf, int buflen)
195 {
196 	static struct {
197 		char *name;
198 		int nargs;
199 		int nreturns;
200 		int phandle;
201 		char *prop;
202 		void *buf;
203 		int buflen;
204 		int size;
205 	} args = {
206 		"setprop",
207 		4,
208 		1,
209 	};
210 	uint32_t s;
211 	int ret;
212 
213 	if (buflen > NBPG)
214 		return -1;
215 	s = ofw_msr();
216 	args.phandle = handle;
217 	args.prop = prop;
218 	ofbcopy(buf, OF_buf, buflen);
219 	args.buf = OF_buf;
220 	args.buflen = buflen;
221 	if (openfirmware(&args) == -1)
222 		ret = -1;
223 	else
224 		ret = args.size;
225 	ppc_mtmsr(s);
226 	return ret;
227 }
228 
229 int
OF_nextprop(int handle,char * prop,void * nextprop)230 OF_nextprop(int handle, char *prop, void *nextprop)
231 {
232 	static struct {
233 		const char *name;
234 		int nargs;
235 		int nreturns;
236 		int phandle;
237 		const char *prop;
238 		char *buf;
239 		int flag;
240 	} args = {
241 		"nextprop",
242 		3,
243 		1,
244 	};
245 	uint32_t s;
246 	int ret;
247 
248 	s = ofw_msr();
249 	args.phandle = handle;
250 	args.prop = prop;
251 	args.buf = OF_buf;
252 	if (openfirmware(&args) == -1)
253 		ret = -1;
254 	else {
255 		strlcpy(nextprop, OF_buf, 32);
256 		ret = args.flag;
257 	}
258 	ppc_mtmsr(s);
259 	return ret;
260 }
261 
262 int
OF_interpret(char * cmd,int nreturns,...)263 OF_interpret(char *cmd, int nreturns, ...)
264 {
265 	va_list ap;
266 	static struct {
267 		char *name;
268 		int nargs;
269 		int nreturns;
270 		char *cmd;
271 		int status;
272 		int results[8];
273 	} args = {
274 		"interpret",
275 		1,
276 		2,
277 	};
278 	uint32_t s;
279 	int i, ret;
280 
281 	if (nreturns > 8)
282 		return -1;
283 	if ((i = strlen(cmd)) >= NBPG)
284 		return -1;
285 	s = ofw_msr();
286 	ofbcopy(cmd, OF_buf, i + 1);
287 	args.cmd = OF_buf;
288 	args.nargs = 1;
289 	args.nreturns = nreturns + 1;
290 	if (openfirmware(&args) == -1)
291 		ret = -1;
292 	else {
293 		va_start(ap, nreturns);
294 		for (i = 0; i < nreturns; i++)
295 			*va_arg(ap, int *) = args.results[i];
296 		va_end(ap);
297 		ret = args.status;
298 	}
299 	ppc_mtmsr(s);
300 	return ret;
301 }
302 
303 
304 int
OF_finddevice(char * name)305 OF_finddevice(char *name)
306 {
307 	static struct {
308 		char *name;
309 		int nargs;
310 		int nreturns;
311 		char *device;
312 		int phandle;
313 	} args = {
314 		"finddevice",
315 		1,
316 		1,
317 	};
318 	uint32_t s;
319 	int ret;
320 
321 	s = ofw_msr();
322 	args.device = name;
323 	if (openfirmware(&args) == -1)
324 		ret = -1;
325 	else
326 		ret = args.phandle;
327 	ppc_mtmsr(s);
328 	return ret;
329 }
330 static void OF_rboot(char *bootspec);
331 
332 static void
OF_rboot(char * bootspec)333 OF_rboot(char *bootspec)
334 {
335 	static struct {
336 		char *name;
337 		int nargs;
338 		int nreturns;
339 	} args = {
340 		"reset-all",
341 		0,
342 		0,
343 	};
344 	uint32_t s;
345 	int l;
346 
347 	if ((l = strlen(bootspec)) >= NBPG)
348 		panic("OF_boot");
349 	s = ofw_msr();
350 	openfirmware(&args);
351 	ppc_mtmsr(s);
352 	/* will attempt exit in OF_boot */
353 }
354 
355 
356 void
OF_boot(char * bootspec)357 OF_boot(char *bootspec)
358 {
359 	OF_rboot(bootspec);
360 	printf ("OF_boot returned!");		/* just in case */
361 	OF_exit();
362 	while(1);
363 }
364 
365 void
OF_exit(void)366 OF_exit(void)
367 {
368 	static struct {
369 		char *name;
370 		int nargs;
371 		int nreturns;
372 	} args = {
373 		"exit",
374 		0,
375 		0,
376 	};
377 
378 	ofw_msr();
379 	openfirmware(&args);
380 	panic ("OF_exit returned!");		/* just in case */
381 	while (1);
382 }
383 
384 void
OF_quiesce(void)385 OF_quiesce(void)
386 {
387 	static struct {
388 		const char *name;
389 		int nargs;
390 		int nreturns;
391 	} args = {
392 		"quiesce",
393 		0,
394 		0,
395 	};
396 	uint32_t s;
397 
398 	s = ofw_msr();
399 	openfirmware(&args);
400 	ppc_mtmsr(s);
401 }
402 
403 /* XXX What is the reason to have this instead of bcopy/memcpy? */
404 void
ofbcopy(const void * src,void * dst,size_t len)405 ofbcopy(const void *src, void *dst, size_t len)
406 {
407         const char *sp = src;
408         char *dp = dst;
409 
410         if (src == dst)
411                 return;
412 
413         while (len-- > 0)
414                 *dp++ = *sp++;
415 }
416 
417 int
OF_getnodebyname(int start,const char * name)418 OF_getnodebyname(int start, const char *name)
419 {
420 	char nname[32];
421 	int len;
422 	int node = 0;
423 	int next;
424 
425 	if (start == 0)
426 		start = OF_peer(0);
427 
428 	for (node = start; node; node = next) {
429 		len = OF_getprop(node, "name", nname, sizeof(nname));
430 		nname[len] = 0;
431 		if (strcmp(nname, name) == 0) {
432 			return node;
433 		}
434 		if ((next = OF_child(node)) != 0)
435 			continue;
436 		while (node) {
437 			if ((next = OF_peer(node)) != 0)
438 				break;
439 			node = OF_parent(node);
440 		}
441 	}
442 	return node;
443 }
444