Annotation of sys/dev/acpi/acpidebug.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: acpidebug.c,v 1.15 2007/02/06 18:56:31 jordan Exp $ */
2: /*
3: * Copyright (c) 2006 Marco Peereboom <marco@openbsd.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: #include <machine/db_machdep.h>
19: #include <ddb/db_command.h>
20: #include <ddb/db_output.h>
21: #include <ddb/db_extern.h>
22: #include <ddb/db_lex.h>
23:
24: #include <machine/bus.h>
25: #include <sys/malloc.h>
26:
27: #include <dev/acpi/acpireg.h>
28: #include <dev/acpi/acpivar.h>
29: #include <dev/acpi/amltypes.h>
30: #include <dev/acpi/acpidebug.h>
31: #include <dev/acpi/dsdt.h>
32:
33: void db_aml_disline(uint8_t *, int, const char *, ...);
34: void db_aml_disint(struct aml_scope *, int, int);
35: uint8_t *db_aml_disasm(struct aml_node *, uint8_t *, uint8_t *, int, int);
36:
37: extern int aml_pc(uint8_t *);
38: extern struct aml_scope *aml_pushscope(struct aml_scope *, uint8_t *, uint8_t *, struct aml_node *);
39: extern struct aml_scope *aml_popscope(struct aml_scope *);
40: extern uint8_t *aml_parsename(struct aml_scope *);
41: extern uint8_t *aml_parseend(struct aml_scope *);
42: extern int aml_parselength(struct aml_scope *);
43: extern int aml_parseopcode(struct aml_scope *);
44:
45: extern const char *aml_mnem(int opcode, uint8_t *);
46: extern const char *aml_args(int opcode);
47: extern const char *aml_getname(uint8_t *);
48: extern const char *aml_nodename(struct aml_node *);
49:
50: const char *db_aml_objtype(struct aml_value *);
51: const char *db_opregion(int);
52: int db_parse_name(void);
53: void db_aml_dump(int, u_int8_t *);
54: void db_aml_showvalue(struct aml_value *);
55: void db_aml_walktree(struct aml_node *);
56:
57: const char *db_aml_fieldacc(int);
58: const char *db_aml_fieldlock(int);
59: const char *db_aml_fieldupdate(int);
60:
61: extern struct aml_node aml_root;
62:
63: /* name of scope for lexer */
64: char scope[80];
65:
66: const char *
67: db_opregion(int id)
68: {
69: switch (id) {
70: case 0:
71: return "SystemMemory";
72: case 1:
73: return "SystemIO";
74: case 2:
75: return "PCIConfig";
76: case 3:
77: return "Embedded";
78: case 4:
79: return "SMBus";
80: case 5:
81: return "CMOS";
82: case 6:
83: return "PCIBAR";
84: }
85: return "";
86: }
87: void
88: db_aml_dump(int len, u_int8_t *buf)
89: {
90: int idx;
91:
92: db_printf("{ ");
93: for (idx = 0; idx < len; idx++)
94: db_printf("%s0x%.2x", idx ? ", " : "", buf[idx]);
95: db_printf(" }\n");
96: }
97:
98: void
99: db_aml_showvalue(struct aml_value *value)
100: {
101: int idx;
102:
103: if (value == NULL)
104: return;
105:
106: if (value->node)
107: db_printf("[%s] ", aml_nodename(value->node));
108:
109: switch (value->type & ~AML_STATIC) {
110: case AML_OBJTYPE_OBJREF:
111: db_printf("refof: %x {\n", value->v_objref.index);
112: db_aml_showvalue(value->v_objref.ref);
113: db_printf("}\n");
114: break;
115: case AML_OBJTYPE_NAMEREF:
116: db_printf("nameref: %s\n", value->v_nameref);
117: break;
118: case AML_OBJTYPE_INTEGER:
119: db_printf("integer: %llx %s\n", value->v_integer,
120: (value->type & AML_STATIC) ? "(static)" : "");
121: break;
122: case AML_OBJTYPE_STRING:
123: db_printf("string: %s\n", value->v_string);
124: break;
125: case AML_OBJTYPE_PACKAGE:
126: db_printf("package: %d {\n", value->length);
127: for (idx = 0; idx < value->length; idx++)
128: db_aml_showvalue(value->v_package[idx]);
129: db_printf("}\n");
130: break;
131: case AML_OBJTYPE_BUFFER:
132: db_printf("buffer: %d ", value->length);
133: db_aml_dump(value->length, value->v_buffer);
134: break;
135: case AML_OBJTYPE_DEBUGOBJ:
136: db_printf("debug");
137: break;
138: case AML_OBJTYPE_MUTEX:
139: db_printf("mutex : %llx\n", value->v_integer);
140: break;
141: case AML_OBJTYPE_DEVICE:
142: db_printf("device\n");
143: break;
144: case AML_OBJTYPE_EVENT:
145: db_printf("event\n");
146: break;
147: case AML_OBJTYPE_PROCESSOR:
148: db_printf("cpu: %x,%x,%x\n",
149: value->v_processor.proc_id,
150: value->v_processor.proc_addr,
151: value->v_processor.proc_len);
152: break;
153: case AML_OBJTYPE_METHOD:
154: db_printf("method: args=%d, serialized=%d, synclevel=%d\n",
155: AML_METHOD_ARGCOUNT(value->v_method.flags),
156: AML_METHOD_SERIALIZED(value->v_method.flags),
157: AML_METHOD_SYNCLEVEL(value->v_method.flags));
158: break;
159: case AML_OBJTYPE_FIELDUNIT:
160: db_printf("%s: access=%x,lock=%x,update=%x pos=%.4x "
161: "len=%.4x\n",
162: aml_mnem(value->v_field.type, NULL),
163: AML_FIELD_ACCESS(value->v_field.flags),
164: AML_FIELD_LOCK(value->v_field.flags),
165: AML_FIELD_UPDATE(value->v_field.flags),
166: value->v_field.bitpos,
167: value->v_field.bitlen);
168:
169: db_aml_showvalue(value->v_field.ref1);
170: db_aml_showvalue(value->v_field.ref2);
171: break;
172: case AML_OBJTYPE_BUFFERFIELD:
173: db_printf("%s: pos=%.4x len=%.4x ",
174: aml_mnem(value->v_field.type, NULL),
175: value->v_field.bitpos,
176: value->v_field.bitlen);
177:
178: db_aml_dump(aml_bytelen(value->v_field.bitlen),
179: value->v_field.ref1->v_buffer +
180: aml_bytepos(value->v_field.bitpos));
181:
182: db_aml_showvalue(value->v_field.ref1);
183: break;
184: case AML_OBJTYPE_OPREGION:
185: db_printf("opregion: %s,0x%llx,0x%x\n",
186: db_opregion(value->v_opregion.iospace),
187: value->v_opregion.iobase,
188: value->v_opregion.iolen);
189: break;
190: default:
191: db_printf("unknown: %d\n", value->type);
192: break;
193: }
194: }
195:
196: const char *
197: db_aml_objtype(struct aml_value *val)
198: {
199: if (val == NULL)
200: return "nil";
201:
202: switch (val->type) {
203: case AML_OBJTYPE_INTEGER+AML_STATIC:
204: return "staticint";
205: case AML_OBJTYPE_INTEGER:
206: return "integer";
207: case AML_OBJTYPE_STRING:
208: return "string";
209: case AML_OBJTYPE_BUFFER:
210: return "buffer";
211: case AML_OBJTYPE_PACKAGE:
212: return "package";
213: case AML_OBJTYPE_DEVICE:
214: return "device";
215: case AML_OBJTYPE_EVENT:
216: return "event";
217: case AML_OBJTYPE_METHOD:
218: return "method";
219: case AML_OBJTYPE_MUTEX:
220: return "mutex";
221: case AML_OBJTYPE_OPREGION:
222: return "opregion";
223: case AML_OBJTYPE_POWERRSRC:
224: return "powerrsrc";
225: case AML_OBJTYPE_PROCESSOR:
226: return "processor";
227: case AML_OBJTYPE_THERMZONE:
228: return "thermzone";
229: case AML_OBJTYPE_DDBHANDLE:
230: return "ddbhandle";
231: case AML_OBJTYPE_DEBUGOBJ:
232: return "debugobj";
233: case AML_OBJTYPE_NAMEREF:
234: return "nameref";
235: case AML_OBJTYPE_OBJREF:
236: return "refof";
237: case AML_OBJTYPE_FIELDUNIT:
238: case AML_OBJTYPE_BUFFERFIELD:
239: return aml_mnem(val->v_field.type, NULL);
240: }
241:
242: return ("");
243: }
244:
245: void
246: db_aml_walktree(struct aml_node *node)
247: {
248: while (node) {
249: db_aml_showvalue(node->value);
250: db_aml_walktree(node->child);
251:
252: node = node->sibling;
253: }
254: }
255:
256: int
257: db_parse_name(void)
258: {
259: int t, rv = 1;
260:
261: memset(scope, 0, sizeof scope);
262: do {
263: t = db_read_token();
264: if (t == tIDENT) {
265: if (strlcat(scope, db_tok_string, sizeof scope) >=
266: sizeof scope) {
267: printf("Input too long\n");
268: goto error;
269: }
270: t = db_read_token();
271: if (t == tDOT)
272: if (strlcat(scope, ".", sizeof scope) >=
273: sizeof scope) {
274: printf("Input too long 2\n");
275: goto error;
276: }
277: }
278: } while (t != tEOL);
279:
280: if (!strlen(scope)) {
281: db_printf("Invalid input\n");
282: goto error;
283: }
284:
285: rv = 0;
286: error:
287: /* get rid of the rest of input */
288: db_flush_lex();
289: return (rv);
290: }
291:
292: /* ddb interface */
293: void
294: db_acpi_showval(db_expr_t addr, int haddr, db_expr_t count, char *modif)
295: {
296: struct aml_node *node;
297:
298: if (db_parse_name())
299: return;
300:
301: node = aml_searchname(&aml_root, scope);
302: if (node)
303: db_aml_showvalue(node->value);
304: else
305: db_printf("Not a valid value\n");
306: }
307:
308: void
309: db_acpi_disasm(db_expr_t addr, int haddr, db_expr_t count, char *modif)
310: {
311: struct aml_node *node;
312:
313: if (db_parse_name())
314: return;
315:
316: node = aml_searchname(&aml_root, scope);
317: if (node && node->value && node->value->type == AML_OBJTYPE_METHOD) {
318: db_aml_disasm(node, node->value->v_method.start,
319: node->value->v_method.end, -1, 0);
320: } else
321: db_printf("Not a valid method\n");
322: }
323:
324: void
325: db_acpi_tree(db_expr_t addr, int haddr, db_expr_t count, char *modif)
326: {
327: db_aml_walktree(aml_root.child);
328: }
329:
330: void
331: db_acpi_trace(db_expr_t addr, int haddr, db_expr_t count, char *modif)
332: {
333: struct aml_scope *root;
334: int idx;
335: extern struct aml_scope *aml_lastscope;
336:
337: for (root=aml_lastscope; root && root->pos; root=root->parent) {
338: db_printf("%.4x Called: %s\n", aml_pc(root->pos),
339: aml_nodename(root->node));
340: for (idx = 0; idx<root->nargs; idx++) {
341: db_printf(" arg%d: ", idx);
342: db_aml_showvalue(&root->args[idx]);
343: }
344: for (idx = 0; root->locals && idx < AML_MAX_LOCAL; idx++) {
345: if (root->locals[idx].type) {
346: db_printf(" local%d: ", idx);
347: db_aml_showvalue(&root->locals[idx]);
348: }
349: }
350: }
351: }
352:
353: void
354: db_aml_disline(uint8_t *pos, int depth, const char *fmt, ...)
355: {
356: va_list ap;
357: char line[128];
358:
359: db_printf("%.6x: ", aml_pc(pos));
360: while (depth--)
361: db_printf(" ");
362:
363: va_start(ap, fmt);
364: vsnprintf(line, sizeof(line), fmt, ap);
365: db_printf(line);
366: va_end(ap);
367: }
368:
369: void
370: db_aml_disint(struct aml_scope *scope, int opcode, int depth)
371: {
372: switch (opcode) {
373: case AML_ANYINT:
374: db_aml_disasm(scope->node, scope->pos, scope->end, -1, depth);
375: break;
376: case AMLOP_BYTEPREFIX:
377: db_aml_disline(scope->pos, depth, "0x%.2x\n",
378: *(uint8_t *)(scope->pos));
379: scope->pos += 1;
380: break;
381: case AMLOP_WORDPREFIX:
382: db_aml_disline(scope->pos, depth, "0x%.4x\n",
383: *(uint16_t *)(scope->pos));
384: scope->pos += 2;
385: break;
386: case AMLOP_DWORDPREFIX:
387: db_aml_disline(scope->pos, depth, "0x%.8x\n",
388: *(uint32_t *)(scope->pos));
389: scope->pos += 4;
390: break;
391: case AMLOP_QWORDPREFIX:
392: db_aml_disline(scope->pos, depth, "0x%.4llx\n",
393: *(uint64_t *)(scope->pos));
394: scope->pos += 8;
395: break;
396: }
397: }
398:
399: uint8_t *
400: db_aml_disasm(struct aml_node *root, uint8_t *start, uint8_t *end,
401: int count, int depth)
402: {
403: int idx, opcode, len, off=0;
404: struct aml_scope *scope;
405: uint8_t *name, *pos;
406: const char *mnem, *args;
407: struct aml_node *node;
408: char *tmpstr;
409:
410: if (start == end)
411: return end;
412:
413: scope = aml_pushscope(NULL, start, end, root);
414: while (scope->pos < scope->end && count--) {
415: pos = scope->pos;
416: start = scope->pos;
417: opcode = aml_parseopcode(scope);
418:
419: mnem = aml_mnem(opcode, scope->pos);
420: args = aml_args(opcode);
421:
422: if (*args == 'p') {
423: end = aml_parseend(scope);
424: args++;
425: }
426: node = scope->node;
427: if (*args == 'N') {
428: name = aml_parsename(scope);
429: node = aml_searchname(scope->node, name);
430: db_aml_disline(pos, depth, "%s %s (%s)\n",
431: mnem, aml_getname(name), aml_nodename(node));
432: args++;
433: } else if (mnem[0] != '.') {
434: db_aml_disline(pos, depth, "%s\n", mnem);
435: }
436: while (*args) {
437: pos = scope->pos;
438: switch (*args) {
439: case 'k':
440: case 'c':
441: case 'D':
442: case 'L':
443: case 'A':
444: break;
445: case 'i':
446: case 't':
447: case 'S':
448: case 'r':
449: scope->pos = db_aml_disasm(node, scope->pos,
450: scope->end, 1, depth+1);
451: break;
452: case 'T':
453: case 'M':
454: scope->pos = db_aml_disasm(node, scope->pos,
455: end, -1, depth+1);
456: break;
457: case 'I':
458: /* Special case: if */
459: scope->pos = db_aml_disasm(node, scope->pos,
460: end, -1, depth+1);
461: if (scope->pos >= scope->end)
462: break;
463: if (*scope->pos == AMLOP_ELSE) {
464: ++scope->pos;
465: end = aml_parseend(scope);
466: db_aml_disline(scope->pos, depth, "Else\n");
467: scope->pos = db_aml_disasm(node, scope->pos,
468: end, -1, depth+1);
469: }
470: break;
471: case 'N':
472: name = aml_parsename(scope);
473: db_aml_disline(pos, depth+1, "%s\n", aml_getname(name));
474: break;
475: case 'n':
476: off = (opcode != AMLOP_NAMECHAR);
477: name = aml_parsename(scope);
478: node = aml_searchname(scope->node, name);
479: db_aml_disline(pos, depth+off, "%s <%s>\n",
480: aml_getname(name),
481: aml_nodename(node));
482:
483: if (!node || !node->value ||
484: node->value->type != AML_OBJTYPE_METHOD)
485: break;
486:
487: /* Method calls */
488: for (idx = 0;
489: idx < AML_METHOD_ARGCOUNT(node->value->v_method.flags);
490: idx++) {
491: scope->pos = db_aml_disasm(node, scope->pos,
492: scope->end, 1, depth+1);
493: }
494: break;
495: case 'b':
496: off = (opcode != AMLOP_BYTEPREFIX);
497: db_aml_disint(scope, AMLOP_BYTEPREFIX, depth+off);
498: break;
499: case 'w':
500: off = (opcode != AMLOP_WORDPREFIX);
501: db_aml_disint(scope, AMLOP_WORDPREFIX, depth+off);
502: break;
503: case 'd':
504: off = (opcode != AMLOP_DWORDPREFIX);
505: db_aml_disint(scope, AMLOP_DWORDPREFIX, depth+off);
506: break;
507: case 's':
508: db_aml_disline(pos, depth, "\"%s\"\n", scope->pos);
509: scope->pos += strlen(scope->pos)+1;
510: break;
511: case 'B':
512: tmpstr = malloc(16 * 6 + 1, M_DEVBUF, M_WAITOK);
513: for (idx = 0; idx < min(end-scope->pos, 8); idx++)
514: snprintf(tmpstr+idx*6, 7, "0x%.2x, ",
515: scope->pos[idx]);
516: db_aml_disline(pos, depth+1, "ByteList <%s>\n", tmpstr);
517: free(tmpstr, M_DEVBUF);
518: scope->pos = end;
519: break;
520: case 'F':
521: off = 0;
522: while (scope->pos < end) {
523: len = 0;
524: pos = scope->pos;
525: switch (*scope->pos) {
526: case 0x00: // reserved
527: scope->pos++;
528: len = aml_parselength(scope);
529: db_aml_disline(pos, depth+1,
530: "Reserved\t%.4x,%.4x\n",
531: off, len);
532: break;
533: case 0x01: // attr
534: db_aml_disline(pos, depth+1,
535: "Attr:%.2x,%.2x\n",
536: scope->pos[1], scope->pos[2]);
537: scope->pos += 3;
538: break;
539: default:
540: name = aml_parsename(scope);
541: len = aml_parselength(scope);
542: db_aml_disline(pos, depth+1,
543: "NamedField\t%.4x,%.4x %s\n",
544: off, len, aml_getname(name));
545: }
546: off += len;
547: }
548: scope->pos = end;
549: break;
550: default:
551: db_printf("remaining args: '%s'\n", args);
552: }
553: args++;
554: }
555: }
556: pos = scope->pos;
557: aml_popscope(scope);
558: return pos;
559: }
CVSweb