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