📄 psparse.c
字号:
parser_state->aml = walk_state->aml_last_while;
break;
case AE_CTRL_TRUE:
/*
* Predicate of an IF was true, and we are at the matching ELSE.
* Just close out this package
*
* Note: Parser_state->Aml is modified by the package length procedure
* TBD: [Investigate] perhaps it shouldn't, too much trouble
*/
start = parser_state->aml;
package_length = acpi_ps_get_next_package_length (parser_state);
parser_state->aml = start + package_length;
break;
case AE_CTRL_FALSE:
/*
* Either an IF/WHILE Predicate was false or we encountered a BREAK
* opcode. In both cases, we do not execute the rest of the
* package; We simply close out the parent (finishing the walk of
* this branch of the tree) and continue execution at the parent
* level.
*/
parser_state->aml = parser_state->scope->parse_scope.pkg_end;
/* In the case of a BREAK, just force a predicate (if any) to FALSE */
walk_state->control_state->common.value = FALSE;
status = AE_CTRL_END;
break;
case AE_CTRL_TRANSFER:
/*
* A method call (invocation) -- transfer control
*/
status = AE_CTRL_TRANSFER;
walk_state->prev_op = op;
walk_state->method_call_op = op;
walk_state->method_call_node = (op->value.arg)->node;
/* Will return value (if any) be used by the caller? */
walk_state->return_used = acpi_ds_is_result_used (op, walk_state);
break;
default:
status = callback_status;
if ((callback_status & AE_CODE_MASK) == AE_CODE_CONTROL) {
status = AE_OK;
}
break;
}
return (status);
}
/*******************************************************************************
*
* FUNCTION: Acpi_ps_parse_loop
*
* PARAMETERS: Parser_state - Current parser state object
*
* RETURN: Status
*
* DESCRIPTION: Parse AML (pointed to by the current parser state) and return
* a tree of ops.
*
******************************************************************************/
ACPI_STATUS
acpi_ps_parse_loop (
ACPI_WALK_STATE *walk_state)
{
ACPI_STATUS status = AE_OK;
ACPI_PARSE_OBJECT *op = NULL; /* current op */
ACPI_OPCODE_INFO *op_info;
ACPI_PARSE_OBJECT *arg = NULL;
ACPI_PARSE2_OBJECT *deferred_op;
u32 arg_count; /* push for fixed or var args */
u32 arg_types = 0;
ACPI_PTRDIFF aml_offset;
u16 opcode;
ACPI_PARSE_OBJECT pre_op;
ACPI_PARSE_STATE *parser_state;
u8 *aml_op_start;
parser_state = walk_state->parser_state;
#ifndef PARSER_ONLY
if (walk_state->walk_type & 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->opcode == AML_IF_OP) ||
(parser_state->scope->parse_scope.op->opcode == AML_WHILE_OP)) &&
(walk_state->control_state) &&
(walk_state->control_state->common.state ==
CONTROL_PREDICATE_EXECUTING)) {
/*
* A predicate was just completed, get the value of the
* predicate and branch based on that value
*/
status = acpi_ds_get_predicate_value (walk_state, NULL, TRUE);
if (ACPI_FAILURE (status) &&
((status & AE_CODE_MASK) != AE_CODE_CONTROL)) {
return (status);
}
status = acpi_ps_next_parse_state (walk_state, op, status);
}
acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
}
else if (walk_state->prev_op) {
/* We were in the middle of an op */
op = walk_state->prev_op;
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)) {
if (!op) {
/* Get the next opcode from the AML stream */
aml_op_start = parser_state->aml;
aml_offset = parser_state->aml - parser_state->aml_start;
opcode = acpi_ps_peek_opcode (parser_state);
/*
* First cut to determine what we have found:
* 1) A valid AML opcode
* 2) A name string
* 3) An unknown/invalid opcode
*/
op_info = acpi_ps_get_opcode_info (opcode);
switch (ACPI_GET_OP_TYPE (op_info)) {
case ACPI_OP_TYPE_OPCODE:
/* Found opcode info, this is a normal opcode */
parser_state->aml += acpi_ps_get_opcode_size (opcode);
arg_types = op_info->parse_args;
break;
case ACPI_OP_TYPE_ASCII:
case ACPI_OP_TYPE_PREFIX:
/*
* Starts with a valid prefix or ASCII char, this is a name
* string. Convert the bare name string to a namepath.
*/
opcode = AML_NAMEPATH_OP;
arg_types = ARGP_NAMESTRING;
break;
case ACPI_OP_TYPE_UNKNOWN:
/* The opcode is unrecognized. Just skip unknown opcodes */
/* Assume one-byte bad opcode */
parser_state->aml++;
continue;
}
/* Create Op structure and append to parent's argument list */
if (acpi_ps_is_named_op (opcode)) {
pre_op.value.arg = NULL;
pre_op.opcode = opcode;
while (GET_CURRENT_ARG_TYPE (arg_types) != ARGP_NAME) {
arg = acpi_ps_get_next_arg (parser_state,
GET_CURRENT_ARG_TYPE (arg_types),
&arg_count);
acpi_ps_append_arg (&pre_op, arg);
INCREMENT_ARG_LIST (arg_types);
}
/* We know that this arg is a name, move to next arg */
INCREMENT_ARG_LIST (arg_types);
if (walk_state->descending_callback != NULL) {
/*
* Find the object. This will either insert the object into
* the namespace or simply look it up
*/
status = walk_state->descending_callback (opcode, NULL, walk_state, &op);
if (op == NULL) {
continue;
}
status = acpi_ps_next_parse_state (walk_state, op, status);
if (status == AE_CTRL_PENDING) {
status = AE_OK;
goto close_this_op;
}
if (ACPI_FAILURE (status)) {
goto close_this_op;
}
}
acpi_ps_append_arg (op, pre_op.value.arg);
acpi_gbl_depth++;
if (op->opcode == AML_REGION_OP) {
deferred_op = acpi_ps_to_extended_op (op);
if (deferred_op) {
/*
* Defer final parsing of an Operation_region body,
* because we don't have enough info in the first pass
* to parse it correctly (i.e., there may be method
* calls within the Term_arg elements of the body.
*
* However, we must continue parsing because
* the opregion is not a standalone package --
* we don't know where the end is at this point.
*
* (Length is unknown until parse of the body complete)
*/
deferred_op->data = aml_op_start;
deferred_op->length = 0;
}
}
}
else {
/* Not a named opcode, just allocate Op and append to parent */
op = acpi_ps_alloc_op (opcode);
if (!op) {
return (AE_NO_MEMORY);
}
if ((op->opcode == AML_CREATE_FIELD_OP) ||
(op->opcode == AML_BIT_FIELD_OP) ||
(op->opcode == AML_BYTE_FIELD_OP) ||
(op->opcode == AML_WORD_FIELD_OP) ||
(op->opcode == AML_DWORD_FIELD_OP)) {
/*
* Backup to beginning of Create_xXXfield declaration
* Body_length is unknown until we parse the body
*/
deferred_op = (ACPI_PARSE2_OBJECT *) op;
deferred_op->data = aml_op_start;
deferred_op->length = 0;
}
acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op);
if ((walk_state->descending_callback != NULL)) {
/*
* Find the object. This will either insert the object into
* the namespace or simply look it up
*/
status = walk_state->descending_callback (opcode, op, walk_state, &op);
status = acpi_ps_next_parse_state (walk_state, op, status);
if (status == AE_CTRL_PENDING) {
status = AE_OK;
goto close_this_op;
}
if (ACPI_FAILURE (status)) {
goto close_this_op;
}
}
}
op->aml_offset = aml_offset;
}
/* Start Arg_count at zero because we don't know if there are any args yet */
arg_count = 0;
if (arg_types) /* Are there any arguments that must be processed? */ {
/* get arguments */
switch (op->opcode) {
case AML_BYTE_OP: /* AML_BYTEDATA_ARG */
case AML_WORD_OP: /* AML_WORDDATA_ARG */
case AML_DWORD_OP: /* AML_DWORDATA_ARG */
case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */
/* fill in constant or string argument directly */
acpi_ps_get_next_simple_arg (parser_state,
GET_CURRENT_ARG_TYPE (arg_types), op);
break;
case AML_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
acpi_ps_get_next_namepath (parser_state, op, &arg_count, 1);
arg_types = 0;
break;
default:
/* Op is not a constant or string, append each argument */
while (GET_CURRENT_ARG_TYPE (arg_types) && !arg_count) {
aml_offset = parser_state->aml - parser_state->aml_start;
arg = acpi_ps_get_next_arg (parser_state,
GET_CURRENT_ARG_TYPE (arg_types),
&arg_count);
if (arg) {
arg->aml_offset = aml_offset;
acpi_ps_append_arg (op, arg);
}
INCREMENT_ARG_LIST (arg_types);
}
/* For a method, save the length and address of the body */
if (op->opcode == AML_METHOD_OP) {
deferred_op = acpi_ps_to_extended_op (op);
if (deferred_op) {
/*
* Skip parsing of control method or opregion body,
* because we don't have enough info in the first pass
* to parse them correctly.
*/
deferred_op->data = parser_state->aml;
deferred_op->length = parser_state->pkg_end -
parser_state->aml;
/*
* Skip body of method. For Op_regions, we must continue
* parsing because the opregion is not a standalone
* package (We don't know where the end is).
*/
parser_state->aml = parser_state->pkg_end;
arg_count = 0;
}
}
break;
}
}
/*
* Zero Arg_count means that all arguments for this op have been processed
*/
if (!arg_count) {
/* completed Op, prepare for next */
if (acpi_ps_is_named_op (op->opcode)) {
if (acpi_gbl_depth) {
acpi_gbl_depth--;
}
if (op->opcode == AML_REGION_OP) {
deferred_op = acpi_ps_to_extended_op (op);
if (deferred_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.
*/
deferred_op->length = parser_state->aml -
deferred_op->data;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -