Module Name: src
Committed By: jmcneill
Date: Sun Dec 6 02:57:31 UTC 2020
Modified Files:
src/etc: MAKEDEV.tmpl
src/etc/etc.aarch64: MAKEDEV.conf
src/etc/etc.amd64: MAKEDEV.conf
src/etc/etc.i386: MAKEDEV.conf
src/etc/etc.ia64: MAKEDEV.conf
src/share/man/man4: acpi.4
src/sys/conf: majors
src/sys/dev/acpi: files.acpi
src/usr.sbin/acpitools/acpidump: acpi_user.c acpidump.8 acpidump.c
Added Files:
src/sys/dev/acpi: acpi_dev.c
Log Message:
acpi: add character device for accessing ACPI tables
The /dev/acpi character device gives an aperture into physical memory
that allows only read access to known ACPI tables: RSDP, XSDT/RSDT, and
the root tables. Adapt acpidump(8) to use this interface by default,
falling back to the old /dev/mem method if it is not available or if
ACPIDUMP_USE_DEVMEM=1 is set in the environment. The user visible benefit
of this change is that "options INSECURE" is no longer required to
dump ACPI tables.
To generate a diff of this commit:
cvs rdiff -u -r1.221 -r1.222 src/etc/MAKEDEV.tmpl
cvs rdiff -u -r1.7 -r1.8 src/etc/etc.aarch64/MAKEDEV.conf
cvs rdiff -u -r1.31 -r1.32 src/etc/etc.amd64/MAKEDEV.conf
cvs rdiff -u -r1.32 -r1.33 src/etc/etc.i386/MAKEDEV.conf
cvs rdiff -u -r1.4 -r1.5 src/etc/etc.ia64/MAKEDEV.conf
cvs rdiff -u -r1.86 -r1.87 src/share/man/man4/acpi.4
cvs rdiff -u -r1.96 -r1.97 src/sys/conf/majors
cvs rdiff -u -r0 -r1.1 src/sys/dev/acpi/acpi_dev.c
cvs rdiff -u -r1.115 -r1.116 src/sys/dev/acpi/files.acpi
cvs rdiff -u -r1.5 -r1.6 src/usr.sbin/acpitools/acpidump/acpi_user.c
cvs rdiff -u -r1.16 -r1.17 src/usr.sbin/acpitools/acpidump/acpidump.8
cvs rdiff -u -r1.7 -r1.8 src/usr.sbin/acpitools/acpidump/acpidump.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/etc/MAKEDEV.tmpl
diff -u src/etc/MAKEDEV.tmpl:1.221 src/etc/MAKEDEV.tmpl:1.222
--- src/etc/MAKEDEV.tmpl:1.221 Sun Jul 26 15:47:27 2020
+++ src/etc/MAKEDEV.tmpl Sun Dec 6 02:57:29 2020
@@ -1,5 +1,5 @@
#!/bin/sh -
-# $NetBSD: MAKEDEV.tmpl,v 1.221 2020/07/26 15:47:27 jdolecek Exp $
+# $NetBSD: MAKEDEV.tmpl,v 1.222 2020/12/06 02:57:29 jmcneill Exp $
#
# Copyright (c) 2003,2007,2008 The NetBSD Foundation, Inc.
# All rights reserved.
@@ -2243,6 +2243,10 @@ xmm[0-9])
mkdev ttyXMM${unit}1 c %wwanc_chr% $(($unit * 65536 + 4))
;;
+acpi)
+ mkdev acpi c %acpi_chr% 0
+ ;;
+
midevend)
%MI_DEVICES_END%
local)
Index: src/etc/etc.aarch64/MAKEDEV.conf
diff -u src/etc/etc.aarch64/MAKEDEV.conf:1.7 src/etc/etc.aarch64/MAKEDEV.conf:1.8
--- src/etc/etc.aarch64/MAKEDEV.conf:1.7 Sat Dec 15 01:02:58 2018
+++ src/etc/etc.aarch64/MAKEDEV.conf Sun Dec 6 02:57:30 2020
@@ -1,4 +1,4 @@
-# $NetBSD: MAKEDEV.conf,v 1.7 2018/12/15 01:02:58 jmcneill Exp $
+# $NetBSD: MAKEDEV.conf,v 1.8 2020/12/06 02:57:30 jmcneill Exp $
all_md)
makedev wscons fd0 fd1 wd0 wd1 wd2 wd3 sd0 sd1 sd2 sd3
@@ -20,6 +20,7 @@ all_md)
makedev spiflash0
makedev bpf
makedev openfirm
+ makedev acpi
;;
ramdisk|floppy)
Index: src/etc/etc.amd64/MAKEDEV.conf
diff -u src/etc/etc.amd64/MAKEDEV.conf:1.31 src/etc/etc.amd64/MAKEDEV.conf:1.32
--- src/etc/etc.amd64/MAKEDEV.conf:1.31 Mon Aug 3 04:32:13 2020
+++ src/etc/etc.amd64/MAKEDEV.conf Sun Dec 6 02:57:30 2020
@@ -1,4 +1,4 @@
-# $NetBSD: MAKEDEV.conf,v 1.31 2020/08/03 04:32:13 nia Exp $
+# $NetBSD: MAKEDEV.conf,v 1.32 2020/12/06 02:57:30 jmcneill Exp $
# As of 2003-04-17, the "init" case must not create more than 890 entries.
all_md)
@@ -45,6 +45,7 @@ all_md)
makedev kttcp
makedev bio
makedev xmm0
+ makedev acpi
;;
xen)
Index: src/etc/etc.i386/MAKEDEV.conf
diff -u src/etc/etc.i386/MAKEDEV.conf:1.32 src/etc/etc.i386/MAKEDEV.conf:1.33
--- src/etc/etc.i386/MAKEDEV.conf:1.32 Mon Aug 3 04:32:13 2020
+++ src/etc/etc.i386/MAKEDEV.conf Sun Dec 6 02:57:30 2020
@@ -1,4 +1,4 @@
-# $NetBSD: MAKEDEV.conf,v 1.32 2020/08/03 04:32:13 nia Exp $
+# $NetBSD: MAKEDEV.conf,v 1.33 2020/12/06 02:57:30 jmcneill Exp $
# As of 2005-03-15, the "init" case must not create more than 1024 entries.
all_md)
@@ -49,6 +49,7 @@ all_md)
makedev io
makedev bio
makedev cfs
+ makedev acpi
;;
xen)
Index: src/etc/etc.ia64/MAKEDEV.conf
diff -u src/etc/etc.ia64/MAKEDEV.conf:1.4 src/etc/etc.ia64/MAKEDEV.conf:1.5
--- src/etc/etc.ia64/MAKEDEV.conf:1.4 Sun Apr 5 14:09:18 2020
+++ src/etc/etc.ia64/MAKEDEV.conf Sun Dec 6 02:57:30 2020
@@ -1,4 +1,4 @@
-# $NetBSD: MAKEDEV.conf,v 1.4 2020/04/05 14:09:18 jdolecek Exp $
+# $NetBSD: MAKEDEV.conf,v 1.5 2020/12/06 02:57:30 jmcneill Exp $
# As of 2005-03-15, the "init" case must not create more than 1024 entries.
all_md)
@@ -43,4 +43,5 @@ all_md)
makedev io
makedev bio
makedev cfs
+ makedev acpi
;;
Index: src/share/man/man4/acpi.4
diff -u src/share/man/man4/acpi.4:1.86 src/share/man/man4/acpi.4:1.87
--- src/share/man/man4/acpi.4:1.86 Sun Mar 4 02:10:26 2018
+++ src/share/man/man4/acpi.4 Sun Dec 6 02:57:30 2020
@@ -1,4 +1,4 @@
-.\" $NetBSD: acpi.4,v 1.86 2018/03/04 02:10:26 pgoyette Exp $
+.\" $NetBSD: acpi.4,v 1.87 2020/12/06 02:57:30 jmcneill Exp $
.\"
.\" Copyright (c) 2002, 2004, 2010 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -24,7 +24,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd March 4, 2018
+.Dd December 5, 2020
.Dt ACPI 4
.Os
.Sh NAME
@@ -491,6 +491,10 @@ When
.Ic hw.acpi.debug.object
is set to 1, the message stored to the debug object
is printed every time the method is called by the interpreter.
+.Sh FILES
+.Bl -tag -width /dev/acpi
+.It Pa /dev/acpi
+.El
.Sh SEE ALSO
.Xr ioapic 4 ,
.Xr acpidump 8 ,
Index: src/sys/conf/majors
diff -u src/sys/conf/majors:1.96 src/sys/conf/majors:1.97
--- src/sys/conf/majors:1.96 Fri Aug 28 14:58:25 2020
+++ src/sys/conf/majors Sun Dec 6 02:57:30 2020
@@ -1,4 +1,4 @@
-# $NetBSD: majors,v 1.96 2020/08/28 14:58:25 riastradh Exp $
+# $NetBSD: majors,v 1.97 2020/12/06 02:57:30 jmcneill Exp $
#
# Device majors for Machine-Independent drivers.
#
@@ -90,3 +90,4 @@ device-major vhci char 355
device-major vio9p char 356 vio9p
device-major fault char 357 fault
device-major wwanc char 358 wwanc
+device-major acpi char 359 acpi
Index: src/sys/dev/acpi/files.acpi
diff -u src/sys/dev/acpi/files.acpi:1.115 src/sys/dev/acpi/files.acpi:1.116
--- src/sys/dev/acpi/files.acpi:1.115 Sat Feb 22 02:28:06 2020
+++ src/sys/dev/acpi/files.acpi Sun Dec 6 02:57:30 2020
@@ -1,4 +1,4 @@
-# $NetBSD: files.acpi,v 1.115 2020/02/22 02:28:06 jmcneill Exp $
+# $NetBSD: files.acpi,v 1.116 2020/12/06 02:57:30 jmcneill Exp $
include "dev/acpi/acpica/files.acpica"
@@ -21,6 +21,7 @@ device acpi: acpica, acpiapmbus, acpinod
attach acpi at acpibus
file dev/acpi/acpi.c acpi
file dev/acpi/acpi_debug.c acpi
+file dev/acpi/acpi_dev.c acpi
file dev/acpi/acpi_event.c acpi
file dev/acpi/acpi_i2c.c acpi
file dev/acpi/acpi_mcfg.c acpi & pci
Index: src/usr.sbin/acpitools/acpidump/acpi_user.c
diff -u src/usr.sbin/acpitools/acpidump/acpi_user.c:1.5 src/usr.sbin/acpitools/acpidump/acpi_user.c:1.6
--- src/usr.sbin/acpitools/acpidump/acpi_user.c:1.5 Thu Aug 20 15:54:12 2020
+++ src/usr.sbin/acpitools/acpidump/acpi_user.c Sun Dec 6 02:57:30 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_user.c,v 1.5 2020/08/20 15:54:12 riastradh Exp $ */
+/* $NetBSD: acpi_user.c,v 1.6 2020/12/06 02:57:30 jmcneill Exp $ */
/*-
* Copyright (c) 1999 Doug Rabson
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: acpi_user.c,v 1.5 2020/08/20 15:54:12 riastradh Exp $");
+__RCSID("$NetBSD: acpi_user.c,v 1.6 2020/12/06 02:57:30 jmcneill Exp $");
#include <sys/param.h>
#include <sys/mman.h>
@@ -39,6 +39,7 @@ __RCSID("$NetBSD: acpi_user.c,v 1.5 2020
#include <sys/sysctl.h>
#include <err.h>
+#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
@@ -48,6 +49,7 @@ __RCSID("$NetBSD: acpi_user.c,v 1.5 2020
static char machdep_acpi_root[] = "hw.acpi.root";
static int acpi_mem_fd = -1;
+static bool acpi_mem_mmap = false;
struct acpi_user_mapping {
LIST_ENTRY(acpi_user_mapping) link;
@@ -61,15 +63,48 @@ static LIST_HEAD(acpi_user_mapping_list,
static void
acpi_user_init(void)
{
+ int saved_errno, use_devmem;
+ const char *s;
if (acpi_mem_fd == -1) {
- acpi_mem_fd = open("/dev/mem", O_RDONLY);
- if (acpi_mem_fd == -1)
- err(EXIT_FAILURE, "opening /dev/mem");
+ s = getenv("ACPIDUMP_USE_DEVMEM");
+ use_devmem = s != NULL && *s == '1';
+ if (!use_devmem) {
+ acpi_mem_fd = open("/dev/acpi", O_RDONLY);
+ }
+ if (acpi_mem_fd == -1) {
+ saved_errno = errno;
+ acpi_mem_fd = open("/dev/mem", O_RDONLY);
+ if (acpi_mem_fd == -1) {
+ errno = saved_errno;
+ } else {
+ acpi_mem_mmap = true;
+ }
+ }
+ if (acpi_mem_fd == -1) {
+ err(EXIT_FAILURE, "opening /dev/acpi");
+ }
LIST_INIT(&maplist);
}
}
+static void *
+acpi_user_read_table(vm_offset_t pa, size_t psize)
+{
+ void *data;
+ ssize_t len;
+
+ data = calloc(1, psize);
+ if (!data)
+ errx(EXIT_FAILURE, "out of memory");
+
+ len = pread(acpi_mem_fd, data, psize, pa);
+ if (len == -1)
+ errx(EXIT_FAILURE, "can't read table");
+
+ return data;
+}
+
static struct acpi_user_mapping *
acpi_user_find_mapping(vm_offset_t pa, size_t size)
{
@@ -82,16 +117,22 @@ acpi_user_find_mapping(vm_offset_t pa, s
}
/* Then create a new one */
- size = round_page(pa + size) - trunc_page(pa);
- pa = trunc_page(pa);
+ if (acpi_mem_mmap) {
+ size = round_page(pa + size) - trunc_page(pa);
+ pa = trunc_page(pa);
+ }
map = malloc(sizeof(struct acpi_user_mapping));
if (!map)
errx(EXIT_FAILURE, "out of memory");
map->pa = pa;
- map->va = mmap(0, size, PROT_READ, MAP_SHARED, acpi_mem_fd, pa);
+ if (acpi_mem_mmap) {
+ map->va = mmap(0, size, PROT_READ, MAP_SHARED, acpi_mem_fd, pa);
+ if ((intptr_t) map->va == -1)
+ err(EXIT_FAILURE, "can't map address");
+ } else {
+ map->va = acpi_user_read_table(pa, size);
+ }
map->size = size;
- if ((intptr_t) map->va == -1)
- err(EXIT_FAILURE, "can't map address");
LIST_INSERT_HEAD(&maplist, map, link);
return map;
Index: src/usr.sbin/acpitools/acpidump/acpidump.8
diff -u src/usr.sbin/acpitools/acpidump/acpidump.8:1.16 src/usr.sbin/acpitools/acpidump/acpidump.8:1.17
--- src/usr.sbin/acpitools/acpidump/acpidump.8:1.16 Sat Jun 22 12:39:40 2019
+++ src/usr.sbin/acpitools/acpidump/acpidump.8 Sun Dec 6 02:57:30 2020
@@ -1,4 +1,4 @@
-.\" $NetBSD: acpidump.8,v 1.16 2019/06/22 12:39:40 maxv Exp $
+.\" $NetBSD: acpidump.8,v 1.17 2020/12/06 02:57:30 jmcneill Exp $
.\" ACPI (ACPI Package)
.\"
.\" Copyright (c) 1999 Doug Rabson <[email protected]>
@@ -30,7 +30,7 @@
.\"
.\" $FreeBSD: head/usr.sbin/acpi/acpidump/acpidump.8 267668 2014-06-20 09:57:27Z bapt $
.\"
-.Dd June 22, 2019
+.Dd December 4, 2020
.Dt ACPIDUMP 8
.Os
.Sh NAME
@@ -73,7 +73,7 @@ When
is invoked without the
.Fl f
option, it will read ACPI tables from physical memory via
-.Pa /dev/mem .
+.Pa /dev/acpi .
First it searches for the RSDP
(Root System Description Pointer),
which has the signature
@@ -173,8 +173,8 @@ Dump the contents of the various fixed t
Enable verbose messages.
.El
.Sh FILES
-.Bl -tag -width /dev/mem
-.It Pa /dev/mem
+.Bl -tag -width /dev/acpi
+.It Pa /dev/acpi
.El
.Sh EXAMPLES
If a developer requests a copy of your ASL, please use the following
Index: src/usr.sbin/acpitools/acpidump/acpidump.c
diff -u src/usr.sbin/acpitools/acpidump/acpidump.c:1.7 src/usr.sbin/acpitools/acpidump/acpidump.c:1.8
--- src/usr.sbin/acpitools/acpidump/acpidump.c:1.7 Fri Aug 4 06:30:36 2017
+++ src/usr.sbin/acpitools/acpidump/acpidump.c Sun Dec 6 02:57:30 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: acpidump.c,v 1.7 2017/08/04 06:30:36 msaitoh Exp $ */
+/* $NetBSD: acpidump.c,v 1.8 2020/12/06 02:57:30 jmcneill Exp $ */
/*-
* Copyright (c) 2000 Mitsuru IWASAKI <[email protected]>
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: acpidump.c,v 1.7 2017/08/04 06:30:36 msaitoh Exp $");
+__RCSID("$NetBSD: acpidump.c,v 1.8 2020/12/06 02:57:30 jmcneill Exp $");
#include <sys/param.h>
@@ -104,7 +104,7 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
- /* Get input either from file or /dev/mem */
+ /* Get input either from file or /dev/acpi */
if (dsdt_input_file != NULL) {
if (dflag == 0 && tflag == 0) {
warnx("Need to specify -d or -t with DSDT input file");
@@ -118,11 +118,11 @@ main(int argc, char *argv[])
rsdt = dsdt_load_file(dsdt_input_file);
} else {
if (vflag)
- warnx("loading RSD PTR from /dev/mem");
+ warnx("loading RSD PTR from /dev/acpi");
rsdt = sdt_load_devmem();
}
- /* Display misc. SDT tables (only available when using /dev/mem) */
+ /* Display misc. SDT tables (only available when using /dev/acpi) */
if (tflag) {
if (vflag)
warnx("printing various SDT tables");
Added files:
Index: src/sys/dev/acpi/acpi_dev.c
diff -u /dev/null src/sys/dev/acpi/acpi_dev.c:1.1
--- /dev/null Sun Dec 6 02:57:31 2020
+++ src/sys/dev/acpi/acpi_dev.c Sun Dec 6 02:57:30 2020
@@ -0,0 +1,220 @@
+/* $NetBSD: acpi_dev.c,v 1.1 2020/12/06 02:57:30 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2020 Jared McNeill <[email protected]>
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: acpi_dev.c,v 1.1 2020/12/06 02:57:30 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/mman.h>
+
+#include <dev/acpi/acpireg.h>
+#include <dev/acpi/acpivar.h>
+
+#define _COMPONENT ACPI_BUS_COMPONENT
+ACPI_MODULE_NAME ("acpi_dev")
+
+static dev_type_read(acpi_read);
+
+const struct cdevsw acpi_cdevsw = {
+ .d_open = nullopen,
+ .d_close = nullclose,
+ .d_read = acpi_read,
+ .d_write = nowrite,
+ .d_ioctl = noioctl,
+ .d_stop = nostop,
+ .d_tty = notty,
+ .d_poll = nopoll,
+ .d_mmap = nommap,
+ .d_kqfilter = nokqfilter,
+ .d_discard = nodiscard,
+ .d_flag = D_OTHER | D_MPSAFE,
+};
+
+/*
+ * acpi_find_table_rsdp --
+ *
+ * Returns true if the RSDP table is found and overlaps the specified
+ * physical address. The table's physical start address and length
+ * are placed in 'paddr' and 'plen' when found.
+ *
+ */
+static bool
+acpi_find_table_rsdp(ACPI_PHYSICAL_ADDRESS pa,
+ ACPI_PHYSICAL_ADDRESS *paddr, uint32_t *plen)
+{
+ ACPI_PHYSICAL_ADDRESS table_pa;
+
+ table_pa = AcpiOsGetRootPointer();
+ if (table_pa == 0) {
+ return false;
+ }
+ if (pa >= table_pa && pa < table_pa + sizeof(ACPI_TABLE_RSDP)) {
+ *paddr = table_pa;
+ *plen = sizeof(ACPI_TABLE_RSDP);
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * acpi_find_table_sdt --
+ *
+ * Returns true if the XSDT/RSDT table is found and overlaps the
+ * specified physical address. The table's physical start address
+ * and length are placed in 'paddr' and 'plen' when found.
+ *
+ */
+static bool
+acpi_find_table_sdt(ACPI_PHYSICAL_ADDRESS pa,
+ ACPI_PHYSICAL_ADDRESS *paddr, uint32_t *plen)
+{
+ ACPI_PHYSICAL_ADDRESS table_pa;
+ ACPI_TABLE_RSDP *rsdp;
+ ACPI_TABLE_HEADER *thdr;
+ uint32_t table_len;
+
+ table_pa = AcpiOsGetRootPointer();
+ KASSERT(table_pa != 0);
+
+ /*
+ * Find the XSDT/RSDT using the RSDP.
+ */
+ rsdp = AcpiOsMapMemory(table_pa, sizeof(ACPI_TABLE_RSDP));
+ if (rsdp == NULL) {
+ return false;
+ }
+ if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress) {
+ table_pa = rsdp->XsdtPhysicalAddress;
+ } else {
+ table_pa = rsdp->RsdtPhysicalAddress;
+ }
+ AcpiOsUnmapMemory(rsdp, sizeof(ACPI_TABLE_RSDP));
+ if (table_pa == 0) {
+ return false;
+ }
+
+ /*
+ * Map the XSDT/RSDT and check access.
+ */
+ thdr = AcpiOsMapMemory(table_pa, sizeof(ACPI_TABLE_HEADER));
+ if (thdr == NULL) {
+ return false;
+ }
+ table_len = thdr->Length;
+ AcpiOsUnmapMemory(thdr, sizeof(ACPI_TABLE_HEADER));
+ if (pa >= table_pa && pa < table_pa + table_len) {
+ *paddr = table_pa;
+ *plen = table_len;
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * acpi_find_table --
+ *
+ * Find an ACPI table that overlaps the specified physical address.
+ * Returns true if the table is found and places the table start
+ * address into 'paddr' and the length into 'plen'.
+ *
+ */
+static bool
+acpi_find_table(ACPI_PHYSICAL_ADDRESS pa,
+ ACPI_PHYSICAL_ADDRESS *paddr, uint32_t *plen)
+{
+ ACPI_TABLE_DESC *tdesc;
+ bool found_table;
+ uint32_t i;
+
+ /* Check for RSDP access. */
+ if (acpi_find_table_rsdp(pa, paddr, plen)) {
+ return true;
+ }
+
+ /* Check for XSDT/RSDT access. */
+ if (acpi_find_table_sdt(pa, paddr, plen)) {
+ return true;
+ }
+
+ /* Check for root table access. */
+ found_table = false;
+ AcpiUtAcquireMutex(ACPI_MTX_TABLES);
+ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) {
+ tdesc = &AcpiGbl_RootTableList.Tables[i];
+ if (pa >= tdesc->Address &&
+ pa < tdesc->Address + tdesc->Length) {
+ *paddr = tdesc->Address;
+ *plen = tdesc->Length;
+ found_table = true;
+ break;
+ }
+ }
+ AcpiUtReleaseMutex(ACPI_MTX_TABLES);
+ return found_table;
+}
+
+/*
+ * acpi_read --
+ *
+ * Read data from an ACPI configuration table that resides in
+ * physical memory. Only supports reading one table at a time.
+ *
+ */
+static int
+acpi_read(dev_t dev, struct uio *uio, int flag)
+{
+ ACPI_PHYSICAL_ADDRESS pa, table_pa;
+ uint32_t table_len;
+ uint8_t *data;
+ int error;
+ size_t len;
+
+ if (uio->uio_rw != UIO_READ) {
+ return EPERM;
+ }
+
+ /* Make sure this is a read of a known table */
+ if (!acpi_find_table(uio->uio_offset, &table_pa, &table_len)) {
+ return EIO;
+ }
+
+ /* Copy the contents of the table to user-space */
+ pa = uio->uio_offset;
+ len = uimin(pa - table_pa + table_len, uio->uio_resid);
+ data = AcpiOsMapMemory(pa, len);
+ if (data == NULL) {
+ return ENOMEM;
+ }
+ error = uiomove(data, len, uio);
+ AcpiOsUnmapMemory(data, len);
+
+ return error;
+}