1/*	$NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $	*/
2
3/*-
4 * SPDX-License-Identifier: BSD-4-Clause
5 *
6 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
7 * Copyright (C) 1995, 1996 TooLs GmbH.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed by TooLs GmbH.
21 * 4. The name of TooLs GmbH may not be used to endorse or promote products
22 *    derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
30 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
33 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35/*-
36 * Copyright (C) 2000 Benno Rice.
37 * All rights reserved.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 *    notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 *    notice, this list of conditions and the following disclaimer in the
46 *    documentation and/or other materials provided with the distribution.
47 *
48 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
49 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
50 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
53 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
54 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
55 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
56 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
57 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 */
59
60#include <sys/cdefs.h>
61#include "opt_platform.h"
62
63#include <sys/param.h>
64#include <sys/kernel.h>
65#include <sys/lock.h>
66#include <sys/malloc.h>
67#include <sys/mutex.h>
68#include <sys/queue.h>
69#include <sys/systm.h>
70#include <sys/endian.h>
71
72#include <machine/stdarg.h>
73
74#include <dev/ofw/ofwvar.h>
75#include <dev/ofw/openfirm.h>
76
77#include "ofw_if.h"
78
79static void OF_putchar(int c, void *arg);
80
81MALLOC_DEFINE(M_OFWPROP, "openfirm", "Open Firmware properties");
82
83static ihandle_t stdout;
84
85static ofw_def_t	*ofw_def_impl = NULL;
86static ofw_t		ofw_obj;
87static struct ofw_kobj	ofw_kernel_obj;
88static struct kobj_ops	ofw_kernel_kops;
89
90struct xrefinfo {
91	phandle_t	xref;
92	phandle_t 	node;
93	device_t  	dev;
94	SLIST_ENTRY(xrefinfo) next_entry;
95};
96
97static SLIST_HEAD(, xrefinfo) xreflist = SLIST_HEAD_INITIALIZER(xreflist);
98static struct mtx xreflist_lock;
99static boolean_t xref_init_done;
100
101#define	FIND_BY_XREF	0
102#define	FIND_BY_NODE	1
103#define	FIND_BY_DEV	2
104
105/*
106 * xref-phandle-device lookup helper routines.
107 *
108 * As soon as we are able to use malloc(), walk the node tree and build a list
109 * of info that cross-references node handles, xref handles, and device_t
110 * instances.  This list exists primarily to allow association of a device_t
111 * with an xref handle, but it is also used to speed up translation between xref
112 * and node handles.  Before malloc() is available we have to recursively search
113 * the node tree each time we want to translate between a node and xref handle.
114 * Afterwards we can do the translations by searching this much shorter list.
115 */
116static void
117xrefinfo_create(phandle_t node)
118{
119	struct xrefinfo * xi;
120	phandle_t child, xref;
121
122	/*
123	 * Recursively descend from parent, looking for nodes with a property
124	 * named either "phandle", "ibm,phandle", or "linux,phandle".  For each
125	 * such node found create an entry in the xreflist.
126	 */
127	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
128		xrefinfo_create(child);
129		if (OF_getencprop(child, "phandle", &xref, sizeof(xref)) ==
130		    -1 && OF_getencprop(child, "ibm,phandle", &xref,
131		    sizeof(xref)) == -1 && OF_getencprop(child,
132		    "linux,phandle", &xref, sizeof(xref)) == -1)
133			continue;
134		xi = malloc(sizeof(*xi), M_OFWPROP, M_WAITOK | M_ZERO);
135		xi->node = child;
136		xi->xref = xref;
137		SLIST_INSERT_HEAD(&xreflist, xi, next_entry);
138	}
139}
140
141static void
142xrefinfo_init(void *unsed)
143{
144
145	/*
146	 * There is no locking during this init because it runs much earlier
147	 * than any of the clients/consumers of the xref list data, but we do
148	 * initialize the mutex that will be used for access later.
149	 */
150	mtx_init(&xreflist_lock, "OF xreflist lock", NULL, MTX_DEF);
151	xrefinfo_create(OF_peer(0));
152	xref_init_done = true;
153}
154SYSINIT(xrefinfo, SI_SUB_KMEM, SI_ORDER_ANY, xrefinfo_init, NULL);
155
156static struct xrefinfo *
157xrefinfo_find(uintptr_t key, int find_by)
158{
159	struct xrefinfo *rv, *xi;
160
161	rv = NULL;
162	mtx_lock(&xreflist_lock);
163	SLIST_FOREACH(xi, &xreflist, next_entry) {
164		if ((find_by == FIND_BY_XREF && (phandle_t)key == xi->xref) ||
165		    (find_by == FIND_BY_NODE && (phandle_t)key == xi->node) ||
166		    (find_by == FIND_BY_DEV && key == (uintptr_t)xi->dev)) {
167			rv = xi;
168			break;
169		}
170	}
171	mtx_unlock(&xreflist_lock);
172	return (rv);
173}
174
175static struct xrefinfo *
176xrefinfo_add(phandle_t node, phandle_t xref, device_t dev)
177{
178	struct xrefinfo *xi;
179
180	xi = malloc(sizeof(*xi), M_OFWPROP, M_WAITOK);
181	xi->node = node;
182	xi->xref = xref;
183	xi->dev  = dev;
184	mtx_lock(&xreflist_lock);
185	SLIST_INSERT_HEAD(&xreflist, xi, next_entry);
186	mtx_unlock(&xreflist_lock);
187	return (xi);
188}
189
190/*
191 * OFW install routines.  Highest priority wins, equal priority also
192 * overrides allowing last-set to win.
193 */
194SET_DECLARE(ofw_set, ofw_def_t);
195
196boolean_t
197OF_install(char *name, int prio)
198{
199	ofw_def_t *ofwp, **ofwpp;
200	static int curr_prio = 0;
201
202	/* Allow OF layer to be uninstalled */
203	if (name == NULL) {
204		ofw_def_impl = NULL;
205		return (FALSE);
206	}
207
208	/*
209	 * Try and locate the OFW kobj corresponding to the name.
210	 */
211	SET_FOREACH(ofwpp, ofw_set) {
212		ofwp = *ofwpp;
213
214		if (ofwp->name &&
215		    !strcmp(ofwp->name, name) &&
216		    prio >= curr_prio) {
217			curr_prio = prio;
218			ofw_def_impl = ofwp;
219			return (TRUE);
220		}
221	}
222
223	return (FALSE);
224}
225
226/* Initializer */
227int
228OF_init(void *cookie)
229{
230	phandle_t chosen;
231	int rv;
232
233	if (ofw_def_impl == NULL)
234		return (-1);
235
236	ofw_obj = &ofw_kernel_obj;
237	/*
238	 * Take care of compiling the selected class, and
239	 * then statically initialize the OFW object.
240	 */
241	kobj_class_compile_static(ofw_def_impl, &ofw_kernel_kops);
242	kobj_init_static((kobj_t)ofw_obj, ofw_def_impl);
243
244	rv = OFW_INIT(ofw_obj, cookie);
245
246	if ((chosen = OF_finddevice("/chosen")) != -1)
247		if (OF_getencprop(chosen, "stdout", &stdout,
248		    sizeof(stdout)) == -1)
249			stdout = -1;
250
251	return (rv);
252}
253
254static void
255OF_putchar(int c, void *arg __unused)
256{
257	char cbuf;
258
259	if (c == '\n') {
260		cbuf = '\r';
261		OF_write(stdout, &cbuf, 1);
262	}
263
264	cbuf = c;
265	OF_write(stdout, &cbuf, 1);
266}
267
268void
269OF_printf(const char *fmt, ...)
270{
271	va_list	va;
272
273	va_start(va, fmt);
274	(void)kvprintf(fmt, OF_putchar, NULL, 10, va);
275	va_end(va);
276}
277
278/*
279 * Generic functions
280 */
281
282/* Test to see if a service exists. */
283int
284OF_test(const char *name)
285{
286
287	if (ofw_def_impl == NULL)
288		return (-1);
289
290	return (OFW_TEST(ofw_obj, name));
291}
292
293int
294OF_interpret(const char *cmd, int nreturns, ...)
295{
296	va_list ap;
297	cell_t slots[16];
298	int i = 0;
299	int status;
300
301	if (ofw_def_impl == NULL)
302		return (-1);
303
304	status = OFW_INTERPRET(ofw_obj, cmd, nreturns, slots);
305	if (status == -1)
306		return (status);
307
308	va_start(ap, nreturns);
309	while (i < nreturns)
310		*va_arg(ap, cell_t *) = slots[i++];
311	va_end(ap);
312
313	return (status);
314}
315
316/*
317 * Device tree functions
318 */
319
320/* Return the next sibling of this node or 0. */
321phandle_t
322OF_peer(phandle_t node)
323{
324
325	if (ofw_def_impl == NULL)
326		return (0);
327
328	return (OFW_PEER(ofw_obj, node));
329}
330
331/* Return the first child of this node or 0. */
332phandle_t
333OF_child(phandle_t node)
334{
335
336	if (ofw_def_impl == NULL)
337		return (0);
338
339	return (OFW_CHILD(ofw_obj, node));
340}
341
342/* Return the parent of this node or 0. */
343phandle_t
344OF_parent(phandle_t node)
345{
346
347	if (ofw_def_impl == NULL)
348		return (0);
349
350	return (OFW_PARENT(ofw_obj, node));
351}
352
353/* Return the package handle that corresponds to an instance handle. */
354phandle_t
355OF_instance_to_package(ihandle_t instance)
356{
357
358	if (ofw_def_impl == NULL)
359		return (-1);
360
361	return (OFW_INSTANCE_TO_PACKAGE(ofw_obj, instance));
362}
363
364/* Get the length of a property of a package. */
365ssize_t
366OF_getproplen(phandle_t package, const char *propname)
367{
368
369	if (ofw_def_impl == NULL)
370		return (-1);
371
372	return (OFW_GETPROPLEN(ofw_obj, package, propname));
373}
374
375/* Check existence of a property of a package. */
376int
377OF_hasprop(phandle_t package, const char *propname)
378{
379
380	return (OF_getproplen(package, propname) >= 0 ? 1 : 0);
381}
382
383/* Get the value of a property of a package. */
384ssize_t
385OF_getprop(phandle_t package, const char *propname, void *buf, size_t buflen)
386{
387
388	if (ofw_def_impl == NULL)
389		return (-1);
390
391	return (OFW_GETPROP(ofw_obj, package, propname, buf, buflen));
392}
393
394ssize_t
395OF_getencprop(phandle_t node, const char *propname, pcell_t *buf, size_t len)
396{
397	ssize_t retval;
398	int i;
399
400	KASSERT(len % 4 == 0, ("Need a multiple of 4 bytes"));
401
402	retval = OF_getprop(node, propname, buf, len);
403	if (retval <= 0)
404		return (retval);
405
406	for (i = 0; i < len/4; i++)
407		buf[i] = be32toh(buf[i]);
408
409	return (retval);
410}
411
412/*
413 * Recursively search the node and its parent for the given property, working
414 * downward from the node to the device tree root.  Returns the value of the
415 * first match.
416 */
417ssize_t
418OF_searchprop(phandle_t node, const char *propname, void *buf, size_t len)
419{
420	ssize_t rv;
421
422	for (; node != 0; node = OF_parent(node))
423		if ((rv = OF_getprop(node, propname, buf, len)) != -1)
424			return (rv);
425	return (-1);
426}
427
428ssize_t
429OF_searchencprop(phandle_t node, const char *propname, pcell_t *buf, size_t len)
430{
431	ssize_t rv;
432
433	for (; node != 0; node = OF_parent(node))
434		if ((rv = OF_getencprop(node, propname, buf, len)) != -1)
435			return (rv);
436	return (-1);
437}
438
439/*
440 * Store the value of a property of a package into newly allocated memory
441 * (using the M_OFWPROP malloc pool and M_WAITOK).
442 */
443ssize_t
444OF_getprop_alloc(phandle_t package, const char *propname, void **buf)
445{
446	int len;
447
448	*buf = NULL;
449	if ((len = OF_getproplen(package, propname)) == -1)
450		return (-1);
451
452	if (len > 0) {
453		*buf = malloc(len, M_OFWPROP, M_WAITOK);
454		if (OF_getprop(package, propname, *buf, len) == -1) {
455			free(*buf, M_OFWPROP);
456			*buf = NULL;
457			return (-1);
458		}
459	}
460	return (len);
461}
462
463/*
464 * Store the value of a property of a package into newly allocated memory
465 * (using the M_OFWPROP malloc pool and M_WAITOK).  elsz is the size of a
466 * single element, the number of elements is return in number.
467 */
468ssize_t
469OF_getprop_alloc_multi(phandle_t package, const char *propname, int elsz, void **buf)
470{
471	int len;
472
473	*buf = NULL;
474	if ((len = OF_getproplen(package, propname)) == -1 ||
475	    len % elsz != 0)
476		return (-1);
477
478	if (len > 0) {
479		*buf = malloc(len, M_OFWPROP, M_WAITOK);
480		if (OF_getprop(package, propname, *buf, len) == -1) {
481			free(*buf, M_OFWPROP);
482			*buf = NULL;
483			return (-1);
484		}
485	}
486	return (len / elsz);
487}
488
489ssize_t
490OF_getencprop_alloc(phandle_t package, const char *name, void **buf)
491{
492	ssize_t ret;
493
494	ret = OF_getencprop_alloc_multi(package, name, sizeof(pcell_t),
495	    buf);
496	if (ret < 0)
497		return (ret);
498	else
499		return (ret * sizeof(pcell_t));
500}
501
502ssize_t
503OF_getencprop_alloc_multi(phandle_t package, const char *name, int elsz,
504    void **buf)
505{
506	ssize_t retval;
507	pcell_t *cell;
508	int i;
509
510	retval = OF_getprop_alloc_multi(package, name, elsz, buf);
511	if (retval == -1)
512		return (-1);
513
514	cell = *buf;
515	for (i = 0; i < retval * elsz / 4; i++)
516		cell[i] = be32toh(cell[i]);
517
518	return (retval);
519}
520
521/* Free buffer allocated by OF_getencprop_alloc or OF_getprop_alloc */
522void OF_prop_free(void *buf)
523{
524
525	free(buf, M_OFWPROP);
526}
527
528/* Get the next property of a package. */
529int
530OF_nextprop(phandle_t package, const char *previous, char *buf, size_t size)
531{
532
533	if (ofw_def_impl == NULL)
534		return (-1);
535
536	return (OFW_NEXTPROP(ofw_obj, package, previous, buf, size));
537}
538
539/* Set the value of a property of a package. */
540int
541OF_setprop(phandle_t package, const char *propname, const void *buf, size_t len)
542{
543
544	if (ofw_def_impl == NULL)
545		return (-1);
546
547	return (OFW_SETPROP(ofw_obj, package, propname, buf,len));
548}
549
550/* Convert a device specifier to a fully qualified pathname. */
551ssize_t
552OF_canon(const char *device, char *buf, size_t len)
553{
554
555	if (ofw_def_impl == NULL)
556		return (-1);
557
558	return (OFW_CANON(ofw_obj, device, buf, len));
559}
560
561/* Return a package handle for the specified device. */
562phandle_t
563OF_finddevice(const char *device)
564{
565
566	if (ofw_def_impl == NULL)
567		return (-1);
568
569	return (OFW_FINDDEVICE(ofw_obj, device));
570}
571
572/* Return the fully qualified pathname corresponding to an instance. */
573ssize_t
574OF_instance_to_path(ihandle_t instance, char *buf, size_t len)
575{
576
577	if (ofw_def_impl == NULL)
578		return (-1);
579
580	return (OFW_INSTANCE_TO_PATH(ofw_obj, instance, buf, len));
581}
582
583/* Return the fully qualified pathname corresponding to a package. */
584ssize_t
585OF_package_to_path(phandle_t package, char *buf, size_t len)
586{
587
588	if (ofw_def_impl == NULL)
589		return (-1);
590
591	return (OFW_PACKAGE_TO_PATH(ofw_obj, package, buf, len));
592}
593
594/* Look up effective phandle (see FDT/PAPR spec) */
595static phandle_t
596OF_child_xref_phandle(phandle_t parent, phandle_t xref)
597{
598	phandle_t child, rxref;
599
600	/*
601	 * Recursively descend from parent, looking for a node with a property
602	 * named either "phandle", "ibm,phandle", or "linux,phandle" that
603	 * matches the xref we are looking for.
604	 */
605
606	for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
607		rxref = OF_child_xref_phandle(child, xref);
608		if (rxref != -1)
609			return (rxref);
610
611		if (OF_getencprop(child, "phandle", &rxref, sizeof(rxref)) ==
612		    -1 && OF_getencprop(child, "ibm,phandle", &rxref,
613		    sizeof(rxref)) == -1 && OF_getencprop(child,
614		    "linux,phandle", &rxref, sizeof(rxref)) == -1)
615			continue;
616
617		if (rxref == xref)
618			return (child);
619	}
620
621	return (-1);
622}
623
624phandle_t
625OF_node_from_xref(phandle_t xref)
626{
627	struct xrefinfo *xi;
628	phandle_t node;
629
630	if (xref_init_done) {
631		if ((xi = xrefinfo_find(xref, FIND_BY_XREF)) == NULL)
632			return (xref);
633		return (xi->node);
634	}
635
636	if ((node = OF_child_xref_phandle(OF_peer(0), xref)) == -1)
637		return (xref);
638	return (node);
639}
640
641phandle_t
642OF_xref_from_node(phandle_t node)
643{
644	struct xrefinfo *xi;
645	phandle_t xref;
646
647	if (xref_init_done) {
648		if ((xi = xrefinfo_find(node, FIND_BY_NODE)) == NULL)
649			return (node);
650		return (xi->xref);
651	}
652
653	if (OF_getencprop(node, "phandle", &xref, sizeof(xref)) == -1 &&
654	    OF_getencprop(node, "ibm,phandle", &xref, sizeof(xref)) == -1 &&
655	    OF_getencprop(node, "linux,phandle", &xref, sizeof(xref)) == -1)
656		return (node);
657	return (xref);
658}
659
660device_t
661OF_device_from_xref(phandle_t xref)
662{
663	struct xrefinfo *xi;
664
665	if (xref_init_done) {
666		if ((xi = xrefinfo_find(xref, FIND_BY_XREF)) == NULL)
667			return (NULL);
668		return (xi->dev);
669	}
670	panic("Attempt to find device before xreflist_init");
671}
672
673phandle_t
674OF_xref_from_device(device_t dev)
675{
676	struct xrefinfo *xi;
677
678	if (xref_init_done) {
679		if ((xi = xrefinfo_find((uintptr_t)dev, FIND_BY_DEV)) == NULL)
680			return (0);
681		return (xi->xref);
682	}
683	panic("Attempt to find xref before xreflist_init");
684}
685
686int
687OF_device_register_xref(phandle_t xref, device_t dev)
688{
689	struct xrefinfo *xi;
690
691	/*
692	 * If the given xref handle doesn't already exist in the list then we
693	 * add a list entry.  In theory this can only happen on a system where
694	 * nodes don't contain phandle properties and xref and node handles are
695	 * synonymous, so the xref handle is added as the node handle as well.
696	 */
697	if (xref_init_done) {
698		if ((xi = xrefinfo_find(xref, FIND_BY_XREF)) == NULL)
699			xrefinfo_add(xref, xref, dev);
700		else
701			xi->dev = dev;
702		return (0);
703	}
704	panic("Attempt to register device before xreflist_init");
705}
706
707/*  Call the method in the scope of a given instance. */
708int
709OF_call_method(const char *method, ihandle_t instance, int nargs, int nreturns,
710    ...)
711{
712	va_list ap;
713	cell_t args_n_results[12];
714	int n, status;
715
716	if (nargs > 6 || ofw_def_impl == NULL)
717		return (-1);
718	va_start(ap, nreturns);
719	for (n = 0; n < nargs; n++)
720		args_n_results[n] = va_arg(ap, cell_t);
721
722	status = OFW_CALL_METHOD(ofw_obj, instance, method, nargs, nreturns,
723	    args_n_results);
724	if (status != 0)
725		return (status);
726
727	for (; n < nargs + nreturns; n++)
728		*va_arg(ap, cell_t *) = args_n_results[n];
729	va_end(ap);
730	return (0);
731}
732
733/*
734 * Device I/O functions
735 */
736
737/* Open an instance for a device. */
738ihandle_t
739OF_open(const char *device)
740{
741
742	if (ofw_def_impl == NULL)
743		return (0);
744
745	return (OFW_OPEN(ofw_obj, device));
746}
747
748/* Close an instance. */
749void
750OF_close(ihandle_t instance)
751{
752
753	if (ofw_def_impl == NULL)
754		return;
755
756	OFW_CLOSE(ofw_obj, instance);
757}
758
759/* Read from an instance. */
760ssize_t
761OF_read(ihandle_t instance, void *addr, size_t len)
762{
763
764	if (ofw_def_impl == NULL)
765		return (-1);
766
767	return (OFW_READ(ofw_obj, instance, addr, len));
768}
769
770/* Write to an instance. */
771ssize_t
772OF_write(ihandle_t instance, const void *addr, size_t len)
773{
774
775	if (ofw_def_impl == NULL)
776		return (-1);
777
778	return (OFW_WRITE(ofw_obj, instance, addr, len));
779}
780
781/* Seek to a position. */
782int
783OF_seek(ihandle_t instance, uint64_t pos)
784{
785
786	if (ofw_def_impl == NULL)
787		return (-1);
788
789	return (OFW_SEEK(ofw_obj, instance, pos));
790}
791
792/*
793 * Memory functions
794 */
795
796/* Claim an area of memory. */
797void *
798OF_claim(void *virt, size_t size, u_int align)
799{
800
801	if (ofw_def_impl == NULL)
802		return ((void *)-1);
803
804	return (OFW_CLAIM(ofw_obj, virt, size, align));
805}
806
807/* Release an area of memory. */
808void
809OF_release(void *virt, size_t size)
810{
811
812	if (ofw_def_impl == NULL)
813		return;
814
815	OFW_RELEASE(ofw_obj, virt, size);
816}
817
818/*
819 * Control transfer functions
820 */
821
822/* Suspend and drop back to the Open Firmware interface. */
823void
824OF_enter(void)
825{
826
827	if (ofw_def_impl == NULL)
828		return;
829
830	OFW_ENTER(ofw_obj);
831}
832
833/* Shut down and drop back to the Open Firmware interface. */
834void
835OF_exit(void)
836{
837
838	if (ofw_def_impl == NULL)
839		panic("OF_exit: Open Firmware not available");
840
841	/* Should not return */
842	OFW_EXIT(ofw_obj);
843
844	for (;;)			/* just in case */
845		;
846}
847