xref: /openbsd-src/sys/dev/acpi/acpidebug.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /* $OpenBSD: acpidebug.c,v 1.22 2008/06/12 20:36:50 jordan Exp $ */
2 /*
3  * Copyright (c) 2006 Marco Peereboom <marco@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <machine/db_machdep.h>
19 #include <ddb/db_command.h>
20 #include <ddb/db_output.h>
21 #include <ddb/db_extern.h>
22 #include <ddb/db_lex.h>
23 
24 #include <machine/bus.h>
25 #include <sys/malloc.h>
26 
27 #include <dev/acpi/acpireg.h>
28 #include <dev/acpi/acpivar.h>
29 #include <dev/acpi/amltypes.h>
30 #include <dev/acpi/acpidebug.h>
31 #include <dev/acpi/dsdt.h>
32 
33 #ifdef DDB
34 
35 extern int aml_pc(uint8_t *);
36 
37 extern const char *aml_mnem(int opcode, uint8_t *);
38 extern const char *aml_nodename(struct aml_node *);
39 extern void aml_disasm(struct aml_scope *scope, int lvl,
40     void (*dbprintf)(void *, const char *, ...),
41     void *arg);
42 
43 const char		*db_aml_objtype(struct aml_value *);
44 const char		*db_opregion(int);
45 int			db_parse_name(void);
46 void			db_aml_dump(int, u_int8_t *);
47 void			db_aml_showvalue(struct aml_value *);
48 void			db_aml_walktree(struct aml_node *);
49 void 			db_disprint(void *, const char *, ...);
50 
51 const char		*db_aml_fieldacc(int);
52 const char		*db_aml_fieldlock(int);
53 const char		*db_aml_fieldupdate(int);
54 
55 extern struct aml_node	aml_root;
56 
57 /* name of scope for lexer */
58 char			scope[80];
59 
60 const char *
61 db_opregion(int id)
62 {
63 	switch (id) {
64 	case 0:
65 		return "SystemMemory";
66 	case 1:
67 		return "SystemIO";
68 	case 2:
69 		return "PCIConfig";
70 	case 3:
71 		return "Embedded";
72 	case 4:
73 		return "SMBus";
74 	case 5:
75 		return "CMOS";
76 	case 6:
77 		return "PCIBAR";
78 	}
79 	return "";
80 }
81 void
82 db_aml_dump(int len, u_int8_t *buf)
83 {
84 	int		idx;
85 
86 	db_printf("{ ");
87 	for (idx = 0; idx < len; idx++)
88 		db_printf("%s0x%.2x", idx ? ", " : "", buf[idx]);
89 	db_printf(" }\n");
90 }
91 
92 void
93 db_aml_showvalue(struct aml_value *value)
94 {
95 	int		idx;
96 
97 	if (value == NULL)
98 		return;
99 
100 	if (value->node)
101 		db_printf("[%s] ", aml_nodename(value->node));
102 
103 	switch (value->type & ~AML_STATIC) {
104 	case AML_OBJTYPE_OBJREF:
105 		db_printf("refof: %x {\n", value->v_objref.index);
106 		db_aml_showvalue(value->v_objref.ref);
107 		db_printf("}\n");
108 		break;
109 	case AML_OBJTYPE_NAMEREF:
110 		db_printf("nameref: %s\n", value->v_nameref);
111 		break;
112 	case AML_OBJTYPE_INTEGER:
113 		db_printf("integer: %llx %s\n", value->v_integer,
114 		    (value->type & AML_STATIC) ? "(static)" : "");
115 		break;
116 	case AML_OBJTYPE_STRING:
117 		db_printf("string: %s\n", value->v_string);
118 		break;
119 	case AML_OBJTYPE_PACKAGE:
120 		db_printf("package: %d {\n", value->length);
121 		for (idx = 0; idx < value->length; idx++)
122 			db_aml_showvalue(value->v_package[idx]);
123 		db_printf("}\n");
124 		break;
125 	case AML_OBJTYPE_BUFFER:
126 		db_printf("buffer: %d ", value->length);
127 		db_aml_dump(value->length, value->v_buffer);
128 		break;
129 	case AML_OBJTYPE_DEBUGOBJ:
130 		db_printf("debug");
131 		break;
132 	case AML_OBJTYPE_MUTEX:
133 		db_printf("mutex : %llx\n", value->v_integer);
134 		break;
135 	case AML_OBJTYPE_DEVICE:
136 		db_printf("device\n");
137 		break;
138 	case AML_OBJTYPE_EVENT:
139 		db_printf("event\n");
140 		break;
141 	case AML_OBJTYPE_PROCESSOR:
142 		db_printf("cpu: %x,%x,%x\n",
143 		    value->v_processor.proc_id,
144 		    value->v_processor.proc_addr,
145 		    value->v_processor.proc_len);
146 		break;
147 	case AML_OBJTYPE_METHOD:
148 		db_printf("method: args=%d, serialized=%d, synclevel=%d\n",
149 		    AML_METHOD_ARGCOUNT(value->v_method.flags),
150 		    AML_METHOD_SERIALIZED(value->v_method.flags),
151 		    AML_METHOD_SYNCLEVEL(value->v_method.flags));
152 		break;
153 	case AML_OBJTYPE_FIELDUNIT:
154 		db_printf("%s: access=%x,lock=%x,update=%x pos=%.4x "
155 		    "len=%.4x\n",
156 		    aml_mnem(value->v_field.type, NULL),
157 		    AML_FIELD_ACCESS(value->v_field.flags),
158 		    AML_FIELD_LOCK(value->v_field.flags),
159 		    AML_FIELD_UPDATE(value->v_field.flags),
160 		    value->v_field.bitpos,
161 		    value->v_field.bitlen);
162 		if (value->v_field.ref2)
163 			db_printf("  index: %.3x %s\n",
164 			    value->v_field.ref3,
165 			    aml_nodename(value->v_field.ref2->node));
166 		if (value->v_field.ref1)
167 			db_printf("  data: %s\n",
168 			    aml_nodename(value->v_field.ref1->node));
169 		break;
170 	case AML_OBJTYPE_BUFFERFIELD:
171 		db_printf("%s: pos=%.4x len=%.4x\n",
172 		    aml_mnem(value->v_field.type, NULL),
173 		    value->v_field.bitpos,
174 		    value->v_field.bitlen);
175 		db_printf("  buffer: %s\n",
176 		    aml_nodename(value->v_field.ref1->node));
177 		break;
178 	case AML_OBJTYPE_OPREGION:
179 		db_printf("opregion: %s,0x%llx,0x%x\n",
180 		    db_opregion(value->v_opregion.iospace),
181 		    value->v_opregion.iobase,
182 		    value->v_opregion.iolen);
183 		break;
184 	default:
185 		db_printf("unknown: %d\n", value->type);
186 		break;
187 	}
188 }
189 
190 const char *
191 db_aml_objtype(struct aml_value *val)
192 {
193 	if (val == NULL)
194 		return "nil";
195 
196 	switch (val->type) {
197 	case AML_OBJTYPE_INTEGER+AML_STATIC:
198 		return "staticint";
199 	case AML_OBJTYPE_INTEGER:
200 		return "integer";
201 	case AML_OBJTYPE_STRING:
202 		return "string";
203 	case AML_OBJTYPE_BUFFER:
204 		return "buffer";
205 	case AML_OBJTYPE_PACKAGE:
206 		return "package";
207 	case AML_OBJTYPE_DEVICE:
208 		return "device";
209 	case AML_OBJTYPE_EVENT:
210 		return "event";
211 	case AML_OBJTYPE_METHOD:
212 		return "method";
213 	case AML_OBJTYPE_MUTEX:
214 		return "mutex";
215 	case AML_OBJTYPE_OPREGION:
216 		return "opregion";
217 	case AML_OBJTYPE_POWERRSRC:
218 		return "powerrsrc";
219 	case AML_OBJTYPE_PROCESSOR:
220 		return "processor";
221 	case AML_OBJTYPE_THERMZONE:
222 		return "thermzone";
223 	case AML_OBJTYPE_DDBHANDLE:
224 		return "ddbhandle";
225 	case AML_OBJTYPE_DEBUGOBJ:
226 		return "debugobj";
227 	case AML_OBJTYPE_NAMEREF:
228 		return "nameref";
229 	case AML_OBJTYPE_OBJREF:
230 		return "refof";
231 	case AML_OBJTYPE_FIELDUNIT:
232 	case AML_OBJTYPE_BUFFERFIELD:
233 		return aml_mnem(val->v_field.type, NULL);
234 	}
235 
236 	return ("");
237 }
238 
239 void
240 db_aml_walktree(struct aml_node *node)
241 {
242 	while (node) {
243 		db_aml_showvalue(node->value);
244 		db_aml_walktree(node->child);
245 
246 		node = node->sibling;
247 	}
248 }
249 
250 int
251 db_parse_name(void)
252 {
253 	int		t, rv = 1;
254 
255 	memset(scope, 0, sizeof scope);
256 	do {
257 		t = db_read_token();
258 		if (t == tIDENT) {
259 			if (strlcat(scope, db_tok_string, sizeof scope) >=
260 			    sizeof scope) {
261 				printf("Input too long\n");
262 				goto error;
263 			}
264 			t = db_read_token();
265 			if (t == tDOT)
266 				if (strlcat(scope, ".", sizeof scope) >=
267 				    sizeof scope) {
268 					printf("Input too long 2\n");
269 					goto error;
270 				}
271 		}
272 	} while (t != tEOL);
273 
274 	if (!strlen(scope)) {
275 		db_printf("Invalid input\n");
276 		goto error;
277 	}
278 
279 	rv = 0;
280 error:
281 	/* get rid of the rest of input */
282 	db_flush_lex();
283 	return (rv);
284 }
285 
286 /* ddb interface */
287 void
288 db_acpi_showval(db_expr_t addr, int haddr, db_expr_t count, char *modif)
289 {
290 	struct aml_node *node;
291 
292 	if (db_parse_name())
293 		return;
294 
295 	node = aml_searchname(&aml_root, scope);
296 	if (node)
297 		db_aml_showvalue(node->value);
298 	else
299 		db_printf("Not a valid value\n");
300 }
301 
302 void db_disprint(void *arg, const char *fmt, ...)
303 {
304 	va_list ap;
305 	char    stre[64];
306 
307 	va_start(ap,fmt);
308 	vsnprintf(stre, sizeof(stre), fmt, ap);
309 	va_end(ap);
310 
311 	db_printf(stre);
312 }
313 
314 void
315 db_acpi_disasm(db_expr_t addr, int haddr, db_expr_t count, char *modif)
316 {
317 	struct aml_node *node;
318 
319 	if (db_parse_name())
320 		return;
321 
322 	node = aml_searchname(&aml_root, scope);
323 	if (node && node->value && node->value->type == AML_OBJTYPE_METHOD) {
324 		struct aml_scope ns;
325 
326 		memset(&ns, 0, sizeof(ns));
327 		ns.pos   = node->value->v_method.start;
328 		ns.end   = node->value->v_method.end;
329 		ns.node  = node;
330 		while (ns.pos < ns.end)
331 			aml_disasm(&ns, 0, db_disprint, 0);
332 	}
333 	else
334 		db_printf("Not a valid method\n");
335 }
336 
337 void
338 db_acpi_tree(db_expr_t addr, int haddr, db_expr_t count, char *modif)
339 {
340 	db_aml_walktree(aml_root.child);
341 }
342 
343 void
344 db_acpi_trace(db_expr_t addr, int haddr, db_expr_t count, char *modif)
345 {
346 	struct aml_scope *root;
347 	struct aml_value *sp;
348 	int idx;
349 	extern struct aml_scope *aml_lastscope;
350 
351 	for (root=aml_lastscope; root && root->pos; root=root->parent) {
352 		db_printf("%.4x Called: %s\n", aml_pc(root->pos),
353 		    aml_nodename(root->node));
354 		for (idx = 0; idx< AML_MAX_ARG; idx++) {
355 			sp = aml_getstack(root, AMLOP_ARG0 + idx);
356 			if (sp && sp->type) {
357 				db_printf("  arg%d: ", idx);
358 				db_aml_showvalue(sp);
359 		}
360 			}
361 		for (idx = 0; idx < AML_MAX_LOCAL; idx++) {
362 			sp = aml_getstack(root, AMLOP_LOCAL0 + idx);
363 			if (sp && sp->type) {
364 				db_printf("  local%d: ", idx);
365 				db_aml_showvalue(sp);
366 		}
367 	}
368 	}
369 }
370 
371 #endif /* DDB */
372