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