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