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