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