xref: /openbmc/linux/drivers/acpi/acpica/dbnames.c (revision 9cfc5c90)
1 /*******************************************************************************
2  *
3  * Module Name: dbnames - Debugger commands for the acpi namespace
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, 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 "acnamesp.h"
47 #include "acdebug.h"
48 #include "acpredef.h"
49 
50 #define _COMPONENT          ACPI_CA_DEBUGGER
51 ACPI_MODULE_NAME("dbnames")
52 
53 /* Local prototypes */
54 static acpi_status
55 acpi_db_walk_and_match_name(acpi_handle obj_handle,
56 			    u32 nesting_level,
57 			    void *context, void **return_value);
58 
59 static acpi_status
60 acpi_db_walk_for_predefined_names(acpi_handle obj_handle,
61 				  u32 nesting_level,
62 				  void *context, void **return_value);
63 
64 static acpi_status
65 acpi_db_walk_for_specific_objects(acpi_handle obj_handle,
66 				  u32 nesting_level,
67 				  void *context, void **return_value);
68 
69 static acpi_status
70 acpi_db_walk_for_object_counts(acpi_handle obj_handle,
71 			       u32 nesting_level,
72 			       void *context, void **return_value);
73 
74 static acpi_status
75 acpi_db_integrity_walk(acpi_handle obj_handle,
76 		       u32 nesting_level, void *context, void **return_value);
77 
78 static acpi_status
79 acpi_db_walk_for_references(acpi_handle obj_handle,
80 			    u32 nesting_level,
81 			    void *context, void **return_value);
82 
83 static acpi_status
84 acpi_db_bus_walk(acpi_handle obj_handle,
85 		 u32 nesting_level, void *context, void **return_value);
86 
87 /*
88  * Arguments for the Objects command
89  * These object types map directly to the ACPI_TYPES
90  */
91 static struct acpi_db_argument_info acpi_db_object_types[] = {
92 	{"ANY"},
93 	{"INTEGERS"},
94 	{"STRINGS"},
95 	{"BUFFERS"},
96 	{"PACKAGES"},
97 	{"FIELDS"},
98 	{"DEVICES"},
99 	{"EVENTS"},
100 	{"METHODS"},
101 	{"MUTEXES"},
102 	{"REGIONS"},
103 	{"POWERRESOURCES"},
104 	{"PROCESSORS"},
105 	{"THERMALZONES"},
106 	{"BUFFERFIELDS"},
107 	{"DDBHANDLES"},
108 	{"DEBUG"},
109 	{"REGIONFIELDS"},
110 	{"BANKFIELDS"},
111 	{"INDEXFIELDS"},
112 	{"REFERENCES"},
113 	{"ALIASES"},
114 	{"METHODALIASES"},
115 	{"NOTIFY"},
116 	{"ADDRESSHANDLER"},
117 	{"RESOURCE"},
118 	{"RESOURCEFIELD"},
119 	{"SCOPES"},
120 	{NULL}			/* Must be null terminated */
121 };
122 
123 /*******************************************************************************
124  *
125  * FUNCTION:    acpi_db_set_scope
126  *
127  * PARAMETERS:  name                - New scope path
128  *
129  * RETURN:      Status
130  *
131  * DESCRIPTION: Set the "current scope" as maintained by this utility.
132  *              The scope is used as a prefix to ACPI paths.
133  *
134  ******************************************************************************/
135 
136 void acpi_db_set_scope(char *name)
137 {
138 	acpi_status status;
139 	struct acpi_namespace_node *node;
140 
141 	if (!name || name[0] == 0) {
142 		acpi_os_printf("Current scope: %s\n", acpi_gbl_db_scope_buf);
143 		return;
144 	}
145 
146 	acpi_db_prep_namestring(name);
147 
148 	if (ACPI_IS_ROOT_PREFIX(name[0])) {
149 
150 		/* Validate new scope from the root */
151 
152 		status = acpi_ns_get_node(acpi_gbl_root_node, name,
153 					  ACPI_NS_NO_UPSEARCH, &node);
154 		if (ACPI_FAILURE(status)) {
155 			goto error_exit;
156 		}
157 
158 		acpi_gbl_db_scope_buf[0] = 0;
159 	} else {
160 		/* Validate new scope relative to old scope */
161 
162 		status = acpi_ns_get_node(acpi_gbl_db_scope_node, name,
163 					  ACPI_NS_NO_UPSEARCH, &node);
164 		if (ACPI_FAILURE(status)) {
165 			goto error_exit;
166 		}
167 	}
168 
169 	/* Build the final pathname */
170 
171 	if (acpi_ut_safe_strcat
172 	    (acpi_gbl_db_scope_buf, sizeof(acpi_gbl_db_scope_buf), name)) {
173 		status = AE_BUFFER_OVERFLOW;
174 		goto error_exit;
175 	}
176 
177 	if (acpi_ut_safe_strcat
178 	    (acpi_gbl_db_scope_buf, sizeof(acpi_gbl_db_scope_buf), "\\")) {
179 		status = AE_BUFFER_OVERFLOW;
180 		goto error_exit;
181 	}
182 
183 	acpi_gbl_db_scope_node = node;
184 	acpi_os_printf("New scope: %s\n", acpi_gbl_db_scope_buf);
185 	return;
186 
187 error_exit:
188 
189 	acpi_os_printf("Could not attach scope: %s, %s\n",
190 		       name, acpi_format_exception(status));
191 }
192 
193 /*******************************************************************************
194  *
195  * FUNCTION:    acpi_db_dump_namespace
196  *
197  * PARAMETERS:  start_arg       - Node to begin namespace dump
198  *              depth_arg       - Maximum tree depth to be dumped
199  *
200  * RETURN:      None
201  *
202  * DESCRIPTION: Dump entire namespace or a subtree. Each node is displayed
203  *              with type and other information.
204  *
205  ******************************************************************************/
206 
207 void acpi_db_dump_namespace(char *start_arg, char *depth_arg)
208 {
209 	acpi_handle subtree_entry = acpi_gbl_root_node;
210 	u32 max_depth = ACPI_UINT32_MAX;
211 
212 	/* No argument given, just start at the root and dump entire namespace */
213 
214 	if (start_arg) {
215 		subtree_entry = acpi_db_convert_to_node(start_arg);
216 		if (!subtree_entry) {
217 			return;
218 		}
219 
220 		/* Now we can check for the depth argument */
221 
222 		if (depth_arg) {
223 			max_depth = strtoul(depth_arg, NULL, 0);
224 		}
225 	}
226 
227 	acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
228 	acpi_os_printf("ACPI Namespace (from %4.4s (%p) subtree):\n",
229 		       ((struct acpi_namespace_node *)subtree_entry)->name.
230 		       ascii, subtree_entry);
231 
232 	/* Display the subtree */
233 
234 	acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
235 	acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth,
236 			     ACPI_OWNER_ID_MAX, subtree_entry);
237 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
238 }
239 
240 /*******************************************************************************
241  *
242  * FUNCTION:    acpi_db_dump_namespace_paths
243  *
244  * PARAMETERS:  None
245  *
246  * RETURN:      None
247  *
248  * DESCRIPTION: Dump entire namespace with full object pathnames and object
249  *              type information. Alternative to "namespace" command.
250  *
251  ******************************************************************************/
252 
253 void acpi_db_dump_namespace_paths(void)
254 {
255 
256 	acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
257 	acpi_os_printf("ACPI Namespace (from root):\n");
258 
259 	/* Display the entire namespace */
260 
261 	acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
262 	acpi_ns_dump_object_paths(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY,
263 				  ACPI_UINT32_MAX, ACPI_OWNER_ID_MAX,
264 				  acpi_gbl_root_node);
265 
266 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
267 }
268 
269 /*******************************************************************************
270  *
271  * FUNCTION:    acpi_db_dump_namespace_by_owner
272  *
273  * PARAMETERS:  owner_arg       - Owner ID whose nodes will be displayed
274  *              depth_arg       - Maximum tree depth to be dumped
275  *
276  * RETURN:      None
277  *
278  * DESCRIPTION: Dump elements of the namespace that are owned by the owner_id.
279  *
280  ******************************************************************************/
281 
282 void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg)
283 {
284 	acpi_handle subtree_entry = acpi_gbl_root_node;
285 	u32 max_depth = ACPI_UINT32_MAX;
286 	acpi_owner_id owner_id;
287 
288 	owner_id = (acpi_owner_id) strtoul(owner_arg, NULL, 0);
289 
290 	/* Now we can check for the depth argument */
291 
292 	if (depth_arg) {
293 		max_depth = strtoul(depth_arg, NULL, 0);
294 	}
295 
296 	acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
297 	acpi_os_printf("ACPI Namespace by owner %X:\n", owner_id);
298 
299 	/* Display the subtree */
300 
301 	acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
302 	acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth,
303 			     owner_id, subtree_entry);
304 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
305 }
306 
307 /*******************************************************************************
308  *
309  * FUNCTION:    acpi_db_walk_and_match_name
310  *
311  * PARAMETERS:  Callback from walk_namespace
312  *
313  * RETURN:      Status
314  *
315  * DESCRIPTION: Find a particular name/names within the namespace. Wildcards
316  *              are supported -- '?' matches any character.
317  *
318  ******************************************************************************/
319 
320 static acpi_status
321 acpi_db_walk_and_match_name(acpi_handle obj_handle,
322 			    u32 nesting_level,
323 			    void *context, void **return_value)
324 {
325 	acpi_status status;
326 	char *requested_name = (char *)context;
327 	u32 i;
328 	struct acpi_buffer buffer;
329 	struct acpi_walk_info info;
330 
331 	/* Check for a name match */
332 
333 	for (i = 0; i < 4; i++) {
334 
335 		/* Wildcard support */
336 
337 		if ((requested_name[i] != '?') &&
338 		    (requested_name[i] != ((struct acpi_namespace_node *)
339 					   obj_handle)->name.ascii[i])) {
340 
341 			/* No match, just exit */
342 
343 			return (AE_OK);
344 		}
345 	}
346 
347 	/* Get the full pathname to this object */
348 
349 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
350 	status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
351 	if (ACPI_FAILURE(status)) {
352 		acpi_os_printf("Could Not get pathname for object %p\n",
353 			       obj_handle);
354 	} else {
355 		info.owner_id = ACPI_OWNER_ID_MAX;
356 		info.debug_level = ACPI_UINT32_MAX;
357 		info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
358 
359 		acpi_os_printf("%32s", (char *)buffer.pointer);
360 		(void)acpi_ns_dump_one_object(obj_handle, nesting_level, &info,
361 					      NULL);
362 		ACPI_FREE(buffer.pointer);
363 	}
364 
365 	return (AE_OK);
366 }
367 
368 /*******************************************************************************
369  *
370  * FUNCTION:    acpi_db_find_name_in_namespace
371  *
372  * PARAMETERS:  name_arg        - The 4-character ACPI name to find.
373  *                                wildcards are supported.
374  *
375  * RETURN:      None
376  *
377  * DESCRIPTION: Search the namespace for a given name (with wildcards)
378  *
379  ******************************************************************************/
380 
381 acpi_status acpi_db_find_name_in_namespace(char *name_arg)
382 {
383 	char acpi_name[5] = "____";
384 	char *acpi_name_ptr = acpi_name;
385 
386 	if (strlen(name_arg) > ACPI_NAME_SIZE) {
387 		acpi_os_printf("Name must be no longer than 4 characters\n");
388 		return (AE_OK);
389 	}
390 
391 	/* Pad out name with underscores as necessary to create a 4-char name */
392 
393 	acpi_ut_strupr(name_arg);
394 	while (*name_arg) {
395 		*acpi_name_ptr = *name_arg;
396 		acpi_name_ptr++;
397 		name_arg++;
398 	}
399 
400 	/* Walk the namespace from the root */
401 
402 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
403 				  ACPI_UINT32_MAX, acpi_db_walk_and_match_name,
404 				  NULL, acpi_name, NULL);
405 
406 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
407 	return (AE_OK);
408 }
409 
410 /*******************************************************************************
411  *
412  * FUNCTION:    acpi_db_walk_for_predefined_names
413  *
414  * PARAMETERS:  Callback from walk_namespace
415  *
416  * RETURN:      Status
417  *
418  * DESCRIPTION: Detect and display predefined ACPI names (names that start with
419  *              an underscore)
420  *
421  ******************************************************************************/
422 
423 static acpi_status
424 acpi_db_walk_for_predefined_names(acpi_handle obj_handle,
425 				  u32 nesting_level,
426 				  void *context, void **return_value)
427 {
428 	struct acpi_namespace_node *node =
429 	    (struct acpi_namespace_node *)obj_handle;
430 	u32 *count = (u32 *)context;
431 	const union acpi_predefined_info *predefined;
432 	const union acpi_predefined_info *package = NULL;
433 	char *pathname;
434 	char string_buffer[48];
435 
436 	predefined = acpi_ut_match_predefined_method(node->name.ascii);
437 	if (!predefined) {
438 		return (AE_OK);
439 	}
440 
441 	pathname = acpi_ns_get_external_pathname(node);
442 	if (!pathname) {
443 		return (AE_OK);
444 	}
445 
446 	/* If method returns a package, the info is in the next table entry */
447 
448 	if (predefined->info.expected_btypes & ACPI_RTYPE_PACKAGE) {
449 		package = predefined + 1;
450 	}
451 
452 	acpi_ut_get_expected_return_types(string_buffer,
453 					  predefined->info.expected_btypes);
454 
455 	acpi_os_printf("%-32s Arguments %X, Return Types: %s", pathname,
456 		       METHOD_GET_ARG_COUNT(predefined->info.argument_list),
457 		       string_buffer);
458 
459 	if (package) {
460 		acpi_os_printf(" (PkgType %2.2X, ObjType %2.2X, Count %2.2X)",
461 			       package->ret_info.type,
462 			       package->ret_info.object_type1,
463 			       package->ret_info.count1);
464 	}
465 
466 	acpi_os_printf("\n");
467 
468 	/* Check that the declared argument count matches the ACPI spec */
469 
470 	acpi_ns_check_acpi_compliance(pathname, node, predefined);
471 
472 	ACPI_FREE(pathname);
473 	(*count)++;
474 	return (AE_OK);
475 }
476 
477 /*******************************************************************************
478  *
479  * FUNCTION:    acpi_db_check_predefined_names
480  *
481  * PARAMETERS:  None
482  *
483  * RETURN:      None
484  *
485  * DESCRIPTION: Validate all predefined names in the namespace
486  *
487  ******************************************************************************/
488 
489 void acpi_db_check_predefined_names(void)
490 {
491 	u32 count = 0;
492 
493 	/* Search all nodes in namespace */
494 
495 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
496 				  ACPI_UINT32_MAX,
497 				  acpi_db_walk_for_predefined_names, NULL,
498 				  (void *)&count, NULL);
499 
500 	acpi_os_printf("Found %u predefined names in the namespace\n", count);
501 }
502 
503 /*******************************************************************************
504  *
505  * FUNCTION:    acpi_db_walk_for_object_counts
506  *
507  * PARAMETERS:  Callback from walk_namespace
508  *
509  * RETURN:      Status
510  *
511  * DESCRIPTION: Display short info about objects in the namespace
512  *
513  ******************************************************************************/
514 
515 static acpi_status
516 acpi_db_walk_for_object_counts(acpi_handle obj_handle,
517 			       u32 nesting_level,
518 			       void *context, void **return_value)
519 {
520 	struct acpi_object_info *info = (struct acpi_object_info *)context;
521 	struct acpi_namespace_node *node =
522 	    (struct acpi_namespace_node *)obj_handle;
523 
524 	if (node->type > ACPI_TYPE_NS_NODE_MAX) {
525 		acpi_os_printf("[%4.4s]: Unknown object type %X\n",
526 			       node->name.ascii, node->type);
527 	} else {
528 		info->types[node->type]++;
529 	}
530 
531 	return (AE_OK);
532 }
533 
534 /*******************************************************************************
535  *
536  * FUNCTION:    acpi_db_walk_for_specific_objects
537  *
538  * PARAMETERS:  Callback from walk_namespace
539  *
540  * RETURN:      Status
541  *
542  * DESCRIPTION: Display short info about objects in the namespace
543  *
544  ******************************************************************************/
545 
546 static acpi_status
547 acpi_db_walk_for_specific_objects(acpi_handle obj_handle,
548 				  u32 nesting_level,
549 				  void *context, void **return_value)
550 {
551 	struct acpi_walk_info *info = (struct acpi_walk_info *)context;
552 	struct acpi_buffer buffer;
553 	acpi_status status;
554 
555 	info->count++;
556 
557 	/* Get and display the full pathname to this object */
558 
559 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
560 	status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
561 	if (ACPI_FAILURE(status)) {
562 		acpi_os_printf("Could Not get pathname for object %p\n",
563 			       obj_handle);
564 		return (AE_OK);
565 	}
566 
567 	acpi_os_printf("%32s", (char *)buffer.pointer);
568 	ACPI_FREE(buffer.pointer);
569 
570 	/* Dump short info about the object */
571 
572 	(void)acpi_ns_dump_one_object(obj_handle, nesting_level, info, NULL);
573 	return (AE_OK);
574 }
575 
576 /*******************************************************************************
577  *
578  * FUNCTION:    acpi_db_display_objects
579  *
580  * PARAMETERS:  obj_type_arg        - Type of object to display
581  *              display_count_arg   - Max depth to display
582  *
583  * RETURN:      None
584  *
585  * DESCRIPTION: Display objects in the namespace of the requested type
586  *
587  ******************************************************************************/
588 
589 acpi_status acpi_db_display_objects(char *obj_type_arg, char *display_count_arg)
590 {
591 	struct acpi_walk_info info;
592 	acpi_object_type type;
593 	struct acpi_object_info *object_info;
594 	u32 i;
595 	u32 total_objects = 0;
596 
597 	/* No argument means display summary/count of all object types */
598 
599 	if (!obj_type_arg) {
600 		object_info =
601 		    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info));
602 
603 		/* Walk the namespace from the root */
604 
605 		(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
606 					  ACPI_UINT32_MAX,
607 					  acpi_db_walk_for_object_counts, NULL,
608 					  (void *)object_info, NULL);
609 
610 		acpi_os_printf("\nSummary of namespace objects:\n\n");
611 
612 		for (i = 0; i < ACPI_TOTAL_TYPES; i++) {
613 			acpi_os_printf("%8u %s\n", object_info->types[i],
614 				       acpi_ut_get_type_name(i));
615 
616 			total_objects += object_info->types[i];
617 		}
618 
619 		acpi_os_printf("\n%8u Total namespace objects\n\n",
620 			       total_objects);
621 
622 		ACPI_FREE(object_info);
623 		return (AE_OK);
624 	}
625 
626 	/* Get the object type */
627 
628 	type = acpi_db_match_argument(obj_type_arg, acpi_db_object_types);
629 	if (type == ACPI_TYPE_NOT_FOUND) {
630 		acpi_os_printf("Invalid or unsupported argument\n");
631 		return (AE_OK);
632 	}
633 
634 	acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
635 	acpi_os_printf
636 	    ("Objects of type [%s] defined in the current ACPI Namespace:\n",
637 	     acpi_ut_get_type_name(type));
638 
639 	acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
640 
641 	info.count = 0;
642 	info.owner_id = ACPI_OWNER_ID_MAX;
643 	info.debug_level = ACPI_UINT32_MAX;
644 	info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
645 
646 	/* Walk the namespace from the root */
647 
648 	(void)acpi_walk_namespace(type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
649 				  acpi_db_walk_for_specific_objects, NULL,
650 				  (void *)&info, NULL);
651 
652 	acpi_os_printf
653 	    ("\nFound %u objects of type [%s] in the current ACPI Namespace\n",
654 	     info.count, acpi_ut_get_type_name(type));
655 
656 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
657 	return (AE_OK);
658 }
659 
660 /*******************************************************************************
661  *
662  * FUNCTION:    acpi_db_integrity_walk
663  *
664  * PARAMETERS:  Callback from walk_namespace
665  *
666  * RETURN:      Status
667  *
668  * DESCRIPTION: Examine one NS node for valid values.
669  *
670  ******************************************************************************/
671 
672 static acpi_status
673 acpi_db_integrity_walk(acpi_handle obj_handle,
674 		       u32 nesting_level, void *context, void **return_value)
675 {
676 	struct acpi_integrity_info *info =
677 	    (struct acpi_integrity_info *)context;
678 	struct acpi_namespace_node *node =
679 	    (struct acpi_namespace_node *)obj_handle;
680 	union acpi_operand_object *object;
681 	u8 alias = TRUE;
682 
683 	info->nodes++;
684 
685 	/* Verify the NS node, and dereference aliases */
686 
687 	while (alias) {
688 		if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
689 			acpi_os_printf
690 			    ("Invalid Descriptor Type for Node %p [%s] - "
691 			     "is %2.2X should be %2.2X\n", node,
692 			     acpi_ut_get_descriptor_name(node),
693 			     ACPI_GET_DESCRIPTOR_TYPE(node),
694 			     ACPI_DESC_TYPE_NAMED);
695 			return (AE_OK);
696 		}
697 
698 		if ((node->type == ACPI_TYPE_LOCAL_ALIAS) ||
699 		    (node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
700 			node = (struct acpi_namespace_node *)node->object;
701 		} else {
702 			alias = FALSE;
703 		}
704 	}
705 
706 	if (node->type > ACPI_TYPE_LOCAL_MAX) {
707 		acpi_os_printf("Invalid Object Type for Node %p, Type = %X\n",
708 			       node, node->type);
709 		return (AE_OK);
710 	}
711 
712 	if (!acpi_ut_valid_acpi_name(node->name.ascii)) {
713 		acpi_os_printf("Invalid AcpiName for Node %p\n", node);
714 		return (AE_OK);
715 	}
716 
717 	object = acpi_ns_get_attached_object(node);
718 	if (object) {
719 		info->objects++;
720 		if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) {
721 			acpi_os_printf
722 			    ("Invalid Descriptor Type for Object %p [%s]\n",
723 			     object, acpi_ut_get_descriptor_name(object));
724 		}
725 	}
726 
727 	return (AE_OK);
728 }
729 
730 /*******************************************************************************
731  *
732  * FUNCTION:    acpi_db_check_integrity
733  *
734  * PARAMETERS:  None
735  *
736  * RETURN:      None
737  *
738  * DESCRIPTION: Check entire namespace for data structure integrity
739  *
740  ******************************************************************************/
741 
742 void acpi_db_check_integrity(void)
743 {
744 	struct acpi_integrity_info info = { 0, 0 };
745 
746 	/* Search all nodes in namespace */
747 
748 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
749 				  ACPI_UINT32_MAX, acpi_db_integrity_walk, NULL,
750 				  (void *)&info, NULL);
751 
752 	acpi_os_printf("Verified %u namespace nodes with %u Objects\n",
753 		       info.nodes, info.objects);
754 }
755 
756 /*******************************************************************************
757  *
758  * FUNCTION:    acpi_db_walk_for_references
759  *
760  * PARAMETERS:  Callback from walk_namespace
761  *
762  * RETURN:      Status
763  *
764  * DESCRIPTION: Check if this namespace object refers to the target object
765  *              that is passed in as the context value.
766  *
767  * Note: Currently doesn't check subobjects within the Node's object
768  *
769  ******************************************************************************/
770 
771 static acpi_status
772 acpi_db_walk_for_references(acpi_handle obj_handle,
773 			    u32 nesting_level,
774 			    void *context, void **return_value)
775 {
776 	union acpi_operand_object *obj_desc =
777 	    (union acpi_operand_object *)context;
778 	struct acpi_namespace_node *node =
779 	    (struct acpi_namespace_node *)obj_handle;
780 
781 	/* Check for match against the namespace node itself */
782 
783 	if (node == (void *)obj_desc) {
784 		acpi_os_printf("Object is a Node [%4.4s]\n",
785 			       acpi_ut_get_node_name(node));
786 	}
787 
788 	/* Check for match against the object attached to the node */
789 
790 	if (acpi_ns_get_attached_object(node) == obj_desc) {
791 		acpi_os_printf("Reference at Node->Object %p [%4.4s]\n",
792 			       node, acpi_ut_get_node_name(node));
793 	}
794 
795 	return (AE_OK);
796 }
797 
798 /*******************************************************************************
799  *
800  * FUNCTION:    acpi_db_find_references
801  *
802  * PARAMETERS:  object_arg      - String with hex value of the object
803  *
804  * RETURN:      None
805  *
806  * DESCRIPTION: Search namespace for all references to the input object
807  *
808  ******************************************************************************/
809 
810 void acpi_db_find_references(char *object_arg)
811 {
812 	union acpi_operand_object *obj_desc;
813 	acpi_size address;
814 
815 	/* Convert string to object pointer */
816 
817 	address = strtoul(object_arg, NULL, 16);
818 	obj_desc = ACPI_TO_POINTER(address);
819 
820 	/* Search all nodes in namespace */
821 
822 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
823 				  ACPI_UINT32_MAX, acpi_db_walk_for_references,
824 				  NULL, (void *)obj_desc, NULL);
825 }
826 
827 /*******************************************************************************
828  *
829  * FUNCTION:    acpi_db_bus_walk
830  *
831  * PARAMETERS:  Callback from walk_namespace
832  *
833  * RETURN:      Status
834  *
835  * DESCRIPTION: Display info about device objects that have a corresponding
836  *              _PRT method.
837  *
838  ******************************************************************************/
839 
840 static acpi_status
841 acpi_db_bus_walk(acpi_handle obj_handle,
842 		 u32 nesting_level, void *context, void **return_value)
843 {
844 	struct acpi_namespace_node *node =
845 	    (struct acpi_namespace_node *)obj_handle;
846 	acpi_status status;
847 	struct acpi_buffer buffer;
848 	struct acpi_namespace_node *temp_node;
849 	struct acpi_device_info *info;
850 	u32 i;
851 
852 	if ((node->type != ACPI_TYPE_DEVICE) &&
853 	    (node->type != ACPI_TYPE_PROCESSOR)) {
854 		return (AE_OK);
855 	}
856 
857 	/* Exit if there is no _PRT under this device */
858 
859 	status = acpi_get_handle(node, METHOD_NAME__PRT,
860 				 ACPI_CAST_PTR(acpi_handle, &temp_node));
861 	if (ACPI_FAILURE(status)) {
862 		return (AE_OK);
863 	}
864 
865 	/* Get the full path to this device object */
866 
867 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
868 	status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
869 	if (ACPI_FAILURE(status)) {
870 		acpi_os_printf("Could Not get pathname for object %p\n",
871 			       obj_handle);
872 		return (AE_OK);
873 	}
874 
875 	status = acpi_get_object_info(obj_handle, &info);
876 	if (ACPI_FAILURE(status)) {
877 		return (AE_OK);
878 	}
879 
880 	/* Display the full path */
881 
882 	acpi_os_printf("%-32s Type %X", (char *)buffer.pointer, node->type);
883 	ACPI_FREE(buffer.pointer);
884 
885 	if (info->flags & ACPI_PCI_ROOT_BRIDGE) {
886 		acpi_os_printf(" - Is PCI Root Bridge");
887 	}
888 	acpi_os_printf("\n");
889 
890 	/* _PRT info */
891 
892 	acpi_os_printf("_PRT: %p\n", temp_node);
893 
894 	/* Dump _ADR, _HID, _UID, _CID */
895 
896 	if (info->valid & ACPI_VALID_ADR) {
897 		acpi_os_printf("_ADR: %8.8X%8.8X\n",
898 			       ACPI_FORMAT_UINT64(info->address));
899 	} else {
900 		acpi_os_printf("_ADR: <Not Present>\n");
901 	}
902 
903 	if (info->valid & ACPI_VALID_HID) {
904 		acpi_os_printf("_HID: %s\n", info->hardware_id.string);
905 	} else {
906 		acpi_os_printf("_HID: <Not Present>\n");
907 	}
908 
909 	if (info->valid & ACPI_VALID_UID) {
910 		acpi_os_printf("_UID: %s\n", info->unique_id.string);
911 	} else {
912 		acpi_os_printf("_UID: <Not Present>\n");
913 	}
914 
915 	if (info->valid & ACPI_VALID_CID) {
916 		for (i = 0; i < info->compatible_id_list.count; i++) {
917 			acpi_os_printf("_CID: %s\n",
918 				       info->compatible_id_list.ids[i].string);
919 		}
920 	} else {
921 		acpi_os_printf("_CID: <Not Present>\n");
922 	}
923 
924 	ACPI_FREE(info);
925 	return (AE_OK);
926 }
927 
928 /*******************************************************************************
929  *
930  * FUNCTION:    acpi_db_get_bus_info
931  *
932  * PARAMETERS:  None
933  *
934  * RETURN:      None
935  *
936  * DESCRIPTION: Display info about system busses.
937  *
938  ******************************************************************************/
939 
940 void acpi_db_get_bus_info(void)
941 {
942 	/* Search all nodes in namespace */
943 
944 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
945 				  ACPI_UINT32_MAX, acpi_db_bus_walk, NULL, NULL,
946 				  NULL);
947 }
948