[BACK]Return to acpidebug.c CVS log [TXT][DIR] Up to [local] / sys / dev / acpi

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