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