summaryrefslogtreecommitdiff
path: root/sys/dev/acpi
diff options
context:
space:
mode:
authorMarco Peereboom <marco@cvs.openbsd.org>2006-03-07 23:13:29 +0000
committerMarco Peereboom <marco@cvs.openbsd.org>2006-03-07 23:13:29 +0000
commitfdd978e2bb230572aebe644005ec1f3f0334a237 (patch)
treee5bb90831f88ad312480970e590d4b6cddd859c4 /sys/dev/acpi
parentb9a3a442b0a958c2f23ffa8166b50dcc25b39581 (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.c327
-rw-r--r--sys/dev/acpi/acpidebug.h3
-rw-r--r--sys/dev/acpi/amltypes.h13
-rw-r--r--sys/dev/acpi/dsdt.c34
-rw-r--r--sys/dev/acpi/dsdt.h32
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__ */