Implement access to EFI variables and ESRT through an ioctl(2) interface
authorkettenis <kettenis@openbsd.org>
Sat, 14 Jan 2023 12:11:10 +0000 (12:11 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 14 Jan 2023 12:11:10 +0000 (12:11 +0000)
that is compatible with what FreeBSD and NetBSD have.  Setting EFI
variables is only allowed at securelevel 0 and below.

Heavily based on work done by Sergii Dmytruk.

ok yasuoka@

13 files changed:
sys/arch/amd64/amd64/conf.c
sys/arch/amd64/amd64/efi_machdep.c
sys/arch/amd64/conf/files.amd64
sys/arch/amd64/include/efivar.h [new file with mode: 0644]
sys/arch/arm64/arm64/conf.c
sys/arch/arm64/conf/files.arm64
sys/arch/arm64/dev/efi_machdep.c
sys/arch/arm64/include/efivar.h [new file with mode: 0644]
sys/dev/efi/efi.c [new file with mode: 0644]
sys/dev/efi/efi.h
sys/dev/efi/efiio.h [new file with mode: 0644]
sys/dev/efi/files.efi [new file with mode: 0644]
sys/sys/conf.h

index eb217a5..83f0089 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.76 2022/09/02 20:06:55 miod Exp $  */
+/*     $OpenBSD: conf.c,v 1.77 2023/01/14 12:11:10 kettenis Exp $      */
 
 /*
  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
@@ -173,6 +173,7 @@ cdev_decl(pci);
 #include "fuse.h"
 #include "pvbus.h"
 #include "ipmi.h"
+#include "efi.h"
 
 struct cdevsw  cdevsw[] =
 {
@@ -272,7 +273,7 @@ struct cdevsw       cdevsw[] =
        cdev_ptm_init(NPTY,ptm),        /* 81: pseudo-tty ptm device */
        cdev_hotplug_init(NHOTPLUG,hotplug), /* 82: devices hot plugging */
        cdev_acpi_init(NACPI,acpi),     /* 83: ACPI */
-       cdev_notdef(),
+       cdev_efi_init(NEFI,efi),        /* 84: EFI */
        cdev_nvram_init(NNVRAM,nvram),  /* 85: NVRAM interface */
        cdev_notdef(),                  /* 86 */
        cdev_drm_init(NDRM,drm),        /* 87: drm */
index 40ed500..a5f4563 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: efi_machdep.c,v 1.4 2022/11/07 01:41:57 guenther Exp $        */
+/*     $OpenBSD: efi_machdep.c,v 1.5 2023/01/14 12:11:10 kettenis Exp $        */
 
 /*
  * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
 extern paddr_t cr3_reuse_pcid;
 
 #include <dev/efi/efi.h>
-
-#include <dev/clock_subr.h>
+#include <machine/efivar.h>
 
 extern EFI_MEMORY_DESCRIPTOR *mmap;
 
-struct efi_softc {
-       struct device   sc_dev;
-       struct pmap     *sc_pm;
-       EFI_RUNTIME_SERVICES *sc_rs;
-       u_long          sc_psw;
-       uint64_t        sc_cr3;
-
-       struct todr_chip_handle sc_todr;
-};
-
 int    efi_match(struct device *, void *, void *);
 void   efi_attach(struct device *, struct device *, void *);
 
@@ -50,21 +39,12 @@ const struct cfattach efi_ca = {
        sizeof(struct efi_softc), efi_match, efi_attach
 };
 
-struct cfdriver efi_cd = {
-       NULL, "efi", DV_DULL
-};
-
 void   efi_map_runtime(struct efi_softc *);
-void   efi_enter(struct efi_softc *);
-void   efi_leave(struct efi_softc *);
 int    efi_gettime(struct todr_chip_handle *, struct timeval *);
 int    efi_settime(struct todr_chip_handle *, struct timeval *);
 
 label_t efi_jmpbuf;
 
-#define efi_enter_check(sc) (setjmp(&efi_jmpbuf) ? \
-    (efi_leave(sc), EFAULT) : (efi_enter(sc), 0))
-
 int
 efi_match(struct device *parent, void *match, void *aux)
 {
@@ -124,6 +104,9 @@ efi_attach(struct device *parent, struct device *self, void *aux)
        if ((bios_efiinfo->flags & BEI_64BIT) == 0)
                return;
 
+       if (bios_efiinfo->flags & BEI_ESRT)
+               sc->sc_esrt = (void *)bios_efiinfo->config_esrt;
+
        efi_map_runtime(sc);
 
        /*
index 91c5592..cb136df 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files.amd64,v 1.106 2022/10/16 15:03:39 kettenis Exp $
+#      $OpenBSD: files.amd64,v 1.107 2023/01/14 12:11:10 kettenis Exp $
 
 maxpartitions 16
 maxusers 2 16 128
@@ -245,9 +245,9 @@ file        arch/amd64/pci/acpipci.c                acpipci
 #
 # EFI
 #
-device efi
+include "dev/efi/files.efi"
 attach efi at bios
-file   arch/amd64/amd64/efi_machdep.c          efi needs-flag
+file   arch/amd64/amd64/efi_machdep.c          efi
 
 #
 # VMM
diff --git a/sys/arch/amd64/include/efivar.h b/sys/arch/amd64/include/efivar.h
new file mode 100644 (file)
index 0000000..5db2b55
--- /dev/null
@@ -0,0 +1,42 @@
+/*     $OpenBSD: efivar.h,v 1.1 2023/01/14 12:11:10 kettenis Exp $     */
+/*
+ * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_EFIVAR_H_
+#define _MACHINE_EFIVAR_H_
+
+#include <dev/clock_subr.h>
+
+struct efi_softc {
+       struct device   sc_dev;
+       struct pmap     *sc_pm;
+       EFI_RUNTIME_SERVICES *sc_rs;
+       EFI_SYSTEM_RESOURCE_TABLE *sc_esrt;
+       u_long          sc_psw;
+       uint64_t        sc_cr3;
+
+       struct todr_chip_handle sc_todr;
+};
+
+void   efi_enter(struct efi_softc *);
+void   efi_leave(struct efi_softc *);
+
+extern label_t efi_jmpbuf;
+
+#define efi_enter_check(sc) (setjmp(&efi_jmpbuf) ? \
+    (efi_leave(sc), EFAULT) : (efi_enter(sc), 0))
+
+#endif /* _MACHINE_EFIVAR_H_ */
index b2713bc..4e47542 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.20 2022/09/02 20:06:55 miod Exp $  */
+/*     $OpenBSD: conf.c,v 1.21 2023/01/14 12:11:11 kettenis Exp $      */
 
 /*
  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
@@ -121,6 +121,7 @@ cdev_decl(pci);
 #include "openprom.h"
 #include "gpio.h"
 #include "ipmi.h"
+#include "efi.h"
 
 struct cdevsw  cdevsw[] =
 {
@@ -199,7 +200,7 @@ struct cdevsw       cdevsw[] =
            wsmouse),
        cdev_mouse_init(NWSMUX, wsmux), /* 69: ws multiplexor */
        cdev_openprom_init(NOPENPROM,openprom), /* 70: /dev/openprom */
-       cdev_notdef(),                  /* 71: was: Cyclades-Z serial port */
+       cdev_efi_init(NEFI,efi),        /* 71: EFI */
 #ifdef USER_PCICONF
        cdev_pci_init(NPCI,pci),        /* 72: PCI user */
 #else
index b30947a..9ec032f 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: files.arm64,v 1.65 2022/12/17 11:56:44 kettenis Exp $
+# $OpenBSD: files.arm64,v 1.66 2023/01/14 12:11:11 kettenis Exp $
 
 maxpartitions  16
 maxusers       2 8 128
@@ -63,9 +63,10 @@ device       simplebus: fdt
 attach simplebus at fdt
 file   arch/arm64/dev/simplebus.c              simplebus
 
-device efi {}
+# EFI
+include "dev/efi/files.efi"
 attach efi at fdt
-file   arch/arm64/dev/efi_machdep.c            efi needs-flag
+file   arch/arm64/dev/efi_machdep.c            efi
 
 device smbios
 attach smbios at efi
index 3779f9f..a37b41e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: efi_machdep.c,v 1.5 2022/11/06 11:44:30 kettenis Exp $        */
+/*     $OpenBSD: efi_machdep.c,v 1.6 2023/01/14 12:11:11 kettenis Exp $        */
 
 /*
  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
@@ -32,8 +32,7 @@
 #include <dev/ofw/fdt.h>
 
 #include <dev/efi/efi.h>
-
-#include <dev/clock_subr.h>
+#include <machine/efivar.h>
 
 /*
  * We need a large address space to allow identity mapping of physical
@@ -50,15 +49,6 @@ extern EFI_MEMORY_DESCRIPTOR *mmap;
 uint64_t efi_acpi_table;
 uint64_t efi_smbios_table;
 
-struct efi_softc {
-       struct device   sc_dev;
-       struct pmap     *sc_pm;
-       EFI_RUNTIME_SERVICES *sc_rs;
-       u_long          sc_psw;
-
-       struct todr_chip_handle sc_todr;
-};
-
 int    efi_match(struct device *, void *, void *);
 void   efi_attach(struct device *, struct device *, void *);
 
@@ -66,21 +56,12 @@ const struct cfattach efi_ca = {
        sizeof(struct efi_softc), efi_match, efi_attach
 };
 
-struct cfdriver efi_cd = {
-       NULL, "efi", DV_DULL
-};
-
 void   efi_map_runtime(struct efi_softc *);
-void   efi_enter(struct efi_softc *);
-void   efi_leave(struct efi_softc *);
 int    efi_gettime(struct todr_chip_handle *, struct timeval *);
 int    efi_settime(struct todr_chip_handle *, struct timeval *);
 
 label_t efi_jmpbuf;
 
-#define efi_enter_check(sc) (setjmp(&efi_jmpbuf) ? \
-    (efi_leave(sc), EFAULT) : (efi_enter(sc), 0))
-
 int
 efi_match(struct device *parent, void *match, void *aux)
 {
diff --git a/sys/arch/arm64/include/efivar.h b/sys/arch/arm64/include/efivar.h
new file mode 100644 (file)
index 0000000..190549a
--- /dev/null
@@ -0,0 +1,41 @@
+/*     $OpenBSD: efivar.h,v 1.1 2023/01/14 12:11:11 kettenis Exp $     */
+/*
+ * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _MACHINE_EFIVAR_H_
+#define _MACHINE_EFIVAR_H_
+
+#include <dev/clock_subr.h>
+
+struct efi_softc {
+       struct device   sc_dev;
+       struct pmap     *sc_pm;
+       EFI_RUNTIME_SERVICES *sc_rs;
+       EFI_SYSTEM_RESOURCE_TABLE *sc_esrt;
+       u_long          sc_psw;
+
+       struct todr_chip_handle sc_todr;
+};
+
+void   efi_enter(struct efi_softc *);
+void   efi_leave(struct efi_softc *);
+
+extern label_t efi_jmpbuf;
+
+#define efi_enter_check(sc) (setjmp(&efi_jmpbuf) ? \
+    (efi_leave(sc), EFAULT) : (efi_enter(sc), 0))
+
+#endif /* _MACHINE_EFIVAR_H_ */
diff --git a/sys/dev/efi/efi.c b/sys/dev/efi/efi.c
new file mode 100644 (file)
index 0000000..6f8b37b
--- /dev/null
@@ -0,0 +1,284 @@
+/*     $OpenBSD: efi.c,v 1.1 2023/01/14 12:11:11 kettenis Exp $        */
+/*
+ * Copyright (c) 2022 3mdeb <contact@3mdeb.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+
+#include <dev/efi/efi.h>
+#include <dev/efi/efiio.h>
+#include <machine/efivar.h>
+
+struct cfdriver efi_cd = {
+       NULL, "efi", DV_DULL
+};
+
+int    efiioc_get_table(struct efi_softc *sc, void *);
+int    efiioc_var_get(struct efi_softc *sc, void *);
+int    efiioc_var_next(struct efi_softc *sc, void *);
+int    efiioc_var_set(struct efi_softc *sc, void *);
+int    efi_adapt_error(EFI_STATUS);
+
+int
+efiopen(dev_t dev, int flag, int mode, struct proc *p)
+{
+       return (efi_cd.cd_ndevs > 0 ? 0 : ENXIO);
+}
+
+int
+eficlose(dev_t dev, int flag, int mode, struct proc *p)
+{
+       return 0;
+}
+
+int
+efiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
+{
+       struct efi_softc *sc = efi_cd.cd_devs[0];
+       int error;
+
+       switch (cmd) {
+       case EFIIOC_GET_TABLE:
+               error = efiioc_get_table(sc, data);
+               break;
+       case EFIIOC_VAR_GET:
+               error = efiioc_var_get(sc, data);
+               break;
+       case EFIIOC_VAR_NEXT:
+               error = efiioc_var_next(sc, data);
+               break;
+       case EFIIOC_VAR_SET:
+               error = efiioc_var_set(sc, data);
+               break;
+       default:
+               error = ENOTTY;
+               break;
+       }
+
+       return error;
+}
+
+int
+efiioc_get_table(struct efi_softc *sc, void *data)
+{
+       EFI_GUID esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID;
+       struct efi_get_table_ioc *ioc = data;
+       char *buf = NULL;
+       int error;
+
+       /* Only ESRT is supported at the moment. */
+       if (memcmp(&ioc->uuid, &esrt_guid, sizeof(ioc->uuid)) != 0)
+               return EINVAL;
+
+       /* ESRT might not be present. */
+       if (sc->sc_esrt == NULL)
+               return ENXIO;
+
+       if (efi_enter_check(sc)) {
+               free(buf, M_TEMP, ioc->table_len);
+               return ENOSYS;
+       }
+
+       ioc->table_len = sizeof(*sc->sc_esrt) +
+           sizeof(EFI_SYSTEM_RESOURCE_ENTRY) * sc->sc_esrt->FwResourceCount;
+
+       /* Return table length to userspace. */
+       if (ioc->buf == NULL) {
+               efi_leave(sc);
+               return 0;
+       }
+
+       /* Refuse to copy only part of the table. */
+       if (ioc->buf_len < ioc->table_len) {
+               efi_leave(sc);
+               return EINVAL;
+       }
+
+       buf = malloc(ioc->table_len, M_TEMP, M_WAITOK);
+       memcpy(buf, sc->sc_esrt, ioc->table_len);
+
+       efi_leave(sc);
+
+       error = copyout(buf, ioc->buf, ioc->table_len);
+       free(buf, M_TEMP, ioc->table_len);
+
+       return error;
+}
+
+int
+efiioc_var_get(struct efi_softc *sc, void *data)
+{
+       struct efi_var_ioc *ioc = data;
+       void *value = NULL;
+       efi_char *name = NULL;
+       size_t valuesize = ioc->datasize;
+       EFI_STATUS status;
+       int error;
+
+       if (valuesize > 0)
+               value = malloc(valuesize, M_TEMP, M_WAITOK);
+       name = malloc(ioc->namesize, M_TEMP, M_WAITOK);
+       error = copyin(ioc->name, name, ioc->namesize);
+       if (error != 0)
+               goto leave;
+
+       /* NULL-terminated name must fit into namesize bytes. */
+       if (name[ioc->namesize / sizeof(*name) - 1] != 0) {
+               error = EINVAL;
+               goto leave;
+       }
+
+       if (efi_enter_check(sc)) {
+               error = ENOSYS;
+               goto leave;
+       }
+       status = sc->sc_rs->GetVariable(name, (EFI_GUID *)&ioc->vendor,
+           &ioc->attrib, &ioc->datasize, value);
+       efi_leave(sc);
+
+       if (status == EFI_BUFFER_TOO_SMALL) {
+               /*
+                * Return size of the value, which was set by EFI RT,
+                * reporting no error to match FreeBSD's behaviour.
+                */
+               ioc->data = NULL;
+               goto leave;
+       }
+
+       error = efi_adapt_error(status);
+       if (error == 0)
+               error = copyout(value, ioc->data, ioc->datasize);
+
+leave:
+       free(value, M_TEMP, valuesize);
+       free(name, M_TEMP, ioc->namesize);
+       return error;
+}
+
+int
+efiioc_var_next(struct efi_softc *sc, void *data)
+{
+       struct efi_var_ioc *ioc = data;
+       efi_char *name;
+       size_t namesize = ioc->namesize;
+       EFI_STATUS status;
+       int error;
+
+       name = malloc(namesize, M_TEMP, M_WAITOK);
+       error = copyin(ioc->name, name, namesize);
+       if (error)
+               goto leave;
+
+       if (efi_enter_check(sc)) {
+               error = ENOSYS;
+               goto leave;
+       }
+       status = sc->sc_rs->GetNextVariableName(&ioc->namesize,
+           name, (EFI_GUID *)&ioc->vendor);
+       efi_leave(sc);
+
+       if (status == EFI_BUFFER_TOO_SMALL) {
+               /*
+                * Return size of the name, which was set by EFI RT,
+                * reporting no error to match FreeBSD's behaviour.
+                */
+               ioc->name = NULL;
+               goto leave;
+       }
+
+       error = efi_adapt_error(status);
+       if (error == 0)
+               error = copyout(name, ioc->name, ioc->namesize);
+
+leave:
+       free(name, M_TEMP, namesize);
+       return error;
+}
+
+int
+efiioc_var_set(struct efi_softc *sc, void *data)
+{
+       struct efi_var_ioc *ioc = data;
+       void *value = NULL;
+       efi_char *name = NULL;
+       EFI_STATUS status;
+       int error;
+
+       /* Zero datasize means variable deletion. */
+       if (ioc->datasize > 0) {
+               value = malloc(ioc->datasize, M_TEMP, M_WAITOK);
+               error = copyin(ioc->data, value, ioc->datasize);
+               if (error)
+                       goto leave;
+       }
+
+       name = malloc(ioc->namesize, M_TEMP, M_WAITOK);
+       error = copyin(ioc->name, name, ioc->namesize);
+       if (error)
+               goto leave;
+
+       /* NULL-terminated name must fit into namesize bytes. */
+       if (name[ioc->namesize / sizeof(*name) - 1] != 0) {
+               error = EINVAL;
+               goto leave;
+       }
+
+       if (securelevel > 0) {
+               error = EPERM;
+               goto leave;
+       }
+
+       if (efi_enter_check(sc)) {
+               error = ENOSYS;
+               goto leave;
+       }
+       status = sc->sc_rs->SetVariable(name, (EFI_GUID *)&ioc->vendor,
+           ioc->attrib, ioc->datasize, value);
+       efi_leave(sc);
+
+       error = efi_adapt_error(status);
+
+leave:
+       free(value, M_TEMP, ioc->datasize);
+       free(name, M_TEMP, ioc->namesize);
+       return error;
+}
+
+int
+efi_adapt_error(EFI_STATUS status)
+{
+       switch (status) {
+       case EFI_SUCCESS:
+               return 0;
+       case EFI_DEVICE_ERROR:
+               return EIO;
+       case EFI_INVALID_PARAMETER:
+               return EINVAL;
+       case EFI_NOT_FOUND:
+               return ENOENT;
+       case EFI_OUT_OF_RESOURCES:
+               return EAGAIN;
+       case EFI_SECURITY_VIOLATION:
+               return EPERM;
+       case EFI_UNSUPPORTED:
+               return ENOSYS;
+       case EFI_WRITE_PROTECTED:
+               return EROFS;
+       default:
+               return EIO;
+       }
+}
index 85a4f23..b7856ba 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: efi.h,v 1.3 2022/10/18 10:17:56 kettenis Exp $ */
+/* $OpenBSD: efi.h,v 1.4 2023/01/14 12:11:11 kettenis Exp $ */
 
 /* Public Domain */
 
 #define EFIAPI
 #endif
 
+#ifdef __LP64__
+#define EFIERR(x)      (0x8000000000000000 | (x))
+#else
+#define EFIERR(x)      (0x80000000 | (x))
+#endif
+
 typedef uint8_t                UINT8;
 typedef int16_t                INT16;
 typedef uint16_t       UINT16;
@@ -47,6 +53,10 @@ typedef struct {
   { 0xf2fd1544, 0x9794, 0x4a2c, \
     { 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 } }
 
+#define EFI_SYSTEM_RESOURCE_TABLE_GUID \
+  { 0xb122a263, 0x3661, 0x4f68, \
+    { 0x99, 0x29, 0x78, 0xf8, 0xb0, 0xd6, 0x21, 0x80 } }
+
 #define EFI_GLOBAL_VARIABLE \
   { 0x8be4df61, 0x93ca, 0x11d2, \
     { 0xaa,0x0d,0x00,0xe0,0x98,0x03,0x2b,0x8c } }
@@ -175,8 +185,34 @@ typedef struct {
        EFI_CONFIGURATION_TABLE         *ConfigurationTable;
 } EFI_SYSTEM_TABLE;
 
+typedef struct {
+       EFI_GUID                        FwClass;
+       UINT32                          FwType;
+       UINT32                          FwVersion;
+       UINT32                          LowestSupportedFwVersion;
+       UINT32                          CapsuleFlags;
+       UINT32                          LastAttemptVersion;
+       UINT32                          LastAttemptStatus;
+} EFI_SYSTEM_RESOURCE_ENTRY;
+
+typedef struct {
+       UINT32                          FwResourceCount;
+       UINT32                          FwResourceCountMax;
+       UINT64                          FwResourceVersion;
+       EFI_SYSTEM_RESOURCE_ENTRY       Entries[];
+} EFI_SYSTEM_RESOURCE_TABLE;
+
 #define EFI_SUCCESS    0
 
+#define EFI_INVALID_PARAMETER  EFIERR(2)
+#define EFI_UNSUPPORTED                EFIERR(3)
+#define EFI_BUFFER_TOO_SMALL   EFIERR(5)
+#define EFI_DEVICE_ERROR       EFIERR(7)
+#define EFI_WRITE_PROTECTED    EFIERR(8)
+#define EFI_OUT_OF_RESOURCES   EFIERR(9)
+#define EFI_NOT_FOUND          EFIERR(14)
+#define EFI_SECURITY_VIOLATION EFIERR(26)
+
 #define        efi_guidcmp(_a, _b)     memcmp((_a), (_b), sizeof(EFI_GUID))
 
 #endif /* _DEV_ACPI_EFI_H_ */
diff --git a/sys/dev/efi/efiio.h b/sys/dev/efi/efiio.h
new file mode 100644 (file)
index 0000000..7929b2e
--- /dev/null
@@ -0,0 +1,82 @@
+/*     $OpenBSD: efiio.h,v 1.1 2023/01/14 12:11:11 kettenis Exp $      */
+/*-
+ * Copyright (c) 2016 Netflix, Inc.
+ * Copyright (c) 2022 3mdeb <contact@3mdeb.com>
+ *
+ * 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.
+ */
+
+#ifndef _DEV_EFI_EFIIO_H_
+#define _DEV_EFI_EFIIO_H_
+
+#include <sys/types.h>
+#include <sys/ioccom.h>
+#include <sys/uuid.h>
+
+typedef uint16_t efi_char;
+
+#define EFI_TABLE_ESRT                                 \
+       {0xb122a263,0x3661,0x4f68,0x99,0x29,{0x78,0xf8,0xb0,0xd6,0x21,0x80}}
+
+struct efi_esrt_table {
+       uint32_t        fw_resource_count;
+       uint32_t        fw_resource_count_max;
+       uint64_t        fw_resource_version;
+#define ESRT_FIRMWARE_RESOURCE_VERSION 1
+       uint8_t         entries[];
+};
+
+struct efi_esrt_entry_v1 {
+       struct uuid     fw_class;
+       uint32_t        fw_type;
+       uint32_t        fw_version;
+       uint32_t        lowest_supported_fw_version;
+       uint32_t        capsule_flags;
+       uint32_t        last_attempt_version;
+       uint32_t        last_attempt_status;
+};
+
+struct efi_get_table_ioc
+{
+       void *buf;              /* Pointer to userspace buffer */
+       struct uuid uuid;       /* UUID to look up */
+       size_t table_len;       /* Table size */
+       size_t buf_len;         /* Size of the buffer */
+};
+
+struct efi_var_ioc
+{
+       uint16_t *name;         /* User pointer to name, in UCS2 chars */
+       size_t namesize;        /* Number of *bytes* in the name including
+                                  terminator */
+       struct uuid vendor;     /* Vendor's UUID for variable */
+       uint32_t attrib;        /* Attributes */
+       void *data;             /* User pointer to value */
+       size_t datasize;        /* Number of *bytes* in the value */
+};
+
+#define EFIIOC_GET_TABLE       _IOWR('E',  1, struct efi_get_table_ioc)
+#define EFIIOC_VAR_GET         _IOWR('E',  2, struct efi_var_ioc)
+#define EFIIOC_VAR_NEXT                _IOWR('E',  3, struct efi_var_ioc)
+#define EFIIOC_VAR_SET         _IOWR('E',  4, struct efi_var_ioc)
+
+#endif /* _DEV_EFI_EFIIO_H_ */
diff --git a/sys/dev/efi/files.efi b/sys/dev/efi/files.efi
new file mode 100644 (file)
index 0000000..4f6b14a
--- /dev/null
@@ -0,0 +1,7 @@
+#      $OpenBSD: files.efi,v 1.1 2023/01/14 12:11:11 kettenis Exp $
+#
+# Config file and device description for machine-independent ACPI code.
+# Included by ports that need it.
+
+device efi {}
+file   dev/efi/efi.c           efi needs-flag
index e651732..798ded6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.h,v 1.160 2022/11/06 13:03:52 dlg Exp $  */
+/*     $OpenBSD: conf.h,v 1.161 2023/01/14 12:11:11 kettenis Exp $     */
 /*     $NetBSD: conf.h,v 1.33 1996/05/03 20:03:32 christos Exp $       */
 
 /*-
@@ -481,6 +481,13 @@ extern struct cdevsw cdevsw[];
        (dev_type_stop((*))) enodev, 0, (dev_type_mmap((*))) enodev, \
        0, 0, seltrue_kqfilter }
 
+/* open, close, ioctl */
+#define cdev_efi_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+       (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+       (dev_type_stop((*))) enodev, 0, \
+       (dev_type_mmap((*))) enodev }
+
 /* open, close, ioctl, mmap */
 #define cdev_kcov_init(c,n) { \
        dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
@@ -632,6 +639,7 @@ cdev_decl(amdmsr);
 cdev_decl(fuse);
 cdev_decl(pvbus);
 cdev_decl(ipmi);
+cdev_decl(efi);
 cdev_decl(kcov);
 
 #endif