1 /*******************************************************************************
2 *
3 * Module Name: dbcmds - Miscellaneous debug commands and output routines
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 "acevents.h"
47 #include "acdebug.h"
48 #include "acnamesp.h"
49 #include "acresrc.h"
50 #include "actables.h"
51
52 #define _COMPONENT ACPI_CA_DEBUGGER
53 ACPI_MODULE_NAME("dbcmds")
54
55 /* Local prototypes */
56 static void
57 acpi_dm_compare_aml_resources(u8 *aml1_buffer,
58 acpi_rsdesc_size aml1_buffer_length,
59 u8 *aml2_buffer,
60 acpi_rsdesc_size aml2_buffer_length);
61
62 static acpi_status
63 acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name);
64
65 static acpi_status
66 acpi_db_resource_callback(struct acpi_resource *resource, void *context);
67
68 static acpi_status
69 acpi_db_device_resources(acpi_handle obj_handle,
70 u32 nesting_level, void *context, void **return_value);
71
72 static void acpi_db_do_one_sleep_state(u8 sleep_state);
73
74 static char *acpi_db_trace_method_name = NULL;
75
76 /*******************************************************************************
77 *
78 * FUNCTION: acpi_db_convert_to_node
79 *
80 * PARAMETERS: in_string - String to convert
81 *
82 * RETURN: Pointer to a NS node
83 *
84 * DESCRIPTION: Convert a string to a valid NS pointer. Handles numeric or
85 * alphanumeric strings.
86 *
87 ******************************************************************************/
88
acpi_db_convert_to_node(char * in_string)89 struct acpi_namespace_node *acpi_db_convert_to_node(char *in_string)
90 {
91 struct acpi_namespace_node *node;
92 acpi_size address;
93
94 if ((*in_string >= 0x30) && (*in_string <= 0x39)) {
95
96 /* Numeric argument, convert */
97
98 address = strtoul(in_string, NULL, 16);
99 node = ACPI_TO_POINTER(address);
100 if (!acpi_os_readable(node, sizeof(struct acpi_namespace_node))) {
101 acpi_os_printf("Address %p is invalid", node);
102 return (NULL);
103 }
104
105 /* Make sure pointer is valid NS node */
106
107 if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
108 acpi_os_printf
109 ("Address %p is not a valid namespace node [%s]\n",
110 node, acpi_ut_get_descriptor_name(node));
111 return (NULL);
112 }
113 } else {
114 /*
115 * Alpha argument: The parameter is a name string that must be
116 * resolved to a Namespace object.
117 */
118 node = acpi_db_local_ns_lookup(in_string);
119 if (!node) {
120 acpi_os_printf
121 ("Could not find [%s] in namespace, defaulting to root node\n",
122 in_string);
123 node = acpi_gbl_root_node;
124 }
125 }
126
127 return (node);
128 }
129
130 /*******************************************************************************
131 *
132 * FUNCTION: acpi_db_sleep
133 *
134 * PARAMETERS: object_arg - Desired sleep state (0-5). NULL means
135 * invoke all possible sleep states.
136 *
137 * RETURN: Status
138 *
139 * DESCRIPTION: Simulate sleep/wake sequences
140 *
141 ******************************************************************************/
142
acpi_db_sleep(char * object_arg)143 acpi_status acpi_db_sleep(char *object_arg)
144 {
145 u8 sleep_state;
146 u32 i;
147
148 ACPI_FUNCTION_TRACE(acpi_db_sleep);
149
150 /* Null input (no arguments) means to invoke all sleep states */
151
152 if (!object_arg) {
153 acpi_os_printf("Invoking all possible sleep states, 0-%d\n",
154 ACPI_S_STATES_MAX);
155
156 for (i = 0; i <= ACPI_S_STATES_MAX; i++) {
157 acpi_db_do_one_sleep_state((u8)i);
158 }
159
160 return_ACPI_STATUS(AE_OK);
161 }
162
163 /* Convert argument to binary and invoke the sleep state */
164
165 sleep_state = (u8)strtoul(object_arg, NULL, 0);
166 acpi_db_do_one_sleep_state(sleep_state);
167 return_ACPI_STATUS(AE_OK);
168 }
169
170 /*******************************************************************************
171 *
172 * FUNCTION: acpi_db_do_one_sleep_state
173 *
174 * PARAMETERS: sleep_state - Desired sleep state (0-5)
175 *
176 * RETURN: None
177 *
178 * DESCRIPTION: Simulate a sleep/wake sequence
179 *
180 ******************************************************************************/
181
acpi_db_do_one_sleep_state(u8 sleep_state)182 static void acpi_db_do_one_sleep_state(u8 sleep_state)
183 {
184 acpi_status status;
185 u8 sleep_type_a;
186 u8 sleep_type_b;
187
188 /* Validate parameter */
189
190 if (sleep_state > ACPI_S_STATES_MAX) {
191 acpi_os_printf("Sleep state %d out of range (%d max)\n",
192 sleep_state, ACPI_S_STATES_MAX);
193 return;
194 }
195
196 acpi_os_printf("\n---- Invoking sleep state S%d (%s):\n",
197 sleep_state, acpi_gbl_sleep_state_names[sleep_state]);
198
199 /* Get the values for the sleep type registers (for display only) */
200
201 status =
202 acpi_get_sleep_type_data(sleep_state, &sleep_type_a, &sleep_type_b);
203 if (ACPI_FAILURE(status)) {
204 acpi_os_printf("Could not evaluate [%s] method, %s\n",
205 acpi_gbl_sleep_state_names[sleep_state],
206 acpi_format_exception(status));
207 return;
208 }
209
210 acpi_os_printf
211 ("Register values for sleep state S%d: Sleep-A: %.2X, Sleep-B: %.2X\n",
212 sleep_state, sleep_type_a, sleep_type_b);
213
214 /* Invoke the various sleep/wake interfaces */
215
216 acpi_os_printf("**** Sleep: Prepare to sleep (S%d) ****\n",
217 sleep_state);
218 status = acpi_enter_sleep_state_prep(sleep_state);
219 if (ACPI_FAILURE(status)) {
220 goto error_exit;
221 }
222
223 acpi_os_printf("**** Sleep: Going to sleep (S%d) ****\n", sleep_state);
224 status = acpi_enter_sleep_state(sleep_state);
225 if (ACPI_FAILURE(status)) {
226 goto error_exit;
227 }
228
229 acpi_os_printf("**** Wake: Prepare to return from sleep (S%d) ****\n",
230 sleep_state);
231 status = acpi_leave_sleep_state_prep(sleep_state);
232 if (ACPI_FAILURE(status)) {
233 goto error_exit;
234 }
235
236 acpi_os_printf("**** Wake: Return from sleep (S%d) ****\n",
237 sleep_state);
238 status = acpi_leave_sleep_state(sleep_state);
239 if (ACPI_FAILURE(status)) {
240 goto error_exit;
241 }
242
243 return;
244
245 error_exit:
246 ACPI_EXCEPTION((AE_INFO, status, "During invocation of sleep state S%d",
247 sleep_state));
248 }
249
250 /*******************************************************************************
251 *
252 * FUNCTION: acpi_db_display_locks
253 *
254 * PARAMETERS: None
255 *
256 * RETURN: None
257 *
258 * DESCRIPTION: Display information about internal mutexes.
259 *
260 ******************************************************************************/
261
acpi_db_display_locks(void)262 void acpi_db_display_locks(void)
263 {
264 u32 i;
265
266 for (i = 0; i < ACPI_MAX_MUTEX; i++) {
267 acpi_os_printf("%26s : %s\n", acpi_ut_get_mutex_name(i),
268 acpi_gbl_mutex_info[i].thread_id ==
269 ACPI_MUTEX_NOT_ACQUIRED ? "Locked" : "Unlocked");
270 }
271 }
272
273 /*******************************************************************************
274 *
275 * FUNCTION: acpi_db_display_table_info
276 *
277 * PARAMETERS: table_arg - Name of table to be displayed
278 *
279 * RETURN: None
280 *
281 * DESCRIPTION: Display information about loaded tables. Current
282 * implementation displays all loaded tables.
283 *
284 ******************************************************************************/
285
acpi_db_display_table_info(char * table_arg)286 void acpi_db_display_table_info(char *table_arg)
287 {
288 u32 i;
289 struct acpi_table_desc *table_desc;
290 acpi_status status;
291
292 /* Header */
293
294 acpi_os_printf("Idx ID Status Type "
295 "TableHeader (Sig, Address, Length, Misc)\n");
296
297 /* Walk the entire root table list */
298
299 for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
300 table_desc = &acpi_gbl_root_table_list.tables[i];
301
302 /* Index and Table ID */
303
304 acpi_os_printf("%3u %.2u ", i, table_desc->owner_id);
305
306 /* Decode the table flags */
307
308 if (!(table_desc->flags & ACPI_TABLE_IS_LOADED)) {
309 acpi_os_printf("NotLoaded ");
310 } else {
311 acpi_os_printf(" Loaded ");
312 }
313
314 switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
315 case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
316
317 acpi_os_printf("External/virtual ");
318 break;
319
320 case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
321
322 acpi_os_printf("Internal/physical ");
323 break;
324
325 case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
326
327 acpi_os_printf("Internal/virtual ");
328 break;
329
330 default:
331
332 acpi_os_printf("INVALID TYPE ");
333 break;
334 }
335
336 /* Make sure that the table is mapped */
337
338 status = acpi_tb_validate_table(table_desc);
339 if (ACPI_FAILURE(status)) {
340 return;
341 }
342
343 /* Dump the table header */
344
345 if (table_desc->pointer) {
346 acpi_tb_print_table_header(table_desc->address,
347 table_desc->pointer);
348 } else {
349 /* If the pointer is null, the table has been unloaded */
350
351 ACPI_INFO(("%4.4s - Table has been unloaded",
352 table_desc->signature.ascii));
353 }
354 }
355 }
356
357 /*******************************************************************************
358 *
359 * FUNCTION: acpi_db_unload_acpi_table
360 *
361 * PARAMETERS: object_name - Namespace pathname for an object that
362 * is owned by the table to be unloaded
363 *
364 * RETURN: None
365 *
366 * DESCRIPTION: Unload an ACPI table, via any namespace node that is owned
367 * by the table.
368 *
369 ******************************************************************************/
370
acpi_db_unload_acpi_table(char * object_name)371 void acpi_db_unload_acpi_table(char *object_name)
372 {
373 struct acpi_namespace_node *node;
374 acpi_status status;
375
376 /* Translate name to an Named object */
377
378 node = acpi_db_convert_to_node(object_name);
379 if (!node) {
380 return;
381 }
382
383 status = acpi_unload_parent_table(ACPI_CAST_PTR(acpi_handle, node));
384 if (ACPI_SUCCESS(status)) {
385 acpi_os_printf("Parent of [%s] (%p) unloaded and uninstalled\n",
386 object_name, node);
387 } else {
388 acpi_os_printf("%s, while unloading parent table of [%s]\n",
389 acpi_format_exception(status), object_name);
390 }
391 }
392
393 /*******************************************************************************
394 *
395 * FUNCTION: acpi_db_send_notify
396 *
397 * PARAMETERS: name - Name of ACPI object where to send notify
398 * value - Value of the notify to send.
399 *
400 * RETURN: None
401 *
402 * DESCRIPTION: Send an ACPI notification. The value specified is sent to the
403 * named object as an ACPI notify.
404 *
405 ******************************************************************************/
406
acpi_db_send_notify(char * name,u32 value)407 void acpi_db_send_notify(char *name, u32 value)
408 {
409 struct acpi_namespace_node *node;
410 acpi_status status;
411
412 /* Translate name to an Named object */
413
414 node = acpi_db_convert_to_node(name);
415 if (!node) {
416 return;
417 }
418
419 /* Dispatch the notify if legal */
420
421 if (acpi_ev_is_notify_object(node)) {
422 status = acpi_ev_queue_notify_request(node, value);
423 if (ACPI_FAILURE(status)) {
424 acpi_os_printf("Could not queue notify\n");
425 }
426 } else {
427 acpi_os_printf("Named object [%4.4s] Type %s, "
428 "must be Device/Thermal/Processor type\n",
429 acpi_ut_get_node_name(node),
430 acpi_ut_get_type_name(node->type));
431 }
432 }
433
434 /*******************************************************************************
435 *
436 * FUNCTION: acpi_db_display_interfaces
437 *
438 * PARAMETERS: action_arg - Null, "install", or "remove"
439 * interface_name_arg - Name for install/remove options
440 *
441 * RETURN: None
442 *
443 * DESCRIPTION: Display or modify the global _OSI interface list
444 *
445 ******************************************************************************/
446
acpi_db_display_interfaces(char * action_arg,char * interface_name_arg)447 void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg)
448 {
449 struct acpi_interface_info *next_interface;
450 char *sub_string;
451 acpi_status status;
452
453 /* If no arguments, just display current interface list */
454
455 if (!action_arg) {
456 (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex,
457 ACPI_WAIT_FOREVER);
458
459 next_interface = acpi_gbl_supported_interfaces;
460 while (next_interface) {
461 if (!(next_interface->flags & ACPI_OSI_INVALID)) {
462 acpi_os_printf("%s\n", next_interface->name);
463 }
464
465 next_interface = next_interface->next;
466 }
467
468 acpi_os_release_mutex(acpi_gbl_osi_mutex);
469 return;
470 }
471
472 /* If action_arg exists, so must interface_name_arg */
473
474 if (!interface_name_arg) {
475 acpi_os_printf("Missing Interface Name argument\n");
476 return;
477 }
478
479 /* Uppercase the action for match below */
480
481 acpi_ut_strupr(action_arg);
482
483 /* install - install an interface */
484
485 sub_string = strstr("INSTALL", action_arg);
486 if (sub_string) {
487 status = acpi_install_interface(interface_name_arg);
488 if (ACPI_FAILURE(status)) {
489 acpi_os_printf("%s, while installing \"%s\"\n",
490 acpi_format_exception(status),
491 interface_name_arg);
492 }
493 return;
494 }
495
496 /* remove - remove an interface */
497
498 sub_string = strstr("REMOVE", action_arg);
499 if (sub_string) {
500 status = acpi_remove_interface(interface_name_arg);
501 if (ACPI_FAILURE(status)) {
502 acpi_os_printf("%s, while removing \"%s\"\n",
503 acpi_format_exception(status),
504 interface_name_arg);
505 }
506 return;
507 }
508
509 /* Invalid action_arg */
510
511 acpi_os_printf("Invalid action argument: %s\n", action_arg);
512 return;
513 }
514
515 /*******************************************************************************
516 *
517 * FUNCTION: acpi_db_display_template
518 *
519 * PARAMETERS: buffer_arg - Buffer name or address
520 *
521 * RETURN: None
522 *
523 * DESCRIPTION: Dump a buffer that contains a resource template
524 *
525 ******************************************************************************/
526
acpi_db_display_template(char * buffer_arg)527 void acpi_db_display_template(char *buffer_arg)
528 {
529 struct acpi_namespace_node *node;
530 acpi_status status;
531 struct acpi_buffer return_buffer;
532
533 /* Translate buffer_arg to an Named object */
534
535 node = acpi_db_convert_to_node(buffer_arg);
536 if (!node || (node == acpi_gbl_root_node)) {
537 acpi_os_printf("Invalid argument: %s\n", buffer_arg);
538 return;
539 }
540
541 /* We must have a buffer object */
542
543 if (node->type != ACPI_TYPE_BUFFER) {
544 acpi_os_printf
545 ("Not a Buffer object, cannot be a template: %s\n",
546 buffer_arg);
547 return;
548 }
549
550 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
551 return_buffer.pointer = acpi_gbl_db_buffer;
552
553 /* Attempt to convert the raw buffer to a resource list */
554
555 status = acpi_rs_create_resource_list(node->object, &return_buffer);
556
557 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
558 acpi_dbg_level |= ACPI_LV_RESOURCES;
559
560 if (ACPI_FAILURE(status)) {
561 acpi_os_printf
562 ("Could not convert Buffer to a resource list: %s, %s\n",
563 buffer_arg, acpi_format_exception(status));
564 goto dump_buffer;
565 }
566
567 /* Now we can dump the resource list */
568
569 acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource,
570 return_buffer.pointer));
571
572 dump_buffer:
573 acpi_os_printf("\nRaw data buffer:\n");
574 acpi_ut_debug_dump_buffer((u8 *)node->object->buffer.pointer,
575 node->object->buffer.length,
576 DB_BYTE_DISPLAY, ACPI_UINT32_MAX);
577
578 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
579 return;
580 }
581
582 /*******************************************************************************
583 *
584 * FUNCTION: acpi_dm_compare_aml_resources
585 *
586 * PARAMETERS: aml1_buffer - Contains first resource list
587 * aml1_buffer_length - Length of first resource list
588 * aml2_buffer - Contains second resource list
589 * aml2_buffer_length - Length of second resource list
590 *
591 * RETURN: None
592 *
593 * DESCRIPTION: Compare two AML resource lists, descriptor by descriptor (in
594 * order to isolate a miscompare to an individual resource)
595 *
596 ******************************************************************************/
597
598 static void
acpi_dm_compare_aml_resources(u8 * aml1_buffer,acpi_rsdesc_size aml1_buffer_length,u8 * aml2_buffer,acpi_rsdesc_size aml2_buffer_length)599 acpi_dm_compare_aml_resources(u8 *aml1_buffer,
600 acpi_rsdesc_size aml1_buffer_length,
601 u8 *aml2_buffer,
602 acpi_rsdesc_size aml2_buffer_length)
603 {
604 u8 *aml1;
605 u8 *aml2;
606 u8 *aml1_end;
607 u8 *aml2_end;
608 acpi_rsdesc_size aml1_length;
609 acpi_rsdesc_size aml2_length;
610 acpi_rsdesc_size offset = 0;
611 u8 resource_type;
612 u32 count = 0;
613 u32 i;
614
615 /* Compare overall buffer sizes (may be different due to size rounding) */
616
617 if (aml1_buffer_length != aml2_buffer_length) {
618 acpi_os_printf("**** Buffer length mismatch in converted "
619 "AML: Original %X, New %X ****\n",
620 aml1_buffer_length, aml2_buffer_length);
621 }
622
623 aml1 = aml1_buffer;
624 aml2 = aml2_buffer;
625 aml1_end = aml1_buffer + aml1_buffer_length;
626 aml2_end = aml2_buffer + aml2_buffer_length;
627
628 /* Walk the descriptor lists, comparing each descriptor */
629
630 while ((aml1 < aml1_end) && (aml2 < aml2_end)) {
631
632 /* Get the lengths of each descriptor */
633
634 aml1_length = acpi_ut_get_descriptor_length(aml1);
635 aml2_length = acpi_ut_get_descriptor_length(aml2);
636 resource_type = acpi_ut_get_resource_type(aml1);
637
638 /* Check for descriptor length match */
639
640 if (aml1_length != aml2_length) {
641 acpi_os_printf
642 ("**** Length mismatch in descriptor [%.2X] type %2.2X, "
643 "Offset %8.8X Len1 %X, Len2 %X ****\n", count,
644 resource_type, offset, aml1_length, aml2_length);
645 }
646
647 /* Check for descriptor byte match */
648
649 else if (memcmp(aml1, aml2, aml1_length)) {
650 acpi_os_printf
651 ("**** Data mismatch in descriptor [%.2X] type %2.2X, "
652 "Offset %8.8X ****\n", count, resource_type,
653 offset);
654
655 for (i = 0; i < aml1_length; i++) {
656 if (aml1[i] != aml2[i]) {
657 acpi_os_printf
658 ("Mismatch at byte offset %.2X: is %2.2X, "
659 "should be %2.2X\n", i, aml2[i],
660 aml1[i]);
661 }
662 }
663 }
664
665 /* Exit on end_tag descriptor */
666
667 if (resource_type == ACPI_RESOURCE_NAME_END_TAG) {
668 return;
669 }
670
671 /* Point to next descriptor in each buffer */
672
673 count++;
674 offset += aml1_length;
675 aml1 += aml1_length;
676 aml2 += aml2_length;
677 }
678 }
679
680 /*******************************************************************************
681 *
682 * FUNCTION: acpi_dm_test_resource_conversion
683 *
684 * PARAMETERS: node - Parent device node
685 * name - resource method name (_CRS)
686 *
687 * RETURN: Status
688 *
689 * DESCRIPTION: Compare the original AML with a conversion of the AML to
690 * internal resource list, then back to AML.
691 *
692 ******************************************************************************/
693
694 static acpi_status
acpi_dm_test_resource_conversion(struct acpi_namespace_node * node,char * name)695 acpi_dm_test_resource_conversion(struct acpi_namespace_node *node, char *name)
696 {
697 acpi_status status;
698 struct acpi_buffer return_buffer;
699 struct acpi_buffer resource_buffer;
700 struct acpi_buffer new_aml;
701 union acpi_object *original_aml;
702
703 acpi_os_printf("Resource Conversion Comparison:\n");
704
705 new_aml.length = ACPI_ALLOCATE_LOCAL_BUFFER;
706 return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
707 resource_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
708
709 /* Get the original _CRS AML resource template */
710
711 status = acpi_evaluate_object(node, name, NULL, &return_buffer);
712 if (ACPI_FAILURE(status)) {
713 acpi_os_printf("Could not obtain %s: %s\n",
714 name, acpi_format_exception(status));
715 return (status);
716 }
717
718 /* Get the AML resource template, converted to internal resource structs */
719
720 status = acpi_get_current_resources(node, &resource_buffer);
721 if (ACPI_FAILURE(status)) {
722 acpi_os_printf("AcpiGetCurrentResources failed: %s\n",
723 acpi_format_exception(status));
724 goto exit1;
725 }
726
727 /* Convert internal resource list to external AML resource template */
728
729 status = acpi_rs_create_aml_resources(&resource_buffer, &new_aml);
730 if (ACPI_FAILURE(status)) {
731 acpi_os_printf("AcpiRsCreateAmlResources failed: %s\n",
732 acpi_format_exception(status));
733 goto exit2;
734 }
735
736 /* Compare original AML to the newly created AML resource list */
737
738 original_aml = return_buffer.pointer;
739
740 acpi_dm_compare_aml_resources(original_aml->buffer.pointer,
741 (acpi_rsdesc_size)original_aml->buffer.
742 length, new_aml.pointer,
743 (acpi_rsdesc_size)new_aml.length);
744
745 /* Cleanup and exit */
746
747 ACPI_FREE(new_aml.pointer);
748 exit2:
749 ACPI_FREE(resource_buffer.pointer);
750 exit1:
751 ACPI_FREE(return_buffer.pointer);
752 return (status);
753 }
754
755 /*******************************************************************************
756 *
757 * FUNCTION: acpi_db_resource_callback
758 *
759 * PARAMETERS: acpi_walk_resource_callback
760 *
761 * RETURN: Status
762 *
763 * DESCRIPTION: Simple callback to exercise acpi_walk_resources and
764 * acpi_walk_resource_buffer.
765 *
766 ******************************************************************************/
767
768 static acpi_status
acpi_db_resource_callback(struct acpi_resource * resource,void * context)769 acpi_db_resource_callback(struct acpi_resource *resource, void *context)
770 {
771
772 return (AE_OK);
773 }
774
775 /*******************************************************************************
776 *
777 * FUNCTION: acpi_db_device_resources
778 *
779 * PARAMETERS: acpi_walk_callback
780 *
781 * RETURN: Status
782 *
783 * DESCRIPTION: Display the _PRT/_CRS/_PRS resources for a device object.
784 *
785 ******************************************************************************/
786
787 static acpi_status
acpi_db_device_resources(acpi_handle obj_handle,u32 nesting_level,void * context,void ** return_value)788 acpi_db_device_resources(acpi_handle obj_handle,
789 u32 nesting_level, void *context, void **return_value)
790 {
791 struct acpi_namespace_node *node;
792 struct acpi_namespace_node *prt_node = NULL;
793 struct acpi_namespace_node *crs_node = NULL;
794 struct acpi_namespace_node *prs_node = NULL;
795 struct acpi_namespace_node *aei_node = NULL;
796 char *parent_path;
797 struct acpi_buffer return_buffer;
798 acpi_status status;
799
800 node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
801 parent_path = acpi_ns_get_normalized_pathname(node, TRUE);
802 if (!parent_path) {
803 return (AE_NO_MEMORY);
804 }
805
806 /* Get handles to the resource methods for this device */
807
808 (void)acpi_get_handle(node, METHOD_NAME__PRT,
809 ACPI_CAST_PTR(acpi_handle, &prt_node));
810 (void)acpi_get_handle(node, METHOD_NAME__CRS,
811 ACPI_CAST_PTR(acpi_handle, &crs_node));
812 (void)acpi_get_handle(node, METHOD_NAME__PRS,
813 ACPI_CAST_PTR(acpi_handle, &prs_node));
814 (void)acpi_get_handle(node, METHOD_NAME__AEI,
815 ACPI_CAST_PTR(acpi_handle, &aei_node));
816
817 if (!prt_node && !crs_node && !prs_node && !aei_node) {
818 goto cleanup; /* Nothing to do */
819 }
820
821 acpi_os_printf("\nDevice: %s\n", parent_path);
822
823 /* Prepare for a return object of arbitrary size */
824
825 return_buffer.pointer = acpi_gbl_db_buffer;
826 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
827
828 /* _PRT */
829
830 if (prt_node) {
831 acpi_os_printf("Evaluating _PRT\n");
832
833 status =
834 acpi_evaluate_object(prt_node, NULL, NULL, &return_buffer);
835 if (ACPI_FAILURE(status)) {
836 acpi_os_printf("Could not evaluate _PRT: %s\n",
837 acpi_format_exception(status));
838 goto get_crs;
839 }
840
841 return_buffer.pointer = acpi_gbl_db_buffer;
842 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
843
844 status = acpi_get_irq_routing_table(node, &return_buffer);
845 if (ACPI_FAILURE(status)) {
846 acpi_os_printf("GetIrqRoutingTable failed: %s\n",
847 acpi_format_exception(status));
848 goto get_crs;
849 }
850
851 acpi_rs_dump_irq_list(ACPI_CAST_PTR(u8, acpi_gbl_db_buffer));
852 }
853
854 /* _CRS */
855
856 get_crs:
857 if (crs_node) {
858 acpi_os_printf("Evaluating _CRS\n");
859
860 return_buffer.pointer = acpi_gbl_db_buffer;
861 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
862
863 status =
864 acpi_evaluate_object(crs_node, NULL, NULL, &return_buffer);
865 if (ACPI_FAILURE(status)) {
866 acpi_os_printf("Could not evaluate _CRS: %s\n",
867 acpi_format_exception(status));
868 goto get_prs;
869 }
870
871 /* This code exercises the acpi_walk_resources interface */
872
873 status = acpi_walk_resources(node, METHOD_NAME__CRS,
874 acpi_db_resource_callback, NULL);
875 if (ACPI_FAILURE(status)) {
876 acpi_os_printf("AcpiWalkResources failed: %s\n",
877 acpi_format_exception(status));
878 goto get_prs;
879 }
880
881 /* Get the _CRS resource list (test ALLOCATE buffer) */
882
883 return_buffer.pointer = NULL;
884 return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
885
886 status = acpi_get_current_resources(node, &return_buffer);
887 if (ACPI_FAILURE(status)) {
888 acpi_os_printf("AcpiGetCurrentResources failed: %s\n",
889 acpi_format_exception(status));
890 goto get_prs;
891 }
892
893 /* This code exercises the acpi_walk_resource_buffer interface */
894
895 status = acpi_walk_resource_buffer(&return_buffer,
896 acpi_db_resource_callback,
897 NULL);
898 if (ACPI_FAILURE(status)) {
899 acpi_os_printf("AcpiWalkResourceBuffer failed: %s\n",
900 acpi_format_exception(status));
901 goto end_crs;
902 }
903
904 /* Dump the _CRS resource list */
905
906 acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource,
907 return_buffer.
908 pointer));
909
910 /*
911 * Perform comparison of original AML to newly created AML. This
912 * tests both the AML->Resource conversion and the Resource->AML
913 * conversion.
914 */
915 (void)acpi_dm_test_resource_conversion(node, METHOD_NAME__CRS);
916
917 /* Execute _SRS with the resource list */
918
919 acpi_os_printf("Evaluating _SRS\n");
920
921 status = acpi_set_current_resources(node, &return_buffer);
922 if (ACPI_FAILURE(status)) {
923 acpi_os_printf("AcpiSetCurrentResources failed: %s\n",
924 acpi_format_exception(status));
925 goto end_crs;
926 }
927
928 end_crs:
929 ACPI_FREE(return_buffer.pointer);
930 }
931
932 /* _PRS */
933
934 get_prs:
935 if (prs_node) {
936 acpi_os_printf("Evaluating _PRS\n");
937
938 return_buffer.pointer = acpi_gbl_db_buffer;
939 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
940
941 status =
942 acpi_evaluate_object(prs_node, NULL, NULL, &return_buffer);
943 if (ACPI_FAILURE(status)) {
944 acpi_os_printf("Could not evaluate _PRS: %s\n",
945 acpi_format_exception(status));
946 goto get_aei;
947 }
948
949 return_buffer.pointer = acpi_gbl_db_buffer;
950 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
951
952 status = acpi_get_possible_resources(node, &return_buffer);
953 if (ACPI_FAILURE(status)) {
954 acpi_os_printf("AcpiGetPossibleResources failed: %s\n",
955 acpi_format_exception(status));
956 goto get_aei;
957 }
958
959 acpi_rs_dump_resource_list(ACPI_CAST_PTR
960 (struct acpi_resource,
961 acpi_gbl_db_buffer));
962 }
963
964 /* _AEI */
965
966 get_aei:
967 if (aei_node) {
968 acpi_os_printf("Evaluating _AEI\n");
969
970 return_buffer.pointer = acpi_gbl_db_buffer;
971 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
972
973 status =
974 acpi_evaluate_object(aei_node, NULL, NULL, &return_buffer);
975 if (ACPI_FAILURE(status)) {
976 acpi_os_printf("Could not evaluate _AEI: %s\n",
977 acpi_format_exception(status));
978 goto cleanup;
979 }
980
981 return_buffer.pointer = acpi_gbl_db_buffer;
982 return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;
983
984 status = acpi_get_event_resources(node, &return_buffer);
985 if (ACPI_FAILURE(status)) {
986 acpi_os_printf("AcpiGetEventResources failed: %s\n",
987 acpi_format_exception(status));
988 goto cleanup;
989 }
990
991 acpi_rs_dump_resource_list(ACPI_CAST_PTR
992 (struct acpi_resource,
993 acpi_gbl_db_buffer));
994 }
995
996 cleanup:
997 ACPI_FREE(parent_path);
998 return (AE_OK);
999 }
1000
1001 /*******************************************************************************
1002 *
1003 * FUNCTION: acpi_db_display_resources
1004 *
1005 * PARAMETERS: object_arg - String object name or object pointer.
1006 * NULL or "*" means "display resources for
1007 * all devices"
1008 *
1009 * RETURN: None
1010 *
1011 * DESCRIPTION: Display the resource objects associated with a device.
1012 *
1013 ******************************************************************************/
1014
acpi_db_display_resources(char * object_arg)1015 void acpi_db_display_resources(char *object_arg)
1016 {
1017 struct acpi_namespace_node *node;
1018
1019 acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
1020 acpi_dbg_level |= ACPI_LV_RESOURCES;
1021
1022 /* Asterisk means "display resources for all devices" */
1023
1024 if (!object_arg || (!strcmp(object_arg, "*"))) {
1025 (void)acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1026 ACPI_UINT32_MAX,
1027 acpi_db_device_resources, NULL, NULL,
1028 NULL);
1029 } else {
1030 /* Convert string to object pointer */
1031
1032 node = acpi_db_convert_to_node(object_arg);
1033 if (node) {
1034 if (node->type != ACPI_TYPE_DEVICE) {
1035 acpi_os_printf
1036 ("%4.4s: Name is not a device object (%s)\n",
1037 node->name.ascii,
1038 acpi_ut_get_type_name(node->type));
1039 } else {
1040 (void)acpi_db_device_resources(node, 0, NULL,
1041 NULL);
1042 }
1043 }
1044 }
1045
1046 acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
1047 }
1048
1049 #if (!ACPI_REDUCED_HARDWARE)
1050 /*******************************************************************************
1051 *
1052 * FUNCTION: acpi_db_generate_gpe
1053 *
1054 * PARAMETERS: gpe_arg - Raw GPE number, ascii string
1055 * block_arg - GPE block number, ascii string
1056 * 0 or 1 for FADT GPE blocks
1057 *
1058 * RETURN: None
1059 *
1060 * DESCRIPTION: Simulate firing of a GPE
1061 *
1062 ******************************************************************************/
1063
acpi_db_generate_gpe(char * gpe_arg,char * block_arg)1064 void acpi_db_generate_gpe(char *gpe_arg, char *block_arg)
1065 {
1066 u32 block_number = 0;
1067 u32 gpe_number;
1068 struct acpi_gpe_event_info *gpe_event_info;
1069
1070 gpe_number = strtoul(gpe_arg, NULL, 0);
1071
1072 /*
1073 * If no block arg, or block arg == 0 or 1, use the FADT-defined
1074 * GPE blocks.
1075 */
1076 if (block_arg) {
1077 block_number = strtoul(block_arg, NULL, 0);
1078 if (block_number == 1) {
1079 block_number = 0;
1080 }
1081 }
1082
1083 gpe_event_info =
1084 acpi_ev_get_gpe_event_info(ACPI_TO_POINTER(block_number),
1085 gpe_number);
1086 if (!gpe_event_info) {
1087 acpi_os_printf("Invalid GPE\n");
1088 return;
1089 }
1090
1091 (void)acpi_ev_gpe_dispatch(NULL, gpe_event_info, gpe_number);
1092 }
1093
1094 /*******************************************************************************
1095 *
1096 * FUNCTION: acpi_db_generate_sci
1097 *
1098 * PARAMETERS: None
1099 *
1100 * RETURN: None
1101 *
1102 * DESCRIPTION: Simulate an SCI -- just call the SCI dispatch.
1103 *
1104 ******************************************************************************/
1105
acpi_db_generate_sci(void)1106 void acpi_db_generate_sci(void)
1107 {
1108 acpi_ev_sci_dispatch();
1109 }
1110
1111 #endif /* !ACPI_REDUCED_HARDWARE */
1112
1113 /*******************************************************************************
1114 *
1115 * FUNCTION: acpi_db_trace
1116 *
1117 * PARAMETERS: enable_arg - ENABLE/AML to enable tracer
1118 * DISABLE to disable tracer
1119 * method_arg - Method to trace
1120 * once_arg - Whether trace once
1121 *
1122 * RETURN: None
1123 *
1124 * DESCRIPTION: Control method tracing facility
1125 *
1126 ******************************************************************************/
1127
acpi_db_trace(char * enable_arg,char * method_arg,char * once_arg)1128 void acpi_db_trace(char *enable_arg, char *method_arg, char *once_arg)
1129 {
1130 u32 debug_level = 0;
1131 u32 debug_layer = 0;
1132 u32 flags = 0;
1133
1134 acpi_ut_strupr(enable_arg);
1135 acpi_ut_strupr(once_arg);
1136
1137 if (method_arg) {
1138 if (acpi_db_trace_method_name) {
1139 ACPI_FREE(acpi_db_trace_method_name);
1140 acpi_db_trace_method_name = NULL;
1141 }
1142
1143 acpi_db_trace_method_name =
1144 ACPI_ALLOCATE(strlen(method_arg) + 1);
1145 if (!acpi_db_trace_method_name) {
1146 acpi_os_printf("Failed to allocate method name (%s)\n",
1147 method_arg);
1148 return;
1149 }
1150
1151 strcpy(acpi_db_trace_method_name, method_arg);
1152 }
1153
1154 if (!strcmp(enable_arg, "ENABLE") ||
1155 !strcmp(enable_arg, "METHOD") || !strcmp(enable_arg, "OPCODE")) {
1156 if (!strcmp(enable_arg, "ENABLE")) {
1157
1158 /* Inherit current console settings */
1159
1160 debug_level = acpi_gbl_db_console_debug_level;
1161 debug_layer = acpi_dbg_layer;
1162 } else {
1163 /* Restrict console output to trace points only */
1164
1165 debug_level = ACPI_LV_TRACE_POINT;
1166 debug_layer = ACPI_EXECUTER;
1167 }
1168
1169 flags = ACPI_TRACE_ENABLED;
1170
1171 if (!strcmp(enable_arg, "OPCODE")) {
1172 flags |= ACPI_TRACE_OPCODE;
1173 }
1174
1175 if (once_arg && !strcmp(once_arg, "ONCE")) {
1176 flags |= ACPI_TRACE_ONESHOT;
1177 }
1178 }
1179
1180 (void)acpi_debug_trace(acpi_db_trace_method_name,
1181 debug_level, debug_layer, flags);
1182 }
1183