This source file includes following definitions.
- db_opregion
- db_aml_dump
- db_aml_showvalue
- db_aml_objtype
- db_aml_walktree
- db_parse_name
- db_acpi_showval
- db_acpi_disasm
- db_acpi_tree
- db_acpi_trace
- db_aml_disline
- db_aml_disint
- db_aml_disasm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 void db_aml_disline(uint8_t *, int, const char *, ...);
34 void db_aml_disint(struct aml_scope *, int, int);
35 uint8_t *db_aml_disasm(struct aml_node *, uint8_t *, uint8_t *, int, int);
36
37 extern int aml_pc(uint8_t *);
38 extern struct aml_scope *aml_pushscope(struct aml_scope *, uint8_t *, uint8_t *, struct aml_node *);
39 extern struct aml_scope *aml_popscope(struct aml_scope *);
40 extern uint8_t *aml_parsename(struct aml_scope *);
41 extern uint8_t *aml_parseend(struct aml_scope *);
42 extern int aml_parselength(struct aml_scope *);
43 extern int aml_parseopcode(struct aml_scope *);
44
45 extern const char *aml_mnem(int opcode, uint8_t *);
46 extern const char *aml_args(int opcode);
47 extern const char *aml_getname(uint8_t *);
48 extern const char *aml_nodename(struct aml_node *);
49
50 const char *db_aml_objtype(struct aml_value *);
51 const char *db_opregion(int);
52 int db_parse_name(void);
53 void db_aml_dump(int, u_int8_t *);
54 void db_aml_showvalue(struct aml_value *);
55 void db_aml_walktree(struct aml_node *);
56
57 const char *db_aml_fieldacc(int);
58 const char *db_aml_fieldlock(int);
59 const char *db_aml_fieldupdate(int);
60
61 extern struct aml_node aml_root;
62
63
64 char scope[80];
65
66 const char *
67 db_opregion(int id)
68 {
69 switch (id) {
70 case 0:
71 return "SystemMemory";
72 case 1:
73 return "SystemIO";
74 case 2:
75 return "PCIConfig";
76 case 3:
77 return "Embedded";
78 case 4:
79 return "SMBus";
80 case 5:
81 return "CMOS";
82 case 6:
83 return "PCIBAR";
84 }
85 return "";
86 }
87 void
88 db_aml_dump(int len, u_int8_t *buf)
89 {
90 int idx;
91
92 db_printf("{ ");
93 for (idx = 0; idx < len; idx++)
94 db_printf("%s0x%.2x", idx ? ", " : "", buf[idx]);
95 db_printf(" }\n");
96 }
97
98 void
99 db_aml_showvalue(struct aml_value *value)
100 {
101 int idx;
102
103 if (value == NULL)
104 return;
105
106 if (value->node)
107 db_printf("[%s] ", aml_nodename(value->node));
108
109 switch (value->type & ~AML_STATIC) {
110 case AML_OBJTYPE_OBJREF:
111 db_printf("refof: %x {\n", value->v_objref.index);
112 db_aml_showvalue(value->v_objref.ref);
113 db_printf("}\n");
114 break;
115 case AML_OBJTYPE_NAMEREF:
116 db_printf("nameref: %s\n", value->v_nameref);
117 break;
118 case AML_OBJTYPE_INTEGER:
119 db_printf("integer: %llx %s\n", value->v_integer,
120 (value->type & AML_STATIC) ? "(static)" : "");
121 break;
122 case AML_OBJTYPE_STRING:
123 db_printf("string: %s\n", value->v_string);
124 break;
125 case AML_OBJTYPE_PACKAGE:
126 db_printf("package: %d {\n", value->length);
127 for (idx = 0; idx < value->length; idx++)
128 db_aml_showvalue(value->v_package[idx]);
129 db_printf("}\n");
130 break;
131 case AML_OBJTYPE_BUFFER:
132 db_printf("buffer: %d ", value->length);
133 db_aml_dump(value->length, value->v_buffer);
134 break;
135 case AML_OBJTYPE_DEBUGOBJ:
136 db_printf("debug");
137 break;
138 case AML_OBJTYPE_MUTEX:
139 db_printf("mutex : %llx\n", value->v_integer);
140 break;
141 case AML_OBJTYPE_DEVICE:
142 db_printf("device\n");
143 break;
144 case AML_OBJTYPE_EVENT:
145 db_printf("event\n");
146 break;
147 case AML_OBJTYPE_PROCESSOR:
148 db_printf("cpu: %x,%x,%x\n",
149 value->v_processor.proc_id,
150 value->v_processor.proc_addr,
151 value->v_processor.proc_len);
152 break;
153 case AML_OBJTYPE_METHOD:
154 db_printf("method: args=%d, serialized=%d, synclevel=%d\n",
155 AML_METHOD_ARGCOUNT(value->v_method.flags),
156 AML_METHOD_SERIALIZED(value->v_method.flags),
157 AML_METHOD_SYNCLEVEL(value->v_method.flags));
158 break;
159 case AML_OBJTYPE_FIELDUNIT:
160 db_printf("%s: access=%x,lock=%x,update=%x pos=%.4x "
161 "len=%.4x\n",
162 aml_mnem(value->v_field.type, NULL),
163 AML_FIELD_ACCESS(value->v_field.flags),
164 AML_FIELD_LOCK(value->v_field.flags),
165 AML_FIELD_UPDATE(value->v_field.flags),
166 value->v_field.bitpos,
167 value->v_field.bitlen);
168
169 db_aml_showvalue(value->v_field.ref1);
170 db_aml_showvalue(value->v_field.ref2);
171 break;
172 case AML_OBJTYPE_BUFFERFIELD:
173 db_printf("%s: pos=%.4x len=%.4x ",
174 aml_mnem(value->v_field.type, NULL),
175 value->v_field.bitpos,
176 value->v_field.bitlen);
177
178 db_aml_dump(aml_bytelen(value->v_field.bitlen),
179 value->v_field.ref1->v_buffer +
180 aml_bytepos(value->v_field.bitpos));
181
182 db_aml_showvalue(value->v_field.ref1);
183 break;
184 case AML_OBJTYPE_OPREGION:
185 db_printf("opregion: %s,0x%llx,0x%x\n",
186 db_opregion(value->v_opregion.iospace),
187 value->v_opregion.iobase,
188 value->v_opregion.iolen);
189 break;
190 default:
191 db_printf("unknown: %d\n", value->type);
192 break;
193 }
194 }
195
196 const char *
197 db_aml_objtype(struct aml_value *val)
198 {
199 if (val == NULL)
200 return "nil";
201
202 switch (val->type) {
203 case AML_OBJTYPE_INTEGER+AML_STATIC:
204 return "staticint";
205 case AML_OBJTYPE_INTEGER:
206 return "integer";
207 case AML_OBJTYPE_STRING:
208 return "string";
209 case AML_OBJTYPE_BUFFER:
210 return "buffer";
211 case AML_OBJTYPE_PACKAGE:
212 return "package";
213 case AML_OBJTYPE_DEVICE:
214 return "device";
215 case AML_OBJTYPE_EVENT:
216 return "event";
217 case AML_OBJTYPE_METHOD:
218 return "method";
219 case AML_OBJTYPE_MUTEX:
220 return "mutex";
221 case AML_OBJTYPE_OPREGION:
222 return "opregion";
223 case AML_OBJTYPE_POWERRSRC:
224 return "powerrsrc";
225 case AML_OBJTYPE_PROCESSOR:
226 return "processor";
227 case AML_OBJTYPE_THERMZONE:
228 return "thermzone";
229 case AML_OBJTYPE_DDBHANDLE:
230 return "ddbhandle";
231 case AML_OBJTYPE_DEBUGOBJ:
232 return "debugobj";
233 case AML_OBJTYPE_NAMEREF:
234 return "nameref";
235 case AML_OBJTYPE_OBJREF:
236 return "refof";
237 case AML_OBJTYPE_FIELDUNIT:
238 case AML_OBJTYPE_BUFFERFIELD:
239 return aml_mnem(val->v_field.type, NULL);
240 }
241
242 return ("");
243 }
244
245 void
246 db_aml_walktree(struct aml_node *node)
247 {
248 while (node) {
249 db_aml_showvalue(node->value);
250 db_aml_walktree(node->child);
251
252 node = node->sibling;
253 }
254 }
255
256 int
257 db_parse_name(void)
258 {
259 int t, rv = 1;
260
261 memset(scope, 0, sizeof scope);
262 do {
263 t = db_read_token();
264 if (t == tIDENT) {
265 if (strlcat(scope, db_tok_string, sizeof scope) >=
266 sizeof scope) {
267 printf("Input too long\n");
268 goto error;
269 }
270 t = db_read_token();
271 if (t == tDOT)
272 if (strlcat(scope, ".", sizeof scope) >=
273 sizeof scope) {
274 printf("Input too long 2\n");
275 goto error;
276 }
277 }
278 } while (t != tEOL);
279
280 if (!strlen(scope)) {
281 db_printf("Invalid input\n");
282 goto error;
283 }
284
285 rv = 0;
286 error:
287
288 db_flush_lex();
289 return (rv);
290 }
291
292
293 void
294 db_acpi_showval(db_expr_t addr, int haddr, db_expr_t count, char *modif)
295 {
296 struct aml_node *node;
297
298 if (db_parse_name())
299 return;
300
301 node = aml_searchname(&aml_root, scope);
302 if (node)
303 db_aml_showvalue(node->value);
304 else
305 db_printf("Not a valid value\n");
306 }
307
308 void
309 db_acpi_disasm(db_expr_t addr, int haddr, db_expr_t count, char *modif)
310 {
311 struct aml_node *node;
312
313 if (db_parse_name())
314 return;
315
316 node = aml_searchname(&aml_root, scope);
317 if (node && node->value && node->value->type == AML_OBJTYPE_METHOD) {
318 db_aml_disasm(node, node->value->v_method.start,
319 node->value->v_method.end, -1, 0);
320 } else
321 db_printf("Not a valid method\n");
322 }
323
324 void
325 db_acpi_tree(db_expr_t addr, int haddr, db_expr_t count, char *modif)
326 {
327 db_aml_walktree(aml_root.child);
328 }
329
330 void
331 db_acpi_trace(db_expr_t addr, int haddr, db_expr_t count, char *modif)
332 {
333 struct aml_scope *root;
334 int idx;
335 extern struct aml_scope *aml_lastscope;
336
337 for (root=aml_lastscope; root && root->pos; root=root->parent) {
338 db_printf("%.4x Called: %s\n", aml_pc(root->pos),
339 aml_nodename(root->node));
340 for (idx = 0; idx<root->nargs; idx++) {
341 db_printf(" arg%d: ", idx);
342 db_aml_showvalue(&root->args[idx]);
343 }
344 for (idx = 0; root->locals && idx < AML_MAX_LOCAL; idx++) {
345 if (root->locals[idx].type) {
346 db_printf(" local%d: ", idx);
347 db_aml_showvalue(&root->locals[idx]);
348 }
349 }
350 }
351 }
352
353 void
354 db_aml_disline(uint8_t *pos, int depth, const char *fmt, ...)
355 {
356 va_list ap;
357 char line[128];
358
359 db_printf("%.6x: ", aml_pc(pos));
360 while (depth--)
361 db_printf(" ");
362
363 va_start(ap, fmt);
364 vsnprintf(line, sizeof(line), fmt, ap);
365 db_printf(line);
366 va_end(ap);
367 }
368
369 void
370 db_aml_disint(struct aml_scope *scope, int opcode, int depth)
371 {
372 switch (opcode) {
373 case AML_ANYINT:
374 db_aml_disasm(scope->node, scope->pos, scope->end, -1, depth);
375 break;
376 case AMLOP_BYTEPREFIX:
377 db_aml_disline(scope->pos, depth, "0x%.2x\n",
378 *(uint8_t *)(scope->pos));
379 scope->pos += 1;
380 break;
381 case AMLOP_WORDPREFIX:
382 db_aml_disline(scope->pos, depth, "0x%.4x\n",
383 *(uint16_t *)(scope->pos));
384 scope->pos += 2;
385 break;
386 case AMLOP_DWORDPREFIX:
387 db_aml_disline(scope->pos, depth, "0x%.8x\n",
388 *(uint32_t *)(scope->pos));
389 scope->pos += 4;
390 break;
391 case AMLOP_QWORDPREFIX:
392 db_aml_disline(scope->pos, depth, "0x%.4llx\n",
393 *(uint64_t *)(scope->pos));
394 scope->pos += 8;
395 break;
396 }
397 }
398
399 uint8_t *
400 db_aml_disasm(struct aml_node *root, uint8_t *start, uint8_t *end,
401 int count, int depth)
402 {
403 int idx, opcode, len, off=0;
404 struct aml_scope *scope;
405 uint8_t *name, *pos;
406 const char *mnem, *args;
407 struct aml_node *node;
408 char *tmpstr;
409
410 if (start == end)
411 return end;
412
413 scope = aml_pushscope(NULL, start, end, root);
414 while (scope->pos < scope->end && count--) {
415 pos = scope->pos;
416 start = scope->pos;
417 opcode = aml_parseopcode(scope);
418
419 mnem = aml_mnem(opcode, scope->pos);
420 args = aml_args(opcode);
421
422 if (*args == 'p') {
423 end = aml_parseend(scope);
424 args++;
425 }
426 node = scope->node;
427 if (*args == 'N') {
428 name = aml_parsename(scope);
429 node = aml_searchname(scope->node, name);
430 db_aml_disline(pos, depth, "%s %s (%s)\n",
431 mnem, aml_getname(name), aml_nodename(node));
432 args++;
433 } else if (mnem[0] != '.') {
434 db_aml_disline(pos, depth, "%s\n", mnem);
435 }
436 while (*args) {
437 pos = scope->pos;
438 switch (*args) {
439 case 'k':
440 case 'c':
441 case 'D':
442 case 'L':
443 case 'A':
444 break;
445 case 'i':
446 case 't':
447 case 'S':
448 case 'r':
449 scope->pos = db_aml_disasm(node, scope->pos,
450 scope->end, 1, depth+1);
451 break;
452 case 'T':
453 case 'M':
454 scope->pos = db_aml_disasm(node, scope->pos,
455 end, -1, depth+1);
456 break;
457 case 'I':
458
459 scope->pos = db_aml_disasm(node, scope->pos,
460 end, -1, depth+1);
461 if (scope->pos >= scope->end)
462 break;
463 if (*scope->pos == AMLOP_ELSE) {
464 ++scope->pos;
465 end = aml_parseend(scope);
466 db_aml_disline(scope->pos, depth, "Else\n");
467 scope->pos = db_aml_disasm(node, scope->pos,
468 end, -1, depth+1);
469 }
470 break;
471 case 'N':
472 name = aml_parsename(scope);
473 db_aml_disline(pos, depth+1, "%s\n", aml_getname(name));
474 break;
475 case 'n':
476 off = (opcode != AMLOP_NAMECHAR);
477 name = aml_parsename(scope);
478 node = aml_searchname(scope->node, name);
479 db_aml_disline(pos, depth+off, "%s <%s>\n",
480 aml_getname(name),
481 aml_nodename(node));
482
483 if (!node || !node->value ||
484 node->value->type != AML_OBJTYPE_METHOD)
485 break;
486
487
488 for (idx = 0;
489 idx < AML_METHOD_ARGCOUNT(node->value->v_method.flags);
490 idx++) {
491 scope->pos = db_aml_disasm(node, scope->pos,
492 scope->end, 1, depth+1);
493 }
494 break;
495 case 'b':
496 off = (opcode != AMLOP_BYTEPREFIX);
497 db_aml_disint(scope, AMLOP_BYTEPREFIX, depth+off);
498 break;
499 case 'w':
500 off = (opcode != AMLOP_WORDPREFIX);
501 db_aml_disint(scope, AMLOP_WORDPREFIX, depth+off);
502 break;
503 case 'd':
504 off = (opcode != AMLOP_DWORDPREFIX);
505 db_aml_disint(scope, AMLOP_DWORDPREFIX, depth+off);
506 break;
507 case 's':
508 db_aml_disline(pos, depth, "\"%s\"\n", scope->pos);
509 scope->pos += strlen(scope->pos)+1;
510 break;
511 case 'B':
512 tmpstr = malloc(16 * 6 + 1, M_DEVBUF, M_WAITOK);
513 for (idx = 0; idx < min(end-scope->pos, 8); idx++)
514 snprintf(tmpstr+idx*6, 7, "0x%.2x, ",
515 scope->pos[idx]);
516 db_aml_disline(pos, depth+1, "ByteList <%s>\n", tmpstr);
517 free(tmpstr, M_DEVBUF);
518 scope->pos = end;
519 break;
520 case 'F':
521 off = 0;
522 while (scope->pos < end) {
523 len = 0;
524 pos = scope->pos;
525 switch (*scope->pos) {
526 case 0x00:
527 scope->pos++;
528 len = aml_parselength(scope);
529 db_aml_disline(pos, depth+1,
530 "Reserved\t%.4x,%.4x\n",
531 off, len);
532 break;
533 case 0x01:
534 db_aml_disline(pos, depth+1,
535 "Attr:%.2x,%.2x\n",
536 scope->pos[1], scope->pos[2]);
537 scope->pos += 3;
538 break;
539 default:
540 name = aml_parsename(scope);
541 len = aml_parselength(scope);
542 db_aml_disline(pos, depth+1,
543 "NamedField\t%.4x,%.4x %s\n",
544 off, len, aml_getname(name));
545 }
546 off += len;
547 }
548 scope->pos = end;
549 break;
550 default:
551 db_printf("remaining args: '%s'\n", args);
552 }
553 args++;
554 }
555 }
556 pos = scope->pos;
557 aml_popscope(scope);
558 return pos;
559 }