xref: /openbmc/linux/drivers/acpi/acpica/dbutils.c (revision a8fe58ce)
1 /*******************************************************************************
2  *
3  * Module Name: dbutils - AML debugger utilities
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, 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 "acnamesp.h"
47 #include "acdebug.h"
48 
49 #define _COMPONENT          ACPI_CA_DEBUGGER
50 ACPI_MODULE_NAME("dbutils")
51 
52 /* Local prototypes */
53 #ifdef ACPI_OBSOLETE_FUNCTIONS
54 acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root);
55 
56 void acpi_db_dump_buffer(u32 address);
57 #endif
58 
59 static char *gbl_hex_to_ascii = "0123456789ABCDEF";
60 
61 /*******************************************************************************
62  *
63  * FUNCTION:    acpi_db_match_argument
64  *
65  * PARAMETERS:  user_argument           - User command line
66  *              arguments               - Array of commands to match against
67  *
68  * RETURN:      Index into command array or ACPI_TYPE_NOT_FOUND if not found
69  *
70  * DESCRIPTION: Search command array for a command match
71  *
72  ******************************************************************************/
73 
74 acpi_object_type
75 acpi_db_match_argument(char *user_argument,
76 		       struct acpi_db_argument_info *arguments)
77 {
78 	u32 i;
79 
80 	if (!user_argument || user_argument[0] == 0) {
81 		return (ACPI_TYPE_NOT_FOUND);
82 	}
83 
84 	for (i = 0; arguments[i].name; i++) {
85 		if (strstr(arguments[i].name, user_argument) ==
86 		    arguments[i].name) {
87 			return (i);
88 		}
89 	}
90 
91 	/* Argument not recognized */
92 
93 	return (ACPI_TYPE_NOT_FOUND);
94 }
95 
96 /*******************************************************************************
97  *
98  * FUNCTION:    acpi_db_set_output_destination
99  *
100  * PARAMETERS:  output_flags        - Current flags word
101  *
102  * RETURN:      None
103  *
104  * DESCRIPTION: Set the current destination for debugger output. Also sets
105  *              the debug output level accordingly.
106  *
107  ******************************************************************************/
108 
109 void acpi_db_set_output_destination(u32 output_flags)
110 {
111 
112 	acpi_gbl_db_output_flags = (u8)output_flags;
113 
114 	if ((output_flags & ACPI_DB_REDIRECTABLE_OUTPUT) &&
115 	    acpi_gbl_db_output_to_file) {
116 		acpi_dbg_level = acpi_gbl_db_debug_level;
117 	} else {
118 		acpi_dbg_level = acpi_gbl_db_console_debug_level;
119 	}
120 }
121 
122 /*******************************************************************************
123  *
124  * FUNCTION:    acpi_db_dump_external_object
125  *
126  * PARAMETERS:  obj_desc        - External ACPI object to dump
127  *              level           - Nesting level.
128  *
129  * RETURN:      None
130  *
131  * DESCRIPTION: Dump the contents of an ACPI external object
132  *
133  ******************************************************************************/
134 
135 void acpi_db_dump_external_object(union acpi_object *obj_desc, u32 level)
136 {
137 	u32 i;
138 
139 	if (!obj_desc) {
140 		acpi_os_printf("[Null Object]\n");
141 		return;
142 	}
143 
144 	for (i = 0; i < level; i++) {
145 		acpi_os_printf(" ");
146 	}
147 
148 	switch (obj_desc->type) {
149 	case ACPI_TYPE_ANY:
150 
151 		acpi_os_printf("[Null Object] (Type=0)\n");
152 		break;
153 
154 	case ACPI_TYPE_INTEGER:
155 
156 		acpi_os_printf("[Integer] = %8.8X%8.8X\n",
157 			       ACPI_FORMAT_UINT64(obj_desc->integer.value));
158 		break;
159 
160 	case ACPI_TYPE_STRING:
161 
162 		acpi_os_printf("[String] Length %.2X = ",
163 			       obj_desc->string.length);
164 		acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX);
165 		acpi_os_printf("\n");
166 		break;
167 
168 	case ACPI_TYPE_BUFFER:
169 
170 		acpi_os_printf("[Buffer] Length %.2X = ",
171 			       obj_desc->buffer.length);
172 		if (obj_desc->buffer.length) {
173 			if (obj_desc->buffer.length > 16) {
174 				acpi_os_printf("\n");
175 			}
176 
177 			acpi_ut_debug_dump_buffer(ACPI_CAST_PTR
178 						  (u8,
179 						   obj_desc->buffer.pointer),
180 						  obj_desc->buffer.length,
181 						  DB_BYTE_DISPLAY, _COMPONENT);
182 		} else {
183 			acpi_os_printf("\n");
184 		}
185 		break;
186 
187 	case ACPI_TYPE_PACKAGE:
188 
189 		acpi_os_printf("[Package] Contains %u Elements:\n",
190 			       obj_desc->package.count);
191 
192 		for (i = 0; i < obj_desc->package.count; i++) {
193 			acpi_db_dump_external_object(&obj_desc->package.
194 						     elements[i], level + 1);
195 		}
196 		break;
197 
198 	case ACPI_TYPE_LOCAL_REFERENCE:
199 
200 		acpi_os_printf("[Object Reference] = ");
201 		acpi_db_display_internal_object(obj_desc->reference.handle,
202 						NULL);
203 		break;
204 
205 	case ACPI_TYPE_PROCESSOR:
206 
207 		acpi_os_printf("[Processor]\n");
208 		break;
209 
210 	case ACPI_TYPE_POWER:
211 
212 		acpi_os_printf("[Power Resource]\n");
213 		break;
214 
215 	default:
216 
217 		acpi_os_printf("[Unknown Type] %X\n", obj_desc->type);
218 		break;
219 	}
220 }
221 
222 /*******************************************************************************
223  *
224  * FUNCTION:    acpi_db_prep_namestring
225  *
226  * PARAMETERS:  name            - String to prepare
227  *
228  * RETURN:      None
229  *
230  * DESCRIPTION: Translate all forward slashes and dots to backslashes.
231  *
232  ******************************************************************************/
233 
234 void acpi_db_prep_namestring(char *name)
235 {
236 
237 	if (!name) {
238 		return;
239 	}
240 
241 	acpi_ut_strupr(name);
242 
243 	/* Convert a leading forward slash to a backslash */
244 
245 	if (*name == '/') {
246 		*name = '\\';
247 	}
248 
249 	/* Ignore a leading backslash, this is the root prefix */
250 
251 	if (ACPI_IS_ROOT_PREFIX(*name)) {
252 		name++;
253 	}
254 
255 	/* Convert all slash path separators to dots */
256 
257 	while (*name) {
258 		if ((*name == '/') || (*name == '\\')) {
259 			*name = '.';
260 		}
261 
262 		name++;
263 	}
264 }
265 
266 /*******************************************************************************
267  *
268  * FUNCTION:    acpi_db_local_ns_lookup
269  *
270  * PARAMETERS:  name            - Name to lookup
271  *
272  * RETURN:      Pointer to a namespace node, null on failure
273  *
274  * DESCRIPTION: Lookup a name in the ACPI namespace
275  *
276  * Note: Currently begins search from the root. Could be enhanced to use
277  * the current prefix (scope) node as the search beginning point.
278  *
279  ******************************************************************************/
280 
281 struct acpi_namespace_node *acpi_db_local_ns_lookup(char *name)
282 {
283 	char *internal_path;
284 	acpi_status status;
285 	struct acpi_namespace_node *node = NULL;
286 
287 	acpi_db_prep_namestring(name);
288 
289 	/* Build an internal namestring */
290 
291 	status = acpi_ns_internalize_name(name, &internal_path);
292 	if (ACPI_FAILURE(status)) {
293 		acpi_os_printf("Invalid namestring: %s\n", name);
294 		return (NULL);
295 	}
296 
297 	/*
298 	 * Lookup the name.
299 	 * (Uses root node as the search starting point)
300 	 */
301 	status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY,
302 				ACPI_IMODE_EXECUTE,
303 				ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE,
304 				NULL, &node);
305 	if (ACPI_FAILURE(status)) {
306 		acpi_os_printf("Could not locate name: %s, %s\n",
307 			       name, acpi_format_exception(status));
308 	}
309 
310 	ACPI_FREE(internal_path);
311 	return (node);
312 }
313 
314 /*******************************************************************************
315  *
316  * FUNCTION:    acpi_db_uint32_to_hex_string
317  *
318  * PARAMETERS:  value           - The value to be converted to string
319  *              buffer          - Buffer for result (not less than 11 bytes)
320  *
321  * RETURN:      None
322  *
323  * DESCRIPTION: Convert the unsigned 32-bit value to the hexadecimal image
324  *
325  * NOTE: It is the caller's responsibility to ensure that the length of buffer
326  *       is sufficient.
327  *
328  ******************************************************************************/
329 
330 void acpi_db_uint32_to_hex_string(u32 value, char *buffer)
331 {
332 	int i;
333 
334 	if (value == 0) {
335 		strcpy(buffer, "0");
336 		return;
337 	}
338 
339 	buffer[8] = '\0';
340 
341 	for (i = 7; i >= 0; i--) {
342 		buffer[i] = gbl_hex_to_ascii[value & 0x0F];
343 		value = value >> 4;
344 	}
345 }
346 
347 #ifdef ACPI_OBSOLETE_FUNCTIONS
348 /*******************************************************************************
349  *
350  * FUNCTION:    acpi_db_second_pass_parse
351  *
352  * PARAMETERS:  root            - Root of the parse tree
353  *
354  * RETURN:      Status
355  *
356  * DESCRIPTION: Second pass parse of the ACPI tables. We need to wait until
357  *              second pass to parse the control methods
358  *
359  ******************************************************************************/
360 
361 acpi_status acpi_db_second_pass_parse(union acpi_parse_object *root)
362 {
363 	union acpi_parse_object *op = root;
364 	union acpi_parse_object *method;
365 	union acpi_parse_object *search_op;
366 	union acpi_parse_object *start_op;
367 	acpi_status status = AE_OK;
368 	u32 base_aml_offset;
369 	struct acpi_walk_state *walk_state;
370 
371 	ACPI_FUNCTION_ENTRY();
372 
373 	acpi_os_printf("Pass two parse ....\n");
374 
375 	while (op) {
376 		if (op->common.aml_opcode == AML_METHOD_OP) {
377 			method = op;
378 
379 			/* Create a new walk state for the parse */
380 
381 			walk_state =
382 			    acpi_ds_create_walk_state(0, NULL, NULL, NULL);
383 			if (!walk_state) {
384 				return (AE_NO_MEMORY);
385 			}
386 
387 			/* Init the Walk State */
388 
389 			walk_state->parser_state.aml =
390 			    walk_state->parser_state.aml_start =
391 			    method->named.data;
392 			walk_state->parser_state.aml_end =
393 			    walk_state->parser_state.pkg_end =
394 			    method->named.data + method->named.length;
395 			walk_state->parser_state.start_scope = op;
396 
397 			walk_state->descending_callback =
398 			    acpi_ds_load1_begin_op;
399 			walk_state->ascending_callback = acpi_ds_load1_end_op;
400 
401 			/* Perform the AML parse */
402 
403 			status = acpi_ps_parse_aml(walk_state);
404 
405 			base_aml_offset =
406 			    (method->common.value.arg)->common.aml_offset + 1;
407 			start_op = (method->common.value.arg)->common.next;
408 			search_op = start_op;
409 
410 			while (search_op) {
411 				search_op->common.aml_offset += base_aml_offset;
412 				search_op =
413 				    acpi_ps_get_depth_next(start_op, search_op);
414 			}
415 		}
416 
417 		if (op->common.aml_opcode == AML_REGION_OP) {
418 
419 			/* TBD: [Investigate] this isn't quite the right thing to do! */
420 			/*
421 			 *
422 			 * Method = (ACPI_DEFERRED_OP *) Op;
423 			 * Status = acpi_ps_parse_aml (Op, Method->Body, Method->body_length);
424 			 */
425 		}
426 
427 		if (ACPI_FAILURE(status)) {
428 			break;
429 		}
430 
431 		op = acpi_ps_get_depth_next(root, op);
432 	}
433 
434 	return (status);
435 }
436 
437 /*******************************************************************************
438  *
439  * FUNCTION:    acpi_db_dump_buffer
440  *
441  * PARAMETERS:  address             - Pointer to the buffer
442  *
443  * RETURN:      None
444  *
445  * DESCRIPTION: Print a portion of a buffer
446  *
447  ******************************************************************************/
448 
449 void acpi_db_dump_buffer(u32 address)
450 {
451 
452 	acpi_os_printf("\nLocation %X:\n", address);
453 
454 	acpi_dbg_level |= ACPI_LV_TABLES;
455 	acpi_ut_debug_dump_buffer(ACPI_TO_POINTER(address), 64, DB_BYTE_DISPLAY,
456 				  ACPI_UINT32_MAX);
457 }
458 #endif
459