// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.01/*******************************************************************************2*3* Module Name: dbutils - AML debugger utilities4*5******************************************************************************/67#include <acpi/acpi.h>8#include "accommon.h"9#include "acnamesp.h"10#include "acdebug.h"1112#define _COMPONENT ACPI_CA_DEBUGGER13ACPI_MODULE_NAME("dbutils")1415/* Local prototypes */16#ifdef ACPI_OBSOLETE_FUNCTIONS17acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root);1819void acpi_db_dump_buffer(u32 address);20#endif2122/*******************************************************************************23*24* FUNCTION: acpi_db_match_argument25*26* PARAMETERS: user_argument - User command line27* arguments - Array of commands to match against28*29* RETURN: Index into command array or ACPI_TYPE_NOT_FOUND if not found30*31* DESCRIPTION: Search command array for a command match32*33******************************************************************************/3435acpi_object_type36acpi_db_match_argument(char *user_argument,37struct acpi_db_argument_info *arguments)38{39u32 i;4041if (!user_argument || user_argument[0] == 0) {42return (ACPI_TYPE_NOT_FOUND);43}4445for (i = 0; arguments[i].name; i++) {46if (strstr(ACPI_CAST_PTR(char, arguments[i].name),47ACPI_CAST_PTR(char,48user_argument)) == arguments[i].name) {49return (i);50}51}5253/* Argument not recognized */5455return (ACPI_TYPE_NOT_FOUND);56}5758/*******************************************************************************59*60* FUNCTION: acpi_db_set_output_destination61*62* PARAMETERS: output_flags - Current flags word63*64* RETURN: None65*66* DESCRIPTION: Set the current destination for debugger output. Also sets67* the debug output level accordingly.68*69******************************************************************************/7071void acpi_db_set_output_destination(u32 output_flags)72{7374acpi_gbl_db_output_flags = (u8)output_flags;7576if ((output_flags & ACPI_DB_REDIRECTABLE_OUTPUT) &&77acpi_gbl_db_output_to_file) {78acpi_dbg_level = acpi_gbl_db_debug_level;79} else {80acpi_dbg_level = acpi_gbl_db_console_debug_level;81}82}8384/*******************************************************************************85*86* FUNCTION: acpi_db_dump_external_object87*88* PARAMETERS: obj_desc - External ACPI object to dump89* level - Nesting level.90*91* RETURN: None92*93* DESCRIPTION: Dump the contents of an ACPI external object94*95******************************************************************************/9697void acpi_db_dump_external_object(union acpi_object *obj_desc, u32 level)98{99u32 i;100101if (!obj_desc) {102acpi_os_printf("[Null Object]\n");103return;104}105106for (i = 0; i < level; i++) {107acpi_os_printf(" ");108}109110switch (obj_desc->type) {111case ACPI_TYPE_ANY:112113acpi_os_printf("[Null Object] (Type=0)\n");114break;115116case ACPI_TYPE_INTEGER:117118acpi_os_printf("[Integer] = %8.8X%8.8X\n",119ACPI_FORMAT_UINT64(obj_desc->integer.value));120break;121122case ACPI_TYPE_STRING:123124acpi_os_printf("[String] Length %.2X = ",125obj_desc->string.length);126acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX);127acpi_os_printf("\n");128break;129130case ACPI_TYPE_BUFFER:131132acpi_os_printf("[Buffer] Length %.2X = ",133obj_desc->buffer.length);134if (obj_desc->buffer.length) {135if (obj_desc->buffer.length > 16) {136acpi_os_printf("\n");137}138139acpi_ut_debug_dump_buffer(ACPI_CAST_PTR140(u8,141obj_desc->buffer.pointer),142obj_desc->buffer.length,143DB_BYTE_DISPLAY, _COMPONENT);144} else {145acpi_os_printf("\n");146}147break;148149case ACPI_TYPE_PACKAGE:150151acpi_os_printf("[Package] Contains %u Elements:\n",152obj_desc->package.count);153154for (i = 0; i < obj_desc->package.count; i++) {155acpi_db_dump_external_object(&obj_desc->package.156elements[i], level + 1);157}158break;159160case ACPI_TYPE_LOCAL_REFERENCE:161162acpi_os_printf("[Object Reference] = ");163acpi_db_display_internal_object(obj_desc->reference.handle,164NULL);165break;166167case ACPI_TYPE_PROCESSOR:168169acpi_os_printf("[Processor]\n");170break;171172case ACPI_TYPE_POWER:173174acpi_os_printf("[Power Resource]\n");175break;176177default:178179acpi_os_printf("[Unknown Type] %X\n", obj_desc->type);180break;181}182}183184/*******************************************************************************185*186* FUNCTION: acpi_db_prep_namestring187*188* PARAMETERS: name - String to prepare189*190* RETURN: None191*192* DESCRIPTION: Translate all forward slashes and dots to backslashes.193*194******************************************************************************/195196void acpi_db_prep_namestring(char *name)197{198199if (!name) {200return;201}202203acpi_ut_strupr(name);204205/* Convert a leading forward slash to a backslash */206207if (*name == '/') {208*name = '\\';209}210211/* Ignore a leading backslash, this is the root prefix */212213if (ACPI_IS_ROOT_PREFIX(*name)) {214name++;215}216217/* Convert all slash path separators to dots */218219while (*name) {220if ((*name == '/') || (*name == '\\')) {221*name = '.';222}223224name++;225}226}227228/*******************************************************************************229*230* FUNCTION: acpi_db_local_ns_lookup231*232* PARAMETERS: name - Name to lookup233*234* RETURN: Pointer to a namespace node, null on failure235*236* DESCRIPTION: Lookup a name in the ACPI namespace237*238* Note: Currently begins search from the root. Could be enhanced to use239* the current prefix (scope) node as the search beginning point.240*241******************************************************************************/242243struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name)244{245char *internal_path;246acpi_status status;247struct acpi_namespace_node *node = NULL;248249acpi_db_prep_namestring(name);250251/* Build an internal namestring */252253status = acpi_ns_internalize_name(name, &internal_path);254if (ACPI_FAILURE(status)) {255acpi_os_printf("Invalid namestring: %s\n", name);256return (NULL);257}258259/*260* Lookup the name.261* (Uses root node as the search starting point)262*/263status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY,264ACPI_IMODE_EXECUTE,265ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE,266NULL, &node);267if (ACPI_FAILURE(status)) {268acpi_os_printf("Could not locate name: %s, %s\n",269name, acpi_format_exception(status));270}271272ACPI_FREE(internal_path);273return (node);274}275276/*******************************************************************************277*278* FUNCTION: acpi_db_uint32_to_hex_string279*280* PARAMETERS: value - The value to be converted to string281* buffer - Buffer for result (not less than 11 bytes)282*283* RETURN: None284*285* DESCRIPTION: Convert the unsigned 32-bit value to the hexadecimal image286*287* NOTE: It is the caller's responsibility to ensure that the length of buffer288* is sufficient.289*290******************************************************************************/291292void acpi_db_uint32_to_hex_string(u32 value, char *buffer)293{294int i;295296if (value == 0) {297strcpy(buffer, "0");298return;299}300301buffer[8] = '\0';302303for (i = 7; i >= 0; i--) {304buffer[i] = acpi_gbl_upper_hex_digits[value & 0x0F];305value = value >> 4;306}307}308309#ifdef ACPI_OBSOLETE_FUNCTIONS310/*******************************************************************************311*312* FUNCTION: acpi_db_second_pass_parse313*314* PARAMETERS: root - Root of the parse tree315*316* RETURN: Status317*318* DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until319* second pass to parse the control methods320*321******************************************************************************/322323acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root)324{325union acpi_parse_object *op = root;326union acpi_parse_object *method;327union acpi_parse_object *search_op;328union acpi_parse_object *start_op;329acpi_status status = AE_OK;330u32 base_aml_offset;331struct acpi_walk_state *walk_state;332333ACPI_FUNCTION_ENTRY();334335acpi_os_printf("Pass two parse ....\n");336337while (op) {338if (op->common.aml_opcode == AML_METHOD_OP) {339method = op;340341/* Create a new walk state for the parse */342343walk_state =344acpi_ds_create_walk_state(0, NULL, NULL, NULL);345if (!walk_state) {346return (AE_NO_MEMORY);347}348349/* Init the Walk State */350351walk_state->parser_state.aml =352walk_state->parser_state.aml_start =353method->named.data;354walk_state->parser_state.aml_end =355walk_state->parser_state.pkg_end =356method->named.data + method->named.length;357walk_state->parser_state.start_scope = op;358359walk_state->descending_callback =360acpi_ds_load1_begin_op;361walk_state->ascending_callback = acpi_ds_load1_end_op;362363/* Perform the AML parse */364365status = acpi_ps_parse_aml(walk_state);366367base_aml_offset =368(method->common.value.arg)->common.aml_offset + 1;369start_op = (method->common.value.arg)->common.next;370search_op = start_op;371372while (search_op) {373search_op->common.aml_offset += base_aml_offset;374search_op =375acpi_ps_get_depth_next(start_op, search_op);376}377}378379if (op->common.aml_opcode == AML_REGION_OP) {380381/* TBD: [Investigate] this isn't quite the right thing to do! */382/*383*384* Method = (ACPI_DEFERRED_OP *) Op;385* Status = acpi_ps_parse_aml (Op, Method->Body, Method->body_length);386*/387}388389if (ACPI_FAILURE(status)) {390break;391}392393op = acpi_ps_get_depth_next(root, op);394}395396return (status);397}398399/*******************************************************************************400*401* FUNCTION: acpi_db_dump_buffer402*403* PARAMETERS: address - Pointer to the buffer404*405* RETURN: None406*407* DESCRIPTION: Print a portion of a buffer408*409******************************************************************************/410411void acpi_db_dump_buffer(u32 address)412{413414acpi_os_printf("\nLocation %X:\n", address);415416acpi_dbg_level |= ACPI_LV_TABLES;417acpi_ut_debug_dump_buffer(ACPI_TO_POINTER(address), 64, DB_BYTE_DISPLAY,418ACPI_UINT32_MAX);419}420#endif421422423