/******************************************************************************* * * FUNCTION: acpi_ex_resolve_node_to_value * * PARAMETERS: object_ptr - Pointer to a location that contains * a pointer to a NS node, and will receive a * pointer to the resolved object. * walk_state - Current state. Valid only if executing AML * code. NULL if simply resolving an object * * RETURN: Status * * DESCRIPTION: Resolve a Namespace node to a valued object * * Note: for some of the data types, the pointer attached to the Node * can be either a pointer to an actual internal object or a pointer into the * AML stream itself. These types are currently: * * ACPI_TYPE_INTEGER * ACPI_TYPE_STRING * ACPI_TYPE_BUFFER * ACPI_TYPE_MUTEX * ACPI_TYPE_PACKAGE * ******************************************************************************/ acpi_status acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, struct acpi_walk_state *walk_state) { acpi_status status = AE_OK; union acpi_operand_object *source_desc; union acpi_operand_object *obj_desc = NULL; struct acpi_namespace_node *node; acpi_object_type entry_type; ACPI_FUNCTION_TRACE(ex_resolve_node_to_value); /* * The stack pointer points to a struct acpi_namespace_node (Node). Get the * object that is attached to the Node. */ node = *object_ptr; source_desc = acpi_ns_get_attached_object(node); entry_type = acpi_ns_get_type((acpi_handle)node); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n", node, source_desc, acpi_ut_get_type_name(entry_type))); if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) || (entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { /* There is always exactly one level of indirection */ node = ACPI_CAST_PTR(struct acpi_namespace_node, node->object); source_desc = acpi_ns_get_attached_object(node); entry_type = acpi_ns_get_type((acpi_handle)node); *object_ptr = node; }
static u8 acpi_ev_has_default_handler(struct acpi_namespace_node *node, acpi_adr_space_type space_id) { union acpi_operand_object *obj_desc; union acpi_operand_object *handler_obj; /* Must have an existing internal object */ obj_desc = acpi_ns_get_attached_object(node); if (obj_desc) { handler_obj = obj_desc->device.handler; /* Walk the linked list of handlers for this object */ while (handler_obj) { if (handler_obj->address_space.space_id == space_id) { if (handler_obj->address_space.handler_flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { return (TRUE); } } handler_obj = handler_obj->address_space.next; } } return (FALSE); }
void acpi_ns_terminate (void) { union acpi_operand_object *obj_desc; ACPI_FUNCTION_TRACE ("ns_terminate"); /* * 1) Free the entire namespace -- all nodes and objects * * Delete all object descriptors attached to namepsace nodes */ acpi_ns_delete_namespace_subtree (acpi_gbl_root_node); /* Detach any objects attached to the root */ obj_desc = acpi_ns_get_attached_object (acpi_gbl_root_node); if (obj_desc) { acpi_ns_detach_object (acpi_gbl_root_node); } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n")); /* * 2) Now we can delete the ACPI tables */ acpi_tb_delete_all_tables (); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n")); return_VOID; }
acpi_object_type acpi_ds_method_data_get_type(u16 opcode, u32 index, struct acpi_walk_state *walk_state) { acpi_status status; struct acpi_namespace_node *node; union acpi_operand_object *object; ACPI_FUNCTION_TRACE(ds_method_data_get_type); /* Get the namespace node for the arg/local */ status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); if (ACPI_FAILURE(status)) { return_VALUE((ACPI_TYPE_NOT_FOUND)); } /* Get the object */ object = acpi_ns_get_attached_object(node); if (!object) { /* Uninitialized local/arg, return TYPE_ANY */ return_VALUE(ACPI_TYPE_ANY); } /* Get the object type */ return_VALUE(ACPI_GET_OBJECT_TYPE(object)); }
void acpi_ex_dump_node ( struct acpi_namespace_node *node, u32 flags) { ACPI_FUNCTION_ENTRY (); if (!flags) { if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) { return; } } acpi_os_printf ("%20s : %4.4s\n", "Name", acpi_ut_get_node_name (node)); acpi_ex_out_string ("Type", acpi_ut_get_type_name (node->type)); acpi_ex_out_integer ("Flags", node->flags); acpi_ex_out_integer ("Owner Id", node->owner_id); acpi_ex_out_integer ("Reference Count", node->reference_count); acpi_ex_out_pointer ("Attached Object", acpi_ns_get_attached_object (node)); acpi_ex_out_pointer ("child_list", node->child); acpi_ex_out_pointer ("next_peer", node->peer); acpi_ex_out_pointer ("Parent", acpi_ns_get_parent_node (node)); }
acpi_status acpi_ns_init_one_package(acpi_handle obj_handle, u32 level, void *context, void **return_value) { acpi_status status; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node = (struct acpi_namespace_node *)obj_handle; obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { return (AE_OK); } /* Exit if package is already initialized */ if (obj_desc->package.flags & AOPOBJ_DATA_VALID) { return (AE_OK); } status = acpi_ds_get_package_arguments(obj_desc); if (ACPI_FAILURE(status)) { return (AE_OK); } status = acpi_ut_walk_package_tree(obj_desc, NULL, acpi_ds_init_package_element, NULL); if (ACPI_FAILURE(status)) { return (AE_OK); } obj_desc->package.flags |= AOPOBJ_DATA_VALID; return (AE_OK); }
static acpi_status acpi_db_walk_for_references(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { union acpi_operand_object *obj_desc = (union acpi_operand_object *)context; struct acpi_namespace_node *node = (struct acpi_namespace_node *)obj_handle; /* Check for match against the namespace node itself */ if (node == (void *)obj_desc) { acpi_os_printf("Object is a Node [%4.4s]\n", acpi_ut_get_node_name(node)); } /* Check for match against the object attached to the node */ if (acpi_ns_get_attached_object(node) == obj_desc) { acpi_os_printf("Reference at Node->Object %p [%4.4s]\n", node, acpi_ut_get_node_name(node)); } return (AE_OK); }
static void acpi_db_decode_node(struct acpi_namespace_node *node) { acpi_os_printf("<Node> Name %4.4s", acpi_ut_get_node_name(node)); if (node->flags & ANOBJ_METHOD_ARG) { acpi_os_printf(" [Method Arg]"); } if (node->flags & ANOBJ_METHOD_LOCAL) { acpi_os_printf(" [Method Local]"); } switch (node->type) { /* These types have no attached object */ case ACPI_TYPE_DEVICE: acpi_os_printf(" Device"); break; case ACPI_TYPE_THERMAL: acpi_os_printf(" Thermal Zone"); break; default: acpi_db_decode_internal_object(acpi_ns_get_attached_object (node)); break; } }
ACPI_STATUS acpi_ns_execute_control_method ( ACPI_NAMESPACE_NODE *method_node, ACPI_OPERAND_OBJECT **params, ACPI_OPERAND_OBJECT **return_obj_desc) { ACPI_STATUS status; ACPI_OPERAND_OBJECT *obj_desc; /* Verify that there is a method associated with this object */ obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) method_node); if (!obj_desc) { return (AE_ERROR); } /* * Unlock the namespace before execution. This allows namespace access * via the external Acpi* interfaces while a method is being executed. * However, any namespace deletion must acquire both the namespace and * interpreter locks to ensure that no thread is using the portion of the * namespace that is being deleted. */ acpi_cm_release_mutex (ACPI_MTX_NAMESPACE); /* * Excecute the method via the interpreter */ status = acpi_aml_execute_method (method_node, params, return_obj_desc); return (status); }
acpi_status acpi_ns_evaluate_by_name(char *pathname, struct acpi_parameter_info *info) { acpi_status status; char *internal_path = NULL; ACPI_FUNCTION_TRACE("ns_evaluate_by_name"); /* Build an internal name string for the method */ status = acpi_ns_internalize_name(pathname, &internal_path); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { goto cleanup; } /* Lookup the name in the namespace */ status = acpi_ns_lookup(NULL, internal_path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, &info->node); (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Object at [%s] was not found, status=%.4X\n", pathname, status)); goto cleanup; } /* * Now that we have a handle to the object, we can attempt to evaluate it. */ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", pathname, info->node, acpi_ns_get_attached_object(info->node))); status = acpi_ns_evaluate_by_handle(info); ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "*** Completed eval of object %s ***\n", pathname)); cleanup: /* Cleanup */ if (internal_path) { ACPI_MEM_FREE(internal_path); } return_ACPI_STATUS(status); }
static acpi_status acpi_db_integrity_walk(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { struct acpi_integrity_info *info = (struct acpi_integrity_info *)context; struct acpi_namespace_node *node = (struct acpi_namespace_node *)obj_handle; union acpi_operand_object *object; u8 alias = TRUE; info->nodes++; /* Verify the NS node, and dereference aliases */ while (alias) { if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) { acpi_os_printf ("Invalid Descriptor Type for Node %p [%s] - " "is %2.2X should be %2.2X\n", node, acpi_ut_get_descriptor_name(node), ACPI_GET_DESCRIPTOR_TYPE(node), ACPI_DESC_TYPE_NAMED); return (AE_OK); } if ((node->type == ACPI_TYPE_LOCAL_ALIAS) || (node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { node = (struct acpi_namespace_node *)node->object; } else { alias = FALSE; } } if (node->type > ACPI_TYPE_LOCAL_MAX) { acpi_os_printf("Invalid Object Type for Node %p, Type = %X\n", node, node->type); return (AE_OK); } if (!acpi_ut_valid_nameseg(node->name.ascii)) { acpi_os_printf("Invalid AcpiName for Node %p\n", node); return (AE_OK); } object = acpi_ns_get_attached_object(node); if (object) { info->objects++; if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) { acpi_os_printf ("Invalid Descriptor Type for Object %p [%s]\n", object, acpi_ut_get_descriptor_name(object)); } } return (AE_OK); }
acpi_status acpi_ns_execute_control_method ( acpi_namespace_node *method_node, acpi_operand_object **params, acpi_operand_object **return_obj_desc) { acpi_status status; acpi_operand_object *obj_desc; FUNCTION_TRACE ("Ns_execute_control_method"); /* Verify that there is a method associated with this object */ obj_desc = acpi_ns_get_attached_object (method_node); if (!obj_desc) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n")); acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (AE_NULL_OBJECT); } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Control method at Offset %p Length %x]\n", obj_desc->method.aml_start + 1, obj_desc->method.aml_length - 1)); DUMP_PATHNAME (method_node, "Ns_execute_control_method: Executing", ACPI_LV_NAMES, _COMPONENT); ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "At offset %p\n", obj_desc->method.aml_start + 1)); /* * Unlock the namespace before execution. This allows namespace access * via the external Acpi* interfaces while a method is being executed. * However, any namespace deletion must acquire both the namespace and * interpreter locks to ensure that no thread is using the portion of the * namespace that is being deleted. */ acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); /* * Execute the method via the interpreter. The interpreter is locked * here before calling into the AML parser */ status = acpi_ex_enter_interpreter (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } status = acpi_psx_execute (method_node, params, return_obj_desc); acpi_ex_exit_interpreter (); return_ACPI_STATUS (status); }
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, u32 gpe_number) { union acpi_operand_object *obj_desc; struct acpi_gpe_block_info *gpe_block; acpi_native_uint i; ACPI_FUNCTION_ENTRY(); /* A NULL gpe_block means use the FADT-defined GPE block(s) */ if (!gpe_device) { /* Examine GPE Block 0 and 1 (These blocks are permanent) */ for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) { gpe_block = acpi_gbl_gpe_fadt_blocks[i]; if (gpe_block) { if ((gpe_number >= gpe_block->block_base_number) && (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) { return (&gpe_block-> event_info[gpe_number - gpe_block-> block_base_number]); } } } /* The gpe_number was not in the range of either FADT GPE block */ return (NULL); } /* A Non-NULL gpe_device means this is a GPE Block Device */ obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *) gpe_device); if (!obj_desc || !obj_desc->device.gpe_block) { return (NULL); } gpe_block = obj_desc->device.gpe_block; if ((gpe_number >= gpe_block->block_base_number) && (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) { return (&gpe_block-> event_info[gpe_number - gpe_block->block_base_number]); } return (NULL); }
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, u32 gpe_number) { union acpi_operand_object *obj_desc; struct acpi_gpe_block_info *gpe_block; u32 i; ACPI_FUNCTION_ENTRY(); if (!gpe_device) { for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) { gpe_block = acpi_gbl_gpe_fadt_blocks[i]; if (gpe_block) { if ((gpe_number >= gpe_block->block_base_number) && (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) { return (&gpe_block-> event_info[gpe_number - gpe_block-> block_base_number]); } } } return (NULL); } obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *) gpe_device); if (!obj_desc || !obj_desc->device.gpe_block) { return (NULL); } gpe_block = obj_desc->device.gpe_block; if ((gpe_number >= gpe_block->block_base_number) && (gpe_number < gpe_block->block_base_number + (gpe_block->register_count * 8))) { return (&gpe_block-> event_info[gpe_number - gpe_block->block_base_number]); } return (NULL); }
acpi_status acpi_ds_initialize_region(acpi_handle obj_handle) { union acpi_operand_object *obj_desc; acpi_status status; obj_desc = acpi_ns_get_attached_object(obj_handle); /* Namespace is NOT locked */ status = acpi_ev_initialize_region(obj_desc, FALSE); return (status); }
static acpi_status acpi_db_classify_one_object(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { struct acpi_namespace_node *node; union acpi_operand_object *obj_desc; u32 type; acpi_gbl_num_nodes++; node = (struct acpi_namespace_node *)obj_handle; obj_desc = acpi_ns_get_attached_object(node); acpi_db_enumerate_object(obj_desc); type = node->type; if (type > ACPI_TYPE_NS_NODE_MAX) { acpi_gbl_node_type_count_misc++; } else { acpi_gbl_node_type_count[type]++; } return (AE_OK); #ifdef ACPI_FUTURE_IMPLEMENTATION /* TBD: These need to be counted during the initial parsing phase */ if (acpi_ps_is_named_op(op->opcode)) { num_nodes++; } if (is_method) { num_method_elements++; } num_grammar_elements++; op = acpi_ps_get_depth_next(root, op); size_of_parse_tree = (num_grammar_elements - num_method_elements) * (u32)sizeof(union acpi_parse_object); size_of_method_trees = num_method_elements * (u32)sizeof(union acpi_parse_object); size_of_node_entries = num_nodes * (u32)sizeof(struct acpi_namespace_node); size_of_acpi_objects = num_nodes * (u32)sizeof(union acpi_operand_object); #endif }
static acpi_status acpi_ev_reg_run(acpi_handle obj_handle, u32 level, void *context, void **return_value) { union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; acpi_status status; struct acpi_reg_walk_info *info; info = ACPI_CAST_PTR(struct acpi_reg_walk_info, context); /* Convert and validate the device handle */ node = acpi_ns_validate_handle(obj_handle); if (!node) { return (AE_BAD_PARAMETER); } /* * We only care about regions.and objects that are allowed to have address * space handlers */ if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { return (AE_OK); } /* Check for an existing internal object */ obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { /* No object, just exit */ return (AE_OK); } /* Object is a Region */ if (obj_desc->region.space_id != info->space_id) { /* This region is for a different address space, just ignore it */ return (AE_OK); } info->reg_run_count++; status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT); return (status); }
/******************************************************************************* * * FUNCTION: acpi_remove_gpe_block * * PARAMETERS: gpe_device - Handle to the parent GPE Block Device * * RETURN: Status * * DESCRIPTION: Remove a previously installed block of GPE registers * ******************************************************************************/ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) { union acpi_operand_object *obj_desc; acpi_status status; struct acpi_namespace_node *node; ACPI_FUNCTION_TRACE(acpi_remove_gpe_block); if (!gpe_device) { return_ACPI_STATUS(AE_BAD_PARAMETER); } status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } node = acpi_ns_validate_handle(gpe_device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } /* Validate the parent device */ if (node->type != ACPI_TYPE_DEVICE) { status = AE_TYPE; goto unlock_and_exit; } /* Get the device_object attached to the node */ obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc || !obj_desc->device.gpe_block) { return_ACPI_STATUS(AE_NULL_OBJECT); } /* Delete the GPE block (but not the device_object) */ status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block); if (ACPI_SUCCESS(status)) { obj_desc->device.gpe_block = NULL; } unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); return_ACPI_STATUS(status); }
void acpi_ds_method_data_delete_value ( u16 opcode, u32 index, struct acpi_walk_state *walk_state) { acpi_status status; struct acpi_namespace_node *node; union acpi_operand_object *object; ACPI_FUNCTION_TRACE ("ds_method_data_delete_value"); /* Get the namespace node for the arg/local */ status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node); if (ACPI_FAILURE (status)) { return_VOID; } /* Get the associated object */ object = acpi_ns_get_attached_object (node); /* * Undefine the Arg or Local by setting its descriptor * pointer to NULL. Locals/Args can contain both * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs */ node->object = NULL; if ((object) && (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_OPERAND)) { /* * There is a valid object. * Decrement the reference count by one to balance the * increment when the object was stored. */ acpi_ut_remove_reference (object); } return_VOID; }
static acpi_status acpi_db_display_non_root_handlers(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { struct acpi_namespace_node *node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); union acpi_operand_object *obj_desc; union acpi_operand_object *handler_obj; char *pathname; obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { return (AE_OK); } pathname = acpi_ns_get_normalized_pathname(node, TRUE); if (!pathname) { return (AE_OK); } /* Display all handlers associated with this device */ handler_obj = obj_desc->common_notify.handler; while (handler_obj) { acpi_os_printf(ACPI_PREDEFINED_PREFIX, acpi_ut_get_region_name((u8)handler_obj-> address_space.space_id), handler_obj->address_space.space_id); acpi_os_printf(ACPI_HANDLER_PRESENT_STRING2, (handler_obj->address_space.handler_flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) ? "Default" : "User", handler_obj->address_space.handler); acpi_os_printf(" Device Name: %s (%p)\n", pathname, node); handler_obj = handler_obj->address_space.next; } ACPI_FREE(pathname); return (AE_OK); }
static acpi_status acpi_ut_get_mutex_object(acpi_handle handle, acpi_string pathname, union acpi_operand_object **ret_obj) { struct acpi_namespace_node *mutex_node; union acpi_operand_object *mutex_obj; acpi_status status; /* Parameter validation */ if (!ret_obj || (!handle && !pathname)) { return (AE_BAD_PARAMETER); } /* Get a the namespace node for the mutex */ mutex_node = handle; if (pathname != NULL) { status = acpi_get_handle(handle, pathname, ACPI_CAST_PTR(acpi_handle, &mutex_node)); if (ACPI_FAILURE(status)) { return (status); } } /* Ensure that we actually have a Mutex object */ if (!mutex_node || (mutex_node->type != ACPI_TYPE_MUTEX)) { return (AE_TYPE); } /* Get the low-level mutex object */ mutex_obj = acpi_ns_get_attached_object(mutex_node); if (!mutex_obj) { return (AE_NULL_OBJECT); } *ret_obj = mutex_obj; return (AE_OK); }
ACPI_STATUS acpi_ds_begin_method_execution ( ACPI_NAMESPACE_NODE *method_node, ACPI_OPERAND_OBJECT *obj_desc) { ACPI_STATUS status = AE_OK; if (!method_node) { return (AE_NULL_ENTRY); } obj_desc = acpi_ns_get_attached_object (method_node); if (!obj_desc) { return (AE_NULL_OBJECT); } /* * If there is a concurrency limit on this method, we need to * obtain a unit from the method semaphore. This releases the * interpreter if we block */ if (obj_desc->method.semaphore) { status = acpi_aml_system_wait_semaphore (obj_desc->method.semaphore, WAIT_FOREVER); } /* * Increment the method parse tree thread count since there * is one additional thread executing in it. If configured * for deletion-on-exit, the parse tree will be deleted when * the last thread completes execution of the method */ obj_desc->method.thread_count++; return (status); }
struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, u32 gpe_number) { union acpi_operand_object *obj_desc; struct acpi_gpe_event_info *gpe_info; u32 i; ACPI_FUNCTION_ENTRY(); /* A NULL gpe_device means use the FADT-defined GPE block(s) */ if (!gpe_device) { /* Examine GPE Block 0 and 1 (These blocks are permanent) */ for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) { gpe_info = acpi_ev_low_get_gpe_info(gpe_number, acpi_gbl_gpe_fadt_blocks [i]); if (gpe_info) { return (gpe_info); } } /* The gpe_number was not in the range of either FADT GPE block */ return (NULL); } /* A Non-NULL gpe_device means this is a GPE Block Device */ obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *) gpe_device); if (!obj_desc || !obj_desc->device.gpe_block) { return (NULL); } return (acpi_ev_low_get_gpe_info (gpe_number, obj_desc->device.gpe_block)); }
void acpi_ns_terminate (void) { acpi_operand_object *obj_desc; acpi_namespace_node *this_node; FUNCTION_TRACE ("Ns_terminate"); this_node = acpi_gbl_root_node; /* * 1) Free the entire namespace -- all objects, tables, and stacks * * Delete all objects linked to the root * (additional table descriptors) */ acpi_ns_delete_namespace_subtree (this_node); /* Detach any object(s) attached to the root */ obj_desc = acpi_ns_get_attached_object (this_node); if (obj_desc) { acpi_ns_detach_object (this_node); acpi_ut_remove_reference (obj_desc); } acpi_ns_delete_children (this_node); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n")); /* * 2) Now we can delete the ACPI tables */ acpi_tb_delete_acpi_tables (); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n")); return_VOID; }
void acpi_ex_dump_namespace_node(struct acpi_namespace_node *node, u32 flags) { ACPI_FUNCTION_ENTRY(); if (!flags) { if (! ((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) { return; } } acpi_os_printf("%20s : %4.4s\n", "Name", acpi_ut_get_node_name(node)); acpi_ex_out_string("Type", acpi_ut_get_type_name(node->type)); acpi_ex_out_pointer("Attached Object", acpi_ns_get_attached_object(node)); acpi_ex_out_pointer("Parent", acpi_ns_get_parent_node(node)); acpi_ex_dump_object(ACPI_CAST_PTR(union acpi_operand_object, node), acpi_ex_dump_node); }
acpi_status acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, union acpi_parse_object *op, struct acpi_namespace_node *method_node, u8 * aml_start, u32 aml_length, struct acpi_evaluate_info *info, u8 pass_number) { acpi_status status; struct acpi_parse_state *parser_state = &walk_state->parser_state; union acpi_parse_object *extra_op; ACPI_FUNCTION_TRACE(ds_init_aml_walk); walk_state->parser_state.aml = walk_state->parser_state.aml_start = aml_start; walk_state->parser_state.aml_end = walk_state->parser_state.pkg_end = aml_start + aml_length; /* The next_op of the next_walk will be the beginning of the method */ walk_state->next_op = NULL; walk_state->pass_number = pass_number; if (info) { walk_state->params = info->parameters; walk_state->caller_return_desc = &info->return_object; } status = acpi_ps_init_scope(&walk_state->parser_state, op); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (method_node) { walk_state->parser_state.start_node = method_node; walk_state->walk_type = ACPI_WALK_METHOD; walk_state->method_node = method_node; walk_state->method_desc = acpi_ns_get_attached_object(method_node); /* 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_ACPI_STATUS(status); } /* Init the method arguments */ status = acpi_ds_method_data_init_args(walk_state->params, ACPI_METHOD_NUM_ARGS, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } else { /* * Setup the current scope. * Find a Named Op that has a namespace node associated with it. * search upwards from this Op. Current scope is the first * Op with a namespace node. */ extra_op = parser_state->start_op; while (extra_op && !extra_op->common.node) { extra_op = extra_op->common.parent; } if (!extra_op) { parser_state->start_node = NULL; } else { parser_state->start_node = extra_op->common.node; } if (parser_state->start_node) { /* Push start scope on scope stack and make it current */ status = acpi_ds_scope_stack_push(parser_state->start_node, parser_state->start_node-> type, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } } status = acpi_ds_init_callbacks(walk_state, pass_number); return_ACPI_STATUS(status); }
acpi_status acpi_ds_call_control_method(struct acpi_thread_state *thread, struct acpi_walk_state *this_walk_state, union acpi_parse_object *op) { acpi_status status; struct acpi_namespace_node *method_node; struct acpi_walk_state *next_walk_state = NULL; union acpi_operand_object *obj_desc; struct acpi_evaluate_info *info; u32 i; ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state); ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Calling method %p, currentstate=%p\n", this_walk_state->prev_op, this_walk_state)); /* * Get the namespace entry for the control method we are about to call */ method_node = this_walk_state->method_call_node; 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, possibly wait on method mutex */ status = acpi_ds_begin_method_execution(method_node, obj_desc, this_walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Begin method parse/execution. Create a new walk state */ next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, obj_desc, thread); if (!next_walk_state) { status = AE_NO_MEMORY; goto cleanup; } /* * The resolved arguments were put on the previous walk state's operand * stack. Operands on the previous walk state stack always * start at index 0. Also, null terminate the list of arguments */ this_walk_state->operands[this_walk_state->num_operands] = NULL; /* * Allocate and initialize the evaluation information block * TBD: this is somewhat inefficient, should change interface to * ds_init_aml_walk. For now, keeps this struct off the CPU stack */ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); if (!info) { return_ACPI_STATUS(AE_NO_MEMORY); } info->parameters = &this_walk_state->operands[0]; info->parameter_type = ACPI_PARAM_ARGS; status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node, obj_desc->method.aml_start, obj_desc->method.aml_length, info, ACPI_IMODE_EXECUTE); ACPI_FREE(info); if (ACPI_FAILURE(status)) { goto cleanup; } /* * Delete the operands on the previous walkstate operand stack * (they were copied to new objects) */ for (i = 0; i < obj_desc->method.param_count; i++) { acpi_ut_remove_reference(this_walk_state->operands[i]); this_walk_state->operands[i] = NULL; } /* Clear the operand stack */ this_walk_state->num_operands = 0; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "**** Begin nested execution of [%4.4s] **** WalkState=%p\n", method_node->name.ascii, next_walk_state)); /* Invoke an internal method if necessary */ if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { status = obj_desc->method.implementation(next_walk_state); } return_ACPI_STATUS(status); cleanup: /* On error, we must terminate the method properly */ acpi_ds_terminate_control_method(obj_desc, next_walk_state); if (next_walk_state) { acpi_ds_delete_walk_state(next_walk_state); } return_ACPI_STATUS(status); }
} /* * For a method alias, we must grab the actual method node so that proper * scoping context will be established before execution. */ if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { info->resolved_node = ACPI_CAST_PTR(struct acpi_namespace_node, info->resolved_node->object); } ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname, info->resolved_node, acpi_ns_get_attached_object(info->resolved_node))); node = info->resolved_node; /* * Two major cases here: * * 1) The object is a control method -- execute it * 2) The object is not a method -- just return it's current value */ if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) { /* * 1) Object is a control method - execute it */ /* Verify that there is a method object associated with this node */
acpi_status acpi_ds_store_object_to_local(u16 opcode, u32 index, union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state) { acpi_status status; struct acpi_namespace_node *node; union acpi_operand_object *current_obj_desc; union acpi_operand_object *new_obj_desc; ACPI_FUNCTION_TRACE(ds_store_object_to_local); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n", opcode, index, obj_desc)); /* Parameter validation */ if (!obj_desc) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Get the namespace node for the arg/local */ status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } current_obj_desc = acpi_ns_get_attached_object(node); if (current_obj_desc == obj_desc) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n", obj_desc)); return_ACPI_STATUS(status); } /* * If the reference count on the object is more than one, we must * take a copy of the object before we store. A reference count * of exactly 1 means that the object was just created during the * evaluation of an expression, and we can safely use it since it * is not used anywhere else. */ new_obj_desc = obj_desc; if (obj_desc->common.reference_count > 1) { status = acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* * If there is an object already in this slot, we either * have to delete it, or if this is an argument and there * is an object reference stored there, we have to do * an indirect store! */ if (current_obj_desc) { /* * Check for an indirect store if an argument * contains an object reference (stored as an Node). * We don't allow this automatic dereferencing for * locals, since a store to a local should overwrite * anything there, including an object reference. * * If both Arg0 and Local0 contain ref_of (Local4): * * Store (1, Arg0) - Causes indirect store to local4 * Store (1, Local0) - Stores 1 in local0, overwriting * the reference to local4 * Store (1, de_refof (Local0)) - Causes indirect store to local4 * * Weird, but true. */ if (opcode == AML_ARG_OP) { /* * If we have a valid reference object that came from ref_of(), * do the indirect store */ if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) == ACPI_DESC_TYPE_OPERAND) && (current_obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) && (current_obj_desc->reference.opcode == AML_REF_OF_OP)) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Arg (%p) is an ObjRef(Node), storing in node %p\n", new_obj_desc, current_obj_desc)); /* * Store this object to the Node (perform the indirect store) * NOTE: No implicit conversion is performed, as per the ACPI * specification rules on storing to Locals/Args. */ status = acpi_ex_store_object_to_node(new_obj_desc, current_obj_desc-> reference. object, walk_state, ACPI_NO_IMPLICIT_CONVERSION); /* Remove local reference if we copied the object above */ if (new_obj_desc != obj_desc) { acpi_ut_remove_reference(new_obj_desc); } return_ACPI_STATUS(status); } } /* * Delete the existing object * before storing the new one */ acpi_ds_method_data_delete_value(opcode, index, walk_state); } /* * Install the Obj descriptor (*new_obj_desc) into * the descriptor for the Arg or Local. * (increments the object reference count by one) */ status = acpi_ds_method_data_set_value(opcode, index, new_obj_desc, walk_state); /* Remove local reference if we copied the object above */ if (new_obj_desc != obj_desc) { acpi_ut_remove_reference(new_obj_desc); } return_ACPI_STATUS(status); }
acpi_status acpi_ev_queue_notify_request ( struct acpi_namespace_node *node, u32 notify_value) { union acpi_operand_object *obj_desc; union acpi_operand_object *handler_obj = NULL; union acpi_generic_state *notify_info; acpi_status status = AE_OK; ACPI_FUNCTION_NAME ("ev_queue_notify_request"); /* * For value 3 (Ejection Request), some device method may need to be run. * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need to be run. * For value 0x80 (Status Change) on the power button or sleep button, * initiate soft-off or sleep operation? */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Dispatching Notify(%X) on node %p\n", notify_value, node)); if (notify_value <= 7) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Notify value: %s\n", acpi_notify_value_names[notify_value])); } else { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "notify value: 0x2.2_x **Device Specific**\n", notify_value)); } /* * Get the notify object attached to the NS Node */ obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { /* We have the notify object, Get the right handler */ switch (node->type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_THERMAL: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: if (notify_value <= ACPI_MAX_SYS_NOTIFY) { handler_obj = obj_desc->common_notify.system_notify; } else { handler_obj = obj_desc->common_notify.device_notify; } break; default: /* All other types are not supported */ return (AE_TYPE); } } /* If there is any handler to run, schedule the dispatcher */ if ((acpi_gbl_system_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) || (acpi_gbl_device_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { notify_info = acpi_ut_create_generic_state (); if (!notify_info) { return (AE_NO_MEMORY); } notify_info->common.data_type = ACPI_DESC_TYPE_STATE_NOTIFY; notify_info->notify.node = node; notify_info->notify.value = (u16) notify_value; notify_info->notify.handler_obj = handler_obj; status = acpi_os_queue_for_execution (OSD_PRIORITY_HIGH, acpi_ev_notify_dispatch, notify_info); if (ACPI_FAILURE (status)) { acpi_ut_delete_generic_state (notify_info); } } if (!handler_obj) { /* There is no per-device notify handler for this device */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for [%4.4s] node %p\n", acpi_ut_get_node_name (node), node)); } return (status); }