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