xref: /openbmc/linux/drivers/acpi/acpica/dbutils.c (revision 95857638)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
299575102SLv Zheng /*******************************************************************************
399575102SLv Zheng  *
499575102SLv Zheng  * Module Name: dbutils - AML debugger utilities
599575102SLv Zheng  *
699575102SLv Zheng  ******************************************************************************/
799575102SLv Zheng 
899575102SLv Zheng #include <acpi/acpi.h>
999575102SLv Zheng #include "accommon.h"
1099575102SLv Zheng #include "acnamesp.h"
1199575102SLv Zheng #include "acdebug.h"
1299575102SLv Zheng 
1399575102SLv Zheng #define _COMPONENT          ACPI_CA_DEBUGGER
1499575102SLv Zheng ACPI_MODULE_NAME("dbutils")
1599575102SLv Zheng 
1699575102SLv Zheng /* Local prototypes */
1799575102SLv Zheng #ifdef ACPI_OBSOLETE_FUNCTIONS
1899575102SLv Zheng acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root);
1999575102SLv Zheng 
2099575102SLv Zheng void acpi_db_dump_buffer(u32 address);
2199575102SLv Zheng #endif
2299575102SLv Zheng 
2399575102SLv Zheng /*******************************************************************************
2499575102SLv Zheng  *
2599575102SLv Zheng  * FUNCTION:    acpi_db_match_argument
2699575102SLv Zheng  *
2799575102SLv Zheng  * PARAMETERS:  user_argument           - User command line
2899575102SLv Zheng  *              arguments               - Array of commands to match against
2999575102SLv Zheng  *
3099575102SLv Zheng  * RETURN:      Index into command array or ACPI_TYPE_NOT_FOUND if not found
3199575102SLv Zheng  *
3299575102SLv Zheng  * DESCRIPTION: Search command array for a command match
3399575102SLv Zheng  *
3499575102SLv Zheng  ******************************************************************************/
3599575102SLv Zheng 
3699575102SLv Zheng acpi_object_type
acpi_db_match_argument(char * user_argument,struct acpi_db_argument_info * arguments)3799575102SLv Zheng acpi_db_match_argument(char *user_argument,
3899575102SLv Zheng 		       struct acpi_db_argument_info *arguments)
3999575102SLv Zheng {
4099575102SLv Zheng 	u32 i;
4199575102SLv Zheng 
4299575102SLv Zheng 	if (!user_argument || user_argument[0] == 0) {
4399575102SLv Zheng 		return (ACPI_TYPE_NOT_FOUND);
4499575102SLv Zheng 	}
4599575102SLv Zheng 
4699575102SLv Zheng 	for (i = 0; arguments[i].name; i++) {
470dfaaa3dSBob Moore 		if (strstr(ACPI_CAST_PTR(char, arguments[i].name),
480dfaaa3dSBob Moore 			   ACPI_CAST_PTR(char,
490dfaaa3dSBob Moore 					 user_argument)) == arguments[i].name) {
5099575102SLv Zheng 			return (i);
5199575102SLv Zheng 		}
5299575102SLv Zheng 	}
5399575102SLv Zheng 
5499575102SLv Zheng 	/* Argument not recognized */
5599575102SLv Zheng 
5699575102SLv Zheng 	return (ACPI_TYPE_NOT_FOUND);
5799575102SLv Zheng }
5899575102SLv Zheng 
5999575102SLv Zheng /*******************************************************************************
6099575102SLv Zheng  *
6199575102SLv Zheng  * FUNCTION:    acpi_db_set_output_destination
6299575102SLv Zheng  *
6399575102SLv Zheng  * PARAMETERS:  output_flags        - Current flags word
6499575102SLv Zheng  *
6599575102SLv Zheng  * RETURN:      None
6699575102SLv Zheng  *
6799575102SLv Zheng  * DESCRIPTION: Set the current destination for debugger output. Also sets
6899575102SLv Zheng  *              the debug output level accordingly.
6999575102SLv Zheng  *
7099575102SLv Zheng  ******************************************************************************/
7199575102SLv Zheng 
acpi_db_set_output_destination(u32 output_flags)7299575102SLv Zheng void acpi_db_set_output_destination(u32 output_flags)
7399575102SLv Zheng {
7499575102SLv Zheng 
7599575102SLv Zheng 	acpi_gbl_db_output_flags = (u8)output_flags;
7699575102SLv Zheng 
7799575102SLv Zheng 	if ((output_flags & ACPI_DB_REDIRECTABLE_OUTPUT) &&
7899575102SLv Zheng 	    acpi_gbl_db_output_to_file) {
7999575102SLv Zheng 		acpi_dbg_level = acpi_gbl_db_debug_level;
8099575102SLv Zheng 	} else {
8199575102SLv Zheng 		acpi_dbg_level = acpi_gbl_db_console_debug_level;
8299575102SLv Zheng 	}
8399575102SLv Zheng }
8499575102SLv Zheng 
8599575102SLv Zheng /*******************************************************************************
8699575102SLv Zheng  *
8799575102SLv Zheng  * FUNCTION:    acpi_db_dump_external_object
8899575102SLv Zheng  *
8999575102SLv Zheng  * PARAMETERS:  obj_desc        - External ACPI object to dump
9099575102SLv Zheng  *              level           - Nesting level.
9199575102SLv Zheng  *
9299575102SLv Zheng  * RETURN:      None
9399575102SLv Zheng  *
9499575102SLv Zheng  * DESCRIPTION: Dump the contents of an ACPI external object
9599575102SLv Zheng  *
9699575102SLv Zheng  ******************************************************************************/
9799575102SLv Zheng 
acpi_db_dump_external_object(union acpi_object * obj_desc,u32 level)9899575102SLv Zheng void acpi_db_dump_external_object(union acpi_object *obj_desc, u32 level)
9999575102SLv Zheng {
10099575102SLv Zheng 	u32 i;
10199575102SLv Zheng 
10299575102SLv Zheng 	if (!obj_desc) {
10399575102SLv Zheng 		acpi_os_printf("[Null Object]\n");
10499575102SLv Zheng 		return;
10599575102SLv Zheng 	}
10699575102SLv Zheng 
10799575102SLv Zheng 	for (i = 0; i < level; i++) {
10899575102SLv Zheng 		acpi_os_printf(" ");
10999575102SLv Zheng 	}
11099575102SLv Zheng 
11199575102SLv Zheng 	switch (obj_desc->type) {
11299575102SLv Zheng 	case ACPI_TYPE_ANY:
11399575102SLv Zheng 
11499575102SLv Zheng 		acpi_os_printf("[Null Object] (Type=0)\n");
11599575102SLv Zheng 		break;
11699575102SLv Zheng 
11799575102SLv Zheng 	case ACPI_TYPE_INTEGER:
11899575102SLv Zheng 
11999575102SLv Zheng 		acpi_os_printf("[Integer] = %8.8X%8.8X\n",
12099575102SLv Zheng 			       ACPI_FORMAT_UINT64(obj_desc->integer.value));
12199575102SLv Zheng 		break;
12299575102SLv Zheng 
12399575102SLv Zheng 	case ACPI_TYPE_STRING:
12499575102SLv Zheng 
12599575102SLv Zheng 		acpi_os_printf("[String] Length %.2X = ",
12699575102SLv Zheng 			       obj_desc->string.length);
12799575102SLv Zheng 		acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX);
12899575102SLv Zheng 		acpi_os_printf("\n");
12999575102SLv Zheng 		break;
13099575102SLv Zheng 
13199575102SLv Zheng 	case ACPI_TYPE_BUFFER:
13299575102SLv Zheng 
13399575102SLv Zheng 		acpi_os_printf("[Buffer] Length %.2X = ",
13499575102SLv Zheng 			       obj_desc->buffer.length);
13599575102SLv Zheng 		if (obj_desc->buffer.length) {
13699575102SLv Zheng 			if (obj_desc->buffer.length > 16) {
13799575102SLv Zheng 				acpi_os_printf("\n");
13899575102SLv Zheng 			}
1391fad8738SBob Moore 
14099575102SLv Zheng 			acpi_ut_debug_dump_buffer(ACPI_CAST_PTR
14199575102SLv Zheng 						  (u8,
14299575102SLv Zheng 						   obj_desc->buffer.pointer),
14399575102SLv Zheng 						  obj_desc->buffer.length,
14499575102SLv Zheng 						  DB_BYTE_DISPLAY, _COMPONENT);
14599575102SLv Zheng 		} else {
14699575102SLv Zheng 			acpi_os_printf("\n");
14799575102SLv Zheng 		}
14899575102SLv Zheng 		break;
14999575102SLv Zheng 
15099575102SLv Zheng 	case ACPI_TYPE_PACKAGE:
15199575102SLv Zheng 
15299575102SLv Zheng 		acpi_os_printf("[Package] Contains %u Elements:\n",
15399575102SLv Zheng 			       obj_desc->package.count);
15499575102SLv Zheng 
15599575102SLv Zheng 		for (i = 0; i < obj_desc->package.count; i++) {
15699575102SLv Zheng 			acpi_db_dump_external_object(&obj_desc->package.
15799575102SLv Zheng 						     elements[i], level + 1);
15899575102SLv Zheng 		}
15999575102SLv Zheng 		break;
16099575102SLv Zheng 
16199575102SLv Zheng 	case ACPI_TYPE_LOCAL_REFERENCE:
16299575102SLv Zheng 
16399575102SLv Zheng 		acpi_os_printf("[Object Reference] = ");
16499575102SLv Zheng 		acpi_db_display_internal_object(obj_desc->reference.handle,
16599575102SLv Zheng 						NULL);
16699575102SLv Zheng 		break;
16799575102SLv Zheng 
16899575102SLv Zheng 	case ACPI_TYPE_PROCESSOR:
16999575102SLv Zheng 
17099575102SLv Zheng 		acpi_os_printf("[Processor]\n");
17199575102SLv Zheng 		break;
17299575102SLv Zheng 
17399575102SLv Zheng 	case ACPI_TYPE_POWER:
17499575102SLv Zheng 
17599575102SLv Zheng 		acpi_os_printf("[Power Resource]\n");
17699575102SLv Zheng 		break;
17799575102SLv Zheng 
17899575102SLv Zheng 	default:
17999575102SLv Zheng 
18099575102SLv Zheng 		acpi_os_printf("[Unknown Type] %X\n", obj_desc->type);
18199575102SLv Zheng 		break;
18299575102SLv Zheng 	}
18399575102SLv Zheng }
18499575102SLv Zheng 
18599575102SLv Zheng /*******************************************************************************
18699575102SLv Zheng  *
18799575102SLv Zheng  * FUNCTION:    acpi_db_prep_namestring
18899575102SLv Zheng  *
18999575102SLv Zheng  * PARAMETERS:  name            - String to prepare
19099575102SLv Zheng  *
19199575102SLv Zheng  * RETURN:      None
19299575102SLv Zheng  *
19399575102SLv Zheng  * DESCRIPTION: Translate all forward slashes and dots to backslashes.
19499575102SLv Zheng  *
19599575102SLv Zheng  ******************************************************************************/
19699575102SLv Zheng 
acpi_db_prep_namestring(char * name)19799575102SLv Zheng void acpi_db_prep_namestring(char *name)
19899575102SLv Zheng {
19999575102SLv Zheng 
20099575102SLv Zheng 	if (!name) {
20199575102SLv Zheng 		return;
20299575102SLv Zheng 	}
20399575102SLv Zheng 
20499575102SLv Zheng 	acpi_ut_strupr(name);
20599575102SLv Zheng 
20699575102SLv Zheng 	/* Convert a leading forward slash to a backslash */
20799575102SLv Zheng 
20899575102SLv Zheng 	if (*name == '/') {
20999575102SLv Zheng 		*name = '\\';
21099575102SLv Zheng 	}
21199575102SLv Zheng 
21299575102SLv Zheng 	/* Ignore a leading backslash, this is the root prefix */
21399575102SLv Zheng 
21499575102SLv Zheng 	if (ACPI_IS_ROOT_PREFIX(*name)) {
21599575102SLv Zheng 		name++;
21699575102SLv Zheng 	}
21799575102SLv Zheng 
21899575102SLv Zheng 	/* Convert all slash path separators to dots */
21999575102SLv Zheng 
22099575102SLv Zheng 	while (*name) {
22199575102SLv Zheng 		if ((*name == '/') || (*name == '\\')) {
22299575102SLv Zheng 			*name = '.';
22399575102SLv Zheng 		}
22499575102SLv Zheng 
22599575102SLv Zheng 		name++;
22699575102SLv Zheng 	}
22799575102SLv Zheng }
22899575102SLv Zheng 
22999575102SLv Zheng /*******************************************************************************
23099575102SLv Zheng  *
23199575102SLv Zheng  * FUNCTION:    acpi_db_local_ns_lookup
23299575102SLv Zheng  *
23399575102SLv Zheng  * PARAMETERS:  name            - Name to lookup
23499575102SLv Zheng  *
23599575102SLv Zheng  * RETURN:      Pointer to a namespace node, null on failure
23699575102SLv Zheng  *
23799575102SLv Zheng  * DESCRIPTION: Lookup a name in the ACPI namespace
23899575102SLv Zheng  *
23999575102SLv Zheng  * Note: Currently begins search from the root. Could be enhanced to use
24099575102SLv Zheng  * the current prefix (scope) node as the search beginning point.
24199575102SLv Zheng  *
24299575102SLv Zheng  ******************************************************************************/
24399575102SLv Zheng 
acpi_db_local_ns_lookup(char * name)24499575102SLv Zheng struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name)
24599575102SLv Zheng {
24699575102SLv Zheng 	char *internal_path;
24799575102SLv Zheng 	acpi_status status;
24899575102SLv Zheng 	struct acpi_namespace_node *node = NULL;
24999575102SLv Zheng 
25099575102SLv Zheng 	acpi_db_prep_namestring(name);
25199575102SLv Zheng 
25299575102SLv Zheng 	/* Build an internal namestring */
25399575102SLv Zheng 
25499575102SLv Zheng 	status = acpi_ns_internalize_name(name, &internal_path);
25599575102SLv Zheng 	if (ACPI_FAILURE(status)) {
25699575102SLv Zheng 		acpi_os_printf("Invalid namestring: %s\n", name);
25799575102SLv Zheng 		return (NULL);
25899575102SLv Zheng 	}
25999575102SLv Zheng 
26099575102SLv Zheng 	/*
26199575102SLv Zheng 	 * Lookup the name.
26299575102SLv Zheng 	 * (Uses root node as the search starting point)
26399575102SLv Zheng 	 */
26499575102SLv Zheng 	status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY,
26599575102SLv Zheng 				ACPI_IMODE_EXECUTE,
26699575102SLv Zheng 				ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE,
26799575102SLv Zheng 				NULL, &node);
26899575102SLv Zheng 	if (ACPI_FAILURE(status)) {
26999575102SLv Zheng 		acpi_os_printf("Could not locate name: %s, %s\n",
27099575102SLv Zheng 			       name, acpi_format_exception(status));
27199575102SLv Zheng 	}
27299575102SLv Zheng 
27399575102SLv Zheng 	ACPI_FREE(internal_path);
27499575102SLv Zheng 	return (node);
27599575102SLv Zheng }
27699575102SLv Zheng 
27799575102SLv Zheng /*******************************************************************************
27899575102SLv Zheng  *
27999575102SLv Zheng  * FUNCTION:    acpi_db_uint32_to_hex_string
28099575102SLv Zheng  *
28199575102SLv Zheng  * PARAMETERS:  value           - The value to be converted to string
28299575102SLv Zheng  *              buffer          - Buffer for result (not less than 11 bytes)
28399575102SLv Zheng  *
28499575102SLv Zheng  * RETURN:      None
28599575102SLv Zheng  *
28699575102SLv Zheng  * DESCRIPTION: Convert the unsigned 32-bit value to the hexadecimal image
28799575102SLv Zheng  *
28899575102SLv Zheng  * NOTE: It is the caller's responsibility to ensure that the length of buffer
28999575102SLv Zheng  *       is sufficient.
29099575102SLv Zheng  *
29199575102SLv Zheng  ******************************************************************************/
29299575102SLv Zheng 
acpi_db_uint32_to_hex_string(u32 value,char * buffer)29399575102SLv Zheng void acpi_db_uint32_to_hex_string(u32 value, char *buffer)
29499575102SLv Zheng {
29599575102SLv Zheng 	int i;
29699575102SLv Zheng 
29799575102SLv Zheng 	if (value == 0) {
29899575102SLv Zheng 		strcpy(buffer, "0");
29999575102SLv Zheng 		return;
30099575102SLv Zheng 	}
30199575102SLv Zheng 
30299575102SLv Zheng 	buffer[8] = '\0';
30399575102SLv Zheng 
30499575102SLv Zheng 	for (i = 7; i >= 0; i--) {
3050dfaaa3dSBob Moore 		buffer[i] = acpi_gbl_upper_hex_digits[value & 0x0F];
30699575102SLv Zheng 		value = value >> 4;
30799575102SLv Zheng 	}
30899575102SLv Zheng }
30999575102SLv Zheng 
31099575102SLv Zheng #ifdef ACPI_OBSOLETE_FUNCTIONS
31199575102SLv Zheng /*******************************************************************************
31299575102SLv Zheng  *
31399575102SLv Zheng  * FUNCTION:    acpi_db_second_pass_parse
31499575102SLv Zheng  *
31599575102SLv Zheng  * PARAMETERS:  root            - Root of the parse tree
31699575102SLv Zheng  *
31799575102SLv Zheng  * RETURN:      Status
31899575102SLv Zheng  *
31999575102SLv Zheng  * DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until
32099575102SLv Zheng  *              second pass to parse the control methods
32199575102SLv Zheng  *
32299575102SLv Zheng  ******************************************************************************/
32399575102SLv Zheng 
acpi_db_second_pass_parse(union acpi_parse_object * root)32499575102SLv Zheng acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root)
32599575102SLv Zheng {
32699575102SLv Zheng 	union acpi_parse_object *op = root;
32799575102SLv Zheng 	union acpi_parse_object *method;
32899575102SLv Zheng 	union acpi_parse_object *search_op;
32999575102SLv Zheng 	union acpi_parse_object *start_op;
33099575102SLv Zheng 	acpi_status status = AE_OK;
33199575102SLv Zheng 	u32 base_aml_offset;
33299575102SLv Zheng 	struct acpi_walk_state *walk_state;
33399575102SLv Zheng 
33499575102SLv Zheng 	ACPI_FUNCTION_ENTRY();
33599575102SLv Zheng 
33699575102SLv Zheng 	acpi_os_printf("Pass two parse ....\n");
33799575102SLv Zheng 
33899575102SLv Zheng 	while (op) {
33999575102SLv Zheng 		if (op->common.aml_opcode == AML_METHOD_OP) {
34099575102SLv Zheng 			method = op;
34199575102SLv Zheng 
34299575102SLv Zheng 			/* Create a new walk state for the parse */
34399575102SLv Zheng 
34499575102SLv Zheng 			walk_state =
34599575102SLv Zheng 			    acpi_ds_create_walk_state(0, NULL, NULL, NULL);
34699575102SLv Zheng 			if (!walk_state) {
34799575102SLv Zheng 				return (AE_NO_MEMORY);
34899575102SLv Zheng 			}
34999575102SLv Zheng 
35099575102SLv Zheng 			/* Init the Walk State */
35199575102SLv Zheng 
35299575102SLv Zheng 			walk_state->parser_state.aml =
35399575102SLv Zheng 			    walk_state->parser_state.aml_start =
35499575102SLv Zheng 			    method->named.data;
35599575102SLv Zheng 			walk_state->parser_state.aml_end =
35699575102SLv Zheng 			    walk_state->parser_state.pkg_end =
35799575102SLv Zheng 			    method->named.data + method->named.length;
35899575102SLv Zheng 			walk_state->parser_state.start_scope = op;
35999575102SLv Zheng 
36099575102SLv Zheng 			walk_state->descending_callback =
36199575102SLv Zheng 			    acpi_ds_load1_begin_op;
36299575102SLv Zheng 			walk_state->ascending_callback = acpi_ds_load1_end_op;
36399575102SLv Zheng 
36499575102SLv Zheng 			/* Perform the AML parse */
36599575102SLv Zheng 
36699575102SLv Zheng 			status = acpi_ps_parse_aml(walk_state);
36799575102SLv Zheng 
36899575102SLv Zheng 			base_aml_offset =
36999575102SLv Zheng 			    (method->common.value.arg)->common.aml_offset + 1;
37099575102SLv Zheng 			start_op = (method->common.value.arg)->common.next;
37199575102SLv Zheng 			search_op = start_op;
37299575102SLv Zheng 
37399575102SLv Zheng 			while (search_op) {
37499575102SLv Zheng 				search_op->common.aml_offset += base_aml_offset;
37599575102SLv Zheng 				search_op =
37699575102SLv Zheng 				    acpi_ps_get_depth_next(start_op, search_op);
37799575102SLv Zheng 			}
37899575102SLv Zheng 		}
37999575102SLv Zheng 
38099575102SLv Zheng 		if (op->common.aml_opcode == AML_REGION_OP) {
38199575102SLv Zheng 
38299575102SLv Zheng 			/* TBD: [Investigate] this isn't quite the right thing to do! */
38399575102SLv Zheng 			/*
38499575102SLv Zheng 			 *
38599575102SLv Zheng 			 * Method = (ACPI_DEFERRED_OP *) Op;
38699575102SLv Zheng 			 * Status = acpi_ps_parse_aml (Op, Method->Body, Method->body_length);
38799575102SLv Zheng 			 */
38899575102SLv Zheng 		}
38999575102SLv Zheng 
39099575102SLv Zheng 		if (ACPI_FAILURE(status)) {
39199575102SLv Zheng 			break;
39299575102SLv Zheng 		}
39399575102SLv Zheng 
39499575102SLv Zheng 		op = acpi_ps_get_depth_next(root, op);
39599575102SLv Zheng 	}
39699575102SLv Zheng 
39799575102SLv Zheng 	return (status);
39899575102SLv Zheng }
39999575102SLv Zheng 
40099575102SLv Zheng /*******************************************************************************
40199575102SLv Zheng  *
40299575102SLv Zheng  * FUNCTION:    acpi_db_dump_buffer
40399575102SLv Zheng  *
40499575102SLv Zheng  * PARAMETERS:  address             - Pointer to the buffer
40599575102SLv Zheng  *
40699575102SLv Zheng  * RETURN:      None
40799575102SLv Zheng  *
40899575102SLv Zheng  * DESCRIPTION: Print a portion of a buffer
40999575102SLv Zheng  *
41099575102SLv Zheng  ******************************************************************************/
41199575102SLv Zheng 
acpi_db_dump_buffer(u32 address)41299575102SLv Zheng void acpi_db_dump_buffer(u32 address)
41399575102SLv Zheng {
41499575102SLv Zheng 
41599575102SLv Zheng 	acpi_os_printf("\nLocation %X:\n", address);
41699575102SLv Zheng 
41799575102SLv Zheng 	acpi_dbg_level |= ACPI_LV_TABLES;
41899575102SLv Zheng 	acpi_ut_debug_dump_buffer(ACPI_TO_POINTER(address), 64, DB_BYTE_DISPLAY,
41999575102SLv Zheng 				  ACPI_UINT32_MAX);
42099575102SLv Zheng }
42199575102SLv Zheng #endif
422