Page MenuHomeFreeBSD

D8128.id20951.diff
No OneTemporary

D8128.id20951.diff

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

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)

Event Timeline