The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ofw/openfirmio.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: openfirmio.c,v 1.8 2003/08/07 16:31:10 agc 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. Neither the name of the University nor the names of its contributors
   25  *    may be used to endorse or promote products derived from this software
   26  *    without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   38  * SUCH DAMAGE.
   39  *
   40  *      @(#)openfirm.c  8.1 (Berkeley) 6/11/93
   41  */
   42 
   43 #include <sys/cdefs.h>
   44 __KERNEL_RCSID(0, "$NetBSD: openfirmio.c,v 1.8 2003/08/07 16:31:10 agc Exp $");
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/errno.h>
   49 #include <sys/fcntl.h>
   50 #include <sys/ioctl.h>
   51 #include <sys/malloc.h>
   52 #include <sys/conf.h>
   53 #include <sys/device.h>
   54 #include <sys/event.h>
   55 
   56 #include <dev/ofw/openfirm.h>
   57 #include <dev/ofw/openfirmio.h>
   58 
   59 static  int lastnode;                   /* speed hack */
   60 
   61 static int openfirmcheckid (int, int);
   62 static int openfirmgetstr (int, char *, char **);
   63 
   64 void openfirmattach (int);
   65 
   66 dev_type_ioctl(openfirmioctl);
   67 
   68 const struct cdevsw openfirm_cdevsw = {
   69         nullopen, nullclose, noread, nowrite, openfirmioctl,
   70         nostop, notty, nopoll, nommap, nokqfilter,
   71 };
   72 
   73 void
   74 openfirmattach(int num)
   75 {
   76         /* nothing */
   77 }
   78 
   79 /*
   80  * Verify target ID is valid (exists in the OPENPROM tree), as
   81  * listed from node ID sid forward.
   82  */
   83 static int
   84 openfirmcheckid(int sid, int tid)
   85 {
   86 
   87         for (; sid != 0; sid = OF_peer(sid))
   88                 if (sid == tid || openfirmcheckid(OF_child(sid), tid))
   89                         return (1);
   90 
   91         return (0);
   92 }
   93 
   94 static int
   95 openfirmgetstr(int len, char *user, char **cpp)
   96 {
   97         int error;
   98         char *cp;
   99 
  100         /* Reject obvious bogus requests */
  101         if ((u_int)len > (8 * 1024) - 1)
  102                 return (ENAMETOOLONG);
  103 
  104         *cpp = cp = malloc(len + 1, M_TEMP, M_WAITOK);
  105         error = copyin(user, cp, len);
  106         cp[len] = '\0';
  107         return (error);
  108 }
  109 
  110 int
  111 openfirmioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
  112 {
  113         struct ofiocdesc *of;
  114         int node, len, ok, error, s;
  115         char *name, *value;
  116 
  117         if (cmd == OFIOCGETOPTNODE) {
  118                 s = splhigh();
  119                 *(int *) data = OF_finddevice("/options");
  120                 splx(s);
  121                 return (0);
  122         }
  123 
  124         /* Verify node id */
  125         of = (struct ofiocdesc *)data;
  126         node = of->of_nodeid;
  127         if (node != 0 && node != lastnode) {
  128                 /* Not an easy one, must search for it */
  129                 s = splhigh();
  130                 ok = openfirmcheckid(OF_peer(0), node);
  131                 splx(s);
  132                 if (!ok)
  133                         return (EINVAL);
  134                 lastnode = node;
  135         }
  136 
  137         name = value = NULL;
  138         error = 0;
  139         switch (cmd) {
  140 
  141         case OFIOCGET:
  142                 if ((flags & FREAD) == 0)
  143                         return (EBADF);
  144                 if (node == 0)
  145                         return (EINVAL);
  146                 error = openfirmgetstr(of->of_namelen, of->of_name, &name);
  147                 if (error)
  148                         break;
  149                 s = splhigh();
  150                 len = OF_getproplen(node, name);
  151                 splx(s);
  152                 if (len > of->of_buflen) {
  153                         error = ENOMEM;
  154                         break;
  155                 }
  156                 of->of_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                 if (value == NULL) {
  162                         error = ENOMEM;
  163                         break;
  164                 }
  165                 s = splhigh();
  166                 len = OF_getprop(node, name, (void *)value, len);
  167                 splx(s);
  168                 error = copyout(value, of->of_buf, len);
  169                 break;
  170 
  171 #if 0
  172         case OFIOCSET:
  173                 if ((flags & FWRITE) == 0)
  174                         return (EBADF);
  175                 if (node == 0)
  176                         return (EINVAL);
  177                 error = openfirmgetstr(of->of_namelen, of->of_name, &name);
  178                 if (error)
  179                         break;
  180                 error = openfirmgetstr(of->of_buflen, of->of_buf, &value);
  181                 if (error)
  182                         break;
  183                 s = splhigh();
  184                 len = OF_setprop(node, name, value, of->of_buflen + 1);
  185                 splx(s);
  186                 if (len != of->of_buflen)
  187                         error = EINVAL;
  188                 break;
  189 #endif
  190 
  191         case OFIOCNEXTPROP: {
  192                 char newname[32];
  193                 if ((flags & FREAD) == 0)
  194                         return (EBADF);
  195                 if (node == 0)
  196                         return (EINVAL);
  197                 if (of->of_namelen != 0) {
  198                         error = openfirmgetstr(of->of_namelen, of->of_name,
  199                             &name);
  200                         if (error)
  201                                 break;
  202                 }
  203                 s = splhigh();
  204                 ok = OF_nextprop(node, name, newname);
  205                 splx(s);
  206                 if (ok == 0) {
  207                         error = ENOENT;
  208                         break;
  209                 }
  210                 if (ok == -1) {
  211                         error = EINVAL;
  212                         break;
  213                 }
  214                 len = strlen(newname);
  215                 if (len > of->of_buflen)
  216                         len = of->of_buflen;
  217                 else
  218                         of->of_buflen = len;
  219                 error = copyout(newname, of->of_buf, len);
  220                 break;
  221         }
  222 
  223         case OFIOCGETNEXT:
  224                 if ((flags & FREAD) == 0)
  225                         return (EBADF);
  226                 s = splhigh();
  227                 node = OF_peer(node);
  228                 splx(s);
  229                 *(int *)data = lastnode = node;
  230                 break;
  231 
  232         case OFIOCGETCHILD:
  233                 if ((flags & FREAD) == 0)
  234                         return (EBADF);
  235                 if (node == 0)
  236                         return (EINVAL);
  237                 s = splhigh();
  238                 node = OF_child(node);
  239                 splx(s);
  240                 *(int *)data = lastnode = node;
  241                 break;
  242 
  243         case OFIOCFINDDEVICE:
  244                 if ((flags & FREAD) == 0)
  245                         return (EBADF);
  246                 error = openfirmgetstr(of->of_namelen, of->of_name, &name);
  247                 if (error)
  248                         break;
  249                 node = OF_finddevice(name);
  250                 if (node == 0 || node == -1) {
  251                         error = ENOENT;
  252                         break;
  253                 }
  254                 of->of_nodeid = lastnode = node;
  255                 break;
  256 
  257         default:
  258                 return (ENOTTY);
  259         }
  260 
  261         if (name)
  262                 free(name, M_TEMP);
  263         if (value)
  264                 free(value, M_TEMP);
  265 
  266         return (error);
  267 }

Cache object: 8947bfe67c5c4e7f1f71ce41ce26acd3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.