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