summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Hargrave <jordan@cvs.openbsd.org>2005-12-07 07:46:52 +0000
committerJordan Hargrave <jordan@cvs.openbsd.org>2005-12-07 07:46:52 +0000
commitbad295c13523a162584f90ed6a52e5a1843928fe (patch)
tree17840bf87fa2db1e82099333a693c767c07d8e50
parent44d42f17dc9fc8481b89c5831e4d390a3d5d564d (diff)
Parses DSDT table
some cleanup ok marco@
-rw-r--r--sys/dev/acpi/amltypes.h31
-rw-r--r--sys/dev/acpi/dsdt.c402
2 files changed, 426 insertions, 7 deletions
diff --git a/sys/dev/acpi/amltypes.h b/sys/dev/acpi/amltypes.h
index 650f835b0bf..ef6b799792f 100644
--- a/sys/dev/acpi/amltypes.h
+++ b/sys/dev/acpi/amltypes.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: amltypes.h,v 1.1 2005/12/07 04:24:31 jordan Exp $ */
+/* $OpenBSD: amltypes.h,v 1.2 2005/12/07 07:46:51 jordan Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
*
@@ -35,7 +35,7 @@
#define AMLOP_METHOD 0x14
#define AMLOP_DUALNAMEPREFIX 0x2E
#define AMLOP_MULTINAMEPREFIX 0x2F
-#define AMLOP_EXTOPPREFIX 0x5B
+#define AMLOP_EXTPREFIX 0x5B
#define AMLOP_MUTEX 0x5B01
#define AMLOP_EVENT 0x5B02
#define AMLOP_CONDREFOF 0x5B12
@@ -174,4 +174,31 @@ enum aml_objecttype {
AML_OBJTYPE_DEBUGOBJ
};
+/* AML Opcode Arguments */
+#define AML_ARG_INTEGER 'i'
+#define AML_ARG_BYTE 'b'
+#define AML_ARG_WORD 'w'
+#define AML_ARG_DWORD 'd'
+#define AML_ARG_QWORD 'q'
+#define AML_ARG_ZERO '0'
+#define AML_ARG_ONE '1'
+#define AML_ARG_ONES '!'
+#define AML_ARG_OBJLEN 'p'
+#define AML_ARG_STRING 's'
+#define AML_ARG_BYTELIST 'B'
+#define AML_ARG_REVISION 'R'
+#define AML_ARG_RESULT 'r'
+
+#define AML_ARG_NAMESTRING 'N'
+#define AML_ARG_NAMEREF 'n'
+#define AML_ARG_FIELDLIST 'F'
+#define AML_ARG_FIELDFLAG 'f'
+#define AML_ARG_METHODFLAG 'm'
+
+#define AML_ARG_TERMOBJLIST 'T'
+#define AML_ARG_TERMOBJ 't'
+#define AML_ARG_DATAOBJLIST 'O'
+#define AML_ARG_DATAOBJ 'o'
+
+
#endif /* __AMLPARSE_H__ */
diff --git a/sys/dev/acpi/dsdt.c b/sys/dev/acpi/dsdt.c
index 93c900c6cc1..a27091b1e73 100644
--- a/sys/dev/acpi/dsdt.c
+++ b/sys/dev/acpi/dsdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsdt.c,v 1.2 2005/12/07 04:28:29 marco Exp $ */
+/* $OpenBSD: dsdt.c,v 1.3 2005/12/07 07:46:51 jordan Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
*
@@ -24,6 +24,7 @@
#include <dev/acpi/acpireg.h>
#include <dev/acpi/acpivar.h>
+#include <dev/acpi/amltypes.h>
struct dsdt_softc {
struct device sc_dev;
@@ -44,6 +45,15 @@ struct cfdriver dsdt_cd = {
NULL, "dsdt", DV_DULL
};
+#ifdef AML_DEBUG
+int amldebug=0;
+#define dprintf(x...) do { if (amldebug) printf(x); } while(0)
+#define dnprintf(n,x...) do { if (amldebug > (n)) printf(x); } while(0)
+#else
+#define dprintf(x...)
+#define dnprintf(n,x...)
+#endif
+
int
dsdtmatch(struct device *parent, void *match, void *aux)
{
@@ -56,24 +66,406 @@ dsdtmatch(struct device *parent, void *match, void *aux)
/* if it is an DSDT table, we can attach */
hdr = (struct acpi_table_header *)aaa->aaa_table;
- if (memcmp(hdr->signature, DSDT_SIG, sizeof(DSDT_SIG) - 1) != 0)
- return (0);
+ if (memcmp(hdr->signature, DSDT_SIG, sizeof(DSDT_SIG) - 1) == 0)
+ return (1);
- return (1);
+#if 0
+ /* Attach SSDT tables */
+ if (memcmp(hdr->signature, SSDT_SIG, sizeof(SSDT_SIG) - 1) == 0)
+ return (1);
+#endif
+
+ return (0);
}
void
dsdtattach(struct device *parent, struct device *self, void *aux)
{
- struct dsdt_softc *sc = (struct dsdt_softc *) self;
struct acpi_attach_args *aa = aux;
+ struct dsdt_softc *sc = (struct dsdt_softc *) self;
struct acpi_dsdt *dsdt = (struct acpi_dsdt *)aa->aaa_table;
dsdt_parse_aml(sc, dsdt->aml, dsdt->hdr_length - sizeof(dsdt->hdr));
}
+struct aml_optable
+{
+ u_int16_t opcode;
+ const char *mnem;
+ const char *args;
+};
+
+int aml_isnamedop(uint16_t);
+u_int8_t *aml_decodelength(u_int8_t *, int *);
+u_int8_t *aml_decodename(u_int8_t *);
+u_int8_t *aml_getopcode(u_int8_t *, u_int16_t *);
+u_int8_t *aml_parseargs(struct dsdt_softc *, u_int8_t *, const char *);
+u_int8_t *aml_parse_object(struct dsdt_softc *, u_int8_t *);
+
+/* Decode AML Package length
+ * Upper two bits of first byte denote length
+ * 0x00 = length is in lower 6 bits
+ * 0x40 = length is lower 4 bits + 1 byte
+ * 0x80 = length is lower 4 bits + 2 bytes
+ * 0xC0 = length is lower 4 bits + 3 bytes
+ */
+u_int8_t *
+aml_decodelength(u_int8_t *pos, int *length)
+{
+ u_int8_t lcode;
+
+ lcode = *(pos++);
+
+ *length = (lcode & 0xF);
+ switch(lcode >> 6) {
+ case 0x01:
+ *length += (pos[0] << 4L);
+ return pos+1;
+ case 0x02:
+ *length += (pos[0] << 4L) + (pos[1] << 12L);
+ return pos+2;
+ case 0x03:
+ *length += (pos[0] << 4L) + (pos[1] << 12L) + (pos[2] << 20L);
+ return pos+3;
+ default:
+ *length = (lcode & 0x3F);
+ return pos;
+ }
+}
+
+u_int8_t *
+aml_decodename(u_int8_t *pos)
+{
+ int count;
+ char *name;
+
+ if (*pos == AMLOP_ROOTCHAR) {
+ dprintf(" root ");
+ pos++;
+ }
+ while (*pos == AMLOP_PARENTPREFIX) {
+ dprintf(" parent ");
+ pos++;
+ }
+
+ count = 1;
+ if (*pos == AMLOP_MULTINAMEPREFIX) {
+ dprintf(" multi ");
+ count = *(++pos);
+ pos++;
+ }
+ if (*pos == AMLOP_DUALNAMEPREFIX) {
+ dprintf(" dual ");
+ count = 2;
+ pos++;
+ }
+
+ name = malloc(count * 4 + 1, M_DEVBUF, M_WAITOK);
+ if (name != NULL) {
+ memset(name, 0, count * 4 + 1);
+ memcpy(name, pos, count * 4);
+ dprintf("acpi_name: %s\n", name);
+ free(name, M_DEVBUF);
+ }
+ pos += count*4;
+
+ return pos;
+}
+
+/* Is this opcode an encoded name? */
+int
+aml_isnamedop(uint16_t opcode)
+{
+ switch (opcode) {
+ case AMLOP_ROOTCHAR:
+ case AMLOP_PARENTPREFIX:
+ case AMLOP_MULTINAMEPREFIX:
+ case AMLOP_DUALNAMEPREFIX:
+ case AMLOP_NAMECHAR:
+ return (1);
+ }
+
+ if (opcode >= 'A' && opcode <= 'Z')
+ return (1);
+
+ return (0);
+}
+
+/* Extract opcode from AML bytestream
+ *
+ * Some opcodes are multibyte
+ * Strings can also be embedded within the stream
+ */
+u_int8_t *
+aml_getopcode(u_int8_t *pos, uint16_t *opcode)
+{
+ u_int16_t twocode;
+
+ /* Check for encoded name */
+ if (aml_isnamedop(*pos)) {
+ *opcode = AMLOP_NAMECHAR;
+ return pos;
+ }
+
+ *opcode = *(pos++);
+ twocode = (*opcode << 8L) + *pos;
+
+ /* Check multi-byte opcodes */
+ if (twocode == AMLOP_LNOTEQUAL ||
+ twocode == AMLOP_LLESSEQUAL ||
+ twocode == AMLOP_LGREATEREQUAL ||
+ *opcode == AMLOP_EXTPREFIX) {
+ pos++;
+ *opcode = twocode;
+ }
+
+ return pos;
+}
+
+struct aml_optable aml_table[] = {
+ /* Simple types */
+ { AMLOP_ONES, "Ones", "", },
+ { AMLOP_ZERO, "Zero", "", },
+ { AMLOP_ONE, "One", "", },
+ { AMLOP_BYTEPREFIX, "Byte", "b", },
+ { AMLOP_WORDPREFIX, "Word", "w", },
+ { AMLOP_DWORDPREFIX, "DWord", "d", },
+ { AMLOP_QWORDPREFIX, "QWord", "q", },
+ { AMLOP_REVISION, "Revision", "", },
+ { AMLOP_STRINGPREFIX, "String", "s", },
+ { AMLOP_BUFFER, "Buffer", "piB", },
+
+ /* Simple objects */
+ { AMLOP_DEBUG, "DebugOp", "", },
+ { AMLOP_LOCAL0, "Local0", "", },
+ { AMLOP_LOCAL1, "Local1", "", },
+ { AMLOP_LOCAL2, "Local2", "", },
+ { AMLOP_LOCAL3, "Local3", "", },
+ { AMLOP_LOCAL4, "Local4", "", },
+ { AMLOP_LOCAL5, "Local5", "", },
+ { AMLOP_LOCAL6, "Local6", "", },
+ { AMLOP_LOCAL7, "Local7", "", },
+ { AMLOP_ARG0, "Arg0", "", },
+ { AMLOP_ARG1, "Arg1", "", },
+ { AMLOP_ARG2, "Arg2", "", },
+ { AMLOP_ARG3, "Arg3", "", },
+ { AMLOP_ARG4, "Arg4", "", },
+ { AMLOP_ARG5, "Arg5", "", },
+ { AMLOP_ARG6, "Arg6", "", },
+
+ /* Control flow */
+ { AMLOP_IF, "If", "piT", },
+ { AMLOP_ELSE, "Else", "pT", },
+ { AMLOP_WHILE, "While", "ptT", },
+ { AMLOP_BREAK, "Break", "", },
+ { AMLOP_CONTINUE, "Continue", "", },
+ { AMLOP_RETURN, "Return", "t", },
+
+ { AMLOP_FATAL, "Fatal", "bdi", },
+ { AMLOP_NOP, "Nop", "", },
+ { AMLOP_BREAKPOINT, "BreakPoint", "", },
+
+ /* Arithmetic operations */
+ { AMLOP_INCREMENT, "Increment", "v", },
+ { AMLOP_DECREMENT, "Decrement", "v", },
+ { AMLOP_ADD, "Add", "iir", },
+ { AMLOP_SUBTRACT, "Subtract", "iir", },
+ { AMLOP_MULTIPLY, "Multiply", "iir", },
+ { AMLOP_DIVIDE, "Divide", "iirr", },
+ { AMLOP_SHL, "ShiftLeft", "iir", },
+ { AMLOP_SHR, "ShiftRight", "iir", },
+ { AMLOP_AND, "And", "iir", },
+ { AMLOP_NAND, "Nand", "iir", },
+ { AMLOP_OR, "Or", "iir", },
+ { AMLOP_NOR, "Nor", "iir", },
+ { AMLOP_XOR, "Xor", "iir", },
+ { AMLOP_NOT, "Not", "ir", },
+ { AMLOP_MOD, "Mod", "iir", },
+ { AMLOP_FINDSETLEFTBIT, "FindSetLeftBit", "ir", },
+ { AMLOP_FINDSETRIGHTBIT, "FindSetRightBit", "ir", },
+
+ /* Logical test operations */
+ { AMLOP_LAND, "LAnd", "ii", },
+ { AMLOP_LOR, "LOr", "ii", },
+ { AMLOP_LNOT, "LNot", "i", },
+ { AMLOP_LNOTEQUAL, "LNotEqual", "tt", },
+ { AMLOP_LLESSEQUAL, "LLessEqual", "tt", },
+ { AMLOP_LGREATEREQUAL, "LGreaterEqual", "tt", },
+ { AMLOP_LEQUAL, "LEqual", "tt", },
+ { AMLOP_LGREATER, "LGreater", "tt", },
+ { AMLOP_LLESS, "LLess", "tt", },
+
+ /* Named objects */
+ { AMLOP_NAME, "Name", "No", },
+ { AMLOP_SCOPE, "Scope", "pNT" },
+ { AMLOP_DATAREGION, "DataRegion", "Nttt" },
+ { AMLOP_OPREGION, "OpRegion", "Nfii" },
+ { AMLOP_DEVICE, "Device", "pNO" },
+ { AMLOP_POWERRSRC, "Power Resource", "pNbwO" },
+ { AMLOP_THERMALZONE, "ThermalZone", "pNT" },
+ { AMLOP_METHOD, "Method", "pNmT", },
+ { AMLOP_PROCESSOR, "Processor", "pNbdbO", },
+ { AMLOP_FIELD, "Field", "pNfF" },
+ { AMLOP_INDEXFIELD, "IndexField", "pNnbF" },
+ { AMLOP_BANKFIELD, "BankField", "pNnibF" },
+ { AMLOP_MUTEX, "Mutex", "Nf", },
+ { AMLOP_EVENT, "Event", "N", },
+ { AMLOP_ALIAS, "Alias", "Nn", },
+
+ /* Field operations */
+ { AMLOP_CREATEFIELD, "CreateField", "tiiN", },
+ { AMLOP_CREATEQWORDFIELD, "CreateQWordField","tiN", },
+ { AMLOP_CREATEDWORDFIELD, "CreateDWordField","tiN", },
+ { AMLOP_CREATEWORDFIELD, "CreateWordField", "tiN", },
+ { AMLOP_CREATEBYTEFIELD, "CreateByteField", "tiN", },
+ { AMLOP_CREATEBITFIELD, "CreateBitField", "tiN", },
+
+ /* Conversion operations */
+ { AMLOP_TOINTEGER, "ToInteger", "tr", },
+ { AMLOP_TOBUFFER, "ToBuffer", "tr", },
+ { AMLOP_TODECSTRING, "ToDecString", "ir", },
+ { AMLOP_TOHEXSTRING, "ToHexString", "ir", },
+ { AMLOP_TOSTRING, "ToString", "t", },
+ { AMLOP_FROMBCD, "FromBCD", "ir", },
+ { AMLOP_TOBCD, "ToBCD", "ir", },
+ { AMLOP_MID, "Mid", "tiir", },
+
+ /* Mutex/Signal operations */
+ { AMLOP_ACQUIRE, "Acquire", "vw", },
+ { AMLOP_RELEASE, "Release", "v", },
+ { AMLOP_SIGNAL, "Signal", "v", },
+ { AMLOP_WAIT, "Wait", "vi", },
+ { AMLOP_RESET, "Reset", "v", },
+
+ { AMLOP_INDEX, "Index", "ttr", },
+ { AMLOP_PACKAGE, "Package", "pfT", },
+ { AMLOP_VARPACKAGE, "VarPackage", "piT", },
+ { AMLOP_DEREFOF, "DerefOf", "t", },
+ { AMLOP_REFOF, "RefOf", "v", },
+ { AMLOP_CONDREFOF, "CondRef", "vv", },
+
+ { AMLOP_LOADTABLE, "LoadTable", "tttttt" },
+ { AMLOP_STALL, "Stall", "i", },
+ { AMLOP_SLEEP, "Sleep", "i", },
+ { AMLOP_LOAD, "Load", "Nv" },
+ { AMLOP_UNLOAD, "Unload", "v" },
+ { AMLOP_STORE, "Store", "tv", },
+ { AMLOP_CONCAT, "Concat", "ttr" },
+ { AMLOP_CONCATRES, "ConcatRes", "ttr" },
+ { AMLOP_NOTIFY, "Notify", "vi" },
+ { AMLOP_SIZEOF, "Sizeof", "v", },
+ { AMLOP_MATCH, "Match", "tbibii", },
+ { AMLOP_OBJECTTYPE, "ObjectType", "v", },
+ { AMLOP_COPYOBJECT, "CopyObject", "tn" },
+ { 0xFFFF }
+};
+
+#if 0
+u_int8_t *aml_createinteger(uint8_t *pos, int len)
+{
+ return pos+len;
+}
+#endif
+
+u_int8_t *
+aml_parseargs(struct dsdt_softc *sc, u_int8_t *pos, const char *arg)
+{
+ int len;
+ u_int8_t *nxtpos, *endpos;
+
+ endpos = NULL;
+ nxtpos = pos;
+ while (*arg) {
+ switch (*arg) {
+ case AML_ARG_BYTE:
+ case AML_ARG_FIELDFLAG:
+ case AML_ARG_METHODFLAG:
+ dprintf("byte: %x\n", *(u_int8_t *)pos);
+ nxtpos = pos+1;
+ break;
+ case AML_ARG_WORD:
+ dprintf("word: %x\n", *(u_int16_t *)pos);
+ nxtpos = pos+2;
+ break;
+ case AML_ARG_DWORD:
+ dprintf("dword: %x\n", *(u_int32_t *)pos);
+ nxtpos = pos+4;
+ break;
+ case AML_ARG_QWORD:
+ dprintf("qword: %x\n", *(u_int32_t *)pos);
+ nxtpos = pos+8;
+ break;
+ case AML_ARG_BYTELIST:
+ dprintf("bytelist\n");
+ nxtpos = endpos;
+ break;
+ case AML_ARG_STRING:
+ dprintf("string: %s\n", pos);
+ len = strlen((const char *)pos);
+ nxtpos = pos + len + 1;
+ break;
+ case AML_ARG_NAMESTRING:
+ dprintf("getting name..\n");
+ nxtpos = aml_decodename(pos);
+ break;
+ case AML_ARG_OBJLEN:
+ nxtpos = aml_decodelength(pos, &len);
+ endpos = pos + len;
+ break;
+ case AML_ARG_DATAOBJ:
+ case AML_ARG_INTEGER:
+ case AML_ARG_TERMOBJ:
+ case AML_ARG_RESULT:
+ nxtpos = aml_parse_object(sc, pos);
+ break;
+ case AML_ARG_TERMOBJLIST:
+ case AML_ARG_DATAOBJLIST:
+ while (nxtpos && nxtpos < endpos) {
+ nxtpos = aml_parse_object(sc, nxtpos);
+ }
+ break;
+ default:
+ dprintf("Unknown arg: %c\n", *arg);
+ break;
+ }
+ pos = nxtpos;
+
+ arg++;
+ }
+ return pos;
+}
+
+u_int8_t *
+aml_parse_object(struct dsdt_softc *sc, u_int8_t *pos)
+{
+ struct aml_optable *optab = aml_table;
+ u_int8_t *nxtpos;
+ u_int16_t opcode;
+
+ /* Get AML Opcode; if it is an embedded name, extract name */
+ nxtpos = aml_getopcode(pos, &opcode);
+ if (opcode == AMLOP_NAMECHAR) {
+ return aml_decodename(pos);
+ }
+ while (optab->opcode != 0xFFFF) {
+ if (optab->opcode == opcode) {
+ dprintf("opcode: %.4x = %s\n", opcode, optab->mnem);
+ return aml_parseargs(sc, nxtpos, optab->args);
+ }
+ optab++;
+ }
+ printf("Invalid AML Opcode : %.4x\n", opcode);
+ return NULL;
+}
+
int
dsdt_parse_aml(struct dsdt_softc *sc, u_int8_t *start, u_int32_t length)
{
+ u_int8_t *pos, *nxtpos;
+
+ for (pos = start; pos && pos < start+length; pos=nxtpos) {
+ nxtpos = aml_parse_object(sc, pos);
+ }
+ printf(" : parsed %d AML bytes\n", length);
return (0);
}