From f2f886813ecce43460715d9633751066dbbedd5c Mon Sep 17 00:00:00 2001 From: kettenis Date: Sat, 14 Jan 2023 12:11:10 +0000 Subject: [PATCH] Implement access to EFI variables and ESRT through an ioctl(2) interface 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@ --- sys/arch/amd64/amd64/conf.c | 5 +- sys/arch/amd64/amd64/efi_machdep.c | 27 +-- sys/arch/amd64/conf/files.amd64 | 6 +- sys/arch/amd64/include/efivar.h | 42 +++++ sys/arch/arm64/arm64/conf.c | 5 +- sys/arch/arm64/conf/files.arm64 | 7 +- sys/arch/arm64/dev/efi_machdep.c | 23 +-- sys/arch/arm64/include/efivar.h | 41 +++++ sys/dev/efi/efi.c | 284 +++++++++++++++++++++++++++++ sys/dev/efi/efi.h | 38 +++- sys/dev/efi/efiio.h | 82 +++++++++ sys/dev/efi/files.efi | 7 + sys/sys/conf.h | 10 +- 13 files changed, 522 insertions(+), 55 deletions(-) create mode 100644 sys/arch/amd64/include/efivar.h create mode 100644 sys/arch/arm64/include/efivar.h create mode 100644 sys/dev/efi/efi.c create mode 100644 sys/dev/efi/efiio.h create mode 100644 sys/dev/efi/files.efi diff --git a/sys/arch/amd64/amd64/conf.c b/sys/arch/amd64/amd64/conf.c index eb217a5c5ac..83f0089061d 100644 --- a/sys/arch/amd64/amd64/conf.c +++ b/sys/arch/amd64/amd64/conf.c @@ -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 */ diff --git a/sys/arch/amd64/amd64/efi_machdep.c b/sys/arch/amd64/amd64/efi_machdep.c index 40ed5004b6c..a5f4563ce7d 100644 --- a/sys/arch/amd64/amd64/efi_machdep.c +++ b/sys/arch/amd64/amd64/efi_machdep.c @@ -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 @@ -28,21 +28,10 @@ extern paddr_t cr3_reuse_pcid; #include - -#include +#include 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); /* diff --git a/sys/arch/amd64/conf/files.amd64 b/sys/arch/amd64/conf/files.amd64 index 91c5592e340..cb136df52dc 100644 --- a/sys/arch/amd64/conf/files.amd64 +++ b/sys/arch/amd64/conf/files.amd64 @@ -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 index 00000000000..5db2b55f1e5 --- /dev/null +++ b/sys/arch/amd64/include/efivar.h @@ -0,0 +1,42 @@ +/* $OpenBSD: efivar.h,v 1.1 2023/01/14 12:11:10 kettenis Exp $ */ +/* + * Copyright (c) 2022 Mark Kettenis + * + * 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 + +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_ */ diff --git a/sys/arch/arm64/arm64/conf.c b/sys/arch/arm64/arm64/conf.c index b2713bc2577..4e47542efca 100644 --- a/sys/arch/arm64/arm64/conf.c +++ b/sys/arch/arm64/arm64/conf.c @@ -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 diff --git a/sys/arch/arm64/conf/files.arm64 b/sys/arch/arm64/conf/files.arm64 index b30947a9e61..9ec032f2445 100644 --- a/sys/arch/arm64/conf/files.arm64 +++ b/sys/arch/arm64/conf/files.arm64 @@ -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 diff --git a/sys/arch/arm64/dev/efi_machdep.c b/sys/arch/arm64/dev/efi_machdep.c index 3779f9feba1..a37b41ef5cf 100644 --- a/sys/arch/arm64/dev/efi_machdep.c +++ b/sys/arch/arm64/dev/efi_machdep.c @@ -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 @@ -32,8 +32,7 @@ #include #include - -#include +#include /* * 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 index 00000000000..190549a4a91 --- /dev/null +++ b/sys/arch/arm64/include/efivar.h @@ -0,0 +1,41 @@ +/* $OpenBSD: efivar.h,v 1.1 2023/01/14 12:11:11 kettenis Exp $ */ +/* + * Copyright (c) 2022 Mark Kettenis + * + * 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 + +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 index 00000000000..6f8b37bb017 --- /dev/null +++ b/sys/dev/efi/efi.c @@ -0,0 +1,284 @@ +/* $OpenBSD: efi.c,v 1.1 2023/01/14 12:11:11 kettenis Exp $ */ +/* + * Copyright (c) 2022 3mdeb + * + * 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 +#include +#include + +#include +#include +#include + +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; + } +} diff --git a/sys/dev/efi/efi.h b/sys/dev/efi/efi.h index 85a4f232a8d..b7856ba68e0 100644 --- a/sys/dev/efi/efi.h +++ b/sys/dev/efi/efi.h @@ -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 */ @@ -11,6 +11,12 @@ #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 index 00000000000..7929b2e82bd --- /dev/null +++ b/sys/dev/efi/efiio.h @@ -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 + * + * 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 +#include +#include + +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 index 00000000000..4f6b14ab892 --- /dev/null +++ b/sys/dev/efi/files.efi @@ -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 diff --git a/sys/sys/conf.h b/sys/sys/conf.h index e651732824c..798ded6ffe4 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -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 -- 2.20.1