1 /*- 2 * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 23 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 #include <sys/types.h> 28 #include <sys/ioctl.h> 29 30 #include <dev/ofw/openfirmio.h> 31 32 #include <err.h> 33 #include <errno.h> 34 #include <fcntl.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <sysexits.h> 39 #include <unistd.h> 40 41 #include "pathnames.h" 42 #include "ofw_util.h" 43 44 #define OFW_IOCTL(fd, cmd, val) do { \ 45 if (ioctl(fd, cmd, val) == -1) \ 46 err(EX_IOERR, "ioctl(..., " #cmd ", ...) failed"); \ 47 } while (0) 48 49 int 50 ofw_open(int mode) 51 { 52 int fd; 53 54 if ((fd = open(PATH_DEV_OPENFIRM, mode)) == -1) 55 err(EX_UNAVAILABLE, "could not open " PATH_DEV_OPENFIRM); 56 return (fd); 57 } 58 59 void 60 ofw_close(int fd) 61 { 62 63 close(fd); 64 } 65 66 phandle_t 67 ofw_root(int fd) 68 { 69 70 return (ofw_peer(fd, 0)); 71 } 72 73 phandle_t 74 ofw_optnode(int fd) 75 { 76 phandle_t rv; 77 78 OFW_IOCTL(fd, OFIOCGETOPTNODE, &rv); 79 return (rv); 80 } 81 82 phandle_t 83 ofw_peer(int fd, phandle_t node) 84 { 85 phandle_t rv; 86 87 rv = node; 88 OFW_IOCTL(fd, OFIOCGETNEXT, &rv); 89 return (rv); 90 } 91 92 phandle_t 93 ofw_child(int fd, phandle_t node) 94 { 95 phandle_t rv; 96 97 rv = node; 98 OFW_IOCTL(fd, OFIOCGETCHILD, &rv); 99 return (rv); 100 } 101 102 phandle_t 103 ofw_finddevice(int fd, const char *name) 104 { 105 struct ofiocdesc d; 106 107 d.of_nodeid = 0; 108 d.of_namelen = strlen(name); 109 d.of_name = name; 110 d.of_buflen = 0; 111 d.of_buf = NULL; 112 if (ioctl(fd, OFIOCFINDDEVICE, &d) == -1) { 113 if (errno == ENOENT) 114 err(EX_UNAVAILABLE, "Node '%s' not found", name); 115 else 116 err(EX_IOERR, 117 "ioctl(..., OFIOCFINDDEVICE, ...) failed"); 118 } 119 return (d.of_nodeid); 120 } 121 122 int 123 ofw_firstprop(int fd, phandle_t node, char *buf, int buflen) 124 { 125 126 return (ofw_nextprop(fd, node, NULL, buf, buflen)); 127 } 128 129 int 130 ofw_nextprop(int fd, phandle_t node, const char *prev, char *buf, int buflen) 131 { 132 struct ofiocdesc d; 133 134 d.of_nodeid = node; 135 d.of_namelen = prev != NULL ? strlen(prev) : 0; 136 d.of_name = prev; 137 d.of_buflen = buflen; 138 d.of_buf = buf; 139 if (ioctl(fd, OFIOCNEXTPROP, &d) == -1) { 140 if (errno == ENOENT) 141 return (0); 142 else 143 err(EX_IOERR, "ioctl(..., OFIOCNEXTPROP, ...) failed"); 144 } 145 return (d.of_buflen); 146 } 147 148 static void * 149 ofw_malloc(int size) 150 { 151 void *p; 152 153 if ((p = malloc(size)) == NULL) 154 err(EX_OSERR, "malloc() failed"); 155 return (p); 156 } 157 158 int 159 ofw_getprop(int fd, phandle_t node, const char *name, void *buf, int buflen) 160 { 161 struct ofiocdesc d; 162 163 d.of_nodeid = node; 164 d.of_namelen = strlen(name); 165 d.of_name = name; 166 d.of_buflen = buflen; 167 d.of_buf = buf; 168 OFW_IOCTL(fd, OFIOCGET, &d); 169 return (d.of_buflen); 170 } 171 172 int 173 ofw_setprop(int fd, phandle_t node, const char *name, const void *buf, 174 int buflen) 175 { 176 struct ofiocdesc d; 177 178 d.of_nodeid = node; 179 d.of_namelen = strlen(name); 180 d.of_name = name; 181 d.of_buflen = buflen; 182 d.of_buf = ofw_malloc(buflen); 183 memcpy(d.of_buf, buf, buflen); 184 OFW_IOCTL(fd, OFIOCSET, &d); 185 free(d.of_buf); 186 return (d.of_buflen); 187 } 188 189 int 190 ofw_getproplen(int fd, phandle_t node, const char *name) 191 { 192 struct ofiocdesc d; 193 194 d.of_nodeid = node; 195 d.of_namelen = strlen(name); 196 d.of_name = name; 197 OFW_IOCTL(fd, OFIOCGETPROPLEN, &d); 198 return (d.of_buflen); 199 } 200 201 int 202 ofw_getprop_alloc(int fd, phandle_t node, const char *name, void **buf, 203 int *buflen, int reserve) 204 { 205 struct ofiocdesc d; 206 int len, rv; 207 208 do { 209 len = ofw_getproplen(fd, node, name); 210 if (len < 0) 211 return (len); 212 if (*buflen < len + reserve) { 213 if (*buf != NULL) 214 free(*buf); 215 *buflen = len + reserve + OFIOCMAXVALUE; 216 *buf = ofw_malloc(*buflen); 217 } 218 d.of_nodeid = node; 219 d.of_namelen = strlen(name); 220 d.of_name = name; 221 d.of_buflen = *buflen - reserve; 222 d.of_buf = *buf; 223 rv = ioctl(fd, OFIOCGET, &d); 224 } while (rv == -1 && errno == ENOMEM); 225 if (rv == -1) 226 err(EX_IOERR, "ioctl(..., OFIOCGET, ...) failed"); 227 return (d.of_buflen); 228 } 229