acpi.c revision 1.3 1 /* $NetBSD: acpi.c,v 1.3 2008/02/13 11:47:36 joerg 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.3 2008/02/13 11:47:36 joerg 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\n");
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 errx(1, "RSDT entry %d is corrupt\n", i);
360 if (!memcmp(sdp->signature, "FACP", 4)) {
361 acpi_handle_facp((struct FACPbody *) sdp->body);
362 } else {
363 acpi_print_sdt(sdp);
364 }
365 }
366 }
367
368 /*
369 * Dummy functions
370 */
371
372 void
373 aml_dbgr(struct aml_environ *env1, struct aml_environ *env2)
374 {
375 /* do nothing */
376 }
377
378 int
379 aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset,
380 u_int32_t *valuep)
381 {
382 return (0);
383 }
384
385 int
386 aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset,
387 u_int32_t value)
388 {
389 return (0);
390 }
391
392 u_int32_t
393 aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value)
394 {
395 return (0);
396 }
397
398 u_int32_t
399 aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value)
400 {
401 return (0);
402 }
403
404 int
405 aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value,
406 struct aml_region_handle *h)
407 {
408 return (0);
409 }
410
411 u_int32_t
412 aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags,
413 u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
414 {
415 return (0);
416 }
417
418 int
419 aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags,
420 u_int32_t value, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen)
421 {
422 return (0);
423 }
424
425 int
426 aml_region_write_from_buffer(struct aml_environ *env, int regtype,
427 u_int32_t flags, u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset,
428 u_int32_t bitlen)
429 {
430 return (0);
431 }
432
433 int
434 aml_region_bcopy(struct aml_environ *env, int regtype, u_int32_t flags,
435 u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen,
436 u_int32_t dflags, u_int32_t daddr,
437 u_int32_t dbitoffset, u_int32_t dbitlen)
438 {
439 return (0);
440 }
441
442 int
443 aml_region_read_into_buffer(struct aml_environ *env, int regtype,
444 u_int32_t flags, u_int32_t addr, u_int32_t bitoffset,
445 u_int32_t bitlen, u_int8_t *buffer)
446 {
447 return (0);
448 }
449