1 /* 2 * Copyright (c) 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratory. 13 * 14 * %sccs.include.redist.c% 15 * 16 * @(#)openprom.c 7.2 (Berkeley) 04/27/93 17 * 18 * from: $Header: openprom.c,v 1.3 93/04/27 08:56:09 torek Exp $ 19 */ 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/errno.h> 24 #include <sys/fcntl.h> 25 #include <sys/ioctl.h> 26 #include <sys/malloc.h> 27 28 #include <machine/bsd_openprom.h> 29 #include <machine/openpromio.h> 30 31 static int lastnode; /* speed hack */ 32 extern int optionsnode; /* node ID of ROM's options */ 33 extern int findroot(); /* returns node ID of top node */ 34 extern struct promvec *promvec; 35 36 int 37 openpromopen(dev, flags, mode) 38 dev_t dev; 39 int flags, mode; 40 { 41 42 return (0); 43 } 44 45 int 46 openpromclose(dev, flags, mode) 47 dev_t dev; 48 int flags, mode; 49 { 50 51 return (0); 52 } 53 54 /* 55 * Verify target ID is valid (exists in the OPENPROM tree), as 56 * listed from node ID sid forward. 57 */ 58 static int 59 openpromcheckid(sid, tid) 60 register int sid, tid; 61 { 62 register struct nodeops *no; 63 64 no = promvec->pv_nodeops; 65 for (; sid != 0; sid = no->no_nextnode(sid)) 66 if (sid == tid || openpromcheckid(no->no_child(sid), tid)) 67 return (1); 68 69 return (0); 70 } 71 72 static int 73 openpromgetstr(len, user, cpp) 74 int len; 75 char *user, **cpp; 76 { 77 register int error; 78 register char *cp; 79 80 /* Reject obvious bogus requests */ 81 if ((u_int)len > (8 * 1024) - 1) 82 return (ENAMETOOLONG); 83 84 *cpp = cp = malloc(len + 1, M_TEMP, M_WAITOK); 85 error = copyin(user, cp, len); 86 cp[len] = '\0'; 87 return (error); 88 } 89 90 int 91 openpromioctl(dev, cmd, data, flags, p) 92 dev_t dev; 93 int cmd; 94 caddr_t data; 95 int flags; 96 struct proc *p; 97 { 98 register struct opiocdesc *op; 99 register int node, len, ok, error, s; 100 char *name, *value, *nextprop; 101 register struct nodeops *no; 102 103 /* All too easy... */ 104 if (cmd == OPIOCGETOPTNODE) { 105 *(int *)data = optionsnode; 106 return (0); 107 } 108 109 /* Verify node id */ 110 op = (struct opiocdesc *)data; 111 node = op->op_nodeid; 112 if (node != 0 && node != lastnode && node != optionsnode) { 113 /* Not an easy one, must search for it */ 114 s = splhigh(); 115 ok = openpromcheckid(findroot(), node); 116 splx(s); 117 if (!ok) 118 return (EINVAL); 119 lastnode = node; 120 } 121 122 name = value = NULL; 123 no = promvec->pv_nodeops; 124 error = 0; 125 switch (cmd) { 126 127 case OPIOCGET: 128 if ((flags & FREAD) == 0) 129 return (EBADF); 130 if (node == 0) 131 return (EINVAL); 132 error = openpromgetstr(op->op_namelen, op->op_name, &name); 133 if (error) 134 break; 135 s = splhigh(); 136 len = no->no_proplen(node, name); 137 splx(s); 138 if (len > op->op_buflen) 139 len = op->op_buflen; 140 else 141 op->op_buflen = len; 142 /* -1 means no entry; 0 means no value */ 143 if (len <= 0) 144 break; 145 value = malloc(len, M_TEMP, M_WAITOK); 146 s = splhigh(); 147 (void)no->no_getprop(node, name, value); 148 splx(s); 149 error = copyout(value, op->op_buf, len); 150 break; 151 152 case OPIOCSET: 153 if ((flags & FWRITE) == 0) 154 return (EBADF); 155 if (node == 0) 156 return (EINVAL); 157 error = openpromgetstr(op->op_namelen, op->op_name, &name); 158 if (error) 159 break; 160 error = openpromgetstr(op->op_buflen, op->op_buf, &value); 161 if (error) 162 break; 163 s = splhigh(); 164 len = no->no_setprop(node, name, value, op->op_buflen + 1); 165 splx(s); 166 if (len != op->op_buflen) 167 error = EINVAL; 168 break; 169 170 case OPIOCNEXTPROP: 171 if ((flags & FREAD) == 0) 172 return (EBADF); 173 if (node == 0) 174 return (EINVAL); 175 error = openpromgetstr(op->op_namelen, op->op_name, &name); 176 if (error) 177 break; 178 s = splhigh(); 179 nextprop = no->no_nextprop(node, name); 180 splx(s); 181 len = strlen(nextprop); 182 if (len > op->op_buflen) 183 len = op->op_buflen; 184 else 185 op->op_buflen = len; 186 error = copyout(nextprop, op->op_buf, len); 187 break; 188 189 case OPIOCGETNEXT: 190 if ((flags & FREAD) == 0) 191 return (EBADF); 192 s = splhigh(); 193 node = no->no_nextnode(node); 194 splx(s); 195 *(int *)data = lastnode = node; 196 break; 197 198 case OPIOCGETCHILD: 199 if ((flags & FREAD) == 0) 200 return (EBADF); 201 if (node == 0) 202 return (EINVAL); 203 s = splhigh(); 204 node = no->no_child(node); 205 splx(s); 206 *(int *)data = lastnode = node; 207 break; 208 209 default: 210 return (ENOTTY); 211 } 212 213 if (name) 214 free(name, M_TEMP); 215 if (value) 216 free(value, M_TEMP); 217 218 return (error); 219 } 220