static ACPI_STATUS AcpiNsInitOneObject ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_OBJECT_TYPE Type; ACPI_STATUS Status = AE_OK; ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context; ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_FUNCTION_NAME (NsInitOneObject); Info->ObjectCount++; /* And even then, we are only interested in a few object types */ Type = AcpiNsGetType (ObjHandle); ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { return (AE_OK); } /* Increment counters for object types we are looking for */ switch (Type) { case ACPI_TYPE_REGION: Info->OpRegionCount++; break; case ACPI_TYPE_BUFFER_FIELD: Info->FieldCount++; break; case ACPI_TYPE_LOCAL_BANK_FIELD: Info->FieldCount++; break; case ACPI_TYPE_BUFFER: Info->BufferCount++; break; case ACPI_TYPE_PACKAGE: Info->PackageCount++; break; default: /* No init required, just exit now */ return (AE_OK); } /* If the object is already initialized, nothing else to do */ if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) { return (AE_OK); } /* Must lock the interpreter before executing AML code */ AcpiExEnterInterpreter (); /* * Each of these types can contain executable AML code within the * declaration. */ switch (Type) { case ACPI_TYPE_REGION: Info->OpRegionInit++; Status = AcpiDsGetRegionArguments (ObjDesc); break; case ACPI_TYPE_BUFFER_FIELD: Info->FieldInit++; Status = AcpiDsGetBufferFieldArguments (ObjDesc); break; case ACPI_TYPE_LOCAL_BANK_FIELD: Info->FieldInit++; Status = AcpiDsGetBankFieldArguments (ObjDesc); break; case ACPI_TYPE_BUFFER: Info->BufferInit++; Status = AcpiDsGetBufferArguments (ObjDesc); break; case ACPI_TYPE_PACKAGE: Info->PackageInit++; Status = AcpiDsGetPackageArguments (ObjDesc); 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)", AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type))); } /* * We ignore errors from above, and always return OK, since we don't want * to abort the walk on any single error. */ AcpiExExitInterpreter (); return (AE_OK); }
ACPI_STATUS AcpiExResolveNodeToValue ( ACPI_NAMESPACE_NODE **ObjectPtr, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT *SourceDesc; ACPI_OPERAND_OBJECT *ObjDesc = NULL; ACPI_NAMESPACE_NODE *Node; ACPI_OBJECT_TYPE EntryType; ACPI_FUNCTION_TRACE (ExResolveNodeToValue); /* * The stack pointer points to a ACPI_NAMESPACE_NODE (Node). Get the * object that is attached to the Node. */ Node = *ObjectPtr; SourceDesc = AcpiNsGetAttachedObject (Node); EntryType = AcpiNsGetType ((ACPI_HANDLE) Node); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p SourceDesc=%p [%s]\n", Node, SourceDesc, AcpiUtGetTypeName (EntryType))); if ((EntryType == ACPI_TYPE_LOCAL_ALIAS) || (EntryType == ACPI_TYPE_LOCAL_METHOD_ALIAS)) { /* There is always exactly one level of indirection */ Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Node->Object); SourceDesc = AcpiNsGetAttachedObject (Node); EntryType = AcpiNsGetType ((ACPI_HANDLE) Node); *ObjectPtr = Node; } /* * Several object types require no further processing: * 1) Device/Thermal objects don't have a "real" subobject, return the Node * 2) Method locals and arguments have a pseudo-Node * 3) 10/2007: Added method type to assist with Package construction. */ if ((EntryType == ACPI_TYPE_DEVICE) || (EntryType == ACPI_TYPE_THERMAL) || (EntryType == ACPI_TYPE_METHOD) || (Node->Flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) { return_ACPI_STATUS (AE_OK); } if (!SourceDesc) { ACPI_ERROR ((AE_INFO, "No object attached to node %p", Node)); return_ACPI_STATUS (AE_AML_NO_OPERAND); } /* * Action is based on the type of the Node, which indicates the type * of the attached object or pointer */ switch (EntryType) { case ACPI_TYPE_PACKAGE: if (SourceDesc->Common.Type != ACPI_TYPE_PACKAGE) { ACPI_ERROR ((AE_INFO, "Object not a Package, type %s", AcpiUtGetObjectTypeName (SourceDesc))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } Status = AcpiDsGetPackageArguments (SourceDesc); if (ACPI_SUCCESS (Status)) { /* Return an additional reference to the object */ ObjDesc = SourceDesc; AcpiUtAddReference (ObjDesc); } break; case ACPI_TYPE_BUFFER: if (SourceDesc->Common.Type != ACPI_TYPE_BUFFER) { ACPI_ERROR ((AE_INFO, "Object not a Buffer, type %s", AcpiUtGetObjectTypeName (SourceDesc))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } Status = AcpiDsGetBufferArguments (SourceDesc); if (ACPI_SUCCESS (Status)) { /* Return an additional reference to the object */ ObjDesc = SourceDesc; AcpiUtAddReference (ObjDesc); } break; case ACPI_TYPE_STRING: if (SourceDesc->Common.Type != ACPI_TYPE_STRING) { ACPI_ERROR ((AE_INFO, "Object not a String, type %s", AcpiUtGetObjectTypeName (SourceDesc))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* Return an additional reference to the object */ ObjDesc = SourceDesc; AcpiUtAddReference (ObjDesc); break; case ACPI_TYPE_INTEGER: if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER) { ACPI_ERROR ((AE_INFO, "Object not a Integer, type %s", AcpiUtGetObjectTypeName (SourceDesc))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* Return an additional reference to the object */ ObjDesc = SourceDesc; AcpiUtAddReference (ObjDesc); break; case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "FieldRead Node=%p SourceDesc=%p Type=%X\n", Node, SourceDesc, EntryType)); Status = AcpiExReadDataFromField (WalkState, SourceDesc, &ObjDesc); break; /* For these objects, just return the object attached to the Node */ case ACPI_TYPE_MUTEX: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_EVENT: case ACPI_TYPE_REGION: /* Return an additional reference to the object */ ObjDesc = SourceDesc; AcpiUtAddReference (ObjDesc); break; /* TYPE_ANY is untyped, and thus there is no object associated with it */ case ACPI_TYPE_ANY: ACPI_ERROR ((AE_INFO, "Untyped entry %p, no attached object!", Node)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */ case ACPI_TYPE_LOCAL_REFERENCE: switch (SourceDesc->Reference.Class) { case ACPI_REFCLASS_TABLE: /* This is a DdbHandle */ case ACPI_REFCLASS_REFOF: case ACPI_REFCLASS_INDEX: /* Return an additional reference to the object */ ObjDesc = SourceDesc; AcpiUtAddReference (ObjDesc); break; default: /* No named references are allowed here */ ACPI_ERROR ((AE_INFO, "Unsupported Reference type 0x%X", SourceDesc->Reference.Class)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } break; default: /* Default case is for unknown types */ ACPI_ERROR ((AE_INFO, "Node %p - Unknown object type 0x%X", Node, EntryType)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* switch (EntryType) */ /* Return the object descriptor */ *ObjectPtr = (void *) ObjDesc; return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiEvaluateObject ( ACPI_HANDLE Handle, ACPI_STRING Pathname, ACPI_OBJECT_LIST *ExternalParams, ACPI_BUFFER *ReturnBuffer) { ACPI_STATUS Status; ACPI_EVALUATE_INFO *Info; ACPI_SIZE BufferSpaceNeeded; UINT32 i; ACPI_FUNCTION_TRACE (AcpiEvaluateObject); /* Allocate and initialize the evaluation information block */ Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); if (!Info) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Convert and validate the device handle */ Info->PrefixNode = AcpiNsValidateHandle (Handle); if (!Info->PrefixNode) { 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->PrefixNode = 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->RelativePathname = Pathname; /* * Convert all external objects passed as arguments to the * internal version(s). */ if (ExternalParams && ExternalParams->Count) { Info->ParamCount = (UINT16) ExternalParams->Count; /* Warn on impossible argument count */ if (Info->ParamCount > ACPI_METHOD_NUM_ARGS) { ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, "Excess arguments (%u) - using only %u", Info->ParamCount, ACPI_METHOD_NUM_ARGS)); Info->ParamCount = 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->ParamCount + 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->ParamCount; i++) { Status = AcpiUtCopyEobjectToIobject ( &ExternalParams->Pointer[i], &Info->Parameters[i]); if (ACPI_FAILURE (Status)) { goto Cleanup; } } Info->Parameters[Info->ParamCount] = NULL; } #if 0 /* * Begin incoming argument count analysis. Check for too few args * and too many args. */ switch (AcpiNsGetType (Info->Node)) { case ACPI_TYPE_METHOD: /* Check incoming argument count against the method definition */ if (Info->ObjDesc->Method.ParamCount > Info->ParamCount) { ACPI_ERROR ((AE_INFO, "Insufficient arguments (%u) - %u are required", Info->ParamCount, Info->ObjDesc->Method.ParamCount)); Status = AE_MISSING_ARGUMENTS; goto Cleanup; } else if (Info->ObjDesc->Method.ParamCount < Info->ParamCount) { ACPI_WARNING ((AE_INFO, "Excess arguments (%u) - only %u are required", Info->ParamCount, Info->ObjDesc->Method.ParamCount)); /* Just pass the required number of arguments */ Info->ParamCount = Info->ObjDesc->Method.ParamCount; } /* * Any incoming external objects to be passed as arguments to the * method must be converted to internal objects */ if (Info->ParamCount) { /* * 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->ParamCount + 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->ParamCount; i++) { Status = AcpiUtCopyEobjectToIobject ( &ExternalParams->Pointer[i], &Info->Parameters[i]); if (ACPI_FAILURE (Status)) { goto Cleanup; } } Info->Parameters[Info->ParamCount] = NULL; } break; default: /* Warn if arguments passed to an object that is not a method */ if (Info->ParamCount) { ACPI_WARNING ((AE_INFO, "%u arguments were passed to a non-method ACPI object", Info->ParamCount)); } break; } #endif /* Now we can evaluate the object */ Status = AcpiNsEvaluate (Info); /* * If we are expecting a return value, and all went well above, * copy the return value to an external object. */ if (ReturnBuffer) { if (!Info->ReturnObject) { ReturnBuffer->Length = 0; } else { if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) == 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->ReturnObject = NULL; /* No need to delete a NS Node */ ReturnBuffer->Length = 0; } if (ACPI_SUCCESS (Status)) { /* Dereference Index and RefOf references */ AcpiNsResolveReferences (Info); /* Get the size of the returned object */ Status = AcpiUtGetObjectSize (Info->ReturnObject, &BufferSpaceNeeded); if (ACPI_SUCCESS (Status)) { /* Validate/Allocate/Clear caller buffer */ Status = AcpiUtInitializeBuffer (ReturnBuffer, BufferSpaceNeeded); 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", (UINT32) BufferSpaceNeeded, AcpiFormatException (Status))); } else { /* We have enough space for the object, build it */ Status = AcpiUtCopyIobjectToEobject ( Info->ReturnObject, ReturnBuffer); } } } } } if (Info->ReturnObject) { /* * Delete the internal return object. NOTE: Interpreter must be * locked to avoid race condition. */ AcpiExEnterInterpreter (); /* Remove one reference on the return object (should delete it) */ AcpiUtRemoveReference (Info->ReturnObject); AcpiExExitInterpreter (); } Cleanup: /* Free the input parameter list (if we created one) */ if (Info->Parameters) { /* Free the allocated parameter block */ AcpiUtDeleteInternalObjectList (Info->Parameters); } ACPI_FREE (Info); return_ACPI_STATUS (Status); }
static void AcpiNsExecModuleCode ( ACPI_OPERAND_OBJECT *MethodObj, ACPI_EVALUATE_INFO *Info) { ACPI_OPERAND_OBJECT *ParentObj; ACPI_NAMESPACE_NODE *ParentNode; ACPI_OBJECT_TYPE Type; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (NsExecModuleCode); /* * Get the parent node. We cheat by using the NextObject field * of the method object descriptor. */ ParentNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, MethodObj->Method.NextObject); Type = AcpiNsGetType (ParentNode); /* * Get the region handler and save it in the method object. We may need * this if an operation region declaration causes a _REG method to be run. * * We can't do this in AcpiPsLinkModuleCode because * AcpiGbl_RootNode->Object is NULL at PASS1. */ if ((Type == ACPI_TYPE_DEVICE) && ParentNode->Object) { MethodObj->Method.Dispatch.Handler = ParentNode->Object->Device.Handler; } /* Must clear NextObject (AcpiNsAttachObject needs the field) */ MethodObj->Method.NextObject = NULL; /* Initialize the evaluation information block */ ACPI_MEMSET (Info, 0, sizeof (ACPI_EVALUATE_INFO)); Info->PrefixNode = ParentNode; /* * Get the currently attached parent object. Add a reference, because the * ref count will be decreased when the method object is installed to * the parent node. */ ParentObj = AcpiNsGetAttachedObject (ParentNode); if (ParentObj) { AcpiUtAddReference (ParentObj); } /* Install the method (module-level code) in the parent node */ Status = AcpiNsAttachObject (ParentNode, MethodObj, ACPI_TYPE_METHOD); if (ACPI_FAILURE (Status)) { goto Exit; } /* Execute the parent node as a control method */ Status = AcpiNsEvaluate (Info); ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Executed module-level code at %p\n", MethodObj->Method.AmlStart)); /* Delete a possible implicit return value (in slack mode) */ if (Info->ReturnObject) { AcpiUtRemoveReference (Info->ReturnObject); } /* Detach the temporary method object */ AcpiNsDetachObject (ParentNode); /* Restore the original parent object */ if (ParentObj) { Status = AcpiNsAttachObject (ParentNode, ParentObj, Type); } else { ParentNode->Type = (UINT8) Type; } Exit: if (ParentObj) { AcpiUtRemoveReference (ParentObj); } return_VOID; }
ACPI_STATUS AcpiExStoreObjectToNode ( ACPI_OPERAND_OBJECT *SourceDesc, ACPI_NAMESPACE_NODE *Node, ACPI_WALK_STATE *WalkState, UINT8 ImplicitConversion) { ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT *TargetDesc; ACPI_OPERAND_OBJECT *NewDesc; ACPI_OBJECT_TYPE TargetType; ACPI_FUNCTION_TRACE_PTR (ExStoreObjectToNode, SourceDesc); /* Get current type of the node, and object attached to Node */ TargetType = AcpiNsGetType (Node); TargetDesc = AcpiNsGetAttachedObject (Node); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p (%s) to node %p (%s)\n", SourceDesc, AcpiUtGetObjectTypeName (SourceDesc), Node, AcpiUtGetTypeName (TargetType))); /* * Resolve the source object to an actual value * (If it is a reference object) */ Status = AcpiExResolveObject (&SourceDesc, TargetType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Do the actual store operation */ switch (TargetType) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * The simple data types all support implicit source operand * conversion before the store. */ if ((WalkState->Opcode == AML_COPY_OP) || !ImplicitConversion) { /* * However, CopyObject and Stores to ArgX do not perform * an implicit conversion, as per the ACPI specification. * A direct store is performed instead. */ Status = AcpiExStoreDirectToNode (SourceDesc, Node, WalkState); break; } /* Store with implicit source operand conversion support */ Status = AcpiExStoreObjectToObject (SourceDesc, TargetDesc, &NewDesc, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (NewDesc != TargetDesc) { /* * Store the new NewDesc as the new value of the Name, and set * the Name's type to that of the value being stored in it. * SourceDesc reference count is incremented by AttachObject. * * Note: This may change the type of the node if an explicit * store has been performed such that the node/object type * has been changed. */ Status = AcpiNsAttachObject (Node, NewDesc, NewDesc->Common.Type); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Store %s into %s via Convert/Attach\n", AcpiUtGetObjectTypeName (SourceDesc), AcpiUtGetObjectTypeName (NewDesc))); } break; case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: /* * For all fields, always write the source data to the target * field. Any required implicit source operand conversion is * performed in the function below as necessary. Note, field * objects must retain their original type permanently. */ Status = AcpiExWriteDataToField (SourceDesc, TargetDesc, &WalkState->ResultObj); break; default: /* * No conversions for all other types. Directly store a copy of * the source object. This is the ACPI spec-defined behavior for * the CopyObject operator. * * NOTE: For the Store operator, this is a departure from the * ACPI spec, which states "If conversion is impossible, abort * the running control method". Instead, this code implements * "If conversion is impossible, treat the Store operation as * a CopyObject". */ Status = AcpiExStoreDirectToNode (SourceDesc, Node, WalkState); break; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiDsInitOneObject ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_OBJECT_TYPE Type; ACPI_STATUS Status; ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context; ACPI_FUNCTION_NAME ("DsInitOneObject"); /* * We are only interested in objects owned by the table that * was just loaded */ if (((ACPI_NAMESPACE_NODE *) ObjHandle)->OwnerId != Info->TableDesc->TableId) { return (AE_OK); } Info->ObjectCount++; /* And even then, we are only interested in a few object types */ Type = AcpiNsGetType (ObjHandle); switch (Type) { case ACPI_TYPE_REGION: Status = AcpiDsInitializeRegion (ObjHandle); if (ACPI_FAILURE (Status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %p [%4.4s] - Init failure, %s\n", ObjHandle, ((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Ascii, AcpiFormatException (Status))); } Info->OpRegionCount++; break; case ACPI_TYPE_METHOD: Info->MethodCount++; /* Print a dot for each method unless we are going to print the entire pathname */ if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES)) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, ".")); } /* * Set the execution data width (32 or 64) based upon the * revision number of the parent ACPI table. * TBD: This is really for possible future support of integer width * on a per-table basis. Currently, we just use a global for the width. */ if (Info->TableDesc->Pointer->Revision == 1) { ((ACPI_NAMESPACE_NODE *) ObjHandle)->Flags |= ANOBJ_DATA_WIDTH_32; } /* * Always parse methods to detect errors, we may delete * the parse tree below */ Status = AcpiDsParseMethod (ObjHandle); if (ACPI_FAILURE (Status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n", ObjHandle, ((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Ascii, AcpiFormatException (Status))); /* This parse failed, but we will continue parsing more methods */ break; } /* * Delete the parse tree. We simple re-parse the method * for every execution since there isn't much overhead */ AcpiNsDeleteNamespaceSubtree (ObjHandle); AcpiNsDeleteNamespaceByOwner (((ACPI_NAMESPACE_NODE *) ObjHandle)->Object->Method.OwningId); break; case ACPI_TYPE_DEVICE: Info->DeviceCount++; 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. */ return (AE_OK); }
ACPI_STATUS AcpiNsEvaluate ( ACPI_EVALUATE_INFO *Info) { ACPI_STATUS Status; ACPI_FUNCTION_TRACE (NsEvaluate); if (!Info) { return_ACPI_STATUS (AE_BAD_PARAMETER); } if (!Info->Node) { /* * Get the actual namespace node for the target object if we * need to. 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 */ Status = AcpiNsGetNode (Info->PrefixNode, Info->RelativePathname, ACPI_NS_NO_UPSEARCH, &Info->Node); 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->Node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) { Info->Node = ACPI_CAST_PTR ( ACPI_NAMESPACE_NODE, Info->Node->Object); } /* Complete the info block initialization */ Info->ReturnObject = NULL; Info->NodeFlags = Info->Node->Flags; Info->ObjDesc = AcpiNsGetAttachedObject (Info->Node); ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n", Info->RelativePathname, Info->Node, AcpiNsGetAttachedObject (Info->Node))); /* Get info if we have a predefined name (_HID, etc.) */ Info->Predefined = AcpiUtMatchPredefinedMethod (Info->Node->Name.Ascii); /* Get the full pathname to the object, for use in warning messages */ Info->FullPathname = AcpiNsGetExternalPathname (Info->Node); if (!Info->FullPathname) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Count the number of arguments being passed in */ Info->ParamCount = 0; if (Info->Parameters) { while (Info->Parameters[Info->ParamCount]) { Info->ParamCount++; } /* Warn on impossible argument count */ if (Info->ParamCount > ACPI_METHOD_NUM_ARGS) { ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, ACPI_WARN_ALWAYS, "Excess arguments (%u) - using only %u", Info->ParamCount, ACPI_METHOD_NUM_ARGS)); Info->ParamCount = ACPI_METHOD_NUM_ARGS; } } /* * For predefined names: Check that the declared argument count * matches the ACPI spec -- otherwise this is a BIOS error. */ AcpiNsCheckAcpiCompliance (Info->FullPathname, Info->Node, Info->Predefined); /* * For all names: Check that the incoming argument count for * this method/object matches the actual ASL/AML definition. */ AcpiNsCheckArgumentCount (Info->FullPathname, Info->Node, Info->ParamCount, Info->Predefined); /* For predefined names: Typecheck all incoming arguments */ AcpiNsCheckArgumentTypes (Info); /* * Three major evaluation cases: * * 1) Object types that cannot be evaluated by definition * 2) The object is a control method -- execute it * 3) The object is not a method -- just return it's current value */ switch (AcpiNsGetType (Info->Node)) { 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: /* * 1) Disallow evaluation of certain object types. For these, * object evaluation is undefined and not supported. */ ACPI_ERROR ((AE_INFO, "%s: Evaluation of object type [%s] is not supported", Info->FullPathname, AcpiUtGetTypeName (Info->Node->Type))); Status = AE_TYPE; goto Cleanup; case ACPI_TYPE_METHOD: /* * 2) Object is a control method - execute it */ /* Verify that there is a method object associated with this node */ if (!Info->ObjDesc) { ACPI_ERROR ((AE_INFO, "%s: Method has no attached sub-object", Info->FullPathname)); Status = AE_NULL_OBJECT; goto Cleanup; } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "**** Execute method [%s] at AML address %p length %X\n", Info->FullPathname, 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 (); break; default: /* * 3) All other non-method objects -- get the current object value */ /* * Some 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 * the Node 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 (); /* TBD: ResolveNodeToValue has a strange interface, fix */ Info->ReturnObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Info->Node); Status = AcpiExResolveNodeToValue (ACPI_CAST_INDIRECT_PTR ( ACPI_NAMESPACE_NODE, &Info->ReturnObject), NULL); AcpiExExitInterpreter (); if (ACPI_FAILURE (Status)) { goto Cleanup; } ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returned object %p [%s]\n", Info->ReturnObject, AcpiUtGetObjectTypeName (Info->ReturnObject))); Status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */ break; } /* * For predefined names, check the return value against the ACPI * specification. Some incorrect return value types are repaired. */ (void) AcpiNsCheckReturnValue (Info->Node, Info, 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->RelativePathname)); Cleanup: /* * Namespace was unlocked by the handling AcpiNs* function, so we * just free the pathname and return */ ACPI_FREE (Info->FullPathname); Info->FullPathname = NULL; return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExPrepFieldValue ( ACPI_CREATE_FIELD_INFO *Info) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *SecondDesc = NULL; ACPI_STATUS Status; UINT32 AccessByteWidth; UINT32 Type; ACPI_FUNCTION_TRACE (ExPrepFieldValue); /* Parameter validation */ if (Info->FieldType != ACPI_TYPE_LOCAL_INDEX_FIELD) { if (!Info->RegionNode) { ACPI_ERROR ((AE_INFO, "Null RegionNode")); return_ACPI_STATUS (AE_AML_NO_OPERAND); } Type = AcpiNsGetType (Info->RegionNode); if (Type != ACPI_TYPE_REGION) { ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)", Type, AcpiUtGetTypeName (Type))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } } /* Allocate a new field object */ ObjDesc = AcpiUtCreateInternalObject (Info->FieldType); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Initialize areas of the object that are common to all fields */ ObjDesc->CommonField.Node = Info->FieldNode; Status = AcpiExPrepCommonFieldObject (ObjDesc, Info->FieldFlags, Info->Attribute, Info->FieldBitPosition, Info->FieldBitLength); if (ACPI_FAILURE (Status)) { AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (Status); } /* Initialize areas of the object that are specific to the field type */ switch (Info->FieldType) { case ACPI_TYPE_LOCAL_REGION_FIELD: ObjDesc->Field.RegionObj = AcpiNsGetAttachedObject (Info->RegionNode); /* Fields specific to GenericSerialBus fields */ ObjDesc->Field.AccessLength = Info->AccessLength; if (Info->ConnectionNode) { SecondDesc = Info->ConnectionNode->Object; if (!(SecondDesc->Common.Flags & AOPOBJ_DATA_VALID)) { Status = AcpiDsGetBufferArguments (SecondDesc); if (ACPI_FAILURE (Status)) { AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (Status); } } ObjDesc->Field.ResourceBuffer = SecondDesc->Buffer.Pointer; ObjDesc->Field.ResourceLength = (UINT16) SecondDesc->Buffer.Length; } else if (Info->ResourceBuffer) { ObjDesc->Field.ResourceBuffer = Info->ResourceBuffer; ObjDesc->Field.ResourceLength = Info->ResourceLength; } /* Allow full data read from EC address space */ if ((ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) && (ObjDesc->CommonField.BitLength > 8)) { AccessByteWidth = ACPI_ROUND_BITS_UP_TO_BYTES ( ObjDesc->CommonField.BitLength); /* Maximum byte width supported is 255 */ if (AccessByteWidth < 256) { ObjDesc->CommonField.AccessByteWidth = (UINT8) AccessByteWidth; } } /* An additional reference for the container */ AcpiUtAddReference (ObjDesc->Field.RegionObj); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", ObjDesc->Field.StartFieldBitOffset, ObjDesc->Field.BaseByteOffset, ObjDesc->Field.AccessByteWidth, ObjDesc->Field.RegionObj)); break; case ACPI_TYPE_LOCAL_BANK_FIELD: ObjDesc->BankField.Value = Info->BankValue; ObjDesc->BankField.RegionObj = AcpiNsGetAttachedObject (Info->RegionNode); ObjDesc->BankField.BankObj = AcpiNsGetAttachedObject (Info->RegisterNode); /* An additional reference for the attached objects */ AcpiUtAddReference (ObjDesc->BankField.RegionObj); AcpiUtAddReference (ObjDesc->BankField.BankObj); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n", ObjDesc->BankField.StartFieldBitOffset, ObjDesc->BankField.BaseByteOffset, ObjDesc->Field.AccessByteWidth, ObjDesc->BankField.RegionObj, ObjDesc->BankField.BankObj)); /* * Remember location in AML stream of the field unit * opcode and operands -- since the BankValue * operands must be evaluated. */ SecondDesc = ObjDesc->Common.NextObject; SecondDesc->Extra.AmlStart = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Info->DataRegisterNode)->Named.Data; SecondDesc->Extra.AmlLength = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Info->DataRegisterNode)->Named.Length; break; case ACPI_TYPE_LOCAL_INDEX_FIELD: /* Get the Index and Data registers */ ObjDesc->IndexField.IndexObj = AcpiNsGetAttachedObject (Info->RegisterNode); ObjDesc->IndexField.DataObj = AcpiNsGetAttachedObject (Info->DataRegisterNode); if (!ObjDesc->IndexField.DataObj || !ObjDesc->IndexField.IndexObj) { ACPI_ERROR ((AE_INFO, "Null Index Object during field prep")); AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (AE_AML_INTERNAL); } /* An additional reference for the attached objects */ AcpiUtAddReference (ObjDesc->IndexField.DataObj); AcpiUtAddReference (ObjDesc->IndexField.IndexObj); /* * April 2006: Changed to match MS behavior * * The value written to the Index register is the byte offset of the * target field in units of the granularity of the IndexField * * Previously, the value was calculated as an index in terms of the * width of the Data register, as below: * * ObjDesc->IndexField.Value = (UINT32) * (Info->FieldBitPosition / ACPI_MUL_8 ( * ObjDesc->Field.AccessByteWidth)); * * February 2006: Tried value as a byte offset: * ObjDesc->IndexField.Value = (UINT32) * ACPI_DIV_8 (Info->FieldBitPosition); */ ObjDesc->IndexField.Value = (UINT32) ACPI_ROUND_DOWN ( ACPI_DIV_8 (Info->FieldBitPosition), ObjDesc->IndexField.AccessByteWidth); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n", ObjDesc->IndexField.StartFieldBitOffset, ObjDesc->IndexField.BaseByteOffset, ObjDesc->IndexField.Value, ObjDesc->Field.AccessByteWidth, ObjDesc->IndexField.IndexObj, ObjDesc->IndexField.DataObj)); break; default: /* No other types should get here */ break; } /* * Store the constructed descriptor (ObjDesc) into the parent Node, * preserving the current type of that NamedObj. */ Status = AcpiNsAttachObject (Info->FieldNode, ObjDesc, AcpiNsGetType (Info->FieldNode)); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set NamedObj %p [%4.4s], ObjDesc %p\n", Info->FieldNode, AcpiUtGetNodeName (Info->FieldNode), ObjDesc)); /* Remove local reference to the object */ AcpiUtRemoveReference (ObjDesc); return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiDsInitOneObject ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context; ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; ACPI_OBJECT_TYPE Type; ACPI_STATUS Status; ACPI_FUNCTION_ENTRY (); /* * We are only interested in NS nodes owned by the table that * was just loaded */ if (Node->OwnerId != Info->OwnerId) { return (AE_OK); } Info->ObjectCount++; /* And even then, we are only interested in a few object types */ Type = AcpiNsGetType (ObjHandle); switch (Type) { case ACPI_TYPE_REGION: Status = AcpiDsInitializeRegion (ObjHandle); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "During Region initialization %p [%4.4s]", ObjHandle, AcpiUtGetNodeName (ObjHandle))); } Info->OpRegionCount++; break; case ACPI_TYPE_METHOD: Info->MethodCount++; break; case ACPI_TYPE_DEVICE: Info->DeviceCount++; 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. */ return (AE_OK); }
static ACPI_STATUS AcpiDsInitOneObject ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context; ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_FUNCTION_ENTRY (); /* * We are only interested in NS nodes owned by the table that * was just loaded */ if (Node->OwnerId != Info->OwnerId) { return (AE_OK); } Info->ObjectCount++; /* And even then, we are only interested in a few object types */ switch (AcpiNsGetType (ObjHandle)) { case ACPI_TYPE_REGION: Status = AcpiDsInitializeRegion (ObjHandle); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "During Region initialization %p [%4.4s]", ObjHandle, AcpiUtGetNodeName (ObjHandle))); } Info->OpRegionCount++; break; case ACPI_TYPE_METHOD: /* * Auto-serialization support. We will examine each method that is * NotSerialized to determine if it creates any Named objects. If * it does, it will be marked serialized to prevent problems if * the method is entered by two or more threads and an attempt is * made to create the same named object twice -- which results in * an AE_ALREADY_EXISTS exception and method abort. */ Info->MethodCount++; ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { break; } /* Ignore if already serialized */ if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED) { Info->SerialMethodCount++; break; } if (AcpiGbl_AutoSerializeMethods) { /* Parse/scan method and serialize it if necessary */ AcpiDsAutoSerializeMethod (Node, ObjDesc); if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED) { /* Method was just converted to Serialized */ Info->SerialMethodCount++; Info->SerializedMethodCount++; break; } } Info->NonSerialMethodCount++; break; case ACPI_TYPE_DEVICE: Info->DeviceCount++; 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. */ return (AE_OK); }
static ACPI_STATUS AcpiUtCopyIsimpleToEsimple ( ACPI_OPERAND_OBJECT *InternalObject, ACPI_OBJECT *ExternalObject, UINT8 *DataSpace, ACPI_SIZE *BufferSpaceUsed) { ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE (UtCopyIsimpleToEsimple); *BufferSpaceUsed = 0; /* * Check for NULL object case (could be an uninitialized * package element) */ if (!InternalObject) { return_ACPI_STATUS (AE_OK); } /* Always clear the external object */ ACPI_MEMSET (ExternalObject, 0, sizeof (ACPI_OBJECT)); /* * In general, the external object will be the same type as * the internal object */ ExternalObject->Type = InternalObject->Common.Type; /* However, only a limited number of external types are supported */ switch (InternalObject->Common.Type) { case ACPI_TYPE_STRING: ExternalObject->String.Pointer = (char *) DataSpace; ExternalObject->String.Length = InternalObject->String.Length; *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD ( (ACPI_SIZE) InternalObject->String.Length + 1); ACPI_MEMCPY ((void *) DataSpace, (void *) InternalObject->String.Pointer, (ACPI_SIZE) InternalObject->String.Length + 1); break; case ACPI_TYPE_BUFFER: ExternalObject->Buffer.Pointer = DataSpace; ExternalObject->Buffer.Length = InternalObject->Buffer.Length; *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD ( InternalObject->String.Length); ACPI_MEMCPY ((void *) DataSpace, (void *) InternalObject->Buffer.Pointer, InternalObject->Buffer.Length); break; case ACPI_TYPE_INTEGER: ExternalObject->Integer.Value = InternalObject->Integer.Value; break; case ACPI_TYPE_LOCAL_REFERENCE: /* This is an object reference. */ switch (InternalObject->Reference.Class) { case ACPI_REFCLASS_NAME: /* * For namepath, return the object handle ("reference") * We are referring to the namespace node */ ExternalObject->Reference.Handle = InternalObject->Reference.Node; ExternalObject->Reference.ActualType = AcpiNsGetType (InternalObject->Reference.Node); break; default: /* All other reference types are unsupported */ return_ACPI_STATUS (AE_TYPE); } break; case ACPI_TYPE_PROCESSOR: ExternalObject->Processor.ProcId = InternalObject->Processor.ProcId; ExternalObject->Processor.PblkAddress = InternalObject->Processor.Address; ExternalObject->Processor.PblkLength = InternalObject->Processor.Length; break; case ACPI_TYPE_POWER: ExternalObject->PowerResource.SystemLevel = InternalObject->PowerResource.SystemLevel; ExternalObject->PowerResource.ResourceOrder = InternalObject->PowerResource.ResourceOrder; break; default: /* * There is no corresponding external object type */ ACPI_ERROR ((AE_INFO, "Unsupported object type, cannot convert to external object: %s", AcpiUtGetTypeName (InternalObject->Common.Type))); return_ACPI_STATUS (AE_SUPPORT); } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExResolveMultiple ( ACPI_WALK_STATE *WalkState, ACPI_OPERAND_OBJECT *Operand, ACPI_OBJECT_TYPE *ReturnType, ACPI_OPERAND_OBJECT **ReturnDesc) { ACPI_OPERAND_OBJECT *ObjDesc = (void *) Operand; ACPI_NAMESPACE_NODE *Node; ACPI_OBJECT_TYPE Type; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (AcpiExResolveMultiple); /* Operand can be either a namespace node or an operand descriptor */ switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) { case ACPI_DESC_TYPE_OPERAND: Type = ObjDesc->Common.Type; break; case ACPI_DESC_TYPE_NAMED: Type = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type; ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc); /* If we had an Alias node, use the attached object for type info */ if (Type == ACPI_TYPE_LOCAL_ALIAS) { Type = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type; ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc); } break; default: return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* If type is anything other than a reference, we are done */ if (Type != ACPI_TYPE_LOCAL_REFERENCE) { goto Exit; } /* * For reference objects created via the RefOf, Index, or Load/LoadTable * operators, we need to get to the base object (as per the ACPI * specification of the ObjectType and SizeOf operators). This means * traversing the list of possibly many nested references. */ while (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) { switch (ObjDesc->Reference.Class) { case ACPI_REFCLASS_REFOF: case ACPI_REFCLASS_NAME: /* Dereference the reference pointer */ if (ObjDesc->Reference.Class == ACPI_REFCLASS_REFOF) { Node = ObjDesc->Reference.Object; } else /* AML_INT_NAMEPATH_OP */ { Node = ObjDesc->Reference.Node; } /* All "References" point to a NS node */ if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) { ACPI_ERROR ((AE_INFO, "Not a namespace node %p [%s]", Node, AcpiUtGetDescriptorName (Node))); return_ACPI_STATUS (AE_AML_INTERNAL); } /* Get the attached object */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { /* No object, use the NS node type */ Type = AcpiNsGetType (Node); goto Exit; } /* Check for circular references */ if (ObjDesc == Operand) { return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE); } break; case ACPI_REFCLASS_INDEX: /* Get the type of this reference (index into another object) */ Type = ObjDesc->Reference.TargetType; if (Type != ACPI_TYPE_PACKAGE) { goto Exit; } /* * The main object is a package, we want to get the type * of the individual package element that is referenced by * the index. * * This could of course in turn be another reference object. */ ObjDesc = *(ObjDesc->Reference.Where); if (!ObjDesc) { /* NULL package elements are allowed */ Type = 0; /* Uninitialized */ goto Exit; } break; case ACPI_REFCLASS_TABLE: Type = ACPI_TYPE_DDB_HANDLE; goto Exit; case ACPI_REFCLASS_LOCAL: case ACPI_REFCLASS_ARG: if (ReturnDesc) { Status = AcpiDsMethodDataGetValue (ObjDesc->Reference.Class, ObjDesc->Reference.Value, WalkState, &ObjDesc); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } AcpiUtRemoveReference (ObjDesc); } else { Status = AcpiDsMethodDataGetNode (ObjDesc->Reference.Class, ObjDesc->Reference.Value, WalkState, &Node); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { Type = ACPI_TYPE_ANY; goto Exit; } } break; case ACPI_REFCLASS_DEBUG: /* The Debug Object is of type "DebugObject" */ Type = ACPI_TYPE_DEBUG_OBJECT; goto Exit; default: ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X", ObjDesc->Reference.Class)); return_ACPI_STATUS (AE_AML_INTERNAL); } } /* * Now we are guaranteed to have an object that has not been created * via the RefOf or Index operators. */ Type = ObjDesc->Common.Type; Exit: /* Convert internal types to external types */ switch (Type) { case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: Type = ACPI_TYPE_FIELD_UNIT; break; case ACPI_TYPE_LOCAL_SCOPE: /* Per ACPI Specification, Scope is untyped */ Type = ACPI_TYPE_ANY; break; default: /* No change to Type required */ break; } *ReturnType = Type; if (ReturnDesc) { *ReturnDesc = ObjDesc; } return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiExStoreObjectToNode ( ACPI_OPERAND_OBJECT *SourceDesc, ACPI_NAMESPACE_NODE *Node, ACPI_WALK_STATE *WalkState, UINT8 ImplicitConversion) { ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT *TargetDesc; ACPI_OPERAND_OBJECT *NewDesc; ACPI_OBJECT_TYPE TargetType; ACPI_FUNCTION_TRACE_PTR (ExStoreObjectToNode, SourceDesc); /* Get current type of the node, and object attached to Node */ TargetType = AcpiNsGetType (Node); TargetDesc = AcpiNsGetAttachedObject (Node); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p [%s] to node %p [%s]\n", SourceDesc, AcpiUtGetObjectTypeName (SourceDesc), Node, AcpiUtGetTypeName (TargetType))); /* Only limited target types possible for everything except CopyObject */ if (WalkState->Opcode != AML_COPY_OBJECT_OP) { /* * Only CopyObject allows all object types to be overwritten. For * TargetRef(s), there are restrictions on the object types that * are allowed. * * Allowable operations/typing for Store: * * 1) Simple Store * Integer --> Integer (Named/Local/Arg) * String --> String (Named/Local/Arg) * Buffer --> Buffer (Named/Local/Arg) * Package --> Package (Named/Local/Arg) * * 2) Store with implicit conversion * Integer --> String or Buffer (Named) * String --> Integer or Buffer (Named) * Buffer --> Integer or String (Named) */ switch (TargetType) { case ACPI_TYPE_PACKAGE: /* * Here, can only store a package to an existing package. * Storing a package to a Local/Arg is OK, and handled * elsewhere. */ if (WalkState->Opcode == AML_STORE_OP) { if (SourceDesc->Common.Type != ACPI_TYPE_PACKAGE) { ACPI_ERROR ((AE_INFO, "Cannot assign type [%s] to [Package] " "(source must be type Pkg)", AcpiUtGetObjectTypeName (SourceDesc))); return_ACPI_STATUS (AE_AML_TARGET_TYPE); } break; } /* Fallthrough */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_EVENT: case ACPI_TYPE_MUTEX: case ACPI_TYPE_REGION: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: ACPI_ERROR ((AE_INFO, "Target must be [Buffer/Integer/String/Reference]" ", found [%s] (%4.4s)", AcpiUtGetTypeName (Node->Type), Node->Name.Ascii)); return_ACPI_STATUS (AE_AML_TARGET_TYPE); default: break; } } /* * Resolve the source object to an actual value * (If it is a reference object) */ Status = AcpiExResolveObject (&SourceDesc, TargetType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Do the actual store operation */ switch (TargetType) { /* * The simple data types all support implicit source operand * conversion before the store. */ case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: if ((WalkState->Opcode == AML_COPY_OBJECT_OP) || !ImplicitConversion) { /* * However, CopyObject and Stores to ArgX do not perform * an implicit conversion, as per the ACPI specification. * A direct store is performed instead. */ Status = AcpiExStoreDirectToNode (SourceDesc, Node, WalkState); break; } /* Store with implicit source operand conversion support */ Status = AcpiExStoreObjectToObject (SourceDesc, TargetDesc, &NewDesc, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (NewDesc != TargetDesc) { /* * Store the new NewDesc as the new value of the Name, and set * the Name's type to that of the value being stored in it. * SourceDesc reference count is incremented by AttachObject. * * Note: This may change the type of the node if an explicit * store has been performed such that the node/object type * has been changed. */ Status = AcpiNsAttachObject ( Node, NewDesc, NewDesc->Common.Type); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Store type [%s] into [%s] via Convert/Attach\n", AcpiUtGetObjectTypeName (SourceDesc), AcpiUtGetObjectTypeName (NewDesc))); } break; case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: /* * For all fields, always write the source data to the target * field. Any required implicit source operand conversion is * performed in the function below as necessary. Note, field * objects must retain their original type permanently. */ Status = AcpiExWriteDataToField (SourceDesc, TargetDesc, &WalkState->ResultObj); break; default: /* * CopyObject operator: No conversions for all other types. * Instead, directly store a copy of the source object. * * This is the ACPI spec-defined behavior for the CopyObject * operator. (Note, for this default case, all normal * Store/Target operations exited above with an error). */ Status = AcpiExStoreDirectToNode (SourceDesc, Node, WalkState); break; } return_ACPI_STATUS (Status); }
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); }
ACPI_STATUS AcpiExStoreObjectToNode ( ACPI_OPERAND_OBJECT *SourceDesc, ACPI_NAMESPACE_NODE *Node, ACPI_WALK_STATE *WalkState, UINT8 ImplicitConversion) { ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT *TargetDesc; ACPI_OPERAND_OBJECT *NewDesc; ACPI_OBJECT_TYPE TargetType; ACPI_FUNCTION_TRACE_PTR (ExStoreObjectToNode, SourceDesc); /* Get current type of the node, and object attached to Node */ TargetType = AcpiNsGetType (Node); TargetDesc = AcpiNsGetAttachedObject (Node); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", SourceDesc, AcpiUtGetObjectTypeName (SourceDesc), Node, AcpiUtGetTypeName (TargetType))); /* * Resolve the source object to an actual value * (If it is a reference object) */ Status = AcpiExResolveObject (&SourceDesc, TargetType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* If no implicit conversion, drop into the default case below */ if ((!ImplicitConversion) || ((WalkState->Opcode == AML_COPY_OP) && (TargetType != ACPI_TYPE_LOCAL_REGION_FIELD) && (TargetType != ACPI_TYPE_LOCAL_BANK_FIELD) && (TargetType != ACPI_TYPE_LOCAL_INDEX_FIELD))) { /* * Force execution of default (no implicit conversion). Note: * CopyObject does not perform an implicit conversion, as per the ACPI * spec -- except in case of region/bank/index fields -- because these * objects must retain their original type permanently. */ TargetType = ACPI_TYPE_ANY; } /* Do the actual store operation */ switch (TargetType) { case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: /* For fields, copy the source data to the target field. */ Status = AcpiExWriteDataToField (SourceDesc, TargetDesc, &WalkState->ResultObj); break; case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * These target types are all of type Integer/String/Buffer, and * therefore support implicit conversion before the store. * * Copy and/or convert the source object to a new target object */ Status = AcpiExStoreObjectToObject (SourceDesc, TargetDesc, &NewDesc, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (NewDesc != TargetDesc) { /* * Store the new NewDesc as the new value of the Name, and set * the Name's type to that of the value being stored in it. * SourceDesc reference count is incremented by AttachObject. * * Note: This may change the type of the node if an explicit store * has been performed such that the node/object type has been * changed. */ Status = AcpiNsAttachObject (Node, NewDesc, NewDesc->Common.Type); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Store %s into %s via Convert/Attach\n", AcpiUtGetObjectTypeName (SourceDesc), AcpiUtGetObjectTypeName (NewDesc))); } break; default: ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %s (%p) directly into node (%p) with no implicit conversion\n", AcpiUtGetObjectTypeName (SourceDesc), SourceDesc, Node)); /* No conversions for all other types. Just attach the source object */ Status = AcpiNsAttachObject (Node, SourceDesc, SourceDesc->Common.Type); break; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiNsEvaluateByHandle ( ACPI_NAMESPACE_NODE *Handle, ACPI_OPERAND_OBJECT **Params, ACPI_OPERAND_OBJECT **ReturnObject) { ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_OPERAND_OBJECT *LocalReturnObject; ACPI_FUNCTION_TRACE ("NsEvaluateByHandle"); /* Check if namespace has been initialized */ if (!AcpiGbl_RootNode) { return_ACPI_STATUS (AE_NO_NAMESPACE); } /* Parameter Validation */ if (!Handle) { return_ACPI_STATUS (AE_BAD_PARAMETER); } if (ReturnObject) { /* Initialize the return value to an invalid object */ *ReturnObject = NULL; } /* Get the prefix handle and Node */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } Node = AcpiNsMapHandleToNode (Handle); if (!Node) { (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Two major cases here: * 1) The object is an actual control method -- execute it. * 2) The object is not a method -- just return it's current * value * * In both cases, the namespace is unlocked by the * AcpiNs* procedure */ if (AcpiNsGetType (Node) == ACPI_TYPE_METHOD) { /* * Case 1) We have an actual control method to execute */ Status = AcpiNsExecuteControlMethod (Node, Params, &LocalReturnObject); } else { /* * Case 2) Object is NOT a method, just return its * current value */ Status = AcpiNsGetObjectValue (Node, &LocalReturnObject); } /* * Check if there is a return value on the stack that must * be dealt with */ if (Status == AE_CTRL_RETURN_VALUE) { /* * If the Method returned a value and the caller * provided a place to store a returned value, Copy * the returned value to the object descriptor provided * by the caller. */ if (ReturnObject) { /* * Valid return object, copy the pointer to * the returned object */ *ReturnObject = LocalReturnObject; } /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ Status = AE_OK; } /* * Namespace was unlocked by the handling AcpiNs* function, * so we just return */ return_ACPI_STATUS (Status); }