void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namespace_node *parent_node, /* Parent */ struct acpi_namespace_node *node, /* New Child */ acpi_object_type type) { acpi_owner_id owner_id = 0; struct acpi_namespace_node *child_node; ACPI_FUNCTION_TRACE(ns_install_node); /* * Get the owner ID from the Walk state * The owner ID is used to track table deletion and * deletion of objects created by methods */ if (walk_state) { owner_id = walk_state->owner_id; } /* Link the new entry into the parent and existing children */ child_node = parent_node->child; if (!child_node) { parent_node->child = node; node->flags |= ANOBJ_END_OF_PEER_LIST; node->peer = parent_node; } else { while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) { child_node = child_node->peer; } child_node->peer = node; /* Clear end-of-list flag */ child_node->flags &= ~ANOBJ_END_OF_PEER_LIST; node->flags |= ANOBJ_END_OF_PEER_LIST; node->peer = parent_node; } /* Init the new entry */ node->owner_id = owner_id; node->type = (u8) type; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n", acpi_ut_get_node_name(node), acpi_ut_get_type_name(node->type), node, owner_id, acpi_ut_get_node_name(parent_node), acpi_ut_get_type_name(parent_node->type), parent_node)); return_VOID; }
/**ltl * 功能: 将新分配的命名空间插入到父节点 * 参数: walk_state -> * parent_node ->父节点对象 * node ->要插入到父节点的节点对象 * type ->新节点类型 * 返回值: 无 * 说明: 新节点可能做为子节点插入,也可能子节点的同伴插入 */ void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namespace_node *parent_node, /* Parent */ struct acpi_namespace_node *node, /* New Child */ acpi_object_type type) { acpi_owner_id owner_id = 0; struct acpi_namespace_node *child_node; ACPI_FUNCTION_TRACE(ns_install_node); /* * Get the owner ID from the Walk state * The owner ID is used to track table deletion and * deletion of objects created by methods */ if (walk_state) { owner_id = walk_state->owner_id; } /* Link the new entry into the parent and existing children */ /* 将新的命名空间插入 */ child_node = parent_node->child; if (!child_node) { /* 不存在子节点,则新节点做为新的子节点插入 */ parent_node->child = node; node->flags |= ANOBJ_END_OF_PEER_LIST; node->peer = parent_node; } else { /* 如果存在子节点,找到同伴链表的最后一个节点。 */ while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) { child_node = child_node->peer; } /* 此时child_node为同伴链表的最后一个节点,将新节点做为下一个同伴 */ child_node->peer = node; /* Clear end-of-list flag */ /* 清除原来的标志 */ child_node->flags &= ~ANOBJ_END_OF_PEER_LIST; node->flags |= ANOBJ_END_OF_PEER_LIST; /* 表示此节点为同伴链表的最后一个节点 */ node->peer = parent_node; /* 将最后一个同伴节点的同伴指针指向其父节点 */ } /* Init the new entry */ node->owner_id = owner_id; /* 设置所属ID */ node->type = (u8) type; /* 设置节点类型 */ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n", acpi_ut_get_node_name(node), acpi_ut_get_type_name(node->type), node, owner_id, acpi_ut_get_node_name(parent_node), acpi_ut_get_type_name(parent_node->type), parent_node)); return_VOID; }
void acpi_ns_install_node(struct acpi_walk_state *walk_state, struct acpi_namespace_node *parent_node, struct acpi_namespace_node *node, acpi_object_type type) { acpi_owner_id owner_id = 0; struct acpi_namespace_node *child_node; ACPI_FUNCTION_TRACE(ns_install_node); if (walk_state) { owner_id = walk_state->owner_id; } child_node = parent_node->child; if (!child_node) { parent_node->child = node; node->flags |= ANOBJ_END_OF_PEER_LIST; node->peer = parent_node; } else { while (!(child_node->flags & ANOBJ_END_OF_PEER_LIST)) { child_node = child_node->peer; } child_node->peer = node; child_node->flags &= ~ANOBJ_END_OF_PEER_LIST; node->flags |= ANOBJ_END_OF_PEER_LIST; node->peer = parent_node; } node->owner_id = owner_id; node->type = (u8) type; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n", acpi_ut_get_node_name(node), acpi_ut_get_type_name(node->type), node, owner_id, acpi_ut_get_node_name(parent_node), acpi_ut_get_type_name(parent_node->type), parent_node)); return_VOID; }
void acpi_db_send_notify(char *name, u32 value) { struct acpi_namespace_node *node; acpi_status status; /* Translate name to an Named object */ node = acpi_db_convert_to_node(name); if (!node) { return; } /* Dispatch the notify if legal */ if (acpi_ev_is_notify_object(node)) { status = acpi_ev_queue_notify_request(node, value); if (ACPI_FAILURE(status)) { acpi_os_printf("Could not queue notify\n"); } } else { acpi_os_printf("Named object [%4.4s] Type %s, " "must be Device/Thermal/Processor type\n", acpi_ut_get_node_name(node), acpi_ut_get_type_name(node->type)); } }
acpi_status acpi_db_display_objects ( NATIVE_CHAR *obj_type_arg, NATIVE_CHAR *display_count_arg) { acpi_object_type8 type; /* Get the object type */ type = acpi_db_match_argument (obj_type_arg, acpi_db_object_types); if (type == ACPI_TYPE_NOT_FOUND) { acpi_os_printf ("Invalid or unsupported argument\n"); return (AE_OK); } acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT); acpi_os_printf ("Objects of type [%s] defined in the current ACPI Namespace: \n", acpi_ut_get_type_name (type)); acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT); /* Walk the namespace from the root */ acpi_walk_namespace (type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, acpi_db_walk_for_specific_objects, (void *) &type, NULL); acpi_db_set_output_destination (DB_CONSOLE_OUTPUT); return (AE_OK); }
void acpi_db_display_resources(char *object_arg) { struct acpi_namespace_node *node; acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); acpi_dbg_level |= ACPI_LV_RESOURCES; /* Asterisk means "display resources for all devices" */ if (!object_arg || (!strcmp(object_arg, "*"))) { (void)acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, acpi_db_device_resources, NULL, NULL, NULL); } else { /* Convert string to object pointer */ node = acpi_db_convert_to_node(object_arg); if (node) { if (node->type != ACPI_TYPE_DEVICE) { acpi_os_printf ("%4.4s: Name is not a device object (%s)\n", node->name.ascii, acpi_ut_get_type_name(node->type)); } else { (void)acpi_db_device_resources(node, 0, NULL, NULL); } } } acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); }
acpi_operand_object * acpi_ut_create_internal_object_dbg ( NATIVE_CHAR *module_name, u32 line_number, u32 component_id, acpi_object_type8 type) { acpi_operand_object *object; FUNCTION_TRACE_STR ("Ut_create_internal_object_dbg", acpi_ut_get_type_name (type)); /* Allocate the raw object descriptor */ object = acpi_ut_allocate_object_desc_dbg (module_name, line_number, component_id); if (!object) { /* Allocation failure */ return_PTR (NULL); } /* Save the object type in the object descriptor */ object->common.type = type; /* Init the reference count */ object->common.reference_count = 1; /* Any per-type initialization should go here */ return_PTR (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)); }
/******************************************************************************* * * 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; }
union acpi_operand_object *acpi_ut_create_internal_object_dbg(char *module_name, u32 line_number, u32 component_id, acpi_object_type type) { union acpi_operand_object *object; union acpi_operand_object *second_object; ACPI_FUNCTION_TRACE_STR("ut_create_internal_object_dbg", acpi_ut_get_type_name(type)); /* Allocate the raw object descriptor */ object = acpi_ut_allocate_object_desc_dbg(module_name, line_number, component_id); if (!object) { return_PTR(NULL); } switch (type) { case ACPI_TYPE_REGION: case ACPI_TYPE_BUFFER_FIELD: /* These types require a secondary object */ second_object = acpi_ut_allocate_object_desc_dbg(module_name, line_number, component_id); if (!second_object) { acpi_ut_delete_object_desc(object); return_PTR(NULL); } second_object->common.type = ACPI_TYPE_LOCAL_EXTRA; second_object->common.reference_count = 1; /* Link the second object to the first */ object->common.next_object = second_object; break; default: /* All others have no secondary object */ break; } /* Save the object type in the object descriptor */ object->common.type = (u8) type; /* Init the reference count */ object->common.reference_count = 1; /* Any per-type initialization should go here */ return_PTR(object); }
char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) { if (!obj_desc) { return ("[NULL Object Descriptor]"); } return (acpi_ut_get_type_name(ACPI_GET_OBJECT_TYPE(obj_desc))); }
acpi_status acpi_ds_scope_stack_pop ( struct acpi_walk_state *walk_state) { union acpi_generic_state *scope_info; union acpi_generic_state *new_scope_info; ACPI_FUNCTION_TRACE ("ds_scope_stack_pop"); /* * Pop scope info object off the stack. */ scope_info = acpi_ut_pop_generic_state (&walk_state->scope_info); if (!scope_info) { return_ACPI_STATUS (AE_STACK_UNDERFLOW); } walk_state->scope_depth--; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%.2d] Popped scope [%4.4s] (%s), New scope -> ", (u32) walk_state->scope_depth, acpi_ut_get_node_name (scope_info->scope.node), acpi_ut_get_type_name (scope_info->common.value))); new_scope_info = walk_state->scope_info; if (new_scope_info) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "[%4.4s] (%s)\n", acpi_ut_get_node_name (new_scope_info->scope.node), acpi_ut_get_type_name (new_scope_info->common.value))); } else { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "[\\___] (ROOT)\n")); } acpi_ut_delete_generic_state (scope_info); return_ACPI_STATUS (AE_OK); }
void acpi_ut_display_init_pathname ( u8 type, struct acpi_namespace_node *obj_handle, char *path) { acpi_status status; struct acpi_buffer buffer; ACPI_FUNCTION_ENTRY (); /* Only print the path if the appropriate debug level is enabled */ if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) { return; } /* Get the full pathname to the node */ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; status = acpi_ns_handle_to_pathname (obj_handle, &buffer); if (ACPI_FAILURE (status)) { return; } /* Print what we're doing */ switch (type) { case ACPI_TYPE_METHOD: acpi_os_printf ("Executing "); break; default: acpi_os_printf ("Initializing "); break; } /* Print the object type and pathname */ acpi_os_printf ("%-12s %s", acpi_ut_get_type_name (type), (char *) buffer.pointer); /* Extra path is used to append names like _STA, _INI, etc. */ if (path) { acpi_os_printf (".%s", path); } acpi_os_printf ("\n"); ACPI_MEM_FREE (buffer.pointer); }
u32 acpi_ns_opens_scope(acpi_object_type type) { ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type)); if (!acpi_ut_valid_object_type(type)) { /* type code out of range */ ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type)); return_UINT32(ACPI_NS_NORMAL); } return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); }
u32 acpi_ns_opens_scope ( acpi_object_type type) { ACPI_FUNCTION_TRACE_STR ("ns_opens_scope", acpi_ut_get_type_name (type)); if (!acpi_ut_valid_object_type (type)) { /* type code out of range */ ACPI_REPORT_WARNING (("ns_opens_scope: Invalid Object Type %X\n", type)); return_VALUE (ACPI_NS_NORMAL); } return_VALUE (((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE); }
acpi_status acpi_ds_load1_end_op ( acpi_walk_state *walk_state) { acpi_parse_object *op; acpi_object_type8 data_type; PROC_NAME ("Ds_load1_end_op"); op = walk_state->op; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); /* We are only interested in opcodes that have an associated name */ if (!(walk_state->op_info->flags & AML_NAMED)) { return (AE_OK); } /* Get the type to determine if we should pop the scope */ data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode); if (op->opcode == AML_NAME_OP) { /* For Name opcode, check the argument */ if (op->value.arg) { data_type = acpi_ds_map_opcode_to_data_type ( (op->value.arg)->opcode, NULL); ((acpi_namespace_node *)op->node)->type = (u8) data_type; } } /* Pop the scope stack */ if (acpi_ns_opens_scope (data_type)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n", acpi_ut_get_type_name (data_type), op)); acpi_ds_scope_stack_pop (walk_state); } return (AE_OK); }
acpi_status acpi_db_walk_and_match_name ( acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { acpi_status status; NATIVE_CHAR *requested_name = (NATIVE_CHAR *) context; u32 i; u32 buf_size; NATIVE_CHAR buffer[96]; /* Check for a name match */ for (i = 0; i < 4; i++) { /* Wildcard support */ if ((requested_name[i] != '?') && (requested_name[i] != ((NATIVE_CHAR *) (&((acpi_namespace_node *) obj_handle)->name))[i])) { /* No match, just exit */ return (AE_OK); } } /* Get the full pathname to this object */ buf_size = sizeof (buffer) / sizeof (*buffer); status = acpi_ns_handle_to_pathname (obj_handle, &buf_size, buffer); if (ACPI_FAILURE (status)) { acpi_os_printf ("Could Not get pathname for object %p\n", obj_handle); } else { acpi_os_printf ("%32s (%p) - %s\n", buffer, obj_handle, acpi_ut_get_type_name (((acpi_namespace_node *) obj_handle)->type)); } return (AE_OK); }
/**************************************************************************** * * FUNCTION: acpi_ds_scope_stack_clear * * PARAMETERS: walk_state - Current state * * RETURN: None * * DESCRIPTION: Pop (and free) everything on the scope stack except the * root scope object (which remains at the stack top.) * ***************************************************************************/ void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state) { union acpi_generic_state *scope_info; ACPI_FUNCTION_NAME(ds_scope_stack_clear); while (walk_state->scope_info) { /* Pop a scope off the stack */ scope_info = walk_state->scope_info; walk_state->scope_info = scope_info->scope.next; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Popped object type (%s)\n", acpi_ut_get_type_name(scope_info->common. value))); acpi_ut_delete_generic_state(scope_info); } }
static acpi_status acpi_ex_convert_to_object_type_string(union acpi_operand_object *obj_desc, union acpi_operand_object **result_desc) { union acpi_operand_object *return_desc; const char *type_string; type_string = acpi_ut_get_type_name(obj_desc->common.type); return_desc = acpi_ut_create_string_object(((acpi_size)strlen(type_string) + 9)); /* 9 For "[ Object]" */ if (!return_desc) { return (AE_NO_MEMORY); } strcpy(return_desc->string.pointer, "["); strcat(return_desc->string.pointer, type_string); strcat(return_desc->string.pointer, " Object]"); *result_desc = return_desc; return (AE_OK); }
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_method_data_set_value ( u16 opcode, u32 index, union acpi_operand_object *object, struct acpi_walk_state *walk_state) { acpi_status status; struct acpi_namespace_node *node; ACPI_FUNCTION_TRACE ("ds_method_data_set_value"); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "new_obj %p Opcode %X, Refs=%d [%s]\n", object, opcode, object->common.reference_count, acpi_ut_get_type_name (object->common.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_ACPI_STATUS (status); } /* * Increment ref count so object can't be deleted while installed. * NOTE: We do not copy the object in order to preserve the call by * reference semantics of ACPI Control Method invocation. * (See ACPI specification 2.0_c) */ acpi_ut_add_reference (object); /* Install the object */ node->object = object; return_ACPI_STATUS (status); }
static acpi_status acpi_ns_dump_one_object_path(acpi_handle obj_handle, u32 level, void *context, void **return_value) { u32 max_level = *((u32 *)context); char *pathname; struct acpi_namespace_node *node; int path_indent; if (!obj_handle) { return (AE_OK); } node = acpi_ns_validate_handle(obj_handle); if (!node) { /* Ignore bad node during namespace walk */ return (AE_OK); } pathname = acpi_ns_get_normalized_pathname(node, TRUE); path_indent = 1; if (level <= max_level) { path_indent = max_level - level + 1; } acpi_os_printf("%2d%*s%-12s%*s", level, level, " ", acpi_ut_get_type_name(node->type), path_indent, " "); acpi_os_printf("%s\n", &pathname[1]); ACPI_FREE(pathname); return (AE_OK); }
/******************************************************************************* * * FUNCTION: acpi_ex_opcode_2A_0T_0R * * PARAMETERS: walk_state - Current walk state * * RETURN: Status * * DESCRIPTION: Execute opcode with two arguments, no target, and no return * value. * * ALLOCATION: Deletes both operands * ******************************************************************************/ acpi_status acpi_ex_opcode_2A_0T_0R(struct acpi_walk_state *walk_state) { union acpi_operand_object **operand = &walk_state->operands[0]; struct acpi_namespace_node *node; u32 value; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE_STR("ex_opcode_2A_0T_0R", acpi_ps_get_opcode_name(walk_state->opcode)); /* Examine the opcode */ switch (walk_state->opcode) { case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */ /* The first operand is a namespace node */ node = (struct acpi_namespace_node *)operand[0]; /* Second value is the notify value */ value = (u32) operand[1]->integer.value; /* Are notifies allowed on this object? */ if (!acpi_ev_is_notify_object(node)) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unexpected notify object type [%s]\n", acpi_ut_get_type_name(node->type))); status = AE_AML_OPERAND_TYPE; break; } #ifdef ACPI_GPE_NOTIFY_CHECK /* * GPE method wake/notify check. Here, we want to ensure that we * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx * GPE method during system runtime. If we do, the GPE is marked * as "wake-only" and disabled. * * 1) Is the Notify() value == device_wake? * 2) Is this a GPE deferred method? (An _Lxx or _Exx method) * 3) Did the original GPE happen at system runtime? * (versus during wake) * * If all three cases are true, this is a wake-only GPE that should * be disabled at runtime. */ if (value == 2) { /* device_wake */ status = acpi_ev_check_for_wake_only_gpe(walk_state-> gpe_event_info); if (ACPI_FAILURE(status)) { /* AE_WAKE_ONLY_GPE only error, means ignore this notify */ return_ACPI_STATUS(AE_OK) } } #endif /* * Dispatch the notify to the appropriate handler * NOTE: the request is queued for execution after this method * completes. The notify handlers are NOT invoked synchronously * from this thread -- because handlers may in turn run other * control methods. */ status = acpi_ev_queue_notify_request(node, value); break; default: ACPI_REPORT_ERROR(("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n", walk_state->opcode)); status = AE_AML_BAD_OPCODE; }
acpi_status acpi_db_display_objects(char *obj_type_arg, char *display_count_arg) { struct acpi_walk_info info; acpi_object_type type; struct acpi_object_info *object_info; u32 i; u32 total_objects = 0; /* No argument means display summary/count of all object types */ if (!obj_type_arg) { object_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_object_info)); /* Walk the namespace from the root */ (void)acpi_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, acpi_db_walk_for_object_counts, NULL, (void *)object_info, NULL); acpi_os_printf("\nSummary of namespace objects:\n\n"); for (i = 0; i < ACPI_TOTAL_TYPES; i++) { acpi_os_printf("%8u %s\n", object_info->types[i], acpi_ut_get_type_name(i)); total_objects += object_info->types[i]; } acpi_os_printf("\n%8u Total namespace objects\n\n", total_objects); ACPI_FREE(object_info); return (AE_OK); } /* Get the object type */ type = acpi_db_match_argument(obj_type_arg, acpi_db_object_types); if (type == ACPI_TYPE_NOT_FOUND) { acpi_os_printf("Invalid or unsupported argument\n"); return (AE_OK); } acpi_db_set_output_destination(ACPI_DB_DUPLICATE_OUTPUT); acpi_os_printf ("Objects of type [%s] defined in the current ACPI Namespace:\n", acpi_ut_get_type_name(type)); acpi_db_set_output_destination(ACPI_DB_REDIRECTABLE_OUTPUT); info.count = 0; info.owner_id = ACPI_OWNER_ID_MAX; info.debug_level = ACPI_UINT32_MAX; info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT; /* Walk the namespace from the root */ (void)acpi_walk_namespace(type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, acpi_db_walk_for_specific_objects, NULL, (void *)&info, NULL); acpi_os_printf ("\nFound %u objects of type [%s] in the current ACPI Namespace\n", info.count, acpi_ut_get_type_name(type)); acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT); return (AE_OK); }
acpi_status acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, union acpi_operand_object *obj_desc, union acpi_operand_object **result_desc) { acpi_status status; u32 length; void *buffer; union acpi_operand_object *buffer_desc; u32 function; u16 accessor_type; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); /* Parameter validation */ if (!source_desc || !obj_desc) { return_ACPI_STATUS(AE_AML_NO_OPERAND); } if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { /* * If the buffer_field arguments have not been previously evaluated, * evaluate them now and save the results. */ if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { status = acpi_ds_get_buffer_field_arguments(obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_IPMI)) { /* * This is an SMBus, GSBus or IPMI write. We will bypass the entire field * mechanism and handoff the buffer directly to the handler. For * these address spaces, the buffer is bi-directional; on a write, * return data is returned in the same buffer. * * Source must be a buffer of sufficient size: * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE. * * Note: SMBus and GSBus protocol type is passed in upper 16-bits of Function */ if (source_desc->common.type != ACPI_TYPE_BUFFER) { ACPI_ERROR((AE_INFO, "SMBus/IPMI/GenericSerialBus write requires Buffer, found type %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS) { length = ACPI_SMBUS_BUFFER_SIZE; function = ACPI_WRITE | (obj_desc->field.attribute << 16); } else if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) { accessor_type = obj_desc->field.attribute; length = acpi_ex_get_serial_access_length(accessor_type, obj_desc-> field. access_length); /* * Add additional 2 bytes for the generic_serial_bus data buffer: * * Status; (Byte 0 of the data buffer) * Length; (Byte 1 of the data buffer) * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer) */ length += 2; function = ACPI_WRITE | (accessor_type << 16); } else { /* IPMI */ length = ACPI_IPMI_BUFFER_SIZE; function = ACPI_WRITE; } if (source_desc->buffer.length < length) { ACPI_ERROR((AE_INFO, "SMBus/IPMI/GenericSerialBus write requires Buffer of length %u, found length %u", length, source_desc->buffer.length)); return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); } /* Create the bi-directional buffer */ buffer_desc = acpi_ut_create_buffer_object(length); if (!buffer_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } buffer = buffer_desc->buffer.pointer; ACPI_MEMCPY(buffer, source_desc->buffer.pointer, length); /* Lock entire transaction if requested */ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* * Perform the write (returns status and perhaps data in the * same buffer) */ status = acpi_ex_access_region(obj_desc, 0, (u64 *) buffer, function); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); *result_desc = buffer_desc; return_ACPI_STATUS(status); } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) { /* * For GPIO (general_purpose_io), we will bypass the entire field * mechanism and handoff the bit address and bit width directly to * the handler. The Address will be the bit offset * from the previous Connection() operator, making it effectively a * pin number index. The bit_length is the length of the field, which * is thus the number of pins. */ if (source_desc->common.type != ACPI_TYPE_INTEGER) { return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", acpi_ut_get_type_name(source_desc->common. type), source_desc->common.type, (u32)source_desc->integer.value, obj_desc->field.pin_number_index, obj_desc->field.bit_length)); buffer = &source_desc->integer.value; /* Lock entire transaction if requested */ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* Perform the write */ status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_WRITE); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); return_ACPI_STATUS(status); } /* Get a pointer to the data to be written */ switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: buffer = &source_desc->integer.value; length = sizeof(source_desc->integer.value); break; case ACPI_TYPE_BUFFER: buffer = source_desc->buffer.pointer; length = source_desc->buffer.length; break; case ACPI_TYPE_STRING: buffer = source_desc->string.pointer; length = source_desc->string.length; break; default: return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", source_desc, acpi_ut_get_type_name(source_desc->common.type), source_desc->common.type, buffer, length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", obj_desc, acpi_ut_get_type_name(obj_desc->common.type), obj_desc->common.type, obj_desc->common_field.bit_length, obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.base_byte_offset)); /* Lock entire transaction if requested */ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* Write to the field */ status = acpi_ex_insert_into_field(obj_desc, buffer, length); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); return_ACPI_STATUS(status); }
union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char *module_name, u32 line_number, u32 component_id, acpi_object_type type) { union acpi_operand_object *object; union acpi_operand_object *second_object; ACPI_FUNCTION_TRACE_STR(ut_create_internal_object_dbg, acpi_ut_get_type_name(type)); object = acpi_ut_allocate_object_desc_dbg(module_name, line_number, component_id); if (!object) { return_PTR(NULL); } switch (type) { case ACPI_TYPE_REGION: case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: second_object = acpi_ut_allocate_object_desc_dbg(module_name, line_number, component_id); if (!second_object) { acpi_ut_delete_object_desc(object); return_PTR(NULL); } second_object->common.type = ACPI_TYPE_LOCAL_EXTRA; second_object->common.reference_count = 1; object->common.next_object = second_object; break; default: break; } object->common.type = (u8) type; object->common.reference_count = 1; return_PTR(object); }
acpi_status acpi_evaluate_object_typed(acpi_handle handle, acpi_string pathname, struct acpi_object_list *external_params, struct acpi_buffer *return_buffer, acpi_object_type return_type) { acpi_status status; u8 must_free = FALSE; ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed); /* Return buffer must be valid */ if (!return_buffer) { return_ACPI_STATUS(AE_BAD_PARAMETER); } if (return_buffer->length == ACPI_ALLOCATE_BUFFER) { must_free = TRUE; } /* Evaluate the object */ status = acpi_evaluate_object(handle, pathname, external_params, return_buffer); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Type ANY means "don't care" */ if (return_type == ACPI_TYPE_ANY) { return_ACPI_STATUS(AE_OK); } if (return_buffer->length == 0) { /* Error because caller specifically asked for a return value */ ACPI_ERROR((AE_INFO, "No return value")); return_ACPI_STATUS(AE_NULL_OBJECT); } /* Examine the object type returned from evaluate_object */ if (((union acpi_object *)return_buffer->pointer)->type == return_type) { return_ACPI_STATUS(AE_OK); } /* Return object type does not match requested type */ ACPI_ERROR((AE_INFO, "Incorrect return type [%s] requested [%s]", acpi_ut_get_type_name(((union acpi_object *)return_buffer-> pointer)->type), acpi_ut_get_type_name(return_type))); if (must_free) { /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ ACPI_FREE(return_buffer->pointer); return_buffer->pointer = NULL; } return_buffer->length = 0; return_ACPI_STATUS(AE_TYPE); }
void acpi_ut_dump_allocations(u32 component, const char *module) { struct acpi_debug_mem_block *element; union acpi_descriptor *descriptor; u32 num_outstanding = 0; u8 descriptor_type; ACPI_FUNCTION_TRACE(ut_dump_allocations); if (acpi_gbl_disable_mem_tracking) { return_VOID; } /* * Walk the allocation list. */ if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) { return_VOID; } element = acpi_gbl_global_list->list_head; while (element) { if ((element->component & component) && ((module == NULL) || (0 == strcmp(module, element->module)))) { descriptor = ACPI_CAST_PTR(union acpi_descriptor, &element->user_space); if (element->size < sizeof(struct acpi_common_descriptor)) { acpi_os_printf("%p Length 0x%04X %9.9s-%u " "[Not a Descriptor - too small]\n", descriptor, element->size, element->module, element->line); } else { /* Ignore allocated objects that are in a cache */ if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) != ACPI_DESC_TYPE_CACHED) { acpi_os_printf ("%p Length 0x%04X %9.9s-%u [%s] ", descriptor, element->size, element->module, element->line, acpi_ut_get_descriptor_name (descriptor)); /* Validate the descriptor type using Type field and length */ descriptor_type = 0; /* Not a valid descriptor type */ switch (ACPI_GET_DESCRIPTOR_TYPE (descriptor)) { case ACPI_DESC_TYPE_OPERAND: if (element->size == sizeof(union acpi_operand_object)) { descriptor_type = ACPI_DESC_TYPE_OPERAND; } break; case ACPI_DESC_TYPE_PARSER: if (element->size == sizeof(union acpi_parse_object)) { descriptor_type = ACPI_DESC_TYPE_PARSER; } break; case ACPI_DESC_TYPE_NAMED: if (element->size == sizeof(struct acpi_namespace_node)) { descriptor_type = ACPI_DESC_TYPE_NAMED; } break; default: break; } /* Display additional info for the major descriptor types */ switch (descriptor_type) { case ACPI_DESC_TYPE_OPERAND: acpi_os_printf ("%12.12s RefCount 0x%04X\n", acpi_ut_get_type_name (descriptor->object.common. type), descriptor->object.common. reference_count); break; case ACPI_DESC_TYPE_PARSER: acpi_os_printf ("AmlOpcode 0x%04hX\n", descriptor->op.asl. aml_opcode); break; case ACPI_DESC_TYPE_NAMED: acpi_os_printf("%4.4s\n", acpi_ut_get_node_name (&descriptor-> node)); break; default: acpi_os_printf("\n"); break; } } } num_outstanding++; } element = element->next; }
acpi_status acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, union acpi_parse_object ** out_op) { union acpi_parse_object *op; struct acpi_namespace_node *node; acpi_status status; acpi_object_type object_type; char *path; u32 flags; ACPI_FUNCTION_TRACE(ds_load1_begin_op); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); /* We are only interested in opcodes that have an associated name */ if (op) { if (!(walk_state->op_info->flags & AML_NAMED)) { *out_op = op; return_ACPI_STATUS(AE_OK); } /* Check if this object has already been installed in the namespace */ if (op->common.node) { *out_op = op; return_ACPI_STATUS(AE_OK); } } path = acpi_ps_get_next_namestring(&walk_state->parser_state); /* Map the raw opcode into an internal object type */ object_type = walk_state->op_info->object_type; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "State=%p Op=%p [%s]\n", walk_state, op, acpi_ut_get_type_name(object_type))); switch (walk_state->opcode) { case AML_SCOPE_OP: /* * The target name of the Scope() operator must exist at this point so * that we can actually open the scope to enter new names underneath it. * Allow search-to-root for single namesegs. */ status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node)); #ifdef ACPI_ASL_COMPILER if (status == AE_NOT_FOUND) { /* * Table disassembly: * Target of Scope() not found. Generate an External for it, and * insert the name into the namespace. */ acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0); status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, walk_state, &node); } #endif if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE(path, status); return_ACPI_STATUS(status); } /* * Check to make sure that the target is * one of the opcodes that actually opens a scope */ switch (node->type) { case ACPI_TYPE_ANY: case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: /* These are acceptable types */ break; case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * These types we will allow, but we will change the type. This * enables some existing code of the form: * * Name (DEB, 0) * Scope (DEB) { ... } * * Note: silently change the type here. On the second pass, we will report * a warning */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n", path, acpi_ut_get_type_name(node->type))); node->type = ACPI_TYPE_ANY; walk_state->scope_info->common.value = ACPI_TYPE_ANY; break; default: /* All other types are an error */ ACPI_ERROR((AE_INFO, "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)", acpi_ut_get_type_name(node->type), path)); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } break; default: /* * For all other named opcodes, we will enter the name into * the namespace. * * Setup the search flags. * Since we are entering a name into the namespace, we do not want to * enable the search-to-root upsearch. * * There are only two conditions where it is acceptable that the name * already exists: * 1) the Scope() operator can reopen a scoping object that was * previously defined (Scope, Method, Device, etc.) * 2) Whenever we are parsing a deferred opcode (op_region, Buffer, * buffer_field, or Package), the name of the object is already * in the namespace. */ if (walk_state->deferred_node) { /* This name is already in the namespace, get the node */ node = walk_state->deferred_node; status = AE_OK; break; } /* * If we are executing a method, do not create any namespace objects * during the load phase, only during execution. */ if (walk_state->method_node) { node = NULL; status = AE_OK; break; } flags = ACPI_NS_NO_UPSEARCH; if ((walk_state->opcode != AML_SCOPE_OP) && (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) { flags |= ACPI_NS_ERROR_IF_FOUND; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n", acpi_ut_get_type_name(object_type))); } else { ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[%s] Both Find or Create allowed\n", acpi_ut_get_type_name(object_type))); } /* * Enter the named type into the internal namespace. We enter the name * as we go downward in the parse tree. Any necessary subobjects that * involve arguments to the opcode must be created as we go back up the * parse tree later. */ status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_LOAD_PASS1, flags, walk_state, &node); if (ACPI_FAILURE(status)) { if (status == AE_ALREADY_EXISTS) { /* The name already exists in this scope */ if (node->flags & ANOBJ_IS_EXTERNAL) { /* * Allow one create on an object or segment that was * previously declared External */ node->flags &= ~ANOBJ_IS_EXTERNAL; node->type = (u8) object_type; /* Just retyped a node, probably will need to open a scope */ if (acpi_ns_opens_scope(object_type)) { status = acpi_ds_scope_stack_push (node, object_type, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS (status); } } status = AE_OK; } } if (ACPI_FAILURE(status)) { ACPI_ERROR_NAMESPACE(path, status); return_ACPI_STATUS(status); } } break; } /* Common exit */ if (!op) { /* Create a new op */ op = acpi_ps_alloc_op(walk_state->opcode); if (!op) { return_ACPI_STATUS(AE_NO_MEMORY); } } /* Initialize the op */ #if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)) op->named.path = ACPI_CAST_PTR(u8, path); #endif if (node) { /* * Put the Node in the "op" object that the parser uses, so we * can get it again quickly when this scope is closed */ op->common.node = node; op->named.name = node->name.integer; } acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state), op); *out_op = op; return_ACPI_STATUS(status); }
acpi_status acpi_evaluate_object_typed(acpi_handle handle, acpi_string pathname, struct acpi_object_list *external_params, struct acpi_buffer *return_buffer, acpi_object_type return_type) { acpi_status status; u8 free_buffer_on_error = FALSE; ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed); /* Return buffer must be valid */ if (!return_buffer) { return_ACPI_STATUS(AE_BAD_PARAMETER); } if (return_buffer->length == ACPI_ALLOCATE_BUFFER) { free_buffer_on_error = TRUE; } /* Evaluate the object */ status = acpi_evaluate_object(handle, pathname, external_params, return_buffer); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Type ANY means "don't care" */ if (return_type == ACPI_TYPE_ANY) { return_ACPI_STATUS(AE_OK); } if (return_buffer->length == 0) { /* Error because caller specifically asked for a return value */ ACPI_ERROR((AE_INFO, "No return value")); return_ACPI_STATUS(AE_NULL_OBJECT); } /* Examine the object type returned from evaluate_object */ if (((union acpi_object *)return_buffer->pointer)->type == return_type) { return_ACPI_STATUS(AE_OK); } /* Return object type does not match requested type */ ACPI_ERROR((AE_INFO, "Incorrect return type [%s] requested [%s]", acpi_ut_get_type_name(((union acpi_object *)return_buffer-> pointer)->type), acpi_ut_get_type_name(return_type))); if (free_buffer_on_error) { /* * Free a buffer created via ACPI_ALLOCATE_BUFFER. * Note: We use acpi_os_free here because acpi_os_allocate was used * to allocate the buffer. This purposefully bypasses the * (optionally enabled) allocation tracking mechanism since we * only want to track internal allocations. */ acpi_os_free(return_buffer->pointer); return_buffer->pointer = NULL; } return_buffer->length = 0; return_ACPI_STATUS(AE_TYPE); }