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/efidev/efidev.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 /*-
    2  * Copyright (c) 2016 Netflix, Inc.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer
    9  *    in this position and unchanged.
   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 BE LIABLE FOR ANY DIRECT, INDIRECT,
   18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   24  */
   25 
   26 #include <sys/cdefs.h>
   27 __FBSDID("$FreeBSD$");
   28 
   29 #include <sys/param.h>
   30 #include <sys/systm.h>
   31 #include <sys/kernel.h>
   32 #include <sys/bus.h>
   33 #include <sys/conf.h>
   34 #include <sys/lock.h>
   35 #include <sys/malloc.h>
   36 #include <sys/module.h>
   37 
   38 #include <machine/efi.h>
   39 #include <sys/efiio.h>
   40 
   41 static d_ioctl_t efidev_ioctl;
   42 
   43 static struct cdevsw efi_cdevsw = {
   44         .d_name = "efi",
   45         .d_version = D_VERSION,
   46         .d_ioctl = efidev_ioctl,
   47 };
   48         
   49 static int
   50 efidev_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr,
   51     int flags __unused, struct thread *td __unused)
   52 {
   53         int error;
   54 
   55         switch (cmd) {
   56         case EFIIOC_GET_TABLE:
   57         {
   58                 struct efi_get_table_ioc *egtioc =
   59                     (struct efi_get_table_ioc *)addr;
   60                 void *buf = NULL;
   61 
   62                 error = efi_copy_table(&egtioc->uuid, egtioc->buf ? &buf : NULL,
   63                     egtioc->buf_len, &egtioc->table_len);
   64 
   65                 if (error != 0 || egtioc->buf == NULL)
   66                         break;
   67 
   68                 if (egtioc->buf_len < egtioc->table_len) {
   69                         error = EINVAL;
   70                         free(buf, M_TEMP);
   71                         break;
   72                 }
   73 
   74                 error = copyout(buf, egtioc->buf, egtioc->buf_len);
   75                 free(buf, M_TEMP);
   76 
   77                 break;
   78         }
   79         case EFIIOC_GET_TIME:
   80         {
   81                 struct efi_tm *tm = (struct efi_tm *)addr;
   82 
   83                 error = efi_get_time(tm);
   84                 break;
   85         }
   86         case EFIIOC_SET_TIME:
   87         {
   88                 struct efi_tm *tm = (struct efi_tm *)addr;
   89 
   90                 error = efi_set_time(tm);
   91                 break;
   92         }
   93         case EFIIOC_VAR_GET:
   94         {
   95                 struct efi_var_ioc *ev = (struct efi_var_ioc *)addr;
   96                 void *data;
   97                 efi_char *name;
   98 
   99                 data = malloc(ev->datasize, M_TEMP, M_WAITOK);
  100                 name = malloc(ev->namesize, M_TEMP, M_WAITOK);
  101                 error = copyin(ev->name, name, ev->namesize);
  102                 if (error)
  103                         goto vg_out;
  104                 if (name[ev->namesize / sizeof(efi_char) - 1] != 0) {
  105                         error = EINVAL;
  106                         goto vg_out;
  107                 }
  108 
  109                 error = efi_var_get(name, &ev->vendor, &ev->attrib,
  110                     &ev->datasize, data);
  111 
  112                 if (error == 0) {
  113                         error = copyout(data, ev->data, ev->datasize);
  114                 } else if (error == EOVERFLOW) {
  115                         /*
  116                          * Pass back the size we really need, but
  117                          * convert the error to 0 so the copyout
  118                          * happens. datasize was updated in the
  119                          * efi_var_get call.
  120                          */
  121                         ev->data = NULL;
  122                         error = 0;
  123                 }
  124 vg_out:
  125                 free(data, M_TEMP);
  126                 free(name, M_TEMP);
  127                 break;
  128         }
  129         case EFIIOC_VAR_NEXT:
  130         {
  131                 struct efi_var_ioc *ev = (struct efi_var_ioc *)addr;
  132                 efi_char *name;
  133 
  134                 name = malloc(ev->namesize, M_TEMP, M_WAITOK);
  135                 error = copyin(ev->name, name, ev->namesize);
  136                 if (error)
  137                         goto vn_out;
  138                 /* Note: namesize is the buffer size, not the string lenght */
  139 
  140                 error = efi_var_nextname(&ev->namesize, name, &ev->vendor);
  141                 if (error == 0) {
  142                         error = copyout(name, ev->name, ev->namesize);
  143                 } else if (error == EOVERFLOW) {
  144                         ev->name = NULL;
  145                         error = 0;
  146                 }
  147         vn_out:
  148                 free(name, M_TEMP);
  149                 break;
  150         }
  151         case EFIIOC_VAR_SET:
  152         {
  153                 struct efi_var_ioc *ev = (struct efi_var_ioc *)addr;
  154                 void *data = NULL;
  155                 efi_char *name;
  156 
  157                 /* datasize == 0 -> delete (more or less) */
  158                 if (ev->datasize > 0)
  159                         data = malloc(ev->datasize, M_TEMP, M_WAITOK);
  160                 name = malloc(ev->namesize, M_TEMP, M_WAITOK);
  161                 if (ev->datasize) {
  162                         error = copyin(ev->data, data, ev->datasize);
  163                         if (error)
  164                                 goto vs_out;
  165                 }
  166                 error = copyin(ev->name, name, ev->namesize);
  167                 if (error)
  168                         goto vs_out;
  169                 if (name[ev->namesize / sizeof(efi_char) - 1] != 0) {
  170                         error = EINVAL;
  171                         goto vs_out;
  172                 }
  173 
  174                 error = efi_var_set(name, &ev->vendor, ev->attrib, ev->datasize,
  175                     data);
  176 vs_out:
  177                 free(data, M_TEMP);
  178                 free(name, M_TEMP);
  179                 break;
  180         }
  181         default:
  182                 error = ENOTTY;
  183                 break;
  184         }
  185 
  186         return (error);
  187 }
  188 
  189 static struct cdev *efidev;
  190 
  191 static int
  192 efidev_modevents(module_t m, int event, void *arg __unused)
  193 {
  194         struct make_dev_args mda;
  195         int error;
  196 
  197         switch (event) {
  198         case MOD_LOAD:
  199                 /*
  200                  * If we have no efi environment, then don't create the device.
  201                  */
  202                 if (efi_rt_ok() != 0)
  203                         return (0);
  204                 make_dev_args_init(&mda);
  205                 mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME;
  206                 mda.mda_devsw = &efi_cdevsw;
  207                 mda.mda_uid = UID_ROOT;
  208                 mda.mda_gid = GID_WHEEL;
  209                 mda.mda_mode = 0700;
  210                 error = make_dev_s(&mda, &efidev, "efi");
  211                 return (error);
  212 
  213         case MOD_UNLOAD:
  214                 if (efidev != NULL)
  215                         destroy_dev(efidev);
  216                 efidev = NULL;
  217                 return (0);
  218 
  219         case MOD_SHUTDOWN:
  220                 return (0);
  221 
  222         default:
  223                 return (EOPNOTSUPP);
  224         }
  225 }
  226 
  227 static moduledata_t efidev_moddata = {
  228         .name = "efidev",
  229         .evhand = efidev_modevents,
  230         .priv = NULL,
  231 };
  232 
  233 DECLARE_MODULE(efidev, efidev_moddata, SI_SUB_DRIVERS, SI_ORDER_ANY);
  234 MODULE_VERSION(efidev, 1);
  235 MODULE_DEPEND(efidev, efirt, 1, 1, 1);

Cache object: dc561507e7def1fdad311606205d6179


[ 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.