xref: /netbsd-src/usr.sbin/acpitools/acpidump/acpi.c (revision b5677b36047b601b9addaaa494a58ceae82c2a6c)
1 /*	$NetBSD: acpi.c,v 1.4 2008/02/13 18:59:18 drochner Exp $	*/
2 
3 /*-
4  * Copyright (c) 1998 Doug Rabson
5  * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org>
6  * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  *	Id: acpi.c,v 1.4 2000/08/09 14:47:52 iwasaki Exp
31  *	$FreeBSD: src/usr.sbin/acpi/acpidump/acpi.c,v 1.4 2001/10/22 17:25:25 iwasaki Exp $
32  */
33 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: acpi.c,v 1.4 2008/02/13 18:59:18 drochner Exp $");
35 
36 #include <sys/param.h>
37 #include <sys/stat.h>
38 
39 #include <assert.h>
40 #include <err.h>
41 #include <fcntl.h>
42 #include <stdio.h>
43 #include <unistd.h>
44 #include <string.h>
45 
46 #include <acpi_common.h>
47 #include "acpidump.h"
48 
49 #include "aml/aml_env.h"
50 #include "aml/aml_common.h"
51 #include "aml/aml_parse.h"
52 #include "aml/aml_region.h"
53 
54 #define BEGIN_COMMENT	"/*\n"
55 #define END_COMMENT	" */\n"
56 
57 struct ACPIsdt	dsdt_header = {
58 	.signature = "DSDT",
59 	.rev = 1,
60 	.oemid = "OEMID",
61 	.oemtblid = "OEMTBLID",
62 	.oemrev = 0x12345678,
63 	.creator = "CRTR",
64 	.crerev = 0x12345678,
65 };
66 
67 static void
68 acpi_trim_string(char *s, size_t length)
69 {
70 
71 	/* Trim trailing spaces and NULLs */
72 	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
73 		s[length-- - 1] = '\0';
74 }
75 
76 static void
77 acpi_print_dsdt_definition(void)
78 {
79 	char	oemid[6 + 1];
80 	char	oemtblid[8 + 1];
81 
82 	acpi_trim_string((char *)dsdt_header.oemid, sizeof(oemid) - 1);
83 	acpi_trim_string((char *)dsdt_header.oemtblid, sizeof(oemtblid) - 1);
84 	(void)strlcpy(oemid, (const char *)dsdt_header.oemid, sizeof(oemid));
85 	(void)strlcpy(oemtblid, (const char *)dsdt_header.oemtblid,
86 	    sizeof(oemtblid));
87 
88 	printf("DefinitionBlock (\"%s\", \"%s\", 0x%x, \"%s\", \"%s\", 0x%x)",
89 	    "acpi_dst.aml", "DSDT", dsdt_header.rev, oemid, oemtblid,
90 	    dsdt_header.oemrev);
91 }
92 
93 static void
94 acpi_print_string(const char *s, size_t length)
95 {
96 	int	c;
97 
98 	/* Trim trailing spaces and NULLs */
99 	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
100 		length--;
101 
102 	while (length--) {
103 		c = *s++;
104 		putchar(c);
105 	}
106 }
107 
108 static void
109 acpi_handle_dsdt(struct ACPIsdt *dsdp)
110 {
111 	u_int8_t       *dp;
112 	u_int8_t       *end;
113 
114 	acpi_print_dsdt(dsdp);
115 	dp = (u_int8_t *)dsdp->body;
116 	end = (u_int8_t *)dsdp + dsdp->len;
117 
118 	acpi_dump_dsdt(dp, end);
119 }
120 
121 static void
122 acpi_handle_facp(struct FACPbody *facp)
123 {
124 	struct	ACPIsdt *dsdp;
125 
126 	acpi_print_facp(facp);
127 	dsdp = (struct ACPIsdt *) acpi_map_sdt(facp->dsdt_ptr);
128 	if (acpi_checksum(dsdp, dsdp->len))
129 		errx(1, "DSDT is corrupt");
130 	acpi_handle_dsdt(dsdp);
131 	aml_dump(dsdp);
132 }
133 
134 static void
135 init_namespace(void)
136 {
137 	struct	aml_environ env;
138 	struct	aml_name *newname;
139 
140 	aml_new_name_group((void *)AML_NAME_GROUP_OS_DEFINED);
141 	env.curname = aml_get_rootname();
142 	newname = aml_create_name(&env, (const unsigned char *)"\\_OS_");
143 	newname->property = aml_alloc_object(aml_t_string, NULL);
144 	newname->property->str.needfree = 0;
145 	newname->property->str.string = __UNCONST("Microsoft Windows NT");
146 
147 	newname = aml_create_name(&env, (const unsigned char *)"\\_OSI");
148 	newname->property = aml_alloc_object(aml_t_method, NULL);
149 	newname->property->meth.argnum = 1;
150 }
151 
152 /*
153  * Public interfaces
154  */
155 
156 void
157 acpi_dump_dsdt(u_int8_t *dp, u_int8_t *end)
158 {
159 	extern struct aml_environ	asl_env;
160 
161 	acpi_print_dsdt_definition();
162 
163 	/* 1st stage: parse only w/o printing */
164 	init_namespace();
165 	aml_new_name_group(dp);
166 	bzero(&asl_env, sizeof(asl_env));
167 
168 	asl_env.dp = dp;
169 	asl_env.end = end;
170 	asl_env.curname = aml_get_rootname();
171 
172 	aml_local_stack_push(aml_local_stack_create());
173 	aml_parse_objectlist(&asl_env, 0);
174 	aml_local_stack_delete(aml_local_stack_pop());
175 
176 	assert(asl_env.dp == asl_env.end);
177 	asl_env.dp = dp;
178 
179 	/* 2nd stage: dump whole object list */
180 	printf("\n{\n");
181 	asl_dump_objectlist(&dp, end, 0);
182 	printf("\n}\n");
183 	assert(dp == end);
184 }
185 void
186 acpi_print_sdt(struct ACPIsdt *sdp)
187 {
188 
189 	printf(BEGIN_COMMENT);
190 	acpi_print_string((const char *)sdp->signature, 4);
191 	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
192 	       sdp->len, sdp->rev, sdp->check);
193 	printf("\tOEMID=");
194 	acpi_print_string((const char *)sdp->oemid, 6);
195 	printf(", OEM Table ID=");
196 	acpi_print_string((const char *)sdp->oemtblid, 8);
197 	printf(", OEM Revision=0x%x,\n", sdp->oemrev);
198 	printf("\tCreator ID=");
199 	acpi_print_string((const char *)sdp->creator, 4);
200 	printf(", Creator Revision=0x%x\n", sdp->crerev);
201 	printf(END_COMMENT);
202 	if (!memcmp(sdp->signature, "DSDT", 4)) {
203 		memcpy(&dsdt_header, sdp, sizeof(dsdt_header));
204 	}
205 }
206 
207 void
208 acpi_print_rsdt(struct ACPIsdt *rsdp)
209 {
210 	int	i, entries;
211 
212 	acpi_print_sdt(rsdp);
213 	entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t);
214 	printf(BEGIN_COMMENT);
215 	printf("\tEntries={ ");
216 	for (i = 0; i < entries; i++) {
217 		if (i > 0)
218 			printf(", ");
219 		printf("0x%08x", rsdp->body[i]);
220 	}
221 	printf(" }\n");
222 	printf(END_COMMENT);
223 }
224 
225 void
226 acpi_print_facp(struct FACPbody *facp)
227 {
228 	char	sep;
229 
230 	printf(BEGIN_COMMENT);
231 	printf("\tDSDT=0x%x\n", facp->dsdt_ptr);
232 	printf("\tINT_MODEL=%s\n", facp->int_model ? "APIC" : "PIC");
233 	printf("\tSCI_INT=%d\n", facp->sci_int);
234 	printf("\tSMI_CMD=0x%x, ", facp->smi_cmd);
235 	printf("ACPI_ENABLE=0x%x, ", facp->acpi_enable);
236 	printf("ACPI_DISABLE=0x%x, ", facp->acpi_disable);
237 	printf("S4BIOS_REQ=0x%x\n", facp->s4biosreq);
238 	if (facp->pm1a_evt_blk)
239 		printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
240 		       facp->pm1a_evt_blk,
241 		       facp->pm1a_evt_blk + facp->pm1_evt_len - 1);
242 	if (facp->pm1b_evt_blk)
243 		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
244 		       facp->pm1b_evt_blk,
245 		       facp->pm1b_evt_blk + facp->pm1_evt_len - 1);
246 	if (facp->pm1a_cnt_blk)
247 		printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
248 		       facp->pm1a_cnt_blk,
249 		       facp->pm1a_cnt_blk + facp->pm1_cnt_len - 1);
250 	if (facp->pm1b_cnt_blk)
251 		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
252 		       facp->pm1b_cnt_blk,
253 		       facp->pm1b_cnt_blk + facp->pm1_cnt_len - 1);
254 	if (facp->pm2_cnt_blk)
255 		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
256 		       facp->pm2_cnt_blk,
257 		       facp->pm2_cnt_blk + facp->pm2_cnt_len - 1);
258 	if (facp->pm_tmr_blk)
259 		printf("\tPM2_TMR_BLK=0x%x-0x%x\n",
260 		       facp->pm_tmr_blk,
261 		       facp->pm_tmr_blk + facp->pm_tmr_len - 1);
262 	if (facp->gpe0_blk)
263 		printf("\tPM2_GPE0_BLK=0x%x-0x%x\n",
264 		       facp->gpe0_blk,
265 		       facp->gpe0_blk + facp->gpe0_len - 1);
266 	if (facp->gpe1_blk)
267 		printf("\tPM2_GPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
268 		       facp->gpe1_blk,
269 		       facp->gpe1_blk + facp->gpe1_len - 1,
270 		       facp->gpe1_base);
271 	printf("\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n",
272 	       facp->p_lvl2_lat, facp->p_lvl3_lat);
273 	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
274 	       facp->flush_size, facp->flush_stride);
275 	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
276 	       facp->duty_off, facp->duty_width);
277 	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
278 	       facp->day_alrm, facp->mon_alrm, facp->century);
279 	printf("\tFlags=");
280 	sep = '{';
281 
282 #define PRINTFLAG(xx) do {					\
283 	if (facp->flags & ACPI_FACP_FLAG_## xx) {		\
284 		printf("%c%s", sep, #xx); sep = ',';		\
285 	}							\
286 } while (0)
287 
288 	PRINTFLAG(WBINVD);
289 	PRINTFLAG(WBINVD_FLUSH);
290 	PRINTFLAG(PROC_C1);
291 	PRINTFLAG(P_LVL2_UP);
292 	PRINTFLAG(PWR_BUTTON);
293 	PRINTFLAG(SLP_BUTTON);
294 	PRINTFLAG(FIX_RTC);
295 	PRINTFLAG(RTC_S4);
296 	PRINTFLAG(TMR_VAL_EXT);
297 	PRINTFLAG(DCK_CAP);
298 
299 #undef PRINTFLAG
300 
301 	printf("}\n");
302 	printf(END_COMMENT);
303 }
304 
305 void
306 acpi_print_dsdt(struct ACPIsdt *dsdp)
307 {
308 
309 	acpi_print_sdt(dsdp);
310 }
311 
312 int
313 acpi_checksum(void *p, size_t length)
314 {
315 	u_int8_t	*bp;
316 	u_int8_t	sum;
317 
318 	bp = p;
319 	sum = 0;
320 	while (length--)
321 		sum += *bp++;
322 
323 	return (sum);
324 }
325 
326 struct ACPIsdt *
327 acpi_map_sdt(vm_offset_t pa)
328 {
329 	struct	ACPIsdt *sp;
330 
331 	sp = acpi_map_physical(pa, sizeof(struct ACPIsdt));
332 	sp = acpi_map_physical(pa, sp->len);
333 	return (sp);
334 }
335 
336 void
337 acpi_print_rsd_ptr(struct ACPIrsdp *rp)
338 {
339 
340 	printf(BEGIN_COMMENT);
341 	printf("RSD PTR: Checksum=%d, OEMID=", rp->sum);
342 	acpi_print_string((const char *)rp->oem, 6);
343 	printf(", RsdtAddress=0x%08x\n", rp->addr);
344 	printf(END_COMMENT);
345 }
346 
347 void
348 acpi_handle_rsdt(struct ACPIsdt *rsdp)
349 {
350 	int	i;
351 	int	entries;
352 	struct	ACPIsdt *sdp;
353 
354 	entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t);
355 	acpi_print_rsdt(rsdp);
356 	for (i = 0; i < entries; i++) {
357 		sdp = (struct ACPIsdt *) acpi_map_sdt(rsdp->body[i]);
358 		if (acpi_checksum(sdp, sdp->len)) {
359 			warnx("RSDT entry %d: bad checksum", i);
360 			continue;
361 		}
362 		if (!memcmp(sdp->signature, "FACP", 4)) {
363 			acpi_handle_facp((struct FACPbody *) sdp->body);
364 		} else {
365 			acpi_print_sdt(sdp);
366 		}
367 	}
368 }
369 
370 /*
371  *	Dummy functions
372  */
373 
374 void
375 aml_dbgr(struct aml_environ *env1, struct aml_environ *env2)
376 {
377 	/* do nothing */
378 }
379 
380 int
381 aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset,
382     u_int32_t *valuep)
383 {
384 	return (0);
385 }
386 
387 int
388 aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset,
389     u_int32_t value)
390 {
391 	return (0);
392 }
393 
394 u_int32_t
395 aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value)
396 {
397 	return (0);
398 }
399 
400 u_int32_t
401 aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value)
402 {
403 	return (0);
404 }
405 
406 int
407 aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value,
408     struct aml_region_handle *h)
409 {
410 	return (0);
411 }
412 
413 u_int32_t
414 aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags,
415     u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
416 {
417 	return (0);
418 }
419 
420 int
421 aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags,
422     u_int32_t value, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
423 {
424 	return (0);
425 }
426 
427 int
428 aml_region_write_from_buffer(struct aml_environ *env, int regtype,
429     u_int32_t flags, u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset,
430     u_int32_t bitlen)
431 {
432 	return (0);
433 }
434 
435 int
436 aml_region_bcopy(struct aml_environ *env, int regtype, u_int32_t flags,
437     u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen,
438     u_int32_t dflags, u_int32_t daddr,
439     u_int32_t dbitoffset, u_int32_t dbitlen)
440 {
441 	return (0);
442 }
443 
444 int
445 aml_region_read_into_buffer(struct aml_environ *env, int regtype,
446     u_int32_t flags, u_int32_t addr, u_int32_t bitoffset,
447     u_int32_t bitlen, u_int8_t *buffer)
448 {
449 	return (0);
450 }
451