diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2006-03-07 23:13:29 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2006-03-07 23:13:29 +0000 |
commit | fdd978e2bb230572aebe644005ec1f3f0334a237 (patch) | |
tree | e5bb90831f88ad312480970e590d4b6cddd859c4 /sys/dev/acpi | |
parent | b9a3a442b0a958c2f23ffa8166b50dcc25b39581 (diff) |
Add "disasm" code for ddb. With this one can disassemble AML code from DDB.
example : "machine acpi disasm \\_SB_.BIF_" dumps the battery AML on my laptop.
Disasm code was written by jordan. Help from miod on ddb lexer magic.
ok jordan.
Diffstat (limited to 'sys/dev/acpi')
-rw-r--r-- | sys/dev/acpi/acpidebug.c | 327 | ||||
-rw-r--r-- | sys/dev/acpi/acpidebug.h | 3 | ||||
-rw-r--r-- | sys/dev/acpi/amltypes.h | 13 | ||||
-rw-r--r-- | sys/dev/acpi/dsdt.c | 34 | ||||
-rw-r--r-- | sys/dev/acpi/dsdt.h | 32 |
5 files changed, 367 insertions, 42 deletions
diff --git a/sys/dev/acpi/acpidebug.c b/sys/dev/acpi/acpidebug.c index 863c1a5bb6c..fd09f254822 100644 --- a/sys/dev/acpi/acpidebug.c +++ b/sys/dev/acpi/acpidebug.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpidebug.c,v 1.1 2006/03/05 14:46:46 marco Exp $ */ +/* $OpenBSD: acpidebug.c,v 1.2 2006/03/07 23:13:28 marco Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <marco@openbsd.org> * @@ -18,6 +18,8 @@ #include <machine/db_machdep.h> #include <ddb/db_command.h> #include <ddb/db_output.h> +#include <ddb/db_extern.h> +#include <ddb/db_lex.h> #include <machine/bus.h> @@ -27,8 +29,272 @@ #include <dev/acpi/acpidebug.h> #include <dev/acpi/dsdt.h> -void db_aml_walktree(struct aml_node *); -void db_aml_shownode(struct aml_node *); +void db_aml_walktree(struct aml_node *); +void db_aml_shownode(struct aml_node *); +void db_aml_disline(uint8_t *, int, const char *, ...); +void db_aml_disint(struct acpi_context *, int, int); +void db_aml_disasm(struct acpi_context *, int); +void db_spaceit(int); +const char *db_aml_objtype(struct aml_value *); +const char *db_aml_opname(int); +struct aml_opcode *db_findem(int); +int db_aml_nodetype(struct aml_node *); + +extern struct aml_node aml_root; + +/* Perfect hash values for AML opcodes */ +#define HASH_VAL 11 +#define HASH_SIZE 204 +#define HASH_KEY(v) (((v) * HASH_VAL) % HASH_SIZE) + +struct aml_opcode *htab[HASH_SIZE]; + +/* line buffer */ +char buf[128]; + +/* name of scope for lexer */ +char scope[80]; + +/* Output disassembled line */ +void +db_spaceit(int len) +{ + while(len--) { + db_printf(".."); + } +} + +struct aml_opcode +*db_findem(int opcode) +{ + int key, cnt; + + cnt = 0; + key = HASH_KEY(opcode); + + while (htab[key] != NULL && htab[key]->opcode != opcode) { + key = (key + 1) % HASH_SIZE; + cnt++; + } + + return (htab[key]); +} + +int +db_aml_nodetype(struct aml_node *node) +{ + return (node && node->value) ? node->value->type : -1; +} + +const char * +db_aml_opname(int opcode) +{ + struct aml_opcode *opc; + + opc = db_findem(opcode); + + return (opc ? opc->mnem : ""); +} + +const char * +db_aml_objtype(struct aml_value *val) +{ + if (val == NULL) + return "nil"; + + switch (val->type) { + case AML_OBJTYPE_STATICINT: + return "staticint"; + case AML_OBJTYPE_INTEGER: + return "integer"; + case AML_OBJTYPE_STRING: + return "string"; + case AML_OBJTYPE_BUFFER: + return "buffer"; + case AML_OBJTYPE_PACKAGE: + return "package"; + case AML_OBJTYPE_DEVICE: + return "device"; + case AML_OBJTYPE_EVENT: + return "event"; + case AML_OBJTYPE_METHOD: + return "method"; + case AML_OBJTYPE_MUTEX: + return "mutex"; + case AML_OBJTYPE_OPREGION: + return "opregion"; + case AML_OBJTYPE_POWERRSRC: + return "powerrsrc"; + case AML_OBJTYPE_PROCESSOR: + return "processor"; + case AML_OBJTYPE_THERMZONE: + return "thermzone"; + case AML_OBJTYPE_DDBHANDLE: + return "ddbhandle"; + case AML_OBJTYPE_DEBUGOBJ: + return "debugobj"; + case AML_OBJTYPE_NAMEREF: + return "nameref"; + case AML_OBJTYPE_OBJREF: + return "refof"; + case AML_OBJTYPE_FIELDUNIT: + case AML_OBJTYPE_BUFFERFIELD: + return db_aml_opname(val->v_field.type); + }; + + return (""); +} + +void +db_aml_disline(uint8_t *pos, int level, const char *fmt, ...) +{ + va_list ap; + + db_printf("%.4x %.2x ", pos - aml_root.start, level); + db_spaceit(level); + + va_start(ap, fmt); + vsnprintf(buf, sizeof buf, fmt, ap); + db_printf(buf); + va_end(ap); + + db_printf("\n"); +} + +/* Output disassembled integer */ +void +db_aml_disint(struct acpi_context *ctx, int level, int type) +{ + u_int8_t *pos; + int64_t i1; + + pos = ctx->pos; + i1 = aml_eparseint(ctx, type); + db_aml_disline(pos, level, "%c:0x%.8llx (%lld)", type, i1, i1); +} + +/* Disassemble AML Opcode */ +void +db_aml_disasm(struct acpi_context *ctx, int level) +{ + struct aml_opcode *opc; + uint8_t *end, *np; + const char *arg, *fname; + struct aml_node *node; + int idx, len; + +#if 0 + /* if we want separators */ + if (level == 0) + db_printf("<<<<<<<<<<<<<<\n"); +#endif + np = ctx->pos; + opc = aml_getopcode(ctx); + db_aml_disline(np, level, opc->mnem); + for (arg = opc->args; *arg; arg++) { + np = ctx->pos; + switch (*arg) { + case AML_ARG_BYTE: + case AML_ARG_WORD: + case AML_ARG_DWORD: + case AML_ARG_QWORD: + db_aml_disint(ctx, level + 1, *arg); + break; + case AML_ARG_STRING: + db_aml_disline(np, level + 1, ctx->pos); + ctx->pos += strlen(ctx->pos) + 1; + break; + case AML_ARG_NAMESTRING: + fname = aml_parse_name(ctx); + db_aml_disline(np, level + 1, fname); + break; + case AML_ARG_NAMEREF: + fname = aml_parse_name(ctx); + node = aml_searchname(ctx->scope, fname); + db_aml_disline(np, level + 1, "%s:%s", fname, + node ? db_aml_objtype(node->value) : "none"); + if (db_aml_nodetype(node) == AML_OBJTYPE_METHOD) + /* Parse method arguments */ + for (idx = 0; idx < AML_METHOD_ARGCOUNT(node->value->v_method.flags); idx++) + db_aml_disasm(ctx, level + 1); + break; + case AML_ARG_INTEGER: + case AML_ARG_TERMOBJ: + case AML_ARG_DATAOBJ: + case AML_ARG_SIMPLENAME: + case AML_ARG_SUPERNAME: + db_aml_disasm(ctx, level + 1); + break; + case AML_ARG_DATAOBJLIST: + case AML_ARG_TERMOBJLIST: + case AML_ARG_METHOD: + while (ctx->pos < end) + db_aml_disasm(ctx, level + 1); + break; + case AML_ARG_BYTELIST: + for (idx = 0; idx < end - ctx->pos - 7; idx += 8) { + db_aml_disline(np, level + 1, "buf %.4x: %.2x " + "%.2x %.2x %.2x %.2x %.2x %.2x %.2x", + idx, ctx->pos[idx], + ctx->pos[idx + 1], + ctx->pos[idx + 2], ctx->pos[idx + 3], + ctx->pos[idx + 4], ctx->pos[idx + 5], + ctx->pos[idx + 6], ctx->pos[idx + 7]); + } + ctx->pos = end; + break; + case AML_ARG_FLAG: + /* Flags */ + idx = aml_eparseint(ctx, AML_ARG_BYTE); + if (opc->opcode == AMLOP_METHOD) + db_aml_disline(np, level + 1, + "args:%d serialized:%d synclevel:%d", + AML_METHOD_ARGCOUNT(idx), + AML_METHOD_SERIALIZED(idx), + AML_METHOD_SYNCLEVEL(idx)); + else + db_aml_disline(np, level + 1, + "acc:%d lock:%d update:%d", + AML_FIELD_ACCESS(idx), + AML_FIELD_LOCK(idx), + AML_FIELD_UPDATE(idx)); + break; + case AML_ARG_FIELDLIST: + for (idx = 0; ctx->pos < end; idx += len) { + np = ctx->pos; + switch (*ctx->pos) { + case AML_FIELD_RESERVED: + ctx->pos++; + len = aml_parse_length(ctx); + break; + case AML_FIELD_ATTR__: + db_aml_disline(np, level + 1, + "-- attr %.2x %.2x", + ctx->pos[1], ctx->pos[2]); + ctx->pos += 3; + len = 0; + break; + default: + fname = aml_parse_name(ctx); + len = aml_parse_length(ctx); + db_aml_disline(np, level + 1, + "pos:%.4x len:%.4x name:%s", + idx, len, fname); + break; + } + } + break; + case AML_ARG_OBJLEN: + end = aml_eparselen(ctx); + break; + } + } +#if 0 + /* if we want separators */ + if (level == 0) + db_printf(">>>>>>>>>>>>>>\n"); +#endif +} void db_aml_shownode(struct aml_node *node) @@ -68,7 +334,7 @@ db_aml_shownode(struct aml_node *node) void db_aml_walktree(struct aml_node *node) { - int i; + int i; while(node) { db_printf(" %d ", node->depth); @@ -83,9 +349,58 @@ db_aml_walktree(struct aml_node *node) /* ddb interface */ void -db_acpi_tree(db_expr_t addr, int haddr, db_expr_t count, char *modif) +db_acpi_disasm(db_expr_t addr, int haddr, db_expr_t count, char *modif) { - extern struct aml_node aml_root; + extern struct acpi_softc *acpi_softc; + struct acpi_softc *sc = acpi_softc; + struct acpi_context *ctx; + struct aml_node *node; + int t; + + memset(scope, 0, sizeof scope); + do { + t = db_read_token(); + if (t == tIDENT) { + if (strlcat(scope, db_tok_string, sizeof scope) >= + sizeof scope) { + printf("Input too long\n"); + goto error; + } + t = db_read_token(); + if (t == tDOT) + if (strlcat(scope, ".", sizeof scope) >= + sizeof scope) { + printf("Input too long 2\n"); + goto error; + } + } + } + while (t != tEOL); + if (!strlen(scope)) { + db_printf("Invalid input\n"); + goto error; + } + + /* get rid of the rest of input */ + db_flush_lex(); + + ctx = acpi_alloccontext(sc, &aml_root, 0, NULL); + node = aml_searchname(&aml_root, scope); + if (node && node->value && node->value->type == AML_OBJTYPE_METHOD) { + ctx->pos = node->value->v_method.start; + while (ctx->pos < node->value->v_method.end) + db_aml_disasm(ctx, 0); + } + acpi_freecontext(ctx); + +error: + db_flush_lex(); +} + +void +db_acpi_tree(db_expr_t addr, int haddr, db_expr_t count, char *modif) +{ db_aml_walktree(aml_root.child); + } diff --git a/sys/dev/acpi/acpidebug.h b/sys/dev/acpi/acpidebug.h index 74721f97ac1..b57b6c72fe5 100644 --- a/sys/dev/acpi/acpidebug.h +++ b/sys/dev/acpi/acpidebug.h @@ -1,4 +1,4 @@ -/* $OpenBSD: acpidebug.h,v 1.1 2006/03/05 14:46:46 marco Exp $ */ +/* $OpenBSD: acpidebug.h,v 1.2 2006/03/07 23:13:28 marco Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <marco@openbsd.org> * @@ -15,4 +15,5 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +void db_acpi_disasm(db_expr_t, int, db_expr_t, char *); void db_acpi_tree(db_expr_t, int, db_expr_t, char *); diff --git a/sys/dev/acpi/amltypes.h b/sys/dev/acpi/amltypes.h index 68fb1c29717..1b936048c66 100644 --- a/sys/dev/acpi/amltypes.h +++ b/sys/dev/acpi/amltypes.h @@ -1,4 +1,4 @@ -/* $OpenBSD: amltypes.h,v 1.14 2006/02/23 19:56:44 jordan Exp $ */ +/* $OpenBSD: amltypes.h,v 1.15 2006/03/07 23:13:28 marco Exp $ */ /* * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> * @@ -189,7 +189,7 @@ enum aml_objecttype { #define AML_ARG_QWORD 'q' #define AML_ARG_IMPBYTE '!' #define AML_ARG_OBJLEN 'p' -#define AML_ARG_STRING 's' +#define AML_ARG_STRING 'a' #define AML_ARG_BYTELIST 'B' #define AML_ARG_REVISION 'R' @@ -199,6 +199,12 @@ enum aml_objecttype { #define AML_ARG_FIELDLIST 'F' #define AML_ARG_FLAG 'f' +#define AML_ARG_DATAOBJLIST 'O' +#define AML_ARG_DATAOBJ 'o' + +#define AML_ARG_SIMPLENAME 's' +#define AML_ARG_SUPERNAME 'S' + #define AML_ARG_TERMOBJLIST 'T' #define AML_ARG_TERMOBJ 't' @@ -223,6 +229,9 @@ enum aml_objecttype { # define AML_FIELD_WRITEASONES 0x1 # define AML_FIELD_WRITEASZEROES 0x2 #define AML_FIELD_ATTR(v) ((v) >> 8) +#define AML_FIELD_RESERVED 0x00 +/* XXX fix this name */ +#define AML_FIELD_ATTR__ 0x01 struct aml_node; diff --git a/sys/dev/acpi/dsdt.c b/sys/dev/acpi/dsdt.c index 1ad2097edc2..a2e2e01e2ec 100644 --- a/sys/dev/acpi/dsdt.c +++ b/sys/dev/acpi/dsdt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dsdt.c,v 1.32 2006/03/05 14:46:46 marco Exp $ */ +/* $OpenBSD: dsdt.c,v 1.33 2006/03/07 23:13:28 marco Exp $ */ /* * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> * @@ -55,24 +55,6 @@ #define aml_ipaddr(n) ((n)-aml_root.start) -struct aml_opcode -{ - u_int16_t opcode; - const char *mnem; - const char *args; -}; - -struct acpi_context -{ - int depth; - uint8_t *pos; - uint8_t *start; - struct acpi_softc *sc; - struct aml_value **locals; - struct aml_value **args; - struct aml_node *scope; -}; - #ifdef ACPI_DEBUG const char *opregion(int id); @@ -95,10 +77,8 @@ opregion(int id) int aml_parse_length(struct acpi_context *); u_int64_t aml_parse_int(struct acpi_context *, int); const char *aml_parse_string(struct acpi_context *); -const char *aml_parse_name(struct acpi_context *); int aml_isnamedop(u_int16_t); -struct aml_opcode *aml_getopcode(struct acpi_context *ctx); void aml_shownode(struct aml_node *); @@ -109,12 +89,6 @@ int aml_msb(u_int64_t); int _aml_freevalue(struct aml_value *); -void acpi_freecontext(struct acpi_context *ctx); -struct acpi_context *acpi_alloccontext(struct acpi_softc *sc, - struct aml_node *node, - int argc, - struct aml_value *argv); - struct aml_node *aml_find_name(struct acpi_softc *, struct aml_node *, const char *); int64_t aml_str2int(const char *, int, int); @@ -141,7 +115,6 @@ int aml_bufcmp(const u_int8_t *, int, const u_int8_t *, int); struct aml_value *aml_ederef(struct acpi_context *ctx, struct aml_value *val); void aml_resizevalue(struct aml_value *, int); -int aml_parse_length(struct acpi_context *ctx); struct aml_value *aml_eparseval(struct acpi_context *, int deref); struct aml_opcode *aml_getopcode(struct acpi_context *); struct aml_value *aml_esetnodevalue(struct acpi_context *, struct aml_value *lhs, @@ -150,14 +123,11 @@ struct aml_value *aml_eparselist(struct acpi_context *, u_int8_t *end, int); struct aml_node *_aml_searchname(struct aml_node *, const char *); struct aml_node *aml_doname(struct aml_node *, const char *, int); -struct aml_node *aml_searchname(struct aml_node *, const char *); struct aml_node *aml_createname(struct aml_node *, const char *); struct aml_value *aml_eparsescope(struct acpi_context *, const char *, u_int8_t *, struct aml_opcode *, struct aml_value *); -int64_t aml_eparseint(struct acpi_context *, int type); struct aml_value *aml_efieldunit(struct acpi_context *, int opcode); struct aml_value *aml_ebufferfield(struct acpi_context *, int bitlen, int size, int opcode); -u_int8_t *aml_eparselen(struct acpi_context *); struct aml_value *aml_efield(struct acpi_context *, struct aml_value *e_fld, struct aml_value *rhs); struct aml_node *aml_addvname(struct acpi_context *, const char *name, int opcode, @@ -983,7 +953,7 @@ struct aml_opcode aml_table[] = { { AMLOP_DWORDPREFIX, "DWord", "d" }, { AMLOP_QWORDPREFIX, "QWord", "q" }, { AMLOP_REVISION, "Revision", "" }, - { AMLOP_STRINGPREFIX, "String", "s" }, + { AMLOP_STRINGPREFIX, "String", "a" }, { AMLOP_DEBUG, "DebugOp", "", }, { AMLOP_BUFFER, "Buffer", "piB" }, { AMLOP_PACKAGE, "Package", "pbT" }, diff --git a/sys/dev/acpi/dsdt.h b/sys/dev/acpi/dsdt.h index 419005fb7af..be7f2887721 100644 --- a/sys/dev/acpi/dsdt.h +++ b/sys/dev/acpi/dsdt.h @@ -1,4 +1,4 @@ -/* $OpenBSD: dsdt.h,v 1.10 2006/03/05 14:46:46 marco Exp $ */ +/* $OpenBSD: dsdt.h,v 1.11 2006/03/07 23:13:28 marco Exp $ */ /* * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> * @@ -18,6 +18,24 @@ #ifndef __DEV_ACPI_DSDT_H__ #define __DEV_ACPI_DSDT_H__ +struct acpi_context +{ + int depth; + uint8_t *pos; + uint8_t *start; + struct acpi_softc *sc; + struct aml_value **locals; + struct aml_value **args; + struct aml_node *scope; +}; + +struct aml_opcode +{ + u_int16_t opcode; + const char *mnem; + const char *args; +}; + const char *aml_eisaid(u_int32_t); int aml_find_node(struct aml_node *, const char *, void (*)(struct aml_node *, void *), void *); @@ -52,4 +70,16 @@ void aml_register_notify(struct aml_node *, const char *, void aml_notify(struct aml_node *, int); void aml_notify_dev(const char *, int); +int64_t aml_eparseint(struct acpi_context *, int); +struct aml_opcode *aml_getopcode(struct acpi_context *); +const char *aml_parse_name(struct acpi_context *); +int aml_parse_length(struct acpi_context *); +u_int8_t *aml_eparselen(struct acpi_context *); + +void acpi_freecontext(struct acpi_context *); +struct acpi_context *acpi_alloccontext(struct acpi_softc *, struct aml_node *, + int, struct aml_value *); + +struct aml_node *aml_searchname(struct aml_node *, const char *); + #endif /* __DEV_ACPI_DSDT_H__ */ |