1 /* $NetBSD: openprom.c,v 1.12 2001/12/04 00:05:07 darrenr Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratory. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. All advertising materials mentioning features or use of this software 25 * must display the following acknowledgement: 26 * This product includes software developed by the University of 27 * California, Berkeley and its contributors. 28 * 4. Neither the name of the University nor the names of its contributors 29 * may be used to endorse or promote products derived from this software 30 * without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 * 44 * @(#)openprom.c 8.1 (Berkeley) 6/11/93 45 */ 46 #include "opt_sparc_arch.h" 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/errno.h> 51 #include <sys/fcntl.h> 52 #include <sys/ioctl.h> 53 #include <sys/malloc.h> 54 #include <sys/conf.h> 55 #include <sys/device.h> 56 57 #include <machine/bsd_openprom.h> 58 #include <machine/promlib.h> 59 #include <machine/openpromio.h> 60 #include <machine/conf.h> 61 62 static int lastnode; /* speed hack */ 63 extern int optionsnode; /* node ID of ROM's options */ 64 65 static int openpromcheckid __P((int, int)); 66 static int openpromgetstr __P((int, char *, char **)); 67 68 int 69 openpromopen(dev, flags, mode, p) 70 dev_t dev; 71 int flags, mode; 72 struct proc *p; 73 { 74 #if defined(SUN4) 75 if (cputyp==CPU_SUN4) 76 return (ENODEV); 77 #endif 78 79 return (0); 80 } 81 82 int 83 openpromclose(dev, flags, mode, p) 84 dev_t dev; 85 int flags, mode; 86 struct proc *p; 87 { 88 89 return (0); 90 } 91 92 /* 93 * Verify target ID is valid (exists in the OPENPROM tree), as 94 * listed from node ID sid forward. 95 */ 96 static int 97 openpromcheckid(sid, tid) 98 int sid, tid; 99 { 100 101 for (; sid != 0; sid = nextsibling(sid)) 102 if (sid == tid || openpromcheckid(firstchild(sid), tid)) 103 return (1); 104 105 return (0); 106 } 107 108 static int 109 openpromgetstr(len, user, cpp) 110 int len; 111 char *user, **cpp; 112 { 113 int error; 114 char *cp; 115 116 /* Reject obvious bogus requests */ 117 if ((u_int)len > (8 * 1024) - 1) 118 return (ENAMETOOLONG); 119 120 *cpp = cp = malloc(len + 1, M_TEMP, M_WAITOK); 121 error = copyin(user, cp, len); 122 cp[len] = '\0'; 123 return (error); 124 } 125 126 int 127 openpromioctl(dev, cmd, data, flags, p) 128 dev_t dev; 129 u_long cmd; 130 caddr_t data; 131 int flags; 132 struct proc *p; 133 { 134 struct opiocdesc *op; 135 int node, len, ok, error, s; 136 char *name, *value, *nextprop; 137 138 /* All too easy... */ 139 if (cmd == OPIOCGETOPTNODE) { 140 *(int *)data = optionsnode; 141 return (0); 142 } 143 144 /* Verify node id */ 145 op = (struct opiocdesc *)data; 146 node = op->op_nodeid; 147 if (node != 0 && node != lastnode && node != optionsnode) { 148 /* Not an easy one, must search for it */ 149 s = splhigh(); 150 ok = openpromcheckid(findroot(), node); 151 splx(s); 152 if (!ok) 153 return (EINVAL); 154 lastnode = node; 155 } 156 157 name = value = NULL; 158 error = 0; 159 switch (cmd) { 160 161 case OPIOCGET: 162 if ((flags & FREAD) == 0) 163 return (EBADF); 164 if (node == 0) 165 return (EINVAL); 166 error = openpromgetstr(op->op_namelen, op->op_name, &name); 167 if (error) 168 break; 169 s = splhigh(); 170 len = prom_proplen(node, name); 171 splx(s); 172 if (len > op->op_buflen) { 173 error = ENOMEM; 174 break; 175 } 176 op->op_buflen = len; 177 /* -1 means no entry; 0 means no value */ 178 if (len <= 0) 179 break; 180 value = malloc(len, M_TEMP, M_WAITOK); 181 s = splhigh(); 182 error = PROM_getprop(node, name, 1, &len, (void **)&value); 183 splx(s); 184 if (error != 0) 185 break; 186 error = copyout(value, op->op_buf, len); 187 break; 188 189 case OPIOCSET: 190 if ((flags & FWRITE) == 0) 191 return (EBADF); 192 if (node == 0) 193 return (EINVAL); 194 error = openpromgetstr(op->op_namelen, op->op_name, &name); 195 if (error) 196 break; 197 error = openpromgetstr(op->op_buflen, op->op_buf, &value); 198 if (error) 199 break; 200 s = splhigh(); 201 len = prom_setprop(node, name, value, op->op_buflen + 1); 202 splx(s); 203 if (len != op->op_buflen) 204 error = EINVAL; 205 break; 206 207 case OPIOCNEXTPROP: 208 if ((flags & FREAD) == 0) 209 return (EBADF); 210 if (node == 0) 211 return (EINVAL); 212 error = openpromgetstr(op->op_namelen, op->op_name, &name); 213 if (error) 214 break; 215 s = splhigh(); 216 nextprop = prom_nextprop(node, name); 217 splx(s); 218 len = strlen(nextprop); 219 if (len > op->op_buflen) 220 len = op->op_buflen; 221 else 222 op->op_buflen = len; 223 error = copyout(nextprop, op->op_buf, len); 224 break; 225 226 case OPIOCGETNEXT: 227 if ((flags & FREAD) == 0) 228 return (EBADF); 229 s = splhigh(); 230 node = nextsibling(node); 231 splx(s); 232 *(int *)data = lastnode = node; 233 break; 234 235 case OPIOCGETCHILD: 236 if ((flags & FREAD) == 0) 237 return (EBADF); 238 if (node == 0) 239 return (EINVAL); 240 s = splhigh(); 241 node = firstchild(node); 242 splx(s); 243 *(int *)data = lastnode = node; 244 break; 245 246 default: 247 return (ENOTTY); 248 } 249 250 if (name) 251 free(name, M_TEMP); 252 if (value) 253 free(value, M_TEMP); 254 255 return (error); 256 } 257