4 * Copyright (c) 1999 Doug Rabson
5 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * $FreeBSD: src/usr.sbin/acpi/acpidump/acpi_user.c,v 1.15 2009/08/25 20:35:57 jhb Exp $
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: acpi.c,v 1.4 2008/02/13 18:59:18 drochner Exp $");
35 #include <sys/param.h>
37 #include <sys/queue.h>
39 #include <sys/sysctl.h>
49 static int acpi_mem_fd
= -1;
51 struct acpi_user_mapping
{
52 LIST_ENTRY(acpi_user_mapping
) link
;
58 LIST_HEAD(acpi_user_mapping_list
, acpi_user_mapping
) maplist
;
64 if (acpi_mem_fd
== -1) {
65 acpi_mem_fd
= open("/dev/mem", O_RDONLY
);
66 if (acpi_mem_fd
== -1)
67 err(EXIT_FAILURE
, "opening /dev/mem");
72 static struct acpi_user_mapping
*
73 acpi_user_find_mapping(vm_offset_t pa
, size_t size
)
75 struct acpi_user_mapping
*map
;
77 /* First search for an existing mapping */
78 for (map
= LIST_FIRST(&maplist
); map
; map
= LIST_NEXT(map
, link
)) {
79 if (map
->pa
<= pa
&& map
->size
>= pa
+ size
- map
->pa
)
83 /* Then create a new one */
84 size
= round_page(pa
+ size
) - trunc_page(pa
);
86 map
= malloc(sizeof(struct acpi_user_mapping
));
88 errx(EXIT_FAILURE
, "out of memory");
90 map
->va
= mmap(0, size
, PROT_READ
, MAP_SHARED
, acpi_mem_fd
, pa
);
92 if ((intptr_t) map
->va
== -1)
93 err(EXIT_FAILURE
, "can't map address");
94 LIST_INSERT_HEAD(&maplist
, map
, link
);
99 static ACPI_TABLE_RSDP
*
100 acpi_get_rsdp(u_long addr
)
102 ACPI_TABLE_RSDP rsdp
;
105 /* Read in the table signature and check it. */
106 pread(acpi_mem_fd
, &rsdp
, 8, addr
);
107 if (memcmp(rsdp
.Signature
, "RSD PTR ", 8))
110 /* Read the entire table. */
111 pread(acpi_mem_fd
, &rsdp
, sizeof(rsdp
), addr
);
113 /* Check the standard checksum. */
114 if (acpi_checksum(&rsdp
, ACPI_RSDP_CHECKSUM_LENGTH
) != 0)
117 /* Check extended checksum if table version >= 2. */
118 if (rsdp
.Revision
>= 2 &&
119 acpi_checksum(&rsdp
, ACPI_RSDP_XCHECKSUM_LENGTH
) != 0)
122 /* If the revision is 0, assume a version 1 length. */
123 if (rsdp
.Revision
== 0)
124 len
= ACPI_RSDP_REV0_SIZE
;
128 return (acpi_map_physical(addr
, len
));
131 static ACPI_TABLE_RSDP
*
132 acpi_scan_rsd_ptr(void)
134 #if defined(__amd64__) || defined(__i386__)
135 ACPI_TABLE_RSDP
*rsdp
;
139 * On ia32, scan physical memory for the RSD PTR if above failed.
140 * According to section 5.2.2 of the ACPI spec, we only consider
141 * two regions for the base address:
142 * 1. EBDA (1 KB area addressed by the 16 bit pointer at 0x40E
143 * 2. High memory (0xE0000 - 0xFFFFF)
145 addr
= ACPI_EBDA_PTR_LOCATION
;
146 pread(acpi_mem_fd
, &addr
, sizeof(uint16_t), addr
);
148 end
= addr
+ ACPI_EBDA_WINDOW_SIZE
;
149 for (; addr
< end
; addr
+= 16)
150 if ((rsdp
= acpi_get_rsdp(addr
)) != NULL
)
152 addr
= ACPI_HI_RSDP_WINDOW_BASE
;
153 end
= addr
+ ACPI_HI_RSDP_WINDOW_SIZE
;
154 for (; addr
< end
; addr
+= 16)
155 if ((rsdp
= acpi_get_rsdp(addr
)) != NULL
)
157 #endif /* __amd64__ || __i386__ */
165 acpi_find_rsd_ptr(void)
168 uint8_t buf
[sizeof(ACPI_TABLE_RSDP
)];
171 for (i
= 0; i
< 1024 * 1024; i
+= 16) {
172 read(acpi_mem_fd
, buf
, 16);
173 if (!memcmp(buf
, "RSD PTR ", 8)) {
174 /* Read the rest of the structure */
175 read(acpi_mem_fd
, buf
+ 16, sizeof(ACPI_TABLE_RSDP
) - 16);
177 /* Verify checksum before accepting it. */
178 if (acpi_checksum(buf
, sizeof(ACPI_TABLE_RSDP
)))
180 return (acpi_map_physical(i
, sizeof(ACPI_TABLE_RSDP
)));
184 return acpi_scan_rsd_ptr();
188 acpi_map_physical(vm_offset_t pa
, size_t size
)
190 struct acpi_user_mapping
*map
;
192 map
= acpi_user_find_mapping(pa
, size
);
193 return (map
->va
+ (pa
- map
->pa
));
197 dsdt_load_file(char *infile
)
199 ACPI_TABLE_HEADER
*sdt
;
203 if ((acpi_mem_fd
= open(infile
, O_RDONLY
)) == -1)
204 errx(EXIT_FAILURE
, "opening %s", infile
);
208 if (fstat(acpi_mem_fd
, &sb
) == -1)
209 errx(EXIT_FAILURE
, "fstat %s", infile
);
211 dp
= mmap(0, sb
.st_size
, PROT_READ
, MAP_PRIVATE
, acpi_mem_fd
, 0);
213 errx(EXIT_FAILURE
, "mmap %s", infile
);
215 sdt
= (ACPI_TABLE_HEADER
*)dp
;
216 if (strncmp((char *)dp
, ACPI_SIG_DSDT
, 4) != 0)
217 errx(EXIT_FAILURE
, "DSDT signature mismatch");
219 if (sdt
->Length
> sb
.st_size
)
221 "corrupt DSDT: table size (%"PRIu32
" bytes), file size "
223 sdt
->Length
, sb
.st_size
);
225 if (acpi_checksum(sdt
, sdt
->Length
) != 0)
226 errx(EXIT_FAILURE
, "DSDT checksum mismatch");