xref: /openbmc/linux/drivers/acpi/acpica/dbnames.c (revision 11976fe2)
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 	acpi_evaluate_object(obj_handle, NULL, NULL, &buffer);
554 
555 	/*
556 	 * Since this is a field unit, surround the output in braces
557 	 */
558 	acpi_os_printf("{");
559 
560 	ret_value = (union acpi_object *)buffer.pointer;
561 	switch (ret_value->type) {
562 	case ACPI_TYPE_INTEGER:
563 
564 		acpi_os_printf("%8.8X%8.8X",
565 			       ACPI_FORMAT_UINT64(ret_value->integer.value));
566 		break;
567 
568 	case ACPI_TYPE_BUFFER:
569 
570 		acpi_ut_dump_buffer(ret_value->buffer.pointer,
571 				    ret_value->buffer.length,
572 				    DB_DISPLAY_DATA_ONLY | DB_BYTE_DISPLAY, 0);
573 		break;
574 
575 	default:
576 
577 		break;
578 	}
579 	acpi_os_printf("}\n");
580 
581 	ACPI_FREE(buffer.pointer);
582 
583 	return (AE_OK);
584 }
585 
586 /*******************************************************************************
587  *
588  * FUNCTION:    acpi_db_walk_for_specific_objects
589  *
590  * PARAMETERS:  Callback from walk_namespace
591  *
592  * RETURN:      Status
593  *
594  * DESCRIPTION: Display short info about objects in the namespace
595  *
596  ******************************************************************************/
597 
598 static acpi_status
599 acpi_db_walk_for_specific_objects(acpi_handle obj_handle,
600 				  u32 nesting_level,
601 				  void *context, void **return_value)
602 {
603 	struct acpi_walk_info *info = (struct acpi_walk_info *)context;
604 	struct acpi_buffer buffer;
605 	acpi_status status;
606 
607 	info->count++;
608 
609 	/* Get and display the full pathname to this object */
610 
611 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
612 	status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
613 	if (ACPI_FAILURE(status)) {
614 		acpi_os_printf("Could Not get pathname for object %p\n",
615 			       obj_handle);
616 		return (AE_OK);
617 	}
618 
619 	acpi_os_printf("%32s", (char *)buffer.pointer);
620 	ACPI_FREE(buffer.pointer);
621 
622 	/* Dump short info about the object */
623 
624 	(void)acpi_ns_dump_one_object(obj_handle, nesting_level, info, NULL);
625 	return (AE_OK);
626 }
627 
628 /*******************************************************************************
629  *
630  * FUNCTION:    acpi_db_display_objects
631  *
632  * PARAMETERS:  obj_type_arg        - Type of object to display
633  *              display_count_arg   - Max depth to display
634  *
635  * RETURN:      None
636  *
637  * DESCRIPTION: Display objects in the namespace of the requested type
638  *
639  ******************************************************************************/
640 
641 acpi_status acpi_db_display_objects(char *obj_type_arg, char *display_count_arg)
642 {
643 	struct acpi_walk_info info;
644 	acpi_object_type type;
645 	struct acpi_object_info *object_info;
646 	u32 i;
647 	u32 total_objects = 0;
648 
649 	/* No argument means display summary/count of all object types */
650 
651 	if (!obj_type_arg) {
652 		object_info =
653 		    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info));
654 
655 		if (!object_info)
656 			return (AE_NO_MEMORY);
657 
658 		/* Walk the namespace from the root */
659 
660 		(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
661 					  ACPI_UINT32_MAX,
662 					  acpi_db_walk_for_object_counts, NULL,
663 					  (void *)object_info, NULL);
664 
665 		acpi_os_printf("\nSummary of namespace objects:\n\n");
666 
667 		for (i = 0; i < ACPI_TOTAL_TYPES; i++) {
668 			acpi_os_printf("%8u %s\n", object_info->types[i],
669 				       acpi_ut_get_type_name(i));
670 
671 			total_objects += object_info->types[i];
672 		}
673 
674 		acpi_os_printf("\n%8u Total namespace objects\n\n",
675 			       total_objects);
676 
677 		ACPI_FREE(object_info);
678 		return (AE_OK);
679 	}
680 
681 	/* Get the object type */
682 
683 	type = acpi_db_match_argument(obj_type_arg, acpi_db_object_types);
684 	if (type == ACPI_TYPE_NOT_FOUND) {
685 		acpi_os_printf("Invalid or unsupported argument\n");
686 		return (AE_OK);
687 	}
688 
689 	acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT);
690 	acpi_os_printf
691 	    ("Objects of type [%s] defined in the current ACPI Namespace:\n",
692 	     acpi_ut_get_type_name(type));
693 
694 	acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT);
695 
696 	info.count = 0;
697 	info.owner_id = ACPI_OWNER_ID_MAX;
698 	info.debug_level = ACPI_UINT32_MAX;
699 	info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
700 
701 	/* Walk the namespace from the root */
702 
703 	(void)acpi_walk_namespace(type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
704 				  acpi_db_walk_for_specific_objects, NULL,
705 				  (void *)&info, NULL);
706 
707 	acpi_os_printf
708 	    ("\nFound %u objects of type [%s] in the current ACPI Namespace\n",
709 	     info.count, acpi_ut_get_type_name(type));
710 
711 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
712 	return (AE_OK);
713 }
714 
715 /*******************************************************************************
716  *
717  * FUNCTION:    acpi_db_display_fields
718  *
719  * PARAMETERS:  obj_type_arg        - Type of object to display
720  *              display_count_arg   - Max depth to display
721  *
722  * RETURN:      None
723  *
724  * DESCRIPTION: Display objects in the namespace of the requested type
725  *
726  ******************************************************************************/
727 
728 acpi_status acpi_db_display_fields(u32 address_space_id)
729 {
730 	struct acpi_region_walk_info info;
731 
732 	info.count = 0;
733 	info.owner_id = ACPI_OWNER_ID_MAX;
734 	info.debug_level = ACPI_UINT32_MAX;
735 	info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
736 	info.address_space_id = address_space_id;
737 
738 	/* Walk the namespace from the root */
739 
740 	(void)acpi_walk_namespace(ACPI_TYPE_LOCAL_REGION_FIELD,
741 				  ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
742 				  acpi_db_walk_for_fields, NULL, (void *)&info,
743 				  NULL);
744 
745 	return (AE_OK);
746 }
747 
748 /*******************************************************************************
749  *
750  * FUNCTION:    acpi_db_integrity_walk
751  *
752  * PARAMETERS:  Callback from walk_namespace
753  *
754  * RETURN:      Status
755  *
756  * DESCRIPTION: Examine one NS node for valid values.
757  *
758  ******************************************************************************/
759 
760 static acpi_status
761 acpi_db_integrity_walk(acpi_handle obj_handle,
762 		       u32 nesting_level, void *context, void **return_value)
763 {
764 	struct acpi_integrity_info *info =
765 	    (struct acpi_integrity_info *)context;
766 	struct acpi_namespace_node *node =
767 	    (struct acpi_namespace_node *)obj_handle;
768 	union acpi_operand_object *object;
769 	u8 alias = TRUE;
770 
771 	info->nodes++;
772 
773 	/* Verify the NS node, and dereference aliases */
774 
775 	while (alias) {
776 		if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
777 			acpi_os_printf
778 			    ("Invalid Descriptor Type for Node %p [%s] - "
779 			     "is %2.2X should be %2.2X\n", node,
780 			     acpi_ut_get_descriptor_name(node),
781 			     ACPI_GET_DESCRIPTOR_TYPE(node),
782 			     ACPI_DESC_TYPE_NAMED);
783 			return (AE_OK);
784 		}
785 
786 		if ((node->type == ACPI_TYPE_LOCAL_ALIAS) ||
787 		    (node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
788 			node = (struct acpi_namespace_node *)node->object;
789 		} else {
790 			alias = FALSE;
791 		}
792 	}
793 
794 	if (node->type > ACPI_TYPE_LOCAL_MAX) {
795 		acpi_os_printf("Invalid Object Type for Node %p, Type = %X\n",
796 			       node, node->type);
797 		return (AE_OK);
798 	}
799 
800 	if (!acpi_ut_valid_nameseg(node->name.ascii)) {
801 		acpi_os_printf("Invalid AcpiName for Node %p\n", node);
802 		return (AE_OK);
803 	}
804 
805 	object = acpi_ns_get_attached_object(node);
806 	if (object) {
807 		info->objects++;
808 		if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) {
809 			acpi_os_printf
810 			    ("Invalid Descriptor Type for Object %p [%s]\n",
811 			     object, acpi_ut_get_descriptor_name(object));
812 		}
813 	}
814 
815 	return (AE_OK);
816 }
817 
818 /*******************************************************************************
819  *
820  * FUNCTION:    acpi_db_check_integrity
821  *
822  * PARAMETERS:  None
823  *
824  * RETURN:      None
825  *
826  * DESCRIPTION: Check entire namespace for data structure integrity
827  *
828  ******************************************************************************/
829 
830 void acpi_db_check_integrity(void)
831 {
832 	struct acpi_integrity_info info = { 0, 0 };
833 
834 	/* Search all nodes in namespace */
835 
836 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
837 				  ACPI_UINT32_MAX, acpi_db_integrity_walk, NULL,
838 				  (void *)&info, NULL);
839 
840 	acpi_os_printf("Verified %u namespace nodes with %u Objects\n",
841 		       info.nodes, info.objects);
842 }
843 
844 /*******************************************************************************
845  *
846  * FUNCTION:    acpi_db_walk_for_references
847  *
848  * PARAMETERS:  Callback from walk_namespace
849  *
850  * RETURN:      Status
851  *
852  * DESCRIPTION: Check if this namespace object refers to the target object
853  *              that is passed in as the context value.
854  *
855  * Note: Currently doesn't check subobjects within the Node's object
856  *
857  ******************************************************************************/
858 
859 static acpi_status
860 acpi_db_walk_for_references(acpi_handle obj_handle,
861 			    u32 nesting_level,
862 			    void *context, void **return_value)
863 {
864 	union acpi_operand_object *obj_desc =
865 	    (union acpi_operand_object *)context;
866 	struct acpi_namespace_node *node =
867 	    (struct acpi_namespace_node *)obj_handle;
868 
869 	/* Check for match against the namespace node itself */
870 
871 	if (node == (void *)obj_desc) {
872 		acpi_os_printf("Object is a Node [%4.4s]\n",
873 			       acpi_ut_get_node_name(node));
874 	}
875 
876 	/* Check for match against the object attached to the node */
877 
878 	if (acpi_ns_get_attached_object(node) == obj_desc) {
879 		acpi_os_printf("Reference at Node->Object %p [%4.4s]\n",
880 			       node, acpi_ut_get_node_name(node));
881 	}
882 
883 	return (AE_OK);
884 }
885 
886 /*******************************************************************************
887  *
888  * FUNCTION:    acpi_db_find_references
889  *
890  * PARAMETERS:  object_arg      - String with hex value of the object
891  *
892  * RETURN:      None
893  *
894  * DESCRIPTION: Search namespace for all references to the input object
895  *
896  ******************************************************************************/
897 
898 void acpi_db_find_references(char *object_arg)
899 {
900 	union acpi_operand_object *obj_desc;
901 	acpi_size address;
902 
903 	/* Convert string to object pointer */
904 
905 	address = strtoul(object_arg, NULL, 16);
906 	obj_desc = ACPI_TO_POINTER(address);
907 
908 	/* Search all nodes in namespace */
909 
910 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
911 				  ACPI_UINT32_MAX, acpi_db_walk_for_references,
912 				  NULL, (void *)obj_desc, NULL);
913 }
914 
915 /*******************************************************************************
916  *
917  * FUNCTION:    acpi_db_bus_walk
918  *
919  * PARAMETERS:  Callback from walk_namespace
920  *
921  * RETURN:      Status
922  *
923  * DESCRIPTION: Display info about device objects that have a corresponding
924  *              _PRT method.
925  *
926  ******************************************************************************/
927 
928 static acpi_status
929 acpi_db_bus_walk(acpi_handle obj_handle,
930 		 u32 nesting_level, void *context, void **return_value)
931 {
932 	struct acpi_namespace_node *node =
933 	    (struct acpi_namespace_node *)obj_handle;
934 	acpi_status status;
935 	struct acpi_buffer buffer;
936 	struct acpi_namespace_node *temp_node;
937 	struct acpi_device_info *info;
938 	u32 i;
939 
940 	if ((node->type != ACPI_TYPE_DEVICE) &&
941 	    (node->type != ACPI_TYPE_PROCESSOR)) {
942 		return (AE_OK);
943 	}
944 
945 	/* Exit if there is no _PRT under this device */
946 
947 	status = acpi_get_handle(node, METHOD_NAME__PRT,
948 				 ACPI_CAST_PTR(acpi_handle, &temp_node));
949 	if (ACPI_FAILURE(status)) {
950 		return (AE_OK);
951 	}
952 
953 	/* Get the full path to this device object */
954 
955 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
956 	status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);
957 	if (ACPI_FAILURE(status)) {
958 		acpi_os_printf("Could Not get pathname for object %p\n",
959 			       obj_handle);
960 		return (AE_OK);
961 	}
962 
963 	status = acpi_get_object_info(obj_handle, &info);
964 	if (ACPI_FAILURE(status)) {
965 		return (AE_OK);
966 	}
967 
968 	/* Display the full path */
969 
970 	acpi_os_printf("%-32s Type %X", (char *)buffer.pointer, node->type);
971 	ACPI_FREE(buffer.pointer);
972 
973 	if (info->flags & ACPI_PCI_ROOT_BRIDGE) {
974 		acpi_os_printf(" - Is PCI Root Bridge");
975 	}
976 	acpi_os_printf("\n");
977 
978 	/* _PRT info */
979 
980 	acpi_os_printf("_PRT: %p\n", temp_node);
981 
982 	/* Dump _ADR, _HID, _UID, _CID */
983 
984 	if (info->valid & ACPI_VALID_ADR) {
985 		acpi_os_printf("_ADR: %8.8X%8.8X\n",
986 			       ACPI_FORMAT_UINT64(info->address));
987 	} else {
988 		acpi_os_printf("_ADR: <Not Present>\n");
989 	}
990 
991 	if (info->valid & ACPI_VALID_HID) {
992 		acpi_os_printf("_HID: %s\n", info->hardware_id.string);
993 	} else {
994 		acpi_os_printf("_HID: <Not Present>\n");
995 	}
996 
997 	if (info->valid & ACPI_VALID_UID) {
998 		acpi_os_printf("_UID: %s\n", info->unique_id.string);
999 	} else {
1000 		acpi_os_printf("_UID: <Not Present>\n");
1001 	}
1002 
1003 	if (info->valid & ACPI_VALID_CID) {
1004 		for (i = 0; i < info->compatible_id_list.count; i++) {
1005 			acpi_os_printf("_CID: %s\n",
1006 				       info->compatible_id_list.ids[i].string);
1007 		}
1008 	} else {
1009 		acpi_os_printf("_CID: <Not Present>\n");
1010 	}
1011 
1012 	ACPI_FREE(info);
1013 	return (AE_OK);
1014 }
1015 
1016 /*******************************************************************************
1017  *
1018  * FUNCTION:    acpi_db_get_bus_info
1019  *
1020  * PARAMETERS:  None
1021  *
1022  * RETURN:      None
1023  *
1024  * DESCRIPTION: Display info about system buses.
1025  *
1026  ******************************************************************************/
1027 
1028 void acpi_db_get_bus_info(void)
1029 {
1030 	/* Search all nodes in namespace */
1031 
1032 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
1033 				  ACPI_UINT32_MAX, acpi_db_bus_walk, NULL, NULL,
1034 				  NULL);
1035 }
1036