acpi.c revision 85323
1/*-
2 * Copyright (c) 1998 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.c,v 1.4 2000/08/09 14:47:52 iwasaki Exp $
28 *	$FreeBSD: head/usr.sbin/acpi/acpidump/acpi.c 85323 2001-10-22 17:25:32Z iwasaki $
29 */
30
31#include <sys/param.h>
32#include <sys/stat.h>
33
34#include <assert.h>
35#include <err.h>
36#include <fcntl.h>
37#include <stdio.h>
38#include <unistd.h>
39
40#include "acpidump.h"
41
42#include "aml/aml_env.h"
43#include "aml/aml_common.h"
44
45#define BEGIN_COMMENT	"/*\n"
46#define END_COMMENT	" */\n"
47
48struct ACPIsdt	dsdt_header = {
49	"DSDT", 0, 1, 0, "OEMID", "OEMTBLID", 0x12345678, "CRTR", 0x12345678
50};
51
52static void
53acpi_trim_string(char *s, size_t length)
54{
55
56	/* Trim trailing spaces and NULLs */
57	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
58		s[length-- - 1] = '\0';
59}
60
61static void
62acpi_print_dsdt_definition(void)
63{
64	char	oemid[6 + 1];
65	char	oemtblid[8 + 1];
66
67	acpi_trim_string(dsdt_header.oemid, 6);
68	acpi_trim_string(dsdt_header.oemtblid, 8);
69	strncpy(oemid, dsdt_header.oemid, 6);
70	oemid[6] = '\0';
71	strncpy(oemtblid, dsdt_header.oemtblid, 8);
72	oemtblid[8] = '\0';
73
74	printf("DefinitionBlock (
75    \"acpi_dsdt.aml\",	//Output filename
76    \"DSDT\",		//Signature
77    0x%x,		//DSDT Revision
78    \"%s\",		//OEMID
79    \"%s\",		//TABLE ID
80    0x%x		//OEM Revision\n)\n",
81	dsdt_header.rev, oemid, oemtblid, dsdt_header.oemrev);
82}
83
84static void
85acpi_print_string(char *s, size_t length)
86{
87	int	c;
88
89	/* Trim trailing spaces and NULLs */
90	while (length > 0 && (s[length - 1] == ' ' || s[length - 1] == '\0'))
91		length--;
92
93	while (length--) {
94		c = *s++;
95		putchar(c);
96	}
97}
98
99static void
100acpi_handle_dsdt(struct ACPIsdt *dsdp)
101{
102	u_int8_t       *dp;
103	u_int8_t       *end;
104
105	acpi_print_dsdt(dsdp);
106	dp = (u_int8_t *)dsdp->body;
107	end = (u_int8_t *)dsdp + dsdp->len;
108
109	acpi_dump_dsdt(dp, end);
110}
111
112static void
113acpi_handle_facp(struct FACPbody *facp)
114{
115	struct	ACPIsdt *dsdp;
116
117	acpi_print_facp(facp);
118	dsdp = (struct ACPIsdt *) acpi_map_sdt(facp->dsdt_ptr);
119	if (acpi_checksum(dsdp, dsdp->len))
120		errx(1, "DSDT is corrupt\n");
121	acpi_handle_dsdt(dsdp);
122	aml_dump(dsdp);
123}
124
125static void
126init_namespace()
127{
128	struct	aml_environ env;
129	struct	aml_name *newname;
130
131	aml_new_name_group(AML_NAME_GROUP_OS_DEFINED);
132	env.curname = aml_get_rootname();
133	newname = aml_create_name(&env, "\\_OS_");
134	newname->property = aml_alloc_object(aml_t_string, NULL);
135	newname->property->str.needfree = 0;
136	newname->property->str.string = "Microsoft Windows NT";
137}
138
139/*
140 * Public interfaces
141 */
142
143void
144acpi_dump_dsdt(u_int8_t *dp, u_int8_t *end)
145{
146	extern struct aml_environ	asl_env;
147
148	acpi_print_dsdt_definition();
149
150	/* 1st stage: parse only w/o printing */
151	init_namespace();
152	aml_new_name_group((int)dp);
153	bzero(&asl_env, sizeof(asl_env));
154
155	asl_env.dp = dp;
156	asl_env.end = end;
157	asl_env.curname = aml_get_rootname();
158
159	aml_local_stack_push(aml_local_stack_create());
160	aml_parse_objectlist(&asl_env, 0);
161	aml_local_stack_delete(aml_local_stack_pop());
162
163	assert(asl_env.dp == asl_env.end);
164	asl_env.dp = dp;
165
166	/* 2nd stage: dump whole object list */
167	printf("\n{\n");
168	asl_dump_objectlist(&dp, end, 0);
169	printf("\n}\n");
170	assert(dp == end);
171}
172void
173acpi_print_sdt(struct ACPIsdt *sdp)
174{
175
176	printf(BEGIN_COMMENT);
177	acpi_print_string(sdp->signature, 4);
178	printf(": Length=%d, Revision=%d, Checksum=%d,\n",
179	       sdp->len, sdp->rev, sdp->check);
180	printf("\tOEMID=");
181	acpi_print_string(sdp->oemid, 6);
182	printf(", OEM Table ID=");
183	acpi_print_string(sdp->oemtblid, 8);
184	printf(", OEM Revision=0x%x,\n", sdp->oemrev);
185	printf("\tCreator ID=");
186	acpi_print_string(sdp->creator, 4);
187	printf(", Creator Revision=0x%x\n", sdp->crerev);
188	printf(END_COMMENT);
189	if (!memcmp(sdp->signature, "DSDT", 4)) {
190		memcpy(&dsdt_header, sdp, sizeof(dsdt_header));
191	}
192}
193
194void
195acpi_print_rsdt(struct ACPIsdt *rsdp)
196{
197	int	i, entries;
198
199	acpi_print_sdt(rsdp);
200	entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t);
201	printf(BEGIN_COMMENT);
202	printf("\tEntries={ ");
203	for (i = 0; i < entries; i++) {
204		if (i > 0)
205			printf(", ");
206		printf("0x%08x", rsdp->body[i]);
207	}
208	printf(" }\n");
209	printf(END_COMMENT);
210}
211
212void
213acpi_print_facp(struct FACPbody *facp)
214{
215	char	sep;
216
217	printf(BEGIN_COMMENT);
218	printf("\tDSDT=0x%x\n", facp->dsdt_ptr);
219	printf("\tINT_MODEL=%s\n", facp->int_model ? "APIC" : "PIC");
220	printf("\tSCI_INT=%d\n", facp->sci_int);
221	printf("\tSMI_CMD=0x%x, ", facp->smi_cmd);
222	printf("ACPI_ENABLE=0x%x, ", facp->acpi_enable);
223	printf("ACPI_DISABLE=0x%x, ", facp->acpi_disable);
224	printf("S4BIOS_REQ=0x%x\n", facp->s4biosreq);
225	if (facp->pm1a_evt_blk)
226		printf("\tPM1a_EVT_BLK=0x%x-0x%x\n",
227		       facp->pm1a_evt_blk,
228		       facp->pm1a_evt_blk + facp->pm1_evt_len - 1);
229	if (facp->pm1b_evt_blk)
230		printf("\tPM1b_EVT_BLK=0x%x-0x%x\n",
231		       facp->pm1b_evt_blk,
232		       facp->pm1b_evt_blk + facp->pm1_evt_len - 1);
233	if (facp->pm1a_cnt_blk)
234		printf("\tPM1a_CNT_BLK=0x%x-0x%x\n",
235		       facp->pm1a_cnt_blk,
236		       facp->pm1a_cnt_blk + facp->pm1_cnt_len - 1);
237	if (facp->pm1b_cnt_blk)
238		printf("\tPM1b_CNT_BLK=0x%x-0x%x\n",
239		       facp->pm1b_cnt_blk,
240		       facp->pm1b_cnt_blk + facp->pm1_cnt_len - 1);
241	if (facp->pm2_cnt_blk)
242		printf("\tPM2_CNT_BLK=0x%x-0x%x\n",
243		       facp->pm2_cnt_blk,
244		       facp->pm2_cnt_blk + facp->pm2_cnt_len - 1);
245	if (facp->pm_tmr_blk)
246		printf("\tPM2_TMR_BLK=0x%x-0x%x\n",
247		       facp->pm_tmr_blk,
248		       facp->pm_tmr_blk + facp->pm_tmr_len - 1);
249	if (facp->gpe0_blk)
250		printf("\tPM2_GPE0_BLK=0x%x-0x%x\n",
251		       facp->gpe0_blk,
252		       facp->gpe0_blk + facp->gpe0_len - 1);
253	if (facp->gpe1_blk)
254		printf("\tPM2_GPE1_BLK=0x%x-0x%x, GPE1_BASE=%d\n",
255		       facp->gpe1_blk,
256		       facp->gpe1_blk + facp->gpe1_len - 1,
257		       facp->gpe1_base);
258	printf("\tP_LVL2_LAT=%dms, P_LVL3_LAT=%dms\n",
259	       facp->p_lvl2_lat, facp->p_lvl3_lat);
260	printf("\tFLUSH_SIZE=%d, FLUSH_STRIDE=%d\n",
261	       facp->flush_size, facp->flush_stride);
262	printf("\tDUTY_OFFSET=%d, DUTY_WIDTH=%d\n",
263	       facp->duty_off, facp->duty_width);
264	printf("\tDAY_ALRM=%d, MON_ALRM=%d, CENTURY=%d\n",
265	       facp->day_alrm, facp->mon_alrm, facp->century);
266	printf("\tFlags=");
267	sep = '{';
268
269#define PRINTFLAG(xx) do {					\
270	if (facp->flags & ACPI_FACP_FLAG_## xx) {		\
271		printf("%c%s", sep, #xx); sep = ',';		\
272	}							\
273} while (0)
274
275	PRINTFLAG(WBINVD);
276	PRINTFLAG(WBINVD_FLUSH);
277	PRINTFLAG(PROC_C1);
278	PRINTFLAG(P_LVL2_UP);
279	PRINTFLAG(PWR_BUTTON);
280	PRINTFLAG(SLP_BUTTON);
281	PRINTFLAG(FIX_RTC);
282	PRINTFLAG(RTC_S4);
283	PRINTFLAG(TMR_VAL_EXT);
284	PRINTFLAG(DCK_CAP);
285
286#undef PRINTFLAG
287
288	printf("}\n");
289	printf(END_COMMENT);
290}
291
292void
293acpi_print_dsdt(struct ACPIsdt *dsdp)
294{
295
296	acpi_print_sdt(dsdp);
297}
298
299int
300acpi_checksum(void *p, size_t length)
301{
302	u_int8_t	*bp;
303	u_int8_t	sum;
304
305	bp = p;
306	sum = 0;
307	while (length--)
308		sum += *bp++;
309
310	return (sum);
311}
312
313struct ACPIsdt *
314acpi_map_sdt(vm_offset_t pa)
315{
316	struct	ACPIsdt *sp;
317
318	sp = acpi_map_physical(pa, sizeof(struct ACPIsdt));
319	sp = acpi_map_physical(pa, sp->len);
320	return (sp);
321}
322
323void
324acpi_print_rsd_ptr(struct ACPIrsdp *rp)
325{
326
327	printf(BEGIN_COMMENT);
328	printf("RSD PTR: Checksum=%d, OEMID=", rp->sum);
329	acpi_print_string(rp->oem, 6);
330	printf(", RsdtAddress=0x%08x\n", rp->addr);
331	printf(END_COMMENT);
332}
333
334void
335acpi_handle_rsdt(struct ACPIsdt *rsdp)
336{
337	int	i;
338	int	entries;
339	struct	ACPIsdt *sdp;
340
341	entries = (rsdp->len - SIZEOF_SDT_HDR) / sizeof(u_int32_t);
342	acpi_print_rsdt(rsdp);
343	for (i = 0; i < entries; i++) {
344		sdp = (struct ACPIsdt *) acpi_map_sdt(rsdp->body[i]);
345		if (acpi_checksum(sdp, sdp->len))
346			errx(1, "RSDT entry %d is corrupt\n", i);
347		if (!memcmp(sdp->signature, "FACP", 4)) {
348			acpi_handle_facp((struct FACPbody *) sdp->body);
349		} else {
350			acpi_print_sdt(sdp);
351		}
352	}
353}
354
355/*
356 *	Dummy functions
357 */
358
359void
360aml_dbgr(struct aml_environ *env1, struct aml_environ *env2)
361{
362	/* do nothing */
363}
364
365int
366aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset,
367    u_int32_t *valuep)
368{
369	return (0);
370}
371
372int
373aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset,
374    u_int32_t value)
375{
376	return (0);
377}
378
379u_int32_t
380aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value)
381{
382	return (0);
383}
384
385u_int32_t
386aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value)
387{
388	return (0);
389}
390
391int
392aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value,
393    struct aml_region_handle *h)
394{
395	return (0);
396}
397
398u_int32_t
399aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags,
400    u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
401{
402	return (0);
403}
404
405int
406aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags,
407    u_int32_t value, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
408{
409	return (0);
410}
411
412int
413aml_region_write_from_buffer(struct aml_environ *env, int regtype,
414    u_int32_t flags, u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset,
415    u_int32_t bitlen)
416{
417	return (0);
418}
419
420int
421aml_region_bcopy(struct aml_environ *env, int regtype, u_int32_t flags,
422    u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen,
423    u_int32_t dflags, u_int32_t daddr,
424    u_int32_t dbitoffset, u_int32_t dbitlen)
425{
426	return (0);
427}
428
429int
430aml_region_read_into_buffer(struct aml_environ *env, int regtype,
431    u_int32_t flags, u_int32_t addr, u_int32_t bitoffset,
432    u_int32_t bitlen, u_int8_t *buffer)
433{
434	return (0);
435}
436
437