Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148533661
D8128.id20951.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
64 KB
Referenced Files
None
Subscribers
None
D8128.id20951.diff
View Options
Index: lib/Makefile
===================================================================
--- lib/Makefile
+++ lib/Makefile
@@ -48,6 +48,7 @@
libdevstat \
libdwarf \
libedit \
+ ${_libefivar} \
${_libelftc} \
libevent \
libexecinfo \
@@ -239,6 +240,10 @@
_libcplusplus= libc++
.endif
+.if ${MACHINE_ARCH} == "amd64"
+_libefivar= libefivar
+.endif
+
.if ${MK_LIBTHR} != "no"
_libthr= libthr
.endif
Index: lib/libefi/Makefile
===================================================================
--- lib/libefi/Makefile
+++ /dev/null
@@ -1,23 +0,0 @@
-# $FreeBSD$
-
-.include <bsd.own.mk>
-
-PACKAGE=lib${LIB}
-LIB= efi
-SHLIB_MAJOR= 1
-
-SRCS= libefi.c \
- efi_getvar.c \
- efi_nextvarname.c \
- efi_setvar.c
-
-CFLAGS+= -I${.CURDIR}
-
-INCS= libefi.h
-
-MAN+= libefi.3
-MLINKS+=libefi.3 efi_getvar.3 \
- libefi.3 efi_nextvarname.3 \
- libefi.3 efi_setvar.3
-
-.include <bsd.lib.mk>
Index: lib/libefi/efi_getvar.c
===================================================================
--- lib/libefi/efi_getvar.c
+++ /dev/null
@@ -1,68 +0,0 @@
-/*-
- * Copyright (c) 2010 Marcel Moolenaar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <libefi.h>
-#include <stdlib.h>
-
-#include "libefi_int.h"
-
-/*
- * EFI_STATUS
- * GetVariable(
- * IN CHAR16 *VariableName,
- * IN EFI_GUID *VendorGuid,
- * OUT UINT32 *Attributes OPTIONAL,
- * IN OUT UINTN *DataSize,
- * OUT VOID *Data
- * );
- */
-
-int
-efi_getvar(char *name, uuid_t *vendor, uint32_t *attrib, size_t *datasize,
- void *data)
-{
- struct iodev_efivar_req req;
- int error;
-
- req.namesize = 0;
- error = libefi_utf8_to_ucs2(name, &req.namesize, &req.name);
- if (error)
- return (error);
-
- req.vendor = *vendor;
- req.datasize = *datasize;
- req.data = data;
- req.access = IODEV_EFIVAR_GETVAR;
- error = libefi_efivar(&req);
- *datasize = req.datasize;
- if (!error && attrib != NULL)
- *attrib = req.attrib;
- free(req.name);
- return (error);
-}
Index: lib/libefi/efi_nextvarname.c
===================================================================
--- lib/libefi/efi_nextvarname.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*-
- * Copyright (c) 2010 Marcel Moolenaar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <libefi.h>
-#include <stdlib.h>
-
-#include "libefi_int.h"
-
-/*
- * EFI_STATUS
- * GetNextVariableName(
- * IN OUT UINTN *VariableNameSize,
- * IN OUT CHAR16 *VariableName,
- * IN OUT EFI_GUID *VendorGuid
- * );
- */
-
-int
-efi_nextvarname(size_t *namesize, char *name, uuid_t *vendor)
-{
- struct iodev_efivar_req req;
- int error;
-
- req.namesize = *namesize;
- error = libefi_utf8_to_ucs2(name, &req.namesize, &req.name);
- if (error)
- return (error);
-
- req.vendor = *vendor;
- req.access = IODEV_EFIVAR_NEXTNAME;
- error = libefi_efivar(&req);
- *namesize = req.namesize;
- if (!error) {
- error = libefi_ucs2_to_utf8(req.name, namesize, name);
- if (!error)
- *vendor = req.vendor;
- }
- free(req.name);
- return (error);
-}
Index: lib/libefi/libefi.h
===================================================================
--- lib/libefi/libefi.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*-
- * Copyright (c) 2010 Marcel Moolenaar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-#ifndef _LIBEFI_H_
-#define _LIBEFI_H_
-
-#include <sys/types.h>
-#include <sys/uuid.h>
-#include <stddef.h>
-
-/* Attributes. */
-#define EFI_ATTR_NV 0x0001 /* Variable stored in NVRAM. */
-#define EFI_ATTR_BS 0x0002 /* Boot services accessable. */
-#define EFI_ATTR_RT 0x0004 /* Runtime accessable. */
-#define EFI_ATTR_HR 0x0008 /* Hardware error record. */
-#define EFI_ATTR_WR 0x0010 /* Authenticated write access. */
-
-/* Vendor for architecturally defined variables. */
-#define EFI_GLOBAL_VARIABLE \
- {0x8be4df61,0x93ca,0x11d2,0xaa,0x0d,{0x00,0xe0,0x98,0x03,0x2b,0x8c}}
-
-/* Vendor for FreeBSD-specific variables. */
-#define EFI_FREEBSD_VARIABLE \
- {0x13c32014,0x0c9c,0x11df,0xa2,0x38,{0x00,0x17,0xa4,0xab,0x91,0x2d}}
-
-__BEGIN_DECLS
-int efi_getvar (char *, uuid_t *, uint32_t *, size_t *, void *);
-int efi_nextvarname (size_t *, char *, uuid_t *);
-int efi_setvar (char *, uuid_t *, uint32_t, size_t, void *);
-__END_DECLS
-
-#endif /* _LIBEFI_H_ */
Index: lib/libefi/libefi.3
===================================================================
--- lib/libefi/libefi.3
+++ /dev/null
@@ -1,143 +0,0 @@
-.\"-
-.\" Copyright (c) 2010 Marcel Moolenaar
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd January 29, 2010
-.Dt LIBEFI 3
-.Os
-.Sh NAME
-.Nm efi_getvar , efi_nextvarname , efi_setvar
-.Nd "interface for accessing the EFI variable services"
-.Sh LIBRARY
-.Lb libefi
-.Sh SYNOPSIS
-.In libefi.h
-.Ft int
-.Fo efi_getvar
-.Fa "char *name" "uuid_t *vendor" "uint32_t *attrib"
-.Fa "size_t *datasize" "void *data"
-.Fc
-.Ft int
-.Fn efi_nextvarname "size_t *namesize" "char *name" "uuid_t *vendor"
-.Ft int
-.Fo efi_setvar
-.Fa "char *name" "uuid_t *vendor" "uint32_t attrib"
-.Fa "size_t datasize" "void *data"
-.Fc
-.Sh DESCRIPTION
-The
-.Nm libefi
-library provides access to a select set of the runtime services of the
-Extensible Firmware Interface (EFI).
-.Pp
-The
-.Fn efi_nextvarname
-function is used to enumerate the variables.
-The
-.Fa namesize
-parameter needs to be set to the size of the buffer pointed to by
-.Fa name .
-On return,
-.Fa namesize
-is set to the length of the variable name (including the terminating
-.Ql \e0 )
-irrespective of whether the buffer was big enough.
-The buffer pointed to by
-.Fa name
-contains the full or partial variable name on return.
-Only on successful completion of the request is the
-.Fa vendor
-updated.
-The values returned should be passed to successive calls to
-.Fn efi_nextvarname
-until all variables have been enumerated.
-.Pp
-The variable name and vendor as returned by
-.Fn efi_nextvarname
-can be passed to
-.Fn efi_getvar
-to obtain the value and attribute of the variable.
-The buffer that is to contain the value is specified by
-.Fa data
-and the size of the buffer is given by
-.Fa datasize .
-The attribute pointed to by
-.Fa attrib
-consists of the bit values defined by the EFI specification.
-.Pp
-Variables can be created, modified and deleted using the
-.Fn efi_setvar
-function.
-All new variables must be non-volatile and runtime accessible in
-order for the request to succeed.
-Note that for runtime accessable variables the boottime accessable bit must
-be set as well.
-To delete a variable, set
-.Fa datasize
-to 0.
-.Pp
-The vendor UUID is used to avoid collisions between variable names of
-different vendors.
-Variables created for use by
-.Fx
-should use the
-.Dv EFI_FREEBSD_VARIABLE
-UUID as defined in the
-.In libefi.h
-header file.
-.Sh RETURN VALUES
-Upon successful completion, these functions return 0.
-Otherwise, the error number is returned.
-These functions will fail if:
-.Bl -tag -width Er
-.It Bq Er EACCES
-Insufficient permissions to access the EFI services.
-.It Bq Er EILSEQ
-The variable name is not in UTF-8.
-.It Bq Er EINVAL
-The request has invalid parameters.
-.It Bq Er ENOENT
-The variable does not exist or no more variables exist.
-.It Bq Er ENOMEM
-Temporary storage could not be allocated.
-.It Bq Er EOVERFLOW
-The variable name is too long or the data is too big to fit in
-the buffer provided.
-.El
-.Sh SEE ALSO
-.Xr errno 2 ,
-.Xr uuid 3
-.Sh HISTORY
-The
-.Nm libefi
-library first appeared in
-.Fx 9.0
-for the ia64 architecture.
-.Sh AUTHORS
-The
-.Nm libefi
-library and this manual page were written by
-.An Marcel Moolenaar Aq Mt marcel@FreeBSD.org .
Index: lib/libefivar/Makefile
===================================================================
--- /dev/null
+++ lib/libefivar/Makefile
@@ -0,0 +1,53 @@
+# Copyright 1998 Juniper Networks, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+.include <src.opts.mk>
+
+PACKAGE=lib${LIB}
+LIB= efivar
+SRCS= efivar.c libefivar.c
+INCS= efivar.h
+SHLIB_MAJOR= 1
+MAN= efivar.3
+
+MLINKS+=efivar.3 efi_set_variables_supported.3 \
+ efivar.3 efi_del_variable.3 \
+ efivar.3 efi_get_variable.3 \
+ efivar.3 efi_get_variable_attributes.3 \
+ efivar.3 efi_get_variable_size.3 \
+ efivar.3 efi_append_variable.3 \
+ efivar.3 efi_set_variable.3 \
+ efivar.3 efi_get_next_variable_name.3 \
+ efivar.3 efi_str_to_guid.3 \
+ efivar.3 efi_guid_to_str.3 \
+ efivar.3 efi_name_to_guid.3 \
+ efivar.3 efi_guid_to_name.3 \
+ efivar.3 efi_guid_to_symbol.3 \
+ efivar.3 libefivar.3
+
+WARNS?= 9
+
+.include <bsd.lib.mk>
Index: lib/libefivar/efivar.h
===================================================================
--- /dev/null
+++ lib/libefivar/efivar.h
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 2016 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _EFIVAR_H_
+#define _EFIVAR_H_
+
+#include <uuid.h>
+#include <sys/efi.h>
+#include <sys/endian.h>
+#include <stdint.h>
+
+/* Shoud these be elsewhere ? */
+#define EFI_VARIABLE_NON_VOLATILE 0x00000001
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
+#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS \
+ 0x00000020
+#define EFI_VARIABLE_APPEND_WRITE 0x00000040
+#if 0 /* todo */
+#define EFI_VARIABLE_HAS_AUTH_HEADER
+#define EFI_VARIABLE_HAS_SIGNATURE
+#endif
+
+
+typedef uuid_t efi_guid_t;
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define EFI_GUID(a, b, c, d, e0, e1, e2, e3, e4, e5) \
+ ((efi_guid_t) {(a), (b), (c), (d) >> 8, (d) & 0xff, \
+ { (e0), (e1), (e2), (e3), (e4), (e5) }})
+#else
+#define EFI_GUID(a, b, c, d, e0, e1, e2, e3, e4, e5) \
+ ((efi_guid_t) {(a), (b), (c), (d) & 0xff, (d) >> 8, \
+ { (e0), (e1), (e2), (e3), (e4), (e5) }})
+#endif
+
+#define EFI_GLOBAL_GUID EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, 0xaa0d, \
+ 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c)
+
+int efi_append_variable(efi_guid_t guid, const char *name,
+ uint8_t *data, size_t data_size, uint32_t attributes);
+int efi_del_variable(efi_guid_t guid, const char *name);
+int efi_get_variable(efi_guid_t guid, const char *name,
+ uint8_t **data, size_t *data_size, uint32_t *attributes);
+int efi_get_variable_attributes(efi_guid_t guid, const char *name,
+ uint32_t *attributes);
+int efi_get_variable_size(efi_guid_t guid, const char *name, size_t *size);
+int efi_get_next_variable_name(efi_guid_t **guid, char **name);
+int efi_guid_cmp(const efi_guid_t *guid1, const efi_guid_t *guid2);
+int efi_guid_is_zero(const efi_guid_t *guid1);
+int efi_guid_to_name(efi_guid_t *guid, char **name);
+int efi_guid_to_symbol(efi_guid_t *guid, char **symbol);
+int efi_guid_to_str(const efi_guid_t *guid, char **sp);
+int efi_name_to_guid(const char *name, efi_guid_t *guid);
+int efi_set_variable(efi_guid_t guid, const char *name,
+ uint8_t *data, size_t data_size, uint32_t attributes, mode_t mode);
+int efi_str_to_guid(const char *s, efi_guid_t *guid);
+int efi_variables_supported(void);
+
+extern const efi_guid_t efi_guid_empty;
+
+/* Stubs that are expected, but aren't really used */
+static inline int
+efi_error_get(unsigned int n __unused, char ** const fn __unused,
+ char ** const func __unused, int *line __unused,
+ char ** const msg __unused, int *err __unused)
+{
+ return 0;
+}
+
+static inline int
+efi_error_set(const char *fn __unused, const char *func __unused,
+ int line __unused, int err __unused, const char *fmt __unused, ...)
+{
+ return 0;
+}
+
+static inline void
+efi_error_clear(void)
+{
+}
+
+static inline int
+efi_error(const char *fmt __unused, ...)
+{
+ return 0;
+}
+
+static inline int
+efi_error_val(int val __unused, const char *fmt __unused, ...)
+{
+ return 0;
+}
+
+#endif /* _EFIVAR_H_ */
Index: lib/libefivar/efivar.3
===================================================================
--- /dev/null
+++ lib/libefivar/efivar.3
@@ -0,0 +1,98 @@
+.\" Copyright 2016 Netflix, Inc.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 14, 2016
+.Dt LIBEFIVAR 3
+.Os
+.Sh NAME
+.Nm libefivar
+.Nd EFI Non Volatile Variable Suppoert
+.Sh SYNOPSIS
+.In efivar.h
+.Ft int
+.Fn efi_append_variable "efi_guid_t guid" "const char *name" "void *data" "size_t data_size" "uint32_t attributes"
+.Ft int
+.Fn efi_del_variable "efi_guid_t guid" "const char *name"
+.Ft int
+.Fn efi_get_variable "efi_guid_t guid" "const char *name" "void **data" "ssize_t *data_size" "uint32_t *attributes"
+.Ft int
+.Fn efi_get_variable_attributes "efi_guid_t guid" "const char *name" "uint32_t *attributes"
+.Ft int
+.Fn efi_get_variable_size "efi_guid_t guid" "const char *name" "size_t *size"
+.Ft int
+.Fn efi_get_next_variable_name "efi_guid_t **guid" "char **name"
+.Ft int
+.Fn efi_guid_to_name "efi_guid_t *guid" "char **name"
+.Ft int
+.Fn efi_guid_to_symbol "efi_guid_t *guid" "char **symbol"
+.Ft int
+.Fn efi_guid_to_str "const efi_guid_t *guid" "char **sp"
+.Ft int
+.Fn efi_name_to_guid "const char *name" "efi_guid_t *guid"
+.Ft int
+.Fn efi_set_variable "efi_guid_t guid" "const char *name" "void *data" "size_t data_size" "uint32_t attributes"
+.Ft int
+.Fn efi_str_to_guid "const char *s" "efi_guid_t *guid";
+.Ft int
+.Fn efi_variables_supported "void";
+.Sh DESCRIPTION
+The
+.Nm
+library implements access to EFI Variables via the EFI Runtime
+Serivces.
+All char * strings are converted to 16-bit UTF strings before passing
+them to EFI.
+.Pp
+.Fn efi_variables_supported
+returns non-zero if the current machine supports setting of EFI firmware
+variables and the kernel support for doing so is present.
+Otherwise zero is returned.
+.Pp
+.Fn efi_del_variable
+deletes the EFI variable selected by
+.Dv guid
+and
+.Dv name .
+.Pp
+.Fn efi_get_variable
+.Fn efi_get_variable_attributes
+.Fn efi_get_variable_size
+.Fn efi_append_variable
+.Fn efi_set_variable
+.Fn efi_get_next_variable_name
+.Fn efi_str_to_guid
+.Fn efi_guid_to_str
+.Fn efi_name_to_guid
+.Fn efi_guid_to_name
+.Fn efi_guid_to_symbol
+This function is not actually implemented.
+.Sh BUGS
+No facilities exist to process the strings as native UTF.
+This is a limitation in the Linux libefivar library interface.
+.Sh AUTHORS
+.An -nosplit
+This software was originally written by
+.An Warner Losh .
Index: lib/libefivar/efivar.c
===================================================================
--- /dev/null
+++ lib/libefivar/efivar.c
@@ -0,0 +1,377 @@
+/*-
+ * Copyright (c) 2016 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <efivar.h>
+#include <sys/efiio.h>
+#include <sys/param.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libefivar_int.h"
+
+static int efi_fd = -2;
+
+#define Z { 0, 0, 0, 0, 0, { 0 } }
+
+const efi_guid_t efi_guid_empty = Z;
+
+static struct uuid_table
+{
+ const char *uuid_str;
+ const char *name;
+ efi_guid_t guid;
+} guid_tbl [] =
+{
+ { "00000000-0000-0000-0000-000000000000", "zero", Z },
+ { "093e0fae-a6c4-4f50-9f1b-d41e2b89c19a", "sha512", Z },
+ { "0abba7dc-e516-4167-bbf5-4d9d1c739416", "redhat", Z },
+ { "0b6e5233-a65c-44c9-9407-d9ab83bfc8bd", "sha224", Z },
+ { "126a762d-5758-4fca-8531-201a7f57f850", "lenovo_boot_menu", Z },
+ { "3bd2a492-96c0-4079-b420-fcf98ef103ed", "x509_sha256", Z },
+ { "3c5766e8-269c-4e34-aa14-ed776e85b3b6", "rsa2048", Z },
+ { "3CC24E96-22C7-41D8-8863-8E39DCDCC2CF", "lenovo", Z },
+ { "3f7e615b-0d45-4f80-88dc-26b234958560", "lenovo_diag", Z },
+ { "446dbf63-2502-4cda-bcfa-2465d2b0fe9d", "x509_sha512", Z },
+ { "4aafd29d-68df-49ee-8aa9-347d375665a7", "pkcs7_cert", Z },
+ { "605dab50-e046-4300-abb6-3dd810dd8b23", "shim", Z },
+ { "665d3f60-ad3e-4cad-8e26-db46eee9f1b5", "lenovo_rescue", Z },
+ { "67f8444f-8743-48f1-a328-1eaab8736080", "rsa2048_sha1", Z },
+ { "7076876e-80c2-4ee6-aad2-28b349a6865b", "x509_sha384", Z },
+ { "721c8b66-426c-4e86-8e99-3457c46ab0b9", "lenovo_setup", Z },
+ { "77fa9abd-0359-4d32-bd60-28f4e78f784b", "microsoft", Z },
+ { "7FACC7B6-127F-4E9C-9C5D-080F98994345", "lenovo_2", Z },
+ { "826ca512-cf10-4ac9-b187-be01496631bd", "sha1", Z },
+ { "82988420-7467-4490-9059-feb448dd1963", "lenovo_me_config", Z },
+ { "8be4df61-93ca-11d2-aa0d-00e098032b8c", "global", Z },
+ { "a5c059a1-94e4-4aa7-87b5-ab155c2bf072", "x509_cert", Z },
+ { "a7717414-c616-4977-9420-844712a735bf", "rsa2048_sha256_cert", Z },
+ { "a7d8d9a6-6ab0-4aeb-ad9d-163e59a7a380", "lenovo_diag_splash", Z },
+ { "ade9e48f-9cb8-98e6-31af-b4e6009e2fe3", "redhat_2", Z },
+ { "bc7838d2-0f82-4d60-8316-c068ee79d25b", "lenovo_msg", Z },
+ { "c1c41626-504c-4092-aca9-41f936934328", "sha256", Z },
+ { "c57ad6b7-0515-40a8-9d21-551652854e37", "shell", Z },
+ { "d719b2cb-3d3a-4596-a3bc-dad00e67656f", "security", Z },
+ { "e2b36190-879b-4a3d-ad8d-f2e7bba32784", "rsa2048_sha256", Z },
+ { "ff3e5307-9fd0-48c9-85f1-8ad56c701e01", "sha384", Z },
+ { "f46ee6f4-4785-43a3-923d-7f786c3c8479", "lenovo_startup_interrupt", Z },
+ { "ffffffff-ffff-ffff-ffff-ffffffffffff", "zzignore-this-guid", Z },
+};
+#undef Z
+
+static void
+efi_guid_tbl_compile(void)
+{
+ size_t i;
+ uint32_t status;
+
+ for (i = 0; i < nitems(guid_tbl); i++) {
+ uuid_from_string(guid_tbl[i].uuid_str, &guid_tbl[i].guid,
+ &status);
+ /* all f's is a bad version, so ignore that error */
+ if (status != uuid_s_ok && status != uuid_s_bad_version)
+ fprintf(stderr, "Can't convert %s to a uuid for %s: %d\n",
+ guid_tbl[i].uuid_str, guid_tbl[i].name, (int)status);
+ }
+}
+
+static int
+efi_open_dev(void)
+{
+
+ if (efi_fd == -2)
+ efi_fd = open("/dev/efidev", O_RDWR);
+ if (efi_fd < 0)
+ efi_fd = -1;
+ else
+ efi_guid_tbl_compile();
+ return (efi_fd);
+}
+
+static void
+efi_var_reset(struct efi_var_ioc *var)
+{
+ var->name = NULL;
+ var->namesize = 0;
+ memset(&var->vendor, 0, sizeof(var->vendor));
+ var->attrib = 0;
+ var->data = NULL;
+ var->datasize = 0;
+}
+
+static int
+rv_to_linux_rv(int rv)
+{
+ if (rv == 0)
+ rv = 1;
+ else if (errno == ENOENT) {
+ rv = 0;
+ errno = 0;
+ } else
+ rv = -errno;
+ return (rv);
+}
+
+int
+efi_append_variable(efi_guid_t guid, const char *name,
+ uint8_t *data, size_t data_size, uint32_t attributes)
+{
+
+ return efi_set_variable(guid, name, data, data_size,
+ attributes | EFI_VARIABLE_APPEND_WRITE, 0);
+}
+
+int
+efi_del_variable(efi_guid_t guid, const char *name)
+{
+
+ /* data_size of 0 deletes the variable */
+ return efi_set_variable(guid, name, NULL, 0, 0, 0);
+}
+
+int
+efi_get_variable(efi_guid_t guid, const char *name,
+ uint8_t **data, size_t *data_size, uint32_t *attributes)
+{
+ struct efi_var_ioc var;
+ int rv;
+ static uint8_t buf[1024*32];
+
+ if (efi_open_dev() == -1)
+ return -1;
+
+ efi_var_reset(&var);
+ rv = libefi_utf8_to_ucs2(name, &var.name, &var.namesize);
+ if (rv != 0)
+ goto errout;
+ var.vendor = guid;
+ var.data = buf;
+ var.datasize = sizeof(buf);
+ rv = ioctl(efi_fd, EFIIOC_VAR_GET, &var);
+ if (data_size != NULL)
+ *data_size = var.datasize;
+ if (data != NULL)
+ *data = buf;
+ if (attributes != NULL)
+ *attributes = var.attrib;
+errout:
+ free(var.name);
+
+ return rv_to_linux_rv(rv);
+}
+
+int
+efi_get_variable_attributes(efi_guid_t guid, const char *name,
+ uint32_t *attributes)
+{
+ /* Make sure this construct works -- I think it will fail */
+
+ return efi_get_variable(guid, name, NULL, NULL, attributes);
+}
+
+int
+efi_get_variable_size(efi_guid_t guid, const char *name,
+ size_t *size)
+{
+
+ /* XXX check to make sure this matches the linux value */
+
+ *size = 0;
+ return efi_get_variable(guid, name, NULL, size, NULL);
+}
+
+int
+efi_get_next_variable_name(efi_guid_t **guid, char **name)
+{
+ struct efi_var_ioc var;
+ int rv;
+ static efi_char *buf;
+ static size_t buflen = 256 * sizeof(efi_char);
+ static efi_guid_t retguid;
+ size_t size;
+
+ if (efi_open_dev() == -1)
+ return -1;
+
+ if (buf == NULL)
+ buf = malloc(buflen);
+
+again:
+ efi_var_reset(&var);
+ var.name = buf;
+ var.namesize = buflen;
+ if (*name == NULL) {
+ *buf = 0;
+ /* GUID zeroed in var_reset */
+ } else {
+ rv = libefi_utf8_to_ucs2(*name, &var.name, &size);
+ if (rv != 0)
+ goto errout;
+ var.vendor = **guid;
+ }
+ rv = ioctl(efi_fd, EFIIOC_VAR_NEXT, &var);
+ if (rv == 0 && var.name == NULL) {
+ /*
+ * oops, too little space. Try again.
+ */
+ void *new = realloc(buf, buflen);
+ buflen = var.namesize;
+ if (new == NULL) {
+ rv = -1;
+ errno = ENOMEM;
+ goto done;
+ }
+ buf = new;
+ goto again;
+ }
+
+ if (rv == 0) {
+ *name = NULL; /* XXX */
+ var.name[var.namesize / sizeof(efi_char)] = 0; /* EFI doesn't NUL terminate */
+ rv = libefi_ucs2_to_utf8(var.name, name);
+ if (rv != 0)
+ goto errout;
+ retguid = var.vendor;
+ *guid = &retguid;
+ }
+errout:
+
+ /* XXX The linux interface expects name to be a static buffer -- fix or leak memory? */
+done:
+ return (rv_to_linux_rv(rv));
+}
+
+int
+efi_guid_cmp(const efi_guid_t *guid1, const efi_guid_t *guid2)
+{
+ uint32_t status;
+
+ return uuid_compare(guid1, guid2, &status);
+}
+
+int
+efi_guid_is_zero(const efi_guid_t *guid)
+{
+ uint32_t status;
+
+ return uuid_is_nil(guid, &status);
+}
+
+int
+efi_guid_to_name(efi_guid_t *guid, char **name)
+{
+ size_t i;
+ uint32_t status;
+
+ for (i = 0; i < nitems(guid_tbl); i++) {
+ if (uuid_equal(guid, &guid_tbl[i].guid, &status)) {
+ *name = strdup(guid_tbl[i].name);
+ return (0);
+ }
+ }
+ return (efi_guid_to_str(guid, name));
+}
+
+int
+efi_guid_to_symbol(efi_guid_t *guid __unused, char **symbol __unused)
+{
+
+ /*
+ * Unsure what this is used for, efibootmgr doesn't use it.
+ * Leave unimplemented for now.
+ */
+ return -1;
+}
+
+int
+efi_guid_to_str(const efi_guid_t *guid, char **sp)
+{
+ uint32_t status;
+
+ /* knows efi_guid_t is a typedef of uuid_t */
+ uuid_to_string(guid, sp, &status);
+
+ return (status == uuid_s_ok ? 0 : -1);
+}
+
+int
+efi_name_to_guid(const char *name, efi_guid_t *guid)
+{
+ size_t i;
+
+ for (i = 0; i < nitems(guid_tbl); i++) {
+ if (strcmp(name, guid_tbl[i].name) == 0) {
+ *guid = guid_tbl[i].guid;
+ return (0);
+ }
+ }
+ return (efi_str_to_guid(name, guid));
+}
+
+int
+efi_set_variable(efi_guid_t guid, const char *name,
+ uint8_t *data, size_t data_size, uint32_t attributes, mode_t mode __unused)
+{
+ struct efi_var_ioc var;
+ int rv;
+
+ if (efi_open_dev() == -1)
+ return -1;
+
+ efi_var_reset(&var);
+ rv = libefi_utf8_to_ucs2(name, &var.name, &var.namesize);
+ if (rv != 0)
+ goto errout;
+ var.vendor = guid;
+ var.data = data;
+ var.datasize = data_size;
+ var.attrib = attributes;
+ rv = ioctl(efi_fd, EFIIOC_VAR_SET, &var);
+errout:
+ free(var.name);
+
+ return rv;
+}
+
+int
+efi_str_to_guid(const char *s, efi_guid_t *guid)
+{
+ uint32_t status;
+
+ /* knows efi_guid_t is a typedef of uuid_t */
+ uuid_from_string(s, guid, &status);
+
+ return (status == uuid_s_ok ? 0 : -1);
+}
+
+int
+efi_variables_supported(void)
+{
+
+ return efi_open_dev() != -1;
+}
Index: lib/libefivar/libefivar.c
===================================================================
--- lib/libefivar/libefivar.c
+++ lib/libefivar/libefivar.c
@@ -27,86 +27,105 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/ioctl.h>
#include <sys/types.h>
-#include <fcntl.h>
+#include <errno.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sys/efi.h>
+#include <machine/efi.h>
-#include "libefi_int.h"
+#include "libefivar_int.h"
-static int __iofd = -1;
+#include <stdio.h>
-static void
-iodev_fd_close(void)
-{
-
- close(__iofd);
-}
-
-static int
-iodev_fd(int *fd)
+/*
+ * If nm were converted to utf8, what what would strlen
+ * return on the resulting string?
+ */
+static size_t
+utf8_len_of_ucs2(const efi_char *nm)
{
+ size_t len;
+ efi_char c;
- *fd = __iofd;
- if (__iofd != -1)
- return (0);
-
- __iofd = open("/dev/io", O_RDWR);
- if (__iofd == -1)
- return (errno);
+ len = 0;
+ while (*nm) {
+ c = *nm++;
+ if (c > 0x7ff)
+ len += 3;
+ else if (c > 0x7f)
+ len += 2;
+ else
+ len++;
+ }
- atexit(iodev_fd_close);
- *fd = __iofd;
- return (0);
+ return (len);
}
int
-libefi_ucs2_to_utf8(u_short *nm, size_t *szp, char *name)
+libefi_ucs2_to_utf8(const efi_char *nm, char **name)
{
size_t len, sz;
- u_short c;
+ efi_char c;
+ char *cp;
+ int freeit = *name == NULL;
+ sz = utf8_len_of_ucs2(nm) + 1;
len = 0;
- sz = *szp;
+ if (*name != NULL)
+ cp = *name;
+ else
+ cp = *name = malloc(sz);
+ if (*name == NULL)
+ return (ENOMEM);
+
while (*nm) {
c = *nm++;
if (c > 0x7ff) {
if (len++ < sz)
- *name++ = 0xE0 | (c >> 12);
+ *cp++ = (char)(0xE0 | (c >> 12));
if (len++ < sz)
- *name++ = 0x80 | ((c >> 6) & 0x3f);
+ *cp++ = (char)(0x80 | ((c >> 6) & 0x3f));
if (len++ < sz)
- *name++ = 0x80 | (c & 0x3f);
+ *cp++ = (char)(0x80 | (c & 0x3f));
} else if (c > 0x7f) {
if (len++ < sz)
- *name++ = 0xC0 | ((c >> 6) & 0x1f);
+ *cp++ = (char)(0xC0 | ((c >> 6) & 0x1f));
if (len++ < sz)
- *name++ = 0x80 | (c & 0x3f);
+ *cp++ = (char)(0x80 | (c & 0x3f));
} else {
if (len++ < sz)
- *name++ = (c & 0x7f);
+ *cp++ = (char)(c & 0x7f);
}
}
- if (len++ < sz)
- *name++ = 0;
- *szp = len;
- return ((len <= sz) ? 0 : EOVERFLOW);
+ if (len >= sz) {
+ /* Absent bugs, we'll never return EOVERFLOW */
+ if (freeit)
+ free(*name);
+ return (EOVERFLOW);
+ }
+ *cp++ = '\0';
+
+ return (0);
}
int
-libefi_utf8_to_ucs2(char *name, size_t *szp, u_short **nmp)
+libefi_utf8_to_ucs2(const char *name, efi_char **nmp, size_t *len)
{
- u_short *nm;
+ efi_char *nm;
size_t sz;
uint32_t ucs4;
int c, bytes;
+ int freeit = *nmp == NULL;
- *szp = sz = (*szp == 0) ? strlen(name) * 2 + 2 : *szp;
- *nmp = nm = malloc(sz);
+ sz = strlen(name) * 2 + 2;
+ if (*nmp == NULL)
+ *nmp = malloc(sz);
+ nm = *nmp;
+ *len = sz;
ucs4 = 0;
bytes = 0;
@@ -119,7 +138,8 @@
if ((c & 0xc0) != 0x80) {
/* Initial characters. */
if (bytes != 0) {
- free(nm);
+ if (freeit)
+ free(nm);
return (EILSEQ);
}
if ((c & 0xf8) == 0xf0) {
@@ -141,36 +161,28 @@
ucs4 = (ucs4 << 6) + (c & 0x3f);
bytes--;
} else if (bytes == 0) {
- free(nm);
+ if (freeit)
+ free(nm);
return (EILSEQ);
}
}
if (bytes == 0) {
if (ucs4 > 0xffff) {
- free(nm);
+ if (freeit)
+ free(nm);
return (EILSEQ);
}
- *nm++ = (u_short)ucs4;
+ *nm++ = (efi_char)ucs4;
sz -= 2;
}
}
if (sz < 2) {
- free(nm);
+ if (freeit)
+ free(nm);
return (EDOOFUS);
}
+ sz -= 2;
*nm = 0;
+ *len -= sz;
return (0);
}
-
-int
-libefi_efivar(struct iodev_efivar_req *req)
-{
- int error, fd;
-
- error = iodev_fd(&fd);
- if (!error)
- error = (ioctl(fd, IODEV_EFIVAR, req) == -1) ? errno : 0;
- if (!error)
- error = req->result;
- return (error);
-}
Index: lib/libefivar/libefivar_int.h
===================================================================
--- lib/libefivar/libefivar_int.h
+++ lib/libefivar/libefivar_int.h
@@ -29,12 +29,7 @@
#ifndef _LIBEFI_INT_H_
#define _LIBEFI_INT_H_
-#include <sys/errno.h>
-#include <machine/iodev.h>
-
-int libefi_ucs2_to_utf8(u_short *, size_t *, char *);
-int libefi_utf8_to_ucs2(char *, size_t *, u_short **);
-
-int libefi_efivar(struct iodev_efivar_req *);
+int libefi_ucs2_to_utf8(const efi_char *, char **);
+int libefi_utf8_to_ucs2(const char *, efi_char **, size_t *);
#endif /* _LIBEFI_INT_H_ */
Index: share/mk/bsd.libnames.mk
===================================================================
--- share/mk/bsd.libnames.mk
+++ share/mk/bsd.libnames.mk
@@ -59,6 +59,7 @@
LIBDTRACE?= ${DESTDIR}${LIBDIR}/libdtrace.a
LIBDWARF?= ${DESTDIR}${LIBDIR}/libdwarf.a
LIBEDIT?= ${DESTDIR}${LIBDIR}/libedit.a
+LIBEFIVAR?= ${DESTDIR}${LIBDIR}/libefivar.a
LIBELF?= ${DESTDIR}${LIBDIR}/libelf.a
LIBEXECINFO?= ${DESTDIR}${LIBDIR}/libexecinfo.a
LIBFETCH?= ${DESTDIR}${LIBDIR}/libfetch.a
Index: share/mk/src.libnames.mk
===================================================================
--- share/mk/src.libnames.mk
+++ share/mk/src.libnames.mk
@@ -91,6 +91,7 @@
dtrace \
dwarf \
edit \
+ efivar \
elf \
execinfo \
fetch \
Index: share/mk/src.opts.mk
===================================================================
--- share/mk/src.opts.mk
+++ share/mk/src.opts.mk
@@ -82,6 +82,7 @@
DYNAMICROOT \
ED_CRYPTO \
EE \
+ EFI \
ELFCOPY_AS_OBJCOPY \
ELFTOOLCHAIN_BOOTSTRAP \
EXAMPLES \
@@ -264,6 +265,9 @@
.if ${__T:Mmips*}
BROKEN_OPTIONS+=SSP
.endif
+.if ${__T:Mmips*} || ${__T:Mpowerpc*} || ${__T:Msparc64} || ${__T:Mriscv*}
+BROKEN_OPTIONS+=EFI
+.endif
.include <bsd.mkopt.mk>
Index: sys/amd64/amd64/efirt.c
===================================================================
--- sys/amd64/amd64/efirt.c
+++ sys/amd64/amd64/efirt.c
@@ -419,6 +419,13 @@
}
int
+efi_rt_avail(void)
+{
+
+ return (efi_runtime != 0);
+}
+
+int
efi_get_table(struct uuid *uuid, void **ptr)
{
struct efi_cfgtbl *ct;
Index: sys/amd64/conf/GENERIC.efi
===================================================================
--- /dev/null
+++ sys/amd64/conf/GENERIC.efi
@@ -0,0 +1,3 @@
+include GENERIC
+device efirt
+# device efidev
Index: sys/amd64/include/efi.h
===================================================================
--- sys/amd64/include/efi.h
+++ sys/amd64/include/efi.h
@@ -47,6 +47,7 @@
int efi_get_time(struct efi_tm *tm);
int efi_get_time_locked(struct efi_tm *tm);
int efi_reset_system(void);
+int efi_rt_avail(void);
int efi_set_time(struct efi_tm *tm);
int efi_set_time_locked(struct efi_tm *tm);
int efi_var_get(uint16_t *name, struct uuid *vendor, uint32_t *attrib,
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -1430,6 +1430,7 @@
dev/ed/if_ed_rtl80x9.c optional ed
dev/ed/if_ed_pccard.c optional ed pccard
dev/ed/if_ed_pci.c optional ed pci
+dev/efidev/efidev.c optional efidev
dev/eisa/eisa_if.m standard
dev/eisa/eisaconf.c optional eisa
dev/e1000/if_em.c optional em \
Index: sys/dev/efidev/efidev.c
===================================================================
--- /dev/null
+++ sys/dev/efidev/efidev.c
@@ -0,0 +1,268 @@
+/*-
+ * Copyright (c) 2016 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#include <machine/efi.h>
+#include <sys/efiio.h>
+
+static d_ioctl_t efidev_ioctl;
+
+static struct cdevsw efi_cdevsw = {
+ .d_name = "efi",
+ .d_version = D_VERSION,
+ .d_ioctl = efidev_ioctl,
+};
+
+/* ARGSUSED */
+static int
+efidev_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr,
+ int flags __unused, struct thread *td __unused)
+{
+ int error;
+
+ switch (cmd) {
+ case EFIIOC_GET_TABLE:
+ {
+ struct efi_get_table_ioc *egtioc =
+ (struct efi_get_table_ioc *)addr;
+
+ error = efi_get_table(&egtioc->uuid, &egtioc->ptr);
+ break;
+ }
+ case EFIIOC_GET_TIME:
+ {
+ struct efi_tm *tm = (struct efi_tm *)addr;
+
+ error = efi_get_time(tm);
+ break;
+ }
+ case EFIIOC_SET_TIME:
+ {
+ struct efi_tm *tm = (struct efi_tm *)addr;
+
+ error = efi_set_time(tm);
+ break;
+ }
+ case EFIIOC_VAR_GET:
+ {
+ struct efi_var_ioc *ev = (struct efi_var_ioc *)addr;
+ void *data = NULL;
+ efi_char *name = NULL;
+
+ data = malloc(ev->datasize, M_TEMP, M_WAITOK);
+ if (data == NULL) {
+ error = ENOMEM;
+ goto vg_out;
+ }
+ name = malloc(ev->namesize, M_TEMP, M_WAITOK);
+ if (name == NULL) {
+ error = ENOMEM;
+ goto vg_out;
+ }
+ error = copyin(ev->name, name, ev->namesize);
+ if (error)
+ goto vg_out;
+ if (name[ev->namesize / sizeof(efi_char)] != 0) {
+ error = EINVAL;
+ goto vg_out;
+ }
+
+ error = efi_var_get(name, &ev->vendor, &ev->attrib,
+ &ev->datasize, data);
+
+ if (error == 0) {
+ error = copyout(data, ev->data, ev->datasize);
+ } else if (error == EOVERFLOW) {
+ /*
+ * Pass back the size we really need, but
+ * convert the error to 0 so the copyout
+ * happens. datasize was updated in the
+ * efi_var_get call.
+ */
+ ev->data = NULL;
+ error = 0;
+ }
+ vg_out:
+ if (data != NULL)
+ free(data, M_TEMP);
+ if (name != NULL)
+ free(name, M_TEMP);
+ break;
+ }
+ case EFIIOC_VAR_NEXT:
+ {
+ struct efi_var_ioc *ev = (struct efi_var_ioc *)addr;
+ efi_char *name = NULL;
+
+ name = malloc(ev->namesize, M_TEMP, M_WAITOK);
+ if (name == NULL) {
+ error = ENOMEM;
+ goto vn_out;
+ }
+ error = copyin(ev->name, name, ev->namesize);
+ if (error)
+ goto vn_out;
+ /* Note: namesize is the buffer size, not the string lenght */
+
+ error = efi_var_nextname(&ev->namesize, name, &ev->vendor);
+ if (error == 0) {
+ error = copyout(name, ev->name, ev->namesize);
+ } else if (error == EOVERFLOW) {
+ ev->name = NULL;
+ error = 0;
+ }
+ vn_out:
+ if (name != NULL)
+ free(name, M_TEMP);
+ break;
+ }
+ case EFIIOC_VAR_SET:
+ {
+ struct efi_var_ioc *ev = (struct efi_var_ioc *)addr;
+ void *data = NULL;
+ efi_char *name = NULL;
+
+ /* datasize == 0 -> delete (more or less) */
+ if (ev->datasize > 0) {
+ data = malloc(ev->datasize, M_TEMP, M_WAITOK);
+ if (data == NULL) {
+ error = ENOMEM;
+ goto vs_out;
+ }
+ }
+ name = malloc(ev->namesize, M_TEMP, M_WAITOK);
+ if (name == NULL) {
+ error = ENOMEM;
+ goto vs_out;
+ }
+ if (ev->datasize) {
+ error = copyin(ev->data, data, ev->datasize);
+ if (error)
+ goto vs_out;
+ }
+ error = copyin(ev->name, name, ev->namesize);
+ if (error)
+ goto vs_out;
+ if (name[ev->namesize / sizeof(efi_char)] != 0) {
+ error = EINVAL;
+ goto vg_out;
+ }
+
+ error = efi_var_set(name, &ev->vendor, ev->attrib, ev->datasize,
+ data);
+ vs_out:
+ if (data != NULL)
+ free(data, M_TEMP);
+ if (name != NULL)
+ free(name, M_TEMP);
+ break;
+ }
+ default:
+ error = ENOTTY;
+ break;
+ }
+
+ return (error);
+}
+
+struct efidev_softc
+{
+ struct cdev *cdev;
+};
+
+static void
+efidev_identify(driver_t * driver, device_t parent)
+{
+ device_t child;
+
+ child = device_find_child(parent, driver->name, 0);
+ if (child == NULL)
+ child = BUS_ADD_CHILD(parent, 0, "efidev", -1);
+ device_set_driver(child, driver);
+}
+
+static int
+efidev_probe(device_t dev)
+{
+ if (!efi_rt_avail())
+ return (ENXIO);
+
+ device_set_desc(dev, "efi runtime services");
+ return (0);
+}
+
+static int
+efidev_attach(device_t dev)
+{
+ struct efidev_softc *sc;
+
+ sc = device_get_softc(dev);
+ sc->cdev = make_dev(&efi_cdevsw, 0, UID_ROOT, GID_WHEEL, 0700,
+ "efidev");
+
+ return (0);
+}
+static int
+efidev_detach(device_t dev)
+{
+ struct efidev_softc *sc;
+
+ sc = device_get_softc(dev);
+ destroy_dev(sc->cdev);
+
+ return (0);
+}
+
+static device_method_t efidev_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, efidev_identify),
+ DEVMETHOD(device_probe, efidev_probe),
+ DEVMETHOD(device_attach, efidev_attach),
+ DEVMETHOD(device_detach, efidev_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t efidev_driver = {
+ "efidev",
+ efidev_methods,
+ sizeof(struct efidev_softc),
+};
+
+static devclass_t efidev_devclass;
+DRIVER_MODULE(efidev, nexus, efidev_driver, efidev_devclass, NULL, NULL);
+MODULE_VERSION(efidev, 1);
Index: sys/i386/include/efi.h
===================================================================
--- sys/i386/include/efi.h
+++ sys/i386/include/efi.h
@@ -1,7 +1,10 @@
/*-
- * Copyright (c) 2010 Marcel Moolenaar
+ * Copyright (c) 2016 The FreeBSD Foundation
* All rights reserved.
*
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -14,7 +17,7 @@
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -22,45 +25,15 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
+ * $FreeBSD$
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <libefi.h>
-#include <stdlib.h>
-
-#include "libefi_int.h"
-
-/*
- * EFI_STATUS
- * SetVariable(
- * IN CHAR16 *VariableName,
- * IN EFI_GUID *VendorGuid,
- * IN UINT32 Attributes,
- * IN UINTN DataSize,
- * IN VOID *Data
- * );
- */
+#ifndef __I386_INCLUDE_EFI_H_
+#define __I386_INCLUDE_EFI_H_
-int
-efi_setvar(char *name, uuid_t *vendor, uint32_t attrib, size_t datasize,
- void *data)
-{
- struct iodev_efivar_req req;
- int error;
+#define EFIABI_ATTR
- req.namesize = 0;
- error = libefi_utf8_to_ucs2(name, &req.namesize, &req.name);
- if (error)
- return (error);
+/* Note: we don't actually support this on i386 yet */
- req.vendor = *vendor;
- req.attrib = attrib;
- req.datasize = datasize;
- req.data = data;
- req.access = IODEV_EFIVAR_SETVAR;
- error = libefi_efivar(&req);
- free(req.name);
- return (error);
-}
+#endif /* __I386_INCLUDE_EFI_H_ */
Index: sys/modules/Makefile
===================================================================
--- sys/modules/Makefile
+++ sys/modules/Makefile
@@ -103,6 +103,7 @@
${_drm2} \
dummynet \
${_ed} \
+ ${_efidev} \
${_efirt} \
${_elink} \
${_em} \
@@ -672,6 +673,7 @@
.endif
.if ${MACHINE_CPUARCH} == "amd64"
+_efidev= efidev
_efirt= efirt
_ioat= ioat
_ixl= ixl
Index: sys/modules/efidev/Makefile
===================================================================
--- /dev/null
+++ sys/modules/efidev/Makefile
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/efidev
+
+KMOD = efidev
+SRCS = efidev.c
+SRCS += bus_if.h device_if.h
+
+.include <bsd.kmod.mk>
Index: sys/sys/efiio.h
===================================================================
--- /dev/null
+++ sys/sys/efiio.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2016 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_EFIIO_H_
+#define _SYS_EFIIO_H_
+
+#include <sys/ioccom.h>
+#include <sys/uuid.h>
+#include <sys/efi.h>
+
+struct efi_get_table_ioc
+{
+ struct uuid uuid; /* UUID to look up */
+ void *ptr; /* Pointer to table in KVA space */
+};
+
+struct efi_var_ioc
+{
+ efi_char *name; /* User pointer to name, in wide chars */
+ size_t namesize; /* Number of wide characters in name */
+ struct uuid vendor; /* Vendor's UUID for variable */
+ uint32_t attrib; /* Attributes */
+ void *data; /* User pointer to the data */
+ size_t datasize; /* Number of *bytes* in the data */
+};
+
+#define EFIIOC_GET_TABLE _IOWR('E', 1, struct efi_get_table_ioc)
+#define EFIIOC_GET_TIME _IOR('E', 2, struct efi_tm)
+#define EFIIOC_SET_TIME _IOW('E', 3, struct efi_tm)
+#define EFIIOC_VAR_GET _IOWR('E', 4, struct efi_var_ioc)
+#define EFIIOC_VAR_NEXT _IOWR('E', 5, struct efi_var_ioc)
+#define EFIIOC_VAR_SET _IOWR('E', 6, struct efi_var_ioc)
+
+#endif /* _SYS_EFIIO_H_ */
Index: usr.sbin/Makefile
===================================================================
--- usr.sbin/Makefile
+++ usr.sbin/Makefile
@@ -123,6 +123,7 @@
SUBDIR.${MK_CTM}+= ctm
SUBDIR.${MK_DIALOG}+= tzsetup
SUBDIR.${MK_DIALOG}+= bsdconfig
+SUBDIR.${MK_EFI}+= efivar
SUBDIR.${MK_FLOPPY}+= fdcontrol
SUBDIR.${MK_FLOPPY}+= fdformat
SUBDIR.${MK_FLOPPY}+= fdread
Index: usr.sbin/efivar/Makefile
===================================================================
--- /dev/null
+++ usr.sbin/efivar/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+PROG= efivar
+MAN= efivar.8
+
+LIBADD= efivar
+
+.include <bsd.prog.mk>
Index: usr.sbin/efivar/efivar.8
===================================================================
--- /dev/null
+++ usr.sbin/efivar/efivar.8
@@ -0,0 +1,164 @@
+.\" Copyright (c) 2003 Netflix, Inc
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 29, 2016
+.Dt EFIVAR 8
+.Os
+.Sh NAME
+.Nm efivar
+.Nd UEFI environemnt variable interaction
+.Sh SYNOPSIS
+.Nm
+.Op Fl abdDHlLNpRtw
+.Op Fl n Ar name
+.Op Fl f Ar file
+.Op Fl -append
+.Op Fl -ascii
+.Op Fl -attributes
+.Op Fl -binary
+.Op Fl -delete
+.Op Fl -fromfile Ar file
+.Op Fl -hex
+.Op Fl -list-guids
+.Op Fl -list
+.Op Fl -name Ar name
+.Op Fl -no-name
+.Op Fl -print
+.Op Fl -print-decimal
+.Op Fl -raw-guid
+.Op Fl -write
+.Ar name Ns Op = Ns Ar value
+.Sh DESCRIPTION
+This program manages
+.Dq Unified Extensible Firmware Interface
+.Pq UEFI
+environment variables.
+UEFI variables have three part: A namespace, a name and a value.
+The namespace is a GUID that's self assigned by the group defining the
+variables.
+The name is a Unicode name for the variable.
+The value is binary data.
+All Unicode data is presented to the user as UTF-8.
+.Pp
+The following options are available:
+.Bl -tag -width 20m
+.It Fl n Ar name Fl -name Ar name
+Specify the name of the variable to operate on.
+The
+.Ar name
+argument is the GUID of variable, followed by a dash, followed by the
+UEFI variable name.
+The GUID may be in numeric format, or may be one of the well known
+symbolic name (see
+.Fl -list-guids
+for a complete list).
+.It Fl f Ar file Fl -fromfile Ar file
+When writing or appending to a variable, take the data for the
+variable's value from
+.Ar file
+instead of from the command line.
+This flag implies
+.Fl -write
+unless the
+.Fl -append
+flag is given.
+This is not well understood and currently unimplemented.
+.It Fl a Fl -append
+Append the specified value to the UEFI variable rather than replacing
+it.p
+.It Fl t Ar attr Fl -attributes Ar attr
+Specify, in user hostile hexidecimal, the attributes for this
+variable.
+See section 7.2 (GetVariable subsection, Related Definitions) of the
+UEFI Specification for hex values to use.
+.It Fl A Fl -ascii
+Display the variable data as modified ascii: All printable characters
+are printed, while unprintable characters are rendered as a two-digit
+hexadecimal number preceeded by a % character.
+.It Fl A Fl -binary
+Display the variable data as binary data.
+Usually will be used with the
+.Fl N
+or
+.Fl -no-name
+flag.
+Useful in scripts.
+.It Fl D Fl -delete
+Delete the specified variable.
+May not be used with either the
+.Fl -write
+or the
+.Fl -append
+flags.
+No
+.Ar value
+may be specified.
+.It Fl H Fl -hex
+List variable data as a hex dump.
+.It Fl L Fl -list-guids
+Lists the well known GUIDs.
+The names listed here may be used in place of the numeric GUID values.
+These names will replace the numeric GUID values unless
+.Fl -raw-guid
+flag is specified.
+.It Fl l Fl -list
+List all the variables.
+If the
+.Fl -print
+flag is also listed, their values will be displayed.
+.It Fl N Fl -no-name
+Do not display the variable name.
+.It Fl p Fl -print
+Print the value of the variable.
+.It Fl d Fl -print-decimal
+Treat the value of the variable as a number and print it as a
+decimal.
+This is currently unimplemented.
+.It Fl R Fl -raw-guid
+Do not substitute well known names for GUID numeric values in output.
+.It Fl w Fl -write
+Write (replace) the variable specified with the value specified.
+.It Ar name
+Display the
+.Ar name
+environment variable.
+.It Ar name Ns = Ns Ar value
+Set the specified
+.Ar name
+to
+.Ar value .
+This is not yet implemented.
+.Sh COMPATIBILITY
+The
+.Nm
+program is intended to be compatible (strict superset) with a progam
+of the same name included in the Red Hat libefivar package.
+.Sh SEE ALSO
+Appendix A of the UEFI specification has the format for GUIDs.
+All GUIDs
+.Dq Globally Unique Identifiers
+have the format described in RFC 4122.
+.El
Index: usr.sbin/efivar/efivar.c
===================================================================
--- /dev/null
+++ usr.sbin/efivar/efivar.c
@@ -0,0 +1,349 @@
+/*-
+ * Copyright (c) 2016 Netflix, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD");
+
+#include <ctype.h>
+#include <efivar.h>
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* options descriptor */
+static struct option longopts[] = {
+ { "append", no_argument, NULL, 'a' },
+ { "ascii", no_argument, NULL, 'A' },
+ { "attributes", required_argument, NULL, 't' },
+ { "binary", no_argument, NULL, 'b' },
+ { "delete", no_argument, NULL, 'D' },
+ { "fromfile", required_argument, NULL, 'f' },
+ { "hex", no_argument, NULL, 'H' },
+ { "list-guids", no_argument, NULL, 'L' },
+ { "list", no_argument, NULL, 'l' },
+ { "name", required_argument, NULL, 'n' },
+ { "no-name", no_argument, NULL, 'N' },
+ { "print", no_argument, NULL, 'p' },
+ { "print-decimal", no_argument, NULL, 'd' },
+ { "raw-guid", no_argument, NULL, 'R' },
+ { "write", no_argument, NULL, 'w' },
+ { NULL, 0, NULL, 0 }
+};
+
+
+static int aflag, Aflag, bflag, dflag, Dflag, Hflag, Nflag,
+ lflag, Lflag, Rflag, wflag, pflag;
+static char *varname;
+static u_long attrib = 0x7;
+
+static void
+usage(void)
+{
+
+ errx(1, "efivar [-abdDHlLNpRtw] [-n name] [-f file] [--append] [--ascii]\n"
+ "\t[--attributes] [--binary] [--delete] [--fromfile file] [--hex]\n"
+ "\t[--list-guids] [--list] [--name name] [--no-name] [--print]\n"
+ "\t[--print-decimal] [--raw-guid] [--write] name[=value]");
+}
+
+static void
+breakdown_name(char *name, efi_guid_t *guid, char **vname)
+{
+ char *cp;
+
+ cp = strrchr(name, '-');
+ if (cp == NULL)
+ errx(1, "Invalid name: %s", name);
+ *vname = cp + 1;
+ *cp = '\0';
+ if (efi_str_to_guid(name, guid) < 0)
+ errx(1, "Invalid guid %s", name);
+}
+
+static uint8_t *
+get_value(char *val, size_t *datalen)
+{
+ static char buffer[16*1024];
+
+ if (val != NULL) {
+ *datalen = strlen(val);
+ return ((uint8_t *)val);
+ }
+ /* Read from stdin */
+ *datalen = sizeof(buffer);
+ *datalen = read(0, buffer, *datalen);
+ return ((uint8_t *)buffer);
+}
+
+static void
+append_variable(char *name, char *val)
+{
+ char *vname;
+ efi_guid_t guid;
+ size_t datalen;
+ uint8_t *data;
+
+ breakdown_name(name, &guid, &vname);
+ data = get_value(val, &datalen);
+ if (efi_append_variable(guid, vname, data, datalen, attrib) < 0)
+ err(1, "efi_append_variable");
+}
+
+static void
+delete_variable(char *name)
+{
+ char *vname;
+ efi_guid_t guid;
+
+ breakdown_name(name, &guid, &vname);
+ if (efi_del_variable(guid, vname) < 0)
+ err(1, "efi_del_variable");
+}
+
+static void
+write_variable(char *name, char *val)
+{
+ char *vname;
+ efi_guid_t guid;
+ size_t datalen;
+ uint8_t *data;
+
+ breakdown_name(name, &guid, &vname);
+ data = get_value(val, &datalen);
+ if (efi_set_variable(guid, vname, data, datalen, attrib, 0) < 0)
+ err(1, "efi_set_variable");
+}
+
+static void
+asciidump(uint8_t *data, size_t datalen)
+{
+ size_t i;
+ int len;
+
+ len = 0;
+ if (!Nflag)
+ printf("\n");
+ for (i = 0; i < datalen; i++) {
+ if (isprint(data[i])) {
+ len++;
+ if (len > 80) {
+ len = 0;
+ printf("\n");
+ }
+ printf("%c", data[i]);
+ } else {
+ len +=3;
+ if (len > 80) {
+ len = 0;
+ printf("\n");
+ }
+ printf("%%%02x", data[i]);
+ }
+ }
+ printf("\n");
+}
+
+static void
+hexdump(uint8_t *data, size_t datalen)
+{
+ size_t i;
+
+ if (!Nflag)
+ printf("\n");
+ for (i = 0; i < datalen; i++) {
+ if (i % 16 == 0) {
+ if (i != 0)
+ printf("\n");
+ printf("%04x: ", (int)i);
+ }
+ printf("%02x ", data[i]);
+ }
+ printf("\n");
+}
+
+static void
+bindump(uint8_t *data, size_t datalen)
+{
+ write(1, data, datalen);
+}
+
+static void
+print_var(efi_guid_t *guid, char *name)
+{
+ uint32_t att;
+ uint8_t *data;
+ size_t datalen;
+ char *gname;
+ int rv;
+
+ efi_guid_to_str(guid, &gname);
+ if (!Nflag)
+ printf("%s-%s", gname, name);
+ if (pflag) {
+ rv = efi_get_variable(*guid, name, &data, &datalen, &att);
+
+ if (rv < 0)
+ printf("\n --- Error getting value --- %d", errno);
+ else {
+ if (Aflag)
+ asciidump(data, datalen);
+ else if (bflag)
+ bindump(data, datalen);
+ else
+ hexdump(data, datalen);
+ }
+ }
+ free(gname);
+ if (!Nflag)
+ printf("\n");
+}
+
+static void
+print_variable(char *name)
+{
+ char *vname;
+ efi_guid_t guid;
+
+ breakdown_name(name, &guid, &vname);
+ print_var(&guid, vname);
+}
+
+static void
+print_variables(void)
+{
+ int rv;
+ char *name = NULL;
+ efi_guid_t *guid = NULL;
+
+ while ((rv = efi_get_next_variable_name(&guid, &name)) > 0)
+ print_var(guid, name);
+
+ if (rv < 0)
+ err(1, "Error listing names");
+}
+
+static void
+parse_args(int argc, char **argv)
+{
+ int ch, i;
+
+ while ((ch = getopt_long(argc, argv, "aAbdDf:HlLNn:pRt:w",
+ longopts, NULL)) != -1) {
+ switch (ch) {
+ case 'a':
+ aflag++;
+ break;
+ case 'A':
+ Aflag++;
+ break;
+ case 'b':
+ bflag++;
+ break;
+ case 'd':
+ dflag++;
+ break;
+ case 'D':
+ Dflag++;
+ break;
+ case 'H':
+ Hflag++;
+ break;
+ case 'l':
+ lflag++;
+ break;
+ case 'L':
+ Lflag++;
+ break;
+ case 'n':
+ varname = optarg;
+ break;
+ case 'N':
+ Nflag++;
+ break;
+ case 'p':
+ pflag++;
+ break;
+ case 'R':
+ Rflag++;
+ break;
+ case 'w':
+ wflag++;
+ break;
+ case 'f':
+ case 't':
+ case 0:
+ errx(1, "unknown or unimplemented option\n");
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 1)
+ varname = argv[0];
+
+ if (aflag + Dflag + wflag > 1) {
+ warnx("Can only use one of -a (--append), "
+ "-D (--delete) and -w (--write)");
+ usage();
+ }
+
+ if (aflag + Dflag + wflag > 0 && varname == NULL) {
+ warnx("Must specify a variable for -a (--append), "
+ "-D (--delete) or -w (--write)");
+ usage();
+ }
+
+ if (aflag)
+ append_variable(varname, NULL);
+ else if (Dflag)
+ delete_variable(varname);
+ else if (wflag)
+ write_variable(varname, NULL);
+ else if (varname) {
+ pflag++;
+ print_variable(varname);
+ } else if (argc > 0) {
+ pflag++;
+ for (i = 0; i < argc; i++)
+ print_variable(argv[i]);
+ } else
+ print_variables();
+}
+
+int
+main(int argc, char **argv)
+{
+
+ parse_args(argc, argv);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Mar 19, 1:10 PM (21 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29964601
Default Alt Text
D8128.id20951.diff (64 KB)
Attached To
Mode
D8128: UEFI Runtime Services environment variable support.
Attached
Detach File
Event Timeline
Log In to Comment