acpi_status acpi_ev_address_space_dispatch ( union acpi_operand_object *region_obj, u32 function, acpi_physical_address address, u32 bit_width, void *value) { acpi_status status; acpi_status status2; acpi_adr_space_handler handler; acpi_adr_space_setup region_setup; union acpi_operand_object *handler_desc; union acpi_operand_object *region_obj2; void *region_context = NULL; ACPI_FUNCTION_TRACE ("ev_address_space_dispatch"); region_obj2 = acpi_ns_get_secondary_object (region_obj); if (!region_obj2) { return_ACPI_STATUS (AE_NOT_EXIST); } /* Ensure that there is a handler associated with this region */ handler_desc = region_obj->region.address_space; if (!handler_desc) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "no handler for region(%p) [%s]\n", region_obj, acpi_ut_get_region_name (region_obj->region.space_id))); return_ACPI_STATUS (AE_NOT_EXIST); } /* * It may be the case that the region has never been initialized * Some types of regions require special init code */ if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { /* * This region has not been initialized yet, do it */ region_setup = handler_desc->address_space.setup; if (!region_setup) { /* No initialization routine, exit with error */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n", region_obj, acpi_ut_get_region_name (region_obj->region.space_id))); return_ACPI_STATUS (AE_NOT_EXIST); } /* * We must exit the interpreter because the region setup will potentially * execute control methods (e.g., _REG method for this region) */ acpi_ex_exit_interpreter (); status = region_setup (region_obj, ACPI_REGION_ACTIVATE, handler_desc->address_space.context, ®ion_context); /* Re-enter the interpreter */ status2 = acpi_ex_enter_interpreter (); if (ACPI_FAILURE (status2)) { return_ACPI_STATUS (status2); } /* Check for failure of the Region Setup */ if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n", acpi_format_exception (status), acpi_ut_get_region_name (region_obj->region.space_id))); return_ACPI_STATUS (status); } /* * Region initialization may have been completed by region_setup */ if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; if (region_obj2->extra.region_context) { /* The handler for this region was already installed */ ACPI_MEM_FREE (region_context); } else { /* * Save the returned context for use in all accesses to * this particular region */ region_obj2->extra.region_context = region_context; } } } /* We have everything we need, we can invoke the address space handler */ handler = handler_desc->address_space.handler; ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", ®ion_obj->region.address_space->address_space, handler, ACPI_HIDWORD (address), ACPI_LODWORD (address), acpi_ut_get_region_name (region_obj->region.space_id))); if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * For handlers other than the default (supplied) handlers, we must * exit the interpreter because the handler *might* block -- we don't * know what it will do, so we can't hold the lock on the intepreter. */ acpi_ex_exit_interpreter(); } /* Call the handler */ status = handler (function, address, bit_width, value, handler_desc->address_space.context, region_obj2->extra.region_context); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("Handler for [%s] returned %s\n", acpi_ut_get_region_name (region_obj->region.space_id), acpi_format_exception (status))); } if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * We just returned from a non-default handler, we must re-enter the * interpreter */ status2 = acpi_ex_enter_interpreter (); if (ACPI_FAILURE (status2)) { return_ACPI_STATUS (status2); } } return_ACPI_STATUS (status); }
static acpi_status acpi_ns_init_one_object(acpi_handle obj_handle, u32 level, void *context, void **return_value) { acpi_object_type type; acpi_status status = AE_OK; struct acpi_init_walk_info *info = (struct acpi_init_walk_info *)context; struct acpi_namespace_node *node = (struct acpi_namespace_node *)obj_handle; union acpi_operand_object *obj_desc; ACPI_FUNCTION_NAME(ns_init_one_object); info->object_count++; /* And even then, we are only interested in a few object types */ type = acpi_ns_get_type(obj_handle); obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { return (AE_OK); } /* Increment counters for object types we are looking for */ switch (type) { case ACPI_TYPE_REGION: info->op_region_count++; break; case ACPI_TYPE_BUFFER_FIELD: info->field_count++; break; case ACPI_TYPE_LOCAL_BANK_FIELD: info->field_count++; break; case ACPI_TYPE_BUFFER: info->buffer_count++; break; case ACPI_TYPE_PACKAGE: info->package_count++; break; default: /* No init required, just exit now */ return (AE_OK); } /* If the object is already initialized, nothing else to do */ if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return (AE_OK); } /* Must lock the interpreter before executing AML code */ acpi_ex_enter_interpreter(); /* * Each of these types can contain executable AML code within the * declaration. */ switch (type) { case ACPI_TYPE_REGION: info->op_region_init++; status = acpi_ds_get_region_arguments(obj_desc); break; case ACPI_TYPE_BUFFER_FIELD: info->field_init++; status = acpi_ds_get_buffer_field_arguments(obj_desc); break; case ACPI_TYPE_LOCAL_BANK_FIELD: info->field_init++; status = acpi_ds_get_bank_field_arguments(obj_desc); break; case ACPI_TYPE_BUFFER: info->buffer_init++; status = acpi_ds_get_buffer_arguments(obj_desc); break; case ACPI_TYPE_PACKAGE: /* Complete the initialization/resolution of the package object */ info->package_init++; status = acpi_ns_init_one_package(obj_handle, level, NULL, NULL); break; default: /* No other types can get here */ break; } if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not execute arguments for [%4.4s] (%s)", acpi_ut_get_node_name(node), acpi_ut_get_type_name(type))); } /* * We ignore errors from above, and always return OK, since we don't want * to abort the walk on any single error. */ acpi_ex_exit_interpreter(); return (AE_OK); }
acpi_status acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, union acpi_operand_object *field_obj, u32 function, u32 region_offset, u32 bit_width, u64 *value) { acpi_status status; acpi_adr_space_handler handler; acpi_adr_space_setup region_setup; union acpi_operand_object *handler_desc; union acpi_operand_object *region_obj2; void *region_context = NULL; struct acpi_connection_info *context; acpi_physical_address address; ACPI_FUNCTION_TRACE(ev_address_space_dispatch); region_obj2 = acpi_ns_get_secondary_object(region_obj); if (!region_obj2) { return_ACPI_STATUS(AE_NOT_EXIST); } /* Ensure that there is a handler associated with this region */ handler_desc = region_obj->region.handler; if (!handler_desc) { ACPI_ERROR((AE_INFO, "No handler for Region [%4.4s] (%p) [%s]", acpi_ut_get_node_name(region_obj->region.node), region_obj, acpi_ut_get_region_name(region_obj->region. space_id))); return_ACPI_STATUS(AE_NOT_EXIST); } context = handler_desc->address_space.context; /* * It may be the case that the region has never been initialized. * Some types of regions require special init code */ if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { /* This region has not been initialized yet, do it */ region_setup = handler_desc->address_space.setup; if (!region_setup) { /* No initialization routine, exit with error */ ACPI_ERROR((AE_INFO, "No init routine for region(%p) [%s]", region_obj, acpi_ut_get_region_name(region_obj->region. space_id))); return_ACPI_STATUS(AE_NOT_EXIST); } /* * We must exit the interpreter because the region setup will * potentially execute control methods (for example, the _REG method * for this region) */ acpi_ex_exit_interpreter(); status = region_setup(region_obj, ACPI_REGION_ACTIVATE, context, ®ion_context); /* Re-enter the interpreter */ acpi_ex_enter_interpreter(); /* Check for failure of the Region Setup */ if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "During region initialization: [%s]", acpi_ut_get_region_name(region_obj-> region. space_id))); return_ACPI_STATUS(status); } /* Region initialization may have been completed by region_setup */ if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; /* * Save the returned context for use in all accesses to * the handler for this particular region */ if (!(region_obj2->extra.region_context)) { region_obj2->extra.region_context = region_context; } } } /* We have everything we need, we can invoke the address space handler */ handler = handler_desc->address_space.handler; address = (region_obj->region.address + region_offset); /* * Special handling for generic_serial_bus and general_purpose_io: * There are three extra parameters that must be passed to the * handler via the context: * 1) Connection buffer, a resource template from Connection() op * 2) Length of the above buffer * 3) Actual access length from the access_as() op * * In addition, for general_purpose_io, the Address and bit_width fields * are defined as follows: * 1) Address is the pin number index of the field (bit offset from * the previous Connection) * 2) bit_width is the actual bit length of the field (number of pins) */ if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) && context && field_obj) { /* Get the Connection (resource_template) buffer */ context->connection = field_obj->field.resource_buffer; context->length = field_obj->field.resource_length; context->access_length = field_obj->field.access_length; } if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) && context && field_obj) { /* Get the Connection (resource_template) buffer */ context->connection = field_obj->field.resource_buffer; context->length = field_obj->field.resource_length; context->access_length = field_obj->field.access_length; address = field_obj->field.pin_number_index; bit_width = field_obj->field.bit_length; } ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", ®ion_obj->region.handler->address_space, handler, ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(region_obj->region. space_id))); if (!(handler_desc->address_space.handler_flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * For handlers other than the default (supplied) handlers, we must * exit the interpreter because the handler *might* block -- we don't * know what it will do, so we can't hold the lock on the intepreter. */ acpi_ex_exit_interpreter(); } /* Call the handler */ status = handler(function, address, bit_width, value, context, region_obj2->extra.region_context); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]", acpi_ut_get_region_name(region_obj->region. space_id))); } if (!(handler_desc->address_space.handler_flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * We just returned from a non-default handler, we must re-enter the * interpreter */ acpi_ex_enter_interpreter(); } return_ACPI_STATUS(status); }
acpi_status acpi_ns_load_table(u32 table_index, struct acpi_namespace_node *node) { acpi_status status; ACPI_FUNCTION_TRACE(ns_load_table); acpi_ex_enter_interpreter(); /* * Parse the table and load the namespace with all named * objects found within. Control methods are NOT parsed * at this time. In fact, the control methods cannot be * parsed until the entire namespace is loaded, because * if a control method makes a forward reference (call) * to another control method, we can't continue parsing * because we don't know how many arguments to parse next! */ status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { goto unlock_interp; } /* If table already loaded into namespace, just return */ if (acpi_tb_is_table_loaded(table_index)) { status = AE_ALREADY_EXISTS; goto unlock; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "**** Loading table into namespace ****\n")); status = acpi_tb_allocate_owner_id(table_index); if (ACPI_FAILURE(status)) { goto unlock; } status = acpi_ns_parse_table(table_index, node); if (ACPI_SUCCESS(status)) { acpi_tb_set_table_loaded_flag(table_index, TRUE); } else { /* * On error, delete any namespace objects created by this table. * We cannot initialize these objects, so delete them. There are * a couple of expecially bad cases: * AE_ALREADY_EXISTS - namespace collision. * AE_NOT_FOUND - the target of a Scope operator does not * exist. This target of Scope must already exist in the * namespace, as per the ACPI specification. */ (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); acpi_ns_delete_namespace_by_owner(acpi_gbl_root_table_list. tables[table_index].owner_id); acpi_tb_release_owner_id(table_index); return_ACPI_STATUS(status); } unlock: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); unlock_interp: (void)acpi_ex_exit_interpreter(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* * Now we can parse the control methods. We always parse * them here for a sanity check, and if configured for * just-in-time parsing, we delete the control method * parse trees. */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "**** Begin Table Object Initialization\n")); status = acpi_ds_initialize_objects(table_index, node); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "**** Completed Table Object Initialization\n")); /* * Execute any module-level code that was detected during the table load * phase. Although illegal since ACPI 2.0, there are many machines that * contain this type of code. Each block of detected executable AML code * outside of any control method is wrapped with a temporary control * method object and placed on a global list. The methods on this list * are executed below. * * This case executes the module-level code for each table immediately * after the table has been loaded. This provides compatibility with * other ACPI implementations. Optionally, the execution can be deferred * until later, see acpi_initialize_objects. */ if (!acpi_gbl_group_module_level_code) { acpi_ns_exec_module_code_list(); } return_ACPI_STATUS(status); }
static acpi_status acpi_ns_init_one_object(acpi_handle obj_handle, u32 level, void *context, void **return_value) { acpi_object_type type; acpi_status status; struct acpi_init_walk_info *info = (struct acpi_init_walk_info *)context; struct acpi_namespace_node *node = (struct acpi_namespace_node *)obj_handle; union acpi_operand_object *obj_desc; ACPI_FUNCTION_NAME("ns_init_one_object"); info->object_count++; /* And even then, we are only interested in a few object types */ type = acpi_ns_get_type(obj_handle); obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { return (AE_OK); } /* Increment counters for object types we are looking for */ switch (type) { case ACPI_TYPE_REGION: info->op_region_count++; break; case ACPI_TYPE_BUFFER_FIELD: info->field_count++; break; case ACPI_TYPE_BUFFER: info->buffer_count++; break; case ACPI_TYPE_PACKAGE: info->package_count++; break; default: /* No init required, just exit now */ return (AE_OK); } /* * If the object is already initialized, nothing else to do */ if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return (AE_OK); } /* * Must lock the interpreter before executing AML code */ status = acpi_ex_enter_interpreter(); if (ACPI_FAILURE(status)) { return (status); } /* * Each of these types can contain executable AML code within the * declaration. */ switch (type) { case ACPI_TYPE_REGION: info->op_region_init++; status = acpi_ds_get_region_arguments(obj_desc); break; case ACPI_TYPE_BUFFER_FIELD: info->field_init++; status = acpi_ds_get_buffer_field_arguments(obj_desc); break; case ACPI_TYPE_BUFFER: info->buffer_init++; status = acpi_ds_get_buffer_arguments(obj_desc); break; case ACPI_TYPE_PACKAGE: info->package_init++; status = acpi_ds_get_package_arguments(obj_desc); break; default: /* No other types can get here */ break; } if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_ERROR, "\n")); ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Could not execute arguments for [%4.4s] (%s), %s\n", acpi_ut_get_node_name(node), acpi_ut_get_type_name(type), acpi_format_exception(status))); } /* * Print a dot for each object unless we are going to print the entire * pathname */ if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); } /* * We ignore errors from above, and always return OK, since we don't want * to abort the walk on any single error. */ acpi_ex_exit_interpreter(); return (AE_OK); }
/******************************************************************************* * * FUNCTION: acpi_evaluate_object * * PARAMETERS: Handle - Object handle (optional) * Pathname - Object pathname (optional) * external_params - List of parameters to pass to method, * terminated by NULL. May be NULL * if no parameters are being passed. * return_buffer - Where to put method's return value (if * any). If NULL, no value is returned. * * RETURN: Status * * DESCRIPTION: Find and evaluate the given object, passing the given * parameters if necessary. One of "Handle" or "Pathname" must * be valid (non-null) * ******************************************************************************/ acpi_status acpi_evaluate_object(acpi_handle handle, acpi_string pathname, struct acpi_object_list *external_params, struct acpi_buffer *return_buffer) { acpi_status status; struct acpi_evaluate_info *info; acpi_size buffer_space_needed; u32 i; ACPI_FUNCTION_TRACE(acpi_evaluate_object); /* Allocate and initialize the evaluation information block */ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); if (!info) { return_ACPI_STATUS(AE_NO_MEMORY); } info->pathname = pathname; /* Convert and validate the device handle */ info->prefix_node = acpi_ns_validate_handle(handle); if (!info->prefix_node) { status = AE_BAD_PARAMETER; goto cleanup; } /* * If there are parameters to be passed to a control method, the external * objects must all be converted to internal objects */ if (external_params && external_params->count) { /* * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) external_params-> count + 1) * sizeof(void *)); if (!info->parameters) { status = AE_NO_MEMORY; goto cleanup; } /* Convert each external object in the list to an internal object */ for (i = 0; i < external_params->count; i++) { status = acpi_ut_copy_eobject_to_iobject(&external_params-> pointer[i], &info-> parameters[i]); if (ACPI_FAILURE(status)) { goto cleanup; } } info->parameters[external_params->count] = NULL; } /* * Three major cases: * 1) Fully qualified pathname * 2) No handle, not fully qualified pathname (error) * 3) Valid handle */ if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) { /* The path is fully qualified, just evaluate by name */ info->prefix_node = NULL; status = acpi_ns_evaluate(info); } else if (!handle) { /* * A handle is optional iff a fully qualified pathname is specified. * Since we've already handled fully qualified names above, this is * an error */ if (!pathname) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Both Handle and Pathname are NULL")); } else { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Null Handle with relative pathname [%s]", pathname)); } status = AE_BAD_PARAMETER; } else { /* We have a namespace a node and a possible relative path */ status = acpi_ns_evaluate(info); } /* * If we are expecting a return value, and all went well above, * copy the return value to an external object. */ if (return_buffer) { if (!info->return_object) { return_buffer->length = 0; } else { if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) == ACPI_DESC_TYPE_NAMED) { /* * If we received a NS Node as a return object, this means that * the object we are evaluating has nothing interesting to * return (such as a mutex, etc.) We return an error because * these types are essentially unsupported by this interface. * We don't check up front because this makes it easier to add * support for various types at a later date if necessary. */ status = AE_TYPE; info->return_object = NULL; /* No need to delete a NS Node */ return_buffer->length = 0; } if (ACPI_SUCCESS(status)) { /* Dereference Index and ref_of references */ acpi_ns_resolve_references(info); /* Get the size of the returned object */ status = acpi_ut_get_object_size(info->return_object, &buffer_space_needed); if (ACPI_SUCCESS(status)) { /* Validate/Allocate/Clear caller buffer */ status = acpi_ut_initialize_buffer (return_buffer, buffer_space_needed); if (ACPI_FAILURE(status)) { /* * Caller's buffer is too small or a new one can't * be allocated */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Needed buffer size %X, %s\n", (u32) buffer_space_needed, acpi_format_exception (status))); } else { /* We have enough space for the object, build it */ status = acpi_ut_copy_iobject_to_eobject (info->return_object, return_buffer); } } } } } if (info->return_object) { /* * Delete the internal return object. NOTE: Interpreter must be * locked to avoid race condition. */ acpi_ex_enter_interpreter(); /* Remove one reference on the return object (should delete it) */ acpi_ut_remove_reference(info->return_object); acpi_ex_exit_interpreter(); } cleanup: /* Free the input parameter list (if we created one) */ if (info->parameters) { /* Free the allocated parameter block */ acpi_ut_delete_internal_object_list(info->parameters); } ACPI_FREE(info); return_ACPI_STATUS(status); }
static acpi_status acpi_ns_init_one_object(acpi_handle obj_handle, u32 level, void *context, void **return_value) { acpi_object_type type; acpi_status status = AE_OK; struct acpi_init_walk_info *info = (struct acpi_init_walk_info *)context; struct acpi_namespace_node *node = (struct acpi_namespace_node *)obj_handle; union acpi_operand_object *obj_desc; ACPI_FUNCTION_NAME(ns_init_one_object); info->object_count++; type = acpi_ns_get_type(obj_handle); obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { return (AE_OK); } switch (type) { case ACPI_TYPE_REGION: info->op_region_count++; break; case ACPI_TYPE_BUFFER_FIELD: info->field_count++; break; case ACPI_TYPE_LOCAL_BANK_FIELD: info->field_count++; break; case ACPI_TYPE_BUFFER: info->buffer_count++; break; case ACPI_TYPE_PACKAGE: info->package_count++; break; default: return (AE_OK); } if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return (AE_OK); } acpi_ex_enter_interpreter(); switch (type) { case ACPI_TYPE_REGION: info->op_region_init++; status = acpi_ds_get_region_arguments(obj_desc); break; case ACPI_TYPE_BUFFER_FIELD: info->field_init++; status = acpi_ds_get_buffer_field_arguments(obj_desc); break; case ACPI_TYPE_LOCAL_BANK_FIELD: info->field_init++; status = acpi_ds_get_bank_field_arguments(obj_desc); break; case ACPI_TYPE_BUFFER: info->buffer_init++; status = acpi_ds_get_buffer_arguments(obj_desc); break; case ACPI_TYPE_PACKAGE: info->package_init++; status = acpi_ds_get_package_arguments(obj_desc); break; default: break; } if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not execute arguments for [%4.4s] (%s)", acpi_ut_get_node_name(node), acpi_ut_get_type_name(type))); } if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, ".")); } acpi_ex_exit_interpreter(); return (AE_OK); }
acpi_status acpi_ps_execute_table(struct acpi_evaluate_info *info) { acpi_status status; union acpi_parse_object *op = NULL; struct acpi_walk_state *walk_state = NULL; ACPI_FUNCTION_TRACE(ps_execute_table); /* Create and init a Root Node */ op = acpi_ps_create_scope_op(info->obj_desc->method.aml_start); if (!op) { status = AE_NO_MEMORY; goto cleanup; } /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state(info->obj_desc->method.owner_id, NULL, NULL, NULL); if (!walk_state) { status = AE_NO_MEMORY; goto cleanup; } status = acpi_ds_init_aml_walk(walk_state, op, info->node, info->obj_desc->method.aml_start, info->obj_desc->method.aml_length, info, info->pass_number); if (ACPI_FAILURE(status)) { goto cleanup; } if (info->obj_desc->method.info_flags & ACPI_METHOD_MODULE_LEVEL) { walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL; } /* Info->Node is the default location to load the table */ if (info->node && info->node != acpi_gbl_root_node) { status = acpi_ds_scope_stack_push(info->node, ACPI_TYPE_METHOD, walk_state); if (ACPI_FAILURE(status)) { goto cleanup; } } /* * Parse the AML, walk_state will be deleted by parse_aml */ acpi_ex_enter_interpreter(); status = acpi_ps_parse_aml(walk_state); acpi_ex_exit_interpreter(); walk_state = NULL; cleanup: if (walk_state) { acpi_ds_delete_walk_state(walk_state); } if (op) { acpi_ps_delete_parse_tree(op); } return_ACPI_STATUS(status); }
acpi_status acpi_evaluate_object(acpi_handle handle, acpi_string pathname, struct acpi_object_list *external_params, struct acpi_buffer *return_buffer) { acpi_status status; acpi_status status2; struct acpi_parameter_info info; acpi_size buffer_space_needed; u32 i; ACPI_FUNCTION_TRACE("acpi_evaluate_object"); info.node = handle; info.parameters = NULL; info.return_object = NULL; info.parameter_type = ACPI_PARAM_ARGS; /* * If there are parameters to be passed to the object * (which must be a control method), the external objects * must be converted to internal objects */ if (external_params && external_params->count) { /* * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ info.parameters = ACPI_MEM_CALLOCATE(((acpi_size) external_params->count + 1) * sizeof(void *)); if (!info.parameters) { return_ACPI_STATUS(AE_NO_MEMORY); } /* * Convert each external object in the list to an * internal object */ for (i = 0; i < external_params->count; i++) { status = acpi_ut_copy_eobject_to_iobject(&external_params-> pointer[i], &info. parameters[i]); if (ACPI_FAILURE(status)) { acpi_ut_delete_internal_object_list(info. parameters); return_ACPI_STATUS(status); } } info.parameters[external_params->count] = NULL; } /* * Three major cases: * 1) Fully qualified pathname * 2) No handle, not fully qualified pathname (error) * 3) Valid handle */ if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) { /* * The path is fully qualified, just evaluate by name */ status = acpi_ns_evaluate_by_name(pathname, &info); } else if (!handle) { /* * A handle is optional iff a fully qualified pathname * is specified. Since we've already handled fully * qualified names above, this is an error */ if (!pathname) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Both Handle and Pathname are NULL\n")); } else { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Handle is NULL and Pathname is relative\n")); } status = AE_BAD_PARAMETER; } else { /* * We get here if we have a handle -- and if we have a * pathname it is relative. The handle will be validated * in the lower procedures */ if (!pathname) { /* * The null pathname case means the handle is for * the actual object to be evaluated */ status = acpi_ns_evaluate_by_handle(&info); } else { /* * Both a Handle and a relative Pathname */ status = acpi_ns_evaluate_relative(pathname, &info); } } /* * If we are expecting a return value, and all went well above, * copy the return value to an external object. */ if (return_buffer) { if (!info.return_object) { return_buffer->length = 0; } else { if (ACPI_GET_DESCRIPTOR_TYPE(info.return_object) == ACPI_DESC_TYPE_NAMED) { /* * If we received a NS Node as a return object, this means that * the object we are evaluating has nothing interesting to * return (such as a mutex, etc.) We return an error because * these types are essentially unsupported by this interface. * We don't check up front because this makes it easier to add * support for various types at a later date if necessary. */ status = AE_TYPE; info.return_object = NULL; /* No need to delete a NS Node */ return_buffer->length = 0; } if (ACPI_SUCCESS(status)) { /* * Find out how large a buffer is needed * to contain the returned object */ status = acpi_ut_get_object_size(info.return_object, &buffer_space_needed); if (ACPI_SUCCESS(status)) { /* Validate/Allocate/Clear caller buffer */ status = acpi_ut_initialize_buffer (return_buffer, buffer_space_needed); if (ACPI_FAILURE(status)) { /* * Caller's buffer is too small or a new one can't be allocated */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Needed buffer size %X, %s\n", (u32) buffer_space_needed, acpi_format_exception (status))); } else { /* * We have enough space for the object, build it */ status = acpi_ut_copy_iobject_to_eobject (info.return_object, return_buffer); } } } } } if (info.return_object) { /* * Delete the internal return object. NOTE: Interpreter * must be locked to avoid race condition. */ status2 = acpi_ex_enter_interpreter(); if (ACPI_SUCCESS(status2)) { /* * Delete the internal return object. (Or at least * decrement the reference count by one) */ acpi_ut_remove_reference(info.return_object); acpi_ex_exit_interpreter(); } } /* * Free the input parameter list (if we created one), */ if (info.parameters) { /* Free the allocated parameter block */ acpi_ut_delete_internal_object_list(info.parameters); } return_ACPI_STATUS(status); }
acpi_status acpi_ns_one_complete_parse(u32 pass_number, u32 table_index, struct acpi_namespace_node *start_node) { union acpi_parse_object *parse_root; acpi_status status; u32 aml_length; u8 *aml_start; struct acpi_walk_state *walk_state; struct acpi_table_header *table; acpi_owner_id owner_id; ACPI_FUNCTION_TRACE(ns_one_complete_parse); status = acpi_get_table_by_index(table_index, &table); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Table must consist of at least a complete header */ if (table->length < sizeof(struct acpi_table_header)) { return_ACPI_STATUS(AE_BAD_HEADER); } aml_start = (u8 *)table + sizeof(struct acpi_table_header); aml_length = table->length - sizeof(struct acpi_table_header); status = acpi_tb_get_owner_id(table_index, &owner_id); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Create and init a Root Node */ parse_root = acpi_ps_create_scope_op(aml_start); if (!parse_root) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL); if (!walk_state) { acpi_ps_free_op(parse_root); return_ACPI_STATUS(AE_NO_MEMORY); } status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL, aml_start, aml_length, NULL, (u8)pass_number); if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); goto cleanup; } /* Found OSDT table, enable the namespace override feature */ if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_OSDT) && pass_number == ACPI_IMODE_LOAD_PASS1) { walk_state->namespace_override = TRUE; } /* start_node is the default location to load the table */ if (start_node && start_node != acpi_gbl_root_node) { status = acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD, walk_state); if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); goto cleanup; } } /* Parse the AML */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "*PARSE* pass %u parse\n", pass_number)); acpi_ex_enter_interpreter(); status = acpi_ps_parse_aml(walk_state); acpi_ex_exit_interpreter(); cleanup: acpi_ps_delete_parse_tree(parse_root); return_ACPI_STATUS(status); }
/******************************************************************************* * * FUNCTION: acpi_evaluate_object * * PARAMETERS: handle - Object handle (optional) * pathname - Object pathname (optional) * external_params - List of parameters to pass to method, * terminated by NULL. May be NULL * if no parameters are being passed. * return_buffer - Where to put method's return value (if * any). If NULL, no value is returned. * * RETURN: Status * * DESCRIPTION: Find and evaluate the given object, passing the given * parameters if necessary. One of "Handle" or "Pathname" must * be valid (non-null) * ******************************************************************************/ acpi_status acpi_evaluate_object(acpi_handle handle, acpi_string pathname, struct acpi_object_list *external_params, struct acpi_buffer *return_buffer) { acpi_status status; struct acpi_evaluate_info *info; acpi_size buffer_space_needed; u32 i; ACPI_FUNCTION_TRACE(acpi_evaluate_object); /* Allocate and initialize the evaluation information block */ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); if (!info) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Convert and validate the device handle */ info->prefix_node = acpi_ns_validate_handle(handle); if (!info->prefix_node) { status = AE_BAD_PARAMETER; goto cleanup; } /* * Get the actual namespace node for the target object. * Handles these cases: * * 1) Null node, valid pathname from root (absolute path) * 2) Node and valid pathname (path relative to Node) * 3) Node, Null pathname */ if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) { /* The path is fully qualified, just evaluate by name */ info->prefix_node = NULL; } else if (!handle) { /* * A handle is optional iff a fully qualified pathname is specified. * Since we've already handled fully qualified names above, this is * an error. */ if (!pathname) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Both Handle and Pathname are NULL")); } else { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Null Handle with relative pathname [%s]", pathname)); } status = AE_BAD_PARAMETER; goto cleanup; } info->relative_pathname = pathname; /* * Convert all external objects passed as arguments to the * internal version(s). */ if (external_params && external_params->count) { info->param_count = (u16)external_params->count; /* Warn on impossible argument count */ if (info->param_count > ACPI_METHOD_NUM_ARGS) { ACPI_WARN_PREDEFINED((AE_INFO, pathname, ACPI_WARN_ALWAYS, "Excess arguments (%u) - using only %u", info->param_count, ACPI_METHOD_NUM_ARGS)); info->param_count = ACPI_METHOD_NUM_ARGS; } /* * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) info-> param_count + 1) * sizeof(void *)); if (!info->parameters) { status = AE_NO_MEMORY; goto cleanup; } /* Convert each external object in the list to an internal object */ for (i = 0; i < info->param_count; i++) { status = acpi_ut_copy_eobject_to_iobject(&external_params-> pointer[i], &info-> parameters[i]); if (ACPI_FAILURE(status)) { goto cleanup; } } info->parameters[info->param_count] = NULL; } #if 0 /* * Begin incoming argument count analysis. Check for too few args * and too many args. */ switch (acpi_ns_get_type(info->node)) { case ACPI_TYPE_METHOD: /* Check incoming argument count against the method definition */ if (info->obj_desc->method.param_count > info->param_count) { ACPI_ERROR((AE_INFO, "Insufficient arguments (%u) - %u are required", info->param_count, info->obj_desc->method.param_count)); status = AE_MISSING_ARGUMENTS; goto cleanup; } else if (info->obj_desc->method.param_count < info->param_count) { ACPI_WARNING((AE_INFO, "Excess arguments (%u) - only %u are required", info->param_count, info->obj_desc->method.param_count)); /* Just pass the required number of arguments */ info->param_count = info->obj_desc->method.param_count; } /* * Any incoming external objects to be passed as arguments to the * method must be converted to internal objects */ if (info->param_count) { /* * Allocate a new parameter block for the internal objects * Add 1 to count to allow for null terminated internal list */ info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) info-> param_count + 1) * sizeof(void *)); if (!info->parameters) { status = AE_NO_MEMORY; goto cleanup; } /* Convert each external object in the list to an internal object */ for (i = 0; i < info->param_count; i++) { status = acpi_ut_copy_eobject_to_iobject (&external_params->pointer[i], &info->parameters[i]); if (ACPI_FAILURE(status)) { goto cleanup; } } info->parameters[info->param_count] = NULL; } break; default: /* Warn if arguments passed to an object that is not a method */ if (info->param_count) { ACPI_WARNING((AE_INFO, "%u arguments were passed to a non-method ACPI object", info->param_count)); } break; } #endif /* Now we can evaluate the object */ status = acpi_ns_evaluate(info); /* * If we are expecting a return value, and all went well above, * copy the return value to an external object. */ if (return_buffer) { if (!info->return_object) { return_buffer->length = 0; } else { if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) == ACPI_DESC_TYPE_NAMED) { /* * If we received a NS Node as a return object, this means that * the object we are evaluating has nothing interesting to * return (such as a mutex, etc.) We return an error because * these types are essentially unsupported by this interface. * We don't check up front because this makes it easier to add * support for various types at a later date if necessary. */ status = AE_TYPE; info->return_object = NULL; /* No need to delete a NS Node */ return_buffer->length = 0; } if (ACPI_SUCCESS(status)) { /* Dereference Index and ref_of references */ acpi_ns_resolve_references(info); /* Get the size of the returned object */ status = acpi_ut_get_object_size(info->return_object, &buffer_space_needed); if (ACPI_SUCCESS(status)) { /* Validate/Allocate/Clear caller buffer */ status = acpi_ut_initialize_buffer (return_buffer, buffer_space_needed); if (ACPI_FAILURE(status)) { /* * Caller's buffer is too small or a new one can't * be allocated */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Needed buffer size %X, %s\n", (u32) buffer_space_needed, acpi_format_exception (status))); } else { /* We have enough space for the object, build it */ status = acpi_ut_copy_iobject_to_eobject (info->return_object, return_buffer); } } } } } if (info->return_object) { /* * Delete the internal return object. NOTE: Interpreter must be * locked to avoid race condition. */ acpi_ex_enter_interpreter(); /* Remove one reference on the return object (should delete it) */ acpi_ut_remove_reference(info->return_object); acpi_ex_exit_interpreter(); } cleanup: /* Free the input parameter list (if we created one) */ if (info->parameters) { /* Free the allocated parameter block */ acpi_ut_delete_internal_object_list(info->parameters); } ACPI_FREE(info); return_ACPI_STATUS(status); }
acpi_status acpi_ns_init_one_object ( acpi_handle obj_handle, u32 level, void *context, void **return_value) { acpi_object_type8 type; acpi_status status; acpi_init_walk_info *info = (acpi_init_walk_info *) context; acpi_namespace_node *node = (acpi_namespace_node *) obj_handle; acpi_operand_object *obj_desc; PROC_NAME ("Ns_init_one_object"); info->object_count++; /* And even then, we are only interested in a few object types */ type = acpi_ns_get_type (obj_handle); obj_desc = node->object; if (!obj_desc) { return (AE_OK); } if ((type != ACPI_TYPE_REGION) && (type != ACPI_TYPE_BUFFER_FIELD)) { return (AE_OK); } /* * Must lock the interpreter before executing AML code */ status = acpi_ex_enter_interpreter (); if (ACPI_FAILURE (status)) { return (status); } switch (type) { case ACPI_TYPE_REGION: info->op_region_count++; if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { break; } info->op_region_init++; status = acpi_ds_get_region_arguments (obj_desc); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n")); ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s while getting region arguments [%4.4s]\n", acpi_format_exception (status), (char*)&node->name)); } if (!(acpi_dbg_level & ACPI_LV_INIT)) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, ".")); } break; case ACPI_TYPE_BUFFER_FIELD: info->field_count++; if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { break; } info->field_init++; status = acpi_ds_get_buffer_field_arguments (obj_desc); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "\n")); ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s while getting buffer field arguments [%4.4s]\n", acpi_format_exception (status), (char*)&node->name)); } if (!(acpi_dbg_level & ACPI_LV_INIT)) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, ".")); } break; default: break; } /* * We ignore errors from above, and always return OK, since * we don't want to abort the walk on a single error. */ acpi_ex_exit_interpreter (); return (AE_OK); }
acpi_status acpi_ns_get_object_value ( acpi_namespace_node *node, acpi_operand_object **return_obj_desc) { acpi_status status = AE_OK; acpi_operand_object *obj_desc; acpi_operand_object *source_desc; FUNCTION_TRACE ("Ns_get_object_value"); /* * We take the value from certain objects directly */ if ((node->type == ACPI_TYPE_PROCESSOR) || (node->type == ACPI_TYPE_POWER)) { /* * Create a Reference object to contain the object */ obj_desc = acpi_ut_create_internal_object (node->type); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* * Get the attached object */ source_desc = acpi_ns_get_attached_object (node); if (!source_desc) { status = AE_NULL_OBJECT; goto unlock_and_exit; } /* * Just copy from the original to the return object * * TBD: [Future] - need a low-level object copy that handles * the reference count automatically. (Don't want to copy it) */ MEMCPY (obj_desc, source_desc, sizeof (acpi_operand_object)); obj_desc->common.reference_count = 1; acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); } /* * Other objects require a reference object wrapper which we * then attempt to resolve. */ else { /* Create an Reference object to contain the object */ obj_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE); if (!obj_desc) { status = AE_NO_MEMORY; goto unlock_and_exit; } /* Construct a descriptor pointing to the name */ obj_desc->reference.opcode = (u8) AML_NAME_OP; obj_desc->reference.object = (void *) node; /* * Use Resolve_to_value() to get the associated value. This call * always deletes Obj_desc (allocated above). * * NOTE: we can get away with passing in NULL for a walk state * because Obj_desc is guaranteed to not be a reference to either * a method local or a method argument * * Even though we do not directly invoke the interpreter * for this, we must enter it because we could access an opregion. * The opregion access code assumes that the interpreter * is locked. * * We must release the namespace lock before entering the * intepreter. */ acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); status = acpi_ex_enter_interpreter (); if (ACPI_SUCCESS (status)) { status = acpi_ex_resolve_to_value (&obj_desc, NULL); acpi_ex_exit_interpreter (); } } /* * If Acpi_ex_resolve_to_value() succeeded, the return value was * placed in Obj_desc. */ if (ACPI_SUCCESS (status)) { status = AE_CTRL_RETURN_VALUE; *return_obj_desc = obj_desc; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Returning obj %p\n", *return_obj_desc)); } /* Namespace is unlocked */ return_ACPI_STATUS (status); unlock_and_exit: /* Unlock the namespace */ acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (status); }