acpi_status acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, union acpi_operand_object *obj_desc) { acpi_status status; union acpi_parse_object *op = NULL; struct acpi_walk_state *walk_state; ACPI_FUNCTION_TRACE_PTR(ds_auto_serialize_method, node); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Method auto-serialization parse [%4.4s] %p\n", acpi_ut_get_node_name(node), node)); acpi_ex_enter_interpreter(); /* Create/Init a root op for the method parse tree */ op = acpi_ps_alloc_op(AML_METHOD_OP, obj_desc->method.aml_start); if (!op) { status = AE_NO_MEMORY; goto unlock; } acpi_ps_set_name(op, node->name.integer); op->common.node = node; /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state(node->owner_id, NULL, NULL, NULL); if (!walk_state) { acpi_ps_free_op(op); status = AE_NO_MEMORY; goto unlock; } status = acpi_ds_init_aml_walk(walk_state, op, node, obj_desc->method.aml_start, obj_desc->method.aml_length, NULL, 0); if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); acpi_ps_free_op(op); return_ACPI_STATUS(status); } walk_state->descending_callback = acpi_ds_detect_named_opcodes; /* Parse the method, scan for creation of named objects */ status = acpi_ps_parse_aml(walk_state); acpi_ps_delete_parse_tree(op); unlock: acpi_ex_exit_interpreter(); return_ACPI_STATUS(status); }
/******************************************************************************* * * FUNCTION: acpi_ds_parse_method * * PARAMETERS: Node - Method node * * RETURN: Status * * DESCRIPTION: Parse the AML that is associated with the method. * * MUTEX: Assumes parser is locked * ******************************************************************************/ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node) { acpi_status status; union acpi_operand_object *obj_desc; union acpi_parse_object *op; struct acpi_walk_state *walk_state; ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node); /* Parameter Validation */ if (!node) { return_ACPI_STATUS(AE_NULL_ENTRY); } ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n", acpi_ut_get_node_name(node), node)); /* Extract the method object from the method Node */ obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { return_ACPI_STATUS(AE_NULL_OBJECT); } /* Create a mutex for the method if there is a concurrency limit */ if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) && (!obj_desc->method.semaphore)) { status = acpi_os_create_semaphore(obj_desc->method.concurrency, obj_desc->method.concurrency, &obj_desc->method.semaphore); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* * Allocate a new parser op to be the root of the parsed * method tree */ op = acpi_ps_alloc_op(AML_METHOD_OP); if (!op) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Init new op with the method name and pointer back to the Node */ acpi_ps_set_name(op, node->name.integer); op->common.node = node; /* * Get a new owner_id for objects created by this method. Namespace * objects (such as Operation Regions) can be created during the * first pass parse. */ status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); if (ACPI_FAILURE(status)) { goto cleanup; } /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL, NULL); if (!walk_state) { status = AE_NO_MEMORY; goto cleanup2; } status = acpi_ds_init_aml_walk(walk_state, op, node, obj_desc->method.aml_start, obj_desc->method.aml_length, NULL, 1); if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); goto cleanup2; } /* * Parse the method, first pass * * The first pass load is where newly declared named objects are added into * the namespace. Actual evaluation of the named objects (what would be * called a "second pass") happens during the actual execution of the * method so that operands to the named objects can take on dynamic * run-time values. */ status = acpi_ps_parse_aml(walk_state); if (ACPI_FAILURE(status)) { goto cleanup2; } ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", acpi_ut_get_node_name(node), node, op)); /* * Delete the parse tree. We simply re-parse the method for every * execution since there isn't much overhead (compared to keeping lots * of parse trees around) */ acpi_ns_delete_namespace_subtree(node); acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id); cleanup2: acpi_ut_release_owner_id(&obj_desc->method.owner_id); cleanup: acpi_ps_delete_parse_tree(op); return_ACPI_STATUS(status); }
acpi_status acpi_psx_execute ( acpi_namespace_node *method_node, acpi_operand_object **params, acpi_operand_object **return_obj_desc) { acpi_status status; acpi_operand_object *obj_desc; u32 i; acpi_parse_object *op; acpi_walk_state *walk_state; FUNCTION_TRACE ("Psx_execute"); /* Validate the Node and get the attached object */ if (!method_node) { return_ACPI_STATUS (AE_NULL_ENTRY); } obj_desc = acpi_ns_get_attached_object (method_node); if (!obj_desc) { return_ACPI_STATUS (AE_NULL_OBJECT); } /* Init for new method, wait on concurrency semaphore */ status = acpi_ds_begin_method_execution (method_node, obj_desc, NULL); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } if (params) { /* * The caller "owns" the parameters, so give each one an extra * reference */ for (i = 0; params[i]; i++) { acpi_ut_add_reference (params[i]); } } /* * 1) Perform the first pass parse of the method to enter any * named objects that it creates into the namespace */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Begin Method Parse **** Entry=%p obj=%p\n", method_node, obj_desc)); /* Create and init a Root Node */ op = acpi_ps_alloc_op (AML_SCOPE_OP); if (!op) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start, obj_desc->method.aml_length, NULL, NULL, 1); if (ACPI_FAILURE (status)) { /* TBD: delete walk state */ return_ACPI_STATUS (status); } /* Parse the AML */ status = acpi_ps_parse_aml (walk_state); acpi_ps_delete_parse_tree (op); /* * 2) Execute the method. Performs second pass parse simultaneously */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Begin Method Execution **** Entry=%p obj=%p\n", method_node, obj_desc)); /* Create and init a Root Node */ op = acpi_ps_alloc_op (AML_SCOPE_OP); if (!op) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Init new op with the method name and pointer back to the NS node */ acpi_ps_set_name (op, method_node->name); op->node = method_node; /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } status = acpi_ds_init_aml_walk (walk_state, op, method_node, obj_desc->method.aml_start, obj_desc->method.aml_length, params, return_obj_desc, 3); if (ACPI_FAILURE (status)) { /* TBD: delete walk state */ return_ACPI_STATUS (status); } /* * The walk of the parse tree is where we actually execute the method */ status = acpi_ps_parse_aml (walk_state); acpi_ps_delete_parse_tree (op); if (params) { /* Take away the extra reference that we gave the parameters above */ for (i = 0; params[i]; i++) { acpi_ut_update_object_reference (params[i], REF_DECREMENT); } } if (ACPI_FAILURE (status)) { DUMP_PATHNAME (method_node, "Ps_execute: method failed -", ACPI_LV_ERROR, _COMPONENT); } /* * If the method has returned an object, signal this to the caller with * a control exception code */ if (*return_obj_desc) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Method returned Obj_desc=%p\n", *return_obj_desc)); DUMP_STACK_ENTRY (*return_obj_desc); status = AE_CTRL_RETURN_VALUE; } return_ACPI_STATUS (status); }
static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state *parser_state) { u32 aml_offset = (u32) ACPI_PTR_DIFF(parser_state->aml, parser_state->aml_start); union acpi_parse_object *field; u16 opcode; u32 name; ACPI_FUNCTION_TRACE("ps_get_next_field"); /* Determine field type */ switch (ACPI_GET8(parser_state->aml)) { default: opcode = AML_INT_NAMEDFIELD_OP; break; case 0x00: opcode = AML_INT_RESERVEDFIELD_OP; parser_state->aml++; break; case 0x01: opcode = AML_INT_ACCESSFIELD_OP; parser_state->aml++; break; } /* Allocate a new field op */ field = acpi_ps_alloc_op(opcode); if (!field) { return_PTR(NULL); } field->common.aml_offset = aml_offset; /* Decode the field type */ switch (opcode) { case AML_INT_NAMEDFIELD_OP: /* Get the 4-character name */ ACPI_MOVE_32_TO_32(&name, parser_state->aml); acpi_ps_set_name(field, name); parser_state->aml += ACPI_NAME_SIZE; /* Get the length which is encoded as a package length */ field->common.value.size = acpi_ps_get_next_package_length(parser_state); break; case AML_INT_RESERVEDFIELD_OP: /* Get the length which is encoded as a package length */ field->common.value.size = acpi_ps_get_next_package_length(parser_state); break; case AML_INT_ACCESSFIELD_OP: /* * Get access_type and access_attrib and merge into the field Op * access_type is first operand, access_attribute is second */ field->common.value.integer = (ACPI_GET8(parser_state->aml) << 8); parser_state->aml++; field->common.value.integer |= ACPI_GET8(parser_state->aml); parser_state->aml++; break; default: /* Opcode was set in previous switch */ break; } return_PTR(field); }
ACPI_STATUS acpi_ds_parse_method ( ACPI_HANDLE obj_handle) { ACPI_STATUS status; ACPI_OPERAND_OBJECT *obj_desc; ACPI_PARSE_OBJECT *op; ACPI_NAMESPACE_NODE *node; ACPI_OWNER_ID owner_id; /* Parameter Validation */ if (!obj_handle) { return (AE_NULL_ENTRY); } /* Extract the method object from the method Node */ node = (ACPI_NAMESPACE_NODE *) obj_handle; obj_desc = node->object; if (!obj_desc) { return (AE_NULL_OBJECT); } /* Create a mutex for the method if there is a concurrency limit */ if ((obj_desc->method.concurrency != INFINITE_CONCURRENCY) && (!obj_desc->method.semaphore)) { status = acpi_os_create_semaphore (1,obj_desc->method.concurrency, &obj_desc->method.semaphore); if (ACPI_FAILURE (status)) { return (status); } } /* * Allocate a new parser op to be the root of the parsed * method tree */ op = acpi_ps_alloc_op (AML_METHOD_OP); if (!op) { return (AE_NO_MEMORY); } /* Init new op with the method name and pointer back to the Node */ acpi_ps_set_name (op, node->name); op->node = node; /* * Parse the method, first pass * * The first pass load is * where newly declared named objects are * added into the namespace. Actual evaluation of * the named objects (what would be called a "second * pass") happens during the actual execution of the * method so that operands to the named objects can * take on dynamic run-time values. */ status = acpi_ps_parse_aml (op, obj_desc->method.pcode, obj_desc->method.pcode_length, ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE, node, NULL, NULL, acpi_ds_load1_begin_op, acpi_ds_load1_end_op); if (ACPI_FAILURE (status)) { return (status); } /* Get a new Owner_id for objects created by this method */ owner_id = acpi_cm_allocate_owner_id (OWNER_TYPE_METHOD); obj_desc->method.owning_id = owner_id; /* Install the parsed tree in the method object */ /* TBD: [Restructure] Obsolete field? */ acpi_ps_delete_parse_tree (op); return (status); }
acpi_status acpi_psx_execute ( struct acpi_parameter_info *info) { acpi_status status; union acpi_operand_object *obj_desc; u32 i; union acpi_parse_object *op; struct acpi_walk_state *walk_state; ACPI_FUNCTION_TRACE ("psx_execute"); /* Validate the Node and get the attached object */ if (!info || !info->node) { return_ACPI_STATUS (AE_NULL_ENTRY); } obj_desc = acpi_ns_get_attached_object (info->node); if (!obj_desc) { return_ACPI_STATUS (AE_NULL_OBJECT); } /* Init for new method, wait on concurrency semaphore */ status = acpi_ds_begin_method_execution (info->node, obj_desc, NULL); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) { /* * The caller "owns" the parameters, so give each one an extra * reference */ for (i = 0; info->parameters[i]; i++) { acpi_ut_add_reference (info->parameters[i]); } } /* * 1) Perform the first pass parse of the method to enter any * named objects that it creates into the namespace */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Begin Method Parse **** Entry=%p obj=%p\n", info->node, obj_desc)); /* Create and init a Root Node */ op = acpi_ps_create_scope_op (); if (!op) { status = AE_NO_MEMORY; goto cleanup1; } /* * Get a new owner_id for objects created by this method. Namespace * objects (such as Operation Regions) can be created during the * first pass parse. */ obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, NULL, NULL, NULL); if (!walk_state) { status = AE_NO_MEMORY; goto cleanup2; } status = acpi_ds_init_aml_walk (walk_state, op, info->node, obj_desc->method.aml_start, obj_desc->method.aml_length, NULL, 1); if (ACPI_FAILURE (status)) { goto cleanup3; } /* Parse the AML */ status = acpi_ps_parse_aml (walk_state); acpi_ps_delete_parse_tree (op); if (ACPI_FAILURE (status)) { goto cleanup1; /* Walk state is already deleted */ } /* * 2) Execute the method. Performs second pass parse simultaneously */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Begin Method Execution **** Entry=%p obj=%p\n", info->node, obj_desc)); /* Create and init a Root Node */ op = acpi_ps_create_scope_op (); if (!op) { status = AE_NO_MEMORY; goto cleanup1; } /* Init new op with the method name and pointer back to the NS node */ acpi_ps_set_name (op, info->node->name.integer); op->common.node = info->node; /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); if (!walk_state) { status = AE_NO_MEMORY; goto cleanup2; } status = acpi_ds_init_aml_walk (walk_state, op, info->node, obj_desc->method.aml_start, obj_desc->method.aml_length, info, 3); if (ACPI_FAILURE (status)) { goto cleanup3; } /* The walk of the parse tree is where we actually execute the method */ status = acpi_ps_parse_aml (walk_state); goto cleanup2; /* Walk state already deleted */ cleanup3: acpi_ds_delete_walk_state (walk_state); cleanup2: acpi_ps_delete_parse_tree (op); cleanup1: if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) { /* Take away the extra reference that we gave the parameters above */ for (i = 0; info->parameters[i]; i++) { /* Ignore errors, just do them all */ (void) acpi_ut_update_object_reference ( info->parameters[i], REF_DECREMENT); } } if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* * If the method has returned an object, signal this to the caller with * a control exception code */ if (info->return_object) { ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n", info->return_object)); ACPI_DUMP_STACK_ENTRY (info->return_object); status = AE_CTRL_RETURN_VALUE; } return_ACPI_STATUS (status); }
ACPI_PARSE_OBJECT * acpi_ps_get_next_field ( ACPI_PARSE_STATE *parser_state) { ACPI_PTRDIFF aml_offset = parser_state->aml - parser_state->aml_start; ACPI_PARSE_OBJECT *field; u16 opcode; u32 name; /* determine field type */ switch (GET8 (parser_state->aml)) { default: opcode = AML_NAMEDFIELD_OP; break; case 0x00: opcode = AML_RESERVEDFIELD_OP; parser_state->aml++; break; case 0x01: opcode = AML_ACCESSFIELD_OP; parser_state->aml++; break; } /* Allocate a new field op */ field = acpi_ps_alloc_op (opcode); if (field) { field->aml_offset = aml_offset; /* Decode the field type */ switch (opcode) { case AML_NAMEDFIELD_OP: /* Get the 4-character name */ MOVE_UNALIGNED32_TO_32 (&name, parser_state->aml); acpi_ps_set_name (field, name); parser_state->aml += 4; /* Get the length which is encoded as a package length */ field->value.size = acpi_ps_get_next_package_length (parser_state); break; case AML_RESERVEDFIELD_OP: /* Get the length which is encoded as a package length */ field->value.size = acpi_ps_get_next_package_length (parser_state); break; case AML_ACCESSFIELD_OP: /* Get Access_type and Access_atrib and merge into the field Op */ field->value.integer = ((GET8 (parser_state->aml) << 8) | GET8 (parser_state->aml)); parser_state->aml += 2; break; } } return (field); }