Annotation of sys/dev/acpi/acpidebug.c, Revision 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