1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /******************************************************************************* |
3 | * |
4 | * Module Name: dbdisply - debug display commands |
5 | * |
6 | ******************************************************************************/ |
7 | |
8 | #include <acpi/acpi.h> |
9 | #include "accommon.h" |
10 | #include "amlcode.h" |
11 | #include "acdispat.h" |
12 | #include "acnamesp.h" |
13 | #include "acparser.h" |
14 | #include "acinterp.h" |
15 | #include "acevents.h" |
16 | #include "acdebug.h" |
17 | |
18 | #define _COMPONENT ACPI_CA_DEBUGGER |
19 | ACPI_MODULE_NAME("dbdisply" ) |
20 | |
21 | /* Local prototypes */ |
22 | static void acpi_db_dump_parser_descriptor(union acpi_parse_object *op); |
23 | |
24 | static void *acpi_db_get_pointer(void *target); |
25 | |
26 | static acpi_status |
27 | acpi_db_display_non_root_handlers(acpi_handle obj_handle, |
28 | u32 nesting_level, |
29 | void *context, void **return_value); |
30 | |
31 | /* |
32 | * System handler information. |
33 | * Used for Handlers command, in acpi_db_display_handlers. |
34 | */ |
35 | #define ACPI_PREDEFINED_PREFIX "%25s (%.2X) : " |
36 | #define ACPI_HANDLER_NAME_STRING "%30s : " |
37 | #define ACPI_HANDLER_PRESENT_STRING "%-9s (%p)\n" |
38 | #define ACPI_HANDLER_PRESENT_STRING2 "%-9s (%p)" |
39 | #define ACPI_HANDLER_NOT_PRESENT_STRING "%-9s\n" |
40 | |
41 | /* All predefined Address Space IDs */ |
42 | |
43 | static acpi_adr_space_type acpi_gbl_space_id_list[] = { |
44 | ACPI_ADR_SPACE_SYSTEM_MEMORY, |
45 | ACPI_ADR_SPACE_SYSTEM_IO, |
46 | ACPI_ADR_SPACE_PCI_CONFIG, |
47 | ACPI_ADR_SPACE_EC, |
48 | ACPI_ADR_SPACE_SMBUS, |
49 | ACPI_ADR_SPACE_CMOS, |
50 | ACPI_ADR_SPACE_PCI_BAR_TARGET, |
51 | ACPI_ADR_SPACE_IPMI, |
52 | ACPI_ADR_SPACE_GPIO, |
53 | ACPI_ADR_SPACE_GSBUS, |
54 | ACPI_ADR_SPACE_PLATFORM_COMM, |
55 | ACPI_ADR_SPACE_PLATFORM_RT, |
56 | ACPI_ADR_SPACE_DATA_TABLE, |
57 | ACPI_ADR_SPACE_FIXED_HARDWARE |
58 | }; |
59 | |
60 | /* Global handler information */ |
61 | |
62 | typedef struct acpi_handler_info { |
63 | void *handler; |
64 | char *name; |
65 | |
66 | } acpi_handler_info; |
67 | |
68 | static struct acpi_handler_info acpi_gbl_handler_list[] = { |
69 | {&acpi_gbl_global_notify[0].handler, "System Notifications" }, |
70 | {&acpi_gbl_global_notify[1].handler, "Device Notifications" }, |
71 | {&acpi_gbl_table_handler, "ACPI Table Events" }, |
72 | {&acpi_gbl_exception_handler, "Control Method Exceptions" }, |
73 | {&acpi_gbl_interface_handler, "OSI Invocations" } |
74 | }; |
75 | |
76 | /******************************************************************************* |
77 | * |
78 | * FUNCTION: acpi_db_get_pointer |
79 | * |
80 | * PARAMETERS: target - Pointer to string to be converted |
81 | * |
82 | * RETURN: Converted pointer |
83 | * |
84 | * DESCRIPTION: Convert an ascii pointer value to a real value |
85 | * |
86 | ******************************************************************************/ |
87 | |
88 | static void *acpi_db_get_pointer(void *target) |
89 | { |
90 | void *obj_ptr; |
91 | acpi_size address; |
92 | |
93 | address = strtoul(target, NULL, 16); |
94 | obj_ptr = ACPI_TO_POINTER(address); |
95 | return (obj_ptr); |
96 | } |
97 | |
98 | /******************************************************************************* |
99 | * |
100 | * FUNCTION: acpi_db_dump_parser_descriptor |
101 | * |
102 | * PARAMETERS: op - A parser Op descriptor |
103 | * |
104 | * RETURN: None |
105 | * |
106 | * DESCRIPTION: Display a formatted parser object |
107 | * |
108 | ******************************************************************************/ |
109 | |
110 | static void acpi_db_dump_parser_descriptor(union acpi_parse_object *op) |
111 | { |
112 | const struct acpi_opcode_info *info; |
113 | |
114 | info = acpi_ps_get_opcode_info(opcode: op->common.aml_opcode); |
115 | |
116 | acpi_os_printf(format: "Parser Op Descriptor:\n" ); |
117 | acpi_os_printf(format: "%20.20s : %4.4X\n" , "Opcode" , op->common.aml_opcode); |
118 | |
119 | ACPI_DEBUG_ONLY_MEMBERS(acpi_os_printf("%20.20s : %s\n" , "Opcode Name" , |
120 | info->name)); |
121 | |
122 | acpi_os_printf(format: "%20.20s : %p\n" , "Value/ArgList" , op->common.value.arg); |
123 | acpi_os_printf(format: "%20.20s : %p\n" , "Parent" , op->common.parent); |
124 | acpi_os_printf(format: "%20.20s : %p\n" , "NextOp" , op->common.next); |
125 | } |
126 | |
127 | /******************************************************************************* |
128 | * |
129 | * FUNCTION: acpi_db_decode_and_display_object |
130 | * |
131 | * PARAMETERS: target - String with object to be displayed. Names |
132 | * and hex pointers are supported. |
133 | * output_type - Byte, Word, Dword, or Qword (B|W|D|Q) |
134 | * |
135 | * RETURN: None |
136 | * |
137 | * DESCRIPTION: Display a formatted ACPI object |
138 | * |
139 | ******************************************************************************/ |
140 | |
141 | void acpi_db_decode_and_display_object(char *target, char *output_type) |
142 | { |
143 | void *obj_ptr; |
144 | struct acpi_namespace_node *node; |
145 | union acpi_operand_object *obj_desc; |
146 | u32 display = DB_BYTE_DISPLAY; |
147 | char buffer[80]; |
148 | struct acpi_buffer ret_buf; |
149 | acpi_status status; |
150 | u32 size; |
151 | |
152 | if (!target) { |
153 | return; |
154 | } |
155 | |
156 | /* Decode the output type */ |
157 | |
158 | if (output_type) { |
159 | acpi_ut_strupr(src_string: output_type); |
160 | if (output_type[0] == 'W') { |
161 | display = DB_WORD_DISPLAY; |
162 | } else if (output_type[0] == 'D') { |
163 | display = DB_DWORD_DISPLAY; |
164 | } else if (output_type[0] == 'Q') { |
165 | display = DB_QWORD_DISPLAY; |
166 | } |
167 | } |
168 | |
169 | ret_buf.length = sizeof(buffer); |
170 | ret_buf.pointer = buffer; |
171 | |
172 | /* Differentiate between a number and a name */ |
173 | |
174 | if ((target[0] >= 0x30) && (target[0] <= 0x39)) { |
175 | obj_ptr = acpi_db_get_pointer(target); |
176 | if (!acpi_os_readable(pointer: obj_ptr, length: 16)) { |
177 | acpi_os_printf |
178 | (format: "Address %p is invalid in this address space\n" , |
179 | obj_ptr); |
180 | return; |
181 | } |
182 | |
183 | /* Decode the object type */ |
184 | |
185 | switch (ACPI_GET_DESCRIPTOR_TYPE(obj_ptr)) { |
186 | case ACPI_DESC_TYPE_NAMED: |
187 | |
188 | /* This is a namespace Node */ |
189 | |
190 | if (!acpi_os_readable |
191 | (pointer: obj_ptr, length: sizeof(struct acpi_namespace_node))) { |
192 | acpi_os_printf |
193 | (format: "Cannot read entire Named object at address %p\n" , |
194 | obj_ptr); |
195 | return; |
196 | } |
197 | |
198 | node = obj_ptr; |
199 | goto dump_node; |
200 | |
201 | case ACPI_DESC_TYPE_OPERAND: |
202 | |
203 | /* This is a ACPI OPERAND OBJECT */ |
204 | |
205 | if (!acpi_os_readable |
206 | (pointer: obj_ptr, length: sizeof(union acpi_operand_object))) { |
207 | acpi_os_printf |
208 | (format: "Cannot read entire ACPI object at address %p\n" , |
209 | obj_ptr); |
210 | return; |
211 | } |
212 | |
213 | acpi_ut_debug_dump_buffer(buffer: obj_ptr, |
214 | count: sizeof(union |
215 | acpi_operand_object), |
216 | display, ACPI_UINT32_MAX); |
217 | acpi_ex_dump_object_descriptor(object: obj_ptr, flags: 1); |
218 | break; |
219 | |
220 | case ACPI_DESC_TYPE_PARSER: |
221 | |
222 | /* This is a Parser Op object */ |
223 | |
224 | if (!acpi_os_readable |
225 | (pointer: obj_ptr, length: sizeof(union acpi_parse_object))) { |
226 | acpi_os_printf |
227 | (format: "Cannot read entire Parser object at address %p\n" , |
228 | obj_ptr); |
229 | return; |
230 | } |
231 | |
232 | acpi_ut_debug_dump_buffer(buffer: obj_ptr, |
233 | count: sizeof(union |
234 | acpi_parse_object), |
235 | display, ACPI_UINT32_MAX); |
236 | acpi_db_dump_parser_descriptor(op: (union acpi_parse_object |
237 | *)obj_ptr); |
238 | break; |
239 | |
240 | default: |
241 | |
242 | /* Is not a recognizable object */ |
243 | |
244 | acpi_os_printf |
245 | (format: "Not a known ACPI internal object, descriptor type %2.2X\n" , |
246 | ACPI_GET_DESCRIPTOR_TYPE(obj_ptr)); |
247 | |
248 | size = 16; |
249 | if (acpi_os_readable(pointer: obj_ptr, length: 64)) { |
250 | size = 64; |
251 | } |
252 | |
253 | /* Just dump some memory */ |
254 | |
255 | acpi_ut_debug_dump_buffer(buffer: obj_ptr, count: size, display, |
256 | ACPI_UINT32_MAX); |
257 | break; |
258 | } |
259 | |
260 | return; |
261 | } |
262 | |
263 | /* The parameter is a name string that must be resolved to a Named obj */ |
264 | |
265 | node = acpi_db_local_ns_lookup(name: target); |
266 | if (!node) { |
267 | return; |
268 | } |
269 | |
270 | dump_node: |
271 | /* Now dump the NS node */ |
272 | |
273 | status = acpi_get_name(object: node, ACPI_FULL_PATHNAME_NO_TRAILING, ret_path_ptr: &ret_buf); |
274 | if (ACPI_FAILURE(status)) { |
275 | acpi_os_printf(format: "Could not convert name to pathname\n" ); |
276 | } |
277 | |
278 | else { |
279 | acpi_os_printf(format: "Object %p: Namespace Node - Pathname: %s\n" , |
280 | node, (char *)ret_buf.pointer); |
281 | } |
282 | |
283 | if (!acpi_os_readable(pointer: node, length: sizeof(struct acpi_namespace_node))) { |
284 | acpi_os_printf(format: "Invalid Named object at address %p\n" , node); |
285 | return; |
286 | } |
287 | |
288 | acpi_ut_debug_dump_buffer(buffer: (void *)node, |
289 | count: sizeof(struct acpi_namespace_node), display, |
290 | ACPI_UINT32_MAX); |
291 | acpi_ex_dump_namespace_node(node, flags: 1); |
292 | |
293 | obj_desc = acpi_ns_get_attached_object(node); |
294 | if (obj_desc) { |
295 | acpi_os_printf(format: "\nAttached Object %p:" , obj_desc); |
296 | if (!acpi_os_readable |
297 | (pointer: obj_desc, length: sizeof(union acpi_operand_object))) { |
298 | acpi_os_printf |
299 | (format: "Invalid internal ACPI Object at address %p\n" , |
300 | obj_desc); |
301 | return; |
302 | } |
303 | |
304 | if (ACPI_GET_DESCRIPTOR_TYPE(((struct acpi_namespace_node *) |
305 | obj_desc)) == |
306 | ACPI_DESC_TYPE_NAMED) { |
307 | acpi_os_printf(format: " Namespace Node - " ); |
308 | status = |
309 | acpi_get_name(object: (struct acpi_namespace_node *) |
310 | obj_desc, |
311 | ACPI_FULL_PATHNAME_NO_TRAILING, |
312 | ret_path_ptr: &ret_buf); |
313 | if (ACPI_FAILURE(status)) { |
314 | acpi_os_printf |
315 | (format: "Could not convert name to pathname\n" ); |
316 | } else { |
317 | acpi_os_printf(format: "Pathname: %s" , |
318 | (char *)ret_buf.pointer); |
319 | } |
320 | |
321 | acpi_os_printf(format: "\n" ); |
322 | acpi_ut_debug_dump_buffer(buffer: (void *)obj_desc, |
323 | count: sizeof(struct |
324 | acpi_namespace_node), |
325 | display, ACPI_UINT32_MAX); |
326 | } else { |
327 | acpi_os_printf(format: "\n" ); |
328 | acpi_ut_debug_dump_buffer(buffer: (void *)obj_desc, |
329 | count: sizeof(union |
330 | acpi_operand_object), |
331 | display, ACPI_UINT32_MAX); |
332 | } |
333 | |
334 | acpi_ex_dump_object_descriptor(object: obj_desc, flags: 1); |
335 | } |
336 | } |
337 | |
338 | /******************************************************************************* |
339 | * |
340 | * FUNCTION: acpi_db_display_method_info |
341 | * |
342 | * PARAMETERS: start_op - Root of the control method parse tree |
343 | * |
344 | * RETURN: None |
345 | * |
346 | * DESCRIPTION: Display information about the current method |
347 | * |
348 | ******************************************************************************/ |
349 | |
350 | void acpi_db_display_method_info(union acpi_parse_object *start_op) |
351 | { |
352 | struct acpi_walk_state *walk_state; |
353 | union acpi_operand_object *obj_desc; |
354 | struct acpi_namespace_node *node; |
355 | union acpi_parse_object *root_op; |
356 | union acpi_parse_object *op; |
357 | const struct acpi_opcode_info *op_info; |
358 | u32 num_ops = 0; |
359 | u32 num_operands = 0; |
360 | u32 num_operators = 0; |
361 | u32 num_remaining_ops = 0; |
362 | u32 num_remaining_operands = 0; |
363 | u32 num_remaining_operators = 0; |
364 | u8 count_remaining = FALSE; |
365 | |
366 | walk_state = acpi_ds_get_current_walk_state(thread: acpi_gbl_current_walk_list); |
367 | if (!walk_state) { |
368 | acpi_os_printf(format: "There is no method currently executing\n" ); |
369 | return; |
370 | } |
371 | |
372 | obj_desc = walk_state->method_desc; |
373 | node = walk_state->method_node; |
374 | |
375 | acpi_os_printf(format: "Currently executing control method is [%4.4s]\n" , |
376 | acpi_ut_get_node_name(object: node)); |
377 | acpi_os_printf(format: "%X Arguments, SyncLevel = %X\n" , |
378 | (u32)obj_desc->method.param_count, |
379 | (u32)obj_desc->method.sync_level); |
380 | |
381 | root_op = start_op; |
382 | while (root_op->common.parent) { |
383 | root_op = root_op->common.parent; |
384 | } |
385 | |
386 | op = root_op; |
387 | |
388 | while (op) { |
389 | if (op == start_op) { |
390 | count_remaining = TRUE; |
391 | } |
392 | |
393 | num_ops++; |
394 | if (count_remaining) { |
395 | num_remaining_ops++; |
396 | } |
397 | |
398 | /* Decode the opcode */ |
399 | |
400 | op_info = acpi_ps_get_opcode_info(opcode: op->common.aml_opcode); |
401 | switch (op_info->class) { |
402 | case AML_CLASS_ARGUMENT: |
403 | |
404 | if (count_remaining) { |
405 | num_remaining_operands++; |
406 | } |
407 | |
408 | num_operands++; |
409 | break; |
410 | |
411 | case AML_CLASS_UNKNOWN: |
412 | |
413 | /* Bad opcode or ASCII character */ |
414 | |
415 | continue; |
416 | |
417 | default: |
418 | |
419 | if (count_remaining) { |
420 | num_remaining_operators++; |
421 | } |
422 | |
423 | num_operators++; |
424 | break; |
425 | } |
426 | |
427 | op = acpi_ps_get_depth_next(origin: start_op, op); |
428 | } |
429 | |
430 | acpi_os_printf |
431 | (format: "Method contains: %X AML Opcodes - %X Operators, %X Operands\n" , |
432 | num_ops, num_operators, num_operands); |
433 | |
434 | acpi_os_printf |
435 | (format: "Remaining to execute: %X AML Opcodes - %X Operators, %X Operands\n" , |
436 | num_remaining_ops, num_remaining_operators, |
437 | num_remaining_operands); |
438 | } |
439 | |
440 | /******************************************************************************* |
441 | * |
442 | * FUNCTION: acpi_db_display_locals |
443 | * |
444 | * PARAMETERS: None |
445 | * |
446 | * RETURN: None |
447 | * |
448 | * DESCRIPTION: Display all locals for the currently running control method |
449 | * |
450 | ******************************************************************************/ |
451 | |
452 | void acpi_db_display_locals(void) |
453 | { |
454 | struct acpi_walk_state *walk_state; |
455 | |
456 | walk_state = acpi_ds_get_current_walk_state(thread: acpi_gbl_current_walk_list); |
457 | if (!walk_state) { |
458 | acpi_os_printf(format: "There is no method currently executing\n" ); |
459 | return; |
460 | } |
461 | |
462 | acpi_db_decode_locals(walk_state); |
463 | } |
464 | |
465 | /******************************************************************************* |
466 | * |
467 | * FUNCTION: acpi_db_display_arguments |
468 | * |
469 | * PARAMETERS: None |
470 | * |
471 | * RETURN: None |
472 | * |
473 | * DESCRIPTION: Display all arguments for the currently running control method |
474 | * |
475 | ******************************************************************************/ |
476 | |
477 | void acpi_db_display_arguments(void) |
478 | { |
479 | struct acpi_walk_state *walk_state; |
480 | |
481 | walk_state = acpi_ds_get_current_walk_state(thread: acpi_gbl_current_walk_list); |
482 | if (!walk_state) { |
483 | acpi_os_printf(format: "There is no method currently executing\n" ); |
484 | return; |
485 | } |
486 | |
487 | acpi_db_decode_arguments(walk_state); |
488 | } |
489 | |
490 | /******************************************************************************* |
491 | * |
492 | * FUNCTION: acpi_db_display_results |
493 | * |
494 | * PARAMETERS: None |
495 | * |
496 | * RETURN: None |
497 | * |
498 | * DESCRIPTION: Display current contents of a method result stack |
499 | * |
500 | ******************************************************************************/ |
501 | |
502 | void acpi_db_display_results(void) |
503 | { |
504 | u32 i; |
505 | struct acpi_walk_state *walk_state; |
506 | union acpi_operand_object *obj_desc; |
507 | u32 result_count = 0; |
508 | struct acpi_namespace_node *node; |
509 | union acpi_generic_state *frame; |
510 | u32 index; /* Index onto current frame */ |
511 | |
512 | walk_state = acpi_ds_get_current_walk_state(thread: acpi_gbl_current_walk_list); |
513 | if (!walk_state) { |
514 | acpi_os_printf(format: "There is no method currently executing\n" ); |
515 | return; |
516 | } |
517 | |
518 | node = walk_state->method_node; |
519 | |
520 | if (walk_state->results) { |
521 | result_count = walk_state->result_count; |
522 | } |
523 | |
524 | acpi_os_printf(format: "Method [%4.4s] has %X stacked result objects\n" , |
525 | acpi_ut_get_node_name(object: node), result_count); |
526 | |
527 | /* From the top element of result stack */ |
528 | |
529 | frame = walk_state->results; |
530 | index = (result_count - 1) % ACPI_RESULTS_FRAME_OBJ_NUM; |
531 | |
532 | for (i = 0; i < result_count; i++) { |
533 | obj_desc = frame->results.obj_desc[index]; |
534 | acpi_os_printf(format: "Result%u: " , i); |
535 | acpi_db_display_internal_object(obj_desc, walk_state); |
536 | |
537 | if (index == 0) { |
538 | frame = frame->results.next; |
539 | index = ACPI_RESULTS_FRAME_OBJ_NUM; |
540 | } |
541 | |
542 | index--; |
543 | } |
544 | } |
545 | |
546 | /******************************************************************************* |
547 | * |
548 | * FUNCTION: acpi_db_display_calling_tree |
549 | * |
550 | * PARAMETERS: None |
551 | * |
552 | * RETURN: None |
553 | * |
554 | * DESCRIPTION: Display current calling tree of nested control methods |
555 | * |
556 | ******************************************************************************/ |
557 | |
558 | void acpi_db_display_calling_tree(void) |
559 | { |
560 | struct acpi_walk_state *walk_state; |
561 | struct acpi_namespace_node *node; |
562 | |
563 | walk_state = acpi_ds_get_current_walk_state(thread: acpi_gbl_current_walk_list); |
564 | if (!walk_state) { |
565 | acpi_os_printf(format: "There is no method currently executing\n" ); |
566 | return; |
567 | } |
568 | |
569 | acpi_os_printf(format: "Current Control Method Call Tree\n" ); |
570 | |
571 | while (walk_state) { |
572 | node = walk_state->method_node; |
573 | acpi_os_printf(format: " [%4.4s]\n" , acpi_ut_get_node_name(object: node)); |
574 | |
575 | walk_state = walk_state->next; |
576 | } |
577 | } |
578 | |
579 | /******************************************************************************* |
580 | * |
581 | * FUNCTION: acpi_db_display_object_type |
582 | * |
583 | * PARAMETERS: object_arg - User entered NS node handle |
584 | * |
585 | * RETURN: None |
586 | * |
587 | * DESCRIPTION: Display type of an arbitrary NS node |
588 | * |
589 | ******************************************************************************/ |
590 | |
591 | void acpi_db_display_object_type(char *object_arg) |
592 | { |
593 | acpi_size arg; |
594 | acpi_handle handle; |
595 | struct acpi_device_info *info; |
596 | acpi_status status; |
597 | u32 i; |
598 | |
599 | arg = strtoul(object_arg, NULL, 16); |
600 | handle = ACPI_TO_POINTER(arg); |
601 | |
602 | status = acpi_get_object_info(object: handle, return_buffer: &info); |
603 | if (ACPI_FAILURE(status)) { |
604 | acpi_os_printf(format: "Could not get object info, %s\n" , |
605 | acpi_format_exception(exception: status)); |
606 | return; |
607 | } |
608 | |
609 | acpi_os_printf(format: "ADR: %8.8X%8.8X, Flags: %X\n" , |
610 | ACPI_FORMAT_UINT64(info->address), info->flags); |
611 | |
612 | acpi_os_printf(format: "S1D-%2.2X S2D-%2.2X S3D-%2.2X S4D-%2.2X\n" , |
613 | info->highest_dstates[0], info->highest_dstates[1], |
614 | info->highest_dstates[2], info->highest_dstates[3]); |
615 | |
616 | acpi_os_printf(format: "S0W-%2.2X S1W-%2.2X S2W-%2.2X S3W-%2.2X S4W-%2.2X\n" , |
617 | info->lowest_dstates[0], info->lowest_dstates[1], |
618 | info->lowest_dstates[2], info->lowest_dstates[3], |
619 | info->lowest_dstates[4]); |
620 | |
621 | if (info->valid & ACPI_VALID_HID) { |
622 | acpi_os_printf(format: "HID: %s\n" , info->hardware_id.string); |
623 | } |
624 | |
625 | if (info->valid & ACPI_VALID_UID) { |
626 | acpi_os_printf(format: "UID: %s\n" , info->unique_id.string); |
627 | } |
628 | |
629 | if (info->valid & ACPI_VALID_CID) { |
630 | for (i = 0; i < info->compatible_id_list.count; i++) { |
631 | acpi_os_printf(format: "CID %u: %s\n" , i, |
632 | info->compatible_id_list.ids[i].string); |
633 | } |
634 | } |
635 | |
636 | ACPI_FREE(info); |
637 | } |
638 | |
639 | /******************************************************************************* |
640 | * |
641 | * FUNCTION: acpi_db_display_result_object |
642 | * |
643 | * PARAMETERS: obj_desc - Object to be displayed |
644 | * walk_state - Current walk state |
645 | * |
646 | * RETURN: None |
647 | * |
648 | * DESCRIPTION: Display the result of an AML opcode |
649 | * |
650 | * Note: Currently only displays the result object if we are single stepping. |
651 | * However, this output may be useful in other contexts and could be enabled |
652 | * to do so if needed. |
653 | * |
654 | ******************************************************************************/ |
655 | |
656 | void |
657 | acpi_db_display_result_object(union acpi_operand_object *obj_desc, |
658 | struct acpi_walk_state *walk_state) |
659 | { |
660 | |
661 | #ifndef ACPI_APPLICATION |
662 | if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) { |
663 | return; |
664 | } |
665 | #endif |
666 | |
667 | /* Only display if single stepping */ |
668 | |
669 | if (!acpi_gbl_cm_single_step) { |
670 | return; |
671 | } |
672 | |
673 | acpi_os_printf(format: "ResultObj: " ); |
674 | acpi_db_display_internal_object(obj_desc, walk_state); |
675 | acpi_os_printf(format: "\n" ); |
676 | } |
677 | |
678 | /******************************************************************************* |
679 | * |
680 | * FUNCTION: acpi_db_display_argument_object |
681 | * |
682 | * PARAMETERS: obj_desc - Object to be displayed |
683 | * walk_state - Current walk state |
684 | * |
685 | * RETURN: None |
686 | * |
687 | * DESCRIPTION: Display the result of an AML opcode |
688 | * |
689 | ******************************************************************************/ |
690 | |
691 | void |
692 | acpi_db_display_argument_object(union acpi_operand_object *obj_desc, |
693 | struct acpi_walk_state *walk_state) |
694 | { |
695 | |
696 | #ifndef ACPI_APPLICATION |
697 | if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) { |
698 | return; |
699 | } |
700 | #endif |
701 | |
702 | if (!acpi_gbl_cm_single_step) { |
703 | return; |
704 | } |
705 | |
706 | acpi_os_printf(format: "ArgObj: " ); |
707 | acpi_db_display_internal_object(obj_desc, walk_state); |
708 | } |
709 | |
710 | #if (!ACPI_REDUCED_HARDWARE) |
711 | /******************************************************************************* |
712 | * |
713 | * FUNCTION: acpi_db_display_gpes |
714 | * |
715 | * PARAMETERS: None |
716 | * |
717 | * RETURN: None |
718 | * |
719 | * DESCRIPTION: Display the current GPE structures |
720 | * |
721 | ******************************************************************************/ |
722 | |
723 | void acpi_db_display_gpes(void) |
724 | { |
725 | struct acpi_gpe_block_info *gpe_block; |
726 | struct acpi_gpe_xrupt_info *gpe_xrupt_info; |
727 | struct acpi_gpe_event_info *gpe_event_info; |
728 | struct acpi_gpe_register_info *gpe_register_info; |
729 | char *gpe_type; |
730 | struct acpi_gpe_notify_info *notify; |
731 | u32 gpe_index; |
732 | u32 block = 0; |
733 | u32 i; |
734 | u32 j; |
735 | u32 count; |
736 | char buffer[80]; |
737 | struct acpi_buffer ret_buf; |
738 | acpi_status status; |
739 | |
740 | ret_buf.length = sizeof(buffer); |
741 | ret_buf.pointer = buffer; |
742 | |
743 | block = 0; |
744 | |
745 | /* Walk the GPE lists */ |
746 | |
747 | gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; |
748 | while (gpe_xrupt_info) { |
749 | gpe_block = gpe_xrupt_info->gpe_block_list_head; |
750 | while (gpe_block) { |
751 | status = acpi_get_name(gpe_block->node, |
752 | ACPI_FULL_PATHNAME_NO_TRAILING, |
753 | &ret_buf); |
754 | if (ACPI_FAILURE(status)) { |
755 | acpi_os_printf |
756 | ("Could not convert name to pathname\n" ); |
757 | } |
758 | |
759 | if (gpe_block->node == acpi_gbl_fadt_gpe_device) { |
760 | gpe_type = "FADT-defined GPE block" ; |
761 | } else { |
762 | gpe_type = "GPE Block Device" ; |
763 | } |
764 | |
765 | acpi_os_printf |
766 | ("\nBlock %u - Info %p DeviceNode %p [%s] - %s\n" , |
767 | block, gpe_block, gpe_block->node, buffer, |
768 | gpe_type); |
769 | |
770 | acpi_os_printf(" Registers: %u (%u GPEs)\n" , |
771 | gpe_block->register_count, |
772 | gpe_block->gpe_count); |
773 | |
774 | acpi_os_printf |
775 | (" GPE range: 0x%X to 0x%X on interrupt %u\n" , |
776 | gpe_block->block_base_number, |
777 | gpe_block->block_base_number + |
778 | (gpe_block->gpe_count - 1), |
779 | gpe_xrupt_info->interrupt_number); |
780 | |
781 | acpi_os_printf |
782 | (" RegisterInfo: %p Status %8.8X%8.8X Enable %8.8X%8.8X\n" , |
783 | gpe_block->register_info, |
784 | ACPI_FORMAT_UINT64(gpe_block->register_info-> |
785 | status_address.address), |
786 | ACPI_FORMAT_UINT64(gpe_block->register_info-> |
787 | enable_address.address)); |
788 | |
789 | acpi_os_printf(" EventInfo: %p\n" , |
790 | gpe_block->event_info); |
791 | |
792 | /* Examine each GPE Register within the block */ |
793 | |
794 | for (i = 0; i < gpe_block->register_count; i++) { |
795 | gpe_register_info = |
796 | &gpe_block->register_info[i]; |
797 | |
798 | acpi_os_printf(" Reg %u: (GPE %.2X-%.2X) " |
799 | "RunEnable %2.2X WakeEnable %2.2X" |
800 | " Status %8.8X%8.8X Enable %8.8X%8.8X\n" , |
801 | i, |
802 | gpe_register_info-> |
803 | base_gpe_number, |
804 | gpe_register_info-> |
805 | base_gpe_number + |
806 | (ACPI_GPE_REGISTER_WIDTH - 1), |
807 | gpe_register_info-> |
808 | enable_for_run, |
809 | gpe_register_info-> |
810 | enable_for_wake, |
811 | ACPI_FORMAT_UINT64 |
812 | (gpe_register_info-> |
813 | status_address.address), |
814 | ACPI_FORMAT_UINT64 |
815 | (gpe_register_info-> |
816 | enable_address.address)); |
817 | |
818 | /* Now look at the individual GPEs in this byte register */ |
819 | |
820 | for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { |
821 | gpe_index = |
822 | (i * ACPI_GPE_REGISTER_WIDTH) + j; |
823 | gpe_event_info = |
824 | &gpe_block->event_info[gpe_index]; |
825 | |
826 | if (ACPI_GPE_DISPATCH_TYPE |
827 | (gpe_event_info->flags) == |
828 | ACPI_GPE_DISPATCH_NONE) { |
829 | |
830 | /* This GPE is not used (no method or handler), ignore it */ |
831 | |
832 | continue; |
833 | } |
834 | |
835 | acpi_os_printf |
836 | (" GPE %.2X: %p RunRefs %2.2X Flags %2.2X (" , |
837 | gpe_block->block_base_number + |
838 | gpe_index, gpe_event_info, |
839 | gpe_event_info->runtime_count, |
840 | gpe_event_info->flags); |
841 | |
842 | /* Decode the flags byte */ |
843 | |
844 | if (gpe_event_info-> |
845 | flags & ACPI_GPE_LEVEL_TRIGGERED) { |
846 | acpi_os_printf("Level, " ); |
847 | } else { |
848 | acpi_os_printf("Edge, " ); |
849 | } |
850 | |
851 | if (gpe_event_info-> |
852 | flags & ACPI_GPE_CAN_WAKE) { |
853 | acpi_os_printf("CanWake, " ); |
854 | } else { |
855 | acpi_os_printf("RunOnly, " ); |
856 | } |
857 | |
858 | switch (ACPI_GPE_DISPATCH_TYPE |
859 | (gpe_event_info->flags)) { |
860 | case ACPI_GPE_DISPATCH_NONE: |
861 | |
862 | acpi_os_printf("NotUsed" ); |
863 | break; |
864 | |
865 | case ACPI_GPE_DISPATCH_METHOD: |
866 | |
867 | acpi_os_printf("Method" ); |
868 | break; |
869 | |
870 | case ACPI_GPE_DISPATCH_HANDLER: |
871 | |
872 | acpi_os_printf("Handler" ); |
873 | break; |
874 | |
875 | case ACPI_GPE_DISPATCH_NOTIFY: |
876 | |
877 | count = 0; |
878 | notify = |
879 | gpe_event_info->dispatch. |
880 | notify_list; |
881 | while (notify) { |
882 | count++; |
883 | notify = notify->next; |
884 | } |
885 | |
886 | acpi_os_printf |
887 | ("Implicit Notify on %u devices" , |
888 | count); |
889 | break; |
890 | |
891 | case ACPI_GPE_DISPATCH_RAW_HANDLER: |
892 | |
893 | acpi_os_printf("RawHandler" ); |
894 | break; |
895 | |
896 | default: |
897 | |
898 | acpi_os_printf("UNKNOWN: %X" , |
899 | ACPI_GPE_DISPATCH_TYPE |
900 | (gpe_event_info-> |
901 | flags)); |
902 | break; |
903 | } |
904 | |
905 | acpi_os_printf(")\n" ); |
906 | } |
907 | } |
908 | |
909 | block++; |
910 | gpe_block = gpe_block->next; |
911 | } |
912 | |
913 | gpe_xrupt_info = gpe_xrupt_info->next; |
914 | } |
915 | } |
916 | #endif /* !ACPI_REDUCED_HARDWARE */ |
917 | |
918 | /******************************************************************************* |
919 | * |
920 | * FUNCTION: acpi_db_display_handlers |
921 | * |
922 | * PARAMETERS: None |
923 | * |
924 | * RETURN: None |
925 | * |
926 | * DESCRIPTION: Display the currently installed global handlers |
927 | * |
928 | ******************************************************************************/ |
929 | |
930 | void acpi_db_display_handlers(void) |
931 | { |
932 | union acpi_operand_object *obj_desc; |
933 | union acpi_operand_object *handler_obj; |
934 | acpi_adr_space_type space_id; |
935 | u32 i; |
936 | |
937 | /* Operation region handlers */ |
938 | |
939 | acpi_os_printf(format: "\nOperation Region Handlers at the namespace root:\n" ); |
940 | |
941 | obj_desc = acpi_ns_get_attached_object(node: acpi_gbl_root_node); |
942 | if (obj_desc) { |
943 | for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_gbl_space_id_list); i++) { |
944 | space_id = acpi_gbl_space_id_list[i]; |
945 | |
946 | acpi_os_printf(ACPI_PREDEFINED_PREFIX, |
947 | acpi_ut_get_region_name(space_id: (u8)space_id), |
948 | space_id); |
949 | |
950 | handler_obj = |
951 | acpi_ev_find_region_handler(space_id, |
952 | handler_obj: obj_desc->common_notify. |
953 | handler); |
954 | if (handler_obj) { |
955 | acpi_os_printf(ACPI_HANDLER_PRESENT_STRING, |
956 | (handler_obj->address_space. |
957 | handler_flags & |
958 | ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) |
959 | ? "Default" : "User" , |
960 | handler_obj->address_space. |
961 | handler); |
962 | |
963 | goto found_handler; |
964 | } |
965 | |
966 | /* There is no handler for this space_id */ |
967 | |
968 | acpi_os_printf(format: "None\n" ); |
969 | |
970 | found_handler: ; |
971 | } |
972 | |
973 | /* Find all handlers for user-defined space_IDs */ |
974 | |
975 | handler_obj = obj_desc->common_notify.handler; |
976 | while (handler_obj) { |
977 | if (handler_obj->address_space.space_id >= |
978 | ACPI_USER_REGION_BEGIN) { |
979 | acpi_os_printf(ACPI_PREDEFINED_PREFIX, |
980 | "User-defined ID" , |
981 | handler_obj->address_space. |
982 | space_id); |
983 | acpi_os_printf(ACPI_HANDLER_PRESENT_STRING, |
984 | (handler_obj->address_space. |
985 | handler_flags & |
986 | ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) |
987 | ? "Default" : "User" , |
988 | handler_obj->address_space. |
989 | handler); |
990 | } |
991 | |
992 | handler_obj = handler_obj->address_space.next; |
993 | } |
994 | } |
995 | #if (!ACPI_REDUCED_HARDWARE) |
996 | |
997 | /* Fixed event handlers */ |
998 | |
999 | acpi_os_printf("\nFixed Event Handlers:\n" ); |
1000 | |
1001 | for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) { |
1002 | acpi_os_printf(ACPI_PREDEFINED_PREFIX, |
1003 | acpi_ut_get_event_name(i), i); |
1004 | if (acpi_gbl_fixed_event_handlers[i].handler) { |
1005 | acpi_os_printf(ACPI_HANDLER_PRESENT_STRING, "User" , |
1006 | acpi_gbl_fixed_event_handlers[i]. |
1007 | handler); |
1008 | } else { |
1009 | acpi_os_printf(ACPI_HANDLER_NOT_PRESENT_STRING, "None" ); |
1010 | } |
1011 | } |
1012 | |
1013 | #endif /* !ACPI_REDUCED_HARDWARE */ |
1014 | |
1015 | /* Miscellaneous global handlers */ |
1016 | |
1017 | acpi_os_printf(format: "\nMiscellaneous Global Handlers:\n" ); |
1018 | |
1019 | for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_gbl_handler_list); i++) { |
1020 | acpi_os_printf(ACPI_HANDLER_NAME_STRING, |
1021 | acpi_gbl_handler_list[i].name); |
1022 | |
1023 | if (acpi_gbl_handler_list[i].handler) { |
1024 | acpi_os_printf(ACPI_HANDLER_PRESENT_STRING, "User" , |
1025 | acpi_gbl_handler_list[i].handler); |
1026 | } else { |
1027 | acpi_os_printf(ACPI_HANDLER_NOT_PRESENT_STRING, "None" ); |
1028 | } |
1029 | } |
1030 | |
1031 | /* Other handlers that are installed throughout the namespace */ |
1032 | |
1033 | acpi_os_printf(format: "\nOperation Region Handlers for specific devices:\n" ); |
1034 | |
1035 | (void)acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
1036 | ACPI_UINT32_MAX, |
1037 | descending_callback: acpi_db_display_non_root_handlers, NULL, NULL, |
1038 | NULL); |
1039 | } |
1040 | |
1041 | /******************************************************************************* |
1042 | * |
1043 | * FUNCTION: acpi_db_display_non_root_handlers |
1044 | * |
1045 | * PARAMETERS: acpi_walk_callback |
1046 | * |
1047 | * RETURN: Status |
1048 | * |
1049 | * DESCRIPTION: Display information about all handlers installed for a |
1050 | * device object. |
1051 | * |
1052 | ******************************************************************************/ |
1053 | |
1054 | static acpi_status |
1055 | acpi_db_display_non_root_handlers(acpi_handle obj_handle, |
1056 | u32 nesting_level, |
1057 | void *context, void **return_value) |
1058 | { |
1059 | struct acpi_namespace_node *node = |
1060 | ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); |
1061 | union acpi_operand_object *obj_desc; |
1062 | union acpi_operand_object *handler_obj; |
1063 | char *pathname; |
1064 | |
1065 | obj_desc = acpi_ns_get_attached_object(node); |
1066 | if (!obj_desc) { |
1067 | return (AE_OK); |
1068 | } |
1069 | |
1070 | pathname = acpi_ns_get_normalized_pathname(node, TRUE); |
1071 | if (!pathname) { |
1072 | return (AE_OK); |
1073 | } |
1074 | |
1075 | /* Display all handlers associated with this device */ |
1076 | |
1077 | handler_obj = obj_desc->common_notify.handler; |
1078 | while (handler_obj) { |
1079 | acpi_os_printf(ACPI_PREDEFINED_PREFIX, |
1080 | acpi_ut_get_region_name(space_id: (u8)handler_obj-> |
1081 | address_space.space_id), |
1082 | handler_obj->address_space.space_id); |
1083 | |
1084 | acpi_os_printf(ACPI_HANDLER_PRESENT_STRING2, |
1085 | (handler_obj->address_space.handler_flags & |
1086 | ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) ? "Default" |
1087 | : "User" , handler_obj->address_space.handler); |
1088 | |
1089 | acpi_os_printf(format: " Device Name: %s (%p)\n" , pathname, node); |
1090 | |
1091 | handler_obj = handler_obj->address_space.next; |
1092 | } |
1093 | |
1094 | ACPI_FREE(pathname); |
1095 | return (AE_OK); |
1096 | } |
1097 | |