root/dev/acpi/acpidebug.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. db_opregion
  2. db_aml_dump
  3. db_aml_showvalue
  4. db_aml_objtype
  5. db_aml_walktree
  6. db_parse_name
  7. db_acpi_showval
  8. db_acpi_disasm
  9. db_acpi_tree
  10. db_acpi_trace
  11. db_aml_disline
  12. db_aml_disint
  13. db_aml_disasm

    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 }

/* [<][>][^][v][top][bottom][index][help] */