diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
commit | 2c3c1048746a4622d8c89a29670120dc8fab93c4 (patch) | |
tree | 848558de17fb3008cdf4d861b01ac7781903ce39 /drivers/acpi/acpica/dbnames.c | |
parent | Initial commit. (diff) | |
download | linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.tar.xz linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.zip |
Adding upstream version 6.1.76.upstream/6.1.76
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/acpi/acpica/dbnames.c')
-rw-r--r-- | drivers/acpi/acpica/dbnames.c | 1035 |
1 files changed, 1035 insertions, 0 deletions
diff --git a/drivers/acpi/acpica/dbnames.c b/drivers/acpi/acpica/dbnames.c new file mode 100644 index 000000000..b91155ea9 --- /dev/null +++ b/drivers/acpi/acpica/dbnames.c @@ -0,0 +1,1035 @@ +// 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" +#include "acinterp.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_NAMESEG_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_fields + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Display short info about objects in the namespace + * + ******************************************************************************/ + +static acpi_status +acpi_db_walk_for_fields(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value) +{ + union acpi_object *ret_value; + struct acpi_region_walk_info *info = + (struct acpi_region_walk_info *)context; + struct acpi_buffer buffer; + acpi_status status; + struct acpi_namespace_node *node = acpi_ns_validate_handle(obj_handle); + + if (!node) { + return (AE_OK); + } + if (node->object->field.region_obj->region.space_id != + info->address_space_id) { + return (AE_OK); + } + + 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("%s ", (char *)buffer.pointer); + ACPI_FREE(buffer.pointer); + + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + acpi_evaluate_object(obj_handle, NULL, NULL, &buffer); + + /* + * Since this is a field unit, surround the output in braces + */ + acpi_os_printf("{"); + + ret_value = (union acpi_object *)buffer.pointer; + switch (ret_value->type) { + case ACPI_TYPE_INTEGER: + + acpi_os_printf("%8.8X%8.8X", + ACPI_FORMAT_UINT64(ret_value->integer.value)); + break; + + case ACPI_TYPE_BUFFER: + + acpi_ut_dump_buffer(ret_value->buffer.pointer, + ret_value->buffer.length, + DB_DISPLAY_DATA_ONLY | DB_BYTE_DISPLAY, 0); + break; + + default: + + break; + } + acpi_os_printf("}\n"); + + ACPI_FREE(buffer.pointer); + + 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)); + + if (!object_info) + return (AE_NO_MEMORY); + + /* 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_display_fields + * + * 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_fields(u32 address_space_id) +{ + struct acpi_region_walk_info info; + + 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; + info.address_space_id = address_space_id; + + /* Walk the namespace from the root */ + + (void)acpi_walk_namespace(ACPI_TYPE_LOCAL_REGION_FIELD, + ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + acpi_db_walk_for_fields, NULL, (void *)&info, + NULL); + + 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 buses. + * + ******************************************************************************/ + +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); +} |