0,0 → 1,457 |
/******************************************************************************* |
* |
* Module Name: dbutils - AML debugger utilities |
* |
******************************************************************************/ |
|
/* |
* Copyright (C) 2000 - 2015, Intel Corp. |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* 1. Redistributions of source code must retain the above copyright |
* notice, this list of conditions, and the following disclaimer, |
* without modification. |
* 2. Redistributions in binary form must reproduce at minimum a disclaimer |
* substantially similar to the "NO WARRANTY" disclaimer below |
* ("Disclaimer") and any redistribution must be conditioned upon |
* including a substantially similar Disclaimer requirement for further |
* binary redistribution. |
* 3. Neither the names of the above-listed copyright holders nor the names |
* of any contributors may be used to endorse or promote products derived |
* from this software without specific prior written permission. |
* |
* Alternatively, this software may be distributed under the terms of the |
* GNU General Public License ("GPL") version 2 as published by the Free |
* Software Foundation. |
* |
* NO WARRANTY |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
* POSSIBILITY OF SUCH DAMAGES. |
*/ |
|
#include <acpi/acpi.h> |
#include "accommon.h" |
#include "acnamesp.h" |
#include "acdebug.h" |
|
#define _COMPONENT ACPI_CA_DEBUGGER |
ACPI_MODULE_NAME("dbutils") |
|
/* Local prototypes */ |
#ifdef ACPI_OBSOLETE_FUNCTIONS |
acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root); |
|
void acpi_db_dump_buffer(u32 address); |
#endif |
|
static char *gbl_hex_to_ascii = "0123456789ABCDEF"; |
|
/******************************************************************************* |
* |
* FUNCTION: acpi_db_match_argument |
* |
* PARAMETERS: user_argument - User command line |
* arguments - Array of commands to match against |
* |
* RETURN: Index into command array or ACPI_TYPE_NOT_FOUND if not found |
* |
* DESCRIPTION: Search command array for a command match |
* |
******************************************************************************/ |
|
acpi_object_type |
acpi_db_match_argument(char *user_argument, |
struct acpi_db_argument_info *arguments) |
{ |
u32 i; |
|
if (!user_argument || user_argument[0] == 0) { |
return (ACPI_TYPE_NOT_FOUND); |
} |
|
for (i = 0; arguments[i].name; i++) { |
if (strstr(arguments[i].name, user_argument) == |
arguments[i].name) { |
return (i); |
} |
} |
|
/* Argument not recognized */ |
|
return (ACPI_TYPE_NOT_FOUND); |
} |
|
/******************************************************************************* |
* |
* FUNCTION: acpi_db_set_output_destination |
* |
* PARAMETERS: output_flags - Current flags word |
* |
* RETURN: None |
* |
* DESCRIPTION: Set the current destination for debugger output. Also sets |
* the debug output level accordingly. |
* |
******************************************************************************/ |
|
void acpi_db_set_output_destination(u32 output_flags) |
{ |
|
acpi_gbl_db_output_flags = (u8)output_flags; |
|
if ((output_flags & ACPI_DB_REDIRECTABLE_OUTPUT) && |
acpi_gbl_db_output_to_file) { |
acpi_dbg_level = acpi_gbl_db_debug_level; |
} else { |
acpi_dbg_level = acpi_gbl_db_console_debug_level; |
} |
} |
|
/******************************************************************************* |
* |
* FUNCTION: acpi_db_dump_external_object |
* |
* PARAMETERS: obj_desc - External ACPI object to dump |
* level - Nesting level. |
* |
* RETURN: None |
* |
* DESCRIPTION: Dump the contents of an ACPI external object |
* |
******************************************************************************/ |
|
void acpi_db_dump_external_object(union acpi_object *obj_desc, u32 level) |
{ |
u32 i; |
|
if (!obj_desc) { |
acpi_os_printf("[Null Object]\n"); |
return; |
} |
|
for (i = 0; i < level; i++) { |
acpi_os_printf(" "); |
} |
|
switch (obj_desc->type) { |
case ACPI_TYPE_ANY: |
|
acpi_os_printf("[Null Object] (Type=0)\n"); |
break; |
|
case ACPI_TYPE_INTEGER: |
|
acpi_os_printf("[Integer] = %8.8X%8.8X\n", |
ACPI_FORMAT_UINT64(obj_desc->integer.value)); |
break; |
|
case ACPI_TYPE_STRING: |
|
acpi_os_printf("[String] Length %.2X = ", |
obj_desc->string.length); |
acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX); |
acpi_os_printf("\n"); |
break; |
|
case ACPI_TYPE_BUFFER: |
|
acpi_os_printf("[Buffer] Length %.2X = ", |
obj_desc->buffer.length); |
if (obj_desc->buffer.length) { |
if (obj_desc->buffer.length > 16) { |
acpi_os_printf("\n"); |
} |
acpi_ut_debug_dump_buffer(ACPI_CAST_PTR |
(u8, |
obj_desc->buffer.pointer), |
obj_desc->buffer.length, |
DB_BYTE_DISPLAY, _COMPONENT); |
} else { |
acpi_os_printf("\n"); |
} |
break; |
|
case ACPI_TYPE_PACKAGE: |
|
acpi_os_printf("[Package] Contains %u Elements:\n", |
obj_desc->package.count); |
|
for (i = 0; i < obj_desc->package.count; i++) { |
acpi_db_dump_external_object(&obj_desc->package. |
elements[i], level + 1); |
} |
break; |
|
case ACPI_TYPE_LOCAL_REFERENCE: |
|
acpi_os_printf("[Object Reference] = "); |
acpi_db_display_internal_object(obj_desc->reference.handle, |
NULL); |
break; |
|
case ACPI_TYPE_PROCESSOR: |
|
acpi_os_printf("[Processor]\n"); |
break; |
|
case ACPI_TYPE_POWER: |
|
acpi_os_printf("[Power Resource]\n"); |
break; |
|
default: |
|
acpi_os_printf("[Unknown Type] %X\n", obj_desc->type); |
break; |
} |
} |
|
/******************************************************************************* |
* |
* FUNCTION: acpi_db_prep_namestring |
* |
* PARAMETERS: name - String to prepare |
* |
* RETURN: None |
* |
* DESCRIPTION: Translate all forward slashes and dots to backslashes. |
* |
******************************************************************************/ |
|
void acpi_db_prep_namestring(char *name) |
{ |
|
if (!name) { |
return; |
} |
|
acpi_ut_strupr(name); |
|
/* Convert a leading forward slash to a backslash */ |
|
if (*name == '/') { |
*name = '\\'; |
} |
|
/* Ignore a leading backslash, this is the root prefix */ |
|
if (ACPI_IS_ROOT_PREFIX(*name)) { |
name++; |
} |
|
/* Convert all slash path separators to dots */ |
|
while (*name) { |
if ((*name == '/') || (*name == '\\')) { |
*name = '.'; |
} |
|
name++; |
} |
} |
|
/******************************************************************************* |
* |
* FUNCTION: acpi_db_local_ns_lookup |
* |
* PARAMETERS: name - Name to lookup |
* |
* RETURN: Pointer to a namespace node, null on failure |
* |
* DESCRIPTION: Lookup a name in the ACPI namespace |
* |
* Note: Currently begins search from the root. Could be enhanced to use |
* the current prefix (scope) node as the search beginning point. |
* |
******************************************************************************/ |
|
struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name) |
{ |
char *internal_path; |
acpi_status status; |
struct acpi_namespace_node *node = NULL; |
|
acpi_db_prep_namestring(name); |
|
/* Build an internal namestring */ |
|
status = acpi_ns_internalize_name(name, &internal_path); |
if (ACPI_FAILURE(status)) { |
acpi_os_printf("Invalid namestring: %s\n", name); |
return (NULL); |
} |
|
/* |
* Lookup the name. |
* (Uses root node as the search starting point) |
*/ |
status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY, |
ACPI_IMODE_EXECUTE, |
ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE, |
NULL, &node); |
if (ACPI_FAILURE(status)) { |
acpi_os_printf("Could not locate name: %s, %s\n", |
name, acpi_format_exception(status)); |
} |
|
ACPI_FREE(internal_path); |
return (node); |
} |
|
/******************************************************************************* |
* |
* FUNCTION: acpi_db_uint32_to_hex_string |
* |
* PARAMETERS: value - The value to be converted to string |
* buffer - Buffer for result (not less than 11 bytes) |
* |
* RETURN: None |
* |
* DESCRIPTION: Convert the unsigned 32-bit value to the hexadecimal image |
* |
* NOTE: It is the caller's responsibility to ensure that the length of buffer |
* is sufficient. |
* |
******************************************************************************/ |
|
void acpi_db_uint32_to_hex_string(u32 value, char *buffer) |
{ |
int i; |
|
if (value == 0) { |
strcpy(buffer, "0"); |
return; |
} |
|
buffer[8] = '\0'; |
|
for (i = 7; i >= 0; i--) { |
buffer[i] = gbl_hex_to_ascii[value & 0x0F]; |
value = value >> 4; |
} |
} |
|
#ifdef ACPI_OBSOLETE_FUNCTIONS |
/******************************************************************************* |
* |
* FUNCTION: acpi_db_second_pass_parse |
* |
* PARAMETERS: root - Root of the parse tree |
* |
* RETURN: Status |
* |
* DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until |
* second pass to parse the control methods |
* |
******************************************************************************/ |
|
acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root) |
{ |
union acpi_parse_object *op = root; |
union acpi_parse_object *method; |
union acpi_parse_object *search_op; |
union acpi_parse_object *start_op; |
acpi_status status = AE_OK; |
u32 base_aml_offset; |
struct acpi_walk_state *walk_state; |
|
ACPI_FUNCTION_ENTRY(); |
|
acpi_os_printf("Pass two parse ....\n"); |
|
while (op) { |
if (op->common.aml_opcode == AML_METHOD_OP) { |
method = op; |
|
/* Create a new walk state for the parse */ |
|
walk_state = |
acpi_ds_create_walk_state(0, NULL, NULL, NULL); |
if (!walk_state) { |
return (AE_NO_MEMORY); |
} |
|
/* Init the Walk State */ |
|
walk_state->parser_state.aml = |
walk_state->parser_state.aml_start = |
method->named.data; |
walk_state->parser_state.aml_end = |
walk_state->parser_state.pkg_end = |
method->named.data + method->named.length; |
walk_state->parser_state.start_scope = op; |
|
walk_state->descending_callback = |
acpi_ds_load1_begin_op; |
walk_state->ascending_callback = acpi_ds_load1_end_op; |
|
/* Perform the AML parse */ |
|
status = acpi_ps_parse_aml(walk_state); |
|
base_aml_offset = |
(method->common.value.arg)->common.aml_offset + 1; |
start_op = (method->common.value.arg)->common.next; |
search_op = start_op; |
|
while (search_op) { |
search_op->common.aml_offset += base_aml_offset; |
search_op = |
acpi_ps_get_depth_next(start_op, search_op); |
} |
} |
|
if (op->common.aml_opcode == AML_REGION_OP) { |
|
/* TBD: [Investigate] this isn't quite the right thing to do! */ |
/* |
* |
* Method = (ACPI_DEFERRED_OP *) Op; |
* Status = acpi_ps_parse_aml (Op, Method->Body, Method->body_length); |
*/ |
} |
|
if (ACPI_FAILURE(status)) { |
break; |
} |
|
op = acpi_ps_get_depth_next(root, op); |
} |
|
return (status); |
} |
|
/******************************************************************************* |
* |
* FUNCTION: acpi_db_dump_buffer |
* |
* PARAMETERS: address - Pointer to the buffer |
* |
* RETURN: None |
* |
* DESCRIPTION: Print a portion of a buffer |
* |
******************************************************************************/ |
|
void acpi_db_dump_buffer(u32 address) |
{ |
|
acpi_os_printf("\nLocation %X:\n", address); |
|
acpi_dbg_level |= ACPI_LV_TABLES; |
acpi_ut_debug_dump_buffer(ACPI_TO_POINTER(address), 64, DB_BYTE_DISPLAY, |
ACPI_UINT32_MAX); |
} |
#endif |