xref: /freebsd/usr.sbin/acpi/acpidump/acpi_user.c (revision 1b6c76a2fe091c74f08427e6c870851025a9cf67)
1 /*-
2  * Copyright (c) 1999 Doug Rabson
3  * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *	$Id: acpi_user.c,v 1.5 2000/08/09 14:47:52 iwasaki Exp $
28  *	$FreeBSD$
29  */
30 
31 #include <sys/param.h>
32 #include <sys/mman.h>
33 #include <sys/queue.h>
34 #include <sys/stat.h>
35 
36 #include <err.h>
37 #include <fcntl.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 
42 #include "acpidump.h"
43 
44 static int      acpi_mem_fd = -1;
45 
46 struct acpi_user_mapping {
47 	LIST_ENTRY(acpi_user_mapping) link;
48 	vm_offset_t     pa;
49 	caddr_t         va;
50 	size_t          size;
51 };
52 
53 LIST_HEAD(acpi_user_mapping_list, acpi_user_mapping) maplist;
54 
55 static void
56 acpi_user_init()
57 {
58 
59 	if (acpi_mem_fd == -1) {
60 		acpi_mem_fd = open("/dev/mem", O_RDONLY);
61 		if (acpi_mem_fd == -1)
62 			err(1, "opening /dev/mem");
63 		LIST_INIT(&maplist);
64 	}
65 }
66 
67 static struct acpi_user_mapping *
68 acpi_user_find_mapping(vm_offset_t pa, size_t size)
69 {
70 	struct	acpi_user_mapping *map;
71 
72 	/* First search for an existing mapping */
73 	for (map = LIST_FIRST(&maplist); map; map = LIST_NEXT(map, link)) {
74 		if (map->pa <= pa && map->size >= pa + size - map->pa)
75 			return (map);
76 	}
77 
78 	/* Then create a new one */
79 	size = round_page(pa + size) - trunc_page(pa);
80 	pa = trunc_page(pa);
81 	map = malloc(sizeof(struct acpi_user_mapping));
82 	if (!map)
83 		errx(1, "out of memory");
84 	map->pa = pa;
85 	map->va = mmap(0, size, PROT_READ, MAP_SHARED, acpi_mem_fd, pa);
86 	map->size = size;
87 	if ((intptr_t) map->va == -1)
88 		err(1, "can't map address");
89 	LIST_INSERT_HEAD(&maplist, map, link);
90 
91 	return (map);
92 }
93 
94 /*
95  * Public interfaces
96  */
97 
98 struct ACPIrsdp *
99 acpi_find_rsd_ptr()
100 {
101 	int		i;
102 	u_int8_t	buf[sizeof(struct ACPIrsdp)];
103 
104 	acpi_user_init();
105 	for (i = 0; i < 1024 * 1024; i += 16) {
106 		read(acpi_mem_fd, buf, 16);
107 		if (!memcmp(buf, "RSD PTR ", 8)) {
108 			/* Read the rest of the structure */
109 			read(acpi_mem_fd, buf + 16, sizeof(struct ACPIrsdp) - 16);
110 
111 			/* Verify checksum before accepting it. */
112 			if (acpi_checksum(buf, sizeof(struct ACPIrsdp)))
113 				continue;
114 			return (acpi_map_physical(i, sizeof(struct ACPIrsdp)));
115 		}
116 	}
117 
118 	return (0);
119 }
120 
121 void *
122 acpi_map_physical(vm_offset_t pa, size_t size)
123 {
124 	struct	acpi_user_mapping *map;
125 
126 	map = acpi_user_find_mapping(pa, size);
127 	return (map->va + (pa - map->pa));
128 }
129 
130 void
131 acpi_load_dsdt(char *dumpfile, u_int8_t **dpp, u_int8_t **endp)
132 {
133 	u_int8_t	*dp;
134 	u_int8_t	*end;
135 	struct	stat sb;
136 
137 	if ((acpi_mem_fd = open(dumpfile, O_RDONLY)) == -1) {
138 		errx(1, "opening %s\n", dumpfile);
139 	}
140 
141 	LIST_INIT(&maplist);
142 
143 	if (fstat(acpi_mem_fd, &sb) == -1) {
144 		errx(1, "fstat %s\n", dumpfile);
145 	}
146 
147 	dp = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, acpi_mem_fd, 0);
148 	if (dp == NULL) {
149 		errx(1, "mmap %s\n", dumpfile);
150 	}
151 
152 	/*
153 	 * Microsoft asl.exe generates 0x23 byte additional info.
154 	 * at the begining of the file, so just ignore it.
155 	 */
156         if (strncmp(dp, "DSDT", 4) == 0) {
157                 dp += 0x23;
158 		sb.st_size -= 0x23;
159         }
160 
161 	end = (u_int8_t *) dp + sb.st_size;
162 	*dpp = dp;
163 	*endp = end;
164 }
165