xref: /openbsd/sys/dev/acpi/acpidebug.c (revision e6117b4f)
1*e6117b4fSderaadt /* $OpenBSD: acpidebug.c,v 1.13 2006/12/21 11:29:58 deraadt Exp $ */
2559cf7adSmarco /*
3559cf7adSmarco  * Copyright (c) 2006 Marco Peereboom <marco@openbsd.org>
4559cf7adSmarco  *
5559cf7adSmarco  * Permission to use, copy, modify, and distribute this software for any
6559cf7adSmarco  * purpose with or without fee is hereby granted, provided that the above
7559cf7adSmarco  * copyright notice and this permission notice appear in all copies.
8559cf7adSmarco  *
9559cf7adSmarco  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10559cf7adSmarco  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11559cf7adSmarco  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12559cf7adSmarco  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13559cf7adSmarco  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14559cf7adSmarco  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15559cf7adSmarco  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16559cf7adSmarco  */
17559cf7adSmarco 
18559cf7adSmarco #include <machine/db_machdep.h>
19559cf7adSmarco #include <ddb/db_command.h>
20559cf7adSmarco #include <ddb/db_output.h>
21cda98319Smarco #include <ddb/db_extern.h>
22cda98319Smarco #include <ddb/db_lex.h>
23559cf7adSmarco 
24559cf7adSmarco #include <machine/bus.h>
2530a01ff4Sjordan #include <sys/malloc.h>
26559cf7adSmarco 
27559cf7adSmarco #include <dev/acpi/acpireg.h>
28559cf7adSmarco #include <dev/acpi/acpivar.h>
29559cf7adSmarco #include <dev/acpi/amltypes.h>
30559cf7adSmarco #include <dev/acpi/acpidebug.h>
31559cf7adSmarco #include <dev/acpi/dsdt.h>
32559cf7adSmarco 
3330a01ff4Sjordan void db_aml_disline(uint8_t *, int, const char *, ...);
3430a01ff4Sjordan void db_aml_disint(struct aml_scope *, int, int);
3530a01ff4Sjordan uint8_t *db_aml_disasm(struct aml_node *, uint8_t *, uint8_t *, int, int);
3630a01ff4Sjordan 
3730a01ff4Sjordan extern int aml_pc(uint8_t *);
3830a01ff4Sjordan extern struct aml_scope *aml_pushscope(struct aml_scope *, uint8_t *, uint8_t *, struct aml_node *);
3930a01ff4Sjordan extern struct aml_scope *aml_popscope(struct aml_scope *);
4030a01ff4Sjordan extern uint8_t *aml_parsename(struct aml_scope *);
4130a01ff4Sjordan extern uint8_t *aml_parseend(struct aml_scope *);
4230a01ff4Sjordan extern int aml_parselength(struct aml_scope *);
4330a01ff4Sjordan extern int aml_parseopcode(struct aml_scope *);
4430a01ff4Sjordan 
4530a01ff4Sjordan extern const char *aml_mnem(int opcode);
4630a01ff4Sjordan extern const char *aml_args(int opcode);
4730a01ff4Sjordan extern const char *aml_getname(uint8_t *);
4830a01ff4Sjordan extern const char *aml_nodename(struct aml_node *);
4930a01ff4Sjordan 
50127317ceSmarco const char		*db_aml_objtype(struct aml_value *);
51127317ceSmarco const char		*db_opregion(int);
52127317ceSmarco int			db_parse_name(void);
534e3126f2Smarco void			db_aml_dump(int, u_int8_t *);
544e3126f2Smarco void			db_aml_showvalue(struct aml_value *);
55127317ceSmarco void			db_aml_walktree(struct aml_node *);
56d478d440Sjordan 
57d478d440Sjordan const char		*db_aml_fieldacc(int);
58d478d440Sjordan const char		*db_aml_fieldlock(int);
59d478d440Sjordan const char		*db_aml_fieldupdate(int);
60cda98319Smarco 
61cda98319Smarco extern struct aml_node	aml_root;
62cda98319Smarco 
63cda98319Smarco /* name of scope for lexer */
64cda98319Smarco char			scope[80];
65cda98319Smarco 
664e3126f2Smarco const char *
674e3126f2Smarco db_opregion(int id)
684e3126f2Smarco {
694e3126f2Smarco 	switch (id) {
704e3126f2Smarco 	case 0:
714e3126f2Smarco 		return "SystemMemory";
724e3126f2Smarco 	case 1:
734e3126f2Smarco 		return "SystemIO";
744e3126f2Smarco 	case 2:
754e3126f2Smarco 		return "PCIConfig";
764e3126f2Smarco 	case 3:
774e3126f2Smarco 		return "Embedded";
784e3126f2Smarco 	case 4:
794e3126f2Smarco 		return "SMBus";
804e3126f2Smarco 	case 5:
814e3126f2Smarco 		return "CMOS";
824e3126f2Smarco 	case 6:
834e3126f2Smarco 		return "PCIBAR";
844e3126f2Smarco 	}
854e3126f2Smarco 	return "";
864e3126f2Smarco }
874e3126f2Smarco void
884e3126f2Smarco db_aml_dump(int len, u_int8_t *buf)
894e3126f2Smarco {
904e3126f2Smarco 	int		idx;
914e3126f2Smarco 
924e3126f2Smarco 	db_printf("{ ");
937d03a03dSmarco 	for (idx = 0; idx < len; idx++)
944e3126f2Smarco 		db_printf("%s0x%.2x", idx ? ", " : "", buf[idx]);
954e3126f2Smarco 	db_printf(" }\n");
964e3126f2Smarco }
974e3126f2Smarco 
984e3126f2Smarco void
994e3126f2Smarco db_aml_showvalue(struct aml_value *value)
1004e3126f2Smarco {
1014e3126f2Smarco 	int		idx;
1024e3126f2Smarco 
1034e3126f2Smarco 	if (value == NULL)
1044e3126f2Smarco 		return;
1054e3126f2Smarco 
1064e3126f2Smarco 	if (value->node)
10730a01ff4Sjordan 		db_printf("[%s] ", aml_nodename(value->node));
1084e3126f2Smarco 
10930a01ff4Sjordan 	switch (value->type & ~AML_STATIC) {
1104e3126f2Smarco 	case AML_OBJTYPE_OBJREF:
1114e3126f2Smarco 		db_printf("refof: %x {\n", value->v_objref.index);
1124e3126f2Smarco 		db_aml_showvalue(value->v_objref.ref);
1134e3126f2Smarco 		db_printf("}\n");
1144e3126f2Smarco 		break;
1154e3126f2Smarco 	case AML_OBJTYPE_NAMEREF:
1166ab98c39Sjordan 		db_printf("nameref: %s\n", value->v_nameref);
1174e3126f2Smarco 		break;
1184e3126f2Smarco 	case AML_OBJTYPE_INTEGER:
1194e3126f2Smarco 		db_printf("integer: %llx %s\n", value->v_integer,
1206ab98c39Sjordan 		    (value->type & AML_STATIC) ? "(static)" : "");
1214e3126f2Smarco 		break;
1224e3126f2Smarco 	case AML_OBJTYPE_STRING:
1234e3126f2Smarco 		db_printf("string: %s\n", value->v_string);
1244e3126f2Smarco 		break;
1254e3126f2Smarco 	case AML_OBJTYPE_PACKAGE:
1264e3126f2Smarco 		db_printf("package: %d {\n", value->length);
1274e3126f2Smarco 		for (idx = 0; idx < value->length; idx++)
1284e3126f2Smarco 			db_aml_showvalue(value->v_package[idx]);
1294e3126f2Smarco 		db_printf("}\n");
1304e3126f2Smarco 		break;
1314e3126f2Smarco 	case AML_OBJTYPE_BUFFER:
1324e3126f2Smarco 		db_printf("buffer: %d ", value->length);
1334e3126f2Smarco 		db_aml_dump(value->length, value->v_buffer);
1344e3126f2Smarco 		break;
1354e3126f2Smarco 	case AML_OBJTYPE_DEBUGOBJ:
1364e3126f2Smarco 		db_printf("debug");
1374e3126f2Smarco 		break;
1384e3126f2Smarco 	case AML_OBJTYPE_MUTEX:
1394e3126f2Smarco 		db_printf("mutex : %llx\n", value->v_integer);
1404e3126f2Smarco 		break;
1414e3126f2Smarco 	case AML_OBJTYPE_DEVICE:
1424e3126f2Smarco 		db_printf("device\n");
1434e3126f2Smarco 		break;
1444e3126f2Smarco 	case AML_OBJTYPE_EVENT:
1454e3126f2Smarco 		db_printf("event\n");
1464e3126f2Smarco 		break;
1474e3126f2Smarco 	case AML_OBJTYPE_PROCESSOR:
1484e3126f2Smarco 		db_printf("cpu: %x,%x,%x\n",
1494e3126f2Smarco 		    value->v_processor.proc_id,
1504e3126f2Smarco 		    value->v_processor.proc_addr,
1514e3126f2Smarco 		    value->v_processor.proc_len);
1524e3126f2Smarco 		break;
1534e3126f2Smarco 	case AML_OBJTYPE_METHOD:
1544e3126f2Smarco 		db_printf("method: args=%d, serialized=%d, synclevel=%d\n",
1554e3126f2Smarco 		    AML_METHOD_ARGCOUNT(value->v_method.flags),
1564e3126f2Smarco 		    AML_METHOD_SERIALIZED(value->v_method.flags),
1574e3126f2Smarco 		    AML_METHOD_SYNCLEVEL(value->v_method.flags));
1584e3126f2Smarco 		break;
1594e3126f2Smarco 	case AML_OBJTYPE_FIELDUNIT:
1604e3126f2Smarco 		db_printf("%s: access=%x,lock=%x,update=%x pos=%.4x "
1614e3126f2Smarco 		    "len=%.4x\n",
1626ab98c39Sjordan 		    aml_mnem(value->v_field.type),
1634e3126f2Smarco 		    AML_FIELD_ACCESS(value->v_field.flags),
1644e3126f2Smarco 		    AML_FIELD_LOCK(value->v_field.flags),
1654e3126f2Smarco 		    AML_FIELD_UPDATE(value->v_field.flags),
1664e3126f2Smarco 		    value->v_field.bitpos,
1674e3126f2Smarco 		    value->v_field.bitlen);
1684e3126f2Smarco 
1694e3126f2Smarco 		db_aml_showvalue(value->v_field.ref1);
1704e3126f2Smarco 		db_aml_showvalue(value->v_field.ref2);
1714e3126f2Smarco 		break;
1724e3126f2Smarco 	case AML_OBJTYPE_BUFFERFIELD:
1734e3126f2Smarco 		db_printf("%s: pos=%.4x len=%.4x ",
1746ab98c39Sjordan 		    aml_mnem(value->v_field.type),
1754e3126f2Smarco 		    value->v_field.bitpos,
1764e3126f2Smarco 		    value->v_field.bitlen);
1774e3126f2Smarco 
1784e3126f2Smarco 		db_aml_dump(aml_bytelen(value->v_field.bitlen),
1794e3126f2Smarco 		    value->v_field.ref1->v_buffer +
1804e3126f2Smarco 		    aml_bytepos(value->v_field.bitpos));
1814e3126f2Smarco 
1824e3126f2Smarco 		db_aml_showvalue(value->v_field.ref1);
1834e3126f2Smarco 		break;
1844e3126f2Smarco 	case AML_OBJTYPE_OPREGION:
1854e3126f2Smarco 		db_printf("opregion: %s,0x%llx,0x%x\n",
1864e3126f2Smarco 		    db_opregion(value->v_opregion.iospace),
1874e3126f2Smarco 		    value->v_opregion.iobase,
1884e3126f2Smarco 		    value->v_opregion.iolen);
1894e3126f2Smarco 		break;
1904e3126f2Smarco 	default:
1914e3126f2Smarco 		db_printf("unknown: %d\n", value->type);
1924e3126f2Smarco 		break;
1934e3126f2Smarco 	}
1944e3126f2Smarco }
1954e3126f2Smarco 
196cda98319Smarco const char *
197cda98319Smarco db_aml_objtype(struct aml_value *val)
198cda98319Smarco {
199cda98319Smarco 	if (val == NULL)
200cda98319Smarco 		return "nil";
201cda98319Smarco 
202cda98319Smarco 	switch (val->type) {
2036ab98c39Sjordan 	case AML_OBJTYPE_INTEGER+AML_STATIC:
204cda98319Smarco 		return "staticint";
205cda98319Smarco 	case AML_OBJTYPE_INTEGER:
206cda98319Smarco 		return "integer";
207cda98319Smarco 	case AML_OBJTYPE_STRING:
208cda98319Smarco 		return "string";
209cda98319Smarco 	case AML_OBJTYPE_BUFFER:
210cda98319Smarco 		return "buffer";
211cda98319Smarco 	case AML_OBJTYPE_PACKAGE:
212cda98319Smarco 		return "package";
213cda98319Smarco 	case AML_OBJTYPE_DEVICE:
214cda98319Smarco 		return "device";
215cda98319Smarco 	case AML_OBJTYPE_EVENT:
216cda98319Smarco 		return "event";
217cda98319Smarco 	case AML_OBJTYPE_METHOD:
218cda98319Smarco 		return "method";
219cda98319Smarco 	case AML_OBJTYPE_MUTEX:
220cda98319Smarco 		return "mutex";
221cda98319Smarco 	case AML_OBJTYPE_OPREGION:
222cda98319Smarco 		return "opregion";
223cda98319Smarco 	case AML_OBJTYPE_POWERRSRC:
224cda98319Smarco 		return "powerrsrc";
225cda98319Smarco 	case AML_OBJTYPE_PROCESSOR:
226cda98319Smarco 		return "processor";
227cda98319Smarco 	case AML_OBJTYPE_THERMZONE:
228cda98319Smarco 		return "thermzone";
229cda98319Smarco 	case AML_OBJTYPE_DDBHANDLE:
230cda98319Smarco 		return "ddbhandle";
231cda98319Smarco 	case AML_OBJTYPE_DEBUGOBJ:
232cda98319Smarco 		return "debugobj";
233cda98319Smarco 	case AML_OBJTYPE_NAMEREF:
234cda98319Smarco 		return "nameref";
235cda98319Smarco 	case AML_OBJTYPE_OBJREF:
236cda98319Smarco 		return "refof";
237cda98319Smarco 	case AML_OBJTYPE_FIELDUNIT:
238cda98319Smarco 	case AML_OBJTYPE_BUFFERFIELD:
2396ab98c39Sjordan 		return aml_mnem(val->v_field.type);
240*e6117b4fSderaadt 	}
241cda98319Smarco 
242cda98319Smarco 	return ("");
243cda98319Smarco }
244cda98319Smarco 
245cda98319Smarco void
246559cf7adSmarco db_aml_walktree(struct aml_node *node)
247559cf7adSmarco {
248559cf7adSmarco 	while (node) {
24930a01ff4Sjordan 		db_aml_showvalue(node->value);
250559cf7adSmarco 		db_aml_walktree(node->child);
25130a01ff4Sjordan 
252559cf7adSmarco 		node = node->sibling;
253559cf7adSmarco 	}
254559cf7adSmarco }
255559cf7adSmarco 
256fc0379faSmarco int
257fc0379faSmarco db_parse_name(void)
2584e3126f2Smarco {
259fc0379faSmarco 	int		t, rv = 1;
2604e3126f2Smarco 
2614e3126f2Smarco 	memset(scope, 0, sizeof scope);
2624e3126f2Smarco 	do {
2634e3126f2Smarco 		t = db_read_token();
2644e3126f2Smarco 		if (t == tIDENT) {
2654e3126f2Smarco 			if (strlcat(scope, db_tok_string, sizeof scope) >=
2664e3126f2Smarco 			    sizeof scope) {
2674e3126f2Smarco 				printf("Input too long\n");
2684e3126f2Smarco 				goto error;
2694e3126f2Smarco 			}
2704e3126f2Smarco 			t = db_read_token();
2714e3126f2Smarco 			if (t == tDOT)
2724e3126f2Smarco 				if (strlcat(scope, ".", sizeof scope) >=
2734e3126f2Smarco 				    sizeof scope) {
2744e3126f2Smarco 					printf("Input too long 2\n");
2754e3126f2Smarco 					goto error;
2764e3126f2Smarco 				}
2774e3126f2Smarco 		}
278*e6117b4fSderaadt 	} while (t != tEOL);
2794e3126f2Smarco 
2804e3126f2Smarco 	if (!strlen(scope)) {
2814e3126f2Smarco 		db_printf("Invalid input\n");
2824e3126f2Smarco 		goto error;
2834e3126f2Smarco 	}
2844e3126f2Smarco 
285fc0379faSmarco 	rv = 0;
286fc0379faSmarco error:
2874e3126f2Smarco 	/* get rid of the rest of input */
2884e3126f2Smarco 	db_flush_lex();
289fc0379faSmarco 	return (rv);
290fc0379faSmarco }
291fc0379faSmarco 
292fc0379faSmarco /* ddb interface */
293fc0379faSmarco void
294fc0379faSmarco db_acpi_showval(db_expr_t addr, int haddr, db_expr_t count, char *modif)
295fc0379faSmarco {
296fc0379faSmarco 	struct aml_node *node;
297fc0379faSmarco 
298fc0379faSmarco 	if (db_parse_name())
299fc0379faSmarco 		return;
3004e3126f2Smarco 
3014e3126f2Smarco 	node = aml_searchname(&aml_root, scope);
3024e3126f2Smarco 	if (node)
3034e3126f2Smarco 		db_aml_showvalue(node->value);
3044e3126f2Smarco 	else
3054e3126f2Smarco 		db_printf("Not a valid value\n");
3064e3126f2Smarco }
3074e3126f2Smarco 
3084e3126f2Smarco void
309cda98319Smarco db_acpi_disasm(db_expr_t addr, int haddr, db_expr_t count, char *modif)
310cda98319Smarco {
311cda98319Smarco 	struct aml_node *node;
312cda98319Smarco 
313fc0379faSmarco 	if (db_parse_name())
314fc0379faSmarco 		return;
315cda98319Smarco 
316cda98319Smarco 	node = aml_searchname(&aml_root, scope);
317cda98319Smarco 	if (node && node->value && node->value->type == AML_OBJTYPE_METHOD) {
318*e6117b4fSderaadt 		db_aml_disasm(node, node->value->v_method.start,
319*e6117b4fSderaadt 		    node->value->v_method.end, -1, 0);
3204e3126f2Smarco 	} else
3214e3126f2Smarco 		db_printf("Not a valid method\n");
322cda98319Smarco }
323cda98319Smarco 
324cda98319Smarco void
325559cf7adSmarco db_acpi_tree(db_expr_t addr, int haddr, db_expr_t count, char *modif)
326559cf7adSmarco {
327559cf7adSmarco 	db_aml_walktree(aml_root.child);
328559cf7adSmarco }
32930a01ff4Sjordan 
3306c53ca5eSjordan void
3316c53ca5eSjordan db_acpi_trace(db_expr_t addr, int haddr, db_expr_t count, char *modif)
3326c53ca5eSjordan {
3336c53ca5eSjordan 	struct aml_scope *root;
3346c53ca5eSjordan 	int idx;
3356c53ca5eSjordan 	extern struct aml_scope *aml_lastscope;
3366c53ca5eSjordan 
3376c53ca5eSjordan 	for (root=aml_lastscope; root && root->pos; root=root->parent) {
3386c53ca5eSjordan 		db_printf("%.4x Called: %s\n", aml_pc(root->pos),
3396c53ca5eSjordan 		    aml_nodename(root->node));
3406c53ca5eSjordan 		for (idx = 0; idx<root->nargs; idx++) {
3416c53ca5eSjordan 			db_printf("  arg%d: ", idx);
3426c53ca5eSjordan 			db_aml_showvalue(&root->args[idx]);
3436c53ca5eSjordan 		}
3446c53ca5eSjordan 		for (idx = 0; root->locals && idx < AML_MAX_LOCAL; idx++) {
3456c53ca5eSjordan 			if (root->locals[idx].type) {
3466c53ca5eSjordan 				db_printf("  local%d: ", idx);
3476c53ca5eSjordan 				db_aml_showvalue(&root->locals[idx]);
3486c53ca5eSjordan 			}
3496c53ca5eSjordan 		}
3506c53ca5eSjordan 	}
3516c53ca5eSjordan }
3526c53ca5eSjordan 
35330a01ff4Sjordan void
35430a01ff4Sjordan db_aml_disline(uint8_t *pos, int depth, const char *fmt, ...)
3556ab98c39Sjordan {
35630a01ff4Sjordan 	va_list ap;
35730a01ff4Sjordan 	char line[128];
35830a01ff4Sjordan 
35930a01ff4Sjordan 	db_printf("%.6x: ", aml_pc(pos));
36030a01ff4Sjordan 	while (depth--)
36130a01ff4Sjordan 		db_printf("  ");
36230a01ff4Sjordan 
36330a01ff4Sjordan 	va_start(ap, fmt);
36430a01ff4Sjordan 	vsnprintf(line, sizeof(line), fmt, ap);
36530a01ff4Sjordan 	db_printf(line);
36630a01ff4Sjordan 	va_end(ap);
3676ab98c39Sjordan }
36830a01ff4Sjordan 
36930a01ff4Sjordan void
37030a01ff4Sjordan db_aml_disint(struct aml_scope *scope, int opcode, int depth)
3716ab98c39Sjordan {
37230a01ff4Sjordan 	switch (opcode) {
37330a01ff4Sjordan 	case AML_ANYINT:
37430a01ff4Sjordan 		db_aml_disasm(scope->node, scope->pos, scope->end, -1, depth);
37530a01ff4Sjordan 		break;
37630a01ff4Sjordan 	case AMLOP_BYTEPREFIX:
377*e6117b4fSderaadt 		db_aml_disline(scope->pos, depth, "0x%.2x\n",
378*e6117b4fSderaadt 		    *(uint8_t *)(scope->pos));
37930a01ff4Sjordan 		scope->pos += 1;
38030a01ff4Sjordan 		break;
38130a01ff4Sjordan 	case AMLOP_WORDPREFIX:
382*e6117b4fSderaadt 		db_aml_disline(scope->pos, depth, "0x%.4x\n",
383*e6117b4fSderaadt 		    *(uint16_t *)(scope->pos));
38430a01ff4Sjordan 		scope->pos += 2;
38530a01ff4Sjordan 		break;
38630a01ff4Sjordan 	case AMLOP_DWORDPREFIX:
387*e6117b4fSderaadt 		db_aml_disline(scope->pos, depth, "0x%.8x\n",
388*e6117b4fSderaadt 		    *(uint32_t *)(scope->pos));
38930a01ff4Sjordan 		scope->pos += 4;
39030a01ff4Sjordan 		break;
39130a01ff4Sjordan 	case AMLOP_QWORDPREFIX:
392*e6117b4fSderaadt 		db_aml_disline(scope->pos, depth, "0x%.4llx\n",
393*e6117b4fSderaadt 		    *(uint64_t *)(scope->pos));
39430a01ff4Sjordan 		scope->pos += 8;
39530a01ff4Sjordan 		break;
39630a01ff4Sjordan 	}
39730a01ff4Sjordan }
39830a01ff4Sjordan 
39930a01ff4Sjordan uint8_t *
40030a01ff4Sjordan db_aml_disasm(struct aml_node *root, uint8_t *start, uint8_t *end,
40130a01ff4Sjordan     int count, int depth)
40230a01ff4Sjordan {
40330a01ff4Sjordan 	int idx, opcode, len, off=0;
40430a01ff4Sjordan 	struct aml_scope *scope;
40530a01ff4Sjordan 	uint8_t *name, *pos;
40630a01ff4Sjordan 	const char *mnem, *args;
40730a01ff4Sjordan 	struct aml_node *node;
40830a01ff4Sjordan 	char *tmpstr;
40930a01ff4Sjordan 
41030a01ff4Sjordan 	if (start == end)
41130a01ff4Sjordan 		return end;
41230a01ff4Sjordan 
41330a01ff4Sjordan 	scope = aml_pushscope(NULL, start, end, root);
41430a01ff4Sjordan 	while (scope->pos < scope->end && count--) {
41530a01ff4Sjordan 		pos = scope->pos;
41630a01ff4Sjordan 		start = scope->pos;
41730a01ff4Sjordan 		opcode = aml_parseopcode(scope);
41830a01ff4Sjordan 
41930a01ff4Sjordan 		mnem = aml_mnem(opcode);
42030a01ff4Sjordan 		args = aml_args(opcode);
42130a01ff4Sjordan 
42230a01ff4Sjordan 		if (*args == 'p') {
42330a01ff4Sjordan 			end = aml_parseend(scope);
42430a01ff4Sjordan 			args++;
42530a01ff4Sjordan 		}
42630a01ff4Sjordan 		node = scope->node;
42730a01ff4Sjordan 		if (*args == 'N') {
42830a01ff4Sjordan 			name = aml_parsename(scope);
42930a01ff4Sjordan 			node = aml_searchname(scope->node, name);
43030a01ff4Sjordan 			db_aml_disline(pos, depth, "%s %s (%s)\n",
431*e6117b4fSderaadt 			    mnem, aml_getname(name), aml_nodename(node));
43230a01ff4Sjordan 			args++;
433*e6117b4fSderaadt 		} else if (mnem[0] != '.') {
43430a01ff4Sjordan 			db_aml_disline(pos, depth, "%s\n", mnem);
43530a01ff4Sjordan 		}
43630a01ff4Sjordan 		while (*args) {
43730a01ff4Sjordan 			pos = scope->pos;
43830a01ff4Sjordan 			switch (*args) {
43930a01ff4Sjordan 			case 'k':
44030a01ff4Sjordan 			case 'c':
44130a01ff4Sjordan 			case 'D':
44230a01ff4Sjordan 			case 'L':
44330a01ff4Sjordan 			case 'A':
44430a01ff4Sjordan 				break;
44530a01ff4Sjordan 			case 'i':
44630a01ff4Sjordan 			case 't':
44730a01ff4Sjordan 			case 'S':
44830a01ff4Sjordan 			case 'r':
449*e6117b4fSderaadt 				scope->pos = db_aml_disasm(node, scope->pos,
450*e6117b4fSderaadt 				    scope->end, 1, depth+1);
45130a01ff4Sjordan 				break;
45230a01ff4Sjordan 			case 'T':
45330a01ff4Sjordan 			case 'M':
454*e6117b4fSderaadt 				scope->pos = db_aml_disasm(node, scope->pos,
455*e6117b4fSderaadt 				    end, -1, depth+1);
45630a01ff4Sjordan 				break;
45730a01ff4Sjordan 			case 'I':
45830a01ff4Sjordan 				/* Special case: if */
459*e6117b4fSderaadt 				scope->pos = db_aml_disasm(node, scope->pos,
460*e6117b4fSderaadt 				    end, -1, depth+1);
46130a01ff4Sjordan 				if (scope->pos >= scope->end)
46230a01ff4Sjordan 					break;
46330a01ff4Sjordan 				if (*scope->pos == AMLOP_ELSE) {
46430a01ff4Sjordan 					++scope->pos;
46530a01ff4Sjordan 					end = aml_parseend(scope);
46630a01ff4Sjordan 					db_aml_disline(scope->pos, depth, "Else\n");
467*e6117b4fSderaadt 					scope->pos = db_aml_disasm(node, scope->pos,
468*e6117b4fSderaadt 					    end, -1, depth+1);
46930a01ff4Sjordan 				}
47030a01ff4Sjordan 				break;
47130a01ff4Sjordan 			case 'N':
47230a01ff4Sjordan 				name = aml_parsename(scope);
47330a01ff4Sjordan 				db_aml_disline(pos, depth+1, "%s\n", aml_getname(name));
47430a01ff4Sjordan 				break;
47530a01ff4Sjordan 			case 'n':
47630a01ff4Sjordan 				off = (opcode != AMLOP_NAMECHAR);
47730a01ff4Sjordan 				name = aml_parsename(scope);
47830a01ff4Sjordan 				node = aml_searchname(scope->node, name);
47930a01ff4Sjordan 				db_aml_disline(pos, depth+off, "%s <%s>\n",
48030a01ff4Sjordan 					       aml_getname(name),
48130a01ff4Sjordan 					       aml_nodename(node));
48230a01ff4Sjordan 
483*e6117b4fSderaadt 				if (!node || !node->value ||
484*e6117b4fSderaadt 				    node->value->type != AML_OBJTYPE_METHOD)
48530a01ff4Sjordan 					break;
48630a01ff4Sjordan 
48730a01ff4Sjordan 				/* Method calls */
48830a01ff4Sjordan 				for (idx=0;
48930a01ff4Sjordan 				     idx<AML_METHOD_ARGCOUNT(node->value->v_method.flags);
49030a01ff4Sjordan 				     idx++) {
491*e6117b4fSderaadt 					scope->pos = db_aml_disasm(node, scope->pos,
492*e6117b4fSderaadt 					    scope->end, 1, depth+1);
49330a01ff4Sjordan 				}
49430a01ff4Sjordan 				break;
49530a01ff4Sjordan 			case 'b':
49630a01ff4Sjordan 				off = (opcode != AMLOP_BYTEPREFIX);
49730a01ff4Sjordan 				db_aml_disint(scope, AMLOP_BYTEPREFIX, depth+off);
49830a01ff4Sjordan 				break;
49930a01ff4Sjordan 			case 'w':
50030a01ff4Sjordan 				off = (opcode != AMLOP_WORDPREFIX);
50130a01ff4Sjordan 				db_aml_disint(scope, AMLOP_WORDPREFIX, depth+off);
50230a01ff4Sjordan 				break;
50330a01ff4Sjordan 			case 'd':
50430a01ff4Sjordan 				off = (opcode != AMLOP_DWORDPREFIX);
50530a01ff4Sjordan 				db_aml_disint(scope, AMLOP_DWORDPREFIX, depth+off);
50630a01ff4Sjordan 				break;
50730a01ff4Sjordan 			case 's':
50830a01ff4Sjordan 				db_aml_disline(pos, depth, "\"%s\"\n", scope->pos);
50930a01ff4Sjordan 				scope->pos += strlen(scope->pos)+1;
51030a01ff4Sjordan 				break;
51130a01ff4Sjordan 			case 'B':
51230a01ff4Sjordan 				tmpstr = malloc(16 * 6 + 1, M_DEVBUF, M_WAITOK);
51330a01ff4Sjordan 				for (idx=0; idx<min(end-scope->pos, 8); idx++)
514*e6117b4fSderaadt 					snprintf(tmpstr+idx*6, 7, "0x%.2x, ",
515*e6117b4fSderaadt 					    scope->pos[idx]);
51630a01ff4Sjordan 				db_aml_disline(pos, depth+1, "ByteList <%s>\n", tmpstr);
51730a01ff4Sjordan 			        free(tmpstr, M_DEVBUF);
51830a01ff4Sjordan 				scope->pos = end;
51930a01ff4Sjordan 				break;
52030a01ff4Sjordan 			case 'F':
52130a01ff4Sjordan 				off = 0;
52230a01ff4Sjordan 				while (scope->pos < end) {
52330a01ff4Sjordan 					len = 0;
52430a01ff4Sjordan 					pos = scope->pos;
52530a01ff4Sjordan 					switch (*scope->pos) {
52630a01ff4Sjordan 					case 0x00: // reserved
52730a01ff4Sjordan 						scope->pos++;
52830a01ff4Sjordan 						len = aml_parselength(scope);
529*e6117b4fSderaadt 						db_aml_disline(pos, depth+1,
530*e6117b4fSderaadt 						    "Reserved\t%.4x,%.4x\n",
53130a01ff4Sjordan 						     off, len);
53230a01ff4Sjordan 						break;
53330a01ff4Sjordan 					case 0x01: // attr
534*e6117b4fSderaadt 						db_aml_disline(pos, depth+1,
535*e6117b4fSderaadt 						    "Attr:%.2x,%.2x\n",
53630a01ff4Sjordan 						     scope->pos[1], scope->pos[2]);
53730a01ff4Sjordan 						scope->pos += 3;
53830a01ff4Sjordan 						break;
53930a01ff4Sjordan 					default:
54030a01ff4Sjordan 						name = aml_parsename(scope);
54130a01ff4Sjordan 						len = aml_parselength(scope);
542*e6117b4fSderaadt 						db_aml_disline(pos, depth+1,
543*e6117b4fSderaadt 						    "NamedField\t%.4x,%.4x %s\n",
54430a01ff4Sjordan 						    off, len, aml_getname(name));
54530a01ff4Sjordan 					}
54630a01ff4Sjordan 					off += len;
54730a01ff4Sjordan 				}
54830a01ff4Sjordan 				scope->pos = end;
54930a01ff4Sjordan 				break;
55030a01ff4Sjordan 			default:
55130a01ff4Sjordan 				db_printf("remaining args: '%s'\n", args);
55230a01ff4Sjordan 			}
55330a01ff4Sjordan 			args++;
55430a01ff4Sjordan 		}
55530a01ff4Sjordan 	}
55630a01ff4Sjordan 	pos = scope->pos;
55730a01ff4Sjordan 	aml_popscope(scope);
55830a01ff4Sjordan 	return pos;
5596ab98c39Sjordan }
560