1*9108e412Spatrick /* $OpenBSD: acpidebug.c,v 1.33 2022/08/10 16:58:16 patrick 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 18311b6aa8Smpi #include <sys/param.h> 19311b6aa8Smpi #include <sys/systm.h> 20311b6aa8Smpi #include <sys/malloc.h> 21311b6aa8Smpi #include <machine/bus.h> 22559cf7adSmarco #include <machine/db_machdep.h> 23559cf7adSmarco #include <ddb/db_output.h> 24cda98319Smarco #include <ddb/db_extern.h> 25cda98319Smarco #include <ddb/db_lex.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 33df33944cSmarco #ifdef DDB 3430a01ff4Sjordan 3530a01ff4Sjordan extern int aml_pc(uint8_t *); 3630a01ff4Sjordan 37048d6e7cSjordan extern const char *aml_mnem(int opcode, uint8_t *); 3830a01ff4Sjordan extern const char *aml_nodename(struct aml_node *); 39ce151df9Sjordan extern void aml_disasm(struct aml_scope *scope, int lvl, 40ce151df9Sjordan void (*dbprintf)(void *, const char *, ...), 41ce151df9Sjordan void *arg); 4230a01ff4Sjordan 43127317ceSmarco const char *db_aml_objtype(struct aml_value *); 44127317ceSmarco const char *db_opregion(int); 45127317ceSmarco int db_parse_name(void); 46d2eaebe9Skettenis void db_aml_dump(int, uint8_t *); 474e3126f2Smarco void db_aml_showvalue(struct aml_value *); 48127317ceSmarco void db_aml_walktree(struct aml_node *); 49ce151df9Sjordan void db_disprint(void *, const char *, ...); 50d478d440Sjordan 51d478d440Sjordan const char *db_aml_fieldacc(int); 52d478d440Sjordan const char *db_aml_fieldlock(int); 53d478d440Sjordan const char *db_aml_fieldupdate(int); 54cda98319Smarco 55cda98319Smarco /* name of scope for lexer */ 56cda98319Smarco char scope[80]; 57cda98319Smarco 584e3126f2Smarco const char * 594e3126f2Smarco db_opregion(int id) 604e3126f2Smarco { 614e3126f2Smarco switch (id) { 624e3126f2Smarco case 0: 634e3126f2Smarco return "SystemMemory"; 644e3126f2Smarco case 1: 654e3126f2Smarco return "SystemIO"; 664e3126f2Smarco case 2: 674e3126f2Smarco return "PCIConfig"; 684e3126f2Smarco case 3: 694e3126f2Smarco return "Embedded"; 704e3126f2Smarco case 4: 714e3126f2Smarco return "SMBus"; 724e3126f2Smarco case 5: 734e3126f2Smarco return "CMOS"; 744e3126f2Smarco case 6: 754e3126f2Smarco return "PCIBAR"; 764e3126f2Smarco } 774e3126f2Smarco return ""; 784e3126f2Smarco } 794e3126f2Smarco void 80d2eaebe9Skettenis db_aml_dump(int len, uint8_t *buf) 814e3126f2Smarco { 824e3126f2Smarco int idx; 834e3126f2Smarco 844e3126f2Smarco db_printf("{ "); 857d03a03dSmarco for (idx = 0; idx < len; idx++) 864e3126f2Smarco db_printf("%s0x%.2x", idx ? ", " : "", buf[idx]); 874e3126f2Smarco db_printf(" }\n"); 884e3126f2Smarco } 894e3126f2Smarco 904e3126f2Smarco void 914e3126f2Smarco db_aml_showvalue(struct aml_value *value) 924e3126f2Smarco { 934e3126f2Smarco int idx; 944e3126f2Smarco 954e3126f2Smarco if (value == NULL) 964e3126f2Smarco return; 974e3126f2Smarco 984e3126f2Smarco if (value->node) 9930a01ff4Sjordan db_printf("[%s] ", aml_nodename(value->node)); 1004e3126f2Smarco 1010cfeeb27Sjordan switch (value->type) { 1024e3126f2Smarco case AML_OBJTYPE_OBJREF: 1034e3126f2Smarco db_printf("refof: %x {\n", value->v_objref.index); 1044e3126f2Smarco db_aml_showvalue(value->v_objref.ref); 1054e3126f2Smarco db_printf("}\n"); 1064e3126f2Smarco break; 1074e3126f2Smarco case AML_OBJTYPE_NAMEREF: 1086ab98c39Sjordan db_printf("nameref: %s\n", value->v_nameref); 1094e3126f2Smarco break; 1104e3126f2Smarco case AML_OBJTYPE_INTEGER: 1110cfeeb27Sjordan db_printf("integer: %llx\n", value->v_integer); 1124e3126f2Smarco break; 1134e3126f2Smarco case AML_OBJTYPE_STRING: 1144e3126f2Smarco db_printf("string: %s\n", value->v_string); 1154e3126f2Smarco break; 1164e3126f2Smarco case AML_OBJTYPE_PACKAGE: 1174e3126f2Smarco db_printf("package: %d {\n", value->length); 1184e3126f2Smarco for (idx = 0; idx < value->length; idx++) 1194e3126f2Smarco db_aml_showvalue(value->v_package[idx]); 1204e3126f2Smarco db_printf("}\n"); 1214e3126f2Smarco break; 1224e3126f2Smarco case AML_OBJTYPE_BUFFER: 1234e3126f2Smarco db_printf("buffer: %d ", value->length); 1244e3126f2Smarco db_aml_dump(value->length, value->v_buffer); 1254e3126f2Smarco break; 1264e3126f2Smarco case AML_OBJTYPE_DEBUGOBJ: 1274e3126f2Smarco db_printf("debug"); 1284e3126f2Smarco break; 1294e3126f2Smarco case AML_OBJTYPE_MUTEX: 1304e3126f2Smarco db_printf("mutex : %llx\n", value->v_integer); 1314e3126f2Smarco break; 1324e3126f2Smarco case AML_OBJTYPE_DEVICE: 1334e3126f2Smarco db_printf("device\n"); 1344e3126f2Smarco break; 1354e3126f2Smarco case AML_OBJTYPE_EVENT: 1364e3126f2Smarco db_printf("event\n"); 1374e3126f2Smarco break; 1384e3126f2Smarco case AML_OBJTYPE_PROCESSOR: 1394e3126f2Smarco db_printf("cpu: %x,%x,%x\n", 1404e3126f2Smarco value->v_processor.proc_id, 1414e3126f2Smarco value->v_processor.proc_addr, 1424e3126f2Smarco value->v_processor.proc_len); 1434e3126f2Smarco break; 1444e3126f2Smarco case AML_OBJTYPE_METHOD: 1454e3126f2Smarco db_printf("method: args=%d, serialized=%d, synclevel=%d\n", 1464e3126f2Smarco AML_METHOD_ARGCOUNT(value->v_method.flags), 1474e3126f2Smarco AML_METHOD_SERIALIZED(value->v_method.flags), 1484e3126f2Smarco AML_METHOD_SYNCLEVEL(value->v_method.flags)); 1494e3126f2Smarco break; 1504e3126f2Smarco case AML_OBJTYPE_FIELDUNIT: 1514e3126f2Smarco db_printf("%s: access=%x,lock=%x,update=%x pos=%.4x " 1524e3126f2Smarco "len=%.4x\n", 153048d6e7cSjordan aml_mnem(value->v_field.type, NULL), 1544e3126f2Smarco AML_FIELD_ACCESS(value->v_field.flags), 1554e3126f2Smarco AML_FIELD_LOCK(value->v_field.flags), 1564e3126f2Smarco AML_FIELD_UPDATE(value->v_field.flags), 1574e3126f2Smarco value->v_field.bitpos, 1584e3126f2Smarco value->v_field.bitlen); 1593b455a03Smarco if (value->v_field.ref2) 1603b455a03Smarco db_printf(" index: %.3x %s\n", 1613b455a03Smarco value->v_field.ref3, 1623b455a03Smarco aml_nodename(value->v_field.ref2->node)); 1633b455a03Smarco if (value->v_field.ref1) 1643b455a03Smarco db_printf(" data: %s\n", 1653b455a03Smarco aml_nodename(value->v_field.ref1->node)); 1664e3126f2Smarco break; 1674e3126f2Smarco case AML_OBJTYPE_BUFFERFIELD: 1683b455a03Smarco db_printf("%s: pos=%.4x len=%.4x\n", 169048d6e7cSjordan aml_mnem(value->v_field.type, NULL), 1704e3126f2Smarco value->v_field.bitpos, 1714e3126f2Smarco value->v_field.bitlen); 1723b455a03Smarco db_printf(" buffer: %s\n", 1733b455a03Smarco aml_nodename(value->v_field.ref1->node)); 1744e3126f2Smarco break; 1754e3126f2Smarco case AML_OBJTYPE_OPREGION: 1764e3126f2Smarco db_printf("opregion: %s,0x%llx,0x%x\n", 1774e3126f2Smarco db_opregion(value->v_opregion.iospace), 1784e3126f2Smarco value->v_opregion.iobase, 1794e3126f2Smarco value->v_opregion.iolen); 1804e3126f2Smarco break; 1814e3126f2Smarco default: 1824e3126f2Smarco db_printf("unknown: %d\n", value->type); 1834e3126f2Smarco break; 1844e3126f2Smarco } 1854e3126f2Smarco } 1864e3126f2Smarco 187cda98319Smarco const char * 188cda98319Smarco db_aml_objtype(struct aml_value *val) 189cda98319Smarco { 190cda98319Smarco if (val == NULL) 191cda98319Smarco return "nil"; 192cda98319Smarco 193cda98319Smarco switch (val->type) { 194cda98319Smarco case AML_OBJTYPE_INTEGER: 195cda98319Smarco return "integer"; 196cda98319Smarco case AML_OBJTYPE_STRING: 197cda98319Smarco return "string"; 198cda98319Smarco case AML_OBJTYPE_BUFFER: 199cda98319Smarco return "buffer"; 200cda98319Smarco case AML_OBJTYPE_PACKAGE: 201cda98319Smarco return "package"; 202cda98319Smarco case AML_OBJTYPE_DEVICE: 203cda98319Smarco return "device"; 204cda98319Smarco case AML_OBJTYPE_EVENT: 205cda98319Smarco return "event"; 206cda98319Smarco case AML_OBJTYPE_METHOD: 207cda98319Smarco return "method"; 208cda98319Smarco case AML_OBJTYPE_MUTEX: 209cda98319Smarco return "mutex"; 210cda98319Smarco case AML_OBJTYPE_OPREGION: 211cda98319Smarco return "opregion"; 212cda98319Smarco case AML_OBJTYPE_POWERRSRC: 213cda98319Smarco return "powerrsrc"; 214cda98319Smarco case AML_OBJTYPE_PROCESSOR: 215cda98319Smarco return "processor"; 216cda98319Smarco case AML_OBJTYPE_THERMZONE: 217cda98319Smarco return "thermzone"; 218cda98319Smarco case AML_OBJTYPE_DDBHANDLE: 219cda98319Smarco return "ddbhandle"; 220cda98319Smarco case AML_OBJTYPE_DEBUGOBJ: 221cda98319Smarco return "debugobj"; 222cda98319Smarco case AML_OBJTYPE_NAMEREF: 223cda98319Smarco return "nameref"; 224cda98319Smarco case AML_OBJTYPE_OBJREF: 225cda98319Smarco return "refof"; 226cda98319Smarco case AML_OBJTYPE_FIELDUNIT: 227cda98319Smarco case AML_OBJTYPE_BUFFERFIELD: 228048d6e7cSjordan return aml_mnem(val->v_field.type, NULL); 229e6117b4fSderaadt } 230cda98319Smarco 231cda98319Smarco return (""); 232cda98319Smarco } 233cda98319Smarco 234cda98319Smarco void 235559cf7adSmarco db_aml_walktree(struct aml_node *node) 236559cf7adSmarco { 237559cf7adSmarco while (node) { 23830a01ff4Sjordan db_aml_showvalue(node->value); 239311c37bcSjordan db_aml_walktree(SIMPLEQ_FIRST(&node->son)); 240311c37bcSjordan node = SIMPLEQ_NEXT(node, sib); 241559cf7adSmarco } 242559cf7adSmarco } 243559cf7adSmarco 244fc0379faSmarco int 245fc0379faSmarco db_parse_name(void) 2464e3126f2Smarco { 247fc0379faSmarco int t, rv = 1; 2484e3126f2Smarco 2494e3126f2Smarco memset(scope, 0, sizeof scope); 2504e3126f2Smarco do { 2514e3126f2Smarco t = db_read_token(); 2524e3126f2Smarco if (t == tIDENT) { 2534e3126f2Smarco if (strlcat(scope, db_tok_string, sizeof scope) >= 2544e3126f2Smarco sizeof scope) { 2554e3126f2Smarco printf("Input too long\n"); 2564e3126f2Smarco goto error; 2574e3126f2Smarco } 2584e3126f2Smarco t = db_read_token(); 2594e3126f2Smarco if (t == tDOT) 2604e3126f2Smarco if (strlcat(scope, ".", sizeof scope) >= 2614e3126f2Smarco sizeof scope) { 2624e3126f2Smarco printf("Input too long 2\n"); 2634e3126f2Smarco goto error; 2644e3126f2Smarco } 2654e3126f2Smarco } 266e6117b4fSderaadt } while (t != tEOL); 2674e3126f2Smarco 2684e3126f2Smarco if (!strlen(scope)) { 2694e3126f2Smarco db_printf("Invalid input\n"); 2704e3126f2Smarco goto error; 2714e3126f2Smarco } 2724e3126f2Smarco 273fc0379faSmarco rv = 0; 274fc0379faSmarco error: 2754e3126f2Smarco /* get rid of the rest of input */ 2764e3126f2Smarco db_flush_lex(); 277fc0379faSmarco return (rv); 278fc0379faSmarco } 279fc0379faSmarco 280fc0379faSmarco /* ddb interface */ 281fc0379faSmarco void 282fc0379faSmarco db_acpi_showval(db_expr_t addr, int haddr, db_expr_t count, char *modif) 283fc0379faSmarco { 284fc0379faSmarco struct aml_node *node; 285fc0379faSmarco 286fc0379faSmarco if (db_parse_name()) 287fc0379faSmarco return; 2884e3126f2Smarco 289*9108e412Spatrick node = aml_searchname(acpi_softc->sc_root, scope); 2904e3126f2Smarco if (node) 2914e3126f2Smarco db_aml_showvalue(node->value); 2924e3126f2Smarco else 2934e3126f2Smarco db_printf("Not a valid value\n"); 2944e3126f2Smarco } 2954e3126f2Smarco 2963b455a03Smarco void db_disprint(void *arg, const char *fmt, ...) 2973b455a03Smarco { 2983b455a03Smarco va_list ap; 2993b455a03Smarco 3003b455a03Smarco va_start(ap,fmt); 3010a331823Sguenther db_vprintf(fmt, ap); 3023b455a03Smarco va_end(ap); 3033b455a03Smarco } 3043b455a03Smarco 3053b455a03Smarco void 306cda98319Smarco db_acpi_disasm(db_expr_t addr, int haddr, db_expr_t count, char *modif) 307cda98319Smarco { 308cda98319Smarco struct aml_node *node; 309cda98319Smarco 310fc0379faSmarco if (db_parse_name()) 311fc0379faSmarco return; 312cda98319Smarco 313*9108e412Spatrick node = aml_searchname(acpi_softc->sc_root, scope); 314cda98319Smarco if (node && node->value && node->value->type == AML_OBJTYPE_METHOD) { 3153b455a03Smarco struct aml_scope ns; 3163b455a03Smarco 3173b455a03Smarco memset(&ns, 0, sizeof(ns)); 3183b455a03Smarco ns.pos = node->value->v_method.start; 3193b455a03Smarco ns.end = node->value->v_method.end; 3203b455a03Smarco ns.node = node; 3213b455a03Smarco while (ns.pos < ns.end) 3223b455a03Smarco aml_disasm(&ns, 0, db_disprint, 0); 3233b455a03Smarco } 3243b455a03Smarco else 3253b455a03Smarco db_printf("Not a valid method\n"); 326cda98319Smarco } 327cda98319Smarco 328cda98319Smarco void 329559cf7adSmarco db_acpi_tree(db_expr_t addr, int haddr, db_expr_t count, char *modif) 330559cf7adSmarco { 331*9108e412Spatrick db_aml_walktree(acpi_softc->sc_root); 332559cf7adSmarco } 33330a01ff4Sjordan 3346c53ca5eSjordan void 3356c53ca5eSjordan db_acpi_trace(db_expr_t addr, int haddr, db_expr_t count, char *modif) 3366c53ca5eSjordan { 3376c53ca5eSjordan struct aml_scope *root; 338ce151df9Sjordan struct aml_value *sp; 3396c53ca5eSjordan int idx; 3406c53ca5eSjordan extern struct aml_scope *aml_lastscope; 3416c53ca5eSjordan 3426c53ca5eSjordan for (root=aml_lastscope; root && root->pos; root=root->parent) { 3436c53ca5eSjordan db_printf("%.4x Called: %s\n", aml_pc(root->pos), 3446c53ca5eSjordan aml_nodename(root->node)); 345ce151df9Sjordan for (idx = 0; idx< AML_MAX_ARG; idx++) { 346ce151df9Sjordan sp = aml_getstack(root, AMLOP_ARG0 + idx); 347ce151df9Sjordan if (sp && sp->type) { 3486c53ca5eSjordan db_printf(" arg%d: ", idx); 349ce151df9Sjordan db_aml_showvalue(sp); 3506c53ca5eSjordan } 351ce151df9Sjordan } 352ce151df9Sjordan for (idx = 0; idx < AML_MAX_LOCAL; idx++) { 353ce151df9Sjordan sp = aml_getstack(root, AMLOP_LOCAL0 + idx); 354ce151df9Sjordan if (sp && sp->type) { 3556c53ca5eSjordan db_printf(" local%d: ", idx); 356ce151df9Sjordan db_aml_showvalue(sp); 3576c53ca5eSjordan } 3586c53ca5eSjordan } 3596c53ca5eSjordan } 3606c53ca5eSjordan } 3616c53ca5eSjordan 362080446a7Smarco #endif /* DDB */ 363