acpi_status acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, union acpi_parse_object *op, struct acpi_namespace_node *method_node, u8 * aml_start, u32 aml_length, struct acpi_evaluate_info *info, u8 pass_number) { acpi_status status; struct acpi_parse_state *parser_state = &walk_state->parser_state; union acpi_parse_object *extra_op; ACPI_FUNCTION_TRACE(ds_init_aml_walk); walk_state->parser_state.aml = walk_state->parser_state.aml_start = aml_start; walk_state->parser_state.aml_end = walk_state->parser_state.pkg_end = aml_start + aml_length; /* The next_op of the next_walk will be the beginning of the method */ walk_state->next_op = NULL; walk_state->pass_number = pass_number; if (info) { walk_state->params = info->parameters; walk_state->caller_return_desc = &info->return_object; } status = acpi_ps_init_scope(&walk_state->parser_state, op); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (method_node) { walk_state->parser_state.start_node = method_node; walk_state->walk_type = ACPI_WALK_METHOD; walk_state->method_node = method_node; walk_state->method_desc = acpi_ns_get_attached_object(method_node); /* Push start scope on scope stack and make it current */ status = acpi_ds_scope_stack_push(method_node, ACPI_TYPE_METHOD, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Init the method arguments */ status = acpi_ds_method_data_init_args(walk_state->params, ACPI_METHOD_NUM_ARGS, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } else { /* * Setup the current scope. * Find a Named Op that has a namespace node associated with it. * search upwards from this Op. Current scope is the first * Op with a namespace node. */ extra_op = parser_state->start_op; while (extra_op && !extra_op->common.node) { extra_op = extra_op->common.parent; } if (!extra_op) { parser_state->start_node = NULL; } else { parser_state->start_node = extra_op->common.node; } if (parser_state->start_node) { /* Push start scope on scope stack and make it current */ status = acpi_ds_scope_stack_push(parser_state->start_node, parser_state->start_node-> type, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } } status = acpi_ds_init_callbacks(walk_state, pass_number); return_ACPI_STATUS(status); }
ACPI_STATUS acpi_ds_call_control_method ( ACPI_WALK_LIST *walk_list, ACPI_WALK_STATE *this_walk_state, ACPI_PARSE_OBJECT *op) { ACPI_STATUS status; ACPI_NAMESPACE_NODE *method_node; ACPI_OPERAND_OBJECT *obj_desc; ACPI_WALK_STATE *next_walk_state; ACPI_PARSE_STATE *parser_state; u32 i; /* * Get the namespace entry for the control method we are about to call */ method_node = this_walk_state->method_call_node; if (!method_node) { return (AE_NULL_ENTRY); } obj_desc = acpi_ns_get_attached_object (method_node); if (!obj_desc) { return (AE_NULL_OBJECT); } /* Init for new method, wait on concurrency semaphore */ status = acpi_ds_begin_method_execution (method_node, obj_desc); if (ACPI_FAILURE (status)) { return (status); } /* Create and initialize a new parser state */ parser_state = acpi_ps_create_state (obj_desc->method.pcode, obj_desc->method.pcode_length); if (!parser_state) { return (AE_NO_MEMORY); } acpi_ps_init_scope (parser_state, NULL); parser_state->start_node = method_node; /* Create a new state for the preempting walk */ next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, NULL, obj_desc, walk_list); if (!next_walk_state) { /* TBD: delete parser state */ return (AE_NO_MEMORY); } next_walk_state->walk_type = WALK_METHOD; next_walk_state->method_node = method_node; next_walk_state->parser_state = parser_state; next_walk_state->parse_flags = this_walk_state->parse_flags; next_walk_state->descending_callback = this_walk_state->descending_callback; next_walk_state->ascending_callback = this_walk_state->ascending_callback; /* The Next_op of the Next_walk will be the beginning of the method */ /* TBD: [Restructure] -- obsolete? */ next_walk_state->next_op = NULL; /* Open a new scope */ status = acpi_ds_scope_stack_push (method_node, ACPI_TYPE_METHOD, next_walk_state); if (ACPI_FAILURE (status)) { goto cleanup; } /* * Initialize the arguments for the method. The resolved * arguments were put on the previous walk state's operand * stack. Operands on the previous walk state stack always * start at index 0. */ status = acpi_ds_method_data_init_args (&this_walk_state->operands[0], this_walk_state->num_operands, next_walk_state); if (ACPI_FAILURE (status)) { goto cleanup; } /* Create and init a Root Node */ op = acpi_ps_alloc_op (AML_SCOPE_OP); if (!op) { return (AE_NO_MEMORY); } status = acpi_ps_parse_aml (op, obj_desc->method.pcode, obj_desc->method.pcode_length, ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, method_node, NULL, NULL, acpi_ds_load1_begin_op, acpi_ds_load1_end_op); acpi_ps_delete_parse_tree (op); /* * Delete the operands on the previous walkstate operand stack * (they were copied to new objects) */ for (i = 0; i < obj_desc->method.param_count; i++) { acpi_cm_remove_reference (this_walk_state->operands [i]); this_walk_state->operands [i] = NULL; } /* Clear the operand stack */ this_walk_state->num_operands = 0; return (AE_OK); /* On error, we must delete the new walk state */ cleanup: acpi_ds_terminate_control_method (next_walk_state); acpi_ds_delete_walk_state (next_walk_state); return (status); }