📄 psparse.c
字号:
}
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) ||
(op->opcode == AML_QWORD_FIELD_OP)) {
/*
* Backup to beginning of Create_xXXfield declaration (1 for
* Opcode)
*
* Body_length is unknown until we parse the body
*/
deferred_op = (ACPI_PARSE2_OBJECT *) op;
deferred_op->length = parser_state->aml - deferred_op->data;
}
/* This op complete, notify the dispatcher */
if (walk_state->ascending_callback != NULL) {
status = walk_state->ascending_callback (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;
}
}
close_this_op:
/*
* Finished one argument of the containing scope
*/
parser_state->scope->parse_scope.arg_count--;
/* Close this Op (may result in parse subtree deletion) */
if (acpi_ps_complete_this_op (walk_state, op)) {
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 = op;
walk_state->prev_arg_types = arg_types;
return (status);
break;
case AE_CTRL_END:
acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
status = walk_state->ascending_callback (walk_state, op);
status = acpi_ps_next_parse_state (walk_state, op, status);
acpi_ps_complete_this_op (walk_state, op);
op = NULL;
status = AE_OK;
break;
case AE_CTRL_TERMINATE:
status = AE_OK;
/* Clean up */
do {
if (op) {
acpi_ps_complete_this_op (walk_state, op);
}
acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
} while (op);
return (status);
break;
default: /* All other non-AE_OK status */
if (op == NULL) {
acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
}
walk_state->prev_op = op;
walk_state->prev_arg_types = arg_types;
/*
* TEMP:
*/
return (status);
break;
}
/* This scope complete? */
if (acpi_ps_has_completed_scope (parser_state)) {
acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
}
else {
op = NULL;
}
}
/* Arg_count is non-zero */
else {
/* complex argument, push Op and prepare for argument */
acpi_ps_push_scope (parser_state, op, arg_types, arg_count);
op = NULL;
}
} /* while Parser_state->Aml */
/*
* 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 AML blocks are closed with
* sequential closing braces). We want to terminate each one cleanly.
*/
do {
if (op) {
if (walk_state->ascending_callback != NULL) {
status = walk_state->ascending_callback (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 (status == AE_CTRL_TERMINATE) {
status = AE_OK;
/* Clean up */
do {
if (op) {
acpi_ps_complete_this_op (walk_state, op);
}
acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
} while (op);
return (status);
}
else if (ACPI_FAILURE (status)) {
acpi_ps_complete_this_op (walk_state, op);
return (status);
}
}
acpi_ps_complete_this_op (walk_state, op);
}
acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
} while (op);
return (status);
}
/*******************************************************************************
*
* FUNCTION: Acpi_ps_parse_aml
*
* PARAMETERS: Start_scope - The starting point of the parse. Becomes the
* root of the parsed op tree.
* Aml - Pointer to the raw AML code to parse
* Aml_size - Length of the AML to parse
*
* RETURN: Status
*
* DESCRIPTION: Parse raw AML and return a tree of ops
*
******************************************************************************/
ACPI_STATUS
acpi_ps_parse_aml (
ACPI_PARSE_OBJECT *start_scope,
u8 *aml,
u32 aml_size,
u32 parse_flags,
ACPI_NAMESPACE_NODE *method_node,
ACPI_OPERAND_OBJECT **params,
ACPI_OPERAND_OBJECT **caller_return_desc,
ACPI_PARSE_DOWNWARDS descending_callback,
ACPI_PARSE_UPWARDS ascending_callback)
{
ACPI_STATUS status;
ACPI_PARSE_STATE *parser_state;
ACPI_WALK_STATE *walk_state;
ACPI_WALK_LIST walk_list;
ACPI_NAMESPACE_NODE *node = NULL;
ACPI_WALK_LIST *prev_walk_list = acpi_gbl_current_walk_list;
ACPI_OPERAND_OBJECT *return_desc;
ACPI_OPERAND_OBJECT *mth_desc = NULL;
/* Create and initialize a new parser state */
parser_state = acpi_ps_create_state (aml, aml_size);
if (!parser_state) {
return (AE_NO_MEMORY);
}
acpi_ps_init_scope (parser_state, start_scope);
if (method_node) {
mth_desc = acpi_ns_get_attached_object (method_node);
}
/* Create and initialize a new walk list */
walk_list.walk_state = NULL;
walk_list.acquired_mutex_list.prev = NULL;
walk_list.acquired_mutex_list.next = NULL;
walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, parser_state->start_op, mth_desc, &walk_list);
if (!walk_state) {
status = AE_NO_MEMORY;
goto cleanup;
}
walk_state->method_node = method_node;
walk_state->parser_state = parser_state;
walk_state->parse_flags = parse_flags;
walk_state->descending_callback = descending_callback;
walk_state->ascending_callback = ascending_callback;
/* TBD: [Restructure] TEMP until we pass Walk_state to the interpreter
*/
acpi_gbl_current_walk_list = &walk_list;
if (method_node) {
parser_state->start_node = method_node;
walk_state->walk_type = WALK_METHOD;
/* 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 (status);
}
/* Init arguments if this is a control method */
/* TBD: [Restructure] add walkstate as a param */
acpi_ds_method_data_init_args (params, MTH_NUM_ARGS, walk_state);
}
else {
/* Setup the current scope */
node = parser_state->start_op->node;
parser_state->start_node = node;
if (node) {
/* Push start scope on scope stack and make it current */
status = acpi_ds_scope_stack_push (node, node->type,
walk_state);
if (ACPI_FAILURE (status)) {
goto cleanup;
}
}
}
status = AE_OK;
/*
* Execute the walk loop as long as there is a valid Walk State. This
* handles nested control method invocations without recursion.
*/
while (walk_state) {
if (ACPI_SUCCESS (status)) {
status = acpi_ps_parse_loop (walk_state);
}
if (status == AE_CTRL_TRANSFER) {
/*
* A method call was detected.
* Transfer control to the called control method
*/
status = acpi_ds_call_control_method (&walk_list, walk_state, NULL);
/*
* If the transfer to the new method method call worked, a new walk
* state was created -- get it
*/
walk_state = acpi_ds_get_current_walk_state (&walk_list);
continue;
}
else if (status == AE_CTRL_TERMINATE) {
status = AE_OK;
}
/* We are done with this walk, move on to the parent if any */
walk_state = acpi_ds_pop_walk_state (&walk_list);
/* Extract return value before we delete Walk_state */
return_desc = walk_state->return_desc;
/* Reset the current scope to the beginning of scope stack */
acpi_ds_scope_stack_clear (walk_state);
/*
* If we just returned from the execution of a control method,
* there's lots of cleanup to do
*/
if ((walk_state->parse_flags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) {
acpi_ds_terminate_control_method (walk_state);
}
/* Delete this walk state and all linked control states */
acpi_ps_cleanup_scope (walk_state->parser_state);
acpi_cm_free (walk_state->parser_state);
acpi_ds_delete_walk_state (walk_state);
/* Check if we have restarted a preempted walk */
walk_state = acpi_ds_get_current_walk_state (&walk_list);
if (walk_state &&
ACPI_SUCCESS (status)) {
/* There is another walk state, restart it */
/*
* If the method returned value is not used by the parent,
* The object is deleted
*/
acpi_ds_restart_control_method (walk_state, return_desc);
walk_state->walk_type |= WALK_METHOD_RESTART;
}
/*
* Just completed a 1st-level method, save the final internal return
* value (if any)
*/
else if (caller_return_desc) {
*caller_return_desc = return_desc; /* NULL if no return value */
}
else if (return_desc) {
/* Caller doesn't want it, must delete it */
acpi_cm_remove_reference (return_desc);
}
}
/* Normal exit */
acpi_aml_release_all_mutexes ((ACPI_OPERAND_OBJECT *) &walk_list.acquired_mutex_list);
acpi_gbl_current_walk_list = prev_walk_list;
return (status);
cleanup:
/* Cleanup */
acpi_ds_delete_walk_state (walk_state);
acpi_ps_cleanup_scope (parser_state);
acpi_cm_free (parser_state);
acpi_aml_release_all_mutexes ((ACPI_OPERAND_OBJECT *)&walk_list.acquired_mutex_list);
acpi_gbl_current_walk_list = prev_walk_list;
return (status);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -