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