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