tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

EFI and ACPI



Hi,

I'm running NetBSD/amd64 on a Lenovo Thinkpad X230i. This machine run
under an EFI. When the EFI is configured to work in legacy-only mode
(i.e., BIOS), NetBSD successfully locate the ACPI RSDT. This is not
the case when configured to work in EFI-only mode (with CSM disabled).

My understanding is that under EFI, locating the RSDT consist in
walking through the EFI System Table. The physical address of this
table being passed by the bootloader to NetBSD (I don't know of a way
to locate it without the help of the bootloader).

As this machine use GRUB as bootloader, I
experimented as follow:
- patched GRUB to pass the EFI System Table PA to NetBSD via the
  knetbsd command (grub-knetbsd-efi-systbl.patch);
- and made NetBSD use this information in acpi_md_OsGetRootPointer
  to attempt to locate the RSDT but falling back to the actual
  behaviour if missing/broken (efi.patch).

I attached the the patches and the dmesg.

To improve the GRUB part of the solution, I suppose I would need to
make NetBSD/amd64 comply to the multiboot specification. Isn't
NetBSD/i386 compliant?

To improve the NetBSd part of the solution I wonder if I shouldn't dig
into the CFATTACH and make it a pseudo-device like mainbus0 is.

Anyway all comments are welcome :)

Regards,
--
Sheda
diff -ur grub2-2.00/grub-core/commands/efi/lsefisystab.c 
patched-grub2-2.00/grub-core/commands/efi/lsefisystab.c
--- grub2-2.00/grub-core/commands/efi/lsefisystab.c     2011-04-11 
21:39:12.000000000 +0200
+++ patched-grub2-2.00/grub-core/commands/efi/lsefisystab.c     2014-05-14 
23:10:25.947655143 +0200
@@ -51,7 +51,10 @@
   const grub_efi_system_table_t *st = grub_efi_system_table;
   grub_efi_configuration_table_t *t;
   unsigned int i;
+  grub_uint64_t pa;
+  memcpy(&pa, &st, sizeof(pa));
 
+  grub_printf ("Address: %016" PRIxGRUB_UINT64_T "\n", pa);
   grub_printf ("Signature: %016" PRIxGRUB_UINT64_T " revision: %08x\n",
               st->hdr.signature, st->hdr.revision);
   {
diff -ur grub2-2.00/grub-core/loader/i386/bsd.c 
patched-grub2-2.00/grub-core/loader/i386/bsd.c
--- grub2-2.00/grub-core/loader/i386/bsd.c      2014-05-14 22:54:34.000000000 
+0200
+++ patched-grub2-2.00/grub-core/loader/i386/bsd.c      2014-04-20 
13:53:35.253846209 +0200
@@ -1129,6 +1129,16 @@
   if (err)
     return err;
 
+/* XXX */
+#ifdef GRUB_MACHINE_EFI
+{
+  err = grub_bsd_add_meta (NETBSD_BTINFO_EFI, 
+                           &grub_efi_system_table, sizeof(void *));
+  if (err)
+    return err;
+}
+#endif
+
   {
     struct bsd_tag *tag;
     tag_buf_len = 0;
diff -ur grub2-2.00/include/grub/i386/netbsd_bootinfo.h 
patched-grub2-2.00/include/grub/i386/netbsd_bootinfo.h
--- grub2-2.00/include/grub/i386/netbsd_bootinfo.h      2011-11-09 
15:05:40.000000000 +0100
+++ patched-grub2-2.00/include/grub/i386/netbsd_bootinfo.h      2014-04-20 
07:25:30.927413596 +0200
@@ -58,6 +58,8 @@
 #define NETBSD_BTINFO_BOOTWEDGE                10
 #define NETBSD_BTINFO_MODULES          11
 #define NETBSD_BTINFO_FRAMEBUF         12
+#define NETBSD_BTINFO_USERCONFCOMMANDS  13
+#define NETBSD_BTINFO_EFI              14
 
 struct grub_netbsd_bootinfo
 {
@@ -146,4 +148,9 @@
 
 #define GRUB_NETBSD_MAX_ROOTDEVICE_LEN 16
 
+struct grub_netbsd_btinfo_efi
+{
+  void *pa_systbl;  /* Physical address of the EFI System Table */
+};
+
 #endif
Index: arch/amd64/amd64/mainbus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/mainbus.c,v
retrieving revision 1.34
diff -u -r1.34 mainbus.c
--- arch/amd64/amd64/mainbus.c  31 Jul 2013 14:05:33 -0000      1.34
+++ arch/amd64/amd64/mainbus.c  21 May 2014 20:05:56 -0000
@@ -54,6 +54,7 @@
 #include "opt_mpbios.h"
 #include "opt_pcifixup.h"
 
+#include <machine/bootinfo.h>
 #include <machine/cpuvar.h>
 #include <machine/i82093var.h>
 #include <machine/mpbiosvar.h>
@@ -169,6 +170,7 @@
 
        aprint_naive("\n");
        aprint_normal("\n");
+       aprint_bootinfo();
 
 #ifdef MPBIOS
        mpbios_present = mpbios_probe(self);
Index: arch/amd64/conf/files.amd64
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/conf/files.amd64,v
retrieving revision 1.83
diff -u -r1.83 files.amd64
--- arch/amd64/conf/files.amd64 20 Feb 2014 03:48:06 -0000      1.83
+++ arch/amd64/conf/files.amd64 21 May 2014 20:05:56 -0000
@@ -47,6 +47,9 @@
 file   arch/amd64/amd64/lock_stubs.S
 file   dev/cons.c
 
+# EFI Support
+file   arch/x86/x86/efi.c
+
 file   arch/amd64/amd64/mptramp.S        multiprocessor
 
 #
Index: arch/amd64/include/efi.h
===================================================================
RCS file: arch/amd64/include/efi.h
diff -N arch/amd64/include/efi.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ arch/amd64/include/efi.h    21 May 2014 20:05:56 -0000
@@ -0,0 +1 @@
+#include <x86/efi.h>
Index: arch/x86/acpi/acpi_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/acpi/acpi_machdep.c,v
retrieving revision 1.8
diff -u -r1.8 acpi_machdep.c
--- arch/x86/acpi/acpi_machdep.c        12 May 2014 11:51:34 -0000      1.8
+++ arch/x86/acpi/acpi_machdep.c        21 May 2014 20:06:01 -0000
@@ -61,6 +61,7 @@
 #include <machine/i82093reg.h>
 #include <machine/i82093var.h>
 #include <machine/pic.h>
+#include <machine/efi.h>
 
 #include <dev/pci/pcivar.h>
 
@@ -83,13 +84,25 @@
 acpi_md_OsGetRootPointer(void)
 {
        ACPI_PHYSICAL_ADDRESS PhysicalAddress;
-       ACPI_STATUS Status;
 
-       Status = AcpiFindRootPointer(&PhysicalAddress);
+       PhysicalAddress = 0;
 
-       if (ACPI_FAILURE(Status))
-               PhysicalAddress = 0;
+       /* If EFI is available, attempt to use it to locate the ACPI table. */
+       if (efi_probe()) {
+               PhysicalAddress = efi_getcfgtblpa(&EFI_UUID_ACPI20);
+               if (!PhysicalAddress) {
+                       PhysicalAddress = efi_getcfgtblpa(&EFI_UUID_ACPI10);
+               }
+       }
+
+       if (!PhysicalAddress) {
+               ACPI_STATUS Status;
 
+               Status = AcpiFindRootPointer(&PhysicalAddress);
+
+               if (ACPI_FAILURE(Status))
+                       PhysicalAddress = 0;
+       }
        return PhysicalAddress;
 }
 
Index: arch/x86/include/bootinfo.h
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/include/bootinfo.h,v
retrieving revision 1.23
diff -u -r1.23 bootinfo.h
--- arch/x86/include/bootinfo.h 30 Aug 2013 16:42:17 -0000      1.23
+++ arch/x86/include/bootinfo.h 21 May 2014 20:06:01 -0000
@@ -38,6 +38,7 @@
 #define BTINFO_MODULELIST      11
 #define BTINFO_FRAMEBUFFER     12
 #define BTINFO_USERCONFCOMMANDS        13
+#define BTINFO_EFI             14
 
 #ifndef _LOCORE
 
@@ -213,6 +214,12 @@
        /* bi_userconfcommand list follows */
 };
 
+/* EFI Information */
+struct btinfo_efi {
+       struct btinfo_common common;
+       paddr_t              bi_systbl; /* Physical address of the EFI System 
Table */
+};
+
 #endif /* _LOCORE */
 
 #ifdef _KERNEL
@@ -237,6 +244,7 @@
 extern struct bootinfo bootinfo;
 
 void *lookup_bootinfo(int);
+void  aprint_bootinfo(void);
 #endif /* _LOCORE */
 
 #endif /* _KERNEL */
Index: arch/x86/include/efi.h
===================================================================
RCS file: arch/x86/include/efi.h
diff -N arch/x86/include/efi.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ arch/x86/include/efi.h      21 May 2014 20:06:01 -0000
@@ -0,0 +1,175 @@
+/*     $NetBSD: efi.h,v 1.1 2006/04/07 14:21:18 cherry Exp $   */
+
+/*-
+ * Copyright (c) 2004 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 ``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$
+ */
+
+/* This file is mainly ia64/include/efi.h with little modifications. */
+
+#ifndef _MACHINE_EFI_H_
+#define _MACHINE_EFI_H_
+
+#include <sys/uuid.h>
+
+#define        EFI_PAGE_SHIFT          12
+#define        EFI_PAGE_SIZE           (1 << EFI_PAGE_SHIFT)
+#define        EFI_PAGE_MASK           (EFI_PAGE_SIZE - 1)
+
+extern const struct uuid EFI_UUID_ACPI20;
+extern const struct uuid EFI_UUID_ACPI10;
+
+#define        EFI_TABLE_SAL                           \
+       {0xeb9d2d32,0x2d88,0x11d3,0x9a,0x16,{0x00,0x90,0x27,0x3f,0xc1,0x4d}}
+
+enum efi_reset {
+       EFI_RESET_COLD,
+       EFI_RESET_WARM
+};
+
+typedef uint16_t       efi_char;
+typedef unsigned long efi_status;
+
+
+struct efi_cfgtbl {
+       struct uuid     ct_uuid;
+       uint64_t        ct_data;
+};
+struct efi_md {
+       uint32_t        md_type;
+#define        EFI_MD_TYPE_NULL        0
+#define        EFI_MD_TYPE_CODE        1       /* Loader text. */
+#define        EFI_MD_TYPE_DATA        2       /* Loader data. */
+#define        EFI_MD_TYPE_BS_CODE     3       /* Boot services text. */
+#define        EFI_MD_TYPE_BS_DATA     4       /* Boot services data. */
+#define        EFI_MD_TYPE_RT_CODE     5       /* Runtime services text. */
+#define        EFI_MD_TYPE_RT_DATA     6       /* Runtime services data. */
+#define        EFI_MD_TYPE_FREE        7       /* Unused/free memory. */
+#define        EFI_MD_TYPE_BAD         8       /* Bad memory */
+#define        EFI_MD_TYPE_RECLAIM     9       /* ACPI reclaimable memory. */
+#define        EFI_MD_TYPE_FIRMWARE    10      /* ACPI NV memory */
+#define        EFI_MD_TYPE_IOMEM       11      /* Memory-mapped I/O. */
+#define        EFI_MD_TYPE_IOPORT      12      /* I/O port space. */
+#define        EFI_MD_TYPE_PALCODE     13      /* PAL */
+       uint32_t        __pad;
+       uint64_t        md_phys;
+       void            *md_virt;
+       uint64_t        md_pages;
+       uint64_t        md_attr;
+#define        EFI_MD_ATTR_UC          0x0000000000000001UL
+#define        EFI_MD_ATTR_WC          0x0000000000000002UL
+#define        EFI_MD_ATTR_WT          0x0000000000000004UL
+#define        EFI_MD_ATTR_WB          0x0000000000000008UL
+#define        EFI_MD_ATTR_UCE         0x0000000000000010UL
+#define        EFI_MD_ATTR_WP          0x0000000000001000UL
+#define        EFI_MD_ATTR_RP          0x0000000000002000UL
+#define        EFI_MD_ATTR_XP          0x0000000000004000UL
+#define        EFI_MD_ATTR_RT          0x8000000000000000UL
+};
+
+struct efi_tm {
+       uint16_t        tm_year;                /* 1998 - 20XX */
+       uint8_t         tm_mon;                 /* 1 - 12 */
+       uint8_t         tm_mday;                /* 1 - 31 */
+       uint8_t         tm_hour;                /* 0 - 23 */
+       uint8_t         tm_min;                 /* 0 - 59 */
+       uint8_t         tm_sec;                 /* 0 - 59 */
+       uint8_t         __pad1;
+       uint32_t        tm_nsec;                /* 0 - 999,999,999 */
+       int16_t         tm_tz;                  /* -1440 to 1440 or 2047 */
+       uint8_t         tm_dst;
+       uint8_t         __pad2;
+};
+
+struct efi_tmcap {
+       uint32_t        tc_res;         /* 1e-6 parts per million */
+       uint32_t        tc_prec;        /* hertz */
+       uint8_t         tc_stz;         /* Set clears sub-second time */
+};
+
+struct efi_tblhdr {
+       uint64_t        th_sig;
+       uint32_t        th_rev;
+       uint32_t        th_hdrsz;
+       uint32_t        th_crc32;
+       uint32_t        __res;
+};
+
+struct efi_rt {
+       struct efi_tblhdr rt_hdr;
+       efi_status      (*rt_gettime)(struct efi_tm *, struct efi_tmcap *);
+       efi_status      (*rt_settime)(struct efi_tm *);
+       efi_status      (*rt_getwaketime)(uint8_t *, uint8_t *,
+           struct efi_tm *);
+       efi_status      (*rt_setwaketime)(uint8_t, struct efi_tm *);
+       efi_status      (*rt_setvirtual)(u_long, u_long, uint32_t,
+           struct efi_md *);
+       efi_status      (*rt_cvtptr)(u_long, void **);
+       efi_status      (*rt_getvar)(efi_char *, struct uuid *, uint32_t *,
+           u_long *, void *);
+       efi_status      (*rt_scanvar)(u_long *, efi_char *, struct uuid *);
+       efi_status      (*rt_setvar)(efi_char *, struct uuid *, uint32_t,
+           u_long, void *);
+       efi_status      (*rt_gethicnt)(uint32_t *);
+       efi_status      (*rt_reset)(enum efi_reset, efi_status, u_long,
+           efi_char *);
+};
+
+struct efi_systbl {
+       struct efi_tblhdr st_hdr;
+#define        EFI_SYSTBL_SIG  0x5453595320494249UL
+       efi_char        *st_fwvendor;
+       uint32_t        st_fwrev;
+       uint32_t        __pad;
+       void            *st_cin;
+       void            *st_cinif;
+       void            *st_cout;
+       void            *st_coutif;
+       void            *st_cerr;
+       void            *st_cerrif;
+       uint64_t        st_rt;
+       void            *st_bs;
+       u_long          st_entries;
+       uint64_t        st_cfgtbl;
+};
+
+bool               efi_probe(void);
+paddr_t            efi_getsystblpa(void);
+struct efi_systbl *efi_getsystbl(void);
+paddr_t            efi_getcfgtblpa(const struct uuid*);
+void              *efi_getcfgtbl(const struct uuid*);
+/*
+void efi_boot_finish(void);
+int efi_boot_minimal(uint64_t);
+void *efi_get_table(struct uuid *);
+void efi_get_time(struct efi_tm *);
+struct efi_md *efi_md_first(void);
+struct efi_md *efi_md_next(struct efi_md *);
+void efi_reset_system(void);
+efi_status efi_set_time(struct efi_tm *);
+*/
+
+#endif /* _MACHINE_EFI_H_ */
Index: arch/x86/x86/efi.c
===================================================================
RCS file: arch/x86/x86/efi.c
diff -N arch/x86/x86/efi.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ arch/x86/x86/efi.c  21 May 2014 20:06:01 -0000
@@ -0,0 +1,254 @@
+#include <sys/cdefs.h>
+#include <sys/kmem.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/uuid.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/bootinfo.h>
+#include <machine/efi.h>
+
+#include <dev/mm.h>
+
+const struct uuid EFI_UUID_ACPI20 = {
+       .time_low = 0x8868e871,
+       .time_mid = 0xe4f1, 
+       .time_hi_and_version = 0x11d3,
+       .clock_seq_hi_and_reserved = 0xbc,
+       .clock_seq_low =0x22,
+       .node = { 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 }
+};
+const struct uuid EFI_UUID_ACPI10 = { 
+       .time_low = 0xeb9d2d30,
+       .time_mid = 0x2d88,
+       .time_hi_and_version =  0x11d3,
+       .clock_seq_hi_and_reserved = 0x9a,
+       .clock_seq_low = 0x16, 
+       .node = { 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d }
+};
+
+vaddr_t            efi_getva(paddr_t);
+void               efi_relva(vaddr_t);
+struct efi_cfgtbl *efi_getcfgtblhead(void);
+void               efi_aprintcfgtbl(void);
+void               efi_aprintuuid(const struct uuid *);
+bool              efi_uuideq(const struct uuid *, const struct uuid *);
+
+static struct efi_systbl *efi_systbl_va = NULL;
+static struct efi_cfgtbl *efi_cfgtblhead_va = NULL;
+
+/*
+ * Map a physical address (PA) to a newly allocated virtual address (VA). 
+ * The VA must be freed using efi_relva().
+ */
+vaddr_t
+efi_getva(paddr_t pa)
+{
+       vaddr_t va;
+
+#ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS
+       mm_md_direct_mapped_phys(pa, &va);
+#else
+       /* XXX This code path is not tested. */
+       va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
+                                 UVM_KMF_VAONLY | UVM_KMF_WAITVA);
+       if (va == 0) {
+               aprint_debug("efi: unable to allocate va\n");
+               return NULL;
+       }
+       pmap_kenter_pa(va, pa, VM_PROT_READ, 0);
+       pmap_update( pmap_kernel() );
+#endif
+       return va;
+}
+
+/*
+ * Free a virtual address (VA) allocated using efi_getva().
+ */
+void
+efi_relva(vaddr_t va)
+{
+#ifdef __HAVE_MM_MD_DIRECT_MAPPED_PHYS
+       /* XXX Should we free the va? */
+#else
+       /* XXX This code path is not tested. */
+       uvm_km_free(kernel_map, va, PAGE_SIZE, UVM_KMF_VAONLY);
+#endif
+}
+
+/*
+ * Test if 2 UUIDs matches.
+ */
+bool
+efi_uuideq(const struct uuid *a, const struct uuid *b)
+{
+       return !memcmp(a, b, sizeof(struct uuid));
+}
+
+/*
+ * Print an UUID in a human-readable manner.
+ */
+void
+efi_aprintuuid(const struct uuid *uuid)
+{
+       int i;
+
+       aprint_debug(" %08"PRIx32"", uuid->time_low);
+       aprint_debug("-%04"PRIx16"", uuid->time_mid);
+       aprint_debug("-%04"PRIx16"", uuid->time_hi_and_version);
+       aprint_debug("-%02"PRIx8"",  uuid->clock_seq_hi_and_reserved);
+               aprint_debug("-%02"PRIx8"",  uuid->clock_seq_low);
+               aprint_debug("-");
+       for (i = 0; i < _UUID_NODE_LEN; i++) {
+                       aprint_debug("%02"PRIx8"", uuid->node[i]);
+       }
+       /* If known, also print the human-readable name */
+       if (efi_uuideq(uuid, &EFI_UUID_ACPI20)) {
+               aprint_debug(" ACPI 2.0");
+       } else if (efi_uuideq(uuid, &EFI_UUID_ACPI10)) {
+               aprint_debug(" ACPI 1.0");
+       }
+}
+
+/* 
+ * Return the VA of the cfgtbl. Must be freed using efi_relva().
+ */
+struct efi_cfgtbl *
+efi_getcfgtblhead(void)
+{
+       if (efi_cfgtblhead_va == NULL) {
+               paddr_t pa;
+               vaddr_t va;
+
+               pa = (paddr_t)efi_systbl_va->st_cfgtbl;
+               aprint_debug("efi: cfgtbl at pa %"PRIx64"\n", pa);
+               va = efi_getva(pa);
+               aprint_debug("efi: cfgtbl mapped at va %"PRIx64"\n", va);
+               efi_cfgtblhead_va = (struct efi_cfgtbl *)va;
+               efi_aprintcfgtbl();
+       }
+       return efi_cfgtblhead_va;
+}
+
+/*
+ * Print the config tables.
+ */
+void
+efi_aprintcfgtbl(void)
+{
+       struct efi_cfgtbl *ct;
+       unsigned long      count;
+
+       ct    = efi_cfgtblhead_va;
+       count = efi_systbl_va->st_entries;
+        aprint_debug("efi: %lu cfgtbl entries:\n", count);
+       for (; count; count--, ct++) {
+               aprint_debug("efi: %16"PRIx64"", ct->ct_data);
+               efi_aprintuuid(&ct->ct_uuid);
+                       aprint_debug("\n");
+       }
+}
+
+/*
+ * Return the VA of the config table with the given UUID if found.
+ * The VA must be freed using efi_relva().
+ */
+void *
+efi_getcfgtbl(const struct uuid *uuid)
+{
+       paddr_t pa;
+       vaddr_t va;
+
+       pa = efi_getcfgtblpa(uuid);
+       if (pa == 0) {
+               return NULL;
+       }
+       va = efi_getva(pa);
+       return (void *)va;
+}
+
+/*
+ * Return the PA of the first config table.
+ */
+paddr_t
+efi_getcfgtblpa(const struct uuid *uuid)
+{
+       struct efi_cfgtbl *ct;
+       unsigned long      count;
+
+       ct    = efi_cfgtblhead_va;
+       count = efi_systbl_va->st_entries;
+       for (; count; count--, ct++) {
+               if (efi_uuideq(&ct->ct_uuid, uuid)) {
+                       return (paddr_t)ct->ct_data;
+               }
+       }
+       return 0; /* Not found. */
+}
+
+/* Return the PA of the EFI System Table. */
+paddr_t
+efi_getsystblpa(void)
+{
+       struct btinfo_efi *bi;
+       paddr_t            pa;
+
+       bi = lookup_bootinfo(BTINFO_EFI);
+       if (bi == NULL) {
+               /* Unable to locate the EFI System Table. */
+               return 0;
+       }
+       pa = bi->bi_systbl;
+       return pa;
+}
+
+/* 
+ * Return a pointer to the EFI System Table. The pointer must be 
+ * freed using efi_relva(). 
+ */
+struct efi_systbl *
+efi_getsystbl(void)
+{
+       if (!efi_systbl_va) {
+               paddr_t pa;
+               vaddr_t va;
+               struct efi_systbl *systbl;
+
+               pa = efi_getsystblpa();
+               if (pa == 0)
+                       return NULL;
+               aprint_normal("efi: systbl at pa %"PRIx64"\n", pa);
+               va = efi_getva(pa);
+               aprint_debug("efi: systbl mapped at va %"PRIx64"\n", va);
+               systbl = (struct efi_systbl *)va;
+               /* XXX Check the signature and the CRC32 */
+               aprint_debug("efi: signature %"PRIx64" revision %"PRIx32" crc32 
%"PRIx32"\n", 
+                            systbl->st_hdr.th_sig, systbl->st_hdr.th_rev, 
+                            systbl->st_hdr.th_crc32);
+               aprint_debug("efi: firmware revision %"PRIx32"\n", 
systbl->st_fwrev);
+               /* XXX Also print fwvendor, which is an UCS-2 string (use some 
UTF-16 routine?) */
+               aprint_debug("efi: runtime services at pa %"PRIx64"\n", 
systbl->st_rt);
+               aprint_debug("efi: boot services at pa %"PRIx64"\n", 
(uint64_t)systbl->st_bs);
+               efi_systbl_va = systbl;
+       }
+       return efi_systbl_va;
+}
+
+/* 
+ * EFI is available if we are able to locate the EFI System Table. 
+ */
+bool
+efi_probe(void)
+{
+       if (efi_getsystbl() == 0) {
+               aprint_debug("efi: missing or invalid systbl");
+               return false;
+       }
+       if (efi_getcfgtblhead() == 0) {
+               aprint_debug("efi: missing or invalid cfgtbl");
+               efi_relva((vaddr_t)efi_systbl_va);
+               return false;
+       }
+       return true;
+}
Index: arch/x86/x86/x86_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x86/x86/x86_machdep.c,v
retrieving revision 1.64
diff -u -r1.64 x86_machdep.c
--- arch/x86/x86/x86_machdep.c  1 Apr 2014 07:16:18 -0000       1.64
+++ arch/x86/x86/x86_machdep.c  21 May 2014 20:06:01 -0000
@@ -121,6 +121,67 @@
 }
 
 /*
+ * List the available bootinfo entries.
+ */
+void
+aprint_bootinfo(void)
+{
+       int i;
+       struct btinfo_common *bic;
+
+       aprint_normal("bootinfo:");
+       bic = (struct btinfo_common *)(bootinfo.bi_data);
+       for (i = 0; i < bootinfo.bi_nentries; i++) {
+               switch (bic->type) {
+               case BTINFO_BOOTPATH:    
+                       aprint_normal(" bootpath");
+                       break;
+               case BTINFO_ROOTDEVICE:  
+                       aprint_normal(" rootdevice");
+                       break;
+               case BTINFO_BOOTDISK:    
+                       aprint_normal(" bootdisk");
+                       break;
+               case BTINFO_NETIF:       
+                       aprint_normal(" netif");
+                       break;
+               case BTINFO_CONSOLE:     
+                       aprint_normal(" console");
+                       break;
+               case BTINFO_BIOSGEOM:    
+                       aprint_normal(" biosgeom");
+                       break;
+               case BTINFO_SYMTAB:      
+                       aprint_normal(" symtab");
+                       break;
+               case BTINFO_MEMMAP:      
+                       aprint_normal(" memmap");
+                       break;
+               case BTINFO_BOOTWEDGE:   
+                       aprint_normal(" bootwedge");
+                       break;
+               case BTINFO_MODULELIST:
+                       aprint_normal(" modulelist");
+                       break;
+               case BTINFO_FRAMEBUFFER:
+                       aprint_normal(" framebuffer");
+                       break;
+               case BTINFO_USERCONFCOMMANDS: 
+                       aprint_normal(" userconfcommands");
+                       break;
+               case BTINFO_EFI: 
+                       aprint_normal(" efi");
+                       break;
+               default:
+                       aprint_normal(" %d", bic->type);
+               }
+               bic = (struct btinfo_common *)
+                   ((uint8_t *)bic + bic->len);
+       }
+       aprint_normal("\n");
+}
+
+/*
  * mm_md_physacc: check if given pa is accessible.
  */
 int

Attachment: dmesg-generic.out
Description: Binary data

Attachment: dmesg-current.out
Description: Binary data



Home | Main Index | Thread Index | Old Index