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;
+}

Reply via email to