ACPI_STATUS AcpiDsMethodDataSetEntry ( UINT16 Opcode, UINT32 Index, ACPI_OPERAND_OBJECT *Object, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT **Entry; FUNCTION_TRACE ("DsMethodDataSetEntry"); /* Get a pointer to the stack entry to set */ Status = AcpiDsMethodDataGetEntry (Opcode, Index, WalkState, &Entry); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Increment ref count so object can't be deleted while installed */ AcpiUtAddReference (Object); /* Install the object into the stack entry */ *Entry = Object; return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiEvAttachRegion ( ACPI_OPERAND_OBJECT *HandlerObj, ACPI_OPERAND_OBJECT *RegionObj, BOOLEAN AcpiNsIsLocked) { ACPI_FUNCTION_TRACE (EvAttachRegion); ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Adding Region [%4.4s] %p to address handler %p [%s]\n", AcpiUtGetNodeName (RegionObj->Region.Node), RegionObj, HandlerObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); /* Link this region to the front of the handler's list */ RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList; HandlerObj->AddressSpace.RegionList = RegionObj; /* Install the region's handler */ if (RegionObj->Region.Handler) { return_ACPI_STATUS (AE_ALREADY_EXISTS); } RegionObj->Region.Handler = HandlerObj; AcpiUtAddReference (HandlerObj); return_ACPI_STATUS (AE_OK); }
static void AcpiNsResolveReferences ( ACPI_EVALUATE_INFO *Info) { ACPI_OPERAND_OBJECT *ObjDesc = NULL; ACPI_NAMESPACE_NODE *Node; /* We are interested in reference objects only */ if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) { return; } /* * Two types of references are supported - those created by Index and * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to * an ACPI_OBJECT. */ switch (Info->ReturnObject->Reference.Class) { case ACPI_REFCLASS_INDEX: ObjDesc = *(Info->ReturnObject->Reference.Where); break; case ACPI_REFCLASS_REFOF: Node = Info->ReturnObject->Reference.Object; if (Node) { ObjDesc = Node->Object; } break; default: return; } /* Replace the existing reference object */ if (ObjDesc) { AcpiUtAddReference (ObjDesc); AcpiUtRemoveReference (Info->ReturnObject); Info->ReturnObject = ObjDesc; } return; }
BOOLEAN AcpiDsDoImplicitReturn ( ACPI_OPERAND_OBJECT *ReturnDesc, ACPI_WALK_STATE *WalkState, BOOLEAN AddReference) { ACPI_FUNCTION_NAME (DsDoImplicitReturn); /* * Slack must be enabled for this feature, and we must * have a valid return object */ if ((!AcpiGbl_EnableInterpreterSlack) || (!ReturnDesc)) { return (FALSE); } ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result %p will be implicitly returned; Prev=%p\n", ReturnDesc, WalkState->ImplicitReturnObj)); /* * Delete any "stale" implicit return value first. However, in * complex statements, the implicit return value can be * bubbled up several levels, so we don't clear the value if it * is the same as the ReturnDesc. */ if (WalkState->ImplicitReturnObj) { if (WalkState->ImplicitReturnObj == ReturnDesc) { return (TRUE); } AcpiDsClearImplicitReturn (WalkState); } /* Save the implicit return value, add a reference if requested */ WalkState->ImplicitReturnObj = ReturnDesc; if (AddReference) { AcpiUtAddReference (ReturnDesc); } return (TRUE); }
static ACPI_STATUS AcpiDsMethodDataSetValue ( UINT8 Type, UINT32 Index, ACPI_OPERAND_OBJECT *Object, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; ACPI_FUNCTION_TRACE (DsMethodDataSetValue); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "NewObj %p Type %2.2X, Refs=%u [%s]\n", Object, Type, Object->Common.ReferenceCount, AcpiUtGetTypeName (Object->Common.Type))); /* Get the namespace node for the arg/local */ Status = AcpiDsMethodDataGetNode (Type, Index, WalkState, &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.0C) */ AcpiUtAddReference (Object); /* Install the object */ Node->Object = Object; return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiInstallNotifyHandler ( ACPI_HANDLE Device, UINT32 HandlerType, ACPI_NOTIFY_HANDLER Handler, void *Context) { ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device); ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerObj; ACPI_STATUS Status; UINT32 i; ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler); /* Parameter validation */ if ((!Device) || (!Handler) || (!HandlerType) || (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Root Object: * Registering a notify handler on the root object indicates that the * caller wishes to receive notifications for all objects. Note that * only one global handler can be registered per notify type. * Ensure that a handler is not already installed. */ if (Device == ACPI_ROOT_OBJECT) { for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (HandlerType & (i+1)) { if (AcpiGbl_GlobalNotify[i].Handler) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } AcpiGbl_GlobalNotify[i].Handler = Handler; AcpiGbl_GlobalNotify[i].Context = Context; } } goto UnlockAndExit; /* Global notify handler installed, all done */ } /* * All Other Objects: * Caller will only receive notifications specific to the target * object. Note that only certain object types are allowed to * receive notifications. */ /* Are Notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { Status = AE_TYPE; goto UnlockAndExit; } /* Check for an existing internal object, might not exist */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { /* Create a new object */ ObjDesc = AcpiUtCreateInternalObject (Node->Type); if (!ObjDesc) { Status = AE_NO_MEMORY; goto UnlockAndExit; } /* Attach new object to the Node, remove local reference */ Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type); AcpiUtRemoveReference (ObjDesc); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } } /* Ensure that the handler is not already installed in the lists */ for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (HandlerType & (i+1)) { HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; while (HandlerObj) { if (HandlerObj->Notify.Handler == Handler) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } HandlerObj = HandlerObj->Notify.Next[i]; } } } /* Create and populate a new notify handler object */ HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY); if (!HandlerObj) { Status = AE_NO_MEMORY; goto UnlockAndExit; } HandlerObj->Notify.Node = Node; HandlerObj->Notify.HandlerType = HandlerType; HandlerObj->Notify.Handler = Handler; HandlerObj->Notify.Context = Context; /* Install the handler at the list head(s) */ for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (HandlerType & (i+1)) { HandlerObj->Notify.Next[i] = ObjDesc->CommonNotify.NotifyList[i]; ObjDesc->CommonNotify.NotifyList[i] = HandlerObj; } } /* Add an extra reference if handler was installed in both lists */ if (HandlerType == ACPI_ALL_NOTIFY) { AcpiUtAddReference (HandlerObj); } UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiNsConvertToReference ( ACPI_NAMESPACE_NODE *Scope, ACPI_OPERAND_OBJECT *OriginalObject, ACPI_OPERAND_OBJECT **ReturnObject) { ACPI_OPERAND_OBJECT *NewObject = NULL; ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; ACPI_GENERIC_STATE ScopeInfo; char *Name; ACPI_FUNCTION_NAME (NsConvertToReference); /* Convert path into internal presentation */ Status = AcpiNsInternalizeName (OriginalObject->String.Pointer, &Name); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Find the namespace node */ ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Scope); Status = AcpiNsLookup (&ScopeInfo, Name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node); if (ACPI_FAILURE (Status)) { /* Check if we are resolving a named reference within a package */ ACPI_ERROR_NAMESPACE (&ScopeInfo, OriginalObject->String.Pointer, Status); goto ErrorExit; } /* Create and init a new internal ACPI object */ NewObject = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); if (!NewObject) { Status = AE_NO_MEMORY; goto ErrorExit; } NewObject->Reference.Node = Node; NewObject->Reference.Object = Node->Object; NewObject->Reference.Class = ACPI_REFCLASS_NAME; /* * Increase reference of the object if needed (the object is likely a * null for device nodes). */ AcpiUtAddReference (Node->Object); ErrorExit: ACPI_FREE (Name); *ReturnObject = NewObject; return (AE_OK); }
ACPI_STATUS AcpiDsExecEndOp ( ACPI_WALK_STATE *WalkState) { ACPI_PARSE_OBJECT *Op; ACPI_STATUS Status = AE_OK; UINT32 OpType; UINT32 OpClass; ACPI_PARSE_OBJECT *NextOp; ACPI_PARSE_OBJECT *FirstArg; ACPI_FUNCTION_TRACE_PTR (DsExecEndOp, WalkState); Op = WalkState->Op; OpType = WalkState->OpInfo->Type; OpClass = WalkState->OpInfo->Class; if (OpClass == AML_CLASS_UNKNOWN) { ACPI_ERROR ((AE_INFO, "Unknown opcode 0x%X", Op->Common.AmlOpcode)); return_ACPI_STATUS (AE_NOT_IMPLEMENTED); } FirstArg = Op->Common.Value.Arg; /* Init the walk state */ WalkState->NumOperands = 0; WalkState->OperandIndex = 0; WalkState->ReturnDesc = NULL; WalkState->ResultObj = NULL; /* Call debugger for single step support (DEBUG build only) */ Status = AcpiDbSingleStep (WalkState, Op, OpClass); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Decode the Opcode Class */ switch (OpClass) { case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */ if (WalkState->Opcode == AML_INT_NAMEPATH_OP) { Status = AcpiDsEvaluateNamePath (WalkState); if (ACPI_FAILURE (Status)) { goto Cleanup; } } break; case AML_CLASS_EXECUTE: /* Most operators with arguments */ /* Build resolved operand stack */ Status = AcpiDsCreateOperands (WalkState, FirstArg); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* * All opcodes require operand resolution, with the only exceptions * being the ObjectType and SizeOf operators. */ if (!(WalkState->OpInfo->Flags & AML_NO_OPERAND_RESOLVE)) { /* Resolve all operands */ Status = AcpiExResolveOperands (WalkState->Opcode, &(WalkState->Operands [WalkState->NumOperands -1]), WalkState); } if (ACPI_SUCCESS (Status)) { /* * Dispatch the request to the appropriate interpreter handler * routine. There is one routine per opcode "type" based upon the * number of opcode arguments and return type. */ Status = AcpiGbl_OpTypeDispatch[OpType] (WalkState); } else { /* * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the * Local is uninitialized. */ if ((Status == AE_AML_UNINITIALIZED_LOCAL) && (WalkState->Opcode == AML_STORE_OP) && (WalkState->Operands[0]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && (WalkState->Operands[1]->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && (WalkState->Operands[0]->Reference.Class == WalkState->Operands[1]->Reference.Class) && (WalkState->Operands[0]->Reference.Value == WalkState->Operands[1]->Reference.Value)) { Status = AE_OK; } else { ACPI_EXCEPTION ((AE_INFO, Status, "While resolving operands for [%s]", AcpiPsGetOpcodeName (WalkState->Opcode))); } } /* Always delete the argument objects and clear the operand stack */ AcpiDsClearOperands (WalkState); /* * If a result object was returned from above, push it on the * current result stack */ if (ACPI_SUCCESS (Status) && WalkState->ResultObj) { Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); } break; default: switch (OpType) { case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */ /* 1 Operand, 0 ExternalResult, 0 InternalResult */ Status = AcpiDsExecEndControlOp (WalkState, Op); break; case AML_TYPE_METHOD_CALL: /* * If the method is referenced from within a package * declaration, it is not a invocation of the method, just * a reference to it. */ if ((Op->Asl.Parent) && ((Op->Asl.Parent->Asl.AmlOpcode == AML_PACKAGE_OP) || (Op->Asl.Parent->Asl.AmlOpcode == AML_VAR_PACKAGE_OP))) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method Reference in a Package, Op=%p\n", Op)); Op->Common.Node = (ACPI_NAMESPACE_NODE *) Op->Asl.Value.Arg->Asl.Node; AcpiUtAddReference (Op->Asl.Value.Arg->Asl.Node->Object); return_ACPI_STATUS (AE_OK); } ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method invocation, Op=%p\n", Op)); /* * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains * the method Node pointer */ /* NextOp points to the op that holds the method name */ NextOp = FirstArg; /* NextOp points to first argument op */ NextOp = NextOp->Common.Next; /* * Get the method's arguments and put them on the operand stack */ Status = AcpiDsCreateOperands (WalkState, NextOp); if (ACPI_FAILURE (Status)) { break; } /* * Since the operands will be passed to another control method, * we must resolve all local references here (Local variables, * arguments to *this* method, etc.) */ Status = AcpiDsResolveOperands (WalkState); if (ACPI_FAILURE (Status)) { /* On error, clear all resolved operands */ AcpiDsClearOperands (WalkState); break; } /* * Tell the walk loop to preempt this running method and * execute the new method */ Status = AE_CTRL_TRANSFER; /* * Return now; we don't want to disturb anything, * especially the operand count! */ return_ACPI_STATUS (Status); case AML_TYPE_CREATE_FIELD: ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Executing CreateField Buffer/Index Op=%p\n", Op)); Status = AcpiDsLoad2EndOp (WalkState); if (ACPI_FAILURE (Status)) { break; } Status = AcpiDsEvalBufferFieldOperands (WalkState, Op); break; case AML_TYPE_CREATE_OBJECT: ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Executing CreateObject (Buffer/Package) Op=%p\n", Op)); switch (Op->Common.Parent->Common.AmlOpcode) { case AML_NAME_OP: /* * Put the Node on the object stack (Contains the ACPI Name * of this object) */ WalkState->Operands[0] = (void *) Op->Common.Parent->Common.Node; WalkState->NumOperands = 1; Status = AcpiDsCreateNode (WalkState, Op->Common.Parent->Common.Node, Op->Common.Parent); if (ACPI_FAILURE (Status)) { break; } /* Fall through */ /*lint -fallthrough */ case AML_INT_EVAL_SUBTREE_OP: Status = AcpiDsEvalDataObjectOperands (WalkState, Op, AcpiNsGetAttachedObject (Op->Common.Parent->Common.Node)); break; default: Status = AcpiDsEvalDataObjectOperands (WalkState, Op, NULL); break; } /* * If a result object was returned from above, push it on the * current result stack */ if (WalkState->ResultObj) { Status = AcpiDsResultPush (WalkState->ResultObj, WalkState); } break; case AML_TYPE_NAMED_FIELD: case AML_TYPE_NAMED_COMPLEX: case AML_TYPE_NAMED_SIMPLE: case AML_TYPE_NAMED_NO_OBJ: Status = AcpiDsLoad2EndOp (WalkState); if (ACPI_FAILURE (Status)) { break; } if (Op->Common.AmlOpcode == AML_REGION_OP) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Executing OpRegion Address/Length Op=%p\n", Op)); Status = AcpiDsEvalRegionOperands (WalkState, Op); if (ACPI_FAILURE (Status)) { break; } } else if (Op->Common.AmlOpcode == AML_DATA_REGION_OP) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Executing DataTableRegion Strings Op=%p\n", Op)); Status = AcpiDsEvalTableRegionOperands (WalkState, Op); if (ACPI_FAILURE (Status)) { break; } } else if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Executing BankField Op=%p\n", Op)); Status = AcpiDsEvalBankFieldOperands (WalkState, Op); if (ACPI_FAILURE (Status)) { break; } } break; case AML_TYPE_UNDEFINED: ACPI_ERROR ((AE_INFO, "Undefined opcode type Op=%p", Op)); return_ACPI_STATUS (AE_NOT_IMPLEMENTED); case AML_TYPE_BOGUS: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Internal opcode=%X type Op=%p\n", WalkState->Opcode, Op)); break; default: ACPI_ERROR ((AE_INFO, "Unimplemented opcode, class=0x%X " "type=0x%X Opcode=0x%X Op=%p", OpClass, OpType, Op->Common.AmlOpcode, Op)); Status = AE_NOT_IMPLEMENTED; break; } } /* * ACPI 2.0 support for 64-bit integers: Truncate numeric * result value if we are executing from a 32-bit ACPI table */ (void) AcpiExTruncateFor32bitTable (WalkState->ResultObj); /* * Check if we just completed the evaluation of a * conditional predicate */ if ((ACPI_SUCCESS (Status)) && (WalkState->ControlState) && (WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) && (WalkState->ControlState->Control.PredicateOp == Op)) { Status = AcpiDsGetPredicateValue (WalkState, WalkState->ResultObj); WalkState->ResultObj = NULL; } Cleanup: if (WalkState->ResultObj) { /* Break to debugger to display result */ AcpiDbDisplayResultObject (WalkState->ResultObj,WalkState); /* * Delete the result op if and only if: * Parent will not use the result -- such as any * non-nested type2 op in a method (parent will be method) */ AcpiDsDeleteResultIfNotUsed (Op, WalkState->ResultObj, WalkState); } #ifdef _UNDER_DEVELOPMENT if (WalkState->ParserState.Aml == WalkState->ParserState.AmlEnd) { AcpiDbMethodEnd (WalkState); } #endif /* Invoke exception handler on error */ if (ACPI_FAILURE (Status)) { Status = AcpiDsMethodError (Status, WalkState); } /* Always clear the object stack */ WalkState->NumOperands = 0; return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiUtCopySimpleObject ( ACPI_OPERAND_OBJECT *SourceDesc, ACPI_OPERAND_OBJECT *DestDesc) { UINT16 ReferenceCount; ACPI_OPERAND_OBJECT *NextObject; /* Save fields from destination that we don't want to overwrite */ ReferenceCount = DestDesc->Common.ReferenceCount; NextObject = DestDesc->Common.NextObject; /* Copy the entire source object over the destination object*/ ACPI_MEMCPY ((char *) DestDesc, (char *) SourceDesc, sizeof (ACPI_OPERAND_OBJECT)); /* Restore the saved fields */ DestDesc->Common.ReferenceCount = ReferenceCount; DestDesc->Common.NextObject = NextObject; /* New object is not static, regardless of source */ DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER; /* Handle the objects with extra data */ switch (ACPI_GET_OBJECT_TYPE (DestDesc)) { case ACPI_TYPE_BUFFER: /* * Allocate and copy the actual buffer if and only if: * 1) There is a valid buffer pointer * 2) The buffer has a length > 0 */ if ((SourceDesc->Buffer.Pointer) && (SourceDesc->Buffer.Length)) { DestDesc->Buffer.Pointer = ACPI_ALLOCATE (SourceDesc->Buffer.Length); if (!DestDesc->Buffer.Pointer) { return (AE_NO_MEMORY); } /* Copy the actual buffer data */ ACPI_MEMCPY (DestDesc->Buffer.Pointer, SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length); } break; case ACPI_TYPE_STRING: /* * Allocate and copy the actual string if and only if: * 1) There is a valid string pointer * (Pointer to a NULL string is allowed) */ if (SourceDesc->String.Pointer) { DestDesc->String.Pointer = ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1); if (!DestDesc->String.Pointer) { return (AE_NO_MEMORY); } /* Copy the actual string data */ ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer, (ACPI_SIZE) SourceDesc->String.Length + 1); } break; case ACPI_TYPE_LOCAL_REFERENCE: /* * We copied the reference object, so we now must add a reference * to the object pointed to by the reference * * DDBHandle reference (from Load/LoadTable is a special reference, * it's Reference.Object is the table index, so does not need to * increase the reference count */ if (SourceDesc->Reference.Opcode == AML_LOAD_OP) { break; } AcpiUtAddReference (SourceDesc->Reference.Object); break; case ACPI_TYPE_REGION: /* * We copied the Region Handler, so we now must add a reference */ if (DestDesc->Region.Handler) { AcpiUtAddReference (DestDesc->Region.Handler); } break; default: /* Nothing to do for other simple objects */ break; } 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 AcpiExOpcode_1A_0T_1R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_OPERAND_OBJECT *TempDesc; ACPI_OPERAND_OBJECT *ReturnDesc = NULL; ACPI_STATUS Status = AE_OK; UINT32 Type; UINT64 Value; ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_1R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Examine the AML opcode */ switch (WalkState->Opcode) { case AML_LNOT_OP: /* LNot (Operand) */ ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) 0); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* * Set result to ONES (TRUE) if Value == 0. Note: * ReturnDesc->Integer.Value is initially == 0 (FALSE) from above. */ if (!Operand[0]->Integer.Value) { ReturnDesc->Integer.Value = ACPI_UINT64_MAX; } break; case AML_DECREMENT_OP: /* Decrement (Operand) */ case AML_INCREMENT_OP: /* Increment (Operand) */ /* * Create a new integer. Can't just get the base integer and * increment it because it may be an Arg or Field. */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* * Since we are expecting a Reference operand, it can be either a * NS Node or an internal object. */ TempDesc = Operand[0]; if (ACPI_GET_DESCRIPTOR_TYPE (TempDesc) == ACPI_DESC_TYPE_OPERAND) { /* Internal reference object - prevent deletion */ AcpiUtAddReference (TempDesc); } /* * Convert the Reference operand to an Integer (This removes a * reference on the Operand[0] object) * * NOTE: We use LNOT_OP here in order to force resolution of the * reference operand to an actual integer. */ Status = AcpiExResolveOperands (AML_LNOT_OP, &TempDesc, WalkState); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While resolving operands for [%s]", AcpiPsGetOpcodeName (WalkState->Opcode))); goto Cleanup; } /* * TempDesc is now guaranteed to be an Integer object -- * Perform the actual increment or decrement */ if (WalkState->Opcode == AML_INCREMENT_OP) { ReturnDesc->Integer.Value = TempDesc->Integer.Value + 1; } else { ReturnDesc->Integer.Value = TempDesc->Integer.Value - 1; } /* Finished with this Integer object */ AcpiUtRemoveReference (TempDesc); /* * Store the result back (indirectly) through the original * Reference object */ Status = AcpiExStore (ReturnDesc, Operand[0], WalkState); break; case AML_OBJECT_TYPE_OP: /* ObjectType (SourceObject) */ /* * Note: The operand is not resolved at this point because we want to * get the associated object, not its value. For example, we don't * want to resolve a FieldUnit to its value, we want the actual * FieldUnit object. */ /* Get the type of the base object */ Status = AcpiExResolveMultiple (WalkState, Operand[0], &Type, NULL); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Allocate a descriptor to hold the type. */ ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) Type); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } break; case AML_SIZE_OF_OP: /* SizeOf (SourceObject) */ /* * Note: The operand is not resolved at this point because we want to * get the associated object, not its value. */ /* Get the base object */ Status = AcpiExResolveMultiple ( WalkState, Operand[0], &Type, &TempDesc); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* * The type of the base object must be integer, buffer, string, or * package. All others are not supported. * * NOTE: Integer is not specifically supported by the ACPI spec, * but is supported implicitly via implicit operand conversion. * rather than bother with conversion, we just use the byte width * global (4 or 8 bytes). */ switch (Type) { case ACPI_TYPE_INTEGER: Value = AcpiGbl_IntegerByteWidth; break; case ACPI_TYPE_STRING: Value = TempDesc->String.Length; break; case ACPI_TYPE_BUFFER: /* Buffer arguments may not be evaluated at this point */ Status = AcpiDsGetBufferArguments (TempDesc); Value = TempDesc->Buffer.Length; break; case ACPI_TYPE_PACKAGE: /* Package arguments may not be evaluated at this point */ Status = AcpiDsGetPackageArguments (TempDesc); Value = TempDesc->Package.Count; break; default: ACPI_ERROR ((AE_INFO, "Operand must be Buffer/Integer/String/Package" " - found type %s", AcpiUtGetTypeName (Type))); Status = AE_AML_OPERAND_TYPE; goto Cleanup; } if (ACPI_FAILURE (Status)) { goto Cleanup; } /* * Now that we have the size of the object, create a result * object to hold the value */ ReturnDesc = AcpiUtCreateIntegerObject (Value); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } break; case AML_REF_OF_OP: /* RefOf (SourceObject) */ Status = AcpiExGetObjectReference ( Operand[0], &ReturnDesc, WalkState); if (ACPI_FAILURE (Status)) { goto Cleanup; } break; case AML_DEREF_OF_OP: /* DerefOf (ObjReference | String) */ /* Check for a method local or argument, or standalone String */ if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) { TempDesc = AcpiNsGetAttachedObject ( (ACPI_NAMESPACE_NODE *) Operand[0]); if (TempDesc && ((TempDesc->Common.Type == ACPI_TYPE_STRING) || (TempDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE))) { Operand[0] = TempDesc; AcpiUtAddReference (TempDesc); } else { Status = AE_AML_OPERAND_TYPE; goto Cleanup; } } else { switch ((Operand[0])->Common.Type) { case ACPI_TYPE_LOCAL_REFERENCE: /* * This is a DerefOf (LocalX | ArgX) * * Must resolve/dereference the local/arg reference first */ switch (Operand[0]->Reference.Class) { case ACPI_REFCLASS_LOCAL: case ACPI_REFCLASS_ARG: /* Set Operand[0] to the value of the local/arg */ Status = AcpiDsMethodDataGetValue ( Operand[0]->Reference.Class, Operand[0]->Reference.Value, WalkState, &TempDesc); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* * Delete our reference to the input object and * point to the object just retrieved */ AcpiUtRemoveReference (Operand[0]); Operand[0] = TempDesc; break; case ACPI_REFCLASS_REFOF: /* Get the object to which the reference refers */ TempDesc = Operand[0]->Reference.Object; AcpiUtRemoveReference (Operand[0]); Operand[0] = TempDesc; break; default: /* Must be an Index op - handled below */ break; } break; case ACPI_TYPE_STRING: break; default: Status = AE_AML_OPERAND_TYPE; goto Cleanup; } } if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) != ACPI_DESC_TYPE_NAMED) { if ((Operand[0])->Common.Type == ACPI_TYPE_STRING) { /* * This is a DerefOf (String). The string is a reference * to a named ACPI object. * * 1) Find the owning Node * 2) Dereference the node to an actual object. Could be a * Field, so we need to resolve the node to a value. */ Status = AcpiNsGetNodeUnlocked (WalkState->ScopeInfo->Scope.Node, Operand[0]->String.Pointer, ACPI_NS_SEARCH_PARENT, ACPI_CAST_INDIRECT_PTR ( ACPI_NAMESPACE_NODE, &ReturnDesc)); if (ACPI_FAILURE (Status)) { goto Cleanup; } Status = AcpiExResolveNodeToValue ( ACPI_CAST_INDIRECT_PTR ( ACPI_NAMESPACE_NODE, &ReturnDesc), WalkState); goto Cleanup; } } /* Operand[0] may have changed from the code above */ if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) { /* * This is a DerefOf (ObjectReference) * Get the actual object from the Node (This is the dereference). * This case may only happen when a LocalX or ArgX is * dereferenced above. */ ReturnDesc = AcpiNsGetAttachedObject ( (ACPI_NAMESPACE_NODE *) Operand[0]); AcpiUtAddReference (ReturnDesc); } else { /* * This must be a reference object produced by either the * Index() or RefOf() operator */ switch (Operand[0]->Reference.Class) { case ACPI_REFCLASS_INDEX: /* * The target type for the Index operator must be * either a Buffer or a Package */ switch (Operand[0]->Reference.TargetType) { case ACPI_TYPE_BUFFER_FIELD: TempDesc = Operand[0]->Reference.Object; /* * Create a new object that contains one element of the * buffer -- the element pointed to by the index. * * NOTE: index into a buffer is NOT a pointer to a * sub-buffer of the main buffer, it is only a pointer to a * single element (byte) of the buffer! * * Since we are returning the value of the buffer at the * indexed location, we don't need to add an additional * reference to the buffer itself. */ ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) TempDesc->Buffer.Pointer[Operand[0]->Reference.Value]); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } break; case ACPI_TYPE_PACKAGE: /* * Return the referenced element of the package. We must * add another reference to the referenced object, however. */ ReturnDesc = *(Operand[0]->Reference.Where); if (!ReturnDesc) { /* * Element is NULL, do not allow the dereference. * This provides compatibility with other ACPI * implementations. */ return_ACPI_STATUS (AE_AML_UNINITIALIZED_ELEMENT); } AcpiUtAddReference (ReturnDesc); break; default: ACPI_ERROR ((AE_INFO, "Unknown Index TargetType 0x%X in reference object %p", Operand[0]->Reference.TargetType, Operand[0])); Status = AE_AML_OPERAND_TYPE; goto Cleanup; } break; case ACPI_REFCLASS_REFOF: ReturnDesc = Operand[0]->Reference.Object; if (ACPI_GET_DESCRIPTOR_TYPE (ReturnDesc) == ACPI_DESC_TYPE_NAMED) { ReturnDesc = AcpiNsGetAttachedObject ( (ACPI_NAMESPACE_NODE *) ReturnDesc); if (!ReturnDesc) { break; } /* * June 2013: * BufferFields/FieldUnits require additional resolution */ switch (ReturnDesc->Common.Type) { case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: Status = AcpiExReadDataFromField ( WalkState, ReturnDesc, &TempDesc); if (ACPI_FAILURE (Status)) { goto Cleanup; } ReturnDesc = TempDesc; break; default: /* Add another reference to the object */ AcpiUtAddReference (ReturnDesc); break; } } break; default: ACPI_ERROR ((AE_INFO, "Unknown class in reference(%p) - 0x%2.2X", Operand[0], Operand[0]->Reference.Class)); Status = AE_TYPE; goto Cleanup; } } break; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; goto Cleanup; } Cleanup: /* Delete return object on error */ if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ReturnDesc); } /* Save return object on success */ else { WalkState->ResultObj = ReturnDesc; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiPsxExecute ( ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT **Params, ACPI_OPERAND_OBJECT **ReturnObjDesc) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; UINT32 i; ACPI_PARSE_OBJECT *Op; ACPI_WALK_STATE *WalkState; ACPI_FUNCTION_TRACE ("PsxExecute"); /* Validate the Node and get the attached object */ if (!MethodNode) { return_ACPI_STATUS (AE_NULL_ENTRY); } ObjDesc = AcpiNsGetAttachedObject (MethodNode); if (!ObjDesc) { return_ACPI_STATUS (AE_NULL_OBJECT); } /* Init for new method, wait on concurrency semaphore */ Status = AcpiDsBeginMethodExecution (MethodNode, ObjDesc, NULL); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (Params) { /* * The caller "owns" the parameters, so give each one an extra * reference */ for (i = 0; Params[i]; i++) { AcpiUtAddReference (Params[i]); } } /* * 1) Perform the first pass parse of the method to enter any * named objects that it creates into the namespace */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Begin Method Parse **** Entry=%p obj=%p\n", MethodNode, ObjDesc)); /* Create and init a Root Node */ Op = AcpiPsCreateScopeOp (); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); } /* * Get a new OwnerId for objects created by this method. Namespace * objects (such as Operation Regions) can be created during the * first pass parse. */ ObjDesc->Method.OwningId = AcpiUtAllocateOwnerId (ACPI_OWNER_TYPE_METHOD); /* Create and initialize a new walk state */ WalkState = AcpiDsCreateWalkState (ObjDesc->Method.OwningId, NULL, NULL, NULL); if (!WalkState) { return_ACPI_STATUS (AE_NO_MEMORY); } Status = AcpiDsInitAmlWalk (WalkState, Op, MethodNode, ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, NULL, NULL, 1); if (ACPI_FAILURE (Status)) { AcpiDsDeleteWalkState (WalkState); return_ACPI_STATUS (Status); } /* Parse the AML */ Status = AcpiPsParseAml (WalkState); AcpiPsDeleteParseTree (Op); /* * 2) Execute the method. Performs second pass parse simultaneously */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Begin Method Execution **** Entry=%p obj=%p\n", MethodNode, ObjDesc)); /* Create and init a Root Node */ Op = AcpiPsCreateScopeOp (); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Init new op with the method name and pointer back to the NS node */ AcpiPsSetName (Op, MethodNode->Name.Integer); Op->Common.Node = MethodNode; /* Create and initialize a new walk state */ WalkState = AcpiDsCreateWalkState (TABLE_ID_DSDT, NULL, NULL, NULL); if (!WalkState) { return_ACPI_STATUS (AE_NO_MEMORY); } Status = AcpiDsInitAmlWalk (WalkState, Op, MethodNode, ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, Params, ReturnObjDesc, 3); if (ACPI_FAILURE (Status)) { AcpiDsDeleteWalkState (WalkState); return_ACPI_STATUS (Status); } /* * The walk of the parse tree is where we actually execute the method */ Status = AcpiPsParseAml (WalkState); AcpiPsDeleteParseTree (Op); if (Params) { /* Take away the extra reference that we gave the parameters above */ for (i = 0; Params[i]; i++) { /* Ignore errors, just do them all */ (void) AcpiUtUpdateObjectReference (Params[i], REF_DECREMENT); } } /* * If the method has returned an object, signal this to the caller with * a control exception code */ if (*ReturnObjDesc) { ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n", *ReturnObjDesc)); ACPI_DUMP_STACK_ENTRY (*ReturnObjDesc); Status = AE_CTRL_RETURN_VALUE; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiDsMethodDataGetValue ( UINT16 Opcode, UINT32 Index, ACPI_WALK_STATE *WalkState, ACPI_OPERAND_OBJECT **DestDesc) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT **Entry; ACPI_OPERAND_OBJECT *Object; FUNCTION_TRACE ("DsMethodDataGetValue"); /* Validate the object descriptor */ if (!DestDesc) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null object descriptor pointer\n")); return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Get a pointer to the requested method stack entry */ Status = AcpiDsMethodDataGetEntry (Opcode, Index, WalkState, &Entry); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Get the object from the method stack */ Object = *Entry; /* Examine the returned object, it must be valid. */ if (!Object) { /* * Index points to uninitialized object stack value. * This means that either 1) The expected argument was * not passed to the method, or 2) A local variable * was referenced by the method (via the ASL) * before it was initialized. Either case is an error. */ switch (Opcode) { case AML_ARG_OP: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Arg[%d] at entry %p\n", Index, Entry)); return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG); break; case AML_LOCAL_OP: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Local[%d] at entry %p\n", Index, Entry)); return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL); break; } } /* * Index points to initialized and valid object stack value. * Return an additional reference to the object */ *DestDesc = Object; AcpiUtAddReference (Object); return_ACPI_STATUS (AE_OK); }
static ACPI_STATUS AcpiExResolveObjectToValue ( ACPI_OPERAND_OBJECT **StackPtr, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT *StackDesc; ACPI_OPERAND_OBJECT *ObjDesc = NULL; UINT8 RefType; ACPI_FUNCTION_TRACE (ExResolveObjectToValue); StackDesc = *StackPtr; /* This is an object of type ACPI_OPERAND_OBJECT */ switch (StackDesc->Common.Type) { case ACPI_TYPE_LOCAL_REFERENCE: RefType = StackDesc->Reference.Class; switch (RefType) { case ACPI_REFCLASS_LOCAL: case ACPI_REFCLASS_ARG: /* * Get the local from the method's state info * Note: this increments the local's object reference count */ Status = AcpiDsMethodDataGetValue (RefType, StackDesc->Reference.Value, WalkState, &ObjDesc); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] ValueObj is %p\n", StackDesc->Reference.Value, ObjDesc)); /* * Now we can delete the original Reference Object and * replace it with the resolved value */ AcpiUtRemoveReference (StackDesc); *StackPtr = ObjDesc; break; case ACPI_REFCLASS_INDEX: switch (StackDesc->Reference.TargetType) { case ACPI_TYPE_BUFFER_FIELD: /* Just return - do not dereference */ break; case ACPI_TYPE_PACKAGE: /* If method call or CopyObject - do not dereference */ if ((WalkState->Opcode == AML_INT_METHODCALL_OP) || (WalkState->Opcode == AML_COPY_OBJECT_OP)) { break; } /* Otherwise, dereference the PackageIndex to a package element */ ObjDesc = *StackDesc->Reference.Where; if (ObjDesc) { /* * Valid object descriptor, copy pointer to return value * (i.e., dereference the package index) * Delete the ref object, increment the returned object */ AcpiUtAddReference (ObjDesc); *StackPtr = ObjDesc; } else { /* * A NULL object descriptor means an uninitialized element of * the package, can't dereference it */ ACPI_ERROR ((AE_INFO, "Attempt to dereference an Index to " "NULL package element Idx=%p", StackDesc)); Status = AE_AML_UNINITIALIZED_ELEMENT; } break; default: /* Invalid reference object */ ACPI_ERROR ((AE_INFO, "Unknown TargetType 0x%X in Index/Reference object %p", StackDesc->Reference.TargetType, StackDesc)); Status = AE_AML_INTERNAL; break; } break; case ACPI_REFCLASS_REFOF: case ACPI_REFCLASS_DEBUG: case ACPI_REFCLASS_TABLE: /* Just leave the object as-is, do not dereference */ break; case ACPI_REFCLASS_NAME: /* Reference to a named object */ /* Dereference the name */ if ((StackDesc->Reference.Node->Type == ACPI_TYPE_DEVICE) || (StackDesc->Reference.Node->Type == ACPI_TYPE_THERMAL)) { /* These node types do not have 'real' subobjects */ *StackPtr = (void *) StackDesc->Reference.Node; } else { /* Get the object pointed to by the namespace node */ *StackPtr = (StackDesc->Reference.Node)->Object; AcpiUtAddReference (*StackPtr); } AcpiUtRemoveReference (StackDesc); break; default: ACPI_ERROR ((AE_INFO, "Unknown Reference type 0x%X in %p", RefType, StackDesc)); Status = AE_AML_INTERNAL; break; } break; case ACPI_TYPE_BUFFER: Status = AcpiDsGetBufferArguments (StackDesc); break; case ACPI_TYPE_PACKAGE: Status = AcpiDsGetPackageArguments (StackDesc); 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 SourceDesc=%p Type=%X\n", StackDesc, StackDesc->Common.Type)); Status = AcpiExReadDataFromField (WalkState, StackDesc, &ObjDesc); /* Remove a reference to the original operand, then override */ AcpiUtRemoveReference (*StackPtr); *StackPtr = (void *) ObjDesc; break; default: break; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExOpcode_2A_1T_1R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_OPERAND_OBJECT *ReturnDesc = NULL; UINT64 Index; ACPI_STATUS Status = AE_OK; ACPI_SIZE Length = 0; ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_1T_1R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Execute the opcode */ if (WalkState->OpInfo->Flags & AML_MATH) { /* All simple math opcodes (add, etc.) */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } ReturnDesc->Integer.Value = AcpiExDoMathOp (WalkState->Opcode, Operand[0]->Integer.Value, Operand[1]->Integer.Value); goto StoreResultToTarget; } switch (WalkState->Opcode) { case AML_MOD_OP: /* Mod (Dividend, Divisor, RemainderResult (ACPI 2.0) */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* ReturnDesc will contain the remainder */ Status = AcpiUtDivide (Operand[0]->Integer.Value, Operand[1]->Integer.Value, NULL, &ReturnDesc->Integer.Value); break; case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */ Status = AcpiExDoConcatenate (Operand[0], Operand[1], &ReturnDesc, WalkState); break; case AML_TO_STRING_OP: /* ToString (Buffer, Length, Result) (ACPI 2.0) */ /* * Input object is guaranteed to be a buffer at this point (it may have * been converted.) Copy the raw buffer data to a new object of * type String. */ /* * Get the length of the new string. It is the smallest of: * 1) Length of the input buffer * 2) Max length as specified in the ToString operator * 3) Length of input buffer up to a zero byte (null terminator) * * NOTE: A length of zero is ok, and will create a zero-length, null * terminated string. */ while ((Length < Operand[0]->Buffer.Length) && (Length < Operand[1]->Integer.Value) && (Operand[0]->Buffer.Pointer[Length])) { Length++; } /* Allocate a new string object */ ReturnDesc = AcpiUtCreateStringObject (Length); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* * Copy the raw buffer data with no transform. * (NULL terminated already) */ ACPI_MEMCPY (ReturnDesc->String.Pointer, Operand[0]->Buffer.Pointer, Length); break; case AML_CONCAT_RES_OP: /* ConcatenateResTemplate (Buffer, Buffer, Result) (ACPI 2.0) */ Status = AcpiExConcatTemplate (Operand[0], Operand[1], &ReturnDesc, WalkState); break; case AML_INDEX_OP: /* Index (Source Index Result) */ /* Create the internal return object */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* Initialize the Index reference object */ Index = Operand[1]->Integer.Value; ReturnDesc->Reference.Value = (UINT32) Index; ReturnDesc->Reference.Class = ACPI_REFCLASS_INDEX; /* * At this point, the Source operand is a String, Buffer, or Package. * Verify that the index is within range. */ switch ((Operand[0])->Common.Type) { case ACPI_TYPE_STRING: if (Index >= Operand[0]->String.Length) { Length = Operand[0]->String.Length; Status = AE_AML_STRING_LIMIT; } ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; break; case ACPI_TYPE_BUFFER: if (Index >= Operand[0]->Buffer.Length) { Length = Operand[0]->Buffer.Length; Status = AE_AML_BUFFER_LIMIT; } ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; break; case ACPI_TYPE_PACKAGE: if (Index >= Operand[0]->Package.Count) { Length = Operand[0]->Package.Count; Status = AE_AML_PACKAGE_LIMIT; } ReturnDesc->Reference.TargetType = ACPI_TYPE_PACKAGE; ReturnDesc->Reference.Where = &Operand[0]->Package.Elements [Index]; break; default: Status = AE_AML_INTERNAL; goto Cleanup; } /* Failure means that the Index was beyond the end of the object */ if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Index (0x%X%8.8X) is beyond end of object (length 0x%X)", ACPI_FORMAT_UINT64 (Index), (UINT32) Length)); goto Cleanup; } /* * Save the target object and add a reference to it for the life * of the index */ ReturnDesc->Reference.Object = Operand[0]; AcpiUtAddReference (Operand[0]); /* Store the reference to the Target */ Status = AcpiExStore (ReturnDesc, Operand[2], WalkState); /* Return the reference */ WalkState->ResultObj = ReturnDesc; goto Cleanup; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; break; } StoreResultToTarget: if (ACPI_SUCCESS (Status)) { /* * Store the result of the operation (which is now in ReturnDesc) into * the Target descriptor. */ Status = AcpiExStore (ReturnDesc, Operand[2], WalkState); if (ACPI_FAILURE (Status)) { goto Cleanup; } if (!WalkState->ResultObj) { WalkState->ResultObj = ReturnDesc; } } Cleanup: /* Delete return object on error */ if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ReturnDesc); WalkState->ResultObj = 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 AcpiUtCopySimpleObject ( ACPI_OPERAND_OBJECT *SourceDesc, ACPI_OPERAND_OBJECT *DestDesc) { UINT16 ReferenceCount; ACPI_OPERAND_OBJECT *NextObject; ACPI_STATUS Status; ACPI_SIZE CopySize; /* Save fields from destination that we don't want to overwrite */ ReferenceCount = DestDesc->Common.ReferenceCount; NextObject = DestDesc->Common.NextObject; /* * Copy the entire source object over the destination object. * Note: Source can be either an operand object or namespace node. */ CopySize = sizeof (ACPI_OPERAND_OBJECT); if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED) { CopySize = sizeof (ACPI_NAMESPACE_NODE); } ACPI_MEMCPY (ACPI_CAST_PTR (char, DestDesc), ACPI_CAST_PTR (char, SourceDesc), CopySize); /* Restore the saved fields */ DestDesc->Common.ReferenceCount = ReferenceCount; DestDesc->Common.NextObject = NextObject; /* New object is not static, regardless of source */ DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER; /* Handle the objects with extra data */ switch (DestDesc->Common.Type) { case ACPI_TYPE_BUFFER: /* * Allocate and copy the actual buffer if and only if: * 1) There is a valid buffer pointer * 2) The buffer has a length > 0 */ if ((SourceDesc->Buffer.Pointer) && (SourceDesc->Buffer.Length)) { DestDesc->Buffer.Pointer = ACPI_ALLOCATE (SourceDesc->Buffer.Length); if (!DestDesc->Buffer.Pointer) { return (AE_NO_MEMORY); } /* Copy the actual buffer data */ ACPI_MEMCPY (DestDesc->Buffer.Pointer, SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length); } break; case ACPI_TYPE_STRING: /* * Allocate and copy the actual string if and only if: * 1) There is a valid string pointer * (Pointer to a NULL string is allowed) */ if (SourceDesc->String.Pointer) { DestDesc->String.Pointer = ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1); if (!DestDesc->String.Pointer) { return (AE_NO_MEMORY); } /* Copy the actual string data */ ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer, (ACPI_SIZE) SourceDesc->String.Length + 1); } break; case ACPI_TYPE_LOCAL_REFERENCE: /* * We copied the reference object, so we now must add a reference * to the object pointed to by the reference * * DDBHandle reference (from Load/LoadTable) is a special reference, * it does not have a Reference.Object, so does not need to * increase the reference count */ if (SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE) { break; } AcpiUtAddReference (SourceDesc->Reference.Object); break; case ACPI_TYPE_REGION: /* * We copied the Region Handler, so we now must add a reference */ if (DestDesc->Region.Handler) { AcpiUtAddReference (DestDesc->Region.Handler); } break; /* * For Mutex and Event objects, we cannot simply copy the underlying * OS object. We must create a new one. */ case ACPI_TYPE_MUTEX: Status = AcpiOsCreateMutex (&DestDesc->Mutex.OsMutex); if (ACPI_FAILURE (Status)) { return (Status); } break; case ACPI_TYPE_EVENT: Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0, &DestDesc->Event.OsSemaphore); if (ACPI_FAILURE (Status)) { return (Status); } break; default: /* Nothing to do for other simple objects */ break; } return (AE_OK); }
ACPI_STATUS AcpiDsMethodDataGetValue ( UINT8 Type, UINT32 Index, ACPI_WALK_STATE *WalkState, ACPI_OPERAND_OBJECT **DestDesc) { ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; ACPI_OPERAND_OBJECT *Object; ACPI_FUNCTION_TRACE (DsMethodDataGetValue); /* Validate the object descriptor */ if (!DestDesc) { ACPI_ERROR ((AE_INFO, "Null object descriptor pointer")); return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Get the namespace node for the arg/local */ Status = AcpiDsMethodDataGetNode (Type, Index, WalkState, &Node); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Get the object from the node */ Object = Node->Object; /* Examine the returned object, it must be valid. */ if (!Object) { /* * Index points to uninitialized object. * This means that either 1) The expected argument was * not passed to the method, or 2) A local variable * was referenced by the method (via the ASL) * before it was initialized. Either case is an error. */ /* If slack enabled, init the LocalX/ArgX to an Integer of value zero */ if (AcpiGbl_EnableInterpreterSlack) { Object = AcpiUtCreateIntegerObject ((UINT64) 0); if (!Object) { return_ACPI_STATUS (AE_NO_MEMORY); } Node->Object = Object; } /* Otherwise, return the error */ else switch (Type) { case ACPI_REFCLASS_ARG: ACPI_ERROR ((AE_INFO, "Uninitialized Arg[%u] at node %p", Index, Node)); return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG); case ACPI_REFCLASS_LOCAL: /* * No error message for this case, will be trapped again later to * detect and ignore cases of Store(LocalX,LocalX) */ return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL); default: ACPI_ERROR ((AE_INFO, "Not a Arg/Local opcode: 0x%X", Type)); return_ACPI_STATUS (AE_AML_INTERNAL); } } /* * The Index points to an initialized and valid object. * Return an additional reference to the object */ *DestDesc = Object; AcpiUtAddReference (Object); return_ACPI_STATUS (AE_OK); }
static ACPI_STATUS AcpiDsBuildInternalObject ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op, ACPI_OPERAND_OBJECT **ObjDescPtr) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_STATUS Status; ACPI_OBJECT_TYPE Type; ACPI_FUNCTION_TRACE (DsBuildInternalObject); *ObjDescPtr = NULL; if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) { /* * This is a named object reference. If this name was * previously looked up in the namespace, it was stored in this op. * Otherwise, go ahead and look it up now */ if (!Op->Common.Node) { Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Common.Value.String, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &(Op->Common.Node))); if (ACPI_FAILURE (Status)) { /* Check if we are resolving a named reference within a package */ if ((Status == AE_NOT_FOUND) && (AcpiGbl_EnableInterpreterSlack) && ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))) { /* * We didn't find the target and we are populating elements * of a package - ignore if slack enabled. Some ASL code * contains dangling invalid references in packages and * expects that no exception will be issued. Leave the * element as a null element. It cannot be used, but it * can be overwritten by subsequent ASL code - this is * typically the case. */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Ignoring unresolved reference in package [%4.4s]\n", WalkState->ScopeInfo->Scope.Node->Name.Ascii)); return_ACPI_STATUS (AE_OK); } else { ACPI_ERROR_NAMESPACE (Op->Common.Value.String, Status); } return_ACPI_STATUS (Status); } } /* Special object resolution for elements of a package */ if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) { /* * Attempt to resolve the node to a value before we insert it into * the package. If this is a reference to a common data type, * resolve it immediately. According to the ACPI spec, package * elements can only be "data objects" or method references. * Attempt to resolve to an Integer, Buffer, String or Package. * If cannot, return the named reference (for things like Devices, * Methods, etc.) Buffer Fields and Fields will resolve to simple * objects (int/buf/str/pkg). * * NOTE: References to things like Devices, Methods, Mutexes, etc. * will remain as named references. This behavior is not described * in the ACPI spec, but it appears to be an oversight. */ ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Op->Common.Node); Status = AcpiExResolveNodeToValue ( ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc), WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Special handling for Alias objects. We need to setup the type * and the Op->Common.Node to point to the Alias target. Note, * Alias has at most one level of indirection internally. */ Type = Op->Common.Node->Type; if (Type == ACPI_TYPE_LOCAL_ALIAS) { Type = ObjDesc->Common.Type; Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Op->Common.Node->Object); } switch (Type) { /* * For these types, we need the actual node, not the subobject. * However, the subobject did not get an extra reference count above. * * TBD: should ExResolveNodeToValue be changed to fix this? */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_THERMAL: AcpiUtAddReference (Op->Common.Node->Object); /*lint -fallthrough */ /* * For these types, we need the actual node, not the subobject. * The subobject got an extra reference count in ExResolveNodeToValue. */ case ACPI_TYPE_MUTEX: case ACPI_TYPE_METHOD: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_EVENT: case ACPI_TYPE_REGION: /* We will create a reference object for these types below */ break; default: /* * All other types - the node was resolved to an actual * object, we are done. */ goto Exit; } } } /* Create and init a new internal ACPI object */ ObjDesc = AcpiUtCreateInternalObject ( (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } Status = AcpiDsInitObjectFromOp (WalkState, Op, Op->Common.AmlOpcode, &ObjDesc); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); return_ACPI_STATUS (Status); } Exit: *ObjDescPtr = ObjDesc; 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 AcpiExResolveObjectToValue ( ACPI_OPERAND_OBJECT **StackPtr, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT *StackDesc; void *TempNode; ACPI_OPERAND_OBJECT *ObjDesc; UINT16 Opcode; FUNCTION_TRACE ("ExResolveObjectToValue"); StackDesc = *StackPtr; /* This is an ACPI_OPERAND_OBJECT */ switch (StackDesc->Common.Type) { case INTERNAL_TYPE_REFERENCE: Opcode = StackDesc->Reference.Opcode; switch (Opcode) { case AML_NAME_OP: /* * Convert indirect name ptr to a direct name ptr. * Then, AcpiExResolveNodeToValue can be used to get the value */ TempNode = StackDesc->Reference.Object; /* Delete the Reference Object */ AcpiUtRemoveReference (StackDesc); /* Put direct name pointer onto stack and exit */ (*StackPtr) = TempNode; break; case AML_LOCAL_OP: case AML_ARG_OP: /* * Get the local from the method's state info * Note: this increments the local's object reference count */ Status = AcpiDsMethodDataGetValue (Opcode, StackDesc->Reference.Offset, WalkState, &ObjDesc); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Now we can delete the original Reference Object and * replace it with the resolve value */ AcpiUtRemoveReference (StackDesc); *StackPtr = ObjDesc; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "[Arg/Local %d] ValueObj is %p\n", StackDesc->Reference.Offset, ObjDesc)); break; /* * TBD: [Restructure] These next three opcodes change the type of * the object, which is actually a no-no. */ case AML_ZERO_OP: StackDesc->Common.Type = (UINT8) ACPI_TYPE_INTEGER; StackDesc->Integer.Value = 0; break; case AML_ONE_OP: StackDesc->Common.Type = (UINT8) ACPI_TYPE_INTEGER; StackDesc->Integer.Value = 1; break; case AML_ONES_OP: StackDesc->Common.Type = (UINT8) ACPI_TYPE_INTEGER; StackDesc->Integer.Value = ACPI_INTEGER_MAX; /* Truncate value if we are executing from a 32-bit ACPI table */ AcpiExTruncateFor32bitTable (StackDesc, WalkState); break; case AML_INDEX_OP: switch (StackDesc->Reference.TargetType) { case ACPI_TYPE_BUFFER_FIELD: /* Just return - leave the Reference on the stack */ break; case ACPI_TYPE_PACKAGE: ObjDesc = *StackDesc->Reference.Where; if (ObjDesc) { /* * Valid obj descriptor, copy pointer to return value * (i.e., dereference the package index) * Delete the ref object, increment the returned object */ AcpiUtRemoveReference (StackDesc); AcpiUtAddReference (ObjDesc); *StackPtr = ObjDesc; } else { /* * A NULL object descriptor means an unitialized element of * the package, can't dereference it */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Attempt to deref an Index to NULL pkg element Idx=%p\n", StackDesc)); Status = AE_AML_UNINITIALIZED_ELEMENT; } break; default: /* Invalid reference object */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown TargetType %X in Index/Reference obj %p\n", StackDesc->Reference.TargetType, StackDesc)); Status = AE_AML_INTERNAL; break; } break; case AML_DEBUG_OP: /* Just leave the object as-is */ break; default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Reference object subtype %02X in %p\n", Opcode, StackDesc)); Status = AE_AML_INTERNAL; break; } /* switch (Opcode) */ break; /* case INTERNAL_TYPE_REFERENCE */ case ACPI_TYPE_BUFFER_FIELD: ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_ANY); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } Status = AcpiExGetBufferFieldValue (StackDesc, ObjDesc); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); ObjDesc = NULL; } *StackPtr = (void *) ObjDesc; break; case INTERNAL_TYPE_BANK_FIELD: ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_ANY); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* TBD: WRONG! */ Status = AcpiExGetBufferFieldValue (StackDesc, ObjDesc); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); ObjDesc = NULL; } *StackPtr = (void *) ObjDesc; break; /* TBD: [Future] - may need to handle IndexField, and DefField someday */ default: break; } /* switch (StackDesc->Common.Type) */ return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExOpcode_1A_1T_1R ( ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_OPERAND_OBJECT *ReturnDesc = NULL; ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL; UINT32 Temp32; UINT32 i; UINT64 PowerOfTen; UINT64 Digit; ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_1R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Examine the AML opcode */ switch (WalkState->Opcode) { case AML_BIT_NOT_OP: case AML_FIND_SET_LEFT_BIT_OP: case AML_FIND_SET_RIGHT_BIT_OP: case AML_FROM_BCD_OP: case AML_TO_BCD_OP: case AML_COND_REF_OF_OP: /* Create a return object of type Integer for these opcodes */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } switch (WalkState->Opcode) { case AML_BIT_NOT_OP: /* Not (Operand, Result) */ ReturnDesc->Integer.Value = ~Operand[0]->Integer.Value; break; case AML_FIND_SET_LEFT_BIT_OP: /* FindSetLeftBit (Operand, Result) */ ReturnDesc->Integer.Value = Operand[0]->Integer.Value; /* * Acpi specification describes Integer type as a little * endian unsigned value, so this boundary condition is valid. */ for (Temp32 = 0; ReturnDesc->Integer.Value && Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32) { ReturnDesc->Integer.Value >>= 1; } ReturnDesc->Integer.Value = Temp32; break; case AML_FIND_SET_RIGHT_BIT_OP: /* FindSetRightBit (Operand, Result) */ ReturnDesc->Integer.Value = Operand[0]->Integer.Value; /* * The Acpi specification describes Integer type as a little * endian unsigned value, so this boundary condition is valid. */ for (Temp32 = 0; ReturnDesc->Integer.Value && Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32) { ReturnDesc->Integer.Value <<= 1; } /* Since the bit position is one-based, subtract from 33 (65) */ ReturnDesc->Integer.Value = Temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - Temp32; break; case AML_FROM_BCD_OP: /* FromBcd (BCDValue, Result) */ /* * The 64-bit ACPI integer can hold 16 4-bit BCD characters * (if table is 32-bit, integer can hold 8 BCD characters) * Convert each 4-bit BCD value */ PowerOfTen = 1; ReturnDesc->Integer.Value = 0; Digit = Operand[0]->Integer.Value; /* Convert each BCD digit (each is one nybble wide) */ for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++) { /* Get the least significant 4-bit BCD digit */ Temp32 = ((UINT32) Digit) & 0xF; /* Check the range of the digit */ if (Temp32 > 9) { ACPI_ERROR ((AE_INFO, "BCD digit too large (not decimal): 0x%X", Temp32)); Status = AE_AML_NUMERIC_OVERFLOW; goto Cleanup; } /* Sum the digit into the result with the current power of 10 */ ReturnDesc->Integer.Value += (((UINT64) Temp32) * PowerOfTen); /* Shift to next BCD digit */ Digit >>= 4; /* Next power of 10 */ PowerOfTen *= 10; } break; case AML_TO_BCD_OP: /* ToBcd (Operand, Result) */ ReturnDesc->Integer.Value = 0; Digit = Operand[0]->Integer.Value; /* Each BCD digit is one nybble wide */ for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++) { (void) AcpiUtShortDivide (Digit, 10, &Digit, &Temp32); /* * Insert the BCD digit that resides in the * remainder from above */ ReturnDesc->Integer.Value |= (((UINT64) Temp32) << ACPI_MUL_4 (i)); } /* Overflow if there is any data left in Digit */ if (Digit > 0) { ACPI_ERROR ((AE_INFO, "Integer too large to convert to BCD: 0x%8.8X%8.8X", ACPI_FORMAT_UINT64 (Operand[0]->Integer.Value))); Status = AE_AML_NUMERIC_OVERFLOW; goto Cleanup; } break; case AML_COND_REF_OF_OP: /* CondRefOf (SourceObject, Result) */ /* * This op is a little strange because the internal return value is * different than the return value stored in the result descriptor * (There are really two return values) */ if ((ACPI_NAMESPACE_NODE *) Operand[0] == AcpiGbl_RootNode) { /* * This means that the object does not exist in the namespace, * return FALSE */ ReturnDesc->Integer.Value = 0; goto Cleanup; } /* Get the object reference, store it, and remove our reference */ Status = AcpiExGetObjectReference (Operand[0], &ReturnDesc2, WalkState); if (ACPI_FAILURE (Status)) { goto Cleanup; } Status = AcpiExStore (ReturnDesc2, Operand[1], WalkState); AcpiUtRemoveReference (ReturnDesc2); /* The object exists in the namespace, return TRUE */ ReturnDesc->Integer.Value = ACPI_UINT64_MAX; goto Cleanup; default: /* No other opcodes get here */ break; } break; case AML_STORE_OP: /* Store (Source, Target) */ /* * A store operand is typically a number, string, buffer or lvalue * Be careful about deleting the source object, * since the object itself may have been stored. */ Status = AcpiExStore (Operand[0], Operand[1], WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* It is possible that the Store already produced a return object */ if (!WalkState->ResultObj) { /* * Normally, we would remove a reference on the Operand[0] * parameter; But since it is being used as the internal return * object (meaning we would normally increment it), the two * cancel out, and we simply don't do anything. */ WalkState->ResultObj = Operand[0]; WalkState->Operands[0] = NULL; /* Prevent deletion */ } return_ACPI_STATUS (Status); /* * ACPI 2.0 Opcodes */ case AML_COPY_OP: /* Copy (Source, Target) */ Status = AcpiUtCopyIobjectToIobject ( Operand[0], &ReturnDesc, WalkState); break; case AML_TO_DECSTRING_OP: /* ToDecimalString (Data, Result) */ Status = AcpiExConvertToString ( Operand[0], &ReturnDesc, ACPI_EXPLICIT_CONVERT_DECIMAL); if (ReturnDesc == Operand[0]) { /* No conversion performed, add ref to handle return value */ AcpiUtAddReference (ReturnDesc); } break; case AML_TO_HEXSTRING_OP: /* ToHexString (Data, Result) */ Status = AcpiExConvertToString ( Operand[0], &ReturnDesc, ACPI_EXPLICIT_CONVERT_HEX); if (ReturnDesc == Operand[0]) { /* No conversion performed, add ref to handle return value */ AcpiUtAddReference (ReturnDesc); } break; case AML_TO_BUFFER_OP: /* ToBuffer (Data, Result) */ Status = AcpiExConvertToBuffer (Operand[0], &ReturnDesc); if (ReturnDesc == Operand[0]) { /* No conversion performed, add ref to handle return value */ AcpiUtAddReference (ReturnDesc); } break; case AML_TO_INTEGER_OP: /* ToInteger (Data, Result) */ /* Perform "explicit" conversion */ Status = AcpiExConvertToInteger (Operand[0], &ReturnDesc, 0); if (ReturnDesc == Operand[0]) { /* No conversion performed, add ref to handle return value */ AcpiUtAddReference (ReturnDesc); } break; case AML_SHIFT_LEFT_BIT_OP: /* ShiftLeftBit (Source, BitNum) */ case AML_SHIFT_RIGHT_BIT_OP: /* ShiftRightBit (Source, BitNum) */ /* These are two obsolete opcodes */ ACPI_ERROR ((AE_INFO, "%s is obsolete and not implemented", AcpiPsGetOpcodeName (WalkState->Opcode))); Status = AE_SUPPORT; goto Cleanup; default: /* Unknown opcode */ ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; goto Cleanup; } if (ACPI_SUCCESS (Status)) { /* Store the return value computed above into the target object */ Status = AcpiExStore (ReturnDesc, Operand[1], WalkState); } Cleanup: /* Delete return object on error */ if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ReturnDesc); } /* Save return object on success */ else if (!WalkState->ResultObj) { WalkState->ResultObj = ReturnDesc; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiNsAttachObject ( ACPI_NAMESPACE_NODE *Node, ACPI_OPERAND_OBJECT *Object, ACPI_OBJECT_TYPE Type) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *LastObjDesc; ACPI_OBJECT_TYPE ObjectType = ACPI_TYPE_ANY; ACPI_FUNCTION_TRACE (NsAttachObject); /* * Parameter validation */ if (!Node) { /* Invalid handle */ ACPI_ERROR ((AE_INFO, "Null NamedObj handle")); return_ACPI_STATUS (AE_BAD_PARAMETER); } if (!Object && (ACPI_TYPE_ANY != Type)) { /* Null object */ ACPI_ERROR ((AE_INFO, "Null object, but type not ACPI_TYPE_ANY")); return_ACPI_STATUS (AE_BAD_PARAMETER); } if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) { /* Not a name handle */ ACPI_ERROR ((AE_INFO, "Invalid handle %p [%s]", Node, AcpiUtGetDescriptorName (Node))); return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Check if this object is already attached */ if (Node->Object == Object) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj %p already installed in NameObj %p\n", Object, Node)); return_ACPI_STATUS (AE_OK); } /* If null object, we will just install it */ if (!Object) { ObjDesc = NULL; ObjectType = ACPI_TYPE_ANY; } /* * If the source object is a namespace Node with an attached object, * we will use that (attached) object */ else if ((ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) && ((ACPI_NAMESPACE_NODE *) Object)->Object) { /* * Value passed is a name handle and that name has a * non-null value. Use that name's value and type. */ ObjDesc = ((ACPI_NAMESPACE_NODE *) Object)->Object; ObjectType = ((ACPI_NAMESPACE_NODE *) Object)->Type; } /* * Otherwise, we will use the parameter object, but we must type * it first */ else { ObjDesc = (ACPI_OPERAND_OBJECT *) Object; /* Use the given type */ ObjectType = Type; } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n", ObjDesc, Node, AcpiUtGetNodeName (Node))); /* Detach an existing attached object if present */ if (Node->Object) { AcpiNsDetachObject (Node); } if (ObjDesc) { /* * Must increment the new value's reference count * (if it is an internal object) */ AcpiUtAddReference (ObjDesc); /* * Handle objects with multiple descriptors - walk * to the end of the descriptor list */ LastObjDesc = ObjDesc; while (LastObjDesc->Common.NextObject) { LastObjDesc = LastObjDesc->Common.NextObject; } /* Install the object at the front of the object list */ LastObjDesc->Common.NextObject = Node->Object; } Node->Type = (UINT8) ObjectType; Node->Object = ObjDesc; return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiDsBuildInternalPackageObj ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op, UINT32 ElementCount, ACPI_OPERAND_OBJECT **ObjDescPtr) { ACPI_PARSE_OBJECT *Arg; ACPI_PARSE_OBJECT *Parent; ACPI_OPERAND_OBJECT *ObjDesc = NULL; ACPI_STATUS Status = AE_OK; UINT32 i; UINT16 Index; UINT16 ReferenceCount; ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj); /* Find the parent of a possibly nested package */ Parent = Op->Common.Parent; while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) || (Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) { Parent = Parent->Common.Parent; } /* * If we are evaluating a Named package object "Name (xxxx, Package)", * the package object already exists, otherwise it must be created. */ ObjDesc = *ObjDescPtr; if (!ObjDesc) { ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE); *ObjDescPtr = ObjDesc; if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } ObjDesc->Package.Node = Parent->Common.Node; } /* * Allocate the element array (array of pointers to the individual * objects) based on the NumElements parameter. Add an extra pointer slot * so that the list is always null terminated. */ ObjDesc->Package.Elements = ACPI_ALLOCATE_ZEROED ( ((ACPI_SIZE) ElementCount + 1) * sizeof (void *)); if (!ObjDesc->Package.Elements) { AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (AE_NO_MEMORY); } ObjDesc->Package.Count = ElementCount; /* * Initialize the elements of the package, up to the NumElements count. * Package is automatically padded with uninitialized (NULL) elements * if NumElements is greater than the package list length. Likewise, * Package is truncated if NumElements is less than the list length. */ Arg = Op->Common.Value.Arg; Arg = Arg->Common.Next; for (i = 0; Arg && (i < ElementCount); i++) { if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) { if (Arg->Common.Node->Type == ACPI_TYPE_METHOD) { /* * A method reference "looks" to the parser to be a method * invocation, so we special case it here */ Arg->Common.AmlOpcode = AML_INT_NAMEPATH_OP; Status = AcpiDsBuildInternalObject (WalkState, Arg, &ObjDesc->Package.Elements[i]); } else { /* This package element is already built, just get it */ ObjDesc->Package.Elements[i] = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node); } } else { Status = AcpiDsBuildInternalObject (WalkState, Arg, &ObjDesc->Package.Elements[i]); } if (*ObjDescPtr) { /* Existing package, get existing reference count */ ReferenceCount = (*ObjDescPtr)->Common.ReferenceCount; if (ReferenceCount > 1) { /* Make new element ref count match original ref count */ for (Index = 0; Index < (ReferenceCount - 1); Index++) { AcpiUtAddReference ((ObjDesc->Package.Elements[i])); } } } Arg = Arg->Common.Next; } /* Check for match between NumElements and actual length of PackageList */ if (Arg) { /* * NumElements was exhausted, but there are remaining elements in the * PackageList. Truncate the package to NumElements. * * Note: technically, this is an error, from ACPI spec: "It is an error * for NumElements to be less than the number of elements in the * PackageList". However, we just print a message and * no exception is returned. This provides Windows compatibility. Some * BIOSs will alter the NumElements on the fly, creating this type * of ill-formed package object. */ while (Arg) { /* * We must delete any package elements that were created earlier * and are not going to be used because of the package truncation. */ if (Arg->Common.Node) { AcpiUtRemoveReference ( ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node)); Arg->Common.Node = NULL; } /* Find out how many elements there really are */ i++; Arg = Arg->Common.Next; } ACPI_INFO ((AE_INFO, "Actual Package length (%u) is larger than NumElements field (%u), truncated", i, ElementCount)); } else if (i < ElementCount) { /* * Arg list (elements) was exhausted, but we did not reach NumElements count. * Note: this is not an error, the package is padded out with NULLs. */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Package List length (%u) smaller than NumElements count (%u), padded with null elements\n", i, ElementCount)); } ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID; Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiInstallNotifyHandler ( ACPI_HANDLE Device, UINT32 HandlerType, ACPI_NOTIFY_HANDLER Handler, void *Context) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *NotifyObj; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler); /* Parameter validation */ if ((!Device) || (!Handler) || (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Convert and validate the device handle */ Node = AcpiNsMapHandleToNode (Device); if (!Node) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* * Root Object: * Registering a notify handler on the root object indicates that the * caller wishes to receive notifications for all objects. Note that * only one <external> global handler can be regsitered (per notify type). */ if (Device == ACPI_ROOT_OBJECT) { /* Make sure the handler is not already installed */ if (((HandlerType & ACPI_SYSTEM_NOTIFY) && AcpiGbl_SystemNotify.Handler) || ((HandlerType & ACPI_DEVICE_NOTIFY) && AcpiGbl_DeviceNotify.Handler)) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } if (HandlerType & ACPI_SYSTEM_NOTIFY) { AcpiGbl_SystemNotify.Node = Node; AcpiGbl_SystemNotify.Handler = Handler; AcpiGbl_SystemNotify.Context = Context; } if (HandlerType & ACPI_DEVICE_NOTIFY) { AcpiGbl_DeviceNotify.Node = Node; AcpiGbl_DeviceNotify.Handler = Handler; AcpiGbl_DeviceNotify.Context = Context; } /* Global notify handler installed */ } /* * All Other Objects: * Caller will only receive notifications specific to the target object. * Note that only certain object types can receive notifications. */ else { /* Notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { Status = AE_TYPE; goto UnlockAndExit; } /* Check for an existing internal object */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* Object exists - make sure there's no handler */ if (((HandlerType & ACPI_SYSTEM_NOTIFY) && ObjDesc->CommonNotify.SystemNotify) || ((HandlerType & ACPI_DEVICE_NOTIFY) && ObjDesc->CommonNotify.DeviceNotify)) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } } else { /* Create a new object */ ObjDesc = AcpiUtCreateInternalObject (Node->Type); if (!ObjDesc) { Status = AE_NO_MEMORY; goto UnlockAndExit; } /* Attach new object to the Node */ Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type); /* Remove local reference to the object */ AcpiUtRemoveReference (ObjDesc); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } } /* Install the handler */ NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY); if (!NotifyObj) { Status = AE_NO_MEMORY; goto UnlockAndExit; } NotifyObj->Notify.Node = Node; NotifyObj->Notify.Handler = Handler; NotifyObj->Notify.Context = Context; if (HandlerType & ACPI_SYSTEM_NOTIFY) { ObjDesc->CommonNotify.SystemNotify = NotifyObj; } if (HandlerType & ACPI_DEVICE_NOTIFY) { ObjDesc->CommonNotify.DeviceNotify = NotifyObj; } if (HandlerType == ACPI_ALL_NOTIFY) { /* Extra ref if installed in both */ AcpiUtAddReference (NotifyObj); } } UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiExStoreObjectToIndex ( ACPI_OPERAND_OBJECT *SourceDesc, ACPI_OPERAND_OBJECT *IndexDesc, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *NewDesc; UINT8 Value = 0; UINT32 i; ACPI_FUNCTION_TRACE (ExStoreObjectToIndex); /* * Destination must be a reference pointer, and * must point to either a buffer or a package */ switch (IndexDesc->Reference.TargetType) { case ACPI_TYPE_PACKAGE: /* * Storing to a package element. Copy the object and replace * any existing object with the new object. No implicit * conversion is performed. * * The object at *(IndexDesc->Reference.Where) is the * element within the package that is to be modified. * The parent package object is at IndexDesc->Reference.Object */ ObjDesc = *(IndexDesc->Reference.Where); if (SourceDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE && SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE) { /* This is a DDBHandle, just add a reference to it */ AcpiUtAddReference (SourceDesc); NewDesc = SourceDesc; } else { /* Normal object, copy it */ Status = AcpiUtCopyIobjectToIobject (SourceDesc, &NewDesc, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } if (ObjDesc) { /* Decrement reference count by the ref count of the parent package */ for (i = 0; i < ((ACPI_OPERAND_OBJECT *) IndexDesc->Reference.Object)->Common.ReferenceCount; i++) { AcpiUtRemoveReference (ObjDesc); } } *(IndexDesc->Reference.Where) = NewDesc; /* Increment ref count by the ref count of the parent package-1 */ for (i = 1; i < ((ACPI_OPERAND_OBJECT *) IndexDesc->Reference.Object)->Common.ReferenceCount; i++) { AcpiUtAddReference (NewDesc); } break; case ACPI_TYPE_BUFFER_FIELD: /* * Store into a Buffer or String (not actually a real BufferField) * at a location defined by an Index. * * The first 8-bit element of the source object is written to the * 8-bit Buffer location defined by the Index destination object, * according to the ACPI 2.0 specification. */ /* * Make sure the target is a Buffer or String. An error should * not happen here, since the ReferenceObject was constructed * by the INDEX_OP code. */ ObjDesc = IndexDesc->Reference.Object; if ((ObjDesc->Common.Type != ACPI_TYPE_BUFFER) && (ObjDesc->Common.Type != ACPI_TYPE_STRING)) { return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* * The assignment of the individual elements will be slightly * different for each source type. */ switch (SourceDesc->Common.Type) { case ACPI_TYPE_INTEGER: /* Use the least-significant byte of the integer */ Value = (UINT8) (SourceDesc->Integer.Value); break; case ACPI_TYPE_BUFFER: case ACPI_TYPE_STRING: /* Note: Takes advantage of common string/buffer fields */ Value = SourceDesc->Buffer.Pointer[0]; break; default: /* All other types are invalid */ ACPI_ERROR ((AE_INFO, "Source must be Integer/Buffer/String type, not %s", AcpiUtGetObjectTypeName (SourceDesc))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* Store the source value into the target buffer byte */ ObjDesc->Buffer.Pointer[IndexDesc->Reference.Value] = Value; break; default: ACPI_ERROR ((AE_INFO, "Target is not a Package or BufferField")); Status = AE_AML_OPERAND_TYPE; break; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiDsBuildInternalPackageObj ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op, UINT32 ElementCount, ACPI_OPERAND_OBJECT **ObjDescPtr) { ACPI_PARSE_OBJECT *Arg; ACPI_PARSE_OBJECT *Parent; ACPI_OPERAND_OBJECT *ObjDesc = NULL; ACPI_STATUS Status = AE_OK; ACPI_NATIVE_UINT i; UINT16 Index; UINT16 ReferenceCount; ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj); /* Find the parent of a possibly nested package */ Parent = Op->Common.Parent; while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) || (Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) { Parent = Parent->Common.Parent; } /* * If we are evaluating a Named package object "Name (xxxx, Package)", * the package object already exists, otherwise it must be created. */ ObjDesc = *ObjDescPtr; if (!ObjDesc) { ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE); *ObjDescPtr = ObjDesc; if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } ObjDesc->Package.Node = Parent->Common.Node; } /* * Allocate the element array (array of pointers to the individual * objects) based on the NumElements parameter. Add an extra pointer slot * so that the list is always null terminated. */ ObjDesc->Package.Elements = ACPI_ALLOCATE_ZEROED ( ((ACPI_SIZE) ElementCount + 1) * sizeof (void *)); if (!ObjDesc->Package.Elements) { AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (AE_NO_MEMORY); } ObjDesc->Package.Count = ElementCount; /* * Initialize the elements of the package, up to the NumElements count. * Package is automatically padded with uninitialized (NULL) elements * if NumElements is greater than the package list length. Likewise, * Package is truncated if NumElements is less than the list length. */ Arg = Op->Common.Value.Arg; Arg = Arg->Common.Next; for (i = 0; Arg && (i < ElementCount); i++) { if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) { /* This package element is already built, just get it */ ObjDesc->Package.Elements[i] = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node); } else { Status = AcpiDsBuildInternalObject (WalkState, Arg, &ObjDesc->Package.Elements[i]); } if (*ObjDescPtr) { /* Existing package, get existing reference count */ ReferenceCount = (*ObjDescPtr)->Common.ReferenceCount; if (ReferenceCount > 1) { /* Make new element ref count match original ref count */ for (Index = 0; Index < (ReferenceCount - 1); Index++) { AcpiUtAddReference ((ObjDesc->Package.Elements[i])); } } } Arg = Arg->Common.Next; } if (!Arg) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Package List length larger than NumElements count (%X), truncated\n", ElementCount)); } ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID; Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc); return_ACPI_STATUS (Status); }