xref: /openbmc/linux/drivers/acpi/acpica/dbcmds.c (revision 4da722ca)
1 /*******************************************************************************
2  *
3  * Module Name: dbcmds - Miscellaneous debug commands and output routines
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2017, 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 
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 
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 
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 
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 
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 
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 
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 
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 
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
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
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
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
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 
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 
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 
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 
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