acpi.c revision 1.4 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 (at) FreeBSD.org>
6 * Copyright (c) 2008 Joerg Sonnenberger <joerg (at) 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