xref: /freebsd-src/usr.sbin/ofwdump/ofw_util.c (revision 4d65a7c6951cea0333f1a0c1b32c38489cdfa6c5)
11b6eef5bSThomas Moestl /*-
21b6eef5bSThomas Moestl  * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>.
31b6eef5bSThomas Moestl  * All rights reserved.
41b6eef5bSThomas Moestl  *
51b6eef5bSThomas Moestl  * Redistribution and use in source and binary forms, with or without
61b6eef5bSThomas Moestl  * modification, are permitted provided that the following conditions
71b6eef5bSThomas Moestl  * are met:
81b6eef5bSThomas Moestl  * 1. Redistributions of source code must retain the above copyright
91b6eef5bSThomas Moestl  *    notice, this list of conditions and the following disclaimer.
101b6eef5bSThomas Moestl  * 2. Redistributions in binary form must reproduce the above copyright
111b6eef5bSThomas Moestl  *    notice, this list of conditions and the following disclaimer in the
121b6eef5bSThomas Moestl  *    documentation and/or other materials provided with the distribution.
131b6eef5bSThomas Moestl  *
141b6eef5bSThomas Moestl  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
151b6eef5bSThomas Moestl  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
161b6eef5bSThomas Moestl  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
171b6eef5bSThomas Moestl  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
181b6eef5bSThomas Moestl  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
191b6eef5bSThomas Moestl  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
201b6eef5bSThomas Moestl  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
211b6eef5bSThomas Moestl  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
221b6eef5bSThomas Moestl  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
231b6eef5bSThomas Moestl  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
241b6eef5bSThomas Moestl  */
251b6eef5bSThomas Moestl 
261b6eef5bSThomas Moestl #include <sys/types.h>
271b6eef5bSThomas Moestl #include <sys/ioctl.h>
281b6eef5bSThomas Moestl 
291b6eef5bSThomas Moestl #include <dev/ofw/openfirmio.h>
301b6eef5bSThomas Moestl 
311b6eef5bSThomas Moestl #include <err.h>
321b6eef5bSThomas Moestl #include <errno.h>
331b6eef5bSThomas Moestl #include <fcntl.h>
341b6eef5bSThomas Moestl #include <stdio.h>
35987c23d4SThomas Moestl #include <stdlib.h>
361b6eef5bSThomas Moestl #include <string.h>
37*8cc2c162SMarius Strobl #include <sysexits.h>
381b6eef5bSThomas Moestl #include <unistd.h>
391b6eef5bSThomas Moestl 
401b6eef5bSThomas Moestl #include "pathnames.h"
411b6eef5bSThomas Moestl #include "ofw_util.h"
421b6eef5bSThomas Moestl 
431b6eef5bSThomas Moestl #define	OFW_IOCTL(fd, cmd, val)	do {					\
441b6eef5bSThomas Moestl 	if (ioctl(fd, cmd, val) == -1)					\
45*8cc2c162SMarius Strobl 		err(EX_IOERR, "ioctl(..., " #cmd ", ...) failed");	\
461b6eef5bSThomas Moestl } while (0)
471b6eef5bSThomas Moestl 
481b6eef5bSThomas Moestl int
ofw_open(int mode)49*8cc2c162SMarius Strobl ofw_open(int mode)
501b6eef5bSThomas Moestl {
511b6eef5bSThomas Moestl 	int fd;
521b6eef5bSThomas Moestl 
53*8cc2c162SMarius Strobl 	if ((fd = open(PATH_DEV_OPENFIRM, mode)) == -1)
54*8cc2c162SMarius Strobl 		err(EX_UNAVAILABLE, "could not open " PATH_DEV_OPENFIRM);
551b6eef5bSThomas Moestl 	return (fd);
561b6eef5bSThomas Moestl }
571b6eef5bSThomas Moestl 
581b6eef5bSThomas Moestl void
ofw_close(int fd)591b6eef5bSThomas Moestl ofw_close(int fd)
601b6eef5bSThomas Moestl {
611b6eef5bSThomas Moestl 
621b6eef5bSThomas Moestl 	close(fd);
631b6eef5bSThomas Moestl }
641b6eef5bSThomas Moestl 
651b6eef5bSThomas Moestl phandle_t
ofw_root(int fd)661b6eef5bSThomas Moestl ofw_root(int fd)
671b6eef5bSThomas Moestl {
681b6eef5bSThomas Moestl 
691b6eef5bSThomas Moestl 	return (ofw_peer(fd, 0));
701b6eef5bSThomas Moestl }
711b6eef5bSThomas Moestl 
721b6eef5bSThomas Moestl phandle_t
ofw_optnode(int fd)73*8cc2c162SMarius Strobl ofw_optnode(int fd)
74*8cc2c162SMarius Strobl {
75*8cc2c162SMarius Strobl 	phandle_t rv;
76*8cc2c162SMarius Strobl 
77*8cc2c162SMarius Strobl 	OFW_IOCTL(fd, OFIOCGETOPTNODE, &rv);
78*8cc2c162SMarius Strobl 	return (rv);
79*8cc2c162SMarius Strobl }
80*8cc2c162SMarius Strobl 
81*8cc2c162SMarius Strobl phandle_t
ofw_peer(int fd,phandle_t node)821b6eef5bSThomas Moestl ofw_peer(int fd, phandle_t node)
831b6eef5bSThomas Moestl {
841b6eef5bSThomas Moestl 	phandle_t rv;
851b6eef5bSThomas Moestl 
861b6eef5bSThomas Moestl 	rv = node;
871b6eef5bSThomas Moestl 	OFW_IOCTL(fd, OFIOCGETNEXT, &rv);
881b6eef5bSThomas Moestl 	return (rv);
891b6eef5bSThomas Moestl }
901b6eef5bSThomas Moestl 
911b6eef5bSThomas Moestl phandle_t
ofw_child(int fd,phandle_t node)921b6eef5bSThomas Moestl ofw_child(int fd, phandle_t node)
931b6eef5bSThomas Moestl {
941b6eef5bSThomas Moestl 	phandle_t rv;
951b6eef5bSThomas Moestl 
961b6eef5bSThomas Moestl 	rv = node;
971b6eef5bSThomas Moestl 	OFW_IOCTL(fd, OFIOCGETCHILD, &rv);
981b6eef5bSThomas Moestl 	return (rv);
991b6eef5bSThomas Moestl }
1001b6eef5bSThomas Moestl 
1011b6eef5bSThomas Moestl phandle_t
ofw_finddevice(int fd,const char * name)102*8cc2c162SMarius Strobl ofw_finddevice(int fd, const char *name)
1031b6eef5bSThomas Moestl {
1041b6eef5bSThomas Moestl 	struct ofiocdesc d;
1051b6eef5bSThomas Moestl 
1061b6eef5bSThomas Moestl 	d.of_nodeid = 0;
1071b6eef5bSThomas Moestl 	d.of_namelen = strlen(name);
1081b6eef5bSThomas Moestl 	d.of_name = name;
1091b6eef5bSThomas Moestl 	d.of_buflen = 0;
1101b6eef5bSThomas Moestl 	d.of_buf = NULL;
1111b6eef5bSThomas Moestl 	if (ioctl(fd, OFIOCFINDDEVICE, &d) == -1) {
1121b6eef5bSThomas Moestl 		if (errno == ENOENT)
113*8cc2c162SMarius Strobl 			err(EX_UNAVAILABLE, "Node '%s' not found", name);
1141b6eef5bSThomas Moestl 		else
115*8cc2c162SMarius Strobl 			err(EX_IOERR,
116*8cc2c162SMarius Strobl 			    "ioctl(..., OFIOCFINDDEVICE, ...) failed");
1171b6eef5bSThomas Moestl 	}
1181b6eef5bSThomas Moestl 	return (d.of_nodeid);
1191b6eef5bSThomas Moestl }
1201b6eef5bSThomas Moestl 
1211b6eef5bSThomas Moestl int
ofw_firstprop(int fd,phandle_t node,char * buf,int buflen)1221b6eef5bSThomas Moestl ofw_firstprop(int fd, phandle_t node, char *buf, int buflen)
1231b6eef5bSThomas Moestl {
1241b6eef5bSThomas Moestl 
1251b6eef5bSThomas Moestl 	return (ofw_nextprop(fd, node, NULL, buf, buflen));
1261b6eef5bSThomas Moestl }
1271b6eef5bSThomas Moestl 
1281b6eef5bSThomas Moestl int
ofw_nextprop(int fd,phandle_t node,const char * prev,char * buf,int buflen)129*8cc2c162SMarius Strobl ofw_nextprop(int fd, phandle_t node, const char *prev, char *buf, int buflen)
1301b6eef5bSThomas Moestl {
1311b6eef5bSThomas Moestl 	struct ofiocdesc d;
1321b6eef5bSThomas Moestl 
1331b6eef5bSThomas Moestl 	d.of_nodeid = node;
1341b6eef5bSThomas Moestl 	d.of_namelen = prev != NULL ? strlen(prev) : 0;
1351b6eef5bSThomas Moestl 	d.of_name = prev;
1361b6eef5bSThomas Moestl 	d.of_buflen = buflen;
1371b6eef5bSThomas Moestl 	d.of_buf = buf;
1381b6eef5bSThomas Moestl 	if (ioctl(fd, OFIOCNEXTPROP, &d) == -1) {
1391b6eef5bSThomas Moestl 		if (errno == ENOENT)
1401b6eef5bSThomas Moestl 			return (0);
1411b6eef5bSThomas Moestl 		else
142*8cc2c162SMarius Strobl 			err(EX_IOERR, "ioctl(..., OFIOCNEXTPROP, ...) failed");
1431b6eef5bSThomas Moestl 	}
1441b6eef5bSThomas Moestl 	return (d.of_buflen);
1451b6eef5bSThomas Moestl }
1461b6eef5bSThomas Moestl 
147987c23d4SThomas Moestl static void *
ofw_malloc(int size)148987c23d4SThomas Moestl ofw_malloc(int size)
149987c23d4SThomas Moestl {
150987c23d4SThomas Moestl 	void *p;
151987c23d4SThomas Moestl 
152987c23d4SThomas Moestl 	if ((p = malloc(size)) == NULL)
153*8cc2c162SMarius Strobl 		err(EX_OSERR, "malloc() failed");
154987c23d4SThomas Moestl 	return (p);
155987c23d4SThomas Moestl }
156987c23d4SThomas Moestl 
1571b6eef5bSThomas Moestl int
ofw_getprop(int fd,phandle_t node,const char * name,void * buf,int buflen)1581b6eef5bSThomas Moestl ofw_getprop(int fd, phandle_t node, const char *name, void *buf, int buflen)
1591b6eef5bSThomas Moestl {
1601b6eef5bSThomas Moestl 	struct ofiocdesc d;
1611b6eef5bSThomas Moestl 
1621b6eef5bSThomas Moestl 	d.of_nodeid = node;
1631b6eef5bSThomas Moestl 	d.of_namelen = strlen(name);
1641b6eef5bSThomas Moestl 	d.of_name = name;
1651b6eef5bSThomas Moestl 	d.of_buflen = buflen;
1661b6eef5bSThomas Moestl 	d.of_buf = buf;
1671b6eef5bSThomas Moestl 	OFW_IOCTL(fd, OFIOCGET, &d);
1681b6eef5bSThomas Moestl 	return (d.of_buflen);
1691b6eef5bSThomas Moestl }
1701b6eef5bSThomas Moestl 
171987c23d4SThomas Moestl int
ofw_setprop(int fd,phandle_t node,const char * name,const void * buf,int buflen)172*8cc2c162SMarius Strobl ofw_setprop(int fd, phandle_t node, const char *name, const void *buf,
173*8cc2c162SMarius Strobl     int buflen)
174*8cc2c162SMarius Strobl {
175*8cc2c162SMarius Strobl 	struct ofiocdesc d;
176*8cc2c162SMarius Strobl 
177*8cc2c162SMarius Strobl 	d.of_nodeid = node;
178*8cc2c162SMarius Strobl 	d.of_namelen = strlen(name);
179*8cc2c162SMarius Strobl 	d.of_name = name;
180*8cc2c162SMarius Strobl 	d.of_buflen = buflen;
181*8cc2c162SMarius Strobl 	d.of_buf = ofw_malloc(buflen);
182*8cc2c162SMarius Strobl 	memcpy(d.of_buf, buf, buflen);
183*8cc2c162SMarius Strobl 	OFW_IOCTL(fd, OFIOCSET, &d);
184*8cc2c162SMarius Strobl 	free(d.of_buf);
185*8cc2c162SMarius Strobl 	return (d.of_buflen);
186*8cc2c162SMarius Strobl }
187*8cc2c162SMarius Strobl 
188*8cc2c162SMarius Strobl int
ofw_getproplen(int fd,phandle_t node,const char * name)189987c23d4SThomas Moestl ofw_getproplen(int fd, phandle_t node, const char *name)
190987c23d4SThomas Moestl {
191987c23d4SThomas Moestl 	struct ofiocdesc d;
192987c23d4SThomas Moestl 
193987c23d4SThomas Moestl 	d.of_nodeid = node;
194987c23d4SThomas Moestl 	d.of_namelen = strlen(name);
195987c23d4SThomas Moestl 	d.of_name = name;
196987c23d4SThomas Moestl 	OFW_IOCTL(fd, OFIOCGETPROPLEN, &d);
197987c23d4SThomas Moestl 	return (d.of_buflen);
198987c23d4SThomas Moestl }
199987c23d4SThomas Moestl 
200987c23d4SThomas Moestl int
ofw_getprop_alloc(int fd,phandle_t node,const char * name,void ** buf,int * buflen,int reserve)201987c23d4SThomas Moestl ofw_getprop_alloc(int fd, phandle_t node, const char *name, void **buf,
202987c23d4SThomas Moestl     int *buflen, int reserve)
203987c23d4SThomas Moestl {
204987c23d4SThomas Moestl 	struct ofiocdesc d;
205987c23d4SThomas Moestl 	int len, rv;
206987c23d4SThomas Moestl 
207987c23d4SThomas Moestl 	do {
208987c23d4SThomas Moestl 		len = ofw_getproplen(fd, node, name);
209987c23d4SThomas Moestl 		if (len < 0)
210987c23d4SThomas Moestl 			return (len);
211987c23d4SThomas Moestl 		if (*buflen < len + reserve) {
212987c23d4SThomas Moestl 			if (*buf != NULL)
213987c23d4SThomas Moestl 				free(*buf);
214*8cc2c162SMarius Strobl 			*buflen = len + reserve + OFIOCMAXVALUE;
215987c23d4SThomas Moestl 			*buf = ofw_malloc(*buflen);
216987c23d4SThomas Moestl 		}
217987c23d4SThomas Moestl 		d.of_nodeid = node;
218987c23d4SThomas Moestl 		d.of_namelen = strlen(name);
219987c23d4SThomas Moestl 		d.of_name = name;
220987c23d4SThomas Moestl 		d.of_buflen = *buflen - reserve;
221987c23d4SThomas Moestl 		d.of_buf = *buf;
222987c23d4SThomas Moestl 		rv = ioctl(fd, OFIOCGET, &d);
223987c23d4SThomas Moestl 	} while (rv == -1 && errno == ENOMEM);
224987c23d4SThomas Moestl 	if (rv == -1)
225*8cc2c162SMarius Strobl 		err(EX_IOERR, "ioctl(..., OFIOCGET, ...) failed");
226987c23d4SThomas Moestl 	return (d.of_buflen);
227987c23d4SThomas Moestl }
228