Implement support for calling EFI runtime services and use it to implement
authorkettenis <kettenis@openbsd.org>
Thu, 4 Jan 2018 14:30:08 +0000 (14:30 +0000)
committerkettenis <kettenis@openbsd.org>
Thu, 4 Jan 2018 14:30:08 +0000 (14:30 +0000)
a time-of-day clock device based on the GetTime() and SetTime() services.
The virtual memory mappings for the runtime services calls are implemented
through a separate pmap that is only activated when we make a runtime services
call.

ok tom@, visa@
tested by naddy@

sys/arch/arm64/arm64/machdep.c
sys/arch/arm64/arm64/pmap.c
sys/arch/arm64/conf/GENERIC
sys/arch/arm64/conf/RAMDISK
sys/arch/arm64/conf/files.arm64
sys/arch/arm64/dev/efi.c [new file with mode: 0644]
sys/arch/arm64/dev/mainbus.c
sys/arch/arm64/include/pmap.h
sys/dev/acpi/efi.h

index d1d5a67..112e348 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: machdep.c,v 1.23 2017/12/11 05:27:40 deraadt Exp $ */
+/* $OpenBSD: machdep.c,v 1.24 2018/01/04 14:30:08 kettenis Exp $ */
 /*
  * Copyright (c) 2014 Patrick Wildt <patrick@blueri.se>
  *
@@ -755,6 +755,7 @@ initarm(struct arm64_bootparams *abp)
        paddr_t memstart, memend;
        void *config = abp->arg2;
        void *fdt = NULL;
+       EFI_PHYSICAL_ADDRESS system_table = 0;
        int (*map_func_save)(bus_space_tag_t, bus_addr_t, bus_size_t, int,
            bus_space_handle_t *);
        int (*map_a4x_func_save)(bus_space_tag_t, bus_addr_t, bus_size_t, int,
@@ -794,6 +795,10 @@ initarm(struct arm64_bootparams *abp)
                len = fdt_node_property(node, "openbsd,uefi-mmap-desc-ver", &prop);
                if (len == sizeof(mmap_desc_ver))
                        mmap_desc_ver = bemtoh32((uint32_t *)prop);
+
+               len = fdt_node_property(node, "openbsd,uefi-system-table", &prop);
+               if (len == sizeof(system_table))
+                       system_table = bemtoh64((uint64_t *)prop);
        }
 
        /* Set the pcpu data, this is needed by pmap_bootstrap */
@@ -874,7 +879,7 @@ initarm(struct arm64_bootparams *abp)
 
                for (va = vstart, csize = size; csize > 0;
                    csize -= PAGE_SIZE, va += PAGE_SIZE, pa += PAGE_SIZE)
-                       pmap_kenter_cache(va, pa, PROT_READ, PMAP_CACHE_WB);
+                       pmap_kenter_cache(va, pa, PROT_READ | PROT_WRITE, PMAP_CACHE_WB);
 
                mmap = (void *)vstart;
                vstart += size;
@@ -912,6 +917,69 @@ initarm(struct arm64_bootparams *abp)
        arm64_bs_tag._space_map = map_func_save;
        arm64_a4x_bs_tag._space_map = map_a4x_func_save;
 
+       /* Remap EFI runtime. */
+       if (mmap_start != 0 && system_table != 0) {
+               EFI_SYSTEM_TABLE *st = (EFI_SYSTEM_TABLE *)system_table;
+               EFI_RUNTIME_SERVICES *rs;
+               EFI_STATUS status;
+               EFI_MEMORY_DESCRIPTOR *src;
+               EFI_MEMORY_DESCRIPTOR *dst;
+               EFI_PHYSICAL_ADDRESS phys_start = ~0ULL;
+               EFI_VIRTUAL_ADDRESS virt_start;
+               vsize_t space;
+               int i, count = 0;
+               paddr_t pa;
+
+               /*
+                * Pick a random address somewhere in the lower half
+                * of the usable virtual address space.
+                */
+               space = 3 * (VM_MAX_ADDRESS - VM_MIN_ADDRESS) / 4;
+               virt_start = VM_MIN_ADDRESS +
+                   ((vsize_t)arc4random_uniform(space >> PAGE_SHIFT) << PAGE_SHIFT);
+
+               /* Make sure the EFI system table is mapped. */
+               pmap_map_early(system_table, sizeof(EFI_SYSTEM_TABLE));
+               rs = st->RuntimeServices;
+
+               /* Make sure memory for EFI runtime services is mapped. */
+               src = mmap;
+               for (i = 0; i < mmap_size / mmap_desc_size; i++) {
+                       if (src->Attribute & EFI_MEMORY_RUNTIME) {
+                               pmap_map_early(src->PhysicalStart,
+                                   src->NumberOfPages * PAGE_SIZE);
+                               if (phys_start > src->PhysicalStart)
+                                       phys_start = src->PhysicalStart;
+                               count++;
+                       }
+                       src = NextMemoryDescriptor(src, mmap_desc_size);
+               }
+
+               /* Allocate memory descriptors for new mappings. */
+               pa = pmap_steal_avail(count * mmap_desc_size,
+                   mmap_desc_size, NULL);
+               memset((void *)pa, 0, count * mmap_desc_size);
+
+               src = mmap;
+               dst = (EFI_MEMORY_DESCRIPTOR *)pa;
+               for (i = 0; i < mmap_size / mmap_desc_size; i++) {
+                       if (src->Attribute & EFI_MEMORY_RUNTIME) {
+                               src->VirtualStart = virt_start +
+                                   (src->PhysicalStart - phys_start);
+                               memcpy(dst, src, mmap_desc_size);
+                               dst = NextMemoryDescriptor(dst, mmap_desc_size);
+                       }
+                       src = NextMemoryDescriptor(src, mmap_desc_size);
+               }
+
+               /* Install new mappings. */
+               dst = (EFI_MEMORY_DESCRIPTOR *)pa;
+               status = rs->SetVirtualAddressMap(count * mmap_desc_size,
+                   mmap_desc_size, mmap_desc_ver, dst);
+               if (status != EFI_SUCCESS)
+                       printf("SetVirtualAddressMap failed: %lu\n", status);
+       }
+
        /* XXX */
        pmap_avail_fixup();
 
@@ -923,6 +991,7 @@ initarm(struct arm64_bootparams *abp)
 
        /* Make all other physical memory available to UVM. */
        if (mmap && mmap_desc_ver == EFI_MEMORY_DESCRIPTOR_VERSION) {
+               EFI_MEMORY_DESCRIPTOR *desc = mmap;
                int i;
 
                /*
@@ -933,20 +1002,20 @@ initarm(struct arm64_bootparams *abp)
                 */
                for (i = 0; i < mmap_size / mmap_desc_size; i++) {
                        printf("type 0x%x pa 0x%llx va 0x%llx pages 0x%llx attr 0x%llx\n",
-                           mmap->Type, mmap->PhysicalStart,
-                           mmap->VirtualStart, mmap->NumberOfPages,
-                           mmap->Attribute);
-                       if (mmap->Type == EfiConventionalMemory &&
-                           mmap->NumberOfPages >= 16) {
-                               uvm_page_physload(atop(mmap->PhysicalStart),
-                                   atop(mmap->PhysicalStart) +
-                                   mmap->NumberOfPages,
-                                   atop(mmap->PhysicalStart),
-                                   atop(mmap->PhysicalStart) +
-                                   mmap->NumberOfPages, 0);
-                               physmem += mmap->NumberOfPages;
+                           desc->Type, desc->PhysicalStart,
+                           desc->VirtualStart, desc->NumberOfPages,
+                           desc->Attribute);
+                       if (desc->Type == EfiConventionalMemory &&
+                           desc->NumberOfPages >= 16) {
+                               uvm_page_physload(atop(desc->PhysicalStart),
+                                   atop(desc->PhysicalStart) +
+                                   desc->NumberOfPages,
+                                   atop(desc->PhysicalStart),
+                                   atop(desc->PhysicalStart) +
+                                   desc->NumberOfPages, 0);
+                               physmem += desc->NumberOfPages;
                        }
-                       mmap = NextMemoryDescriptor(mmap, mmap_desc_size);
+                       desc = NextMemoryDescriptor(desc, mmap_desc_size);
                }
        } else {
                paddr_t start, end;
index f68d2d2..c147b00 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.41 2017/12/31 08:42:04 kettenis Exp $ */
+/* $OpenBSD: pmap.c,v 1.42 2018/01/04 14:30:08 kettenis Exp $ */
 /*
  * Copyright (c) 2008-2009,2014-2016 Dale Rahn <drahn@dalerahn.com>
  *
@@ -186,14 +186,14 @@ VP_IDX3(vaddr_t va)
 }
 
 const uint64_t ap_bits_user[8] = {
-       [PROT_NONE]                     = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AP(2),
-       [PROT_READ]                     = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(3),
-       [PROT_WRITE]                    = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(1),
-       [PROT_WRITE|PROT_READ]          = ATTR_nG|ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(1),
-       [PROT_EXEC]                     = ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(2),
-       [PROT_EXEC|PROT_READ]           = ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(3),
-       [PROT_EXEC|PROT_WRITE]          = ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(1),
-       [PROT_EXEC|PROT_WRITE|PROT_READ]= ATTR_nG|ATTR_PXN|ATTR_AF|ATTR_AP(1),
+       [PROT_NONE]                             = ATTR_PXN|ATTR_UXN|ATTR_AP(2),
+       [PROT_READ]                             = ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(3),
+       [PROT_WRITE]                            = ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(1),
+       [PROT_WRITE|PROT_READ]                  = ATTR_PXN|ATTR_UXN|ATTR_AF|ATTR_AP(1),
+       [PROT_EXEC]                             = ATTR_PXN|ATTR_AF|ATTR_AP(2),
+       [PROT_EXEC|PROT_READ]                   = ATTR_PXN|ATTR_AF|ATTR_AP(3),
+       [PROT_EXEC|PROT_WRITE]                  = ATTR_PXN|ATTR_AF|ATTR_AP(1),
+       [PROT_EXEC|PROT_WRITE|PROT_READ]        = ATTR_PXN|ATTR_AF|ATTR_AP(1),
 };
 
 const uint64_t ap_bits_kern[8] = {
@@ -1081,6 +1081,7 @@ pmap_bootstrap(long kvo, paddr_t lpt1, long kernelstart, long kernelend,
        pt1pa = pmap_steal_avail(sizeof(struct pmapvp1), Lx_TABLE_ALIGN, &va);
        vp1 = (struct pmapvp1 *)pt1pa;
        pmap_kernel()->pm_vp.l1 = (struct pmapvp1 *)va;
+       pmap_kernel()->pm_privileged = 1;
        pmap_kernel()->pm_asid = 0;
 
        /* allocate Lx entries */
@@ -1205,6 +1206,8 @@ pmap_bootstrap(long kvo, paddr_t lpt1, long kernelstart, long kernelend,
 
        printf("all mapped\n");
 
+       curcpu()->ci_curpm = pmap_kernel();
+
        memhook = (char *)vstart;
        vstart += PAGE_SIZE;
 
@@ -1496,12 +1499,14 @@ pmap_pte_update(struct pte_desc *pted, uint64_t *pl3)
                panic("pmap_pte_insert: invalid cache mode");
        }
 
-       /* kernel mappings are global, so nG should not be set */
-       if (pm == pmap_kernel())
+       if (pm->pm_privileged)
                access_bits = ap_bits_kern[pted->pted_pte & PROT_MASK];
        else
                access_bits = ap_bits_user[pted->pted_pte & PROT_MASK];
 
+       if (pted->pted_va < VM_MIN_KERNEL_ADDRESS)
+               access_bits |= ATTR_nG;
+
        pte = (pted->pted_pte & PTE_RPGN) | attr | access_bits | L3_P;
        *pl3 = pte;
 }
index 7a22c87..2e6f23b 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: GENERIC,v 1.47 2018/01/02 22:47:45 kettenis Exp $
+# $OpenBSD: GENERIC,v 1.48 2018/01/04 14:30:08 kettenis Exp $
 #
 # GENERIC machine description file
 #
@@ -36,6 +36,7 @@ config                bsd     swap generic
 # The main bus device
 mainbus0       at root
 cpu0           at mainbus?
+efi0           at mainbus?
 simplebus*     at fdt?
 
 scsibus*       at scsi?
index 0a2a8ce..72b9680 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: RAMDISK,v 1.41 2018/01/02 22:47:45 kettenis Exp $
+# $OpenBSD: RAMDISK,v 1.42 2018/01/04 14:30:08 kettenis Exp $
 #
 # GENERIC machine description file
 #
@@ -47,6 +47,7 @@ config                bsd     root on rd0a swap on rd0b
 # The main bus device
 mainbus0       at root
 cpu0           at mainbus?
+efi0           at mainbus?
 simplebus*     at fdt?
 
 scsibus*       at scsi?
index 00a6bac..a4eee2b 100644 (file)
@@ -1,4 +1,4 @@
-# $OpenBSD: files.arm64,v 1.15 2017/06/04 14:10:42 patrick Exp $
+# $OpenBSD: files.arm64,v 1.16 2018/01/04 14:30:08 kettenis Exp $
 
 maxpartitions  16
 maxusers       2 8 64
@@ -58,6 +58,10 @@ device       simplebus: fdt
 attach simplebus at fdt
 file   arch/arm64/dev/simplebus.c              simplebus
 
+device efi
+attach efi at fdt
+file   arch/arm64/dev/efi.c                    efi
+
 # FDT support
 file   dev/ofw/fdt.c
 file   dev/ofw/ofw_clock.c
diff --git a/sys/arch/arm64/dev/efi.c b/sys/arch/arm64/dev/efi.c
new file mode 100644 (file)
index 0000000..976e4c0
--- /dev/null
@@ -0,0 +1,258 @@
+/*     $OpenBSD: efi.c,v 1.1 2018/01/04 14:30:08 kettenis Exp $        */
+
+/*
+ * Copyright (c) 2017 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.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/cpufunc.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+#include <dev/acpi/efi.h>
+
+#include <dev/clock_subr.h>
+
+extern todr_chip_handle_t todr_handle;
+
+extern uint32_t mmap_size;
+extern uint32_t mmap_desc_size;
+extern uint32_t mmap_desc_ver;
+
+extern EFI_MEMORY_DESCRIPTOR *mmap;
+
+struct efi_softc {
+       struct device   sc_dev;
+       struct pmap     *sc_pm;
+       EFI_RUNTIME_SERVICES *sc_rs;
+       int             sc_psw;
+
+       struct todr_chip_handle sc_todr;
+};
+
+int    efi_match(struct device *, void *, void *);
+void   efi_attach(struct device *, struct device *, void *);
+
+struct cfattach efi_ca = {
+       sizeof(struct efi_softc), efi_match, efi_attach
+};
+
+struct cfdriver efi_cd = {
+       NULL, "efi", DV_DULL
+};
+
+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 *);
+
+int
+efi_match(struct device *parent, void *match, void *aux)
+{
+       struct fdt_attach_args *faa = aux;
+
+       return (strcmp(faa->fa_name, "efi") == 0);
+}
+
+void
+efi_attach(struct device *parent, struct device *self, void *aux)
+{
+       struct efi_softc *sc = (struct efi_softc *)self;
+       struct fdt_attach_args *faa = aux;
+       uint64_t system_table;
+       bus_space_handle_t ioh;
+       EFI_SYSTEM_TABLE *st;
+       EFI_RUNTIME_SERVICES *rs;
+       EFI_MEMORY_DESCRIPTOR *desc;
+       EFI_TIME time;
+       EFI_STATUS status;
+       uint16_t major, minor;
+       int node, i;
+
+       node = OF_finddevice("/chosen");
+       KASSERT(node);
+
+       system_table = OF_getpropint64(node, "openbsd,uefi-system-table", 0);
+       KASSERT(system_table);
+
+       if (bus_space_map(faa->fa_iot, system_table, sizeof(EFI_SYSTEM_TABLE),
+           BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE, &ioh)) {
+               printf(": can't map system table\n");
+               return;
+       }
+
+       st = bus_space_vaddr(faa->fa_iot, ioh);
+       rs = st->RuntimeServices;
+
+       major = st->Hdr.Revision >> 16;
+       minor = st->Hdr.Revision & 0xffff;
+       printf(": UEFI %d.%d", major, minor / 10);
+       if (minor % 10)
+               printf(".%d", minor % 10);
+       printf("\n");
+
+       /*
+        * We don't really want some random executable non-OpenBSD
+        * code lying around in kernel space.  So create a separate
+        * pmap and only activate it when we call runtime services.
+        */
+       sc->sc_pm = pmap_create();
+       sc->sc_pm->pm_privileged = 1;
+
+       desc = mmap;
+       for (i = 0; i < mmap_size / mmap_desc_size; i++) {
+               if (desc->Attribute & EFI_MEMORY_RUNTIME) {
+                       vaddr_t va = desc->VirtualStart;
+                       paddr_t pa = desc->PhysicalStart;
+                       int npages = desc->NumberOfPages;
+                       vm_prot_t prot = PROT_READ;
+
+#ifdef EFI_DEBUG
+                       printf("type 0x%x pa 0x%llx va 0x%llx pages 0x%llx attr 0x%llx\n",
+                           desc->Type, desc->PhysicalStart,
+                           desc->VirtualStart, desc->NumberOfPages,
+                           desc->Attribute);
+#endif
+
+                       if (desc->Type == EfiRuntimeServicesCode)
+                               prot |= PROT_EXEC;
+                       else
+                               prot |= PROT_WRITE;
+                       while (npages--) {
+                               pmap_enter(sc->sc_pm, va, pa, prot,
+                                  prot | PMAP_WIRED);
+                               va += PAGE_SIZE;
+                               pa += PAGE_SIZE;
+                       }
+               }
+               desc = NextMemoryDescriptor(desc, mmap_desc_size);
+       }
+
+       /*
+        * The FirmwareVendor field has been converted from a physical
+        * pointer to a virtual pointer, so we have to activate our
+        * pmap to access it.
+        */
+       if (st->FirmwareVendor) {
+               printf("%s: ", sc->sc_dev.dv_xname);
+               efi_enter(sc);
+               for (i = 0; st->FirmwareVendor[i]; i++)
+                       printf("%c", st->FirmwareVendor[i]);
+               efi_leave(sc);
+               printf(" rev 0x%x\n", st->FirmwareRevision);
+       }
+
+       if (rs == NULL)
+               return;
+
+       efi_enter(sc);
+       status = rs->GetTime(&time, NULL);
+       efi_leave(sc);
+       if (status != EFI_SUCCESS)
+               return;
+
+       sc->sc_rs = rs;
+       sc->sc_todr.cookie = sc;
+       sc->sc_todr.todr_gettime = efi_gettime;
+       sc->sc_todr.todr_settime = efi_settime;
+       todr_handle = &sc->sc_todr;
+}
+
+void
+efi_enter(struct efi_softc *sc)
+{
+       struct pmap *pm = sc->sc_pm;
+
+       sc->sc_psw = disable_interrupts();
+       cpu_setttb(((uint64_t)pm->pm_asid << 48) | pm->pm_pt0pa);
+}
+
+void
+efi_leave(struct efi_softc *sc)
+{
+       struct pmap *pm = curcpu()->ci_curpm;
+
+       cpu_setttb(((uint64_t)pm->pm_asid << 48) | pm->pm_pt0pa);
+       restore_interrupts(sc->sc_psw);
+}
+
+int
+efi_gettime(struct todr_chip_handle *handle, struct timeval *tv)
+{
+       struct efi_softc *sc = handle->cookie;
+       struct clock_ymdhms dt;
+       EFI_TIME time;
+       EFI_STATUS status;
+
+       efi_enter(sc);
+       status = sc->sc_rs->GetTime(&time, NULL);
+       efi_leave(sc);
+       if (status != EFI_SUCCESS)
+               return EIO;
+
+       dt.dt_year = time.Year;
+       dt.dt_mon = time.Month;
+       dt.dt_day = time.Day;
+       dt.dt_hour = time.Hour;
+       dt.dt_min = time.Minute;
+       dt.dt_sec = time.Second;
+
+       if (dt.dt_sec > 59 || dt.dt_min > 59 || dt.dt_hour > 23 ||
+           dt.dt_day > 31 || dt.dt_day == 0 ||
+           dt.dt_mon > 12 || dt.dt_mon == 0 ||
+           dt.dt_year < POSIX_BASE_YEAR)
+               return EINVAL;
+
+       tv->tv_sec = clock_ymdhms_to_secs(&dt);
+       tv->tv_usec = 0;
+       return 0;
+}
+
+int
+efi_settime(struct todr_chip_handle *handle, struct timeval *tv)
+{
+       struct efi_softc *sc = handle->cookie;
+       struct clock_ymdhms dt;
+       EFI_TIME time;
+       EFI_STATUS status;
+
+       clock_secs_to_ymdhms(tv->tv_sec, &dt);
+
+       time.Year = dt.dt_year;
+       time.Month = dt.dt_mon;
+       time.Day = dt.dt_day;
+       time.Hour = dt.dt_hour;
+       time.Minute = dt.dt_min;
+       time.Second = dt.dt_sec;
+       time.Nanosecond = 0;
+       time.TimeZone = 0;
+       time.Daylight = 0;
+
+       efi_enter(sc);
+       status = sc->sc_rs->SetTime(&time);
+       efi_leave(sc);
+       if (status != EFI_SUCCESS)
+               return EIO;
+       return 0;
+}
+
index 780c7ed..474e239 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mainbus.c,v 1.7 2017/08/23 12:58:00 kettenis Exp $ */
+/* $OpenBSD: mainbus.c,v 1.8 2018/01/04 14:30:08 kettenis Exp $ */
 /*
  * Copyright (c) 2016 Patrick Wildt <patrick@blueri.se>
  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
@@ -37,6 +37,7 @@ int mainbus_match_status(struct device *, void *, void *);
 void mainbus_attach_cpus(struct device *, cfmatch_t);
 int mainbus_match_primary(struct device *, void *, void *);
 int mainbus_match_secondary(struct device *, void *, void *);
+void mainbus_attach_efi(struct device *);
 void mainbus_attach_framebuffer(struct device *);
 
 struct mainbus_softc {
@@ -120,6 +121,8 @@ mainbus_attach(struct device *parent, struct device *self, void *aux)
        /* Attach primary CPU first. */
        mainbus_attach_cpus(self, mainbus_match_primary);
 
+       mainbus_attach_efi(self);
+
        sc->sc_rangeslen = OF_getproplen(OF_peer(0), "ranges");
        if (sc->sc_rangeslen > 0 && !(sc->sc_rangeslen % sizeof(uint32_t))) {
                sc->sc_ranges = malloc(sc->sc_rangeslen, M_TEMP, M_WAITOK);
@@ -215,6 +218,9 @@ mainbus_match_status(struct device *parent, void *match, void *aux)
        struct cfdata *cf = match;
        char buf[32];
 
+       if (fa->fa_node == 0)
+               return 0;
+
        if (OF_getprop(fa->fa_node, "status", buf, sizeof(buf)) > 0 &&
            strcmp(buf, "disabled") == 0)
                return 0;
@@ -272,6 +278,23 @@ mainbus_match_secondary(struct device *parent, void *match, void *aux)
        return (*cf->cf_attach->ca_match)(parent, match, aux);
 }
 
+void
+mainbus_attach_efi(struct device *self)
+{
+       struct mainbus_softc *sc = (struct mainbus_softc *)self;
+       struct fdt_attach_args fa;
+       int node = OF_finddevice("/chosen");
+
+       if (node == 0 || OF_getproplen(node, "openbsd,uefi-system-table") <= 0)
+               return;
+
+       memset(&fa, 0, sizeof(fa));
+       fa.fa_name = "efi";
+       fa.fa_iot = sc->sc_iot;
+       fa.fa_dmat = sc->sc_dmat;
+       config_found(self, &fa, NULL);
+}
+
 void
 mainbus_attach_framebuffer(struct device *self)
 {
index e4024d2..0c16ae9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.h,v 1.7 2017/12/31 08:42:04 kettenis Exp $ */
+/* $OpenBSD: pmap.h,v 1.8 2018/01/04 14:30:08 kettenis Exp $ */
 /*
  * Copyright (c) 2008,2009,2014 Dale Rahn <drahn@dalerahn.com>
  *
@@ -71,6 +71,7 @@ struct pmap {
        } pm_vp;
        uint64_t pm_pt0pa;
        int have_4_level_pt;
+       int pm_privileged;
        int pm_asid;
        int pm_refs;                            /* ref count */
        struct pmap_statistics  pm_stats;       /* pmap statistics */
index 91f8ade..a350078 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: efi.h,v 1.1 2017/05/25 21:21:18 kettenis Exp $ */
+/* $OpenBSD: efi.h,v 1.2 2018/01/04 14:30:08 kettenis Exp $ */
 
 /* Public Domain */
 
@@ -6,10 +6,22 @@
 #define _MACHINE_EFI_H_
 
 typedef uint8_t                UINT8;
+typedef int16_t                INT16;
+typedef uint16_t       UINT16;
 typedef uint32_t       UINT32;
 typedef uint64_t       UINT64;
+typedef u_long         UINTN;
+typedef uint16_t       CHAR16;
+typedef void           VOID;
+typedef uint32_t       EFI_GUID[4];
 typedef uint64_t       EFI_PHYSICAL_ADDRESS;
 typedef uint64_t       EFI_VIRTUAL_ADDRESS;
+typedef UINTN          EFI_STATUS;
+typedef VOID           *EFI_HANDLE;
+
+typedef VOID           *EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
+typedef VOID           *EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
+typedef VOID           *EFI_BOOT_SERVICES;
 
 typedef enum {
        EfiReservedMemoryType,
@@ -57,4 +69,65 @@ typedef struct {
 #define NextMemoryDescriptor(Ptr, Size) \
        ((EFI_MEMORY_DESCRIPTOR *)(((UINT8 *)Ptr) + Size))
 
+typedef struct {
+       UINT64                          Signature;
+       UINT32                          Revision;
+       UINT32                          HeaderSize;
+       UINT32                          CRC32;
+       UINT32                          Reserved;
+} EFI_TABLE_HEADER;
+
+typedef struct {
+       UINT16                          Year;
+       UINT8                           Month;
+       UINT8                           Day;
+       UINT8                           Hour;
+       UINT8                           Minute;
+       UINT8                           Second;
+       UINT8                           Pad1;
+       UINT32                          Nanosecond;
+       INT16                           TimeZone;
+       UINT8                           Daylight;
+       UINT8                           Pad2;
+} EFI_TIME;
+
+typedef VOID           *EFI_TIME_CAPABILITIES;
+
+typedef EFI_STATUS (*EFI_GET_TIME)(EFI_TIME *, EFI_TIME_CAPABILITIES *);
+typedef EFI_STATUS (*EFI_SET_TIME)(EFI_TIME *);
+typedef EFI_STATUS (*EFI_SET_VIRTUAL_ADDRESS_MAP)(UINTN, UINTN, UINT32, EFI_MEMORY_DESCRIPTOR *);
+
+typedef struct {
+       EFI_TABLE_HEADER                Hdr;
+       EFI_GET_TIME                    GetTime;
+       EFI_SET_TIME                    SetTime;
+       VOID                            *GetWakeupTime;
+       VOID                            *SetWakeupTime;
+
+       EFI_SET_VIRTUAL_ADDRESS_MAP     SetVirtualAddressMap;
+} EFI_RUNTIME_SERVICES;
+
+typedef struct {
+       EFI_GUID                        VendorGuid;
+       VOID                            *VendorTable;
+} EFI_CONFIGURATION_TABLE;
+
+typedef struct {
+       EFI_TABLE_HEADER                Hdr;
+       CHAR16                          *FirmwareVendor;
+       UINT32                          FirmwareRevision;
+       EFI_HANDLE                      ConsoleInHandle;
+       EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *ConIn;
+       EFI_HANDLE                      ConsoleOutHandle;
+       EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
+       EFI_HANDLE                      StandardErrorHandle;
+       EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr;
+       EFI_RUNTIME_SERVICES            *RuntimeServices;
+       EFI_BOOT_SERVICES               *BootServices;
+       UINTN                           NumberOfTableEntries;
+       EFI_CONFIGURATION_TABLE         *ConfigurationTable;
+} EFI_SYSTEM_TABLE;
+
+#define EFI_SUCCESS    0
+
 #endif /* _MACHINE_EFI_H_ */