Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6595 | serge | 1 | /******************************************************************************* |
2 | * |
||
3 | * Module Name: dbutils - AML debugger utilities |
||
4 | * |
||
5 | ******************************************************************************/ |
||
6 | |||
7 | /* |
||
8 | * Copyright (C) 2000 - 2015, 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 |
||
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 | 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--) { |
||
341 | buffer[i] = gbl_hex_to_ascii[value & 0x0F]; |
||
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>> |