xref: /freebsd/stand/libofw/openfirm.c (revision e453e498cbb88570a3ff7b3679de65c88707da95)
1 /*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $	*/
2 
3 /*-
4  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5  * Copyright (C) 1995, 1996 TooLs GmbH.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by TooLs GmbH.
19  * 4. The name of TooLs GmbH may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 /*-
34  * Copyright (C) 2000 Benno Rice.
35  * All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  *
46  * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
47  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
51  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
52  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
53  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
54  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
55  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56  */
57 
58 #include <sys/endian.h>
59 #include <sys/stdarg.h>
60 
61 #include <stand.h>
62 
63 #include "openfirm.h"
64 
65 int (*openfirmware)(void *);
66 
67 phandle_t chosen;
68 ihandle_t mmu;
69 ihandle_t memory;
70 int	  real_mode = 0;
71 
72 #define IN(x)		htobe32((cell_t)x)
73 #define OUT(x)		be32toh(x)
74 #define SETUP(a, b, c, d)		\
75 	a.name = IN( (b) );		\
76 	a.nargs = IN( (c) );		\
77 	a.nreturns = IN( (d) );
78 
79 /* Initialiser */
80 
81 void
OF_init(int (* openfirm)(void *))82 OF_init(int (*openfirm)(void *))
83 {
84 	phandle_t options;
85 	char	  mode[sizeof("true")];
86 
87 	openfirmware = openfirm;
88 
89 	if ((chosen = OF_finddevice("/chosen")) == -1)
90 		OF_exit();
91 	if (OF_getprop(chosen, "memory", &memory, sizeof(memory)) == -1) {
92 		memory = OF_open("/memory");
93 		if (memory == -1)
94 			memory = OF_open("/memory@0");
95 		if (memory == -1)
96 			OF_exit();
97 	}
98 	if (OF_getprop(chosen, "mmu", &mmu, sizeof(mmu)) == -1)
99 		OF_exit();
100 
101 	/*
102 	 * Check if we run in real mode. If so, we do not need to map
103 	 * memory later on.
104 	 */
105 	options = OF_finddevice("/options");
106 	if (OF_getprop(options, "real-mode?", mode, sizeof(mode)) > 0 &&
107 	    strcmp(mode, "true") == 0)
108 		real_mode = 1;
109 }
110 
111 /*
112  * Generic functions
113  */
114 
115 /* Test to see if a service exists. */
116 int
OF_test(char * name)117 OF_test(char *name)
118 {
119 	static struct {
120 		cell_t name;
121 		cell_t nargs;
122 		cell_t nreturns;
123 		cell_t service;
124 		cell_t missing;
125 	} args = {};
126 	SETUP(args, "test", 1, 1);
127 
128 	args.service = IN(name);
129 	if (openfirmware(&args) == -1)
130 		return (-1);
131 	return (OUT(args.missing));
132 }
133 
134 /* Return firmware millisecond count. */
135 int
OF_milliseconds(void)136 OF_milliseconds(void)
137 {
138 	static struct {
139 		cell_t name;
140 		cell_t nargs;
141 		cell_t nreturns;
142 		cell_t ms;
143 	} args = {};
144 	SETUP(args, "milliseconds", 0, 1);
145 
146 	openfirmware(&args);
147 	return (OUT(args.ms));
148 }
149 
150 /*
151  * Device tree functions
152  */
153 
154 /* Return the next sibling of this node or 0. */
155 phandle_t
OF_peer(phandle_t node)156 OF_peer(phandle_t node)
157 {
158 	static struct {
159 		cell_t name;
160 		cell_t nargs;
161 		cell_t nreturns;
162 		cell_t node;
163 		cell_t next;
164 	} args = {};
165 	SETUP(args, "peer", 1, 1);
166 
167 	args.node = node;
168 	if (openfirmware(&args) == -1)
169 		return (-1);
170 	return (args.next);
171 }
172 
173 /* Return the first child of this node or 0. */
174 phandle_t
OF_child(phandle_t node)175 OF_child(phandle_t node)
176 {
177 	static struct {
178 		cell_t name;
179 		cell_t nargs;
180 		cell_t nreturns;
181 		cell_t node;
182 		cell_t child;
183 	} args = {};
184 	SETUP(args, "child", 1, 1);
185 
186 	args.node = node;
187 	if (openfirmware(&args) == -1)
188 		return (-1);
189 	return (args.child);
190 }
191 
192 /* Return the parent of this node or 0. */
193 phandle_t
OF_parent(phandle_t node)194 OF_parent(phandle_t node)
195 {
196 	static struct {
197 		cell_t name;
198 		cell_t nargs;
199 		cell_t nreturns;
200 		cell_t node;
201 		cell_t parent;
202 	} args = {};
203 	SETUP(args, "parent", 1, 1);
204 
205 	args.node = node;
206 	if (openfirmware(&args) == -1)
207 		return (-1);
208 	return (args.parent);
209 }
210 
211 /* Return the package handle that corresponds to an instance handle. */
212 phandle_t
OF_instance_to_package(ihandle_t instance)213 OF_instance_to_package(ihandle_t instance)
214 {
215 	static struct {
216 		cell_t name;
217 		cell_t nargs;
218 		cell_t nreturns;
219 		cell_t instance;
220 		cell_t package;
221 	} args = {};
222 	SETUP(args, "instance-to-package", 1, 1);
223 
224 	args.instance = instance;
225 	if (openfirmware(&args) == -1)
226 		return (-1);
227 	return (args.package);
228 }
229 
230 /* Get the length of a property of a package. */
231 int
OF_getproplen(phandle_t package,const char * propname)232 OF_getproplen(phandle_t package, const char *propname)
233 {
234 	static struct {
235 		cell_t name;
236 		cell_t nargs;
237 		cell_t nreturns;
238 		cell_t package;
239 		cell_t propname;
240 		cell_t proplen;
241 	} args = {};
242 	SETUP(args, "getproplen", 2, 1);
243 
244 	args.package = package;
245 	args.propname = IN(propname);
246 	if (openfirmware(&args) == -1)
247 		return (-1);
248 	return (OUT(args.proplen));
249 }
250 
251 /* Get the value of a property of a package. */
252 int
OF_getprop(phandle_t package,const char * propname,void * buf,int buflen)253 OF_getprop(phandle_t package, const char *propname, void *buf, int buflen)
254 {
255 	static struct {
256 		cell_t name;
257 		cell_t nargs;
258 		cell_t nreturns;
259 		cell_t package;
260 		cell_t propname;
261 		cell_t buf;
262 		cell_t buflen;
263 		cell_t size;
264 	} args = {};
265 	SETUP(args, "getprop", 4, 1);
266 
267 	args.package = package;
268 	args.propname = IN(propname);
269 	args.buf = IN(buf);
270 	args.buflen = IN(buflen);
271 	if (openfirmware(&args) == -1)
272 		return (-1);
273 	return (OUT(args.size));
274 }
275 
276 /* Decode a binary property from a package. */
277 int
OF_getencprop(phandle_t package,const char * propname,cell_t * buf,int buflen)278 OF_getencprop(phandle_t package, const char *propname, cell_t *buf, int buflen)
279 {
280 	int retval, i;
281 	retval = OF_getprop(package, propname, buf, buflen);
282 	if (retval == -1)
283 		return (retval);
284 
285 	for (i = 0; i < buflen/4; i++)
286 		buf[i] = be32toh((uint32_t)buf[i]);
287 
288 	return (retval);
289 }
290 
291 /* Get the next property of a package. */
292 int
OF_nextprop(phandle_t package,const char * previous,char * buf)293 OF_nextprop(phandle_t package, const char *previous, char *buf)
294 {
295 	static struct {
296 		cell_t name;
297 		cell_t nargs;
298 		cell_t nreturns;
299 		cell_t package;
300 		cell_t previous;
301 		cell_t buf;
302 		cell_t flag;
303 	} args = {};
304 	SETUP(args, "nextprop", 3, 1);
305 
306 	args.package = package;
307 	args.previous = IN(previous);
308 	args.buf = IN(buf);
309 	if (openfirmware(&args) == -1)
310 		return (-1);
311 	return (OUT(args.flag));
312 }
313 
314 /* Set the value of a property of a package. */
315 /* XXX Has a bug on FirePower */
316 int
OF_setprop(phandle_t package,const char * propname,void * buf,int len)317 OF_setprop(phandle_t package, const char *propname, void *buf, int len)
318 {
319 	static struct {
320 		cell_t name;
321 		cell_t nargs;
322 		cell_t nreturns;
323 		cell_t package;
324 		cell_t propname;
325 		cell_t buf;
326 		cell_t len;
327 		cell_t size;
328 	} args = {};
329 	SETUP(args, "setprop", 4, 1);
330 
331 	args.package = package;
332 	args.propname = IN(propname);
333 	args.buf = IN(buf);
334 	args.len = IN(len);
335 	if (openfirmware(&args) == -1)
336 		return (-1);
337 	return (OUT(args.size));
338 }
339 
340 /* Convert a device specifier to a fully qualified pathname. */
341 int
OF_canon(const char * device,char * buf,int len)342 OF_canon(const char *device, char *buf, int len)
343 {
344 	static struct {
345 		cell_t name;
346 		cell_t nargs;
347 		cell_t nreturns;
348 		cell_t device;
349 		cell_t buf;
350 		cell_t len;
351 		cell_t size;
352 	} args = {};
353 	SETUP(args, "canon", 3, 1);
354 
355 	args.device = IN(device);
356 	args.buf = IN(buf);
357 	args.len = IN(len);
358 	if (openfirmware(&args) == -1)
359 		return (-1);
360 	return (OUT(args.size));
361 }
362 
363 /* Return a package handle for the specified device. */
364 phandle_t
OF_finddevice(const char * device)365 OF_finddevice(const char *device)
366 {
367 	static struct {
368 		cell_t name;
369 		cell_t nargs;
370 		cell_t nreturns;
371 		cell_t device;
372 		cell_t package;
373 	} args = {};
374 	SETUP(args, "finddevice", 1, 1);
375 
376 	args.device = IN(device);
377 	if (openfirmware(&args) == -1)
378 		return (-1);
379 	return (args.package);
380 }
381 
382 /* Return the fully qualified pathname corresponding to an instance. */
383 int
OF_instance_to_path(ihandle_t instance,char * buf,int len)384 OF_instance_to_path(ihandle_t instance, char *buf, int len)
385 {
386 	static struct {
387 		cell_t name;
388 		cell_t nargs;
389 		cell_t nreturns;
390 		cell_t instance;
391 		cell_t buf;
392 		cell_t len;
393 		cell_t size;
394 	} args = {};
395 	SETUP(args, "instance-to-path", 3, 1);
396 
397 	args.instance = instance;
398 	args.buf = IN(buf);
399 	args.len = IN(len);
400 	if (openfirmware(&args) == -1)
401 		return (-1);
402 	return (OUT(args.size));
403 }
404 
405 /* Return the fully qualified pathname corresponding to a package. */
406 int
OF_package_to_path(phandle_t package,char * buf,int len)407 OF_package_to_path(phandle_t package, char *buf, int len)
408 {
409 	static struct {
410 		cell_t name;
411 		cell_t nargs;
412 		cell_t nreturns;
413 		cell_t package;
414 		cell_t buf;
415 		cell_t len;
416 		cell_t size;
417 	} args = {};
418 	SETUP(args, "package-to-path", 3, 1);
419 
420 	args.package = package;
421 	args.buf = IN(buf);
422 	args.len = IN(len);
423 	if (openfirmware(&args) == -1)
424 		return (-1);
425 	return (OUT(args.size));
426 }
427 
428 /*  Call the method in the scope of a given instance. */
429 int
OF_call_method(char * method,ihandle_t instance,int nargs,int nreturns,...)430 OF_call_method(char *method, ihandle_t instance, int nargs, int nreturns, ...)
431 {
432 	va_list ap;
433 	static struct {
434 		cell_t name;
435 		cell_t nargs;
436 		cell_t nreturns;
437 		cell_t method;
438 		cell_t instance;
439 		cell_t args_n_results[12];
440 	} args = {};
441 	SETUP(args, "call-method", nargs + 2, nreturns + 1);
442 	cell_t *cp;
443 	int n;
444 
445 	if (nargs > 6)
446 		return (-1);
447 	args.method = IN(method);
448 	args.instance = instance;
449 	va_start(ap, nreturns);
450 	for (cp = (cell_t *)(args.args_n_results + (n = nargs)); --n >= 0;)
451 		*--cp = IN(va_arg(ap, cell_t));
452 	if (openfirmware(&args) == -1)
453 		return (-1);
454 	if (args.args_n_results[nargs])
455 		return (OUT(args.args_n_results[nargs]));
456 	/* XXX what if ihandles or phandles are returned */
457 	for (cp = (cell_t *)(args.args_n_results + nargs +
458 	    (n = be32toh(args.nreturns))); --n > 0;)
459 		*va_arg(ap, cell_t *) = OUT(*--cp);
460 	va_end(ap);
461 	return (0);
462 }
463 
464 /*
465  * Device I/O functions
466  */
467 
468 /* Open an instance for a device. */
469 ihandle_t
OF_open(char * device)470 OF_open(char *device)
471 {
472 	static struct {
473 		cell_t name;
474 		cell_t nargs;
475 		cell_t nreturns;
476 		cell_t device;
477 		cell_t instance;
478 	} args = {};
479 	SETUP(args, "open", 1, 1);
480 
481 	args.device = IN(device);
482 	if (openfirmware(&args) == -1 || args.instance == 0) {
483 		return (-1);
484 	}
485 	return (args.instance);
486 }
487 
488 /* Close an instance. */
489 void
OF_close(ihandle_t instance)490 OF_close(ihandle_t instance)
491 {
492 	static struct {
493 		cell_t name;
494 		cell_t nargs;
495 		cell_t nreturns;
496 		cell_t instance;
497 	} args = {};
498 	SETUP(args, "close", 1, 0);
499 
500 	args.instance = instance;
501 	openfirmware(&args);
502 }
503 
504 /* Read from an instance. */
505 int
OF_read(ihandle_t instance,void * addr,int len)506 OF_read(ihandle_t instance, void *addr, int len)
507 {
508 	static struct {
509 		cell_t name;
510 		cell_t nargs;
511 		cell_t nreturns;
512 		cell_t instance;
513 		cell_t addr;
514 		cell_t len;
515 		cell_t actual;
516 	} args = {};
517 	SETUP(args, "read", 3, 1);
518 
519 	args.instance = instance;
520 	args.addr = IN(addr);
521 	args.len = IN(len);
522 
523 #if defined(OPENFIRM_DEBUG)
524 	printf("OF_read: called with instance=%08x, addr=%p, len=%d\n",
525 	    instance, addr, len);
526 #endif
527 
528 	if (openfirmware(&args) == -1)
529 		return (-1);
530 
531 #if defined(OPENFIRM_DEBUG)
532 	printf("OF_read: returning instance=%d, addr=%p, len=%d, actual=%d\n",
533 	    args.instance, OUT(args.addr), OUT(args.len), OUT(args.actual));
534 #endif
535 
536 	return (OUT(args.actual));
537 }
538 
539 /* Write to an instance. */
540 int
OF_write(ihandle_t instance,void * addr,int len)541 OF_write(ihandle_t instance, void *addr, int len)
542 {
543 	static struct {
544 		cell_t name;
545 		cell_t nargs;
546 		cell_t nreturns;
547 		cell_t instance;
548 		cell_t addr;
549 		cell_t len;
550 		cell_t actual;
551 	} args = {};
552 	SETUP(args, "write", 3, 1);
553 
554 	args.instance = instance;
555 	args.addr = IN(addr);
556 	args.len = IN(len);
557 	if (openfirmware(&args) == -1)
558 		return (-1);
559 	return (OUT(args.actual));
560 }
561 
562 /* Seek to a position. */
563 int
OF_seek(ihandle_t instance,uint64_t pos)564 OF_seek(ihandle_t instance, uint64_t pos)
565 {
566 	static struct {
567 		cell_t name;
568 		cell_t nargs;
569 		cell_t nreturns;
570 		cell_t instance;
571 		cell_t poshi;
572 		cell_t poslo;
573 		cell_t status;
574 	} args = {};
575 	SETUP(args, "seek", 3, 1);
576 
577 	args.instance = instance;
578 	args.poshi = IN(((uint64_t)pos >> 32));
579 	args.poslo = IN(pos);
580 	if (openfirmware(&args) == -1)
581 		return (-1);
582 	return (OUT(args.status));
583 }
584 
585 /* Blocks. */
586 unsigned int
OF_blocks(ihandle_t instance)587 OF_blocks(ihandle_t instance)
588 {
589 	static struct {
590 		cell_t name;
591 		cell_t nargs;
592 		cell_t nreturns;
593 		cell_t instance;
594 		cell_t result;
595 		cell_t blocks;
596 	} args = {};
597 	SETUP(args, "#blocks", 2, 1);
598 
599 	args.instance = instance;
600 	if (openfirmware(&args) == -1)
601 		return ((unsigned int)-1);
602 	return (OUT(args.blocks));
603 }
604 
605 /* Block size. */
606 int
OF_block_size(ihandle_t instance)607 OF_block_size(ihandle_t instance)
608 {
609 	static struct {
610 		cell_t name;
611 		cell_t nargs;
612 		cell_t nreturns;
613 		cell_t instance;
614 		cell_t result;
615 		cell_t size;
616 	} args = {};
617 	SETUP(args, "block-size", 2, 1);
618 
619 	args.instance = instance;
620 	if (openfirmware(&args) == -1)
621 		return (512);
622 	return (OUT(args.size));
623 }
624 
625 /*
626  * Memory functions
627  */
628 
629 /* Claim an area of memory. */
630 void *
OF_claim(void * virt,u_int size,u_int align)631 OF_claim(void *virt, u_int size, u_int align)
632 {
633 	static struct {
634 		cell_t name;
635 		cell_t nargs;
636 		cell_t nreturns;
637 		cell_t virt;
638 		cell_t size;
639 		cell_t align;
640 		cell_t baseaddr;
641 	} args = {};
642 	SETUP(args, "claim", 3, 1);
643 
644 	args.virt = IN(virt);
645 	args.size = IN(size);
646 	args.align = IN(align);
647 	if (openfirmware(&args) == -1)
648 		return ((void *)-1);
649 	return ((void *)OUT(args.baseaddr));
650 }
651 
652 /* Release an area of memory. */
653 void
OF_release(void * virt,u_int size)654 OF_release(void *virt, u_int size)
655 {
656 	static struct {
657 		cell_t name;
658 		cell_t nargs;
659 		cell_t nreturns;
660 		cell_t virt;
661 		cell_t size;
662 	} args = {};
663 	SETUP(args, "release", 2, 0);
664 
665 	args.virt = IN(virt);
666 	args.size = IN(size);
667 	openfirmware(&args);
668 }
669 
670 /*
671  * Control transfer functions
672  */
673 
674 /* Reset the system and call "boot <bootspec>". */
675 void
OF_boot(char * bootspec)676 OF_boot(char *bootspec)
677 {
678 	static struct {
679 		cell_t name;
680 		cell_t nargs;
681 		cell_t nreturns;
682 		cell_t bootspec;
683 	} args = {};
684 	SETUP(args, "boot", 1, 0);
685 
686 	args.bootspec = IN(bootspec);
687 	openfirmware(&args);
688 	for (;;)			/* just in case */
689 		;
690 }
691 
692 /* Suspend and drop back to the Open Firmware interface. */
693 void
OF_enter(void)694 OF_enter(void)
695 {
696 	static struct {
697 		cell_t name;
698 		cell_t nargs;
699 		cell_t nreturns;
700 	} args = {};
701 	SETUP(args, "enter", 0, 0);
702 
703 	openfirmware(&args);
704 	/* We may come back. */
705 }
706 
707 /* Shut down and drop back to the Open Firmware interface. */
708 void
OF_exit(void)709 OF_exit(void)
710 {
711 	static struct {
712 		cell_t name;
713 		cell_t nargs;
714 		cell_t nreturns;
715 	} args = {};
716 	SETUP(args, "exit", 0, 0);
717 
718 	openfirmware(&args);
719 	for (;;)			/* just in case */
720 		;
721 }
722 
723 void
OF_quiesce(void)724 OF_quiesce(void)
725 {
726 	static struct {
727 		cell_t name;
728 		cell_t nargs;
729 		cell_t nreturns;
730 	} args = {};
731 	SETUP(args, "quiesce", 0, 0);
732 
733 	openfirmware(&args);
734 }
735 
736 /* Free <size> bytes starting at <virt>, then call <entry> with <arg>. */
737 #if 0
738 void
739 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
740 {
741 	static struct {
742 		cell_t name;
743 		cell_t nargs;
744 		cell_t nreturns;
745 		cell_t virt;
746 		cell_t size;
747 		cell_t entry;
748 		cell_t arg;
749 		cell_t len;
750 	} args = {};
751 	SETUP(args, "chain", 5, 0);
752 
753 	args.virt = IN(virt);
754 	args.size = IN(size);
755 	args.entry = IN(entry);
756 	args.arg = IN(arg);
757 	args.len = IN(len);
758 	openfirmware(&args);
759 }
760 #else
761 void
OF_chain(void * virt,u_int size,void (* entry)(),void * arg,u_int len)762 OF_chain(void *virt, u_int size, void (*entry)(), void *arg, u_int len)
763 {
764 	/*
765 	 * This is a REALLY dirty hack till the firmware gets this going
766 	 */
767 #if 0
768 	if (size > 0)
769 		OF_release(virt, size);
770 #endif
771 	((int (*)(u_long, u_long, u_long, void *, u_long))entry)
772 	    (0, 0, (u_long)openfirmware, arg, len);
773 }
774 #endif
775