Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*******************************************************************************
  2.  *
  3.  * Module Name: dbxface - AML Debugger external interfaces
  4.  *
  5.  ******************************************************************************/
  6.  
  7. /*
  8.  * Copyright (C) 2000 - 2015, Intel Corp.
  9.  * All rights reserved.
  10.  *
  11.  * Redistribution and use in source and binary forms, with or without
  12.  * modification, are permitted provided that the following conditions
  13.  * are met:
  14.  * 1. Redistributions of source code must retain the above copyright
  15.  *    notice, this list of conditions, and the following disclaimer,
  16.  *    without modification.
  17.  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18.  *    substantially similar to the "NO WARRANTY" disclaimer below
  19.  *    ("Disclaimer") and any redistribution must be conditioned upon
  20.  *    including a substantially similar Disclaimer requirement for further
  21.  *    binary redistribution.
  22.  * 3. Neither the names of the above-listed copyright holders nor the names
  23.  *    of any contributors may be used to endorse or promote products derived
  24.  *    from this software without specific prior written permission.
  25.  *
  26.  * Alternatively, this software may be distributed under the terms of the
  27.  * GNU General Public License ("GPL") version 2 as published by the Free
  28.  * Software Foundation.
  29.  *
  30.  * NO WARRANTY
  31.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35.  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40.  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41.  * POSSIBILITY OF SUCH DAMAGES.
  42.  */
  43.  
  44. #include <acpi/acpi.h>
  45. #include "accommon.h"
  46. #include "amlcode.h"
  47. #include "acdebug.h"
  48.  
  49. #define _COMPONENT          ACPI_CA_DEBUGGER
  50. ACPI_MODULE_NAME("dbxface")
  51.  
  52. /* Local prototypes */
  53. static acpi_status
  54. acpi_db_start_command(struct acpi_walk_state *walk_state,
  55.                       union acpi_parse_object *op);
  56.  
  57. #ifdef ACPI_OBSOLETE_FUNCTIONS
  58. void acpi_db_method_end(struct acpi_walk_state *walk_state);
  59. #endif
  60.  
  61. /*******************************************************************************
  62.  *
  63.  * FUNCTION:    acpi_db_start_command
  64.  *
  65.  * PARAMETERS:  walk_state      - Current walk
  66.  *              op              - Current executing Op, from AML interpreter
  67.  *
  68.  * RETURN:      Status
  69.  *
  70.  * DESCRIPTION: Enter debugger command loop
  71.  *
  72.  ******************************************************************************/
  73.  
  74. static acpi_status
  75. acpi_db_start_command(struct acpi_walk_state *walk_state,
  76.                       union acpi_parse_object *op)
  77. {
  78.         acpi_status status;
  79.  
  80.         /* TBD: [Investigate] are there namespace locking issues here? */
  81.  
  82.         /* acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); */
  83.  
  84.         /* Go into the command loop and await next user command */
  85.  
  86.         acpi_gbl_method_executing = TRUE;
  87.         status = AE_CTRL_TRUE;
  88.         while (status == AE_CTRL_TRUE) {
  89.                 if (acpi_gbl_debugger_configuration == DEBUGGER_MULTI_THREADED) {
  90.  
  91.                         /* Handshake with the front-end that gets user command lines */
  92.  
  93.                         acpi_os_release_mutex(acpi_gbl_db_command_complete);
  94.  
  95.                         status =
  96.                             acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
  97.                                                   ACPI_WAIT_FOREVER);
  98.                         if (ACPI_FAILURE(status)) {
  99.                                 return (status);
  100.                         }
  101.                 } else {
  102.                         /* Single threaded, we must get a command line ourselves */
  103.  
  104.                         /* Force output to console until a command is entered */
  105.  
  106.                         acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
  107.  
  108.                         /* Different prompt if method is executing */
  109.  
  110.                         if (!acpi_gbl_method_executing) {
  111.                                 acpi_os_printf("%1c ",
  112.                                                ACPI_DEBUGGER_COMMAND_PROMPT);
  113.                         } else {
  114.                                 acpi_os_printf("%1c ",
  115.                                                ACPI_DEBUGGER_EXECUTE_PROMPT);
  116.                         }
  117.  
  118.                         /* Get the user input line */
  119.  
  120.                         status = acpi_os_get_line(acpi_gbl_db_line_buf,
  121.                                                   ACPI_DB_LINE_BUFFER_SIZE,
  122.                                                   NULL);
  123.                         if (ACPI_FAILURE(status)) {
  124.                                 ACPI_EXCEPTION((AE_INFO, status,
  125.                                                 "While parsing command line"));
  126.                                 return (status);
  127.                         }
  128.                 }
  129.  
  130.                 status =
  131.                     acpi_db_command_dispatch(acpi_gbl_db_line_buf, walk_state,
  132.                                              op);
  133.         }
  134.  
  135.         /* acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */
  136.  
  137.         return (status);
  138. }
  139.  
  140. /*******************************************************************************
  141.  *
  142.  * FUNCTION:    acpi_db_single_step
  143.  *
  144.  * PARAMETERS:  walk_state      - Current walk
  145.  *              op              - Current executing op (from aml interpreter)
  146.  *              opcode_class    - Class of the current AML Opcode
  147.  *
  148.  * RETURN:      Status
  149.  *
  150.  * DESCRIPTION: Called just before execution of an AML opcode.
  151.  *
  152.  ******************************************************************************/
  153.  
  154. acpi_status
  155. acpi_db_single_step(struct acpi_walk_state * walk_state,
  156.                     union acpi_parse_object * op, u32 opcode_class)
  157. {
  158.         union acpi_parse_object *next;
  159.         acpi_status status = AE_OK;
  160.         u32 original_debug_level;
  161.         union acpi_parse_object *display_op;
  162.         union acpi_parse_object *parent_op;
  163.         u32 aml_offset;
  164.  
  165.         ACPI_FUNCTION_ENTRY();
  166.  
  167. #ifndef ACPI_APPLICATION
  168.         if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
  169.                 return (AE_OK);
  170.         }
  171. #endif
  172.  
  173.         /* Check the abort flag */
  174.  
  175.         if (acpi_gbl_abort_method) {
  176.                 acpi_gbl_abort_method = FALSE;
  177.                 return (AE_ABORT_METHOD);
  178.         }
  179.  
  180.         aml_offset = (u32)ACPI_PTR_DIFF(op->common.aml,
  181.                                         walk_state->parser_state.aml_start);
  182.  
  183.         /* Check for single-step breakpoint */
  184.  
  185.         if (walk_state->method_breakpoint &&
  186.             (walk_state->method_breakpoint <= aml_offset)) {
  187.  
  188.                 /* Check if the breakpoint has been reached or passed */
  189.                 /* Hit the breakpoint, resume single step, reset breakpoint */
  190.  
  191.                 acpi_os_printf("***Break*** at AML offset %X\n", aml_offset);
  192.                 acpi_gbl_cm_single_step = TRUE;
  193.                 acpi_gbl_step_to_next_call = FALSE;
  194.                 walk_state->method_breakpoint = 0;
  195.         }
  196.  
  197.         /* Check for user breakpoint (Must be on exact Aml offset) */
  198.  
  199.         else if (walk_state->user_breakpoint &&
  200.                  (walk_state->user_breakpoint == aml_offset)) {
  201.                 acpi_os_printf("***UserBreakpoint*** at AML offset %X\n",
  202.                                aml_offset);
  203.                 acpi_gbl_cm_single_step = TRUE;
  204.                 acpi_gbl_step_to_next_call = FALSE;
  205.                 walk_state->method_breakpoint = 0;
  206.         }
  207.  
  208.         /*
  209.          * Check if this is an opcode that we are interested in --
  210.          * namely, opcodes that have arguments
  211.          */
  212.         if (op->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
  213.                 return (AE_OK);
  214.         }
  215.  
  216.         switch (opcode_class) {
  217.         case AML_CLASS_UNKNOWN:
  218.         case AML_CLASS_ARGUMENT:        /* constants, literals, etc. do nothing */
  219.  
  220.                 return (AE_OK);
  221.  
  222.         default:
  223.  
  224.                 /* All other opcodes -- continue */
  225.                 break;
  226.         }
  227.  
  228.         /*
  229.          * Under certain debug conditions, display this opcode and its operands
  230.          */
  231.         if ((acpi_gbl_db_output_to_file) ||
  232.             (acpi_gbl_cm_single_step) || (acpi_dbg_level & ACPI_LV_PARSE)) {
  233.                 if ((acpi_gbl_db_output_to_file) ||
  234.                     (acpi_dbg_level & ACPI_LV_PARSE)) {
  235.                         acpi_os_printf
  236.                             ("\n[AmlDebug] Next AML Opcode to execute:\n");
  237.                 }
  238.  
  239.                 /*
  240.                  * Display this op (and only this op - zero out the NEXT field
  241.                  * temporarily, and disable parser trace output for the duration of
  242.                  * the display because we don't want the extraneous debug output)
  243.                  */
  244.                 original_debug_level = acpi_dbg_level;
  245.                 acpi_dbg_level &= ~(ACPI_LV_PARSE | ACPI_LV_FUNCTIONS);
  246.                 next = op->common.next;
  247.                 op->common.next = NULL;
  248.  
  249.                 display_op = op;
  250.                 parent_op = op->common.parent;
  251.                 if (parent_op) {
  252.                         if ((walk_state->control_state) &&
  253.                             (walk_state->control_state->common.state ==
  254.                              ACPI_CONTROL_PREDICATE_EXECUTING)) {
  255.                                 /*
  256.                                  * We are executing the predicate of an IF or WHILE statement
  257.                                  * Search upwards for the containing IF or WHILE so that the
  258.                                  * entire predicate can be displayed.
  259.                                  */
  260.                                 while (parent_op) {
  261.                                         if ((parent_op->common.aml_opcode ==
  262.                                              AML_IF_OP)
  263.                                             || (parent_op->common.aml_opcode ==
  264.                                                 AML_WHILE_OP)) {
  265.                                                 display_op = parent_op;
  266.                                                 break;
  267.                                         }
  268.                                         parent_op = parent_op->common.parent;
  269.                                 }
  270.                         } else {
  271.                                 while (parent_op) {
  272.                                         if ((parent_op->common.aml_opcode ==
  273.                                              AML_IF_OP)
  274.                                             || (parent_op->common.aml_opcode ==
  275.                                                 AML_ELSE_OP)
  276.                                             || (parent_op->common.aml_opcode ==
  277.                                                 AML_SCOPE_OP)
  278.                                             || (parent_op->common.aml_opcode ==
  279.                                                 AML_METHOD_OP)
  280.                                             || (parent_op->common.aml_opcode ==
  281.                                                 AML_WHILE_OP)) {
  282.                                                 break;
  283.                                         }
  284.                                         display_op = parent_op;
  285.                                         parent_op = parent_op->common.parent;
  286.                                 }
  287.                         }
  288.                 }
  289.  
  290.                 /* Now we can display it */
  291.  
  292. #ifdef ACPI_DISASSEMBLER
  293.                 acpi_dm_disassemble(walk_state, display_op, ACPI_UINT32_MAX);
  294. #endif
  295.  
  296.                 if ((op->common.aml_opcode == AML_IF_OP) ||
  297.                     (op->common.aml_opcode == AML_WHILE_OP)) {
  298.                         if (walk_state->control_state->common.value) {
  299.                                 acpi_os_printf
  300.                                     ("Predicate = [True], IF block was executed\n");
  301.                         } else {
  302.                                 acpi_os_printf
  303.                                     ("Predicate = [False], Skipping IF block\n");
  304.                         }
  305.                 } else if (op->common.aml_opcode == AML_ELSE_OP) {
  306.                         acpi_os_printf
  307.                             ("Predicate = [False], ELSE block was executed\n");
  308.                 }
  309.  
  310.                 /* Restore everything */
  311.  
  312.                 op->common.next = next;
  313.                 acpi_os_printf("\n");
  314.                 if ((acpi_gbl_db_output_to_file) ||
  315.                     (acpi_dbg_level & ACPI_LV_PARSE)) {
  316.                         acpi_os_printf("\n");
  317.                 }
  318.                 acpi_dbg_level = original_debug_level;
  319.         }
  320.  
  321.         /* If we are not single stepping, just continue executing the method */
  322.  
  323.         if (!acpi_gbl_cm_single_step) {
  324.                 return (AE_OK);
  325.         }
  326.  
  327.         /*
  328.          * If we are executing a step-to-call command,
  329.          * Check if this is a method call.
  330.          */
  331.         if (acpi_gbl_step_to_next_call) {
  332.                 if (op->common.aml_opcode != AML_INT_METHODCALL_OP) {
  333.  
  334.                         /* Not a method call, just keep executing */
  335.  
  336.                         return (AE_OK);
  337.                 }
  338.  
  339.                 /* Found a method call, stop executing */
  340.  
  341.                 acpi_gbl_step_to_next_call = FALSE;
  342.         }
  343.  
  344.         /*
  345.          * If the next opcode is a method call, we will "step over" it
  346.          * by default.
  347.          */
  348.         if (op->common.aml_opcode == AML_INT_METHODCALL_OP) {
  349.  
  350.                 /* Force no more single stepping while executing called method */
  351.  
  352.                 acpi_gbl_cm_single_step = FALSE;
  353.  
  354.                 /*
  355.                  * Set the breakpoint on/before the call, it will stop execution
  356.                  * as soon as we return
  357.                  */
  358.                 walk_state->method_breakpoint = 1;      /* Must be non-zero! */
  359.         }
  360.  
  361.         status = acpi_db_start_command(walk_state, op);
  362.  
  363.         /* User commands complete, continue execution of the interrupted method */
  364.  
  365.         return (status);
  366. }
  367.  
  368. /*******************************************************************************
  369.  *
  370.  * FUNCTION:    acpi_initialize_debugger
  371.  *
  372.  * PARAMETERS:  None
  373.  *
  374.  * RETURN:      Status
  375.  *
  376.  * DESCRIPTION: Init and start debugger
  377.  *
  378.  ******************************************************************************/
  379.  
  380. acpi_status acpi_initialize_debugger(void)
  381. {
  382.         acpi_status status;
  383.  
  384.         ACPI_FUNCTION_TRACE(acpi_initialize_debugger);
  385.  
  386.         /* Init globals */
  387.  
  388.         acpi_gbl_db_buffer = NULL;
  389.         acpi_gbl_db_filename = NULL;
  390.         acpi_gbl_db_output_to_file = FALSE;
  391.  
  392.         acpi_gbl_db_debug_level = ACPI_LV_VERBOSITY2;
  393.         acpi_gbl_db_console_debug_level = ACPI_NORMAL_DEFAULT | ACPI_LV_TABLES;
  394.         acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
  395.  
  396.         acpi_gbl_db_opt_no_ini_methods = FALSE;
  397.  
  398.         acpi_gbl_db_buffer = acpi_os_allocate(ACPI_DEBUG_BUFFER_SIZE);
  399.         if (!acpi_gbl_db_buffer) {
  400.                 return_ACPI_STATUS(AE_NO_MEMORY);
  401.         }
  402.         memset(acpi_gbl_db_buffer, 0, ACPI_DEBUG_BUFFER_SIZE);
  403.  
  404.         /* Initial scope is the root */
  405.  
  406.         acpi_gbl_db_scope_buf[0] = AML_ROOT_PREFIX;
  407.         acpi_gbl_db_scope_buf[1] = 0;
  408.         acpi_gbl_db_scope_node = acpi_gbl_root_node;
  409.  
  410.         /* Initialize user commands loop */
  411.  
  412.         acpi_gbl_db_terminate_loop = FALSE;
  413.  
  414.         /*
  415.          * If configured for multi-thread support, the debug executor runs in
  416.          * a separate thread so that the front end can be in another address
  417.          * space, environment, or even another machine.
  418.          */
  419.         if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
  420.  
  421.                 /* These were created with one unit, grab it */
  422.  
  423.                 status = acpi_os_acquire_mutex(acpi_gbl_db_command_complete,
  424.                                                ACPI_WAIT_FOREVER);
  425.                 if (ACPI_FAILURE(status)) {
  426.                         acpi_os_printf("Could not get debugger mutex\n");
  427.                         return_ACPI_STATUS(status);
  428.                 }
  429.  
  430.                 status = acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
  431.                                                ACPI_WAIT_FOREVER);
  432.                 if (ACPI_FAILURE(status)) {
  433.                         acpi_os_printf("Could not get debugger mutex\n");
  434.                         return_ACPI_STATUS(status);
  435.                 }
  436.  
  437.                 /* Create the debug execution thread to execute commands */
  438.  
  439.                 acpi_gbl_db_threads_terminated = FALSE;
  440.                 status = acpi_os_execute(OSL_DEBUGGER_MAIN_THREAD,
  441.                                          acpi_db_execute_thread, NULL);
  442.                 if (ACPI_FAILURE(status)) {
  443.                         ACPI_EXCEPTION((AE_INFO, status,
  444.                                         "Could not start debugger thread"));
  445.                         acpi_gbl_db_threads_terminated = TRUE;
  446.                         return_ACPI_STATUS(status);
  447.                 }
  448.         } else {
  449.                 acpi_gbl_db_thread_id = acpi_os_get_thread_id();
  450.         }
  451.  
  452.         return_ACPI_STATUS(AE_OK);
  453. }
  454.  
  455. ACPI_EXPORT_SYMBOL(acpi_initialize_debugger)
  456.  
  457. /*******************************************************************************
  458.  *
  459.  * FUNCTION:    acpi_terminate_debugger
  460.  *
  461.  * PARAMETERS:  None
  462.  *
  463.  * RETURN:      None
  464.  *
  465.  * DESCRIPTION: Stop debugger
  466.  *
  467.  ******************************************************************************/
  468. void acpi_terminate_debugger(void)
  469. {
  470.  
  471.         /* Terminate the AML Debugger */
  472.  
  473.         acpi_gbl_db_terminate_loop = TRUE;
  474.  
  475.         if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
  476.                 acpi_os_release_mutex(acpi_gbl_db_command_ready);
  477.  
  478.                 /* Wait the AML Debugger threads */
  479.  
  480.                 while (!acpi_gbl_db_threads_terminated) {
  481.                         acpi_os_sleep(100);
  482.                 }
  483.         }
  484.  
  485.         if (acpi_gbl_db_buffer) {
  486.                 acpi_os_free(acpi_gbl_db_buffer);
  487.                 acpi_gbl_db_buffer = NULL;
  488.         }
  489.  
  490.         /* Ensure that debug output is now disabled */
  491.  
  492.         acpi_gbl_db_output_flags = ACPI_DB_DISABLE_OUTPUT;
  493. }
  494.  
  495. ACPI_EXPORT_SYMBOL(acpi_terminate_debugger)
  496.  
  497. /*******************************************************************************
  498.  *
  499.  * FUNCTION:    acpi_set_debugger_thread_id
  500.  *
  501.  * PARAMETERS:  thread_id       - Debugger thread ID
  502.  *
  503.  * RETURN:      None
  504.  *
  505.  * DESCRIPTION: Set debugger thread ID
  506.  *
  507.  ******************************************************************************/
  508. void acpi_set_debugger_thread_id(acpi_thread_id thread_id)
  509. {
  510.         acpi_gbl_db_thread_id = thread_id;
  511. }
  512.  
  513. ACPI_EXPORT_SYMBOL(acpi_set_debugger_thread_id)
  514.