ACPI_STATUS AcpiNsExecuteControlMethod ( ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT **Params, ACPI_OPERAND_OBJECT **ReturnObjDesc) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_FUNCTION_TRACE ("NsExecuteControlMethod"); /* Verify that there is a method associated with this object */ ObjDesc = AcpiNsGetAttachedObject (MethodNode); if (!ObjDesc) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No attached method object\n")); (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (AE_NULL_OBJECT); } ACPI_DUMP_PATHNAME (MethodNode, "Execute Method:", ACPI_LV_INFO, _COMPONENT); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n", ObjDesc->Method.AmlStart + 1, ObjDesc->Method.AmlLength - 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. */ Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Execute the method via the interpreter. The interpreter is locked * here before calling into the AML parser */ Status = AcpiExEnterInterpreter (); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } Status = AcpiPsxExecute (MethodNode, Params, ReturnObjDesc); AcpiExExitInterpreter (); return_ACPI_STATUS (Status); }
void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) { u32 length; u32 index; ACPI_FUNCTION_NAME(ex_dump_operand) if (! ((ACPI_LV_EXEC & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) { return; } if (!obj_desc) { /* This could be a null element of a package */ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Null Object Descriptor\n")); return; } if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p Namespace Node: ", obj_desc)); ACPI_DUMP_ENTRY(obj_desc, ACPI_LV_EXEC); return; } if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p is not a node or operand object: [%s]\n", obj_desc, acpi_ut_get_descriptor_name(obj_desc))); ACPI_DUMP_BUFFER(obj_desc, sizeof(union acpi_operand_object)); return; } /* obj_desc is a valid object */ if (depth > 0) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%*s[%u] %p ", depth, " ", depth, obj_desc)); } else { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%p ", obj_desc)); } /* Decode object type */ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_LOCAL_REFERENCE: switch (obj_desc->reference.opcode) { case AML_DEBUG_OP: acpi_os_printf("Reference: Debug\n"); break; case AML_NAME_OP: ACPI_DUMP_PATHNAME(obj_desc->reference.object, "Reference: Name: ", ACPI_LV_INFO, _COMPONENT); ACPI_DUMP_ENTRY(obj_desc->reference.object, ACPI_LV_INFO); break; case AML_INDEX_OP: acpi_os_printf("Reference: Index %p\n", obj_desc->reference.object); break; case AML_REF_OF_OP: acpi_os_printf("Reference: (RefOf) %p\n", obj_desc->reference.object); break; case AML_ARG_OP: acpi_os_printf("Reference: Arg%d", obj_desc->reference.offset); if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { /* Value is an Integer */ acpi_os_printf(" value is [%8.8X%8.8x]", ACPI_FORMAT_UINT64(obj_desc-> integer. value)); } acpi_os_printf("\n"); break; case AML_LOCAL_OP: acpi_os_printf("Reference: Local%d", obj_desc->reference.offset); if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) { /* Value is an Integer */ acpi_os_printf(" value is [%8.8X%8.8x]", ACPI_FORMAT_UINT64(obj_desc-> integer. value)); } acpi_os_printf("\n"); break; case AML_INT_NAMEPATH_OP: acpi_os_printf("Reference.Node->Name %X\n", obj_desc->reference.node->name.integer); break; default: /* Unknown opcode */ acpi_os_printf("Unknown Reference opcode=%X\n", obj_desc->reference.opcode); break; } break; case ACPI_TYPE_BUFFER: acpi_os_printf("Buffer len %X @ %p\n", obj_desc->buffer.length, obj_desc->buffer.pointer); length = obj_desc->buffer.length; if (length > 64) { length = 64; } /* Debug only -- dump the buffer contents */ if (obj_desc->buffer.pointer) { acpi_os_printf("Buffer Contents: "); for (index = 0; index < length; index++) { acpi_os_printf(" %02x", obj_desc->buffer.pointer[index]); } acpi_os_printf("\n"); } break; case ACPI_TYPE_INTEGER: acpi_os_printf("Integer %8.8X%8.8X\n", ACPI_FORMAT_UINT64(obj_desc->integer.value)); break; case ACPI_TYPE_PACKAGE: acpi_os_printf("Package [Len %X] ElementArray %p\n", obj_desc->package.count, obj_desc->package.elements); /* * If elements exist, package element pointer is valid, * and debug_level exceeds 1, dump package's elements. */ if (obj_desc->package.count && obj_desc->package.elements && acpi_dbg_level > 1) { for (index = 0; index < obj_desc->package.count; index++) { acpi_ex_dump_operand(obj_desc->package. elements[index], depth + 1); } } break; case ACPI_TYPE_REGION: acpi_os_printf("Region %s (%X)", acpi_ut_get_region_name(obj_desc->region. space_id), obj_desc->region.space_id); /* * If the address and length have not been evaluated, * don't print them. */ if (!(obj_desc->region.flags & AOPOBJ_DATA_VALID)) { acpi_os_printf("\n"); } else { acpi_os_printf(" base %8.8X%8.8X Length %X\n", ACPI_FORMAT_UINT64(obj_desc->region. address), obj_desc->region.length); } break; case ACPI_TYPE_STRING: acpi_os_printf("String length %X @ %p ", obj_desc->string.length, obj_desc->string.pointer); acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX); acpi_os_printf("\n"); break; case ACPI_TYPE_LOCAL_BANK_FIELD: acpi_os_printf("BankField\n"); break; case ACPI_TYPE_LOCAL_REGION_FIELD: acpi_os_printf ("RegionField: Bits=%X AccWidth=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n", obj_desc->field.bit_length, obj_desc->field.access_byte_width, obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK, obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK, obj_desc->field.base_byte_offset, obj_desc->field.start_field_bit_offset); acpi_ex_dump_operand(obj_desc->field.region_obj, depth + 1); break; case ACPI_TYPE_LOCAL_INDEX_FIELD: acpi_os_printf("IndexField\n"); break; case ACPI_TYPE_BUFFER_FIELD: acpi_os_printf("BufferField: %X bits at byte %X bit %X of\n", obj_desc->buffer_field.bit_length, obj_desc->buffer_field.base_byte_offset, obj_desc->buffer_field.start_field_bit_offset); if (!obj_desc->buffer_field.buffer_obj) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "*NULL*\n")); } else if (ACPI_GET_OBJECT_TYPE(obj_desc->buffer_field.buffer_obj) != ACPI_TYPE_BUFFER) { acpi_os_printf("*not a Buffer*\n"); } else { acpi_ex_dump_operand(obj_desc->buffer_field.buffer_obj, depth + 1); } break; case ACPI_TYPE_EVENT: acpi_os_printf("Event\n"); break; case ACPI_TYPE_METHOD: acpi_os_printf("Method(%X) @ %p:%X\n", obj_desc->method.param_count, obj_desc->method.aml_start, obj_desc->method.aml_length); break; case ACPI_TYPE_MUTEX: acpi_os_printf("Mutex\n"); break; case ACPI_TYPE_DEVICE: acpi_os_printf("Device\n"); break; case ACPI_TYPE_POWER: acpi_os_printf("Power\n"); break; case ACPI_TYPE_PROCESSOR: acpi_os_printf("Processor\n"); break; case ACPI_TYPE_THERMAL: acpi_os_printf("Thermal\n"); break; default: /* Unknown Type */ acpi_os_printf("Unknown Type %X\n", ACPI_GET_OBJECT_TYPE(obj_desc)); break; } return; }
ACPI_STATUS AcpiNsEvaluate ( ACPI_EVALUATE_INFO *Info) { ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; ACPI_FUNCTION_TRACE (NsEvaluate); if (!Info) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Initialize the return value to an invalid object */ Info->ReturnObject = NULL; Info->ParamCount = 0; /* * Get the actual namespace node for the target object. Handles these cases: * * 1) Null node, Pathname (absolute path) * 2) Node, Pathname (path relative to Node) * 3) Node, Null Pathname */ Status = AcpiNsGetNode (Info->PrefixNode, Info->Pathname, ACPI_NS_NO_UPSEARCH, &Info->ResolvedNode); if (ACPI_FAILURE (Status)) { 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 (AcpiNsGetType (Info->ResolvedNode) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { Info->ResolvedNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Info->ResolvedNode->Object); } ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n", Info->Pathname, Info->ResolvedNode, AcpiNsGetAttachedObject (Info->ResolvedNode))); Node = Info->ResolvedNode; /* * 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 (AcpiNsGetType (Info->ResolvedNode) == ACPI_TYPE_METHOD) { /* * 1) Object is a control method - execute it */ /* Verify that there is a method object associated with this node */ Info->ObjDesc = AcpiNsGetAttachedObject (Info->ResolvedNode); if (!Info->ObjDesc) { ACPI_ERROR ((AE_INFO, "Control method has no attached sub-object")); return_ACPI_STATUS (AE_NULL_OBJECT); } /* Count the number of arguments being passed to the method */ if (Info->Parameters) { while (Info->Parameters[Info->ParamCount]) { if (Info->ParamCount > ACPI_METHOD_MAX_ARG) { return_ACPI_STATUS (AE_LIMIT); } Info->ParamCount++; } } ACPI_DUMP_PATHNAME (Info->ResolvedNode, "ACPI: Execute Method", ACPI_LV_INFO, _COMPONENT); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Method at AML address %p Length %X\n", Info->ObjDesc->Method.AmlStart + 1, Info->ObjDesc->Method.AmlLength - 1)); /* * 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. * * Execute the method via the interpreter. The interpreter is locked * here before calling into the AML parser */ AcpiExEnterInterpreter (); Status = AcpiPsExecuteMethod (Info); AcpiExExitInterpreter (); } else { /* * 2) Object is not a method, return its current value * * Disallow certain object types. For these, "evaluation" is undefined. */ switch (Info->ResolvedNode->Type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_EVENT: case ACPI_TYPE_MUTEX: case ACPI_TYPE_REGION: case ACPI_TYPE_THERMAL: case ACPI_TYPE_LOCAL_SCOPE: ACPI_ERROR ((AE_INFO, "[%4.4s] Evaluation of object type [%s] is not supported", Info->ResolvedNode->Name.Ascii, AcpiUtGetTypeName (Info->ResolvedNode->Type))); return_ACPI_STATUS (AE_TYPE); default: break; } /* * Objects require additional resolution steps (e.g., the Node may be * a field that must be read, etc.) -- we can't just grab the object * out of the node. * * Use ResolveNodeToValue() to get the associated value. * * NOTE: we can get away with passing in NULL for a walk state because * ResolvedNode is guaranteed to not be a reference to either a method * local or a method argument (because this interface is never called * from a running method.) * * Even though we do not directly invoke the interpreter for object * resolution, we must lock it because we could access an opregion. * The opregion access code assumes that the interpreter is locked. */ AcpiExEnterInterpreter (); /* Function has a strange interface */ Status = AcpiExResolveNodeToValue (&Info->ResolvedNode, NULL); AcpiExExitInterpreter (); /* * If AcpiExResolveNodeToValue() succeeded, the return value was placed * in ResolvedNode. */ if (ACPI_SUCCESS (Status)) { Status = AE_CTRL_RETURN_VALUE; Info->ReturnObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Info->ResolvedNode); ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returning object %p [%s]\n", Info->ReturnObject, AcpiUtGetObjectTypeName (Info->ReturnObject))); } } /* * Check input argument count against the ASL-defined count for a method. * Also check predefined names: argument count and return value against * the ACPI specification. Some incorrect return value types are repaired. */ (void) AcpiNsCheckPredefinedNames (Node, Info->ParamCount, Status, &Info->ReturnObject); /* Check if there is a return value that must be dealt with */ if (Status == AE_CTRL_RETURN_VALUE) { /* If caller does not want the return value, delete it */ if (Info->Flags & ACPI_IGNORE_RETURN_VALUE) { AcpiUtRemoveReference (Info->ReturnObject); Info->ReturnObject = NULL; } /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ Status = AE_OK; } ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "*** Completed evaluation of object %s ***\n", Info->Pathname)); /* * Namespace was unlocked by the handling AcpiNs* function, so we * just return */ return_ACPI_STATUS (Status); }