psloop.c
来自「linux 内核源代码」· C语言 代码 · 共 1,057 行 · 第 1/2 页
C
1,057 行
* Status - Parse status before complete Op * * RETURN: Status * * DESCRIPTION: Complete Op * ******************************************************************************/static acpi_statusacpi_ps_complete_op(struct acpi_walk_state *walk_state, union acpi_parse_object **op, acpi_status status){ acpi_status status2; ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); /* * Finished one argument of the containing scope */ walk_state->parser_state.scope->parse_scope.arg_count--; /* Close this Op (will result in parse subtree deletion) */ status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } *op = NULL; switch (status) { case AE_OK: break; case AE_CTRL_TRANSFER: /* We are about to transfer to a called method */ walk_state->prev_op = NULL; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); case AE_CTRL_END: acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); if (*op) { walk_state->op = *op; walk_state->op_info = acpi_ps_get_opcode_info((*op)->common.aml_opcode); walk_state->opcode = (*op)->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, *op, status); status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } status = AE_OK; break; case AE_CTRL_BREAK: case AE_CTRL_CONTINUE: /* Pop off scopes until we find the While */ while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); if ((*op)->common.aml_opcode != AML_WHILE_OP) { status2 = acpi_ds_result_stack_pop(walk_state); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } } /* Close this iteration of the While loop */ walk_state->op = *op; walk_state->op_info = acpi_ps_get_opcode_info((*op)->common.aml_opcode); walk_state->opcode = (*op)->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, *op, status); status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } status = AE_OK; break; case AE_CTRL_TERMINATE: /* Clean up */ do { if (*op) { status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } status2 = acpi_ds_result_stack_pop(walk_state); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } acpi_ut_delete_generic_state (acpi_ut_pop_generic_state (&walk_state->control_state)); } acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } while (*op); return_ACPI_STATUS(AE_OK); default: /* All other non-AE_OK status */ do { if (*op) { status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } while (*op);#if 0 /* * TBD: Cleanup parse ops on error */ if (*op == NULL) { acpi_ps_pop_scope(parser_state, op, &walk_state->arg_types, &walk_state->arg_count); }#endif walk_state->prev_op = NULL; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); } /* This scope complete? */ if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); } else { *op = NULL; } return_ACPI_STATUS(AE_OK);}/******************************************************************************* * * FUNCTION: acpi_ps_complete_final_op * * PARAMETERS: walk_state - Current state * Op - Current Op * Status - Current parse status before complete last * Op * * RETURN: Status * * DESCRIPTION: Complete last Op. * ******************************************************************************/static acpi_statusacpi_ps_complete_final_op(struct acpi_walk_state *walk_state, union acpi_parse_object *op, acpi_status status){ acpi_status status2; ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); /* * Complete the last Op (if not completed), and clear the scope stack. * It is easily possible to end an AML "package" with an unbounded number * of open scopes (such as when several ASL blocks are closed with * sequential closing braces). We want to terminate each one cleanly. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", op)); do { if (op) { if (walk_state->ascending_callback != NULL) { walk_state->op = op; walk_state->op_info = acpi_ps_get_opcode_info(op->common. aml_opcode); walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = acpi_ps_complete_op(walk_state, &op, AE_OK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } if (status == AE_CTRL_TERMINATE) { status = AE_OK; /* Clean up */ do { if (op) { status2 = acpi_ps_complete_this_op (walk_state, op); if (ACPI_FAILURE (status2)) { return_ACPI_STATUS (status2); } } acpi_ps_pop_scope(& (walk_state-> parser_state), &op, &walk_state-> arg_types, &walk_state-> arg_count); } while (op); return_ACPI_STATUS(status); } else if (ACPI_FAILURE(status)) { /* First error is most important */ (void) acpi_ps_complete_this_op(walk_state, op); return_ACPI_STATUS(status); } } status2 = acpi_ps_complete_this_op(walk_state, op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } acpi_ps_pop_scope(&(walk_state->parser_state), &op, &walk_state->arg_types, &walk_state->arg_count); } while (op); return_ACPI_STATUS(status);}/******************************************************************************* * * FUNCTION: acpi_ps_parse_loop * * PARAMETERS: walk_state - Current state * * RETURN: Status * * DESCRIPTION: Parse AML (pointed to by the current parser state) and return * a tree of ops. * ******************************************************************************/acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state){ acpi_status status = AE_OK; union acpi_parse_object *op = NULL; /* current op */ struct acpi_parse_state *parser_state; u8 *aml_op_start = NULL; ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state); if (walk_state->descending_callback == NULL) { return_ACPI_STATUS(AE_BAD_PARAMETER); } parser_state = &walk_state->parser_state; walk_state->arg_types = 0;#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { /* We are restarting a preempted control method */ if (acpi_ps_has_completed_scope(parser_state)) { /* * We must check if a predicate to an IF or WHILE statement * was just completed */ if ((parser_state->scope->parse_scope.op) && ((parser_state->scope->parse_scope.op->common. aml_opcode == AML_IF_OP) || (parser_state->scope->parse_scope.op->common. aml_opcode == AML_WHILE_OP)) && (walk_state->control_state) && (walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING)) { /* * A predicate was just completed, get the value of the * predicate and branch based on that value */ walk_state->op = NULL; status = acpi_ds_get_predicate_value(walk_state, ACPI_TO_POINTER (TRUE)); if (ACPI_FAILURE(status) && ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) { if (status == AE_AML_NO_RETURN_VALUE) { ACPI_EXCEPTION((AE_INFO, status, "Invoked method did not return a value")); } ACPI_EXCEPTION((AE_INFO, status, "GetPredicate Failed")); return_ACPI_STATUS(status); } status = acpi_ps_next_parse_state(walk_state, op, status); } acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); } else if (walk_state->prev_op) { /* We were in the middle of an op */ op = walk_state->prev_op; walk_state->arg_types = walk_state->prev_arg_types; } }#endif /* Iterative parsing loop, while there is more AML to process: */ while ((parser_state->aml < parser_state->aml_end) || (op)) { aml_op_start = parser_state->aml; if (!op) { status = acpi_ps_create_op(walk_state, aml_op_start, &op); if (ACPI_FAILURE(status)) { if (status == AE_CTRL_PARSE_CONTINUE) { continue; } if (status == AE_CTRL_PARSE_PENDING) { status = AE_OK; } status = acpi_ps_complete_op(walk_state, &op, status); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } continue; } op->common.aml_offset = walk_state->aml_offset; if (walk_state->op_info) { ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", (u32) op->common.aml_opcode, walk_state->op_info->name, op, parser_state->aml, op->common.aml_offset)); } } /* * Start arg_count at zero because we don't know if there are * any args yet */ walk_state->arg_count = 0; /* Are there any arguments that must be processed? */ if (walk_state->arg_types) { /* Get arguments */ status = acpi_ps_get_arguments(walk_state, aml_op_start, op); if (ACPI_FAILURE(status)) { status = acpi_ps_complete_op(walk_state, &op, status); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } continue; } } /* Check for arguments that need to be processed */ if (walk_state->arg_count) { /* * There are arguments (complex ones), push Op and * prepare for argument */ status = acpi_ps_push_scope(parser_state, op, walk_state->arg_types, walk_state->arg_count); if (ACPI_FAILURE(status)) { status = acpi_ps_complete_op(walk_state, &op, status); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } continue; } op = NULL; continue; } /* * All arguments have been processed -- Op is complete, * prepare for next */ walk_state->op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); if (walk_state->op_info->flags & AML_NAMED) { if (acpi_gbl_depth) { acpi_gbl_depth--; } if (op->common.aml_opcode == AML_REGION_OP) { /* * Skip parsing of control method or opregion body, * because we don't have enough info in the first pass * to parse them correctly. * * Completed parsing an op_region declaration, we now * know the length. */ op->named.length = (u32) (parser_state->aml - op->named.data); } } if (walk_state->op_info->flags & AML_CREATE) { /* * Backup to beginning of create_xXXfield declaration (1 for * Opcode) * * body_length is unknown until we parse the body */ op->named.length = (u32) (parser_state->aml - op->named.data); } /* This op complete, notify the dispatcher */ if (walk_state->ascending_callback != NULL) { walk_state->op = op; walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = AE_OK; } } status = acpi_ps_complete_op(walk_state, &op, status); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* while parser_state->Aml */ status = acpi_ps_complete_final_op(walk_state, op, status); return_ACPI_STATUS(status);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?