1/******************************************************************************* 2 * 3 * Module Name: dbdisply - debug display commands 4 * $Revision: 1.1.1.1 $ 5 * 6 ******************************************************************************/ 7 8/* 9 * Copyright (C) 2000, 2001 R. Byron Moore 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26 27#include "acpi.h" 28#include "acparser.h" 29#include "amlcode.h" 30#include "acdispat.h" 31#include "acnamesp.h" 32#include "acparser.h" 33#include "acevents.h" 34#include "acinterp.h" 35#include "acdebug.h" 36 37 38#ifdef ENABLE_DEBUGGER 39 40 41#define _COMPONENT ACPI_DEBUGGER 42 MODULE_NAME ("dbdisply") 43 44 45/****************************************************************************** 46 * 47 * FUNCTION: Acpi_db_get_pointer 48 * 49 * PARAMETERS: Target - Pointer to string to be converted 50 * 51 * RETURN: Converted pointer 52 * 53 * DESCRIPTION: Convert an ascii pointer value to a real value 54 * 55 *****************************************************************************/ 56 57void * 58acpi_db_get_pointer ( 59 void *target) 60{ 61 void *obj_ptr; 62 63 64#ifdef _IA16 65#include <stdio.h> 66 67 /* Have to handle 16-bit pointers of the form segment:offset */ 68 69 if (!sscanf (target, "%p", &obj_ptr)) { 70 acpi_os_printf ("Invalid pointer: %s\n", target); 71 return (NULL); 72 } 73 74#else 75 76 /* Simple flat pointer */ 77 78 obj_ptr = (void *) STRTOUL (target, NULL, 16); 79 80#endif 81 82 return (obj_ptr); 83} 84 85 86/******************************************************************************* 87 * 88 * FUNCTION: Acpi_db_dump_parser_descriptor 89 * 90 * PARAMETERS: Op - A parser Op descriptor 91 * 92 * RETURN: None 93 * 94 * DESCRIPTION: Display a formatted parser object 95 * 96 ******************************************************************************/ 97 98void 99acpi_db_dump_parser_descriptor ( 100 acpi_parse_object *op) 101{ 102 const acpi_opcode_info *info; 103 104 105 info = acpi_ps_get_opcode_info (op->opcode); 106 107 acpi_os_printf ("Parser Op Descriptor:\n"); 108 acpi_os_printf ("%20.20s : %4.4X\n", "Opcode", op->opcode); 109 110 DEBUG_ONLY_MEMBERS (acpi_os_printf ("%20.20s : %s\n", "Opcode Name", info->name)); 111 112 acpi_os_printf ("%20.20s : %p\n", "Value/Arg_list", op->value); 113 acpi_os_printf ("%20.20s : %p\n", "Parent", op->parent); 114 acpi_os_printf ("%20.20s : %p\n", "Next_op", op->next); 115} 116 117 118/******************************************************************************* 119 * 120 * FUNCTION: Acpi_db_decode_and_display_object 121 * 122 * PARAMETERS: Target - String with object to be displayed. Names 123 * and hex pointers are supported. 124 * Output_type - Byte, Word, Dword, or Qword (B|W|D|Q) 125 * 126 * RETURN: None 127 * 128 * DESCRIPTION: Display a formatted ACPI object 129 * 130 ******************************************************************************/ 131 132void 133acpi_db_decode_and_display_object ( 134 NATIVE_CHAR *target, 135 NATIVE_CHAR *output_type) 136{ 137 void *obj_ptr; 138 acpi_namespace_node *node; 139 u32 display = DB_BYTE_DISPLAY; 140 NATIVE_CHAR buffer[80]; 141 acpi_buffer ret_buf; 142 acpi_status status; 143 u32 size; 144 145 146 if (!target) { 147 return; 148 } 149 150 /* Decode the output type */ 151 152 if (output_type) { 153 STRUPR (output_type); 154 if (output_type[0] == 'W') { 155 display = DB_WORD_DISPLAY; 156 } 157 else if (output_type[0] == 'D') { 158 display = DB_DWORD_DISPLAY; 159 } 160 else if (output_type[0] == 'Q') { 161 display = DB_QWORD_DISPLAY; 162 } 163 } 164 165 166 ret_buf.length = sizeof (buffer); 167 ret_buf.pointer = buffer; 168 169 /* Differentiate between a number and a name */ 170 171 if ((target[0] >= 0x30) && (target[0] <= 0x39)) { 172 obj_ptr = acpi_db_get_pointer (target); 173 if (!acpi_os_readable (obj_ptr, 16)) { 174 acpi_os_printf ("Address %p is invalid in this address space\n", obj_ptr); 175 return; 176 } 177 178 /* Decode the object type */ 179 180 if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_NAMED)) { 181 /* This is a Node */ 182 183 if (!acpi_os_readable (obj_ptr, sizeof (acpi_namespace_node))) { 184 acpi_os_printf ("Cannot read entire Named object at address %p\n", obj_ptr); 185 return; 186 } 187 188 node = obj_ptr; 189 goto dump_nte; 190 } 191 192 else if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_INTERNAL)) { 193 /* This is an ACPI OBJECT */ 194 195 if (!acpi_os_readable (obj_ptr, sizeof (acpi_operand_object))) { 196 acpi_os_printf ("Cannot read entire ACPI object at address %p\n", obj_ptr); 197 return; 198 } 199 200 acpi_ut_dump_buffer (obj_ptr, sizeof (acpi_operand_object), display, ACPI_UINT32_MAX); 201 acpi_ex_dump_object_descriptor (obj_ptr, 1); 202 } 203 204 else if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_PARSER)) { 205 /* This is an Parser Op object */ 206 207 if (!acpi_os_readable (obj_ptr, sizeof (acpi_parse_object))) { 208 acpi_os_printf ("Cannot read entire Parser object at address %p\n", obj_ptr); 209 return; 210 } 211 212 213 acpi_ut_dump_buffer (obj_ptr, sizeof (acpi_parse_object), display, ACPI_UINT32_MAX); 214 acpi_db_dump_parser_descriptor ((acpi_parse_object *) obj_ptr); 215 } 216 217 else { 218 size = 16; 219 if (acpi_os_readable (obj_ptr, 64)) { 220 size = 64; 221 } 222 223 /* Just dump some memory */ 224 225 acpi_ut_dump_buffer (obj_ptr, size, display, ACPI_UINT32_MAX); 226 } 227 228 return; 229 } 230 231 232 /* The parameter is a name string that must be resolved to a Named obj */ 233 234 node = acpi_db_local_ns_lookup (target); 235 if (!node) { 236 return; 237 } 238 239 240dump_nte: 241 /* Now dump the Named obj */ 242 243 status = acpi_get_name (node, ACPI_FULL_PATHNAME, &ret_buf); 244 if (ACPI_FAILURE (status)) { 245 acpi_os_printf ("Could not convert name to pathname\n"); 246 } 247 248 else { 249 acpi_os_printf ("Object (%p) Pathname: %s\n", node, ret_buf.pointer); 250 } 251 252 if (!acpi_os_readable (node, sizeof (acpi_namespace_node))) { 253 acpi_os_printf ("Invalid Named object at address %p\n", node); 254 return; 255 } 256 257 acpi_ut_dump_buffer ((void *) node, sizeof (acpi_namespace_node), display, ACPI_UINT32_MAX); 258 acpi_ex_dump_node (node, 1); 259 260 if (node->object) { 261 acpi_os_printf ("\n_attached Object (%p):\n", node->object); 262 if (!acpi_os_readable (node->object, sizeof (acpi_operand_object))) { 263 acpi_os_printf ("Invalid internal ACPI Object at address %p\n", node->object); 264 return; 265 } 266 267 acpi_ut_dump_buffer ((void *) node->object, sizeof (acpi_operand_object), display, ACPI_UINT32_MAX); 268 acpi_ex_dump_object_descriptor (node->object, 1); 269 } 270} 271 272 273/******************************************************************************* 274 * 275 * FUNCTION: Acpi_db_decode_internal_object 276 * 277 * PARAMETERS: Obj_desc - Object to be displayed 278 * 279 * RETURN: None 280 * 281 * DESCRIPTION: Short display of an internal object. Numbers and Strings. 282 * 283 ******************************************************************************/ 284 285void 286acpi_db_decode_internal_object ( 287 acpi_operand_object *obj_desc) 288{ 289 u32 i; 290 291 292 if (!obj_desc) { 293 return; 294 } 295 296 acpi_os_printf (" %s", acpi_ut_get_type_name (obj_desc->common.type)); 297 298 switch (obj_desc->common.type) { 299 case ACPI_TYPE_INTEGER: 300 301 acpi_os_printf (" %.8X%.8X", HIDWORD (obj_desc->integer.value), 302 LODWORD (obj_desc->integer.value)); 303 break; 304 305 306 case ACPI_TYPE_STRING: 307 308 acpi_os_printf ("(%d) \"%.24s", 309 obj_desc->string.length, obj_desc->string.pointer); 310 311 if (obj_desc->string.length > 24) 312 { 313 acpi_os_printf ("..."); 314 } 315 else 316 { 317 acpi_os_printf ("\""); 318 } 319 break; 320 321 322 case ACPI_TYPE_BUFFER: 323 324 acpi_os_printf ("(%d)", obj_desc->buffer.length); 325 for (i = 0; (i < 8) && (i < obj_desc->buffer.length); i++) { 326 acpi_os_printf (" %2.2X", obj_desc->buffer.pointer[i]); 327 } 328 break; 329 } 330} 331 332 333/******************************************************************************* 334 * 335 * FUNCTION: Acpi_db_display_internal_object 336 * 337 * PARAMETERS: Obj_desc - Object to be displayed 338 * Walk_state - Current walk state 339 * 340 * RETURN: None 341 * 342 * DESCRIPTION: Short display of an internal object 343 * 344 ******************************************************************************/ 345 346void 347acpi_db_display_internal_object ( 348 acpi_operand_object *obj_desc, 349 acpi_walk_state *walk_state) 350{ 351 u8 type; 352 353 354 acpi_os_printf ("%p ", obj_desc); 355 356 if (!obj_desc) { 357 acpi_os_printf ("<Null_obj>\n"); 358 return; 359 } 360 361 362 /* Decode the object type */ 363 364 else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_PARSER)) { 365 acpi_os_printf ("<Parser> "); 366 } 367 368 else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { 369 acpi_os_printf ("<Node> Name %4.4s Type-%s", 370 &((acpi_namespace_node *)obj_desc)->name, 371 acpi_ut_get_type_name (((acpi_namespace_node *) obj_desc)->type)); 372 if (((acpi_namespace_node *) obj_desc)->flags & ANOBJ_METHOD_ARG) { 373 acpi_os_printf (" [Method Arg]"); 374 } 375 if (((acpi_namespace_node *) obj_desc)->flags & ANOBJ_METHOD_LOCAL) { 376 acpi_os_printf (" [Method Local]"); 377 } 378 } 379 380 else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { 381 type = obj_desc->common.type; 382 if (type > INTERNAL_TYPE_MAX) { 383 acpi_os_printf (" Type %x [Invalid Type]", type); 384 return; 385 } 386 387 /* Decode the ACPI object type */ 388 389 switch (obj_desc->common.type) { 390 case INTERNAL_TYPE_REFERENCE: 391 switch (obj_desc->reference.opcode) { 392 case AML_ZERO_OP: 393 acpi_os_printf ("[Const] Zero (0) [Null Target]", 0); 394 break; 395 396 case AML_ONES_OP: 397 acpi_os_printf ("[Const] Ones (0xFFFFFFFFFFFFFFFF) [No Limit]"); 398 break; 399 400 case AML_ONE_OP: 401 acpi_os_printf ("[Const] One (1)"); 402 break; 403 404 case AML_REVISION_OP: 405 acpi_os_printf ("[Const] Revision (%X)", ACPI_CA_SUPPORT_LEVEL); 406 break; 407 408 case AML_LOCAL_OP: 409 acpi_os_printf ("[Local%d]", obj_desc->reference.offset); 410 if (walk_state) { 411 obj_desc = walk_state->local_variables[obj_desc->reference.offset].object; 412 acpi_os_printf (" %p", obj_desc); 413 acpi_db_decode_internal_object (obj_desc); 414 } 415 break; 416 417 case AML_ARG_OP: 418 acpi_os_printf ("[Arg%d] ", obj_desc->reference.offset); 419 if (walk_state) { 420 obj_desc = walk_state->arguments[obj_desc->reference.offset].object; 421 acpi_os_printf (" %p", obj_desc); 422 acpi_db_decode_internal_object (obj_desc); 423 } 424 break; 425 426 case AML_DEBUG_OP: 427 acpi_os_printf ("[Debug] "); 428 break; 429 430 case AML_INDEX_OP: 431 acpi_os_printf ("[Index] "); 432 acpi_db_decode_internal_object (obj_desc->reference.object); 433 break; 434 435 default: 436 break; 437 438 } 439 break; 440 441 default: 442 acpi_os_printf ("<Obj> "); 443 acpi_os_printf (" "); 444 acpi_db_decode_internal_object (obj_desc); 445 break; 446 } 447 } 448 449 else { 450 acpi_os_printf ("<Not a valid ACPI Object Descriptor> "); 451 } 452 453 acpi_os_printf ("\n"); 454} 455 456 457/******************************************************************************* 458 * 459 * FUNCTION: Acpi_db_display_method_info 460 * 461 * PARAMETERS: Start_op - Root of the control method parse tree 462 * 463 * RETURN: None 464 * 465 * DESCRIPTION: Display information about the current method 466 * 467 ******************************************************************************/ 468 469void 470acpi_db_display_method_info ( 471 acpi_parse_object *start_op) 472{ 473 acpi_walk_state *walk_state; 474 acpi_operand_object *obj_desc; 475 acpi_namespace_node *node; 476 acpi_parse_object *root_op; 477 acpi_parse_object *op; 478 const acpi_opcode_info *op_info; 479 u32 num_ops = 0; 480 u32 num_operands = 0; 481 u32 num_operators = 0; 482 u32 num_remaining_ops = 0; 483 u32 num_remaining_operands = 0; 484 u32 num_remaining_operators = 0; 485 u32 num_args; 486 u32 concurrency; 487 u8 count_remaining = FALSE; 488 489 490 walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); 491 if (!walk_state) { 492 acpi_os_printf ("There is no method currently executing\n"); 493 return; 494 } 495 496 obj_desc = walk_state->method_desc; 497 node = walk_state->method_node; 498 499 num_args = obj_desc->method.param_count; 500 concurrency = obj_desc->method.concurrency; 501 502 acpi_os_printf ("Currently executing control method is [%4.4s]\n", &node->name); 503 acpi_os_printf ("%X arguments, max concurrency = %X\n", num_args, concurrency); 504 505 506 root_op = start_op; 507 while (root_op->parent) { 508 root_op = root_op->parent; 509 } 510 511 op = root_op; 512 513 while (op) { 514 if (op == start_op) { 515 count_remaining = TRUE; 516 } 517 518 num_ops++; 519 if (count_remaining) { 520 num_remaining_ops++; 521 } 522 523 /* Decode the opcode */ 524 525 op_info = acpi_ps_get_opcode_info (op->opcode); 526 switch (op_info->class) { 527 case AML_CLASS_ARGUMENT: 528 if (count_remaining) { 529 num_remaining_operands++; 530 } 531 532 num_operands++; 533 break; 534 535 case AML_CLASS_UNKNOWN: 536 /* Bad opcode or ASCII character */ 537 538 continue; 539 540 default: 541 if (count_remaining) { 542 num_remaining_operators++; 543 } 544 545 num_operators++; 546 break; 547 } 548 549 550 op = acpi_ps_get_depth_next (start_op, op); 551 } 552 553 acpi_os_printf ("Method contains: %X AML Opcodes - %X Operators, %X Operands\n", 554 num_ops, num_operators, num_operands); 555 556 acpi_os_printf ("Remaining to execute: %X AML Opcodes - %X Operators, %X Operands\n", 557 num_remaining_ops, num_remaining_operators, num_remaining_operands); 558} 559 560 561/******************************************************************************* 562 * 563 * FUNCTION: Acpi_db_display_locals 564 * 565 * PARAMETERS: None 566 * 567 * RETURN: None 568 * 569 * DESCRIPTION: Display all locals for the currently running control method 570 * 571 ******************************************************************************/ 572 573void 574acpi_db_display_locals (void) 575{ 576 u32 i; 577 acpi_walk_state *walk_state; 578 acpi_operand_object *obj_desc; 579 acpi_namespace_node *node; 580 581 582 walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); 583 if (!walk_state) { 584 acpi_os_printf ("There is no method currently executing\n"); 585 return; 586 } 587 588 obj_desc = walk_state->method_desc; 589 node = walk_state->method_node; 590 591 592 acpi_os_printf ("Local Variables for method [%4.4s]:\n", &node->name); 593 594 for (i = 0; i < MTH_NUM_LOCALS; i++) { 595 obj_desc = walk_state->local_variables[i].object; 596 acpi_os_printf ("Local%d: ", i); 597 acpi_db_display_internal_object (obj_desc, walk_state); 598 } 599} 600 601 602/******************************************************************************* 603 * 604 * FUNCTION: Acpi_db_display_arguments 605 * 606 * PARAMETERS: None 607 * 608 * RETURN: None 609 * 610 * DESCRIPTION: Display all arguments for the currently running control method 611 * 612 ******************************************************************************/ 613 614void 615acpi_db_display_arguments (void) 616{ 617 u32 i; 618 acpi_walk_state *walk_state; 619 acpi_operand_object *obj_desc; 620 u32 num_args; 621 u32 concurrency; 622 acpi_namespace_node *node; 623 624 625 walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); 626 if (!walk_state) { 627 acpi_os_printf ("There is no method currently executing\n"); 628 return; 629 } 630 631 obj_desc = walk_state->method_desc; 632 node = walk_state->method_node; 633 634 num_args = obj_desc->method.param_count; 635 concurrency = obj_desc->method.concurrency; 636 637 acpi_os_printf ("Method [%4.4s] has %X arguments, max concurrency = %X\n", &node->name, num_args, concurrency); 638 639 for (i = 0; i < num_args; i++) { 640 obj_desc = walk_state->arguments[i].object; 641 acpi_os_printf ("Arg%d: ", i); 642 acpi_db_display_internal_object (obj_desc, walk_state); 643 } 644} 645 646 647/******************************************************************************* 648 * 649 * FUNCTION: Acpi_db_display_results 650 * 651 * PARAMETERS: None 652 * 653 * RETURN: None 654 * 655 * DESCRIPTION: Display current contents of a method result stack 656 * 657 ******************************************************************************/ 658 659void 660acpi_db_display_results (void) 661{ 662 u32 i; 663 acpi_walk_state *walk_state; 664 acpi_operand_object *obj_desc; 665 u32 num_results = 0; 666 acpi_namespace_node *node; 667 668 669 walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); 670 if (!walk_state) { 671 acpi_os_printf ("There is no method currently executing\n"); 672 return; 673 } 674 675 obj_desc = walk_state->method_desc; 676 node = walk_state->method_node; 677 678 if (walk_state->results) { 679 num_results = walk_state->results->results.num_results; 680 } 681 682 acpi_os_printf ("Method [%4.4s] has %X stacked result objects\n", &node->name, num_results); 683 684 for (i = 0; i < num_results; i++) { 685 obj_desc = walk_state->results->results.obj_desc[i]; 686 acpi_os_printf ("Result%d: ", i); 687 acpi_db_display_internal_object (obj_desc, walk_state); 688 } 689} 690 691 692/******************************************************************************* 693 * 694 * FUNCTION: Acpi_db_display_calling_tree 695 * 696 * PARAMETERS: None 697 * 698 * RETURN: None 699 * 700 * DESCRIPTION: Display current calling tree of nested control methods 701 * 702 ******************************************************************************/ 703 704void 705acpi_db_display_calling_tree (void) 706{ 707 u32 i; 708 acpi_walk_state *walk_state; 709 acpi_namespace_node *node; 710 711 712 walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list); 713 if (!walk_state) { 714 acpi_os_printf ("There is no method currently executing\n"); 715 return; 716 } 717 718 node = walk_state->method_node; 719 720 acpi_os_printf ("Current Control Method Call Tree\n"); 721 722 for (i = 0; walk_state; i++) { 723 node = walk_state->method_node; 724 725 acpi_os_printf (" [%4.4s]\n", &node->name); 726 727 walk_state = walk_state->next; 728 } 729} 730 731 732/******************************************************************************* 733 * 734 * FUNCTION: Acpi_db_display_result_object 735 * 736 * PARAMETERS: Obj_desc - Object to be displayed 737 * Walk_state - Current walk state 738 * 739 * RETURN: None 740 * 741 * DESCRIPTION: Display the result of an AML opcode 742 * 743 ******************************************************************************/ 744 745void 746acpi_db_display_result_object ( 747 acpi_operand_object *obj_desc, 748 acpi_walk_state *walk_state) 749{ 750 751 /* TBD: [Future] We don't always want to display the result. 752 * For now, only display if single stepping 753 * however, this output is very useful in other contexts also 754 */ 755 if (!acpi_gbl_cm_single_step) { 756 return; 757 } 758 759 acpi_os_printf ("Result_obj: "); 760 acpi_db_display_internal_object (obj_desc, walk_state); 761 acpi_os_printf ("\n"); 762} 763 764 765/******************************************************************************* 766 * 767 * FUNCTION: Acpi_db_display_argument_object 768 * 769 * PARAMETERS: Obj_desc - Object to be displayed 770 * Walk_state - Current walk state 771 * 772 * RETURN: None 773 * 774 * DESCRIPTION: Display the result of an AML opcode 775 * 776 ******************************************************************************/ 777 778void 779acpi_db_display_argument_object ( 780 acpi_operand_object *obj_desc, 781 acpi_walk_state *walk_state) 782{ 783 784 785 if (!acpi_gbl_cm_single_step) { 786 return; 787 } 788 789 acpi_os_printf ("Arg_obj: "); 790 acpi_db_display_internal_object (obj_desc, walk_state); 791} 792 793#endif /* ENABLE_DEBUGGER */ 794 795