• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
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