2 * Copyright (c) 2016 Netflix, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD: head/sys/dev/efidev/efidev.c 307391 2016-10-16 06:07:43Z kib $
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/module.h>
37 #include <sys/device.h>
39 #include <machine/efi.h>
40 #include <sys/efiio.h>
42 static d_ioctl_t efidev_ioctl
;
43 static d_open_t efidev_open
;
44 static d_close_t efidev_close
;
46 static struct dev_ops efi_ops
= {
48 .d_open
= efidev_open
,
49 .d_close
= efidev_close
,
50 .d_ioctl
= efidev_ioctl
,
54 efidev_open(struct dev_open_args
*ap
)
60 efidev_close(struct dev_close_args
*ap
)
66 efidev_ioctl(struct dev_ioctl_args
*ap
)
68 u_long cmd
= ap
->a_cmd
;
69 caddr_t addr
= ap
->a_data
;
73 case EFIIOC_GET_TABLE
:
75 struct efi_get_table_ioc
*egtioc
=
76 (struct efi_get_table_ioc
*)addr
;
78 error
= efi_get_table(&egtioc
->uuid
, &egtioc
->ptr
);
83 struct efi_tm
*tm
= (struct efi_tm
*)addr
;
85 error
= efi_get_time(tm
);
90 struct efi_tm
*tm
= (struct efi_tm
*)addr
;
92 error
= efi_set_time(tm
);
97 struct efi_var_ioc
*ev
= (struct efi_var_ioc
*)addr
;
101 data
= kmalloc(ev
->datasize
, M_TEMP
, M_WAITOK
);
102 name
= kmalloc(ev
->namesize
, M_TEMP
, M_WAITOK
);
103 error
= copyin(ev
->name
, name
, ev
->namesize
);
106 if (name
[ev
->namesize
/ sizeof(efi_char
) - 1] != 0) {
111 error
= efi_var_get(name
, &ev
->vendor
, &ev
->attrib
,
112 &ev
->datasize
, data
);
115 error
= copyout(data
, ev
->data
, ev
->datasize
);
116 } else if (error
== EOVERFLOW
) {
118 * Pass back the size we really need, but
119 * convert the error to 0 so the copyout
120 * happens. datasize was updated in the
131 case EFIIOC_VAR_NEXT
:
133 struct efi_var_ioc
*ev
= (struct efi_var_ioc
*)addr
;
136 name
= kmalloc(ev
->namesize
, M_TEMP
, M_WAITOK
);
137 error
= copyin(ev
->name
, name
, ev
->namesize
);
140 /* Note: namesize is the buffer size, not the string lenght */
142 error
= efi_var_nextname(&ev
->namesize
, name
, &ev
->vendor
);
144 error
= copyout(name
, ev
->name
, ev
->namesize
);
145 } else if (error
== EOVERFLOW
) {
155 struct efi_var_ioc
*ev
= (struct efi_var_ioc
*)addr
;
159 /* datasize == 0 -> delete (more or less) */
160 if (ev
->datasize
> 0)
161 data
= kmalloc(ev
->datasize
, M_TEMP
, M_WAITOK
);
162 name
= kmalloc(ev
->namesize
, M_TEMP
, M_WAITOK
);
164 error
= copyin(ev
->data
, data
, ev
->datasize
);
168 error
= copyin(ev
->name
, name
, ev
->namesize
);
171 if (name
[ev
->namesize
/ sizeof(efi_char
) - 1] != 0) {
176 error
= efi_var_set(name
, &ev
->vendor
, ev
->attrib
, ev
->datasize
,
191 static struct cdev
*efidev
;
194 efidev_modevents(module_t m
, int event
, void *arg __unused
)
198 efidev
= make_dev(&efi_ops
, 0, UID_ROOT
, GID_WHEEL
,
216 static moduledata_t efidev_moddata
= {
218 .evhand
= efidev_modevents
,
222 DECLARE_MODULE(efidev
, efidev_moddata
, SI_SUB_PRE_DRIVERS
, SI_ORDER_ANY
);
223 MODULE_VERSION(efidev
, 1);
224 MODULE_DEPEND(efidev
, efirt
, 1, 1, 1);