From 6218ab30da72717f906576fd5e63c15b990235f1 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 7 Oct 2020 19:54:01 -0700 Subject: [PATCH] ACPICA: Debugger: Add a new command: "ALL " This command will execute/evaluate all objects with a match to the argument. ACPICA commit a1a32ec054f067d1617067e2bafb0a27a8728e07 Link: https://github.com/acpica/acpica/commit/a1a32ec0 Signed-off-by: Bob Moore Signed-off-by: Erik Kaneda Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acdebug.h | 4 + drivers/acpi/acpica/dbexec.c | 39 ++++++-- drivers/acpi/acpica/dbinput.c | 12 +++ drivers/acpi/acpica/dbmethod.c | 167 ++++++++++++++++++++++++++++----- 4 files changed, 188 insertions(+), 34 deletions(-) diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index a676daaa2da5..f8a3abdfe250 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -37,12 +37,14 @@ struct acpi_db_argument_info { struct acpi_db_execute_walk { u32 count; u32 max_count; + char name_seg[ACPI_NAMESEG_SIZE + 1]; }; #define PARAM_LIST(pl) pl #define EX_NO_SINGLE_STEP 1 #define EX_SINGLE_STEP 2 +#define EX_ALL 4 /* * dbxface - external debugger interfaces @@ -124,6 +126,8 @@ void acpi_db_disassemble_aml(char *statements, union acpi_parse_object *op); void acpi_db_evaluate_predefined_names(void); +void acpi_db_evaluate_all(char *name_seg); + /* * dbnames - namespace commands */ diff --git a/drivers/acpi/acpica/dbexec.c b/drivers/acpi/acpica/dbexec.c index 4027eaab18a4..d3a9521e2dc8 100644 --- a/drivers/acpi/acpica/dbexec.c +++ b/drivers/acpi/acpica/dbexec.c @@ -86,7 +86,8 @@ void acpi_db_delete_objects(u32 count, union acpi_object *objects) * * RETURN: Status * - * DESCRIPTION: Execute a control method. + * DESCRIPTION: Execute a control method. Used to evaluate objects via the + * "EXECUTE" or "EVALUATE" commands. * ******************************************************************************/ @@ -314,11 +315,12 @@ acpi_db_execution_walk(acpi_handle obj_handle, status = acpi_evaluate_object(node, NULL, NULL, &return_obj); + acpi_gbl_method_executing = FALSE; + acpi_os_printf("Evaluation of [%4.4s] returned %s\n", acpi_ut_get_node_name(node), acpi_format_exception(status)); - acpi_gbl_method_executing = FALSE; return (AE_OK); } @@ -334,7 +336,8 @@ acpi_db_execution_walk(acpi_handle obj_handle, * RETURN: None * * DESCRIPTION: Execute a control method. Name is relative to the current - * scope. + * scope. Function used for the "EXECUTE", "EVALUATE", and + * "ALL" commands * ******************************************************************************/ @@ -372,6 +375,12 @@ acpi_db_execute(char *name, char **args, acpi_object_type *types, u32 flags) return; } + if ((flags & EX_ALL) && (strlen(name) > 4)) { + acpi_os_printf("Input name (%s) must be a 4-char NameSeg\n", + name); + return; + } + name_string = ACPI_ALLOCATE(strlen(name) + 1); if (!name_string) { return; @@ -389,13 +398,24 @@ acpi_db_execute(char *name, char **args, acpi_object_type *types, u32 flags) return; } - acpi_gbl_db_method_info.name = name_string; - acpi_gbl_db_method_info.args = args; - acpi_gbl_db_method_info.types = types; - acpi_gbl_db_method_info.flags = flags; + /* Command (ALL ) to execute all methods of a particular name */ - return_obj.pointer = NULL; - return_obj.length = ACPI_ALLOCATE_BUFFER; + else if (flags & EX_ALL) { + acpi_gbl_db_method_info.name = name_string; + return_obj.pointer = NULL; + return_obj.length = ACPI_ALLOCATE_BUFFER; + acpi_db_evaluate_all(name_string); + ACPI_FREE(name_string); + return; + } else { + acpi_gbl_db_method_info.name = name_string; + acpi_gbl_db_method_info.args = args; + acpi_gbl_db_method_info.types = types; + acpi_gbl_db_method_info.flags = flags; + + return_obj.pointer = NULL; + return_obj.length = ACPI_ALLOCATE_BUFFER; + } status = acpi_db_execute_setup(&acpi_gbl_db_method_info); if (ACPI_FAILURE(status)) { @@ -450,6 +470,7 @@ acpi_db_execute(char *name, char **args, acpi_object_type *types, u32 flags) (u32)return_obj.length); acpi_db_dump_external_object(return_obj.pointer, 1); + acpi_os_printf("\n"); /* Dump a _PLD buffer if present */ diff --git a/drivers/acpi/acpica/dbinput.c b/drivers/acpi/acpica/dbinput.c index 568d1b0b1f5d..2952856b8a67 100644 --- a/drivers/acpi/acpica/dbinput.c +++ b/drivers/acpi/acpica/dbinput.c @@ -37,6 +37,7 @@ acpi_db_match_command_help(const char *command, enum acpi_ex_debugger_commands { CMD_NOT_FOUND = 0, CMD_NULL, + CMD_ALL, CMD_ALLOCATIONS, CMD_ARGS, CMD_ARGUMENTS, @@ -115,6 +116,7 @@ enum acpi_ex_debugger_commands { static const struct acpi_db_command_info acpi_gbl_db_commands[] = { {"", 0}, {"", 0}, + {"ALL", 1}, {"ALLOCATIONS", 0}, {"ARGS", 0}, {"ARGUMENTS", 0}, @@ -222,6 +224,7 @@ static const struct acpi_db_command_help acpi_gbl_db_command_help[] = { {1, " Type ", "Display object type\n"}, {0, "\nControl Method Execution:", "\n"}, + {1, " All ", "Evaluate all objects named NameSeg\n"}, {1, " Evaluate [Arguments]", "Evaluate object or control method\n"}, {1, " Execute [Arguments]", "Synonym for Evaluate\n"}, @@ -740,6 +743,15 @@ acpi_db_command_dispatch(char *input_buffer, } break; + case CMD_ALL: + + acpi_os_printf("Executing all objects with NameSeg: %s\n", + acpi_gbl_db_args[1]); + acpi_db_execute(acpi_gbl_db_args[1], &acpi_gbl_db_args[2], + &acpi_gbl_db_arg_types[2], + EX_NO_SINGLE_STEP | EX_ALL); + break; + case CMD_ALLOCATIONS: #ifdef ACPI_DBG_TRACK_ALLOCATIONS diff --git a/drivers/acpi/acpica/dbmethod.c b/drivers/acpi/acpica/dbmethod.c index 4e48a7de7413..889d13828e49 100644 --- a/drivers/acpi/acpica/dbmethod.c +++ b/drivers/acpi/acpica/dbmethod.c @@ -21,6 +21,8 @@ static acpi_status acpi_db_walk_for_execute(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value); +static acpi_status acpi_db_evaluate_object(struct acpi_namespace_node *node); + /******************************************************************************* * * FUNCTION: acpi_db_set_method_breakpoint @@ -346,42 +348,26 @@ acpi_status acpi_db_disassemble_method(char *name) /******************************************************************************* * - * FUNCTION: acpi_db_walk_for_execute + * FUNCTION: acpi_db_evaluate_object * - * PARAMETERS: Callback from walk_namespace + * PARAMETERS: node - Namespace node for the object * * RETURN: Status * - * DESCRIPTION: Batch execution module. Currently only executes predefined - * ACPI names. + * DESCRIPTION: Main execution function for the Evaluate/Execute/All debugger + * commands. * ******************************************************************************/ -static acpi_status -acpi_db_walk_for_execute(acpi_handle obj_handle, - u32 nesting_level, void *context, void **return_value) +static acpi_status acpi_db_evaluate_object(struct acpi_namespace_node *node) { - struct acpi_namespace_node *node = - (struct acpi_namespace_node *)obj_handle; - struct acpi_db_execute_walk *info = - (struct acpi_db_execute_walk *)context; - struct acpi_buffer return_obj; - acpi_status status; char *pathname; u32 i; struct acpi_device_info *obj_info; struct acpi_object_list param_objects; union acpi_object params[ACPI_METHOD_NUM_ARGS]; - const union acpi_predefined_info *predefined; - - predefined = acpi_ut_match_predefined_method(node->name.ascii); - if (!predefined) { - return (AE_OK); - } - - if (node->type == ACPI_TYPE_LOCAL_SCOPE) { - return (AE_OK); - } + struct acpi_buffer return_obj; + acpi_status status; pathname = acpi_ns_get_external_pathname(node); if (!pathname) { @@ -390,7 +376,7 @@ acpi_db_walk_for_execute(acpi_handle obj_handle, /* Get the object info for number of method parameters */ - status = acpi_get_object_info(obj_handle, &obj_info); + status = acpi_get_object_info(node, &obj_info); if (ACPI_FAILURE(status)) { ACPI_FREE(pathname); return (status); @@ -421,14 +407,67 @@ acpi_db_walk_for_execute(acpi_handle obj_handle, acpi_gbl_method_executing = TRUE; status = acpi_evaluate_object(node, NULL, ¶m_objects, &return_obj); + acpi_gbl_method_executing = FALSE; acpi_os_printf("%-32s returned %s\n", pathname, acpi_format_exception(status)); - acpi_gbl_method_executing = FALSE; + if (return_obj.length) { + acpi_os_printf("Evaluation of %s returned object %p, " + "external buffer length %X\n", + pathname, return_obj.pointer, + (u32)return_obj.length); + + acpi_db_dump_external_object(return_obj.pointer, 1); + acpi_os_printf("\n"); + } + ACPI_FREE(pathname); /* Ignore status from method execution */ + return (AE_OK); + + /* Update count, check if we have executed enough methods */ + +} + +/******************************************************************************* + * + * FUNCTION: acpi_db_walk_for_execute + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Batch execution function. Evaluates all "predefined" objects -- + * the nameseg begins with an underscore. + * + ******************************************************************************/ + +static acpi_status +acpi_db_walk_for_execute(acpi_handle obj_handle, + u32 nesting_level, void *context, void **return_value) +{ + struct acpi_namespace_node *node = + (struct acpi_namespace_node *)obj_handle; + struct acpi_db_execute_walk *info = + (struct acpi_db_execute_walk *)context; + acpi_status status; + const union acpi_predefined_info *predefined; + + predefined = acpi_ut_match_predefined_method(node->name.ascii); + if (!predefined) { + return (AE_OK); + } + + if (node->type == ACPI_TYPE_LOCAL_SCOPE) { + return (AE_OK); + } + + acpi_db_evaluate_object(node); + + /* Ignore status from object evaluation */ + status = AE_OK; /* Update count, check if we have executed enough methods */ @@ -441,6 +480,52 @@ acpi_db_walk_for_execute(acpi_handle obj_handle, return (status); } +/******************************************************************************* + * + * FUNCTION: acpi_db_walk_for_execute_all + * + * PARAMETERS: Callback from walk_namespace + * + * RETURN: Status + * + * DESCRIPTION: Batch execution function. Evaluates all objects whose path ends + * with the nameseg "Info->NameSeg". Used for the "ALL" command. + * + ******************************************************************************/ + +static acpi_status +acpi_db_walk_for_execute_all(acpi_handle obj_handle, + u32 nesting_level, + void *context, void **return_value) +{ + struct acpi_namespace_node *node = + (struct acpi_namespace_node *)obj_handle; + struct acpi_db_execute_walk *info = + (struct acpi_db_execute_walk *)context; + acpi_status status; + + if (!ACPI_COMPARE_NAMESEG(node->name.ascii, info->name_seg)) { + return (AE_OK); + } + + if (node->type == ACPI_TYPE_LOCAL_SCOPE) { + return (AE_OK); + } + + /* Now evaluate the input object (node) */ + + acpi_db_evaluate_object(node); + + /* Ignore status from method execution */ + + status = AE_OK; + + /* Update count of executed methods/objects */ + + info->count++; + return (status); +} + /******************************************************************************* * * FUNCTION: acpi_db_evaluate_predefined_names @@ -470,3 +555,35 @@ void acpi_db_evaluate_predefined_names(void) acpi_os_printf("Evaluated %u predefined names in the namespace\n", info.count); } + +/******************************************************************************* + * + * FUNCTION: acpi_db_evaluate_all + * + * PARAMETERS: none_acpi_gbl_db_method_info + * + * RETURN: None + * + * DESCRIPTION: Namespace batch execution. Implements the "ALL" command. + * Execute all namepaths whose final nameseg matches the + * input nameseg. + * + ******************************************************************************/ + +void acpi_db_evaluate_all(char *name_seg) +{ + struct acpi_db_execute_walk info; + + info.count = 0; + info.max_count = ACPI_UINT32_MAX; + ACPI_COPY_NAMESEG(info.name_seg, name_seg); + info.name_seg[ACPI_NAMESEG_SIZE] = 0; + + /* Search all nodes in namespace */ + + (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, acpi_db_walk_for_execute_all, + NULL, (void *)&info, NULL); + + acpi_os_printf("Evaluated %u names in the namespace\n", info.count); +}