summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJordan Hargrave <jordan@cvs.openbsd.org>2006-02-03 23:55:48 +0000
committerJordan Hargrave <jordan@cvs.openbsd.org>2006-02-03 23:55:48 +0000
commit10ee7040389481a51445322c1e19655caf35ffad (patch)
treeb4855f10ceec969f4d683d0b85b58a4611513142 /sys
parentd94015f2730668a756180e3fd25367ffe1e07d14 (diff)
Rewrote aml parser yet again...
Fixed bus_space_map for i386/amd64 Added _BST and _BIF to acpibat to get status/info ok marco@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/acpi/acpi.c72
-rw-r--r--sys/dev/acpi/acpibat.c5
-rw-r--r--sys/dev/acpi/acpivar.h4
-rw-r--r--sys/dev/acpi/amltypes.h35
-rw-r--r--sys/dev/acpi/dsdt.c2722
-rw-r--r--sys/dev/acpi/dsdt.h10
6 files changed, 1660 insertions, 1188 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index 4f8dccd991d..ea9977f8c69 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.23 2006/01/20 20:20:28 jordan Exp $ */
+/* $OpenBSD: acpi.c,v 1.24 2006/02/03 23:55:47 jordan Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -85,64 +85,78 @@ struct cfdriver acpi_cd = {
struct acpi_softc *acpi_softc;
int acpi_s5, acpi_evindex, icount;
-void
+#ifdef __i386__
+#define acpi_bus_space_map _bus_space_map
+#define acpi_bus_space_unmap _bus_space_unmap
+#elif defined(__amd64__)
+#define acpi_bus_space_map _x86_memio_map
+#define acpi_bus_space_unmap _x86_memiu_unmap
+#else
+#error ACPI supported on i386/amd64 only
+#endif
+
+int
acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
int access_size, int len, void *buffer)
{
- void *pb;
+ u_int8_t *pb;
bus_space_handle_t ioh;
struct acpi_mem_map mh;
pci_chipset_tag_t pc;
pcitag_t tag;
+ bus_addr_t ioaddr;
int reg, idx, ival, sval;
+ dnprintf(10, "gasio: %x %llx %x %x %p\n", iospace, address, access_size, len, buffer);
+
+ pb = (u_int8_t *)buffer;
switch (iospace) {
case GAS_SYSTEM_MEMORY:
/* copy to/from system memory */
acpi_map(address, len, &mh);
- if (iodir == ACPI_IOREAD) {
+ if (iodir == ACPI_IOREAD)
memcpy(buffer, mh.va, len);
- }
- else {
+ else
memcpy(mh.va, buffer, len);
- }
acpi_unmap(&mh);
break;
case GAS_SYSTEM_IOSPACE:
/* read/write from I/O registers */
- pb = buffer;
- bus_space_map(sc->sc_iot, address, len, 0, &ioh);
- while (pb < buffer+len) {
+ ioaddr = address;
+ if (acpi_bus_space_map(sc->sc_iot, ioaddr, len, 0, &ioh) != 0) {
+ printf("Unable to map iospace!\n");
+ return (-1);
+ }
+ for (reg=0; reg < len; reg += access_size) {
if (iodir == ACPI_IOREAD) {
switch (access_size) {
case 1:
- *(uint8_t *)pb = bus_space_read_1(sc->sc_iot, ioh, 0);
+ *(uint8_t *)(pb+reg) = bus_space_read_1(sc->sc_iot, ioh, reg);
break;
case 2:
- *(uint16_t *)pb = bus_space_read_2(sc->sc_iot, ioh, 0);
+ *(uint16_t *)(pb+reg) = bus_space_read_2(sc->sc_iot, ioh, reg);
break;
case 4:
- *(uint32_t *)pb = bus_space_read_4(sc->sc_iot, ioh, 0);
+ *(uint32_t *)(pb+reg) = bus_space_read_4(sc->sc_iot, ioh, reg);
break;
}
}
else {
switch (access_size) {
case 1:
- bus_space_write_1(sc->sc_iot, ioh, 0, *(uint8_t *)pb);
+ bus_space_write_1(sc->sc_iot, ioh, reg, *(uint8_t *)(pb+reg));
break;
case 2:
- bus_space_write_2(sc->sc_iot, ioh, 0, *(uint16_t *)pb);
+ bus_space_write_2(sc->sc_iot, ioh, reg, *(uint16_t *)(pb+reg));
break;
case 4:
- bus_space_write_4(sc->sc_iot, ioh, 0, *(uint32_t *)pb);
+ bus_space_write_4(sc->sc_iot, ioh, reg, *(uint32_t *)(pb+reg));
break;
}
}
- pb += access_size;
}
- bus_space_unmap(sc->sc_iot, ioh, len);
+ acpi_bus_space_unmap(sc->sc_iot, ioh, len, &ioaddr);
break;
case GAS_PCI_CFG_SPACE:
@@ -153,7 +167,6 @@ acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
* bits 48..63 = bus
*/
pc = NULL;
- pb = buffer;
tag = pci_make_tag(pc,
ACPI_PCI_BUS(address),
ACPI_PCI_DEV(address),
@@ -166,21 +179,21 @@ acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
if (iodir == ACPI_IOREAD) {
switch (idx & 0x3) {
case 0:
- *(u_int8_t *)pb = ival;
+ *pb = ival;
break;
case 1:
- *(u_int8_t *)pb = (ival >> 8);
+ *pb = (ival >> 8);
break;
case 2:
- *(u_int8_t *)pb = (ival >> 16);
+ *pb = (ival >> 16);
break;
case 3:
- *(u_int8_t *)pb = (ival >> 24);
+ *pb = (ival >> 24);
break;
}
}
else {
- sval = *(uint8_t *)pb;
+ sval = *pb;
switch (idx & 0x3) {
case 0:
ival &= ~0xFF;
@@ -205,6 +218,7 @@ acpi_gasio(struct acpi_softc *sc, int iodir, int iospace, uint64_t address,
}
break;
}
+ return (0);
}
/* Map Power Management registers */
@@ -436,7 +450,7 @@ acpi_foundhid(struct aml_node *node, void *arg)
struct aml_value res;
dnprintf(10, "found hid device: %s ", node->parent->name);
- aml_eval_object(sc, node, &res, NULL);
+ aml_eval_object(sc, node, &res, 0, NULL);
switch (res.type) {
case AML_OBJTYPE_STRING:
@@ -618,14 +632,6 @@ acpi_attach(struct device *parent, struct device *self, void *aux)
#endif
acpi_attach_machdep(sc);
- for (idx = 0; idx < ACPIREG_MAXREG; idx++) {
- if (sc->sc_pmregs[idx].name) {
- dnprintf(30, "%8s = %.8x\n",
- sc->sc_pmregs[idx].name,
- acpi_read_pmreg(sc, idx));
- }
- }
-
/*
* If we have an interrupt handler, we can get notification
* when certain status bits changes in the ACPI registers,
diff --git a/sys/dev/acpi/acpibat.c b/sys/dev/acpi/acpibat.c
index 7926a9b67e3..6a575f5c36d 100644
--- a/sys/dev/acpi/acpibat.c
+++ b/sys/dev/acpi/acpibat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpibat.c,v 1.9 2006/01/17 23:42:14 jordan Exp $ */
+/* $OpenBSD: acpibat.c,v 1.10 2006/02/03 23:55:47 jordan Exp $ */
/*
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
*
@@ -78,7 +78,8 @@ acpibat_attach(struct device *parent, struct device *self, void *aux)
sc->sc_acpi = (struct acpi_softc *)parent;
sc->sc_devnode = aa->aaa_node->child;
- /* acpibat_getbif(sc); */
+ acpibat_getbif(sc);
+ acpibat_getbst(sc);
printf("\n");
}
diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h
index 2c82484d7fb..e90419935e9 100644
--- a/sys/dev/acpi/acpivar.h
+++ b/sys/dev/acpi/acpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpivar.h,v 1.13 2006/01/18 22:25:44 jordan Exp $ */
+/* $OpenBSD: acpivar.h,v 1.14 2006/02/03 23:55:47 jordan Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
*
@@ -163,7 +163,7 @@ void acpi_powerdown(void);
#define ACPI_IOREAD 0
#define ACPI_IOWRITE 1
-void acpi_gasio(struct acpi_softc *, int, int, uint64_t, int, int, void *);
+int acpi_gasio(struct acpi_softc *, int, int, uint64_t, int, int, void *);
#endif
diff --git a/sys/dev/acpi/amltypes.h b/sys/dev/acpi/amltypes.h
index 63a96c02931..b3a16c0cae3 100644
--- a/sys/dev/acpi/amltypes.h
+++ b/sys/dev/acpi/amltypes.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: amltypes.h,v 1.11 2006/01/20 20:20:28 jordan Exp $ */
+/* $OpenBSD: amltypes.h,v 1.12 2006/02/03 23:55:47 jordan Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
*
@@ -205,6 +205,7 @@ enum aml_objecttype {
#define AML_METHOD_SERIALIZED(v) (((v) >> 3) & 0x1)
#define AML_METHOD_SYNCLEVEL(v) (((v) >> 4) & 0xF)
+#define AML_FIELD_ACCESSMASK 0x0F
#define AML_FIELD_SETATTR(f,t,a) (((f) & 0xF0) | ((t) & 0xF) | ((a)<<8))
#define AML_FIELD_ACCESS(v) (((v) >> 0) & 0xF)
# define AML_FIELD_ANYACC 0x0
@@ -229,34 +230,35 @@ struct aml_value
{
int type;
int length;
- int dynamic;
int refcnt;
+ const char *name;
union {
int64_t vinteger;
char *vstring;
u_int8_t *vbuffer;
struct aml_value **vpackage;
struct {
- const char *name;
- struct aml_node *ref;
- } vnameref;
- struct {
u_int8_t iospace;
u_int64_t iobase;
u_int32_t iolen;
+#if 0
+ u_int8_t *buf;
+#endif
} vopregion;
struct {
- struct aml_value *args;
- struct aml_value *locals;
- struct aml_value *result;
+ int flags;
+ u_int8_t *start;
+ u_int8_t *end;
} vmethod;
struct {
- u_int8_t acc_size;
+ u_int16_t type;
u_int16_t flags;
- u_int16_t ftype;
- u_int32_t bitpos;
- u_int32_t bitlen;
- struct aml_node *ref;
+ u_int32_t bitpos;
+ u_int32_t bitlen;
+ struct aml_value *ref1;
+ struct aml_value *ref2;
+ int ref3;
+ const char *ftyp;
} vfield;
struct {
u_int8_t proc_id;
@@ -264,8 +266,8 @@ struct aml_value
u_int8_t proc_len;
} vprocessor;
struct {
- int index;
- struct aml_node *ref;
+ int index;
+ struct aml_value *ref;
} vobjref;
struct {
u_int8_t pwr_level;
@@ -275,7 +277,6 @@ struct aml_value
};
#define v_objref _.vobjref
-#define v_nameref _.vnameref
#define v_integer _.vinteger
#define v_string _.vstring
#define v_buffer _.vbuffer
diff --git a/sys/dev/acpi/dsdt.c b/sys/dev/acpi/dsdt.c
index ec6f526080f..f84d58bf20a 100644
--- a/sys/dev/acpi/dsdt.c
+++ b/sys/dev/acpi/dsdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsdt.c,v 1.18 2006/01/20 20:20:28 jordan Exp $ */
+/* $OpenBSD: dsdt.c,v 1.19 2006/02/03 23:55:47 jordan Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
*
@@ -27,27 +27,24 @@
#include <dev/acpi/amltypes.h>
#include <dev/acpi/dsdt.h>
-struct aml_optable
+void *stacktop;
+
+struct aml_opcode
{
u_int16_t opcode;
const char *mnem;
const char *args;
};
-struct acpi_stack
-{
- struct aml_value *locals;
- struct aml_value *args;
- struct aml_value result;
- struct acpi_stack *next;
-};
-
struct acpi_context
{
- struct acpi_softc *sc;
- struct acpi_stack *stack;
-
- u_int8_t *pos;
+ 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
@@ -71,17 +68,12 @@ opregion(int id)
int aml_parse_length(struct acpi_context *);
-int aml_parse_fieldlist(struct acpi_context *, struct aml_node *);
-int aml_parse_objlist(struct acpi_context *, struct aml_node *);
-int aml_parse_args(struct acpi_context *, struct aml_node *, const char *);
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 *, const char *);
-struct aml_node *aml_parse_object(struct acpi_context *, struct aml_node *);
-struct aml_node *aml_preparse(struct acpi_context *, struct aml_node *, struct aml_optable *);
+const char *aml_parse_name(struct acpi_context *);
int aml_isnamedop(u_int16_t);
-u_int16_t aml_getopcode(struct acpi_context *);
+struct aml_opcode *aml_getopcode(struct acpi_context *ctx);
void aml_shownode(struct aml_node *);
@@ -91,9 +83,13 @@ u_int64_t aml_dec2bcd(u_int64_t);
int aml_lsb(u_int64_t val);
int aml_msb(u_int64_t val);
+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);
+
void aml_walkroot(void);
-void aml_addchildnode(struct aml_node *, struct aml_node *);
-struct aml_node *aml_create_node(struct acpi_context *, struct aml_node *, int opcode, const char *mnem);
struct aml_node *aml_find_name(struct acpi_softc *, struct aml_node *, const char *);
int64_t aml_str2int(const char *, int, int);
@@ -101,14 +97,16 @@ int64_t aml_evalmath(u_int16_t, int64_t, int64_t);
int aml_testlogical(u_int16_t, long, long);
int aml_strcmp(u_int16_t opcode, const char *lhs, const char *rhs);
-int aml_eval_object(struct acpi_softc *, struct aml_node *, struct aml_value *, struct aml_value *);
-
int64_t _aml_evalint(struct acpi_context *, struct aml_node *);
struct aml_value *aml_getnodevalue(struct acpi_context *, struct aml_node *);
struct aml_value *_aml_evalref(struct acpi_context *, struct aml_node *);
struct aml_value *aml_evalnode(struct acpi_context *, struct aml_node *);
struct aml_value *_aml_setnodevalue(struct acpi_context *, struct aml_node *, struct aml_value *, uint64_t);
+struct aml_node *aml_create_node(struct aml_node *parent,
+ int opc, const char *mnem,
+ uint8_t *start);
+
int aml_match(int64_t, int, int64_t);
struct aml_node *childOf(struct aml_node *, int);
@@ -127,18 +125,27 @@ void acpi_os_freemem(void *);
void aml_addchildnode(struct aml_node *, struct aml_node *);
-struct aml_node aml_root;
+struct aml_node aml_root;
+struct aml_value *aml_global_lock;
+
+#define acpi_mutex_acquire(ctx,lock,iv) dnprintf(10,"ACQUIRE: %x" #lock "\n", (short)iv)
+#define acpi_mutex_release(ctx,lock) dnprintf(10,"RELEASE: " #lock "\n")
void *
acpi_os_allocmem(size_t size)
{
- return malloc(size, M_DEVBUF, M_WAITOK);
+ void *ptr;
+
+ ptr = malloc(size, M_DEVBUF, M_WAITOK);
+ if (ptr)
+ memset(ptr, 0, size);
+ return ptr;
}
void
acpi_os_freemem(void *ptr)
{
- free(ptr, M_DEVBUF);
+ //free(ptr, M_DEVBUF);
}
/* Bit mangling code */
@@ -163,65 +170,42 @@ aml_setbit(u_int8_t *pb, int bit, int val)
#define aml_ipaddr(n) ((n)-aml_root.start)
+#define AML_REVISION 0x01
#define AML_NUM_LOCALS 8
#define AML_INTSTRLEN 16
#define AML_NAMESEG_LEN 4
-struct aml_node *_aml_searchname(struct aml_node *list, const char *name);
-struct aml_node *_aml_findname(struct aml_node *root, const char *name);
-
-struct aml_node *_aml_searchname(struct aml_node *list, const char *name)
+void aml_addchildnode(struct aml_node *parent,
+ struct aml_node *child)
{
- if (list->opcode == AMLOP_FIELD ||
- list->opcode == AMLOP_INDEXFIELD ||
- list->opcode == AMLOP_BANKFIELD) {
- dnprintf(50, "search field objects\n");
- list = list->child;
- }
- while (list != NULL) {
- if (list->name && !strncmp(list->name, name, AML_NAMESEG_LEN)) {
- return list;
- }
- }
- return NULL;
+ struct aml_node **tmp;
+
+ for (tmp = &parent->child; *tmp; tmp = &((*tmp)->sibling))
+ ;
+
+ child->sibling = NULL;
+ child->parent = parent;
+ *tmp = child;
}
-struct aml_node *_aml_findname(struct aml_node *root, const char *name)
+struct aml_node *aml_create_node(struct aml_node *parent, int opcode,
+ const char *mnem, uint8_t *start)
{
struct aml_node *node;
- if (root == NULL) {
- root = &aml_root;
- }
- if (*name == AMLOP_ROOTCHAR) {
- name++;
- root = &aml_root;
- }
- while (*name == AMLOP_PARENTPREFIX) {
- name++;
- root = root->parent;
- if (root == NULL) {
- dnprintf(50, "_aml_find_node: Bad parent!!\n");
- return NULL;
- }
+ node = (struct aml_node *)acpi_os_allocmem(sizeof(struct aml_node));
+ if (node == NULL) {
+ return NULL;
}
+ node->opcode = opcode;
+ node->mnem = mnem;
+ node->depth = parent->depth+1;
+ node->start = start;
+ node->end = parent->end;
+ node->child = NULL;
- /* Ok... name is parsed.. now search all siblings of parent */
- for (node=NULL; *name && root && !node;) {
- if (*name == '.') name++;
- if ((node = _aml_searchname(root->child, name)) == NULL) {
- /* search parent */
- root = root->parent;
- }
- else if (name[AML_NAMESEG_LEN] == '\0') {
- /* found it */
- return node;
- }
- else {
- root = node;
- name += AML_NAMESEG_LEN;
- }
- }
+ aml_addchildnode(parent, node);
+
return node;
}
@@ -232,34 +216,31 @@ struct aml_node *_aml_findname(struct aml_node *root, const char *name)
* lbl : Debugging label
*/
struct aml_value *
-aml_allocvalue(int type, int64_t ival, const void *bval,
+aml_allocvalue(int type, int64_t ival, void *bval,
const char *lbl)
{
struct aml_value *rv;
+ struct aml_value **pv;
+ int64_t idx;
rv = (struct aml_value *)acpi_os_allocmem(sizeof(struct aml_value));
- if (rv == NULL)
- return NULL;
-
- memset(rv, 0, sizeof(struct aml_value));
rv->type = type;
- rv->dynamic = 1;
rv->refcnt = 1;
switch (type) {
+ case AML_OBJTYPE_OBJREF:
+ rv->v_objref.index = ival;
+ rv->v_objref.ref = (struct aml_value *)bval;
+ break;
case AML_OBJTYPE_INTEGER:
rv->v_integer = ival;
break;
- case AML_OBJTYPE_NAMEREF:
- rv->v_nameref.name = bval;
- break;
case AML_OBJTYPE_STRING:
/* Allocate string: if pointer valid, copy data */
rv->length = ival;
rv->v_string = NULL;
if (ival) {
rv->v_string = acpi_os_allocmem(ival+1);
- memset(rv->v_string, 0, ival+1);
if (bval) {
strncpy(rv->v_string, bval, ival);
}
@@ -271,7 +252,6 @@ aml_allocvalue(int type, int64_t ival, const void *bval,
rv->v_buffer = NULL;
if (ival) {
rv->v_buffer = acpi_os_allocmem(ival);
- memset(rv->v_buffer, 0, ival);
if (bval) {
memcpy(rv->v_buffer, bval, ival);
}
@@ -281,51 +261,67 @@ aml_allocvalue(int type, int64_t ival, const void *bval,
/* Allocate package pointers */
rv->length = ival;
rv->v_package = (struct aml_value **)acpi_os_allocmem(rv->length * sizeof(struct aml_value *));
- memset(rv->v_package, 0, rv->length * sizeof(struct aml_value *));
+ if (bval != NULL) {
+ pv = (struct aml_value **)bval;
+ dnprintf(10, "alloc package..\n");
+ for (idx=0; idx<ival; idx++) {
+ rv->v_package[idx] = aml_copyvalue(pv[idx]);
+ }
+ }
break;
case AML_OBJTYPE_METHOD:
- /* Allocate method stack */
- rv->v_method.locals = (struct aml_value *)acpi_os_allocmem(8 * sizeof(struct aml_value));
- rv->v_method.args = (struct aml_value *)acpi_os_allocmem(ival * sizeof(struct aml_value));
- memset(rv->v_method.locals, 0, 8 * sizeof(struct aml_value));
- memset(rv->v_method.args, 0, ival * sizeof(struct aml_value));
- break;
- case AML_OBJTYPE_OBJREF:
- rv->v_objref.index = ival;
- rv->v_objref.ref = (struct aml_node *)bval;
+ rv->name = bval;
+ rv->v_method.flags = ival;
break;
case AML_OBJTYPE_MUTEX:
+ rv->name = bval;
rv->v_integer = ival;
break;
+ case AML_OBJTYPE_NAMEREF:
+ case AML_OBJTYPE_OPREGION:
+ case AML_OBJTYPE_DEVICE:
+ case AML_OBJTYPE_EVENT:
+ case AML_OBJTYPE_POWERRSRC:
+ case AML_OBJTYPE_PROCESSOR:
+ case AML_OBJTYPE_THERMZONE:
+ rv->name = bval;
+ break;
+ case AML_OBJTYPE_BUFFERFIELD:
+ case AML_OBJTYPE_FIELDUNIT:
+ break;
+ default:
+ dnprintf(10, "Unknown aml_allocvalue: %.2x\n", type);
}
return rv;
}
struct aml_value *
-aml_allocint(uint64_t ival)
+aml_allocint(uint64_t ival, int sc)
{
- return aml_allocvalue(AML_OBJTYPE_INTEGER, ival, NULL, "integer");
+ return aml_allocvalue(AML_OBJTYPE_INTEGER, ival, &sc, "integer");
}
struct aml_value *
aml_allocstr(const char *str)
{
- return aml_allocvalue(AML_OBJTYPE_STRING, strlen(str), str, "string");
+ return aml_allocvalue(AML_OBJTYPE_STRING, strlen(str), (void *)str, "string");
}
int
-aml_freevalue(struct aml_value *v)
+aml_freevalue(struct aml_value **pv)
{
+ struct aml_value *v = *pv;
int idx;
- /* XXX: fix this ref count */
- return (0);
-
/* Don't free static values */
- if (v == NULL || !v->dynamic)
+ if (v == NULL)
+ return (0);
+ if (v->refcnt < 0)
+ return (0);
+ if (--v->refcnt > 0)
return (0);
- dnprintf(50, "freeing value : %x\n", v->type);
+ //dnprintf(50, "freeing value : %x\n", v->type);
switch (v->type) {
case AML_OBJTYPE_STRING:
if (v->v_string) {
@@ -341,7 +337,7 @@ aml_freevalue(struct aml_value *v)
break;
case AML_OBJTYPE_PACKAGE:
for (idx=0; idx<v->length; idx++) {
- aml_freevalue(v->v_package[idx]);
+ aml_freevalue(&v->v_package[idx]);
}
acpi_os_freemem(v->v_package);
v->v_package = NULL;
@@ -351,10 +347,24 @@ aml_freevalue(struct aml_value *v)
}
v->type = 0;
acpi_os_freemem(v);
+ *pv = NULL;
return (1);
}
+void aml_dump(int len, u_int8_t *buf);
+
+void
+aml_dump(int len, u_int8_t *buf)
+{
+ int idx;
+
+ dnprintf(50, "{ ");
+ for (idx=0; idx<len; idx++) {
+ dnprintf(50, "%s0x%.2x", idx ? ", " : "", buf[idx]);
+ }
+ dnprintf(50, " }\n");
+}
void
aml_showvalue(struct aml_value *value)
@@ -363,6 +373,8 @@ aml_showvalue(struct aml_value *value)
if (value == NULL)
return;
+ if (value->name)
+ dnprintf(50, "name:%s ", value->name);
switch (value->type) {
case AML_OBJTYPE_INTEGER:
dnprintf(50, "integer: %x\n", value->v_integer);
@@ -371,11 +383,8 @@ aml_showvalue(struct aml_value *value)
dnprintf(50, "string: %s\n", value->v_string);
break;
case AML_OBJTYPE_BUFFER:
- dnprintf(50, "buffer: %d {\n", value->length);
- for (idx=0; idx<value->length; idx++) {
- dnprintf(50, "%s0x%.2x", (idx ? "," : ""), value->v_buffer[idx]);
- }
- dnprintf(50, "}\n");
+ dnprintf(50, "buffer: %d ", value->length);
+ aml_dump(value->length, value->v_buffer);
break;
case AML_OBJTYPE_PACKAGE:
dnprintf(50, "package: %d {\n", value->length);
@@ -386,11 +395,14 @@ aml_showvalue(struct aml_value *value)
case AML_OBJTYPE_DEBUGOBJ:
dnprintf(50, "debug");
break;
+ case AML_OBJTYPE_MUTEX:
+ dnprintf(50, "mutex : %x\n", value->v_integer);
+ break;
case AML_OBJTYPE_DEVICE:
-#if 0
- xxx
- dnprintf(50, "device: %s", val->v_device->name);
-#endif
+ dnprintf(50, "device\n");
+ break;
+ case AML_OBJTYPE_EVENT:
+ dnprintf(50, "event\n");
break;
case AML_OBJTYPE_PROCESSOR:
dnprintf(50, "cpu: %x,%x,%x\n",
@@ -398,26 +410,40 @@ aml_showvalue(struct aml_value *value)
value->v_processor.proc_addr,
value->v_processor.proc_len);
break;
+ case AML_OBJTYPE_METHOD:
+ dnprintf(50, "method: args=%d, serialized=%d, synclevel=%d\n",
+ AML_METHOD_ARGCOUNT(value->v_method.flags),
+ AML_METHOD_SERIALIZED(value->v_method.flags),
+ AML_METHOD_SYNCLEVEL(value->v_method.flags));
+ break;
case AML_OBJTYPE_FIELDUNIT:
- dnprintf(50, "field: %.4x %x,%x\n",
- value->v_field.ftype,
+ dnprintf(50, "field: access=%x,lock=%x,update=%x type=%6s pos=%.4x len=%.4x\n",
+ AML_FIELD_ACCESS(value->v_field.flags),
+ AML_FIELD_LOCK(value->v_field.flags),
+ AML_FIELD_UPDATE(value->v_field.flags),
+ value->v_field.ftyp,
value->v_field.bitpos,
value->v_field.bitlen);
+ aml_showvalue(value->v_field.ref1);
+ aml_showvalue(value->v_field.ref2);
break;
case AML_OBJTYPE_BUFFERFIELD:
- dnprintf(50, "bufferfield: %.4x %x,%x\n",
- value->v_field.ftype,
+ dnprintf(50, "bufferfield: type=%.4x pos=%.4x len=%.4x ",
+ value->v_field.type,
value->v_field.bitpos,
value->v_field.bitlen);
+ aml_dump(aml_bytelen(value->v_field.bitlen),
+ value->v_field.ref1->v_buffer+aml_bytepos(value->v_field.bitpos));
+ aml_showvalue(value->v_field.ref1);
break;
case AML_OBJTYPE_OPREGION:
- dnprintf(50, "opregion: %s,0x%x,0x%x\n",
+ dnprintf(50, "opregion: %s,0x%llx,0x%x\n",
opregion(value->v_opregion.iospace),
value->v_opregion.iobase,
value->v_opregion.iolen);
break;
default:
- printf("unknown: %d\n", value->type);
+ dnprintf(50, "unknown: %d\n", value->type);
break;
}
}
@@ -445,23 +471,43 @@ struct aml_value *
aml_copyvalue(const struct aml_value *rhs)
{
struct aml_value *rv;
- int idx;
switch (rhs->type) {
case AML_OBJTYPE_INTEGER:
- return aml_allocint(rhs->v_integer);
+ return aml_allocint(rhs->v_integer, rhs->length);
case AML_OBJTYPE_STRING:
- return aml_allocstr(rhs->v_string);
+ return aml_allocvalue(AML_OBJTYPE_STRING,
+ rhs->length,
+ rhs->v_string,
+ "copystr");
case AML_OBJTYPE_BUFFER:
- return aml_allocvalue(rhs->type, rhs->length, rhs->v_buffer, "");
+ return aml_allocvalue(AML_OBJTYPE_BUFFER,
+ rhs->length,
+ rhs->v_buffer,
+ "copybuf");
case AML_OBJTYPE_PACKAGE:
- rv = aml_allocvalue(rhs->type, rhs->length, NULL, "");
- for (idx=0; idx<rv->length; idx++) {
- rv->v_package[idx] = aml_copyvalue(rhs->v_package[idx]);
+ return aml_allocvalue(AML_OBJTYPE_PACKAGE,
+ rhs->length,
+ rhs->v_package,
+ "copypkg");
+
+ case AML_OBJTYPE_BUFFERFIELD:
+ case AML_OBJTYPE_FIELDUNIT:
+ rv = aml_allocvalue(rhs->type, 0, NULL, "field");
+ if (rv != NULL) {
+ rv->name = rhs->name;
+ rv->length = rhs->length;
+ rv->v_field = rhs->v_field;
}
+ return rv;
+
+ default:
+ dnprintf(10,"copy unknown : %x\n", rhs->type);
+ rv = aml_allocvalue(rhs->type, 0, NULL, "any");
+ *rv = *rhs;
break;
}
- return NULL;
+ return rv;
}
/*
@@ -523,54 +569,9 @@ aml_parse_length(struct acpi_context *ctx)
return ival;
}
-int
-aml_parse_fieldlist(struct acpi_context *ctx, struct aml_node *parent)
-{
- u_int16_t flag, type, attr;
- int bitpos, bitlen;
- const char *name;
-
- bitpos = 0;
- flag = parent->flag;
-
- /* Format of flag:
- * bits 00 - 03 : access mode
- * bits 04 - 04 : lock mode
- * bits 05 - 08 : update mode
- * bits 08 - 15 : attribute
- */
- dnprintf(50, "-- parse_fieldlist\n");
- while (ctx->pos < parent->end) {
- bitlen = 0;
- switch (aml_parse_int(ctx, 1)) {
- case 0x00: /* reserved */
- bitlen = aml_parse_length(ctx);
- break;
- case 0x01: /* access field */
- type = aml_parse_int(ctx, 1);
- attr = aml_parse_int(ctx, 1);
- dnprintf(50, " type=%.2x attr=%.2x\n", type, attr);
- flag = AML_FIELD_SETATTR(flag, type, attr);
- break;
- default: /* named field */
- --ctx->pos;
- name = aml_parse_name(ctx, "field");
- bitlen = aml_parse_length(ctx);
- aml_create_fieldunit(ctx, parent, name, bitpos, bitlen, flag);
- }
- bitpos += bitlen;
- }
- if (ctx->pos != parent->end) {
- dnprintf(50, "parse_fieldlist: invalid end!\n");
- ctx->pos = parent->end;
- return (1);
- }
- return (0);
-}
-
/* Decode AML Namestring from stream */
const char *
-aml_parse_name(struct acpi_context *ctx, const char *lbl)
+aml_parse_name(struct acpi_context *ctx)
{
int count, pfxlen;
char *name, *pn;
@@ -621,8 +622,6 @@ aml_parse_name(struct acpi_context *ctx, const char *lbl)
}
*pn = 0;
- dnprintf(50, " acpi_name (%s): %s\n", lbl, name);
-
ctx->pos = base;
return name;
@@ -783,141 +782,141 @@ aml_testlogical(u_int16_t opcode, long lhs, long rhs)
return 0;
}
-struct aml_optable aml_table[] = {
+struct aml_opcode aml_table[] = {
/* Simple types */
- { AMLOP_ZERO, "Zero", "!" },
- { AMLOP_ONE, "One", "!" },
- { AMLOP_ONES, "Ones", "!" },
- { AMLOP_BYTEPREFIX, "Byte", "b" },
- { AMLOP_WORDPREFIX, "Word", "w" },
- { AMLOP_DWORDPREFIX, "DWord", "d" },
- { AMLOP_QWORDPREFIX, "QWord", "q" },
- { AMLOP_REVISION, "Revision", "" },
- { AMLOP_STRINGPREFIX, "String", "s" },
- { AMLOP_DEBUG, "DebugOp", "", },
- { AMLOP_BUFFER, "Buffer", "piB" },
- { AMLOP_PACKAGE, "Package", "pbT" },
- { AMLOP_VARPACKAGE, "VarPackage", "piT" },
+ { AMLOP_ZERO, "Zero", "!" },
+ { AMLOP_ONE, "One", "!" },
+ { AMLOP_ONES, "Ones", "!" },
+ { AMLOP_BYTEPREFIX, "Byte", "b" },
+ { AMLOP_WORDPREFIX, "Word", "w" },
+ { AMLOP_DWORDPREFIX, "DWord", "d" },
+ { AMLOP_QWORDPREFIX, "QWord", "q" },
+ { AMLOP_REVISION, "Revision", "" },
+ { AMLOP_STRINGPREFIX, "String", "s" },
+ { AMLOP_DEBUG, "DebugOp", "", },
+ { AMLOP_BUFFER, "Buffer", "piB" },
+ { AMLOP_PACKAGE, "Package", "pbT" },
+ { AMLOP_VARPACKAGE, "VarPackage", "piT" },
/* Simple objects */
- { 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", "", },
+ { 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", "piT", },
- { AMLOP_BREAK, "Break", "", },
- { AMLOP_CONTINUE, "Continue", "", },
- { AMLOP_RETURN, "Return", "t", },
- { AMLOP_FATAL, "Fatal", "bdi", },
- { AMLOP_NOP, "Nop", "", },
- { AMLOP_BREAKPOINT, "BreakPoint", "", },
+ { AMLOP_IF, "If", "piT", },
+ { AMLOP_ELSE, "Else", "pT", },
+ { AMLOP_WHILE, "While", "piT", },
+ { 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", "t", },
- { AMLOP_DECREMENT, "Decrement", "t", },
- { AMLOP_ADD, "Add", "iit", },
- { AMLOP_SUBTRACT, "Subtract", "iit", },
- { AMLOP_MULTIPLY, "Multiply", "iit", },
- { AMLOP_DIVIDE, "Divide", "iitt", },
- { AMLOP_SHL, "ShiftLeft", "iit", },
- { AMLOP_SHR, "ShiftRight", "iit", },
- { AMLOP_AND, "And", "iit", },
- { AMLOP_NAND, "Nand", "iit", },
- { AMLOP_OR, "Or", "iit", },
- { AMLOP_NOR, "Nor", "iit", },
- { AMLOP_XOR, "Xor", "iit", },
- { AMLOP_NOT, "Not", "it", },
- { AMLOP_MOD, "Mod", "iit", },
- { AMLOP_FINDSETLEFTBIT, "FindSetLeftBit", "it", },
+ { AMLOP_INCREMENT, "Increment", "t", },
+ { AMLOP_DECREMENT, "Decrement", "t", },
+ { AMLOP_ADD, "Add", "iit", },
+ { AMLOP_SUBTRACT, "Subtract", "iit", },
+ { AMLOP_MULTIPLY, "Multiply", "iit", },
+ { AMLOP_DIVIDE, "Divide", "iitt", },
+ { AMLOP_SHL, "ShiftLeft", "iit", },
+ { AMLOP_SHR, "ShiftRight", "iit", },
+ { AMLOP_AND, "And", "iit", },
+ { AMLOP_NAND, "Nand", "iit", },
+ { AMLOP_OR, "Or", "iit", },
+ { AMLOP_NOR, "Nor", "iit", },
+ { AMLOP_XOR, "Xor", "iit", },
+ { AMLOP_NOT, "Not", "it", },
+ { AMLOP_MOD, "Mod", "iit", },
+ { AMLOP_FINDSETLEFTBIT, "FindSetLeftBit", "it", },
{ AMLOP_FINDSETRIGHTBIT, "FindSetRightBit", "it", },
/* 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", },
+ { 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_NAMECHAR, "NameRef", "n" },
- { AMLOP_ALIAS, "Alias", "nN", },
- { AMLOP_NAME, "Name", "Nt", },
- { AMLOP_EVENT, "Event", "N", },
- { AMLOP_MUTEX, "Mutex", "Nb", },
- { AMLOP_DATAREGION, "DataRegion", "Nttt" },
- { AMLOP_OPREGION, "OpRegion", "Nbii" },
- { AMLOP_SCOPE, "Scope", "pNT" },
- { AMLOP_DEVICE, "Device", "pNT" },
- { AMLOP_POWERRSRC, "Power Resource", "pNbwT" },
- { AMLOP_THERMALZONE, "ThermalZone", "pNT" },
- { AMLOP_PROCESSOR, "Processor", "pNbdbT", },
- { AMLOP_METHOD, "Method", "pNfM", },
+ { AMLOP_NAMECHAR, "NameRef", "n" },
+ { AMLOP_ALIAS, "Alias", "nN", },
+ { AMLOP_NAME, "Name", "Nt", },
+ { AMLOP_EVENT, "Event", "N", },
+ { AMLOP_MUTEX, "Mutex", "Nb", },
+ { AMLOP_DATAREGION, "DataRegion", "Nttt" },
+ { AMLOP_OPREGION, "OpRegion", "Nbii" },
+ { AMLOP_SCOPE, "Scope", "pNT" },
+ { AMLOP_DEVICE, "Device", "pNT" },
+ { AMLOP_POWERRSRC, "Power Resource", "pNbwT" },
+ { AMLOP_THERMALZONE, "ThermalZone", "pNT" },
+ { AMLOP_PROCESSOR, "Processor", "pNbdbT", },
+ { AMLOP_METHOD, "Method", "pNfM", },
/* Field operations */
- { AMLOP_FIELD, "Field", "pnfF" },
- { AMLOP_INDEXFIELD, "IndexField", "pntfF" },
- { AMLOP_BANKFIELD, "BankField", "pnnifF" },
- { AMLOP_CREATEFIELD, "CreateField", "tiiN", },
+ { AMLOP_FIELD, "Field", "pnfF" },
+ { AMLOP_INDEXFIELD, "IndexField", "pntfF" },
+ { AMLOP_BANKFIELD, "BankField", "pnnifF" },
+ { AMLOP_CREATEFIELD, "CreateField", "tiiN", },
{ AMLOP_CREATEQWORDFIELD, "CreateQWordField","tiN", },
{ AMLOP_CREATEDWORDFIELD, "CreateDWordField","tiN", },
{ AMLOP_CREATEWORDFIELD, "CreateWordField", "tiN", },
{ AMLOP_CREATEBYTEFIELD, "CreateByteField", "tiN", },
- { AMLOP_CREATEBITFIELD, "CreateBitField", "tiN", },
+ { AMLOP_CREATEBITFIELD, "CreateBitField", "tiN", },
/* Conversion operations */
- { AMLOP_TOINTEGER, "ToInteger", "tt", },
- { AMLOP_TOBUFFER, "ToBuffer", "tt", },
- { AMLOP_TODECSTRING, "ToDecString", "it", },
- { AMLOP_TOHEXSTRING, "ToHexString", "it", },
- { AMLOP_TOSTRING, "ToString", "t", },
- { AMLOP_FROMBCD, "FromBCD", "it", },
- { AMLOP_TOBCD, "ToBCD", "it", },
- { AMLOP_MID, "Mid", "tiit", },
+ { AMLOP_TOINTEGER, "ToInteger", "tt", },
+ { AMLOP_TOBUFFER, "ToBuffer", "tt", },
+ { AMLOP_TODECSTRING, "ToDecString", "it", },
+ { AMLOP_TOHEXSTRING, "ToHexString", "it", },
+ { AMLOP_TOSTRING, "ToString", "t", },
+ { AMLOP_FROMBCD, "FromBCD", "it", },
+ { AMLOP_TOBCD, "ToBCD", "it", },
+ { AMLOP_MID, "Mid", "tiit", },
/* Mutex/Signal operations */
- { AMLOP_ACQUIRE, "Acquire", "tw", },
- { AMLOP_RELEASE, "Release", "t", },
- { AMLOP_SIGNAL, "Signal", "t", },
- { AMLOP_WAIT, "Wait", "ti", },
- { AMLOP_RESET, "Reset", "t", },
+ { AMLOP_ACQUIRE, "Acquire", "tw", },
+ { AMLOP_RELEASE, "Release", "t", },
+ { AMLOP_SIGNAL, "Signal", "t", },
+ { AMLOP_WAIT, "Wait", "ti", },
+ { AMLOP_RESET, "Reset", "t", },
- { AMLOP_INDEX, "Index", "tit", },
- { AMLOP_DEREFOF, "DerefOf", "t", },
- { AMLOP_REFOF, "RefOf", "t", },
- { AMLOP_CONDREFOF, "CondRef", "tt", },
-
- { AMLOP_LOADTABLE, "LoadTable", "tttttt" },
- { AMLOP_STALL, "Stall", "i", },
- { AMLOP_SLEEP, "Sleep", "i", },
- { AMLOP_LOAD, "Load", "nt" },
- { AMLOP_UNLOAD, "Unload", "t" },
- { AMLOP_STORE, "Store", "tt", },
- { AMLOP_CONCAT, "Concat", "ttt" },
- { AMLOP_CONCATRES, "ConcatRes", "ttt" },
- { AMLOP_NOTIFY, "Notify", "ti" },
- { AMLOP_SIZEOF, "Sizeof", "t", },
- { AMLOP_MATCH, "Match", "tbibii", },
- { AMLOP_OBJECTTYPE, "ObjectType", "t", },
- { AMLOP_COPYOBJECT, "CopyObject", "tt" },
+ { AMLOP_INDEX, "Index", "tit", },
+ { AMLOP_DEREFOF, "DerefOf", "t", },
+ { AMLOP_REFOF, "RefOf", "t", },
+ { AMLOP_CONDREFOF, "CondRef", "tt", },
+
+ { AMLOP_LOADTABLE, "LoadTable", "tttttt" },
+ { AMLOP_STALL, "Stall", "i", },
+ { AMLOP_SLEEP, "Sleep", "i", },
+ { AMLOP_LOAD, "Load", "nt" },
+ { AMLOP_UNLOAD, "Unload", "t" },
+ { AMLOP_STORE, "Store", "tt", },
+ { AMLOP_CONCAT, "Concat", "ttt" },
+ { AMLOP_CONCATRES, "ConcatRes", "ttt" },
+ { AMLOP_NOTIFY, "Notify", "ti" },
+ { AMLOP_SIZEOF, "Sizeof", "t", },
+ { AMLOP_MATCH, "Match", "tbibii", },
+ { AMLOP_OBJECTTYPE, "ObjectType", "t", },
+ { AMLOP_COPYOBJECT, "CopyObject", "tt" },
{ 0xFFFF }
};
@@ -926,30 +925,35 @@ struct aml_optable aml_table[] = {
* Some opcodes are multibyte
* Name strings can also be embedded within the stream
*/
-u_int16_t
-aml_getopcode(struct acpi_context *ctx)
+struct aml_opcode *aml_getopcode(struct acpi_context *ctx)
{
- u_int16_t twocode;
- u_int16_t opcode;
+ uint8_t *pc;
+ struct aml_opcode *ptab;
+ uint16_t twocode, opcode;
- /* Check for encoded name */
- if (aml_isnamedop(*ctx->pos)) {
- return AMLOP_NAMECHAR;
+ /* Check if this is a name object */
+ pc = ctx->pos;
+ if (aml_isnamedop(*pc)) {
+ opcode = AMLOP_NAMECHAR;
}
-
- opcode = aml_parse_int(ctx, 1);
- twocode = (opcode << 8L) + *ctx->pos;
-
- /* Check multi-byte opcodes */
- if (twocode == AMLOP_LNOTEQUAL ||
- twocode == AMLOP_LLESSEQUAL ||
- twocode == AMLOP_LGREATEREQUAL ||
- opcode == AMLOP_EXTPREFIX) {
- ctx->pos++;
- return twocode;
+ else {
+ opcode = aml_parse_int(ctx, 1);
+ twocode = (opcode << 8L) + *ctx->pos;
+
+ /* Check multi-byte opcodes */
+ if (twocode == AMLOP_LNOTEQUAL ||
+ twocode == AMLOP_LLESSEQUAL ||
+ twocode == AMLOP_LGREATEREQUAL ||
+ opcode == AMLOP_EXTPREFIX) {
+ opcode = twocode;
+ ctx->pos++;
+ }
}
-
- return opcode;
+ for (ptab = aml_table; ptab->opcode != 0xFFFF; ptab++) {
+ if (ptab->opcode == opcode)
+ return ptab;
+ }
+ return NULL;
}
struct aml_node *
@@ -980,39 +984,6 @@ aml_match(int64_t lhs, int mtype, int64_t rhs)
return (0);
}
-void
-aml_addchildnode(struct aml_node *parent, struct aml_node *child)
-{
- struct aml_node *psib;
-
- child->parent = parent;
- child->sibling = NULL;
- for (psib = parent->child; psib; psib = psib->sibling) {
- if (psib->sibling == NULL) {
- psib->sibling = child;
- return;
- }
- }
- parent->child = child;
-}
-
-struct aml_node *
-aml_create_node(struct acpi_context *ctx, struct aml_node *parent, int opcode, const char *mnem)
-{
- struct aml_node *node;
-
- node = acpi_os_allocmem(sizeof(struct aml_node));
- memset(node, 0, sizeof(struct aml_node));
-
- node->depth = parent->depth+1;
- node->start = ctx->pos;
- node->opcode = opcode;
- node->mnem = mnem;
- aml_addchildnode(parent, node);
-
- return node;
-}
-
struct aml_node *
aml_find_name(struct acpi_softc *sc, struct aml_node *root, const char *name)
{
@@ -1054,7 +1025,7 @@ aml_eval_name(struct acpi_softc *sc, struct aml_node *root, const char *name,
if (root != NULL) {
dnprintf(50, "found eval object : %s, %.4x\n", root->name, root->opcode);
- return aml_eval_object(sc, root, result, env);
+ return aml_eval_object(sc, root, result, 0, env);
}
return (1);
}
@@ -1103,542 +1074,1028 @@ aml_bufcpy(u_int8_t *pDst, int dstPos, const u_int8_t *pSrc, int srcPos,
}
}
-void
-aml_create_fieldunit(struct acpi_context *ctx, struct aml_node *parent, const char *name, int bitpos, int bitlen, int flags)
+struct aml_value *aml_econcat(struct acpi_context *ctx);
+struct aml_value *aml_ederef(struct acpi_context *ctx, struct aml_value *val);
+void aml_resizeval(struct aml_value *pv, int newlen);
+int aml_parse_length(struct acpi_context *ctx);
+struct aml_value *aml_edebugobj;
+struct aml_value *aml_eparseval(struct acpi_context *ctx);
+struct aml_opcode *aml_getopcode(struct acpi_context *ctx);
+struct aml_value *aml_domethod(struct acpi_context *ctx, struct aml_value *val);
+struct aml_value *aml_esetnodevalue(struct acpi_context *ctx, struct aml_value *lhs,
+ struct aml_value *rhs, int64_t rval);
+struct aml_value *aml_eparselist(struct acpi_context *ctx, uint8_t *end);
+
+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_doif(struct acpi_context *ctx);
+struct aml_value *aml_eparsescope(struct acpi_context *ctx, const char *name, uint8_t *end,
+ struct aml_opcode *opc);
+struct aml_value *aml_dowhile(struct acpi_context *ctx);
+int64_t aml_eparseint(struct acpi_context *ctx);
+struct aml_value *aml_efieldunit(struct acpi_context *ctx, int opcode);
+struct aml_value *aml_ebufferfield(struct acpi_context *ctx, int bitlen, int size, int opcode);
+uint8_t *aml_eparselen(struct acpi_context *ctx);
+struct aml_value *aml_eparseref(struct acpi_context *ctx);
+int64_t aml_val2int(struct acpi_context *ctx, struct aml_value *val);
+struct aml_value *aml_efield(struct acpi_context *ctx, struct aml_value *e_fld,
+ struct aml_value *rhs);
+struct aml_value *aml_val2buf(struct acpi_context *ctx, struct aml_value *val);
+void aml_addvname(struct acpi_context *ctx, const char *name, int opcode,
+ struct aml_value *val);
+struct aml_value *aml_eparsenode(struct acpi_context *ctx, struct aml_node *node);
+void aml_delchildren(struct acpi_context *ctx, struct aml_node *node);
+struct aml_value *aml_doloadtable(struct acpi_context *ctx);
+struct aml_value *aml_domatch(struct acpi_context *ctx);
+
+/* Search list of objects for a name match
+ * Special case for fields: search children only
+ */
+struct aml_node *_aml_searchname(struct aml_node *list, const char *name)
{
- struct aml_node *pfield;
+ struct aml_node *child;
- dnprintf(50, "create_fieldunit: name=%s bitpos=%.8x bitlen=%.8x\n", name, bitpos, bitlen);
-
- pfield = aml_create_node(ctx, parent, AMLOP_FIELDUNIT, "fieldunit");
- if (pfield == NULL)
- return;
-
- pfield->name = name;
-
- /* Setup Field Unit object: point to OpRegion NameRef in parent field */
- pfield->value = aml_allocvalue(AML_OBJTYPE_FIELDUNIT, 0, NULL, "FieldUnit");
- if (pfield->value != NULL) {
- pfield->value->length = aml_bytelen(bitlen);
- pfield->value->v_field.flags = flags;
- pfield->value->v_field.ftype = parent->opcode;
- pfield->value->v_field.bitpos = bitpos;
- pfield->value->v_field.bitlen = bitlen;
- pfield->value->v_field.ref = childOf(parent, 0);
-
- switch (AML_FIELD_ACCESS(flags)) {
- case AML_FIELD_ANYACC:
- case AML_FIELD_BYTEACC:
- pfield->value->v_field.acc_size = 1;
- break;
- case AML_FIELD_WORDACC:
- pfield->value->v_field.acc_size = 2;
- break;
- case AML_FIELD_DWORDACC:
- pfield->value->v_field.acc_size = 4;
- break;
- default:
- dnprintf(50, "aml_createfieldunit: invalid field access size: %x\n",
- AML_FIELD_ACCESS(flags));
- break;
+ if (list == NULL) {
+ return NULL;
+ }
+ while (list) {
+ if (list->opcode == AMLOP_FIELD ||
+ list->opcode == AMLOP_BANKFIELD ||
+ list->opcode == AMLOP_INDEXFIELD) {
+ if ((child = _aml_searchname(list->child, name)) != NULL) {
+ return child;
+ }
}
+ if (list->name && !strncmp(list->name, name, AML_NAMESEG_LEN)) {
+ return list;
+ }
+ list = list->sibling;
}
+ return NULL;
}
-void
-aml_create_bufferunit(struct acpi_context *ctx, struct aml_node *node, int bitlen, int size)
+/* Create name references in tree, even if not initialized */
+struct aml_node *aml_doname(struct aml_node *root, const char *name, int create)
{
- /* ASSERT: node->value is NULL */
- node->value = aml_allocvalue(AML_OBJTYPE_BUFFERFIELD, 0, NULL, "bufferunit");
- if (node->value != NULL) {
- if (bitlen == -1) {
- /* AMLOP_CREATEFIELD: decode bitlength */
- bitlen = _aml_evalint(ctx, childOf(node, 2));
+ struct aml_node *tmp;
+
+ if (*name == AMLOP_ROOTCHAR) {
+ name++;
+ root = &aml_root;
+ }
+ while (*name == AMLOP_PARENTPREFIX) {
+ name++;
+ if ((root = root->parent) == NULL) {
+ return NULL;
}
- node->value->length = aml_bytelen(bitlen);
- node->value->v_field.flags = 0;
- node->value->v_field.ftype = node->opcode;
- node->value->v_field.bitpos = _aml_evalint(ctx, childOf(node, 1)) * size;
- node->value->v_field.bitlen = bitlen;
- node->value->v_field.ref = childOf(node, 0);
- node->value->v_field.acc_size = 1;
+ }
+ if (root == NULL) {
+ root = &aml_root;
+ }
+ if (*name && name[AML_NAMESEG_LEN] == '\0' && !create) {
+ do {
+ tmp = _aml_searchname(root->child, name);
+ root = root->parent;
+ } while (tmp == NULL && root != NULL);
+ return tmp;
+ }
+
+ for (tmp = root; tmp && *name; name += AML_NAMESEG_LEN) {
+ if (*name == '.') name++;
+
+ tmp = _aml_searchname(root->child, name);
- dnprintf(50, "create_bufferunit: name=%s pos=%.8x len=%.8x\n",
- node->name, node->value->v_field.bitpos,
- node->value->v_field.bitlen);
+ /* Create name if queried */
+ if (tmp == NULL && create) {
+ tmp = aml_create_node(root, -1, "DUMMY", root->start);
+ if (tmp != NULL) {
+ tmp->name = acpi_os_allocmem(AML_NAMESEG_LEN+1);
+ if (tmp->name) {
+ memcpy((char *)tmp->name, name, AML_NAMESEG_LEN);
+ }
+ }
+ }
+ root = tmp;
}
+ return tmp;
}
-/* Copy to/from a buffer object */
-struct aml_value *
-aml_bufferio(struct acpi_context *ctx, struct aml_value *pfield, struct aml_value *rhs)
+struct aml_node *aml_createname(struct aml_node *root, const char *name)
{
- struct aml_value *pbuf, *rv;
+ return aml_doname(root, name, 1);
+}
- /* ASSERT: pfield is AML_OBJTYPE_BUFFERFIELD */
- pbuf = aml_evalnode(ctx, pfield->v_field.ref);
- if (pbuf->type != AML_OBJTYPE_BUFFERFIELD) {
- dnprintf(50, "Invalid bufferio!\n");
+struct aml_node *aml_searchname(struct aml_node *root, const char *name)
+{
+ return aml_doname(root, name, 0);
+}
+
+struct aml_value *aml_ederef(struct acpi_context *ctx, struct aml_value *val)
+{
+ struct aml_node *pn;
+ struct aml_value *ref;
+ int64_t i1;
+
+ if (val == NULL) {
return NULL;
}
- if (rhs == NULL) {
- /* Return buffer object */
- rv = aml_allocvalue(AML_OBJTYPE_BUFFER, pfield->length, NULL, "bufferio");
- if (rv != NULL) {
- aml_bufcpy(rv->v_buffer, 0, pbuf->v_buffer,
- pfield->v_field.bitpos,
- pfield->v_field.bitlen);
+ switch (val->type) {
+ case AML_OBJTYPE_NAMEREF:
+ if (val->v_objref.ref == NULL) {
+ if ((pn = aml_searchname(ctx->scope, val->name)) != NULL) {
+ val->v_objref.ref = pn->value;
+ }
}
- aml_freevalue(pbuf);
- return rv;
- }
+ if (val->v_objref.ref != NULL) {
+ return aml_ederef(ctx, val->v_objref.ref);
+ }
+ return NULL;
+ case AML_OBJTYPE_OBJREF:
+ i1 = val->v_objref.index;
+ ref = aml_ederef(ctx, val->v_objref.ref);
- switch (rhs->type) {
- case AML_OBJTYPE_INTEGER:
- aml_bufcpy(pbuf->v_buffer, pfield->v_field.bitpos, (u_int8_t *)&rhs->v_integer, 0,
- pfield->v_field.bitlen);
- break;
- case AML_OBJTYPE_BUFFER:
- aml_bufcpy(pbuf->v_buffer, pfield->v_field.bitpos, rhs->v_buffer, 0,
- pfield->v_field.bitlen);
+ if (i1 == -1) {
+ return aml_ederef(ctx, ref);
+ }
+ if (i1 > ref->length) {
+ aml_resizeval(ref, i1);
+ }
+ switch (ref->type) {
+ case AML_OBJTYPE_PACKAGE:
+#if 1
+ if (ref->v_package[i1] == NULL) {
+ /* Lazy allocate package */
+ dnprintf(10, "LazyPkg: %lld/%d\n", i1, ref->length);
+ ref->v_package[i1] = aml_allocint(0, 0);
+ }
+#endif
+ return ref->v_package[i1];
+ case AML_OBJTYPE_BUFFER:
+ return aml_allocvalue(AML_OBJTYPE_BUFFERFIELD, 8, ref->v_buffer+i1, "test");
+ default:
+ dnprintf(50,"Unknown refof\n");
+ }
break;
- default:
- dnprintf(50, "invalid type to bufferio\n");
}
- return NULL;
+ return val;
+}
+
+struct aml_value *aml_eparseref(struct acpi_context *ctx)
+{
+ struct aml_value *lhs, *rhs;
+
+ lhs = aml_eparseval(ctx);
+ rhs = aml_ederef(ctx, lhs);
+ if (lhs != rhs) {
+ aml_freevalue(&lhs);
+ }
+ return rhs;
}
-/* Copy to/from a field object */
struct aml_value *
-aml_fieldio(struct acpi_context *ctx, struct aml_value *pfield, struct aml_value *rhs)
+aml_efield(struct acpi_context *ctx, struct aml_value *e_fld,
+ struct aml_value *rhs)
{
- struct aml_value *pbuf, *rv;
+ struct aml_value *e_rgn;
+ struct aml_value *rv;
+ struct aml_value tmp;
+
+ dnprintf(10, "efield %s: ", rhs ? "set" : "get");
+ aml_showvalue(e_fld);
+ aml_showvalue(rhs);
- switch (pfield->v_field.ftype) {
+ tmp.type = AML_OBJTYPE_INTEGER;
+ switch (e_fld->v_field.type) {
case AMLOP_INDEXFIELD:
- /* Write bit offset to INDEX register
- INDEX is childOf(pfield->v_field.ref, 0)
- DATA is childOf(pfield->v_field.ref, 1)
- */
- _aml_setnodevalue(ctx, childOf(pfield->v_field.ref, 0), 0, pfield->v_field.bitpos);
- if (rhs == NULL) {
- return aml_evalnode(ctx, childOf(pfield->v_field.ref, 1));
+ /* Set INDEX value to FIELD position byte, then write RHS to DATA */
+ if (e_fld->v_field.bitpos & 7) {
+ dnprintf(10, "aml_efield: INDEXFIELD not byte-aligned..\n");
}
- return _aml_setnodevalue(ctx, childOf(pfield->v_field.ref, 1), rhs, 0);
+ tmp.v_integer = e_fld->v_field.bitpos >> 3;
+ aml_efield(ctx, e_fld->v_field.ref1, &tmp);
+ return aml_efield(ctx, e_fld->v_field.ref2, rhs);
case AMLOP_BANKFIELD:
- return NULL;
+ /* Set bank value */
+ tmp.v_integer = e_fld->v_field.ref3;
+ aml_efield(ctx, e_fld->v_field.ref2, &tmp);
+ return aml_efield(ctx, e_fld->v_field.ref2, rhs);
case AMLOP_FIELD:
+ /* e_rgn should be OPREGION */
+ e_rgn = aml_ederef(ctx, e_fld->v_field.ref1);
+ if (e_rgn->type != AML_OBJTYPE_OPREGION) {
+ dnprintf(10, "aml_efield: Wrong FIELD type!\n");
+ return NULL;
+ }
+ if (AML_FIELD_LOCK(e_fld->v_field.flags)) {
+ acpi_mutex_acquire(ctx, aml_global_lock, -1);
+ }
+ rv = aml_allocvalue(AML_OBJTYPE_BUFFER, aml_bytelen(e_fld->v_field.bitlen), NULL, 0);
+ if (rhs == NULL) {
+ /* Read field */
+ if (rv != NULL) {
+ acpi_gasio(ctx->sc, ACPI_IOREAD,
+ e_rgn->v_opregion.iospace,
+ e_rgn->v_opregion.iobase + aml_bytepos(e_fld->v_field.bitpos),
+ AML_FIELD_ACCESS(e_fld->v_field.flags),
+ aml_bytelen(e_fld->v_field.bitlen), rv->v_buffer);
+ }
+ if (AML_FIELD_LOCK(e_fld->v_field.flags)) {
+ acpi_mutex_release(ctx, aml_global_lock);
+ }
+ return rv;
+ }
+
+ /* Write field */
+ rhs = aml_val2buf(ctx, rhs);
+ aml_showvalue(rhs);
+
+ switch (AML_FIELD_UPDATE(e_fld->v_field.flags)) {
+ case AML_FIELD_PRESERVE:
+ /* XXX: fix length, don't read if whole length */
+ dnprintf(10, "old iobase = %llx,%lx\n", e_rgn->v_opregion.iobase, aml_bytepos(e_fld->v_field.bitpos));
+ acpi_gasio(ctx->sc, ACPI_IOREAD,
+ e_rgn->v_opregion.iospace,
+ e_rgn->v_opregion.iobase + aml_bytepos(e_fld->v_field.bitpos),
+ AML_FIELD_ACCESS(e_fld->v_field.flags),
+ aml_bytelen(e_fld->v_field.bitlen), rv->v_buffer);
+ aml_showvalue(rv);
+ break;
+ case AML_FIELD_WRITEASONES:
+ memset(rv->v_buffer, 0xFF, rv->length);
+ break;
+ case AML_FIELD_WRITEASZEROES:
+ memset(rv->v_buffer, 0x00, rv->length);
+ break;
+ }
+ aml_bufcpy(rv->v_buffer, e_fld->v_field.bitpos,
+ rhs->v_buffer, 0,
+ e_fld->v_field.bitlen);
+ acpi_gasio(ctx->sc, ACPI_IOWRITE,
+ e_rgn->v_opregion.iospace,
+ e_rgn->v_opregion.iobase + aml_bytepos(e_fld->v_field.bitpos),
+ AML_FIELD_ACCESS(e_fld->v_field.flags),
+ aml_bytelen(e_fld->v_field.bitlen), rv->v_buffer);
+ if (AML_FIELD_LOCK(e_fld->v_field.flags)) {
+ acpi_mutex_release(ctx, aml_global_lock);
+ }
break;
+ default:
+ /* This is a buffer field */
+ e_rgn = aml_ederef(ctx, e_fld->v_field.ref1);
+ if (e_rgn->type != AML_OBJTYPE_BUFFER) {
+ dnprintf(10, "aml_efield: Wrong type!\n");
+ return NULL;
+ }
+ if (rhs == NULL) {
+ /* Read buffer */
+ rv = aml_allocvalue(AML_OBJTYPE_BUFFER, aml_bytelen(e_fld->v_field.bitlen),
+ NULL, 0);
+ if (rv != NULL) {
+ aml_bufcpy(rv->v_buffer, 0,
+ e_rgn->v_buffer, e_fld->v_field.bitpos,
+ e_fld->v_field.bitlen);
+ }
+ return rv;
+ }
+ /* Write buffer */
+ rhs = aml_val2buf(ctx, rhs);
+ aml_bufcpy(e_rgn->v_buffer, e_fld->v_field.bitpos,
+ rhs->v_buffer, 0,
+ e_fld->v_field.bitlen);
+ break;
}
- /* ASSERT: pfield is AML_OBJTYPE_FIELDUNIT */
- pbuf = aml_evalnode(ctx, pfield->v_field.ref);
- if (pbuf->type != AML_OBJTYPE_OPREGION) {
- dnprintf(50, "Invalid fieldio!\n");
+ return NULL;
+}
+
+struct aml_value *
+aml_val2buf(struct acpi_context *ctx, struct aml_value *val)
+{
+ if (val == NULL)
return NULL;
+ switch (val->type) {
+ case AML_OBJTYPE_BUFFER:
+ return val;
+ case AML_OBJTYPE_BUFFERFIELD:
+ case AML_OBJTYPE_FIELDUNIT:
+ return aml_efield(ctx, val, NULL);
+ case AML_OBJTYPE_NAMEREF:
+ return aml_val2buf(ctx, aml_ederef(ctx, val));
+ case AML_OBJTYPE_INTEGER:
+ return aml_allocvalue(AML_OBJTYPE_BUFFER, 8, &val->v_integer, "");
+ case AML_OBJTYPE_STRING:
+ return aml_allocvalue(AML_OBJTYPE_BUFFER, val->length, val->v_string, "");
+ default:
+ dnprintf(10, "Unknown val2buf : %d\n", val->type);
+ return NULL;
+ }
+}
+
+int64_t
+aml_val2int(struct acpi_context *ctx, struct aml_value *val)
+{
+ int64_t rval;
+
+ if (val == NULL) {
+ dnprintf(10, "null val2int\n");
+ return 0;
}
-
- /* Allocate large enough buffer to hold size bytes */
- rv = aml_allocvalue(AML_OBJTYPE_BUFFER, pfield->length, NULL, "bufferio");
- if (rhs == NULL) {
- /* Return buffer object */
- if (rv != NULL) {
- /* Copy data from field object */
- acpi_gasio(ctx->sc, ACPI_IOREAD,
- pbuf->v_opregion.iospace,
- pbuf->v_opregion.iobase + aml_bytepos(pfield->v_field.bitpos),
- pfield->v_field.acc_size, rv->length,
- rv->v_buffer);
- }
- aml_freevalue(pbuf);
- return rv;
- }
-
- /* Check how we should write nonaligned bits */
- switch (AML_FIELD_UPDATE(pfield->v_field.flags)) {
- case AML_FIELD_PRESERVE:
- /* XXX: don't need to read old bits if new bits == length */
- acpi_gasio(ctx->sc, ACPI_IOREAD,
- pbuf->v_opregion.iospace,
- pbuf->v_opregion.iobase + aml_bytepos(pfield->v_field.bitpos),
- pfield->v_field.acc_size, rv->length,
- rv->v_buffer);
+ switch (val->type) {
+ case AML_OBJTYPE_BUFFER:
+ rval = 0;
+ if (val->length < 8) {
+ memcpy(&rval, val->v_buffer, val->length);
+ }
+ return rval;
+ case AML_OBJTYPE_INTEGER:
+ return val->v_integer;
+ case AML_OBJTYPE_STRING:
+/* XXX: fix me
+
+if (val->v_string == NULL) {
+rval = 0;
+}
+else if (!strncmp(val->v_string, "0x", 2)) {
+sscanf(val->v_string+2, "%Lx", &rval);
+}
+else {
+rval = strtol(val->v_string);
+}
+*/
+ return rval;
+ case AML_OBJTYPE_NAMEREF:
+ case AML_OBJTYPE_OBJREF:
+ val = aml_ederef(ctx, val);
break;
- case AML_FIELD_WRITEASONES:
- memset(rv->v_buffer, 0xFF, rv->length);
+ case AML_OBJTYPE_BUFFERFIELD:
+ case AML_OBJTYPE_FIELDUNIT:
+ val = aml_efield(ctx, val, NULL);
break;
- case AML_FIELD_WRITEASZEROES:
- memset(rv->v_buffer, 0x00, rv->length);
+ case AML_OBJTYPE_METHOD:
+ val = aml_domethod(ctx, val);
break;
+ default:
+ dnprintf(10, "Unknown val2int: %x\n", val->type);
+ return 0x0;
}
- return pbuf;
+ return aml_val2int(ctx, val);
}
-struct aml_value *
-_aml_setnodevalue(struct acpi_context *ctx, struct aml_node *node, struct aml_value *rhs, uint64_t ival)
+void
+aml_addvname(struct acpi_context *ctx, const char *name, int opcode,
+ struct aml_value *val)
{
- if (node == NULL) {
- dnprintf(50, "aml_setnodevalue: invalid node!\n");
- return NULL;
+ struct aml_node *pn;
+
+ val->name = name;
+ val->refcnt = -1;
+ pn = aml_createname(ctx->scope, name);
+ if (pn != NULL) {
+ pn->opcode = opcode;
+ if (!pn->value) {
+ pn->value = val;
+ }
+ aml_showvalue(val);
}
+ dnprintf(10, "\n");
+}
- /* Integer value passed in */
- if (rhs == NULL)
- rhs = aml_allocint(ival);
+/* Parse package length & return pointer to end of package */
+uint8_t *
+aml_eparselen(struct acpi_context *ctx)
+{
+ uint8_t *pos = ctx->pos;
- dnprintf(50, "aml_setnodevalue: ");
- aml_shownode(node);
- aml_showvalue(rhs);
+ return pos + aml_parse_length(ctx);
+}
- return rhs;
+/* Return integer value */
+int64_t
+aml_eparseint(struct acpi_context *ctx)
+{
+ struct aml_value *rv;
+ int64_t rval;
+
+ rv = aml_eparseval(ctx);
+ rval = aml_val2int(ctx, rv);
+ aml_freevalue(&rv);
+
+ return rval;
}
+/* Create field unit
+ * AMLOP_FIELD
+ * AMLOP_INDEXFIELD
+ * AMLOP_BANKFIELD
+ */
+#define AML_FIELD_RESERVED 0x00
+#define AML_FIELD_ATTRIB 0x01
+
struct aml_value *
-aml_getnodevalue(struct acpi_context *ctx, struct aml_node *node)
+aml_efieldunit(struct acpi_context *ctx, int opcode)
{
- u_int64_t i1, i2;
+ uint8_t *end;
+ int attr, access;
+ struct aml_value *rv, tmp;
- if (node->value != NULL) {
- node->value->refcnt++;
- return node->value;
+ /* Create field template */
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = AML_OBJTYPE_FIELDUNIT;
+ tmp.v_field.type = opcode;
+
+ end = aml_eparselen(ctx);
+ switch (opcode) {
+ case AMLOP_FIELD:
+ tmp.v_field.ftyp = "field";
+ tmp.v_field.ref1 = aml_eparseval(ctx);
+ break;
+ case AMLOP_INDEXFIELD:
+ tmp.v_field.ftyp = "index";
+ tmp.v_field.ref1 = aml_eparseval(ctx);
+ tmp.v_field.ref2 = aml_eparseval(ctx);
+ break;
+ case AMLOP_BANKFIELD:
+ tmp.v_field.ftyp = "bank";
+ tmp.v_field.ref1 = aml_eparseval(ctx);
+ tmp.v_field.ref2 = aml_eparseval(ctx);
+ tmp.v_field.ref3 = aml_eparseint(ctx);
+ break;
}
+ tmp.v_field.flags = aml_parse_int(ctx, 1);
- switch (node->opcode) {
- case AMLOP_LOCAL0:
- case AMLOP_LOCAL1:
- case AMLOP_LOCAL2:
- case AMLOP_LOCAL3:
- case AMLOP_LOCAL4:
- case AMLOP_LOCAL5:
- case AMLOP_LOCAL6:
- case AMLOP_LOCAL7:
- i1 = node->opcode - AMLOP_LOCAL0;
- if (ctx->stack) {
- node->value = &ctx->stack->locals[i1];
+ while (ctx->pos < end) {
+ switch (*ctx->pos) {
+ case AML_FIELD_RESERVED:
+ ctx->pos++;
+ tmp.v_field.bitlen = aml_parse_length(ctx);
+ break;
+ case AML_FIELD_ATTRIB:
+ ctx->pos++;
+ access = aml_parse_int(ctx, 1);
+ attr = aml_parse_int(ctx, 1);
+
+ tmp.v_field.flags &= ~AML_FIELD_ACCESSMASK;
+ tmp.v_field.flags |= (access & AML_FIELD_ACCESSMASK);
+ break;
+ default:
+ tmp.name = aml_parse_name(ctx);
+ tmp.v_field.bitlen = aml_parse_length(ctx);
+ rv = aml_copyvalue(&tmp);
+ if (rv != NULL) {
+ aml_addvname(ctx, tmp.name, opcode, rv);
+ }
+ break;
}
- break;
+ tmp.v_field.bitpos += tmp.v_field.bitlen;
+ }
+ return NULL;
+}
- case AMLOP_ARG0:
- case AMLOP_ARG1:
- case AMLOP_ARG2:
- case AMLOP_ARG3:
- case AMLOP_ARG4:
- case AMLOP_ARG5:
- case AMLOP_ARG6:
- i1 = node->opcode - AMLOP_ARG0;
- if (ctx->stack) {
- node->value = &ctx->stack->args[i1];
+/*
+ * Create buffer field object
+ *
+ * AMLOP_CREATEFIELD
+ * AMLOP_CREATEBITFIELD
+ * AMLOP_CREATEBYTEFIELD
+ * AMLOP_CREATEWORDFIELD
+ * AMLOP_CREATEDWORDFIELD
+ * AMLOP_CREATEQWORDFIELD
+ */
+struct aml_value *
+aml_ebufferfield(struct acpi_context *ctx, int bitlen, int size, int opcode)
+{
+ struct aml_value *rv;
+
+ rv = aml_allocvalue(AML_OBJTYPE_BUFFERFIELD, 0, NULL, "createbf");
+ if (rv != NULL) {
+ rv->v_field.type = opcode;
+ rv->v_field.ref1 = aml_eparseval(ctx);
+ rv->v_field.bitpos = aml_eparseint(ctx) * size;
+ if (opcode == AMLOP_CREATEFIELD) {
+ bitlen = aml_eparseint(ctx);
+ }
+ rv->name = aml_parse_name(ctx);
+ rv->v_field.bitlen = bitlen;
+
+ aml_addvname(ctx, rv->name, opcode, rv);
+ }
+ return rv;
+}
+
+/* Set node value */
+struct aml_value *
+aml_esetnodevalue(struct acpi_context *ctx, struct aml_value *lhs,
+ struct aml_value *rhs, int64_t rval)
+{
+ struct aml_value *tmp;
+
+ if (rhs == NULL) {
+ rhs = aml_allocint(rval, 0);
+ }
+
+ /* Eval RHS */
+ switch (rhs->type) {
+ case AML_OBJTYPE_FIELDUNIT:
+ case AML_OBJTYPE_BUFFERFIELD:
+ rhs = aml_efield(ctx, rhs, NULL);
+ break;
+ case AML_OBJTYPE_NAMEREF:
+ case AML_OBJTYPE_OBJREF:
+ tmp = aml_ederef(ctx, rhs);
+ if (tmp == rhs) {
+ dnprintf(10, "No deref!\n");
}
+ rhs = tmp;
break;
+ }
- case AMLOP_CREATEFIELD:
- aml_create_bufferunit(ctx, node, -1, 1);
+ /* Eval LHS */
+ switch (lhs->type) {
+ case AML_OBJTYPE_INTEGER:
+ if (lhs->length == 0) {
+ lhs->v_integer = aml_val2int(ctx, rhs);
+ }
break;
- case AMLOP_CREATEBITFIELD:
- aml_create_bufferunit(ctx, node, 1, 1);
+ case AML_OBJTYPE_STRING:
+ if (rhs->type != AML_OBJTYPE_STRING) {
+ dnprintf(10, "no string...\n");
+ }
+ else {
+ lhs->length = rhs->length;
+ lhs->v_string = rhs->v_string;
+ }
break;
- case AMLOP_CREATEBYTEFIELD:
- aml_create_bufferunit(ctx, node, 8, 8);
+ case AML_OBJTYPE_BUFFER:
+ rhs = aml_val2buf(ctx, rhs);
+ lhs->length = rhs->length;
+ lhs->v_buffer = rhs->v_buffer;
break;
- case AMLOP_CREATEWORDFIELD:
- aml_create_bufferunit(ctx, node, 16, 8);
+ case AML_OBJTYPE_BUFFERFIELD:
+ case AML_OBJTYPE_FIELDUNIT:
+ aml_efield(ctx, lhs, rhs);
break;
- case AMLOP_CREATEDWORDFIELD:
- aml_create_bufferunit(ctx, node, 32, 8);
+ case AML_OBJTYPE_UNINITIALIZED:
+ *lhs = *rhs;
break;
- case AMLOP_CREATEQWORDFIELD:
- aml_create_bufferunit(ctx, node, 64, 8);
+ case AML_OBJTYPE_OBJREF:
+ rhs = aml_esetnodevalue(ctx, aml_ederef(ctx, lhs), rhs, 0);
break;
-
- case AMLOP_DEBUG:
- node->value = aml_allocvalue(AML_OBJTYPE_DEBUGOBJ, 0, NULL, "debugobj");
+ case AML_OBJTYPE_DEBUGOBJ:
+ //aml_freevalue(&lhs->v_debug);
+ //lhs->v_debug = aml_copyvalue(rhs);
break;
+ default:
+ dnprintf(10, "Unknown set value: %x\n", lhs->type);
+ }
- case AMLOP_BUFFER:
- /* Requested length of buffer can be greater than supplied bytes */
- i1 = _aml_evalint(ctx, childOf(node, 0));
- i2 = node->end - node->start;
-
- dnprintf(50, "allocate buffer: %d/%d\n", i2, i1);
- node->value = aml_allocvalue(AML_OBJTYPE_BUFFER, i1, NULL, "buffer");
- if (node->value && i2 > 0) {
- memcpy(node->value->v_buffer, node->start, i2);
+ return rhs;
+}
+
+/* Parse list of objects */
+struct aml_value *aml_eparselist(struct acpi_context *ctx, uint8_t *end)
+{
+ struct aml_value *rv;
+
+ rv = NULL;
+ while (ctx->pos && ctx->pos < end) {
+ aml_freevalue(&rv);
+ rv = aml_eparseval(ctx);
+ }
+ return rv;
+}
+
+/* Concatenate results */
+struct aml_value *aml_econcat(struct acpi_context *ctx)
+{
+ struct aml_value *lhs, *rhs, *set, *tmp;
+
+ lhs = aml_eparseval(ctx);
+ rhs = aml_eparseval(ctx);
+ set = aml_eparseval(ctx);
+ if (lhs == NULL || rhs == NULL || lhs->type != rhs->type) {
+ return NULL;
+ }
+ switch (lhs->type) {
+ case AML_OBJTYPE_STRING:
+ tmp = aml_allocvalue(AML_OBJTYPE_STRING,
+ lhs->length+rhs->length, NULL, "concat");
+ if (tmp != NULL) {
+ strlcpy(tmp->v_string, lhs->v_string, lhs->length);
+ strlcat(tmp->v_string, rhs->v_string, rhs->length);
+ return aml_esetnodevalue(ctx, set, tmp, 0);
}
break;
-
- case AMLOP_PACKAGE:
- case AMLOP_VARPACKAGE:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- dnprintf(50, "allocate package: %d\n", i1);
- node->value = aml_allocvalue(AML_OBJTYPE_PACKAGE, i1, NULL, "package");
- for (i2=0; node->value && i2 < i1; i2++) {
- node->value->v_package[i2] = aml_evalnode(ctx, childOf(node, 1+i2));
+ case AML_OBJTYPE_BUFFER:
+ tmp = aml_allocvalue(AML_OBJTYPE_BUFFER,
+ lhs->length+rhs->length, NULL, "concat");
+ if (tmp != NULL) {
+ memcpy(tmp->v_buffer, lhs->v_buffer, lhs->length);
+ memcpy(tmp->v_buffer+lhs->length, rhs->v_buffer, rhs->length);
+ return aml_esetnodevalue(ctx, set, tmp, 0);
}
break;
+ }
+ return NULL;
+}
- case AMLOP_OPREGION:
- node->value = aml_allocvalue(AML_OBJTYPE_OPREGION, 0, NULL, "opregion");
- if (node->value != NULL) {
- node->value->v_opregion.iospace = _aml_evalint(ctx, childOf(node, 0));
- node->value->v_opregion.iobase = _aml_evalint(ctx, childOf(node, 1));
- node->value->v_opregion.iolen = _aml_evalint(ctx, childOf(node, 2));
- dnprintf(50, "allocate opregion; %x %llx %x\n",
- node->value->v_opregion.iospace,
- node->value->v_opregion.iobase,
- node->value->v_opregion.iolen);
+struct aml_value *aml_eparsescope(struct acpi_context *ctx, const char *name, uint8_t *end,
+ struct aml_opcode *opc)
+{
+ struct aml_node *oldscope;
+ struct aml_value *rv;
+
+ oldscope = ctx->scope;
+ ctx->scope = aml_createname(ctx->scope, name);
+ ctx->scope->mnem = opc->mnem;
+ ctx->scope->opcode = opc->opcode;
+ rv = aml_eparselist(ctx, end);
+ ctx->scope = oldscope;
+ return rv;
+}
+
+/* Parse AMLOP_IF/AMLOP_ELSE block */
+struct aml_value *aml_doif(struct acpi_context *ctx)
+{
+ struct aml_value *rv;
+ uint8_t *end;
+ int64_t i1;
+
+ rv = NULL;
+ end = aml_eparselen(ctx);
+ i1 = aml_eparseint(ctx);
+ dnprintf(10,"evalif: %lld\n", i1);
+ if (i1 != 0) {
+ /* Parse IF block */
+ rv = aml_eparselist(ctx, end);
+ }
+ if (*end == AMLOP_ELSE) {
+ /* Parse ELSE block */
+ ctx->pos = ++end;
+ end = aml_eparselen(ctx);
+ if (i1 == 0) {
+ rv = aml_eparselist(ctx, end);
}
- break;
+ }
+ ctx->pos = end;
+ return rv;
+}
- case AMLOP_PROCESSOR:
- node->value = aml_allocvalue(AML_OBJTYPE_PROCESSOR, 0, NULL, "processor");
- if (node->value != NULL) {
- node->value->v_processor.proc_id = _aml_evalint(ctx, childOf(node, 0));
- node->value->v_processor.proc_addr = _aml_evalint(ctx, childOf(node, 1));
- node->value->v_processor.proc_len = _aml_evalint(ctx, childOf(node, 2));
- dnprintf(50, "allocate processor; %x %x %x\n",
- node->value->v_processor.proc_id,
- node->value->v_processor.proc_addr,
- node->value->v_processor.proc_len);
+/* Parse AMLOP_WHILE/AMLOP_BREAK/AMLOP_CONTINUE block */
+struct aml_value *aml_dowhile(struct acpi_context *ctx)
+{
+ uint8_t *start, *end;
+ struct aml_value *rv;
+ int64_t i1, iw=0;
+
+ end = aml_eparselen(ctx);
+ start = ctx->pos;
+
+ rv = NULL;
+ for(;;) {
+ if (ctx->pos == end) {
+ ctx->pos = start;
}
- break;
+ /* Perform test condition */
+ if (ctx->pos == start) {
+ i1 = aml_eparseint(ctx);
+ dnprintf(10, "whiletest: %lld\n", i1);
+ if (i1 == 0) {
+ break;
+ }
+ }
+ if (*ctx->pos == AMLOP_BREAK) {
+ dnprintf(10,"break\n");
+ break;
+ }
+ else if (*ctx->pos == AMLOP_CONTINUE) {
+ dnprintf(10,"continue\n");
+ ctx->pos = start;
+ }
+ else {
+ aml_freevalue(&rv);
+ rv = aml_eparseval(ctx);
+ }
+ if (iw++ > 10) break;
+ }
+ return rv;
+}
- case AMLOP_THERMALZONE:
- node->value = aml_allocvalue(AML_OBJTYPE_THERMZONE, 0, NULL, "thermzone");
- break;
+struct aml_value *aml_domethod(struct acpi_context *ctx, struct aml_value *val)
+{
+ int64_t i1, i2;
+ struct aml_value **newarg, **oldarg;
+ struct aml_value **newloc, **oldloc;
+ struct aml_value *rv;
+ uint8_t *oldpos;
- case AMLOP_EVENT:
- node->value = aml_allocvalue(AML_OBJTYPE_EVENT, 0, NULL, "event");
- break;
+ oldarg = ctx->args;
+ oldloc = ctx->locals;
- case AMLOP_DEVICE:
- node->value = aml_allocvalue(AML_OBJTYPE_DEVICE, 0, NULL, "device");
- break;
+ if (val->type != AML_OBJTYPE_METHOD) {
+ dnprintf(10, "aml_domethod: Invalid type\n");
+ }
- case AMLOP_MUTEX:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- node->value = aml_allocvalue(AML_OBJTYPE_MUTEX, i1, NULL, "mutex");
- break;
+ i2 = AML_METHOD_ARGCOUNT(val->v_method.flags);
+ newarg = (struct aml_value **)acpi_os_allocmem(sizeof(struct aml_value *)*8);
+ newloc = (struct aml_value **)acpi_os_allocmem(sizeof(struct aml_value *)*8);
- case AMLOP_POWERRSRC:
- node->value = aml_allocvalue(AML_OBJTYPE_POWERRSRC, 0, NULL, "powerrsrc");
- if (node->value != NULL) {
- node->value->v_powerrsrc.pwr_level = _aml_evalint(ctx, childOf(node, 0));
- node->value->v_powerrsrc.pwr_order = _aml_evalint(ctx, childOf(node, 1));
- }
- break;
+ /* Parse arguments */
+ for (i1 = 0; i1<i2; i1++) {
+ newarg[i1] = aml_eparseval(ctx);
+ }
+ dnprintf(10,"\nCall %s: (%lld args)\n", val->name, i2);
+ for (i1 = 0; i1<i2; i1++) {
+ dnprintf(10," arg%lld: ", i1);
+ aml_showvalue(newarg[i1]);
+ }
- default:
- return NULL;
+ /* Save old parse position, call method */
+ oldpos = ctx->pos;
+ ctx->pos = val->v_method.start;
+ ctx->args = newarg;
+ ctx->locals = newloc;
+ rv = aml_eparselist(ctx, val->v_method.end);
+ ctx->pos = oldpos;
+ ctx->args = oldarg;
+ ctx->locals = oldloc;
+
+ for (i1=0; i1<8; i1++) {
+ aml_freevalue(&newloc[i1]);
+ }
+ for (i1=0; i1<i2; i1++) {
+ aml_freevalue(&newarg[i1]);
}
- if (node->value)
- node->value->refcnt++;
- return node->value;
+ return rv;
+
}
-/*
- * Evaluate integer object
- */
-int64_t
-_aml_evalint(struct acpi_context *ctx, struct aml_node *node)
+/* Resize buffer/string/package if out-of-bounds access */
+void aml_resizeval(struct aml_value *pv, int newlen)
{
- struct aml_value *rhs;
- int64_t rval = 0;
+ struct aml_value **oldpkg;
+ int i1;
- rhs = aml_evalnode(ctx, node);
- if (rhs != NULL) {
- switch (rhs->type) {
- case AML_OBJTYPE_INTEGER:
- rval = rhs->v_integer;
- break;
- case AML_OBJTYPE_STRING:
- /* Convert hex/decimal string to integer */
- if (!strncmp(rhs->v_string, "0x", 2))
- rval = aml_str2int(rhs->v_string+2, rhs->length, 16);
- else
- rval = aml_str2int(rhs->v_string, rhs->length, 10);
- break;
- case AML_OBJTYPE_BUFFER:
- rval = *rhs->v_buffer;
- break;
- default:
- dnprintf(50, "aml_evalint: invalid type: %x\n", rhs->type);
- break;
+ ++newlen;
+ dnprintf(10, "supersizeme\n");
+ switch (pv->type) {
+ case AML_OBJTYPE_PACKAGE:
+ oldpkg = pv->v_package;
+ pv->v_package = (struct aml_value **)acpi_os_allocmem(newlen * sizeof(struct aml_value *));
+
+ /* Assign old package values */
+ for (i1 = 0; i1 < pv->length; i1++) {
+ pv->v_package[i1] = oldpkg[i1];
}
- aml_freevalue(rhs);
+
+ /* Free old package */
+ acpi_os_freemem(oldpkg);
+
+ /* Set new length */
+ pv->length = newlen-1;
+
+ break;
}
- return rval;
}
-struct aml_value *
-_aml_evalref(struct acpi_context *ctx, struct aml_node *node)
+struct aml_value *aml_doloadtable(struct acpi_context *ctx)
{
- if (node->value->v_nameref.ref == NULL) {
- dnprintf(50,"deref: %s\n", node->value->v_nameref.name);
- node->value->v_nameref.ref = aml_find_name(ctx->sc, NULL, node->value->v_nameref.name);
- }
- return aml_evalnode(ctx, node->value->v_nameref.ref);
+ aml_eparseval(ctx);
+ aml_eparseval(ctx);
+ aml_eparseval(ctx);
+ aml_eparseval(ctx);
+ aml_eparseval(ctx);
+ aml_eparseval(ctx);
+ aml_eparseval(ctx);
+ return NULL;
}
-struct aml_value *aml_deref(struct acpi_context *ctx, struct aml_value *rv);
-
-struct aml_value *
-aml_deref(struct acpi_context *ctx, struct aml_value *rv)
+struct aml_value *aml_domatch(struct acpi_context *ctx)
{
- struct aml_value *lhs = NULL;
-
- if (rv != NULL) {
- switch (rv->type) {
- case AML_OBJTYPE_BUFFERFIELD:
- lhs = rv;
- rv = aml_bufferio(ctx, rv, NULL);
- break;
- case AML_OBJTYPE_FIELDUNIT:
- lhs = rv;
- rv = aml_fieldio(ctx, rv, NULL);
- break;
- case AML_OBJTYPE_OBJREF:
- break;
+ struct aml_value *lhs, *rv;
+ int64_t op1, op2, mv1, mv2, idx, mval;
+
+ lhs = aml_eparseval(ctx);
+ op1 = aml_parse_int(ctx,1);
+ mv1 = aml_eparseint(ctx);
+ op2 = aml_parse_int(ctx,1);
+ mv2 = aml_eparseint(ctx);
+ idx = aml_eparseint(ctx);
+
+ /* ASSERT: lhs is package */
+ rv = aml_allocint(-1, 0);
+ if (lhs->type == AML_OBJTYPE_PACKAGE) {
+ for (; idx < lhs->length; idx++) {
+ mval = aml_val2int(ctx,lhs->v_package[idx]);
+ if (aml_match(mval, op1, mv1) && aml_match(mval, op2, mv2)) {
+ rv->v_integer = idx;
+ break;
+ }
}
}
- aml_freevalue(lhs);
+ aml_freevalue(&lhs);
return rv;
}
-
struct aml_value *
-aml_evalnode(struct acpi_context *ctx, struct aml_node *node)
+aml_eparseval(struct acpi_context *ctx)
{
- struct aml_value *rv, *lhs, *rhs;
- struct aml_node *cflow;
- int64_t i1, i2, i3, i4, i5, i6;
-
- if (node == NULL) {
- dnprintf(50, "aml_evalnode: invalid node\n");
- return NULL;
- }
-
-#ifdef ACPI_DEBUG
- dnprintf(50, " %d ", node->depth);
- for(i1=0; i1<node->depth; i1++) {
- dnprintf(50, "..");
- }
- printf("evalnode: addr:%.8x %.4x %s\n",
- aml_ipaddr(node->start),
- node->opcode,
- node->mnem);
-#endif
+ struct aml_opcode *opc;
+ struct aml_value *lhs, *rhs, *tmp, *rv;
+ uint8_t *end, *start;
+ const char *name;
+ int64_t i1, i2;
- /* Initialize helper variables */
- lhs = NULL;
rhs = NULL;
- cflow = NULL;
+ lhs = NULL;
+ tmp = NULL;
+ rv = NULL;
- /* Check if node already contains value */
- if ((rv = aml_getnodevalue(ctx, node)) != NULL) {
- /* Dereference object if necessary */
- return aml_deref(ctx, rv);
- }
+ /* Allocate a new instruction, get opcode, etc */
+ start = ctx->pos;
+ opc = aml_getopcode(ctx);
- switch (node->opcode) {
- case AMLOP_NOP:
- case AMLOP_ELSE:
- case AMLOP_BREAK:
- case AMLOP_BREAKPOINT:
- case AMLOP_CONTINUE:
- break;
+ dnprintf(10, "### %2d %.4x %s\n",
+ ctx->depth, opc->opcode, opc->mnem);
- case AMLOP_WHILE:
- for (;;) {
- if (cflow == NULL) {
- /* Test while condition */
- cflow = childOf(node, 1);
- i1 = _aml_evalint(ctx, childOf(node, 0));
- dnprintf(50, "aml_while: %d\n", i1);
- if (i1 == 0)
- break;
+ ctx->depth++;
+ end = NULL;
+ switch (opc->opcode) {
+ case AMLOP_NAMECHAR:
+ name = aml_parse_name(ctx);
+ rv = aml_allocvalue(AML_OBJTYPE_NAMEREF, 0, (char *)name, "nameref");
+ if ((rhs = aml_ederef(ctx, rv)) != NULL) {
+ if (rhs->type == AML_OBJTYPE_METHOD) {
+ rv = aml_domethod(ctx, rhs);
}
- else if (cflow->opcode == AMLOP_BREAK)
- break;
- else if (cflow->opcode == AMLOP_CONTINUE)
- /* Reset cflow to NULL; restart block */
- cflow = NULL;
else {
- /* Execute next node in block */
- aml_freevalue(lhs);
- lhs = aml_evalnode(ctx, cflow);
- cflow = cflow->sibling;
+ rv = rhs;
+ rhs = NULL;
}
}
break;
-
- case AMLOP_IF:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- dnprintf(50, "aml_if: %d\n", i1);
- if (i1 != 0) {
- /* Test true, select 'If' block */
- cflow = childOf(node, 1);
+ case AMLOP_NOP:
+ break;
+ case AMLOP_ZERO:
+ rv = aml_allocint(0,1);
+ aml_showvalue(rv);
+ break;
+ case AMLOP_ONE:
+ rv = aml_allocint(1,1);
+ aml_showvalue(rv);
+ break;
+ case AMLOP_ONES:
+ rv = aml_allocint(-1LL, 1);
+ aml_showvalue(rv);
+ break;
+ case AMLOP_REVISION:
+ rv = aml_allocint(AML_REVISION, 1);
+ aml_showvalue(rv);
+ break;
+ case AMLOP_BYTEPREFIX:
+ rv = aml_allocint(aml_parse_int(ctx, 1), 0);
+ aml_showvalue(rv);
+ break;
+ case AMLOP_WORDPREFIX:
+ rv = aml_allocint(aml_parse_int(ctx, 2), 0);
+ aml_showvalue(rv);
+ break;
+ case AMLOP_DWORDPREFIX:
+ rv = aml_allocint(aml_parse_int(ctx, 4), 0);
+ aml_showvalue(rv);
+ break;
+ case AMLOP_QWORDPREFIX:
+ rv = aml_allocint(aml_parse_int(ctx, 8), 0);
+ aml_showvalue(rv);
+ break;
+ case AMLOP_STRINGPREFIX:
+ rv = aml_allocstr(ctx->pos);
+ if (rv != NULL){
+ ctx->pos += rv->length+1;
}
- else if (node->sibling && node->sibling->opcode == AMLOP_ELSE) {
- /* Test false, select 'Else' block */
- cflow = childOf(node->sibling, 0);
+ aml_showvalue(rv);
+ break;
+ case AMLOP_FIELD:
+ case AMLOP_INDEXFIELD:
+ case AMLOP_BANKFIELD:
+ rv = aml_efieldunit(ctx, opc->opcode);
+ break;
+ case AMLOP_CREATEFIELD:
+ rv = aml_ebufferfield(ctx, -1, 1, opc->opcode);
+ break;
+ case AMLOP_CREATEBITFIELD:
+ rv = aml_ebufferfield(ctx, 1, 1, opc->opcode);
+ break;
+ case AMLOP_CREATEBYTEFIELD:
+ rv = aml_ebufferfield(ctx, 8, 8, opc->opcode);
+ break;
+ case AMLOP_CREATEWORDFIELD:
+ rv = aml_ebufferfield(ctx, 8, 16, opc->opcode);
+ break;
+ case AMLOP_CREATEDWORDFIELD:
+ rv = aml_ebufferfield(ctx, 8, 32, opc->opcode);
+ break;
+ case AMLOP_CREATEQWORDFIELD:
+ rv = aml_ebufferfield(ctx, 8, 64, opc->opcode);
+ break;
+ case AMLOP_DEBUG:
+ if (aml_edebugobj == NULL) {
+ aml_edebugobj = aml_allocvalue(AML_OBJTYPE_DEBUGOBJ, 0, NULL, "debug");
}
- while (cflow) {
- /* Execute all instructions in scope block */
- rv = aml_evalnode(ctx, cflow);
- cflow = cflow->sibling;
+ rv = aml_edebugobj;
+ break;
+ case AMLOP_BUFFER:
+ end = aml_eparselen(ctx);
+ i2 = aml_eparseint(ctx); // requested length
+ i1 = end - ctx->pos; // supplied length
+
+ rv = aml_allocvalue(AML_OBJTYPE_BUFFER, i2, NULL, "buffer");
+ if (i1 > 0) {
+ memcpy(rv->v_buffer, ctx->pos, i1);
}
break;
+ case AMLOP_PACKAGE:
+ case AMLOP_VARPACKAGE:
+ end = aml_eparselen(ctx);
- case AMLOP_METHOD:
- if (node->child == NULL) {
- /* Parse method object */
+ /* Packages have fixed length, varpkg is variable */
+ i2 = (opc->opcode == AMLOP_PACKAGE) ?
+ aml_parse_int(ctx, 1) :
+ aml_eparseint(ctx);
+
+ rv = aml_allocvalue(AML_OBJTYPE_PACKAGE, i2, NULL, "package");
+ for (i1=0; i1 < i2 && ctx->pos < end; i1++) {
+ rv->v_package[i1] = aml_eparseval(ctx);
}
- dnprintf(50, "Evaluating method: %s\n", node->name);
- for (cflow = node->child; cflow; cflow = cflow->sibling) {
- aml_freevalue(rv);
- rv = aml_evalnode(ctx, cflow);
+#if 0
+ for (; i1 < rv->length; i1++) {
+ rv->v_package[i1] = aml_allocint(0,0);
}
+#endif
+ dnprintf(10, "package: %lld of %lld parsed\n", i1, i2);
break;
-
- case AMLOP_NAMECHAR:
- /* Return dereferenced object */
- rv = _aml_evalref(ctx, node);
+ case AMLOP_LOCAL0:
+ case AMLOP_LOCAL1:
+ case AMLOP_LOCAL2:
+ case AMLOP_LOCAL3:
+ case AMLOP_LOCAL4:
+ case AMLOP_LOCAL5:
+ case AMLOP_LOCAL6:
+ case AMLOP_LOCAL7:
+ i1 = opc->opcode - AMLOP_LOCAL0;
+ if (ctx->locals[i1] == NULL) {
+ /* Lazy allocate LocalX */
+ dnprintf(10, "LazyLocal%lld\n", i1);
+ ctx->locals[i1] = aml_allocint(0, 0);
+ }
+ else {
+ ctx->locals[i1]->refcnt++;
+ }
+ rv = ctx->locals[i1];
break;
-
- case AMLOP_NAME:
- case AMLOP_ALIAS:
- case AMLOP_RETURN:
- /* Return child value */
- rv = aml_evalnode(ctx, childOf(node, 0));
+ case AMLOP_ARG0:
+ case AMLOP_ARG1:
+ case AMLOP_ARG2:
+ case AMLOP_ARG3:
+ case AMLOP_ARG4:
+ case AMLOP_ARG5:
+ case AMLOP_ARG6:
+ i1 = opc->opcode - AMLOP_ARG0;
+ if (ctx->args[i1] == NULL) {
+ /* Lazy allocate ArgX - shouldn't happen? */
+ dnprintf(10, "LazyArg%lld\n", i1);
+ ctx->args[i1] = aml_allocint(0, 0);
+ }
+ rv = ctx->args[i1];
break;
case AMLOP_INCREMENT:
case AMLOP_DECREMENT:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- rv = _aml_setnodevalue(ctx, childOf(node, 0), NULL,
- aml_evalmath(node->opcode, i1, 1));
+ lhs = aml_eparseval(ctx);
+ i1 = aml_val2int(ctx, lhs);
+ rv = aml_esetnodevalue(ctx, lhs, NULL, aml_evalmath(opc->opcode, i1, 1));
break;
-
- case AMLOP_NOT:
case AMLOP_FINDSETLEFTBIT:
case AMLOP_FINDSETRIGHTBIT:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- rv = _aml_setnodevalue(ctx, childOf(node, 1), NULL,
- aml_evalmath(node->opcode, i1, 0));
+ case AMLOP_NOT:
+ i1 = aml_eparseint(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_esetnodevalue(ctx, lhs, NULL, aml_evalmath(opc->opcode, i1, 0));
break;
-
case AMLOP_DIVIDE:
- /* Divide: Return quotient and remainder */
- i1 = _aml_evalint(ctx, childOf(node, 0));
- i2 = _aml_evalint(ctx, childOf(node, 1));
- _aml_setnodevalue(ctx, childOf(node, 2), NULL,
- aml_evalmath(AMLOP_MOD, i1, i2));
- rv = _aml_setnodevalue(ctx, childOf(node, 3), NULL,
- aml_evalmath(AMLOP_DIVIDE, i1, i2));
- break;
+ i1 = aml_eparseint(ctx);
+ i2 = aml_eparseint(ctx);
+
+ lhs = aml_eparseval(ctx);
+ rhs = aml_esetnodevalue(ctx, lhs, NULL, aml_evalmath(AMLOP_MOD, i1, i2));
+ aml_freevalue(&lhs);
+ lhs = aml_eparseval(ctx);
+ rv = aml_esetnodevalue(ctx, lhs, NULL, aml_evalmath(AMLOP_DIVIDE, i1, i2));
+ break;
case AMLOP_ADD:
case AMLOP_SUBTRACT:
case AMLOP_MULTIPLY:
@@ -1650,451 +2107,419 @@ aml_evalnode(struct acpi_context *ctx, struct aml_node *node)
case AMLOP_XOR:
case AMLOP_NOR:
case AMLOP_MOD:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- i2 = _aml_evalint(ctx, childOf(node, 1));
- rv = _aml_setnodevalue(ctx, childOf(node, 2), NULL,
- aml_evalmath(node->opcode, i1, i2));
+ i1 = aml_eparseint(ctx);
+ i2 = aml_eparseint(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_esetnodevalue(ctx, lhs, NULL, aml_evalmath(opc->opcode, i1, i2));
break;
-
- case AMLOP_LNOT:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- rv = aml_allocint(!i1);
- break;
-
case AMLOP_LAND:
case AMLOP_LOR:
+ i1 = aml_eparseint(ctx);
+ i2 = aml_eparseint(ctx);
+ rv = aml_allocint(aml_testlogical(opc->opcode, i1, i2),0);
+ break;
+ case AMLOP_LNOT:
+ i1 = aml_eparseint(ctx);
+ rv = aml_allocint(!i1, 1);
+ break;
+ case AMLOP_LLESS:
+ case AMLOP_LLESSEQUAL:
case AMLOP_LEQUAL:
case AMLOP_LNOTEQUAL:
- case AMLOP_LLESSEQUAL:
case AMLOP_LGREATEREQUAL:
case AMLOP_LGREATER:
- case AMLOP_LLESS:
- lhs = aml_evalnode(ctx, childOf(node, 0));
- rhs = aml_evalnode(ctx, childOf(node, 1));
-
- i1 = aml_comparevalue(node->opcode, lhs, rhs);
- rv = aml_allocint(i1);
+ lhs = aml_eparseval(ctx);
+ rhs = aml_eparseval(ctx);
+ i1 = aml_comparevalue(opc->opcode, lhs, rhs);
+ rv = aml_allocint(i1, 0);
+ break;
+ case AMLOP_TOINTEGER:
+ i1 = aml_eparseint(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_esetnodevalue(ctx, lhs, NULL, i1);
break;
+ case AMLOP_FROMBCD:
+ i1 = aml_eparseint(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_esetnodevalue(ctx, lhs, NULL, aml_bcd2dec(i1));
+ break;
+ case AMLOP_TOBCD:
+ i1 = aml_eparseint(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_esetnodevalue(ctx, lhs, NULL, aml_dec2bcd(i1));
+ break;
+ case AMLOP_MID:
+ rhs = aml_eparseval(ctx);
+ i1 = aml_eparseint(ctx); // index
+ i2 = aml_eparseint(ctx); // length
+ if (rhs != NULL) {
+ switch (rhs->type) {
+ case AML_OBJTYPE_STRING:
+ /* Validate index is within range */
+ if (i1 >= lhs->length)
+ i1 = i2 = 0;
+ if (i1+i2 >= lhs->length)
+ i2 = lhs->length - i1;
+ rv = aml_allocvalue(AML_OBJTYPE_STRING, i2, lhs->v_string + i1, "mid");
+ aml_esetnodevalue(ctx, lhs, rv, 0);
+ break;
+ case AML_OBJTYPE_BUFFER:
+ if (i1 >= lhs->length)
+ i1 = i2 = 0;
+ if (i1+i2 >= lhs->length)
+ i2 = lhs->length - i1;
+ rv = aml_allocvalue(AML_OBJTYPE_BUFFER, i2, lhs->v_buffer + i1, "mid");
+ aml_esetnodevalue(ctx, lhs, rv, 0);
+ break;
+ }
+ }
+ break;
+ case AMLOP_TOSTRING:
+ rhs = aml_eparseval(ctx);
+ i1 = aml_eparseint(ctx);
+ lhs = aml_eparseval(ctx);
+ tmp = aml_val2buf(ctx, rhs);
+ if (i1 > tmp->length) {
+ i1 = tmp->length;
+ }
+ for(i2=0; i2<i1; i1++) {
+ if (tmp->v_buffer[i2] == 0) {
+ break;
+ }
+ }
+ rv = aml_allocvalue(AML_OBJTYPE_STRING, i2, tmp->v_buffer, "");
+ aml_esetnodevalue(ctx, lhs, rv, 0);
+ break;
+ case AMLOP_TOBUFFER:
+ rhs = aml_eparseval(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_val2buf(ctx, lhs);
+ aml_esetnodevalue(ctx, lhs, rv, 0);
+ break;
case AMLOP_TODECSTRING:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- rhs = aml_allocvalue(AML_OBJTYPE_STRING, AML_INTSTRLEN, NULL, "");
+ i1 = aml_eparseint(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_allocvalue(AML_OBJTYPE_STRING, AML_INTSTRLEN, NULL, "todec");
if (rhs != NULL) {
- snprintf(rhs->v_string, AML_INTSTRLEN, "%d", i1);
- rv = _aml_setnodevalue(ctx, childOf(node, 1), rhs, 0);
+ snprintf(rhs->v_string, AML_INTSTRLEN, "%lld", i1);
+ aml_esetnodevalue(ctx, lhs, rv, 0);
}
break;
-
case AMLOP_TOHEXSTRING:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- rhs = aml_allocvalue(AML_OBJTYPE_STRING, AML_INTSTRLEN, NULL, "");
+ i1 = aml_eparseint(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_allocvalue(AML_OBJTYPE_STRING, AML_INTSTRLEN, NULL, "todec");
if (rhs != NULL) {
- snprintf(rhs->v_string, AML_INTSTRLEN, "%x", i1);
- rv = _aml_setnodevalue(ctx, childOf(node, 1), rhs, 0);
+ snprintf(rhs->v_string, AML_INTSTRLEN, "0x%Lx", i1);
+ aml_esetnodevalue(ctx, lhs, rv, 0);
}
break;
-
- case AMLOP_TOINTEGER:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- rv = _aml_setnodevalue(ctx, childOf(node, 1), NULL, i1);
+ case AMLOP_STALL:
+ i1 = aml_eparseint(ctx);
+ dnprintf(10, "stall %lld usecs\n", i1);
break;
-
- case AMLOP_FROMBCD:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- rv = _aml_setnodevalue(ctx, childOf(node, 1), NULL, aml_bcd2dec(i1));
+ case AMLOP_SLEEP:
+ i1 = aml_eparseint(ctx);
+ dnprintf(10, "sleep %lld msecs\n", i1);
break;
-
- case AMLOP_TOBCD:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- rv = _aml_setnodevalue(ctx, childOf(node, 1), NULL, aml_dec2bcd(i1));
+ case AMLOP_MUTEX:
+ name = aml_parse_name(ctx);
+ i1 = aml_parse_int(ctx, 1);
+ rv = aml_allocvalue(AML_OBJTYPE_MUTEX, i1, (char *)name, "mutex");
+ if (rv != NULL) {
+ aml_addvname(ctx, name, opc->opcode, rv);
+ }
break;
-
- case AMLOP_MATCH:
- /* Perform match operation */
- lhs = aml_evalnode(ctx, childOf(node, 0)); /* package */
-
- /* Allocate default return value */
- rv = aml_allocint(-1);
- if (lhs->type == AML_OBJTYPE_PACKAGE && rv != NULL) {
- i1 = _aml_evalint(ctx, childOf(node, 1)); /* op1 */
- i2 = _aml_evalint(ctx, childOf(node, 2)); /* match1 */
- i3 = _aml_evalint(ctx, childOf(node, 3)); /* op2 */
- i4 = _aml_evalint(ctx, childOf(node, 4)); /* match2 */
- i5 = _aml_evalint(ctx, childOf(node, 5)); /* index */
-
- while (i5 < lhs->length) {
- if (lhs->v_package[i5]->type == AML_OBJTYPE_INTEGER) {
- i6 = lhs->v_package[i5]->v_integer;
- }
- else {
- dnprintf(50, "aml_match: invalid index: %d:%x\n",
- i5, lhs->v_package[i5]->type);
- break;
- }
- if (aml_match(i6, i1, i2) && aml_match(i6, i3, i4)) {
- rv->v_integer = i5;
- break;
- }
- i5++;
- }
+ case AMLOP_ACQUIRE:
+ lhs = aml_eparseref(ctx);
+ i1 = aml_parse_int(ctx, 2);
+ acpi_mutex_acquire(ctx, &lhs->v_mutex, i1);
+ rv = aml_allocint(0,0);
+ break;
+ case AMLOP_RELEASE:
+ lhs = aml_eparseref(ctx);
+ acpi_mutex_release(ctx, &lhs->v_mutex);
+ break;
+ case AMLOP_EVENT:
+ name = aml_parse_name(ctx);
+ rv = aml_allocvalue(AML_OBJTYPE_EVENT, 0, (char *)name, "event");
+ if (rv != NULL) {
+ aml_addvname(ctx, name, opc->opcode, rv);
}
break;
-
+ case AMLOP_SIGNAL:
+ lhs = aml_eparseref(ctx);
+ dnprintf(10,"signal: %s\n", lhs->v_string);
+ break;
+ case AMLOP_WAIT:
+ lhs = aml_eparseref(ctx);
+ i1 = aml_eparseint(ctx);
+ dnprintf(10, "wait: %s %Lx\n", lhs->v_string, i1);
+ break;
+ case AMLOP_RESET:
+ lhs = aml_eparseref(ctx);
+ dnprintf(10, "reset: %s\n", lhs->v_string);
+ break;
+ case AMLOP_NOTIFY:
+ lhs = aml_eparseval(ctx);
+ i1 = aml_eparseint(ctx);
+ dnprintf(10,"NOTIFY: %Lx %s\n", i1, lhs->name);
+ break;
+ case AMLOP_LOAD:
+ case AMLOP_STORE:
+ rhs = aml_eparseval(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_esetnodevalue(ctx, lhs, rhs, 0);
+ break;
case AMLOP_COPYOBJECT:
- /* Return copy of an object */
- lhs = aml_evalnode(ctx, childOf(node, 0));
- rhs = aml_copyvalue(lhs);
- rv = _aml_setnodevalue(ctx, childOf(node, 1), rhs, 0);
+ rhs = aml_eparseval(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_copyvalue(rhs);
+ aml_esetnodevalue(ctx, lhs, rv, 0);
+ break;
+ case AMLOP_OPREGION:
+ name = aml_parse_name(ctx);
+ rv = aml_allocvalue(AML_OBJTYPE_OPREGION, 0, (char *)name, "opregion");
+ if (rv != NULL) {
+ rv->v_opregion.iospace = aml_parse_int(ctx, 1);
+ rv->v_opregion.iobase = aml_eparseint(ctx);
+ rv->v_opregion.iolen = aml_eparseint(ctx);
+#if 0
+ rv->v_opregion.buf = acpi_os_allocmem(rv->v_opregion.iolen);
+ memset(rv->v_opregion.buf, 0xFF, rv->v_opregion.iolen);
+ acpi_gasio(ctx->sc, ACPI_IOREAD,
+ rv->v_opregion.iospace,
+ rv->v_opregion.iobase,
+ 1,
+ rv->v_opregion.iolen,
+ rv->v_opregion.buf);
+#endif
+ aml_addvname(ctx, name, opc->opcode, rv);
+ }
+ break;
+ case AMLOP_ALIAS:
+ name = aml_parse_name(ctx);
+ rv = aml_allocvalue(AML_OBJTYPE_NAMEREF, 0, (void *)name, "alias");
+ if (rv != NULL) {
+ name = aml_parse_name(ctx);
+ aml_addvname(ctx, name, opc->opcode, rv);
+ }
+ break;
+ case AMLOP_NAME:
+ name = aml_parse_name(ctx);
+ rv = aml_eparseval(ctx);
+ if (rv != NULL) {
+ aml_addvname(ctx, name, opc->opcode, rv);
+ }
+ break;
+ case AMLOP_RETURN:
+ rv = aml_eparseref(ctx);
+ ctx->pos = NULL;
+ break;
+ case AMLOP_CONCAT:
+ rv = aml_econcat(ctx);
break;
- case AMLOP_STORE:
- /* Store value into another */
- rhs = aml_evalnode(ctx, childOf(node, 0));
- rv = _aml_setnodevalue(ctx, childOf(node, 1), rhs, 0);
+ case AMLOP_SCOPE:
+ end = aml_eparselen(ctx);
+ name = aml_parse_name(ctx);
+
+ /* Save old scope, create new scope */
+ rv = aml_eparsescope(ctx, name, end, opc);
break;
+ case AMLOP_DEVICE:
+ end = aml_eparselen(ctx);
+ name = aml_parse_name(ctx);
- case AMLOP_OBJECTTYPE:
- /* Return object type */
- lhs = aml_evalnode(ctx, childOf(node, 0));
- rv = aml_allocint(lhs->type);
+ rv = aml_allocvalue(AML_OBJTYPE_DEVICE, 0, (char *)name, "device");
+
+ /* Save old scope, create new scope */
+ lhs = aml_eparsescope(ctx, name, end, opc);
break;
+ case AMLOP_POWERRSRC:
+ end = aml_eparselen(ctx);
+ name = aml_parse_name(ctx);
- case AMLOP_SIZEOF:
- /* Return sizeof object (string/buffer/package) */
- lhs = aml_evalnode(ctx, childOf(node, 0));
+ rv = aml_allocvalue(AML_OBJTYPE_POWERRSRC, 0, (char *)name, "power");
+ if (rv != NULL) {
+ rv->v_powerrsrc.pwr_level = aml_parse_int(ctx, 1);
+ rv->v_powerrsrc.pwr_order = aml_parse_int(ctx, 2);
- switch (lhs->type) {
- case AML_OBJTYPE_STRING:
- case AML_OBJTYPE_BUFFER:
- case AML_OBJTYPE_PACKAGE:
- i1 = lhs->length;
- break;
- default:
- i1 = 0;
- dnprintf(50,"aml_sizeof: incorrect type: %x\n", lhs->type);
- break;
+ lhs = aml_eparsescope(ctx, name, end, opc);
}
- rv = aml_allocint(i1);
break;
+ case AMLOP_PROCESSOR:
+ end = aml_eparselen(ctx);
+ name = aml_parse_name(ctx);
- case AMLOP_REFOF:
- rv = aml_allocvalue(AML_OBJTYPE_OBJREF, -1, childOf(node, 0), "refof");
- break;
+ rv = aml_allocvalue(AML_OBJTYPE_PROCESSOR, 0, (char *)name, "processor");
+ if (rv != NULL) {
+ rv->v_processor.proc_id = aml_parse_int(ctx, 1);
+ rv->v_processor.proc_addr = aml_parse_int(ctx, 4);
+ rv->v_processor.proc_len = aml_parse_int(ctx, 1);
- case AMLOP_CONDREFOF:
- rv = aml_allocint(AML_FALSE);
- lhs = aml_evalnode(ctx, childOf(node, 0));
- if (lhs != NULL) {
- /* Conditional reference */
- rv->v_integer = AML_TRUE;
- rhs = aml_allocvalue(AML_OBJTYPE_OBJREF, -1, childOf(node, 0), "condref");
- _aml_setnodevalue(ctx, childOf(node, 1), rhs, 0);
+ lhs = aml_eparsescope(ctx, name, end, opc);
}
break;
+ case AMLOP_THERMALZONE:
+ end = aml_eparselen(ctx);
+ name = aml_parse_name(ctx);
- case AMLOP_DEREFOF:
- lhs = aml_evalnode(ctx, childOf(node, 0));
- if (lhs->type == AML_OBJTYPE_OBJREF) {
- rv = aml_evalnode(ctx, lhs->v_objref.ref);
- }
- else if (lhs->type == AML_OBJTYPE_STRING) {
- /* XXX: fix me
- rv = aml_evalname(ctx, node, lhs->v_string);
- */
+ rv = aml_allocvalue(AML_OBJTYPE_THERMZONE, 0, (char *)name, "tzone");
+ if (rv != NULL) {
+ lhs = aml_eparsescope(ctx, name, end, opc);
}
break;
-
- case AMLOP_INDEX:
- i1 = _aml_evalint(ctx, childOf(node, 1));
- rv = aml_allocvalue(AML_OBJTYPE_OBJREF, i1, childOf(node, 0), "index");
-
+ case AMLOP_OBJECTTYPE:
+ lhs = aml_eparseval(ctx);
+ rv = aml_allocint(lhs->type,1);
break;
-
- case AMLOP_MID:
- /* Return substring (actual contents) */
- lhs = aml_evalnode(ctx, childOf(node, 0));
- i1 = _aml_evalint(ctx, childOf(node, 1)); /* length */
- i2 = _aml_evalint(ctx, childOf(node, 2)); /* index */
-
- /* check bounds against source object */
- if (i1 >= lhs->length)
- i1 = i2 = 0;
- if (i1+i2 >= lhs->length)
- i2 = lhs->length - i1;
- switch (lhs->type) {
- case AML_OBJTYPE_STRING:
- rhs = aml_allocvalue(AML_OBJTYPE_STRING, 0, NULL, "");
- if (rhs != NULL) {
- rhs->length = i1;
- rhs->v_string = lhs->v_string + i2;
- rv = _aml_setnodevalue(ctx, childOf(node, 3), rhs, 0);
- }
- break;
- case AML_OBJTYPE_BUFFER:
- rhs = aml_allocvalue(AML_OBJTYPE_BUFFER, 0, NULL, "");
- if (rhs != NULL) {
- rhs->length = i1;
- rhs->v_buffer = lhs->v_buffer + i2;
- rv = _aml_setnodevalue(ctx, childOf(node, 3), rhs, 0);
- }
- break;
- default:
- dnprintf(50, "aml_mid: invalid type: %x\n", lhs->type);
- break;
+ case AMLOP_SIZEOF:
+ lhs = aml_eparseval(ctx);
+ if (lhs != NULL) {
+ rv = aml_allocint(lhs->length, 1);
}
break;
+ case AMLOP_METHOD:
+ end = aml_eparselen(ctx);
+ name = aml_parse_name(ctx);
+ i1 = aml_parse_int(ctx, 1);
+ rv = aml_allocvalue(AML_OBJTYPE_METHOD, i1, (char *)name, "method");
+ if (rv != NULL) {
+ /* Allocate method block */
+ rv->length = end - ctx->pos;
+ rv->v_method.start = acpi_os_allocmem(rv->length);
+ rv->v_method.end = rv->v_method.start + rv->length;
- case AMLOP_CONCAT:
- /* Concatenate result values */
- lhs = aml_evalnode(ctx, childOf(node, 0));
- rhs = aml_evalnode(ctx, childOf(node, 1));
- if (lhs->type == rhs->type) {
- switch (lhs->type) {
- case AML_OBJTYPE_STRING:
- rv = aml_allocvalue(AML_OBJTYPE_STRING, lhs->length+rhs->length, NULL, "");
- if (rv != NULL) {
- strncpy(rv->v_string, lhs->v_string, lhs->length);
- strncpy(rv->v_string+lhs->length, rhs->v_string, rhs->length);
- }
- break;
- case AML_OBJTYPE_BUFFER:
- rv = aml_allocvalue(AML_OBJTYPE_BUFFER, lhs->length+rhs->length, NULL, "");
- if (rv != NULL) {
- memcpy(rv->v_buffer, lhs->v_buffer, lhs->length);
- memcpy(rv->v_buffer+lhs->length, rhs->v_buffer, rhs->length);
- }
- break;
- }
+ memcpy(rv->v_method.start, ctx->pos, rv->length);
+ aml_addvname(ctx, name, opc->opcode, rv);
}
break;
-
- case AMLOP_NOTIFY:
- i1 = _aml_evalint(ctx, childOf(node, 1));
- dnprintf(50,"NOTIFY: %s %x\n", "", i1);
+ case AMLOP_CONDREFOF:
+ rhs = aml_eparseval(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_allocint(0, 1);
+ if (aml_ederef(ctx, rhs) != NULL) {
+ tmp = aml_allocvalue(AML_OBJTYPE_OBJREF, -1, rhs, "condref");
+ aml_esetnodevalue(ctx, lhs, tmp, 0);
+ rv->v_integer = 1;
+ }
+ dnprintf(10,"condrefof: %lld\n", rv->v_integer);
break;
-
- case AMLOP_WAIT:
- lhs = aml_evalnode(ctx, childOf(node, 0));
- i1 = _aml_evalint(ctx, childOf(node, 1));
+ case AMLOP_REFOF:
+ rhs = aml_eparseval(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_allocvalue(AML_OBJTYPE_OBJREF, -1, rhs, "refof");
+ aml_esetnodevalue(ctx, lhs, rv, 0);
break;
-
- case AMLOP_SIGNAL:
- lhs = aml_evalnode(ctx, childOf(node, 0));
+ case AMLOP_INDEX:
+ rhs = aml_eparseval(ctx);
+ i1 = aml_eparseint(ctx);
+ lhs = aml_eparseval(ctx);
+ rv = aml_allocvalue(AML_OBJTYPE_OBJREF, i1, rhs, "index");
+ aml_esetnodevalue(ctx, lhs, rv, 0);
break;
-
- case AMLOP_RESET:
- lhs = aml_evalnode(ctx, childOf(node, 0));
+ case AMLOP_DEREFOF:
+ rv = aml_eparseref(ctx);
break;
-
- case AMLOP_ACQUIRE:
- lhs = aml_evalnode(ctx, childOf(node, 0));
- i1 = _aml_evalint(ctx, childOf(node, 1));
+ case AMLOP_LOADTABLE:
+ rv = aml_doloadtable(ctx);
break;
-
- case AMLOP_RELEASE:
- lhs = aml_evalnode(ctx, childOf(node, 0));
+ case AMLOP_MATCH:
+ rv = aml_domatch(ctx);
break;
-
- case AMLOP_STALL:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- dnprintf(50, "stall %d usecs\n", i1);
+ case AMLOP_WHILE:
+ rv = aml_dowhile(ctx);
+ break;
+ case AMLOP_IF:
+ rv = aml_doif(ctx);
break;
- case AMLOP_SLEEP:
- i1 = _aml_evalint(ctx, childOf(node, 0));
- dnprintf(50, "sleep %d msecs\n", i1);
+ default:
+ dnprintf(10,"Unknown opcode: %.4x %s\n", opc->opcode, opc->mnem);
break;
}
+ if (end > ctx->pos) {
+ ctx->pos = end;
+ }
- /* Free temporary objects */
- aml_freevalue(lhs);
- aml_freevalue(rhs);
-
- aml_showvalue(rv);
-
- return aml_deref(ctx, rv);
+ --ctx->depth;
+ return rv;
}
-int
-aml_eval_object(struct acpi_softc *sc, struct aml_node *node, struct aml_value *result,
- struct aml_value *env)
+/* Remove all children nodes */
+void aml_delchildren(struct acpi_context *ctx, struct aml_node *node)
{
- struct acpi_context ctx;
- struct aml_value *rv;
-
- memset(&ctx, 0, sizeof(ctx));
- ctx.pos = node->start;
+ struct aml_node *pn;
- memset(result, 0, sizeof(struct aml_value));
- rv = aml_evalnode(&ctx, node);
- *result = *rv;
-
- return (0);
+ if (node == NULL) {
+ return;
+ }
+ while ((pn = node->child) != NULL) {
+ node->child = node->child->sibling;
+ aml_delchildren(ctx, pn);
+ acpi_os_freemem(pn);
+ }
}
-int
-aml_parse_args(struct acpi_context *ctx, struct aml_node *node, const char *arg)
-{
- struct aml_node *pnode;
-
- while (*arg) {
- pnode = node;
- switch (*arg) {
- case AML_ARG_FLAG:
- node->flag = aml_parse_int(ctx, 1);
- if (node->opcode == AMLOP_METHOD) {
- dnprintf(50, " method %s %.2x argcount:%d serialized:%d synclevel:%d\n",
- node->name, node->flag,
- AML_METHOD_ARGCOUNT(node->flag),
- AML_METHOD_SERIALIZED(node->flag),
- AML_METHOD_SYNCLEVEL(node->flag));
- }
- else {
- dnprintf(50, " field %.2x access:%d lock:%d update:%d\n",
- node->flag,
- AML_FIELD_ACCESS(node->flag),
- AML_FIELD_LOCK(node->flag),
- AML_FIELD_UPDATE(node->flag));
- }
- break;
- case AML_ARG_IMPBYTE:
- /* Implied byte: same as opcode */
- node->value = aml_allocint((char)node->opcode);
- dnprintf(50, " ibyte: %x\n", (int8_t)node->opcode);
- break;
- case AML_ARG_BYTE:
- if (node->opcode != AMLOP_BYTEPREFIX) {
- pnode = aml_create_node(ctx, node, AMLOP_BYTEPREFIX, "byte");
- }
- pnode->value = aml_allocint(aml_parse_int(ctx, 1));
- dnprintf(50, " byte: %x\n", pnode->value->v_integer);
- break;
- case AML_ARG_WORD:
- if (node->opcode != AMLOP_WORDPREFIX) {
- pnode = aml_create_node(ctx, node, AMLOP_WORDPREFIX, "word");
- }
- pnode->value = aml_allocint(aml_parse_int(ctx, 2));
- dnprintf(50, " word: %x\n", pnode->value->v_integer);
- break;
- case AML_ARG_DWORD:
- if (node->opcode != AMLOP_DWORDPREFIX) {
- pnode = aml_create_node(ctx, node, AMLOP_DWORDPREFIX, "dword");
- }
- pnode->value = aml_allocint(aml_parse_int(ctx, 4));
- dnprintf(50, " dword: %x\n", pnode->value->v_integer);
- break;
- case AML_ARG_QWORD:
- if (node->opcode == AMLOP_QWORDPREFIX) {
- pnode = aml_create_node(ctx, node, AMLOP_QWORDPREFIX, "qword");
- }
- pnode->value = aml_allocint(aml_parse_int(ctx, 8));
- dnprintf(50, " qword: %x\n", pnode->value->v_integer);
- break;
- case AML_ARG_FIELDLIST:
- aml_parse_fieldlist(ctx, node);
- break;
- case AML_ARG_BYTELIST:
- dnprintf(50, " bytelist\n");
- node->start = ctx->pos;
- ctx->pos = node->end;
- break;
- case AML_ARG_STRING:
- node->value = aml_allocstr(aml_parse_string(ctx));
- dnprintf(50, " string: %s\n", node->value->v_string);
- break;
- case AML_ARG_NAMESTRING:
- node->name = aml_parse_name(ctx, "name");
- break;
- case AML_ARG_NAMEREF:
- if (node->opcode != AMLOP_NAMECHAR) {
- pnode = aml_create_node(ctx, node, AMLOP_NAMECHAR, "nameref");
- }
- pnode->value = aml_allocvalue(AML_OBJTYPE_NAMEREF, 0, aml_parse_name(ctx, "nameref"), "");
- break;
- case AML_ARG_OBJLEN:
- dnprintf(50, " pkglen\n");
- node->end = ctx->pos;
- node->end += aml_parse_length(ctx);
- break;
- case AML_ARG_METHOD:
- dnprintf(50, " method\n");
- node->start = ctx->pos;
- ctx->pos = node->end;
- break;
- case AML_ARG_INTEGER:
- case AML_ARG_TERMOBJ:
- /* Recursively parse children */
- aml_parse_object(ctx, node);
- break;
- case AML_ARG_TERMOBJLIST:
- /* Recursively parse children */
- aml_parse_objlist(ctx, node);
- break;
-
- default:
- printf("Unknown arg: %c\n", *arg);
- break;
- }
+/* Ok.. we have a node and hopefully its value.. call value */
+struct aml_value *aml_eparsenode(struct acpi_context *ctx, struct aml_node *node)
+{
+ struct aml_node *oldscope;
+ struct aml_value *rv;
- arg++;
+ if (node->value == NULL) {
+ return NULL;
}
+ switch (node->value->type) {
+ case AML_OBJTYPE_NAMEREF:
+ case AML_OBJTYPE_INTEGER:
+ case AML_OBJTYPE_STRING:
+ case AML_OBJTYPE_BUFFER:
+ case AML_OBJTYPE_PACKAGE:
+ return node->value;
+ case AML_OBJTYPE_BUFFERFIELD:
+ case AML_OBJTYPE_FIELDUNIT:
+ return aml_efield(ctx, node->value, NULL);
+ case AML_OBJTYPE_METHOD:
+ /* Setup method call */
+ oldscope = ctx->scope;
+ ctx->scope = node->parent;
- return (0);
-}
+ dnprintf(10, "Call function: %s\n", node->name);
-struct aml_node *
-aml_preparse(struct acpi_context *ctx, struct aml_node *parent, struct aml_optable *optab)
-{
- const char *arg;
+ ctx->pos = node->value->v_method.start;
+ rv = aml_eparselist(ctx, node->value->v_method.end);
- /* Check for named object */
- for (arg=optab->args; arg && *arg; arg++) {
- if (*arg == AML_ARG_NAMESTRING) {
- /* XXX: check for duplicate name */
- }
+ /* Delete dynamic names */
+ aml_delchildren(ctx, node);
+
+ ctx->scope = oldscope;
+ return rv;
+ default:
+ dnprintf(10, "Unknown node value: %d\n", node->value->type);
}
- return aml_create_node(ctx, parent, optab->opcode, optab->mnem);
+ return NULL;
}
-/* Parse a single object */
-struct aml_node *
-aml_parse_object(struct acpi_context *ctx, struct aml_node *parent)
+int aml_eval_object(struct acpi_softc *sc, struct aml_node *node,
+ struct aml_value *ret, int argc, struct aml_value *argv)
{
- struct aml_optable *optab;
- struct aml_node *node;
- u_int16_t opcode;
+ struct acpi_context *ctx;
+ struct aml_value *rv;
- /* Get AML Opcode; if it is an embedded name, extract name */
- opcode = aml_getopcode(ctx);
- for (optab = aml_table; optab->opcode != 0xFFFF; optab++) {
- if (optab->opcode == opcode) {
- /* Found an opcode in the table */
- node = aml_preparse(ctx, parent, optab);
- aml_parse_args(ctx, node, optab->args);
- return node;
- }
- }
- printf("Invalid AML Opcode : @ %.4x %.4x\n", aml_ipaddr(ctx->pos), opcode);
+ ctx = acpi_alloccontext(sc, node, argc, argv);
+ rv = aml_eparsenode(ctx, node);
+ aml_showvalue(rv);
+ *ret = *rv;
- return NULL;
-}
+ /* XXX: must free rv */
+ acpi_freecontext(ctx);
-/* Parse list of objects; stop at end of parent */
-int
-aml_parse_objlist(struct acpi_context *ctx, struct aml_node *parent)
-{
- while (ctx->pos < parent->end) {
- aml_parse_object(ctx, parent);
- }
- if (ctx->pos != parent->end) {
- dnprintf(50, "aml_parse_objlist: invalid end! %x\n", parent->end - ctx->pos);
- ctx->pos = parent->end;
- return (1);
- }
- return (0);
+ return -1;
}
-
void
aml_shownode(struct aml_node *node)
{
@@ -2109,7 +2534,7 @@ aml_shownode(struct aml_node *node)
break;
case AMLOP_NAMECHAR:
- dnprintf(50, "%s", node->value->v_nameref.name);
+ dnprintf(50, "%s", node->value->name);
break;
case AMLOP_FIELD:
@@ -2198,26 +2623,65 @@ aml_eisaid(u_int32_t pid)
return id;
}
+struct acpi_context *acpi_alloccontext(struct acpi_softc *sc,
+ struct aml_node *node,
+ int argc,
+ struct aml_value *argv)
+{
+ struct acpi_context *ctx;
+ int idx;
+
+ if ((ctx = acpi_os_allocmem(sizeof(struct acpi_context))) != NULL) {
+ ctx->sc = sc;
+ ctx->depth = 0;
+ ctx->start = node->start;
+ ctx->pos = node->start;
+ ctx->scope = node;
+ ctx->locals = (struct aml_value **)acpi_os_allocmem(sizeof(struct aml_value *) * 8);
+ ctx->args = (struct aml_value **)acpi_os_allocmem(sizeof(struct aml_value *) * 8);
+ for (idx=0; idx<argc; idx++) {
+ ctx->args[idx] = aml_copyvalue(&argv[idx]);
+ }
+ }
+ return ctx;
+}
+
+void acpi_freecontext(struct acpi_context *ctx)
+{
+ int idx;
+
+ if (ctx) {
+ for (idx=0; idx<8; idx++) {
+ aml_freevalue(&ctx->args[idx]);
+ aml_freevalue(&ctx->locals[idx]);
+ }
+ acpi_os_freemem(ctx->args);
+ acpi_os_freemem(ctx->locals);
+ acpi_os_freemem(ctx);
+ }
+}
+
int
acpi_parse_aml(struct acpi_softc *sc, u_int8_t *start, u_int32_t length)
{
- struct acpi_context ctx;
-
- memset(&ctx, 0, sizeof(ctx));
- ctx.pos = start;
+ struct acpi_context *ctx;
+ struct aml_value *rv;
+ stacktop = &sc;
+
+ aml_root.depth = -1;
+ aml_root.mnem = "ROOT";
aml_root.start = start;
aml_root.end = start + length;
- aml_parse_objlist(&ctx, &aml_root);
- if (length != aml_ipaddr(ctx.pos)) {
- dnprintf(50, " : error parsing AML @ 0x%x\n", aml_ipaddr(ctx.pos));
- return (-1);
- }
+ ctx = acpi_alloccontext(sc, &aml_root, 0, NULL);
+ rv = aml_eparselist(ctx, aml_root.end);
+ aml_freevalue(&rv);
+ acpi_freecontext(ctx);
dnprintf(50, " : parsed %d AML bytes\n", length);
- aml_walktree(&aml_root);
+ //aml_walktree(&aml_root);
return (0);
}
diff --git a/sys/dev/acpi/dsdt.h b/sys/dev/acpi/dsdt.h
index 7cfcb66ca3a..34a04715741 100644
--- a/sys/dev/acpi/dsdt.h
+++ b/sys/dev/acpi/dsdt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsdt.h,v 1.4 2006/01/20 20:20:28 jordan Exp $ */
+/* $OpenBSD: dsdt.h,v 1.5 2006/02/03 23:55:47 jordan Exp $ */
/*
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
*
@@ -24,19 +24,19 @@ int aml_find_node(struct aml_node *, const char *,
int acpi_parse_aml(struct acpi_softc *, u_int8_t *, u_int32_t);
int aml_eval_object(struct acpi_softc *, struct aml_node *,
- struct aml_value *, struct aml_value *);
+ struct aml_value *, int, struct aml_value *);
int aml_eval_name(struct acpi_softc *, struct aml_node *, const char *,
struct aml_value *, struct aml_value *);
void aml_showvalue(struct aml_value *);
void aml_walktree(struct aml_node *);
-struct aml_value *aml_allocint(uint64_t);
+struct aml_value *aml_allocint(uint64_t, int);
struct aml_value *aml_allocstr(const char *);
-struct aml_value *aml_allocvalue(int, int64_t, const void *, const char *);
+struct aml_value *aml_allocvalue(int, int64_t, void *, const char *);
struct aml_value *aml_copyvalue(const struct aml_value *);
-int aml_freevalue(struct aml_value *);
+int aml_freevalue(struct aml_value **);
int aml_comparevalue(int, const struct aml_value *, const struct aml_value *);
#endif /* __DEV_ACPI_DSDT_H__ */