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