| // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 | 
 | /******************************************************************************* | 
 |  * | 
 |  * Module Name: dbnames - Debugger commands for the acpi namespace | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | #include <acpi/acpi.h> | 
 | #include "accommon.h" | 
 | #include "acnamesp.h" | 
 | #include "acdebug.h" | 
 | #include "acpredef.h" | 
 |  | 
 | #define _COMPONENT          ACPI_CA_DEBUGGER | 
 | ACPI_MODULE_NAME("dbnames") | 
 |  | 
 | /* Local prototypes */ | 
 | static acpi_status | 
 | acpi_db_walk_and_match_name(acpi_handle obj_handle, | 
 | 			    u32 nesting_level, | 
 | 			    void *context, void **return_value); | 
 |  | 
 | static acpi_status | 
 | acpi_db_walk_for_predefined_names(acpi_handle obj_handle, | 
 | 				  u32 nesting_level, | 
 | 				  void *context, void **return_value); | 
 |  | 
 | static acpi_status | 
 | acpi_db_walk_for_specific_objects(acpi_handle obj_handle, | 
 | 				  u32 nesting_level, | 
 | 				  void *context, void **return_value); | 
 |  | 
 | static acpi_status | 
 | acpi_db_walk_for_object_counts(acpi_handle obj_handle, | 
 | 			       u32 nesting_level, | 
 | 			       void *context, void **return_value); | 
 |  | 
 | static acpi_status | 
 | acpi_db_integrity_walk(acpi_handle obj_handle, | 
 | 		       u32 nesting_level, void *context, void **return_value); | 
 |  | 
 | static acpi_status | 
 | acpi_db_walk_for_references(acpi_handle obj_handle, | 
 | 			    u32 nesting_level, | 
 | 			    void *context, void **return_value); | 
 |  | 
 | static acpi_status | 
 | acpi_db_bus_walk(acpi_handle obj_handle, | 
 | 		 u32 nesting_level, void *context, void **return_value); | 
 |  | 
 | /* | 
 |  * Arguments for the Objects command | 
 |  * These object types map directly to the ACPI_TYPES | 
 |  */ | 
 | static struct acpi_db_argument_info acpi_db_object_types[] = { | 
 | 	{"ANY"}, | 
 | 	{"INTEGERS"}, | 
 | 	{"STRINGS"}, | 
 | 	{"BUFFERS"}, | 
 | 	{"PACKAGES"}, | 
 | 	{"FIELDS"}, | 
 | 	{"DEVICES"}, | 
 | 	{"EVENTS"}, | 
 | 	{"METHODS"}, | 
 | 	{"MUTEXES"}, | 
 | 	{"REGIONS"}, | 
 | 	{"POWERRESOURCES"}, | 
 | 	{"PROCESSORS"}, | 
 | 	{"THERMALZONES"}, | 
 | 	{"BUFFERFIELDS"}, | 
 | 	{"DDBHANDLES"}, | 
 | 	{"DEBUG"}, | 
 | 	{"REGIONFIELDS"}, | 
 | 	{"BANKFIELDS"}, | 
 | 	{"INDEXFIELDS"}, | 
 | 	{"REFERENCES"}, | 
 | 	{"ALIASES"}, | 
 | 	{"METHODALIASES"}, | 
 | 	{"NOTIFY"}, | 
 | 	{"ADDRESSHANDLER"}, | 
 | 	{"RESOURCE"}, | 
 | 	{"RESOURCEFIELD"}, | 
 | 	{"SCOPES"}, | 
 | 	{NULL}			/* Must be null terminated */ | 
 | }; | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_set_scope | 
 |  * | 
 |  * PARAMETERS:  name                - New scope path | 
 |  * | 
 |  * RETURN:      Status | 
 |  * | 
 |  * DESCRIPTION: Set the "current scope" as maintained by this utility. | 
 |  *              The scope is used as a prefix to ACPI paths. | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | void acpi_db_set_scope(char *name) | 
 | { | 
 | 	acpi_status status; | 
 | 	struct acpi_namespace_node *node; | 
 |  | 
 | 	if (!name || name[0] == 0) { | 
 | 		acpi_os_printf("Current scope: %s\n", acpi_gbl_db_scope_buf); | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	acpi_db_prep_namestring(name); | 
 |  | 
 | 	if (ACPI_IS_ROOT_PREFIX(name[0])) { | 
 |  | 
 | 		/* Validate new scope from the root */ | 
 |  | 
 | 		status = acpi_ns_get_node(acpi_gbl_root_node, name, | 
 | 					  ACPI_NS_NO_UPSEARCH, &node); | 
 | 		if (ACPI_FAILURE(status)) { | 
 | 			goto error_exit; | 
 | 		} | 
 |  | 
 | 		acpi_gbl_db_scope_buf[0] = 0; | 
 | 	} else { | 
 | 		/* Validate new scope relative to old scope */ | 
 |  | 
 | 		status = acpi_ns_get_node(acpi_gbl_db_scope_node, name, | 
 | 					  ACPI_NS_NO_UPSEARCH, &node); | 
 | 		if (ACPI_FAILURE(status)) { | 
 | 			goto error_exit; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	/* Build the final pathname */ | 
 |  | 
 | 	if (acpi_ut_safe_strcat | 
 | 	    (acpi_gbl_db_scope_buf, sizeof(acpi_gbl_db_scope_buf), name)) { | 
 | 		status = AE_BUFFER_OVERFLOW; | 
 | 		goto error_exit; | 
 | 	} | 
 |  | 
 | 	if (acpi_ut_safe_strcat | 
 | 	    (acpi_gbl_db_scope_buf, sizeof(acpi_gbl_db_scope_buf), "\\")) { | 
 | 		status = AE_BUFFER_OVERFLOW; | 
 | 		goto error_exit; | 
 | 	} | 
 |  | 
 | 	acpi_gbl_db_scope_node = node; | 
 | 	acpi_os_printf("New scope: %s\n", acpi_gbl_db_scope_buf); | 
 | 	return; | 
 |  | 
 | error_exit: | 
 |  | 
 | 	acpi_os_printf("Could not attach scope: %s, %s\n", | 
 | 		       name, acpi_format_exception(status)); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_dump_namespace | 
 |  * | 
 |  * PARAMETERS:  start_arg       - Node to begin namespace dump | 
 |  *              depth_arg       - Maximum tree depth to be dumped | 
 |  * | 
 |  * RETURN:      None | 
 |  * | 
 |  * DESCRIPTION: Dump entire namespace or a subtree. Each node is displayed | 
 |  *              with type and other information. | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | void acpi_db_dump_namespace(char *start_arg, char *depth_arg) | 
 | { | 
 | 	acpi_handle subtree_entry = acpi_gbl_root_node; | 
 | 	u32 max_depth = ACPI_UINT32_MAX; | 
 |  | 
 | 	/* No argument given, just start at the root and dump entire namespace */ | 
 |  | 
 | 	if (start_arg) { | 
 | 		subtree_entry = acpi_db_convert_to_node(start_arg); | 
 | 		if (!subtree_entry) { | 
 | 			return; | 
 | 		} | 
 |  | 
 | 		/* Now we can check for the depth argument */ | 
 |  | 
 | 		if (depth_arg) { | 
 | 			max_depth = strtoul(depth_arg, NULL, 0); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); | 
 |  | 
 | 	if (((struct acpi_namespace_node *)subtree_entry)->parent) { | 
 | 		acpi_os_printf("ACPI Namespace (from %4.4s (%p) subtree):\n", | 
 | 			       ((struct acpi_namespace_node *)subtree_entry)-> | 
 | 			       name.ascii, subtree_entry); | 
 | 	} else { | 
 | 		acpi_os_printf("ACPI Namespace (from %s):\n", | 
 | 			       ACPI_NAMESPACE_ROOT); | 
 | 	} | 
 |  | 
 | 	/* Display the subtree */ | 
 |  | 
 | 	acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); | 
 | 	acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth, | 
 | 			     ACPI_OWNER_ID_MAX, subtree_entry); | 
 | 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_dump_namespace_paths | 
 |  * | 
 |  * PARAMETERS:  None | 
 |  * | 
 |  * RETURN:      None | 
 |  * | 
 |  * DESCRIPTION: Dump entire namespace with full object pathnames and object | 
 |  *              type information. Alternative to "namespace" command. | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | void acpi_db_dump_namespace_paths(void) | 
 | { | 
 |  | 
 | 	acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); | 
 | 	acpi_os_printf("ACPI Namespace (from root):\n"); | 
 |  | 
 | 	/* Display the entire namespace */ | 
 |  | 
 | 	acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); | 
 | 	acpi_ns_dump_object_paths(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, | 
 | 				  ACPI_UINT32_MAX, ACPI_OWNER_ID_MAX, | 
 | 				  acpi_gbl_root_node); | 
 |  | 
 | 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_dump_namespace_by_owner | 
 |  * | 
 |  * PARAMETERS:  owner_arg       - Owner ID whose nodes will be displayed | 
 |  *              depth_arg       - Maximum tree depth to be dumped | 
 |  * | 
 |  * RETURN:      None | 
 |  * | 
 |  * DESCRIPTION: Dump elements of the namespace that are owned by the owner_id. | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | void acpi_db_dump_namespace_by_owner(char *owner_arg, char *depth_arg) | 
 | { | 
 | 	acpi_handle subtree_entry = acpi_gbl_root_node; | 
 | 	u32 max_depth = ACPI_UINT32_MAX; | 
 | 	acpi_owner_id owner_id; | 
 |  | 
 | 	owner_id = (acpi_owner_id)strtoul(owner_arg, NULL, 0); | 
 |  | 
 | 	/* Now we can check for the depth argument */ | 
 |  | 
 | 	if (depth_arg) { | 
 | 		max_depth = strtoul(depth_arg, NULL, 0); | 
 | 	} | 
 |  | 
 | 	acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); | 
 | 	acpi_os_printf("ACPI Namespace by owner %X:\n", owner_id); | 
 |  | 
 | 	/* Display the subtree */ | 
 |  | 
 | 	acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); | 
 | 	acpi_ns_dump_objects(ACPI_TYPE_ANY, ACPI_DISPLAY_SUMMARY, max_depth, | 
 | 			     owner_id, subtree_entry); | 
 | 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_walk_and_match_name | 
 |  * | 
 |  * PARAMETERS:  Callback from walk_namespace | 
 |  * | 
 |  * RETURN:      Status | 
 |  * | 
 |  * DESCRIPTION: Find a particular name/names within the namespace. Wildcards | 
 |  *              are supported -- '?' matches any character. | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | static acpi_status | 
 | acpi_db_walk_and_match_name(acpi_handle obj_handle, | 
 | 			    u32 nesting_level, | 
 | 			    void *context, void **return_value) | 
 | { | 
 | 	acpi_status status; | 
 | 	char *requested_name = (char *)context; | 
 | 	u32 i; | 
 | 	struct acpi_buffer buffer; | 
 | 	struct acpi_walk_info info; | 
 |  | 
 | 	/* Check for a name match */ | 
 |  | 
 | 	for (i = 0; i < 4; i++) { | 
 |  | 
 | 		/* Wildcard support */ | 
 |  | 
 | 		if ((requested_name[i] != '?') && | 
 | 		    (requested_name[i] != ((struct acpi_namespace_node *) | 
 | 					   obj_handle)->name.ascii[i])) { | 
 |  | 
 | 			/* No match, just exit */ | 
 |  | 
 | 			return (AE_OK); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	/* Get the full pathname to this object */ | 
 |  | 
 | 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; | 
 | 	status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); | 
 | 	if (ACPI_FAILURE(status)) { | 
 | 		acpi_os_printf("Could Not get pathname for object %p\n", | 
 | 			       obj_handle); | 
 | 	} else { | 
 | 		info.count = 0; | 
 | 		info.owner_id = ACPI_OWNER_ID_MAX; | 
 | 		info.debug_level = ACPI_UINT32_MAX; | 
 | 		info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; | 
 |  | 
 | 		acpi_os_printf("%32s", (char *)buffer.pointer); | 
 | 		(void)acpi_ns_dump_one_object(obj_handle, nesting_level, &info, | 
 | 					      NULL); | 
 | 		ACPI_FREE(buffer.pointer); | 
 | 	} | 
 |  | 
 | 	return (AE_OK); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_find_name_in_namespace | 
 |  * | 
 |  * PARAMETERS:  name_arg        - The 4-character ACPI name to find. | 
 |  *                                wildcards are supported. | 
 |  * | 
 |  * RETURN:      None | 
 |  * | 
 |  * DESCRIPTION: Search the namespace for a given name (with wildcards) | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | acpi_status acpi_db_find_name_in_namespace(char *name_arg) | 
 | { | 
 | 	char acpi_name[5] = "____"; | 
 | 	char *acpi_name_ptr = acpi_name; | 
 |  | 
 | 	if (strlen(name_arg) > ACPI_NAME_SIZE) { | 
 | 		acpi_os_printf("Name must be no longer than 4 characters\n"); | 
 | 		return (AE_OK); | 
 | 	} | 
 |  | 
 | 	/* Pad out name with underscores as necessary to create a 4-char name */ | 
 |  | 
 | 	acpi_ut_strupr(name_arg); | 
 | 	while (*name_arg) { | 
 | 		*acpi_name_ptr = *name_arg; | 
 | 		acpi_name_ptr++; | 
 | 		name_arg++; | 
 | 	} | 
 |  | 
 | 	/* Walk the namespace from the root */ | 
 |  | 
 | 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, | 
 | 				  ACPI_UINT32_MAX, acpi_db_walk_and_match_name, | 
 | 				  NULL, acpi_name, NULL); | 
 |  | 
 | 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); | 
 | 	return (AE_OK); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_walk_for_predefined_names | 
 |  * | 
 |  * PARAMETERS:  Callback from walk_namespace | 
 |  * | 
 |  * RETURN:      Status | 
 |  * | 
 |  * DESCRIPTION: Detect and display predefined ACPI names (names that start with | 
 |  *              an underscore) | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | static acpi_status | 
 | acpi_db_walk_for_predefined_names(acpi_handle obj_handle, | 
 | 				  u32 nesting_level, | 
 | 				  void *context, void **return_value) | 
 | { | 
 | 	struct acpi_namespace_node *node = | 
 | 	    (struct acpi_namespace_node *)obj_handle; | 
 | 	u32 *count = (u32 *)context; | 
 | 	const union acpi_predefined_info *predefined; | 
 | 	const union acpi_predefined_info *package = NULL; | 
 | 	char *pathname; | 
 | 	char string_buffer[48]; | 
 |  | 
 | 	predefined = acpi_ut_match_predefined_method(node->name.ascii); | 
 | 	if (!predefined) { | 
 | 		return (AE_OK); | 
 | 	} | 
 |  | 
 | 	pathname = acpi_ns_get_normalized_pathname(node, TRUE); | 
 | 	if (!pathname) { | 
 | 		return (AE_OK); | 
 | 	} | 
 |  | 
 | 	/* If method returns a package, the info is in the next table entry */ | 
 |  | 
 | 	if (predefined->info.expected_btypes & ACPI_RTYPE_PACKAGE) { | 
 | 		package = predefined + 1; | 
 | 	} | 
 |  | 
 | 	acpi_ut_get_expected_return_types(string_buffer, | 
 | 					  predefined->info.expected_btypes); | 
 |  | 
 | 	acpi_os_printf("%-32s Arguments %X, Return Types: %s", pathname, | 
 | 		       METHOD_GET_ARG_COUNT(predefined->info.argument_list), | 
 | 		       string_buffer); | 
 |  | 
 | 	if (package) { | 
 | 		acpi_os_printf(" (PkgType %2.2X, ObjType %2.2X, Count %2.2X)", | 
 | 			       package->ret_info.type, | 
 | 			       package->ret_info.object_type1, | 
 | 			       package->ret_info.count1); | 
 | 	} | 
 |  | 
 | 	acpi_os_printf("\n"); | 
 |  | 
 | 	/* Check that the declared argument count matches the ACPI spec */ | 
 |  | 
 | 	acpi_ns_check_acpi_compliance(pathname, node, predefined); | 
 |  | 
 | 	ACPI_FREE(pathname); | 
 | 	(*count)++; | 
 | 	return (AE_OK); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_check_predefined_names | 
 |  * | 
 |  * PARAMETERS:  None | 
 |  * | 
 |  * RETURN:      None | 
 |  * | 
 |  * DESCRIPTION: Validate all predefined names in the namespace | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | void acpi_db_check_predefined_names(void) | 
 | { | 
 | 	u32 count = 0; | 
 |  | 
 | 	/* Search all nodes in namespace */ | 
 |  | 
 | 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, | 
 | 				  ACPI_UINT32_MAX, | 
 | 				  acpi_db_walk_for_predefined_names, NULL, | 
 | 				  (void *)&count, NULL); | 
 |  | 
 | 	acpi_os_printf("Found %u predefined names in the namespace\n", count); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_walk_for_object_counts | 
 |  * | 
 |  * PARAMETERS:  Callback from walk_namespace | 
 |  * | 
 |  * RETURN:      Status | 
 |  * | 
 |  * DESCRIPTION: Display short info about objects in the namespace | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | static acpi_status | 
 | acpi_db_walk_for_object_counts(acpi_handle obj_handle, | 
 | 			       u32 nesting_level, | 
 | 			       void *context, void **return_value) | 
 | { | 
 | 	struct acpi_object_info *info = (struct acpi_object_info *)context; | 
 | 	struct acpi_namespace_node *node = | 
 | 	    (struct acpi_namespace_node *)obj_handle; | 
 |  | 
 | 	if (node->type > ACPI_TYPE_NS_NODE_MAX) { | 
 | 		acpi_os_printf("[%4.4s]: Unknown object type %X\n", | 
 | 			       node->name.ascii, node->type); | 
 | 	} else { | 
 | 		info->types[node->type]++; | 
 | 	} | 
 |  | 
 | 	return (AE_OK); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_walk_for_specific_objects | 
 |  * | 
 |  * PARAMETERS:  Callback from walk_namespace | 
 |  * | 
 |  * RETURN:      Status | 
 |  * | 
 |  * DESCRIPTION: Display short info about objects in the namespace | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | static acpi_status | 
 | acpi_db_walk_for_specific_objects(acpi_handle obj_handle, | 
 | 				  u32 nesting_level, | 
 | 				  void *context, void **return_value) | 
 | { | 
 | 	struct acpi_walk_info *info = (struct acpi_walk_info *)context; | 
 | 	struct acpi_buffer buffer; | 
 | 	acpi_status status; | 
 |  | 
 | 	info->count++; | 
 |  | 
 | 	/* Get and display the full pathname to this object */ | 
 |  | 
 | 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; | 
 | 	status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); | 
 | 	if (ACPI_FAILURE(status)) { | 
 | 		acpi_os_printf("Could Not get pathname for object %p\n", | 
 | 			       obj_handle); | 
 | 		return (AE_OK); | 
 | 	} | 
 |  | 
 | 	acpi_os_printf("%32s", (char *)buffer.pointer); | 
 | 	ACPI_FREE(buffer.pointer); | 
 |  | 
 | 	/* Dump short info about the object */ | 
 |  | 
 | 	(void)acpi_ns_dump_one_object(obj_handle, nesting_level, info, NULL); | 
 | 	return (AE_OK); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_display_objects | 
 |  * | 
 |  * PARAMETERS:  obj_type_arg        - Type of object to display | 
 |  *              display_count_arg   - Max depth to display | 
 |  * | 
 |  * RETURN:      None | 
 |  * | 
 |  * DESCRIPTION: Display objects in the namespace of the requested type | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | acpi_status acpi_db_display_objects(char *obj_type_arg, char *display_count_arg) | 
 | { | 
 | 	struct acpi_walk_info info; | 
 | 	acpi_object_type type; | 
 | 	struct acpi_object_info *object_info; | 
 | 	u32 i; | 
 | 	u32 total_objects = 0; | 
 |  | 
 | 	/* No argument means display summary/count of all object types */ | 
 |  | 
 | 	if (!obj_type_arg) { | 
 | 		object_info = | 
 | 		    ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info)); | 
 |  | 
 | 		/* Walk the namespace from the root */ | 
 |  | 
 | 		(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, | 
 | 					  ACPI_UINT32_MAX, | 
 | 					  acpi_db_walk_for_object_counts, NULL, | 
 | 					  (void *)object_info, NULL); | 
 |  | 
 | 		acpi_os_printf("\nSummary of namespace objects:\n\n"); | 
 |  | 
 | 		for (i = 0; i < ACPI_TOTAL_TYPES; i++) { | 
 | 			acpi_os_printf("%8u %s\n", object_info->types[i], | 
 | 				       acpi_ut_get_type_name(i)); | 
 |  | 
 | 			total_objects += object_info->types[i]; | 
 | 		} | 
 |  | 
 | 		acpi_os_printf("\n%8u Total namespace objects\n\n", | 
 | 			       total_objects); | 
 |  | 
 | 		ACPI_FREE(object_info); | 
 | 		return (AE_OK); | 
 | 	} | 
 |  | 
 | 	/* Get the object type */ | 
 |  | 
 | 	type = acpi_db_match_argument(obj_type_arg, acpi_db_object_types); | 
 | 	if (type == ACPI_TYPE_NOT_FOUND) { | 
 | 		acpi_os_printf("Invalid or unsupported argument\n"); | 
 | 		return (AE_OK); | 
 | 	} | 
 |  | 
 | 	acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); | 
 | 	acpi_os_printf | 
 | 	    ("Objects of type [%s] defined in the current ACPI Namespace:\n", | 
 | 	     acpi_ut_get_type_name(type)); | 
 |  | 
 | 	acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); | 
 |  | 
 | 	info.count = 0; | 
 | 	info.owner_id = ACPI_OWNER_ID_MAX; | 
 | 	info.debug_level = ACPI_UINT32_MAX; | 
 | 	info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; | 
 |  | 
 | 	/* Walk the namespace from the root */ | 
 |  | 
 | 	(void)acpi_walk_namespace(type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, | 
 | 				  acpi_db_walk_for_specific_objects, NULL, | 
 | 				  (void *)&info, NULL); | 
 |  | 
 | 	acpi_os_printf | 
 | 	    ("\nFound %u objects of type [%s] in the current ACPI Namespace\n", | 
 | 	     info.count, acpi_ut_get_type_name(type)); | 
 |  | 
 | 	acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); | 
 | 	return (AE_OK); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_integrity_walk | 
 |  * | 
 |  * PARAMETERS:  Callback from walk_namespace | 
 |  * | 
 |  * RETURN:      Status | 
 |  * | 
 |  * DESCRIPTION: Examine one NS node for valid values. | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | static acpi_status | 
 | acpi_db_integrity_walk(acpi_handle obj_handle, | 
 | 		       u32 nesting_level, void *context, void **return_value) | 
 | { | 
 | 	struct acpi_integrity_info *info = | 
 | 	    (struct acpi_integrity_info *)context; | 
 | 	struct acpi_namespace_node *node = | 
 | 	    (struct acpi_namespace_node *)obj_handle; | 
 | 	union acpi_operand_object *object; | 
 | 	u8 alias = TRUE; | 
 |  | 
 | 	info->nodes++; | 
 |  | 
 | 	/* Verify the NS node, and dereference aliases */ | 
 |  | 
 | 	while (alias) { | 
 | 		if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { | 
 | 			acpi_os_printf | 
 | 			    ("Invalid Descriptor Type for Node %p [%s] - " | 
 | 			     "is %2.2X should be %2.2X\n", node, | 
 | 			     acpi_ut_get_descriptor_name(node), | 
 | 			     ACPI_GET_DESCRIPTOR_TYPE(node), | 
 | 			     ACPI_DESC_TYPE_NAMED); | 
 | 			return (AE_OK); | 
 | 		} | 
 |  | 
 | 		if ((node->type == ACPI_TYPE_LOCAL_ALIAS) || | 
 | 		    (node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { | 
 | 			node = (struct acpi_namespace_node *)node->object; | 
 | 		} else { | 
 | 			alias = FALSE; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	if (node->type > ACPI_TYPE_LOCAL_MAX) { | 
 | 		acpi_os_printf("Invalid Object Type for Node %p, Type = %X\n", | 
 | 			       node, node->type); | 
 | 		return (AE_OK); | 
 | 	} | 
 |  | 
 | 	if (!acpi_ut_valid_nameseg(node->name.ascii)) { | 
 | 		acpi_os_printf("Invalid AcpiName for Node %p\n", node); | 
 | 		return (AE_OK); | 
 | 	} | 
 |  | 
 | 	object = acpi_ns_get_attached_object(node); | 
 | 	if (object) { | 
 | 		info->objects++; | 
 | 		if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { | 
 | 			acpi_os_printf | 
 | 			    ("Invalid Descriptor Type for Object %p [%s]\n", | 
 | 			     object, acpi_ut_get_descriptor_name(object)); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	return (AE_OK); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_check_integrity | 
 |  * | 
 |  * PARAMETERS:  None | 
 |  * | 
 |  * RETURN:      None | 
 |  * | 
 |  * DESCRIPTION: Check entire namespace for data structure integrity | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | void acpi_db_check_integrity(void) | 
 | { | 
 | 	struct acpi_integrity_info info = { 0, 0 }; | 
 |  | 
 | 	/* Search all nodes in namespace */ | 
 |  | 
 | 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, | 
 | 				  ACPI_UINT32_MAX, acpi_db_integrity_walk, NULL, | 
 | 				  (void *)&info, NULL); | 
 |  | 
 | 	acpi_os_printf("Verified %u namespace nodes with %u Objects\n", | 
 | 		       info.nodes, info.objects); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_walk_for_references | 
 |  * | 
 |  * PARAMETERS:  Callback from walk_namespace | 
 |  * | 
 |  * RETURN:      Status | 
 |  * | 
 |  * DESCRIPTION: Check if this namespace object refers to the target object | 
 |  *              that is passed in as the context value. | 
 |  * | 
 |  * Note: Currently doesn't check subobjects within the Node's object | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | static acpi_status | 
 | acpi_db_walk_for_references(acpi_handle obj_handle, | 
 | 			    u32 nesting_level, | 
 | 			    void *context, void **return_value) | 
 | { | 
 | 	union acpi_operand_object *obj_desc = | 
 | 	    (union acpi_operand_object *)context; | 
 | 	struct acpi_namespace_node *node = | 
 | 	    (struct acpi_namespace_node *)obj_handle; | 
 |  | 
 | 	/* Check for match against the namespace node itself */ | 
 |  | 
 | 	if (node == (void *)obj_desc) { | 
 | 		acpi_os_printf("Object is a Node [%4.4s]\n", | 
 | 			       acpi_ut_get_node_name(node)); | 
 | 	} | 
 |  | 
 | 	/* Check for match against the object attached to the node */ | 
 |  | 
 | 	if (acpi_ns_get_attached_object(node) == obj_desc) { | 
 | 		acpi_os_printf("Reference at Node->Object %p [%4.4s]\n", | 
 | 			       node, acpi_ut_get_node_name(node)); | 
 | 	} | 
 |  | 
 | 	return (AE_OK); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_find_references | 
 |  * | 
 |  * PARAMETERS:  object_arg      - String with hex value of the object | 
 |  * | 
 |  * RETURN:      None | 
 |  * | 
 |  * DESCRIPTION: Search namespace for all references to the input object | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | void acpi_db_find_references(char *object_arg) | 
 | { | 
 | 	union acpi_operand_object *obj_desc; | 
 | 	acpi_size address; | 
 |  | 
 | 	/* Convert string to object pointer */ | 
 |  | 
 | 	address = strtoul(object_arg, NULL, 16); | 
 | 	obj_desc = ACPI_TO_POINTER(address); | 
 |  | 
 | 	/* Search all nodes in namespace */ | 
 |  | 
 | 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, | 
 | 				  ACPI_UINT32_MAX, acpi_db_walk_for_references, | 
 | 				  NULL, (void *)obj_desc, NULL); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_bus_walk | 
 |  * | 
 |  * PARAMETERS:  Callback from walk_namespace | 
 |  * | 
 |  * RETURN:      Status | 
 |  * | 
 |  * DESCRIPTION: Display info about device objects that have a corresponding | 
 |  *              _PRT method. | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | static acpi_status | 
 | acpi_db_bus_walk(acpi_handle obj_handle, | 
 | 		 u32 nesting_level, void *context, void **return_value) | 
 | { | 
 | 	struct acpi_namespace_node *node = | 
 | 	    (struct acpi_namespace_node *)obj_handle; | 
 | 	acpi_status status; | 
 | 	struct acpi_buffer buffer; | 
 | 	struct acpi_namespace_node *temp_node; | 
 | 	struct acpi_device_info *info; | 
 | 	u32 i; | 
 |  | 
 | 	if ((node->type != ACPI_TYPE_DEVICE) && | 
 | 	    (node->type != ACPI_TYPE_PROCESSOR)) { | 
 | 		return (AE_OK); | 
 | 	} | 
 |  | 
 | 	/* Exit if there is no _PRT under this device */ | 
 |  | 
 | 	status = acpi_get_handle(node, METHOD_NAME__PRT, | 
 | 				 ACPI_CAST_PTR(acpi_handle, &temp_node)); | 
 | 	if (ACPI_FAILURE(status)) { | 
 | 		return (AE_OK); | 
 | 	} | 
 |  | 
 | 	/* Get the full path to this device object */ | 
 |  | 
 | 	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; | 
 | 	status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE); | 
 | 	if (ACPI_FAILURE(status)) { | 
 | 		acpi_os_printf("Could Not get pathname for object %p\n", | 
 | 			       obj_handle); | 
 | 		return (AE_OK); | 
 | 	} | 
 |  | 
 | 	status = acpi_get_object_info(obj_handle, &info); | 
 | 	if (ACPI_FAILURE(status)) { | 
 | 		return (AE_OK); | 
 | 	} | 
 |  | 
 | 	/* Display the full path */ | 
 |  | 
 | 	acpi_os_printf("%-32s Type %X", (char *)buffer.pointer, node->type); | 
 | 	ACPI_FREE(buffer.pointer); | 
 |  | 
 | 	if (info->flags & ACPI_PCI_ROOT_BRIDGE) { | 
 | 		acpi_os_printf(" - Is PCI Root Bridge"); | 
 | 	} | 
 | 	acpi_os_printf("\n"); | 
 |  | 
 | 	/* _PRT info */ | 
 |  | 
 | 	acpi_os_printf("_PRT: %p\n", temp_node); | 
 |  | 
 | 	/* Dump _ADR, _HID, _UID, _CID */ | 
 |  | 
 | 	if (info->valid & ACPI_VALID_ADR) { | 
 | 		acpi_os_printf("_ADR: %8.8X%8.8X\n", | 
 | 			       ACPI_FORMAT_UINT64(info->address)); | 
 | 	} else { | 
 | 		acpi_os_printf("_ADR: <Not Present>\n"); | 
 | 	} | 
 |  | 
 | 	if (info->valid & ACPI_VALID_HID) { | 
 | 		acpi_os_printf("_HID: %s\n", info->hardware_id.string); | 
 | 	} else { | 
 | 		acpi_os_printf("_HID: <Not Present>\n"); | 
 | 	} | 
 |  | 
 | 	if (info->valid & ACPI_VALID_UID) { | 
 | 		acpi_os_printf("_UID: %s\n", info->unique_id.string); | 
 | 	} else { | 
 | 		acpi_os_printf("_UID: <Not Present>\n"); | 
 | 	} | 
 |  | 
 | 	if (info->valid & ACPI_VALID_CID) { | 
 | 		for (i = 0; i < info->compatible_id_list.count; i++) { | 
 | 			acpi_os_printf("_CID: %s\n", | 
 | 				       info->compatible_id_list.ids[i].string); | 
 | 		} | 
 | 	} else { | 
 | 		acpi_os_printf("_CID: <Not Present>\n"); | 
 | 	} | 
 |  | 
 | 	ACPI_FREE(info); | 
 | 	return (AE_OK); | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  * | 
 |  * FUNCTION:    acpi_db_get_bus_info | 
 |  * | 
 |  * PARAMETERS:  None | 
 |  * | 
 |  * RETURN:      None | 
 |  * | 
 |  * DESCRIPTION: Display info about system busses. | 
 |  * | 
 |  ******************************************************************************/ | 
 |  | 
 | void acpi_db_get_bus_info(void) | 
 | { | 
 | 	/* Search all nodes in namespace */ | 
 |  | 
 | 	(void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, | 
 | 				  ACPI_UINT32_MAX, acpi_db_bus_walk, NULL, NULL, | 
 | 				  NULL); | 
 | } |