ACPI_STATUS AcpiExOpcode_1A_1T_0R ( ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_0R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Examine the AML opcode */ switch (WalkState->Opcode) { case AML_LOAD_OP: Status = AcpiExLoadOp (Operand[0], Operand[1], WalkState); break; default: /* Unknown opcode */ ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; goto Cleanup; } Cleanup: return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExOpcode_2A_0T_0R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_NAMESPACE_NODE *Node; UINT32 Value; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_0R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Examine the opcode */ switch (WalkState->Opcode) { case AML_NOTIFY_OP: /* Notify (NotifyObject, NotifyValue) */ /* The first operand is a namespace node */ Node = (ACPI_NAMESPACE_NODE *) Operand[0]; /* Second value is the notify value */ Value = (UINT32) Operand[1]->Integer.Value; /* Are notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { ACPI_ERROR ((AE_INFO, "Unexpected notify object type [%s]", AcpiUtGetTypeName (Node->Type))); Status = AE_AML_OPERAND_TYPE; break; } /* * Dispatch the notify to the appropriate handler * NOTE: the request is queued for execution after this method * completes. The notify handlers are NOT invoked synchronously * from this thread -- because handlers may in turn run other * control methods. */ Status = AcpiEvQueueNotifyRequest (Node, Value); break; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExOpcode_1A_0T_0R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_0R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Examine the AML opcode */ switch (WalkState->Opcode) { case AML_RELEASE_OP: /* Release (MutexObject) */ Status = AcpiExReleaseMutex (Operand[0], WalkState); break; case AML_RESET_OP: /* Reset (EventObject) */ Status = AcpiExSystemResetEvent (Operand[0]); break; case AML_SIGNAL_OP: /* Signal (EventObject) */ Status = AcpiExSystemSignalEvent (Operand[0]); break; case AML_SLEEP_OP: /* Sleep (MsecTime) */ Status = AcpiExSystemDoSleep (Operand[0]->Integer.Value); break; case AML_STALL_OP: /* Stall (UsecTime) */ Status = AcpiExSystemDoStall ((UINT32) Operand[0]->Integer.Value); break; case AML_UNLOAD_OP: /* Unload (Handle) */ Status = AcpiExUnloadTable (Operand[0]); break; default: /* Unknown opcode */ ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; break; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExOpcode_0A_0T_1R ( ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT *ReturnDesc = NULL; ACPI_FUNCTION_TRACE_STR (ExOpcode_0A_0T_1R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Examine the AML opcode */ switch (WalkState->Opcode) { case AML_TIMER_OP: /* Timer () */ /* Create a return object of type Integer */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } #if ACPI_MACHINE_WIDTH != 16 ReturnDesc->Integer.Value = AcpiOsGetTimer (); #endif break; default: /* Unknown opcode */ ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; break; } Cleanup: /* Delete return object on error */ if ((ACPI_FAILURE (Status)) || WalkState->ResultObj) { AcpiUtRemoveReference (ReturnDesc); } else { /* Save the return value */ WalkState->ResultObj = ReturnDesc; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExOpcode_3A_0T_0R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_SIGNAL_FATAL_INFO *Fatal; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE_STR (ExOpcode_3A_0T_0R, AcpiPsGetOpcodeName (WalkState->Opcode)); switch (WalkState->Opcode) { case AML_FATAL_OP: /* Fatal (FatalType FatalCode FatalArg) */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", (UINT32) Operand[0]->Integer.Value, (UINT32) Operand[1]->Integer.Value, (UINT32) Operand[2]->Integer.Value)); Fatal = ACPI_ALLOCATE (sizeof (ACPI_SIGNAL_FATAL_INFO)); if (Fatal) { Fatal->Type = (UINT32) Operand[0]->Integer.Value; Fatal->Code = (UINT32) Operand[1]->Integer.Value; Fatal->Argument = (UINT32) Operand[2]->Integer.Value; } /* Always signal the OS! */ Status = AcpiOsSignal (ACPI_SIGNAL_FATAL, Fatal); /* Might return while OS is shutting down, just continue */ ACPI_FREE (Fatal); break; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; goto Cleanup; } Cleanup: return_ACPI_STATUS (Status); }
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 */ if ((EntryType == ACPI_TYPE_DEVICE) || (EntryType == ACPI_TYPE_THERMAL) || (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 (ACPI_GET_OBJECT_TYPE (SourceDesc) != 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 (ACPI_GET_OBJECT_TYPE (SourceDesc) != 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 (ACPI_GET_OBJECT_TYPE (SourceDesc) != 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 (ACPI_GET_OBJECT_TYPE (SourceDesc) != 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_METHOD: 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.Opcode) { case AML_LOAD_OP: /* This is a DdbHandle */ /* Return an additional reference to the object */ case AML_REF_OF_OP: ObjDesc = SourceDesc; AcpiUtAddReference (ObjDesc); break; default: /* No named references are allowed here */ ACPI_ERROR ((AE_INFO, "Unsupported Reference opcode %X (%s)", SourceDesc->Reference.Opcode, AcpiPsGetOpcodeName (SourceDesc->Reference.Opcode))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } break; default: /* Default case is for unknown types */ ACPI_ERROR ((AE_INFO, "Node %p - Unknown object type %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 AcpiDsEvalBankFieldOperands ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *OperandDesc; ACPI_NAMESPACE_NODE *Node; ACPI_PARSE_OBJECT *NextOp; ACPI_PARSE_OBJECT *Arg; ACPI_FUNCTION_TRACE_PTR (DsEvalBankFieldOperands, Op); /* * This is where we evaluate the BankValue field of the * BankField declaration */ /* NextOp points to the op that holds the Region */ NextOp = Op->Common.Value.Arg; /* NextOp points to the op that holds the Bank Register */ NextOp = NextOp->Common.Next; /* NextOp points to the op that holds the Bank Value */ NextOp = NextOp->Common.Next; /* * Set proper index into operand stack for AcpiDsObjStackPush * invoked inside AcpiDsCreateOperand. * * We use WalkState->Operands[0] to store the evaluated BankValue */ WalkState->OperandIndex = 0; Status = AcpiDsCreateOperand (WalkState, NextOp, 0); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } Status = AcpiExResolveToValue (&WalkState->Operands[0], WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 1); /* * Get the BankValue operand and save it * (at Top of stack) */ OperandDesc = WalkState->Operands[0]; /* Arg points to the start Bank Field */ Arg = AcpiPsGetArg (Op, 4); while (Arg) { /* Ignore OFFSET and ACCESSAS terms here */ if (Arg->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) { Node = Arg->Common.Node; ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { return_ACPI_STATUS (AE_NOT_EXIST); } ObjDesc->BankField.Value = (UINT32) OperandDesc->Integer.Value; } /* Move to next field in the list */ Arg = Arg->Common.Next; } AcpiUtRemoveReference (OperandDesc); return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiDsInitBufferField ( UINT16 AmlOpcode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_OPERAND_OBJECT *BufferDesc, ACPI_OPERAND_OBJECT *OffsetDesc, ACPI_OPERAND_OBJECT *LengthDesc, ACPI_OPERAND_OBJECT *ResultDesc) { UINT32 Offset; UINT32 BitOffset; UINT32 BitCount; UINT8 FieldFlags; ACPI_STATUS Status; ACPI_FUNCTION_TRACE_PTR (DsInitBufferField, ObjDesc); /* Host object must be a Buffer */ if (BufferDesc->Common.Type != ACPI_TYPE_BUFFER) { ACPI_ERROR ((AE_INFO, "Target of Create Field is not a Buffer object - %s", AcpiUtGetObjectTypeName (BufferDesc))); Status = AE_AML_OPERAND_TYPE; goto Cleanup; } /* * The last parameter to all of these opcodes (ResultDesc) started * out as a NameString, and should therefore now be a NS node * after resolution in AcpiExResolveOperands(). */ if (ACPI_GET_DESCRIPTOR_TYPE (ResultDesc) != ACPI_DESC_TYPE_NAMED) { ACPI_ERROR ((AE_INFO, "(%s) destination not a NS Node [%s]", AcpiPsGetOpcodeName (AmlOpcode), AcpiUtGetDescriptorName (ResultDesc))); Status = AE_AML_OPERAND_TYPE; goto Cleanup; } Offset = (UINT32) OffsetDesc->Integer.Value; /* * Setup the Bit offsets and counts, according to the opcode */ switch (AmlOpcode) { case AML_CREATE_FIELD_OP: /* Offset is in bits, count is in bits */ FieldFlags = AML_FIELD_ACCESS_BYTE; BitOffset = Offset; BitCount = (UINT32) LengthDesc->Integer.Value; /* Must have a valid (>0) bit count */ if (BitCount == 0) { ACPI_ERROR ((AE_INFO, "Attempt to CreateField of length zero")); Status = AE_AML_OPERAND_VALUE; goto Cleanup; } break; case AML_CREATE_BIT_FIELD_OP: /* Offset is in bits, Field is one bit */ BitOffset = Offset; BitCount = 1; FieldFlags = AML_FIELD_ACCESS_BYTE; break; case AML_CREATE_BYTE_FIELD_OP: /* Offset is in bytes, field is one byte */ BitOffset = 8 * Offset; BitCount = 8; FieldFlags = AML_FIELD_ACCESS_BYTE; break; case AML_CREATE_WORD_FIELD_OP: /* Offset is in bytes, field is one word */ BitOffset = 8 * Offset; BitCount = 16; FieldFlags = AML_FIELD_ACCESS_WORD; break; case AML_CREATE_DWORD_FIELD_OP: /* Offset is in bytes, field is one dword */ BitOffset = 8 * Offset; BitCount = 32; FieldFlags = AML_FIELD_ACCESS_DWORD; break; case AML_CREATE_QWORD_FIELD_OP: /* Offset is in bytes, field is one qword */ BitOffset = 8 * Offset; BitCount = 64; FieldFlags = AML_FIELD_ACCESS_QWORD; break; default: ACPI_ERROR ((AE_INFO, "Unknown field creation opcode 0x%02X", AmlOpcode)); Status = AE_AML_BAD_OPCODE; goto Cleanup; } /* Entire field must fit within the current length of the buffer */ if ((BitOffset + BitCount) > (8 * (UINT32) BufferDesc->Buffer.Length)) { ACPI_ERROR ((AE_INFO, "Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)", AcpiUtGetNodeName (ResultDesc), BitOffset + BitCount, AcpiUtGetNodeName (BufferDesc->Buffer.Node), 8 * (UINT32) BufferDesc->Buffer.Length)); Status = AE_AML_BUFFER_LIMIT; goto Cleanup; } /* * Initialize areas of the field object that are common to all fields * For FieldFlags, use LOCK_RULE = 0 (NO_LOCK), * UPDATE_RULE = 0 (UPDATE_PRESERVE) */ Status = AcpiExPrepCommonFieldObject (ObjDesc, FieldFlags, 0, BitOffset, BitCount); if (ACPI_FAILURE (Status)) { goto Cleanup; } ObjDesc->BufferField.BufferObj = BufferDesc; /* Reference count for BufferDesc inherits ObjDesc count */ BufferDesc->Common.ReferenceCount = (UINT16) (BufferDesc->Common.ReferenceCount + ObjDesc->Common.ReferenceCount); Cleanup: /* Always delete the operands */ AcpiUtRemoveReference (OffsetDesc); AcpiUtRemoveReference (BufferDesc); if (AmlOpcode == AML_CREATE_FIELD_OP) { AcpiUtRemoveReference (LengthDesc); } /* On failure, delete the result descriptor */ if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ResultDesc); /* Result descriptor */ } else { /* Now the address and length are valid for this BufferField */ ObjDesc->BufferField.Flags |= AOPOBJ_DATA_VALID; } 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 AcpiExOpcode_3A_1T_1R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_OPERAND_OBJECT *ReturnDesc = NULL; char *Buffer = NULL; ACPI_STATUS Status = AE_OK; UINT64 Index; ACPI_SIZE Length; ACPI_FUNCTION_TRACE_STR (ExOpcode_3A_1T_1R, AcpiPsGetOpcodeName (WalkState->Opcode)); switch (WalkState->Opcode) { case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */ /* * Create the return object. The Source operand is guaranteed to be * either a String or a Buffer, so just use its type. */ ReturnDesc = AcpiUtCreateInternalObject ( (Operand[0])->Common.Type); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* Get the Integer values from the objects */ Index = Operand[1]->Integer.Value; Length = (ACPI_SIZE) Operand[2]->Integer.Value; /* * If the index is beyond the length of the String/Buffer, or if the * requested length is zero, return a zero-length String/Buffer */ if (Index >= Operand[0]->String.Length) { Length = 0; } /* Truncate request if larger than the actual String/Buffer */ else if ((Index + Length) > Operand[0]->String.Length) { Length = (ACPI_SIZE) Operand[0]->String.Length - (ACPI_SIZE) Index; } /* Strings always have a sub-pointer, not so for buffers */ switch ((Operand[0])->Common.Type) { case ACPI_TYPE_STRING: /* Always allocate a new buffer for the String */ Buffer = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) Length + 1); if (!Buffer) { Status = AE_NO_MEMORY; goto Cleanup; } break; case ACPI_TYPE_BUFFER: /* If the requested length is zero, don't allocate a buffer */ if (Length > 0) { /* Allocate a new buffer for the Buffer */ Buffer = ACPI_ALLOCATE_ZEROED (Length); if (!Buffer) { Status = AE_NO_MEMORY; goto Cleanup; } } break; default: /* Should not happen */ Status = AE_AML_OPERAND_TYPE; goto Cleanup; } if (Buffer) { /* We have a buffer, copy the portion requested */ ACPI_MEMCPY (Buffer, Operand[0]->String.Pointer + Index, Length); } /* Set the length of the new String/Buffer */ ReturnDesc->String.Pointer = Buffer; ReturnDesc->String.Length = (UINT32) Length; /* Mark buffer initialized */ ReturnDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; break; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; goto Cleanup; } /* Store the result in the target */ Status = AcpiExStore (ReturnDesc, Operand[3], WalkState); Cleanup: /* Delete return object on error */ if (ACPI_FAILURE (Status) || WalkState->ResultObj) { AcpiUtRemoveReference (ReturnDesc); WalkState->ResultObj = NULL; } /* Set the return object and exit */ else { WalkState->ResultObj = ReturnDesc; } return_ACPI_STATUS (Status); }
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); }
ACPI_STATUS AcpiExResolveOperands ( UINT16 Opcode, ACPI_OPERAND_OBJECT **StackPtr, ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_STATUS Status = AE_OK; UINT8 ObjectType; UINT32 ArgTypes; const ACPI_OPCODE_INFO *OpInfo; UINT32 ThisArgType; ACPI_OBJECT_TYPE TypeNeeded; UINT16 TargetOp = 0; ACPI_FUNCTION_TRACE_U32 (ExResolveOperands, Opcode); OpInfo = AcpiPsGetOpcodeInfo (Opcode); if (OpInfo->Class == AML_CLASS_UNKNOWN) { return_ACPI_STATUS (AE_AML_BAD_OPCODE); } ArgTypes = OpInfo->RuntimeArgs; if (ArgTypes == ARGI_INVALID_OPCODE) { ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", Opcode)); return_ACPI_STATUS (AE_AML_INTERNAL); } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode %X [%s] RequiredOperandTypes=%8.8X\n", Opcode, OpInfo->Name, ArgTypes)); /* * Normal exit is with (ArgTypes == 0) at end of argument list. * Function will return an exception from within the loop upon * finding an entry which is not (or cannot be converted * to) the required type; if stack underflows; or upon * finding a NULL stack entry (which should not happen). */ while (GET_CURRENT_ARG_TYPE (ArgTypes)) { if (!StackPtr || !*StackPtr) { ACPI_ERROR ((AE_INFO, "Null stack entry at %p", StackPtr)); return_ACPI_STATUS (AE_AML_INTERNAL); } /* Extract useful items */ ObjDesc = *StackPtr; /* Decode the descriptor type */ switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) { case ACPI_DESC_TYPE_NAMED: /* Namespace Node */ ObjectType = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type; /* * Resolve an alias object. The construction of these objects * guarantees that there is only one level of alias indirection; * thus, the attached object is always the aliased namespace node */ if (ObjectType == ACPI_TYPE_LOCAL_ALIAS) { ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) ObjDesc); *StackPtr = ObjDesc; ObjectType = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Type; } break; case ACPI_DESC_TYPE_OPERAND: /* ACPI internal object */ ObjectType = ObjDesc->Common.Type; /* Check for bad ACPI_OBJECT_TYPE */ if (!AcpiUtValidObjectType (ObjectType)) { ACPI_ERROR ((AE_INFO, "Bad operand object type [0x%X]", ObjectType)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } if (ObjectType == (UINT8) ACPI_TYPE_LOCAL_REFERENCE) { /* Validate the Reference */ switch (ObjDesc->Reference.Class) { case ACPI_REFCLASS_DEBUG: TargetOp = AML_DEBUG_OP; /*lint -fallthrough */ case ACPI_REFCLASS_ARG: case ACPI_REFCLASS_LOCAL: case ACPI_REFCLASS_INDEX: case ACPI_REFCLASS_REFOF: case ACPI_REFCLASS_TABLE: /* DdbHandle from LOAD_OP or LOAD_TABLE_OP */ case ACPI_REFCLASS_NAME: /* Reference to a named object */ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Operand is a Reference, Class [%s] %2.2X\n", AcpiUtGetReferenceName (ObjDesc), ObjDesc->Reference.Class)); break; default: ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X in %p", ObjDesc->Reference.Class, ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } } break; default: /* Invalid descriptor */ ACPI_ERROR ((AE_INFO, "Invalid descriptor %p [%s]", ObjDesc, AcpiUtGetDescriptorName (ObjDesc))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* Get one argument type, point to the next */ ThisArgType = GET_CURRENT_ARG_TYPE (ArgTypes); INCREMENT_ARG_LIST (ArgTypes); /* * Handle cases where the object does not need to be * resolved to a value */ switch (ThisArgType) { case ARGI_REF_OR_STRING: /* Can be a String or Reference */ if ((ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND) && (ObjDesc->Common.Type == ACPI_TYPE_STRING)) { /* * String found - the string references a named object and * must be resolved to a node */ goto NextOperand; } /* * Else not a string - fall through to the normal Reference * case below */ /*lint -fallthrough */ case ARGI_REFERENCE: /* References: */ case ARGI_INTEGER_REF: case ARGI_OBJECT_REF: case ARGI_DEVICE_REF: case ARGI_TARGETREF: /* Allows implicit conversion rules before store */ case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */ case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */ /* * Need an operand of type ACPI_TYPE_LOCAL_REFERENCE * A Namespace Node is OK as-is */ if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_NAMED) { goto NextOperand; } Status = AcpiExCheckObjectType (ACPI_TYPE_LOCAL_REFERENCE, ObjectType, ObjDesc); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } goto NextOperand; case ARGI_DATAREFOBJ: /* Store operator only */ /* * We don't want to resolve IndexOp reference objects during * a store because this would be an implicit DeRefOf operation. * Instead, we just want to store the reference object. * -- All others must be resolved below. */ if ((Opcode == AML_STORE_OP) && ((*StackPtr)->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && ((*StackPtr)->Reference.Class == ACPI_REFCLASS_INDEX)) { goto NextOperand; } break; default: /* All cases covered above */ break; } /* * Resolve this object to a value */ Status = AcpiExResolveToValue (StackPtr, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Get the resolved object */ ObjDesc = *StackPtr; /* * Check the resulting object (value) type */ switch (ThisArgType) { /* * For the simple cases, only one type of resolved object * is allowed */ case ARGI_MUTEX: /* Need an operand of type ACPI_TYPE_MUTEX */ TypeNeeded = ACPI_TYPE_MUTEX; break; case ARGI_EVENT: /* Need an operand of type ACPI_TYPE_EVENT */ TypeNeeded = ACPI_TYPE_EVENT; break; case ARGI_PACKAGE: /* Package */ /* Need an operand of type ACPI_TYPE_PACKAGE */ TypeNeeded = ACPI_TYPE_PACKAGE; break; case ARGI_ANYTYPE: /* Any operand type will do */ TypeNeeded = ACPI_TYPE_ANY; break; case ARGI_DDBHANDLE: /* Need an operand of type ACPI_TYPE_DDB_HANDLE */ TypeNeeded = ACPI_TYPE_LOCAL_REFERENCE; break; /* * The more complex cases allow multiple resolved object types */ case ARGI_INTEGER: /* * Need an operand of type ACPI_TYPE_INTEGER, * But we can implicitly convert from a STRING or BUFFER * Aka - "Implicit Source Operand Conversion" */ Status = AcpiExConvertToInteger (ObjDesc, StackPtr, 16); if (ACPI_FAILURE (Status)) { if (Status == AE_TYPE) { ACPI_ERROR ((AE_INFO, "Needed [Integer/String/Buffer], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } return_ACPI_STATUS (Status); } if (ObjDesc != *StackPtr) { AcpiUtRemoveReference (ObjDesc); } goto NextOperand; case ARGI_BUFFER: /* * Need an operand of type ACPI_TYPE_BUFFER, * But we can implicitly convert from a STRING or INTEGER * Aka - "Implicit Source Operand Conversion" */ Status = AcpiExConvertToBuffer (ObjDesc, StackPtr); if (ACPI_FAILURE (Status)) { if (Status == AE_TYPE) { ACPI_ERROR ((AE_INFO, "Needed [Integer/String/Buffer], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } return_ACPI_STATUS (Status); } if (ObjDesc != *StackPtr) { AcpiUtRemoveReference (ObjDesc); } goto NextOperand; case ARGI_STRING: /* * Need an operand of type ACPI_TYPE_STRING, * But we can implicitly convert from a BUFFER or INTEGER * Aka - "Implicit Source Operand Conversion" */ Status = AcpiExConvertToString (ObjDesc, StackPtr, ACPI_IMPLICIT_CONVERT_HEX); if (ACPI_FAILURE (Status)) { if (Status == AE_TYPE) { ACPI_ERROR ((AE_INFO, "Needed [Integer/String/Buffer], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } return_ACPI_STATUS (Status); } if (ObjDesc != *StackPtr) { AcpiUtRemoveReference (ObjDesc); } goto NextOperand; case ARGI_COMPUTEDATA: /* Need an operand of type INTEGER, STRING or BUFFER */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* Valid operand */ break; default: ACPI_ERROR ((AE_INFO, "Needed [Integer/String/Buffer], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto NextOperand; case ARGI_BUFFER_OR_STRING: /* Need an operand of type STRING or BUFFER */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* Valid operand */ break; case ACPI_TYPE_INTEGER: /* Highest priority conversion is to type Buffer */ Status = AcpiExConvertToBuffer (ObjDesc, StackPtr); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (ObjDesc != *StackPtr) { AcpiUtRemoveReference (ObjDesc); } break; default: ACPI_ERROR ((AE_INFO, "Needed [Integer/String/Buffer], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto NextOperand; case ARGI_DATAOBJECT: /* * ARGI_DATAOBJECT is only used by the SizeOf operator. * Need a buffer, string, package, or RefOf reference. * * The only reference allowed here is a direct reference to * a namespace node. */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_PACKAGE: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: case ACPI_TYPE_LOCAL_REFERENCE: /* Valid operand */ break; default: ACPI_ERROR ((AE_INFO, "Needed [Buffer/String/Package/Reference], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto NextOperand; case ARGI_COMPLEXOBJ: /* Need a buffer or package or (ACPI 2.0) String */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_PACKAGE: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* Valid operand */ break; default: ACPI_ERROR ((AE_INFO, "Needed [Buffer/String/Package], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto NextOperand; case ARGI_REGION_OR_BUFFER: /* Used by Load() only */ /* Need an operand of type REGION or a BUFFER (which could be a resolved region field) */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_BUFFER: case ACPI_TYPE_REGION: /* Valid operand */ break; default: ACPI_ERROR ((AE_INFO, "Needed [Region/Buffer], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto NextOperand; case ARGI_DATAREFOBJ: /* Used by the Store() operator only */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_PACKAGE: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REFERENCE: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: case ACPI_TYPE_DDB_HANDLE: /* Valid operand */ break; default: if (AcpiGbl_EnableInterpreterSlack) { /* * Enable original behavior of Store(), allowing any and all * objects as the source operand. The ACPI spec does not * allow this, however. */ break; } if (TargetOp == AML_DEBUG_OP) { /* Allow store of any object to the Debug object */ break; } ACPI_ERROR ((AE_INFO, "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p", AcpiUtGetObjectTypeName (ObjDesc), ObjDesc)); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } goto NextOperand; default: /* Unknown type */ ACPI_ERROR ((AE_INFO, "Internal - Unknown ARGI (required operand) type 0x%X", ThisArgType)); return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Make sure that the original object was resolved to the * required object type (Simple cases only). */ Status = AcpiExCheckObjectType (TypeNeeded, (*StackPtr)->Common.Type, *StackPtr); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } NextOperand: /* * If more operands needed, decrement StackPtr to point * to next operand on stack */ if (GET_CURRENT_ARG_TYPE (ArgTypes)) { StackPtr--; } } ACPI_DUMP_OPERANDS (WalkState->Operands, AcpiPsGetOpcodeName (Opcode), WalkState->NumOperands); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExOpcode_2A_0T_0R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_NAMESPACE_NODE *Node; UINT32 Value; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_0R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Examine the opcode */ switch (WalkState->Opcode) { case AML_NOTIFY_OP: /* Notify (NotifyObject, NotifyValue) */ /* The first operand is a namespace node */ Node = (ACPI_NAMESPACE_NODE *) Operand[0]; /* Second value is the notify value */ Value = (UINT32) Operand[1]->Integer.Value; /* Are notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { ACPI_ERROR ((AE_INFO, "Unexpected notify object type [%s]", AcpiUtGetTypeName (Node->Type))); Status = AE_AML_OPERAND_TYPE; break; } #ifdef ACPI_GPE_NOTIFY_CHECK /* * GPE method wake/notify check. Here, we want to ensure that we * don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx * GPE method during system runtime. If we do, the GPE is marked * as "wake-only" and disabled. * * 1) Is the Notify() value == DeviceWake? * 2) Is this a GPE deferred method? (An _Lxx or _Exx method) * 3) Did the original GPE happen at system runtime? * (versus during wake) * * If all three cases are true, this is a wake-only GPE that should * be disabled at runtime. */ if (Value == 2) /* DeviceWake */ { Status = AcpiEvCheckForWakeOnlyGpe (WalkState->GpeEventInfo); if (ACPI_FAILURE (Status)) { /* AE_WAKE_ONLY_GPE only error, means ignore this notify */ return_ACPI_STATUS (AE_OK) } } #endif /* * Dispatch the notify to the appropriate handler * NOTE: the request is queued for execution after this method * completes. The notify handlers are NOT invoked synchronously * from this thread -- because handlers may in turn run other * control methods. */ Status = AcpiEvQueueNotifyRequest (Node, Value); break; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode %X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; }
ACPI_STATUS AcpiPsParseLoop ( ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_PARSE_OBJECT *Op = NULL; /* current op */ ACPI_PARSE_STATE *ParserState; UINT8 *AmlOpStart = NULL; ACPI_FUNCTION_TRACE_PTR (PsParseLoop, WalkState); if (WalkState->DescendingCallback == NULL) { return_ACPI_STATUS (AE_BAD_PARAMETER); } ParserState = &WalkState->ParserState; WalkState->ArgTypes = 0; #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) if (WalkState->WalkType & ACPI_WALK_METHOD_RESTART) { /* We are restarting a preempted control method */ if (AcpiPsHasCompletedScope (ParserState)) { /* * We must check if a predicate to an IF or WHILE statement * was just completed */ if ((ParserState->Scope->ParseScope.Op) && ((ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_IF_OP) || (ParserState->Scope->ParseScope.Op->Common.AmlOpcode == AML_WHILE_OP)) && (WalkState->ControlState) && (WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING)) { /* * A predicate was just completed, get the value of the * predicate and branch based on that value */ WalkState->Op = NULL; Status = AcpiDsGetPredicateValue (WalkState, ACPI_TO_POINTER (TRUE)); if (ACPI_FAILURE (Status) && ((Status & AE_CODE_MASK) != AE_CODE_CONTROL)) { if (Status == AE_AML_NO_RETURN_VALUE) { ACPI_EXCEPTION ((AE_INFO, Status, "Invoked method did not return a value")); } ACPI_EXCEPTION ((AE_INFO, Status, "GetPredicate Failed")); return_ACPI_STATUS (Status); } Status = AcpiPsNextParseState (WalkState, Op, Status); } AcpiPsPopScope (ParserState, &Op, &WalkState->ArgTypes, &WalkState->ArgCount); ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped scope, Op=%p\n", Op)); } else if (WalkState->PrevOp) { /* We were in the middle of an op */ Op = WalkState->PrevOp; WalkState->ArgTypes = WalkState->PrevArgTypes; } } #endif /* Iterative parsing loop, while there is more AML to process: */ while ((ParserState->Aml < ParserState->AmlEnd) || (Op)) { ASL_CV_CAPTURE_COMMENTS (WalkState); AmlOpStart = ParserState->Aml; if (!Op) { Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op); if (ACPI_FAILURE (Status)) { /* * ACPI_PARSE_MODULE_LEVEL means that we are loading a table by * executing it as a control method. However, if we encounter * an error while loading the table, we need to keep trying to * load the table rather than aborting the table load. Set the * status to AE_OK to proceed with the table load. */ if ((WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) && Status == AE_ALREADY_EXISTS) { Status = AE_OK; } if (Status == AE_CTRL_PARSE_CONTINUE) { continue; } if (Status == AE_CTRL_PARSE_PENDING) { Status = AE_OK; } if (Status == AE_CTRL_TERMINATE) { return_ACPI_STATUS (Status); } Status = AcpiPsCompleteOp (WalkState, &Op, Status); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (AcpiNsOpensScope ( AcpiPsGetOpcodeInfo (WalkState->Opcode)->ObjectType)) { /* * If the scope/device op fails to parse, skip the body of * the scope op because the parse failure indicates that * the device may not exist. */ ACPI_ERROR ((AE_INFO, "Skip parsing opcode %s", AcpiPsGetOpcodeName (WalkState->Opcode))); WalkState->ParserState.Aml = WalkState->Aml + 1; WalkState->ParserState.Aml = AcpiPsGetNextPackageEnd(&WalkState->ParserState); WalkState->Aml = WalkState->ParserState.Aml; } continue; } AcpiExStartTraceOpcode (Op, WalkState); } /* * Start ArgCount at zero because we don't know if there are * any args yet */ WalkState->ArgCount = 0; switch (Op->Common.AmlOpcode) { case AML_BYTE_OP: case AML_WORD_OP: case AML_DWORD_OP: case AML_QWORD_OP: break; default: ASL_CV_CAPTURE_COMMENTS (WalkState); break; } /* Are there any arguments that must be processed? */ if (WalkState->ArgTypes) { /* Get arguments */ Status = AcpiPsGetArguments (WalkState, AmlOpStart, Op); if (ACPI_FAILURE (Status)) { Status = AcpiPsCompleteOp (WalkState, &Op, Status); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if ((WalkState->ControlState) && ((WalkState->ControlState->Control.Opcode == AML_IF_OP) || (WalkState->ControlState->Control.Opcode == AML_WHILE_OP))) { /* * If the if/while op fails to parse, we will skip parsing * the body of the op. */ ParserState->Aml = WalkState->ControlState->Control.AmlPredicateStart + 1; ParserState->Aml = AcpiPsGetNextPackageEnd (ParserState); WalkState->Aml = ParserState->Aml; ACPI_ERROR ((AE_INFO, "Skipping While/If block")); if (*WalkState->Aml == AML_ELSE_OP) { ACPI_ERROR ((AE_INFO, "Skipping Else block")); WalkState->ParserState.Aml = WalkState->Aml + 1; WalkState->ParserState.Aml = AcpiPsGetNextPackageEnd (ParserState); WalkState->Aml = ParserState->Aml; } ACPI_FREE(AcpiUtPopGenericState (&WalkState->ControlState)); } Op = NULL; continue; } } /* Check for arguments that need to be processed */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Parseloop: argument count: %8.8X\n", WalkState->ArgCount)); if (WalkState->ArgCount) { /* * There are arguments (complex ones), push Op and * prepare for argument */ Status = AcpiPsPushScope (ParserState, Op, WalkState->ArgTypes, WalkState->ArgCount); if (ACPI_FAILURE (Status)) { Status = AcpiPsCompleteOp (WalkState, &Op, Status); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } continue; } Op = NULL; continue; } /* * All arguments have been processed -- Op is complete, * prepare for next */ WalkState->OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); if (WalkState->OpInfo->Flags & AML_NAMED) { if (Op->Common.AmlOpcode == AML_REGION_OP || Op->Common.AmlOpcode == AML_DATA_REGION_OP) { /* * Skip parsing of control method or opregion body, * because we don't have enough info in the first pass * to parse them correctly. * * Completed parsing an OpRegion declaration, we now * know the length. */ Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); } } if (WalkState->OpInfo->Flags & AML_CREATE) { /* * Backup to beginning of CreateXXXfield declaration (1 for * Opcode) * * BodyLength is unknown until we parse the body */ Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); } if (Op->Common.AmlOpcode == AML_BANK_FIELD_OP) { /* * Backup to beginning of BankField declaration * * BodyLength is unknown until we parse the body */ Op->Named.Length = (UINT32) (ParserState->Aml - Op->Named.Data); } /* This op complete, notify the dispatcher */ if (WalkState->AscendingCallback != NULL) { WalkState->Op = Op; WalkState->Opcode = Op->Common.AmlOpcode; Status = WalkState->AscendingCallback (WalkState); Status = AcpiPsNextParseState (WalkState, Op, Status); if (Status == AE_CTRL_PENDING) { Status = AE_OK; } else if ((WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) && (ACPI_AML_EXCEPTION(Status) || Status == AE_ALREADY_EXISTS || Status == AE_NOT_FOUND)) { /* * ACPI_PARSE_MODULE_LEVEL flag means that we are currently * loading a table by executing it as a control method. * However, if we encounter an error while loading the table, * we need to keep trying to load the table rather than * aborting the table load (setting the status to AE_OK * continues the table load). If we get a failure at this * point, it means that the dispatcher got an error while * trying to execute the Op. */ Status = AE_OK; } } Status = AcpiPsCompleteOp (WalkState, &Op, Status); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } /* while ParserState->Aml */ Status = AcpiPsCompleteFinalOp (WalkState, Op, Status); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExOpcode_6A_0T_1R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_OPERAND_OBJECT *ReturnDesc = NULL; ACPI_STATUS Status = AE_OK; UINT64 Index; ACPI_OPERAND_OBJECT *ThisElement; ACPI_FUNCTION_TRACE_STR (ExOpcode_6A_0T_1R, AcpiPsGetOpcodeName (WalkState->Opcode)); switch (WalkState->Opcode) { case AML_MATCH_OP: /* * Match (SearchPkg[0], MatchOp1[1], MatchObj1[2], * MatchOp2[3], MatchObj2[4], StartIndex[5]) */ /* Validate both Match Term Operators (MTR, MEQ, etc.) */ if ((Operand[1]->Integer.Value > MAX_MATCH_OPERATOR) || (Operand[3]->Integer.Value > MAX_MATCH_OPERATOR)) { ACPI_ERROR ((AE_INFO, "Match operator out of range")); Status = AE_AML_OPERAND_VALUE; goto Cleanup; } /* Get the package StartIndex, validate against the package length */ Index = Operand[5]->Integer.Value; if (Index >= Operand[0]->Package.Count) { ACPI_ERROR ((AE_INFO, "Index (0x%8.8X%8.8X) beyond package end (0x%X)", ACPI_FORMAT_UINT64 (Index), Operand[0]->Package.Count)); Status = AE_AML_PACKAGE_LIMIT; goto Cleanup; } /* Create an integer for the return value */ /* Default return value is ACPI_UINT64_MAX if no match found */ ReturnDesc = AcpiUtCreateIntegerObject (ACPI_UINT64_MAX); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* * Examine each element until a match is found. Both match conditions * must be satisfied for a match to occur. Within the loop, * "continue" signifies that the current element does not match * and the next should be examined. * * Upon finding a match, the loop will terminate via "break" at * the bottom. If it terminates "normally", MatchValue will be * ACPI_UINT64_MAX (Ones) (its initial value) indicating that no * match was found. */ for ( ; Index < Operand[0]->Package.Count; Index++) { /* Get the current package element */ ThisElement = Operand[0]->Package.Elements[Index]; /* Treat any uninitialized (NULL) elements as non-matching */ if (!ThisElement) { continue; } /* * Both match conditions must be satisfied. Execution of a continue * (proceed to next iteration of enclosing for loop) signifies a * non-match. */ if (!AcpiExDoMatch ((UINT32) Operand[1]->Integer.Value, ThisElement, Operand[2])) { continue; } if (!AcpiExDoMatch ((UINT32) Operand[3]->Integer.Value, ThisElement, Operand[4])) { continue; } /* Match found: Index is the return value */ ReturnDesc->Integer.Value = Index; break; } break; case AML_LOAD_TABLE_OP: Status = AcpiExLoadTableOp (WalkState, &ReturnDesc); 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 AcpiExOpcode_3A_0T_0R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_SIGNAL_FATAL_INFO *Fatal; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE_STR (ExOpcode_3A_0T_0R, AcpiPsGetOpcodeName (WalkState->Opcode)); switch (WalkState->Opcode) { case AML_FATAL_OP: /* Fatal (FatalType FatalCode FatalArg) */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", (UINT32) Operand[0]->Integer.Value, (UINT32) Operand[1]->Integer.Value, (UINT32) Operand[2]->Integer.Value)); Fatal = ACPI_ALLOCATE (sizeof (ACPI_SIGNAL_FATAL_INFO)); if (Fatal) { Fatal->Type = (UINT32) Operand[0]->Integer.Value; Fatal->Code = (UINT32) Operand[1]->Integer.Value; Fatal->Argument = (UINT32) Operand[2]->Integer.Value; } /* Always signal the OS! */ Status = AcpiOsSignal (ACPI_SIGNAL_FATAL, Fatal); /* Might return while OS is shutting down, just continue */ ACPI_FREE (Fatal); goto Cleanup; case AML_EXTERNAL_OP: /* * If the interpreter sees this opcode, just ignore it. The External * op is intended for use by disassemblers in order to properly * disassemble control method invocations. The opcode or group of * opcodes should be surrounded by an "if (0)" clause to ensure that * AML interpreters never see the opcode. */ Status = AE_OK; goto Cleanup; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; goto Cleanup; } Cleanup: return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiDsEvalRegionOperands ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *OperandDesc; ACPI_NAMESPACE_NODE *Node; ACPI_PARSE_OBJECT *NextOp; ACPI_FUNCTION_TRACE_PTR (DsEvalRegionOperands, Op); /* * This is where we evaluate the address and length fields of the * OpRegion declaration */ Node = Op->Common.Node; /* NextOp points to the op that holds the SpaceID */ NextOp = Op->Common.Value.Arg; /* NextOp points to address op */ NextOp = NextOp->Common.Next; /* Evaluate/create the address and length operands */ Status = AcpiDsCreateOperands (WalkState, NextOp); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Resolve the length and address operands to numbers */ Status = AcpiExResolveOperands (Op->Common.AmlOpcode, ACPI_WALK_OPERANDS, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 1, "after AcpiExResolveOperands"); ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { return_ACPI_STATUS (AE_NOT_EXIST); } /* * Get the length operand and save it * (at Top of stack) */ OperandDesc = WalkState->Operands[WalkState->NumOperands - 1]; ObjDesc->Region.Length = (UINT32) OperandDesc->Integer.Value; AcpiUtRemoveReference (OperandDesc); /* * Get the address and save it * (at top of stack - 1) */ OperandDesc = WalkState->Operands[WalkState->NumOperands - 2]; ObjDesc->Region.Address = (ACPI_PHYSICAL_ADDRESS) OperandDesc->Integer.Value; AcpiUtRemoveReference (OperandDesc); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", ObjDesc, ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address), ObjDesc->Region.Length)); /* Now the address and length are valid for this opregion */ ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID; return_ACPI_STATUS (Status); }
void OptOptimizeNamePath ( ACPI_PARSE_OBJECT *Op, UINT32 Flags, ACPI_WALK_STATE *WalkState, char *AmlNameString, ACPI_NAMESPACE_NODE *TargetNode) { ACPI_STATUS Status; ACPI_BUFFER TargetPath; ACPI_BUFFER CurrentPath; ACPI_SIZE AmlNameStringLength; ACPI_NAMESPACE_NODE *CurrentNode; char *ExternalNameString; char *NewPath = NULL; ACPI_SIZE HowMuchShorter; ACPI_PARSE_OBJECT *NextOp; ACPI_FUNCTION_TRACE (OptOptimizeNamePath); /* This is an optional optimization */ if (!Gbl_ReferenceOptimizationFlag) { return_VOID; } /* Various required items */ if (!TargetNode || !WalkState || !AmlNameString || !Op->Common.Parent) { return_VOID; } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "PATH OPTIMIZE: Line %5d ParentOp [%12.12s] ThisOp [%12.12s] ", Op->Asl.LogicalLineNumber, AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), AcpiPsGetOpcodeName (Op->Common.AmlOpcode))); if (!(Flags & (AML_NAMED | AML_CREATE))) { if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION) { /* We don't want to fuss with actual name declaration nodes here */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "******* NAME DECLARATION\n")); return_VOID; } } /* * The original path must be longer than one NameSeg (4 chars) for there * to be any possibility that it can be optimized to a shorter string */ AmlNameStringLength = strlen (AmlNameString); if (AmlNameStringLength <= ACPI_NAME_SIZE) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAMESEG %4.4s\n", AmlNameString)); return_VOID; } /* * We need to obtain the node that represents the current scope -- where * we are right now in the namespace. We will compare this path * against the Namepath, looking for commonality. */ CurrentNode = AcpiGbl_RootNode; if (WalkState->ScopeInfo) { CurrentNode = WalkState->ScopeInfo->Scope.Node; } if (Flags & (AML_NAMED | AML_CREATE)) { /* This is the declaration of a new name */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAME\n")); /* * The node of interest is the parent of this node (the containing * scope). The actual namespace node may be up more than one level * of parse op or it may not exist at all (if we traverse back * up to the root.) */ NextOp = Op->Asl.Parent; while (NextOp && (!NextOp->Asl.Node)) { NextOp = NextOp->Asl.Parent; } if (NextOp && NextOp->Asl.Node) { CurrentNode = NextOp->Asl.Node; } else { CurrentNode = AcpiGbl_RootNode; } } else { /* This is a reference to an existing named object */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "REFERENCE\n")); } /* * Obtain the full paths to the two nodes that we are interested in * (Target and current namespace location) in external * format -- something we can easily manipulate */ TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER; Status = AcpiNsHandleToPathname (TargetNode, &TargetPath, FALSE); if (ACPI_FAILURE (Status)) { AslCoreSubsystemError (Op, Status, "Getting Target NamePath", ASL_NO_ABORT); return_VOID; } TargetPath.Length--; /* Subtract one for null terminator */ /* CurrentPath is the path to this scope (where we are in the namespace) */ CurrentPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER; Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath, FALSE); if (ACPI_FAILURE (Status)) { AslCoreSubsystemError (Op, Status, "Getting Current NamePath", ASL_NO_ABORT); return_VOID; } CurrentPath.Length--; /* Subtract one for null terminator */ /* Debug output only */ Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, AmlNameString, NULL, &ExternalNameString); if (ACPI_FAILURE (Status)) { AslCoreSubsystemError (Op, Status, "Externalizing NamePath", ASL_NO_ABORT); return_VOID; } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "CURRENT SCOPE: (%2u) %-37s FULL PATH TO NAME: (%2u) %-32s ACTUAL AML:%-32s\n", (UINT32) CurrentPath.Length, (char *) CurrentPath.Pointer, (UINT32) TargetPath.Length, (char *) TargetPath.Pointer, ExternalNameString)); ACPI_FREE (ExternalNameString); /* * Attempt an optmization depending on the type of namepath */ if (Flags & (AML_NAMED | AML_CREATE)) { /* * This is a named opcode and the namepath is a name declaration, not * a reference. */ Status = OptOptimizeNameDeclaration (Op, WalkState, CurrentNode, TargetNode, AmlNameString, &NewPath); if (ACPI_FAILURE (Status)) { /* * 2) now attempt to * optimize the namestring with carats (up-arrow) */ Status = OptBuildShortestPath (Op, WalkState, CurrentNode, TargetNode, &CurrentPath, &TargetPath, AmlNameStringLength, 1, &NewPath); } } else { /* * This is a reference to an existing named object * * 1) Check if search-to-root can be utilized using the last * NameSeg of the NamePath */ Status = OptSearchToRoot (Op, WalkState, CurrentNode, TargetNode, &TargetPath, &NewPath); if (ACPI_FAILURE (Status)) { /* * 2) Search-to-root could not be used, now attempt to * optimize the namestring with carats (up-arrow) */ Status = OptBuildShortestPath (Op, WalkState, CurrentNode, TargetNode, &CurrentPath, &TargetPath, AmlNameStringLength, 0, &NewPath); } } /* * Success from above indicates that the NamePath was successfully * optimized. We need to update the parse op with the new name */ if (ACPI_SUCCESS (Status)) { HowMuchShorter = (AmlNameStringLength - strlen (NewPath)); OptTotal += HowMuchShorter; ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " REDUCED BY %2u (TOTAL SAVED %2u)", (UINT32) HowMuchShorter, OptTotal)); if (Flags & AML_NAMED) { if (Op->Asl.AmlOpcode == AML_ALIAS_OP) { /* * ALIAS is the only oddball opcode, the name declaration * (alias name) is the second operand */ Op->Asl.Child->Asl.Next->Asl.Value.String = NewPath; Op->Asl.Child->Asl.Next->Asl.AmlLength = strlen (NewPath); } else { Op->Asl.Child->Asl.Value.String = NewPath; Op->Asl.Child->Asl.AmlLength = strlen (NewPath); } } else if (Flags & AML_CREATE) { /* Name must appear as the last parameter */ NextOp = Op->Asl.Child; while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)) { NextOp = NextOp->Asl.Next; } /* Update the parse node with the new NamePath */ NextOp->Asl.Value.String = NewPath; NextOp->Asl.AmlLength = strlen (NewPath); } else { /* Update the parse node with the new NamePath */ Op->Asl.Value.String = NewPath; Op->Asl.AmlLength = strlen (NewPath); } } else { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ALREADY OPTIMAL")); } /* Cleanup path buffers */ ACPI_FREE (TargetPath.Pointer); ACPI_FREE (CurrentPath.Pointer); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "\n")); return_VOID; }
ACPI_STATUS AcpiDsEvalTableRegionOperands ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT **Operand; ACPI_NAMESPACE_NODE *Node; ACPI_PARSE_OBJECT *NextOp; ACPI_NATIVE_UINT TableIndex; ACPI_TABLE_HEADER *Table; ACPI_FUNCTION_TRACE_PTR (DsEvalTableRegionOperands, Op); /* * This is where we evaluate the SignatureString and OemIDString * and OemTableIDString of the DataTableRegion declaration */ Node = Op->Common.Node; /* NextOp points to SignatureString op */ NextOp = Op->Common.Value.Arg; /* * Evaluate/create the SignatureString and OemIDString * and OemTableIDString operands */ Status = AcpiDsCreateOperands (WalkState, NextOp); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Resolve the SignatureString and OemIDString * and OemTableIDString operands */ Status = AcpiExResolveOperands (Op->Common.AmlOpcode, ACPI_WALK_OPERANDS, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE, AcpiPsGetOpcodeName (Op->Common.AmlOpcode), 1, "after AcpiExResolveOperands"); Operand = &WalkState->Operands[0]; /* Find the ACPI table */ Status = AcpiTbFindTable (Operand[0]->String.Pointer, Operand[1]->String.Pointer, Operand[2]->String.Pointer, &TableIndex); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } AcpiUtRemoveReference (Operand[0]); AcpiUtRemoveReference (Operand[1]); AcpiUtRemoveReference (Operand[2]); Status = AcpiGetTableByIndex (TableIndex, &Table); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { return_ACPI_STATUS (AE_NOT_EXIST); } ObjDesc->Region.Address = (ACPI_PHYSICAL_ADDRESS) ACPI_TO_INTEGER (Table); ObjDesc->Region.Length = Table->Length; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", ObjDesc, ACPI_FORMAT_NATIVE_UINT (ObjDesc->Region.Address), ObjDesc->Region.Length)); /* Now the address and length are valid for this opregion */ ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID; return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExOpcode_2A_2T_1R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_OPERAND_OBJECT *ReturnDesc1 = NULL; ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL; ACPI_STATUS Status; ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_2T_1R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Execute the opcode */ switch (WalkState->Opcode) { case AML_DIVIDE_OP: /* Divide (Dividend, Divisor, RemainderResult QuotientResult) */ ReturnDesc1 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!ReturnDesc1) { Status = AE_NO_MEMORY; goto Cleanup; } ReturnDesc2 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!ReturnDesc2) { Status = AE_NO_MEMORY; goto Cleanup; } /* Quotient to ReturnDesc1, remainder to ReturnDesc2 */ Status = AcpiUtDivide (Operand[0]->Integer.Value, Operand[1]->Integer.Value, &ReturnDesc1->Integer.Value, &ReturnDesc2->Integer.Value); if (ACPI_FAILURE (Status)) { goto Cleanup; } break; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; goto Cleanup; } /* Store the results to the target reference operands */ Status = AcpiExStore (ReturnDesc2, Operand[2], WalkState); if (ACPI_FAILURE (Status)) { goto Cleanup; } Status = AcpiExStore (ReturnDesc1, Operand[3], WalkState); if (ACPI_FAILURE (Status)) { goto Cleanup; } Cleanup: /* * Since the remainder is not returned indirectly, remove a reference to * it. Only the quotient is returned indirectly. */ AcpiUtRemoveReference (ReturnDesc2); if (ACPI_FAILURE (Status)) { /* Delete the return object */ AcpiUtRemoveReference (ReturnDesc1); } /* Save return object (the remainder) on success */ else { WalkState->ResultObj = ReturnDesc1; } 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 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 AcpiExOpcode_2A_0T_1R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_OPERAND_OBJECT *ReturnDesc = NULL; ACPI_STATUS Status = AE_OK; BOOLEAN LogicalResult = FALSE; ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_1R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Create the internal return object */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* Execute the Opcode */ if (WalkState->OpInfo->Flags & AML_LOGICAL_NUMERIC) { /* LogicalOp (Operand0, Operand1) */ Status = AcpiExDoLogicalNumericOp (WalkState->Opcode, Operand[0]->Integer.Value, Operand[1]->Integer.Value, &LogicalResult); goto StoreLogicalResult; } else if (WalkState->OpInfo->Flags & AML_LOGICAL) { /* LogicalOp (Operand0, Operand1) */ Status = AcpiExDoLogicalOp (WalkState->Opcode, Operand[0], Operand[1], &LogicalResult); goto StoreLogicalResult; } switch (WalkState->Opcode) { case AML_ACQUIRE_OP: /* Acquire (MutexObject, Timeout) */ Status = AcpiExAcquireMutex (Operand[1], Operand[0], WalkState); if (Status == AE_TIME) { LogicalResult = TRUE; /* TRUE = Acquire timed out */ Status = AE_OK; } break; case AML_WAIT_OP: /* Wait (EventObject, Timeout) */ Status = AcpiExSystemWaitEvent (Operand[1], Operand[0]); if (Status == AE_TIME) { LogicalResult = TRUE; /* TRUE, Wait timed out */ Status = AE_OK; } break; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; goto Cleanup; } StoreLogicalResult: /* * Set return value to according to LogicalResult. logical TRUE (all ones) * Default is FALSE (zero) */ if (LogicalResult) { ReturnDesc->Integer.Value = ACPI_UINT64_MAX; } 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); }
static ACPI_STATUS AeExceptionHandler ( ACPI_STATUS AmlStatus, ACPI_NAME Name, UINT16 Opcode, UINT32 AmlOffset, void *Context) { ACPI_STATUS NewAmlStatus = AmlStatus; ACPI_STATUS Status; ACPI_BUFFER ReturnObj; ACPI_OBJECT_LIST ArgList; ACPI_OBJECT Arg[3]; const char *Exception; Exception = AcpiFormatException (AmlStatus); AcpiOsPrintf ("[AcpiExec] Exception %s during execution ", Exception); if (Name) { AcpiOsPrintf ("of method [%4.4s]", (char *) &Name); } else { AcpiOsPrintf ("at module level (table load)"); } AcpiOsPrintf (" Opcode [%s] @%X\n", AcpiPsGetOpcodeName (Opcode), AmlOffset); /* * Invoke the _ERR method if present * * Setup parameter object */ ArgList.Count = 3; ArgList.Pointer = Arg; Arg[0].Type = ACPI_TYPE_INTEGER; Arg[0].Integer.Value = AmlStatus; Arg[1].Type = ACPI_TYPE_STRING; Arg[1].String.Pointer = ACPI_CAST_PTR (char, Exception); Arg[1].String.Length = ACPI_STRLEN (Exception); Arg[2].Type = ACPI_TYPE_INTEGER; Arg[2].Integer.Value = AcpiOsGetThreadId(); /* Setup return buffer */ ReturnObj.Pointer = NULL; ReturnObj.Length = ACPI_ALLOCATE_BUFFER; Status = AcpiEvaluateObject (NULL, "\\_ERR", &ArgList, &ReturnObj); if (ACPI_SUCCESS (Status)) { if (ReturnObj.Pointer) { /* Override original status */ NewAmlStatus = (ACPI_STATUS) ((ACPI_OBJECT *) ReturnObj.Pointer)->Integer.Value; /* Free a buffer created via ACPI_ALLOCATE_BUFFER */ AcpiOsFree (ReturnObj.Pointer); } } else if (Status != AE_NOT_FOUND) { AcpiOsPrintf ("[AcpiExec] Could not execute _ERR method, %s\n", AcpiFormatException (Status)); } /* Global override */ if (AcpiGbl_IgnoreErrors) { NewAmlStatus = AE_OK; } if (NewAmlStatus != AmlStatus) { AcpiOsPrintf ("[AcpiExec] Exception override, new status %s\n", AcpiFormatException (NewAmlStatus)); } return (NewAmlStatus); }
static ACPI_STATUS AcpiDmDumpDescending ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_OP_WALK_INFO *Info = Context; const ACPI_OPCODE_INFO *OpInfo; char *Path; if (!Op) { return (AE_OK); } OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); Info->Count++; /* Most of the information (count, level, name) here */ AcpiOsPrintf ("% 5d [%2.2d] ", Info->Count, Level); AcpiDmIndent (Level); AcpiOsPrintf ("%-28s", AcpiPsGetOpcodeName (Op->Common.AmlOpcode)); /* Extra info is helpful */ switch (Op->Common.AmlOpcode) { case AML_BYTE_OP: case AML_WORD_OP: case AML_DWORD_OP: AcpiOsPrintf ("%X", (UINT32) Op->Common.Value.Integer); break; case AML_INT_NAMEPATH_OP: if (Op->Common.Value.String) { AcpiNsExternalizeName (ACPI_UINT32_MAX, Op->Common.Value.String, NULL, &Path); AcpiOsPrintf ("%s %p", Path, Op->Common.Node); ACPI_FREE (Path); } else { AcpiOsPrintf ("[NULL]"); } break; case AML_NAME_OP: case AML_METHOD_OP: case AML_DEVICE_OP: case AML_INT_NAMEDFIELD_OP: AcpiOsPrintf ("%4.4s", &Op->Named.Name); break; default: break; } AcpiOsPrintf ("\n"); return (AE_OK); }
ACPI_STATUS AcpiDsEvalBufferFieldOperands ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_NAMESPACE_NODE *Node; ACPI_PARSE_OBJECT *NextOp; ACPI_FUNCTION_TRACE_PTR (DsEvalBufferFieldOperands, Op); /* * This is where we evaluate the address and length fields of the * CreateXxxField declaration */ Node = Op->Common.Node; /* NextOp points to the op that holds the Buffer */ NextOp = Op->Common.Value.Arg; /* Evaluate/create the address and length operands */ Status = AcpiDsCreateOperands (WalkState, NextOp); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { return_ACPI_STATUS (AE_NOT_EXIST); } /* Resolve the operands */ Status = AcpiExResolveOperands (Op->Common.AmlOpcode, ACPI_WALK_OPERANDS, WalkState); if (ACPI_FAILURE (Status)) { ACPI_ERROR ((AE_INFO, "(%s) bad operand(s), status 0x%X", AcpiPsGetOpcodeName (Op->Common.AmlOpcode), Status)); return_ACPI_STATUS (Status); } /* Initialize the Buffer Field */ if (Op->Common.AmlOpcode == AML_CREATE_FIELD_OP) { /* NOTE: Slightly different operands for this opcode */ Status = AcpiDsInitBufferField (Op->Common.AmlOpcode, ObjDesc, WalkState->Operands[0], WalkState->Operands[1], WalkState->Operands[2], WalkState->Operands[3]); } else { /* All other, CreateXxxField opcodes */ Status = AcpiDsInitBufferField (Op->Common.AmlOpcode, ObjDesc, WalkState->Operands[0], WalkState->Operands[1], NULL, WalkState->Operands[2]); } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiNsDumpOneObject ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_WALK_INFO *Info = (ACPI_WALK_INFO *) Context; ACPI_NAMESPACE_NODE *ThisNode; ACPI_OPERAND_OBJECT *ObjDesc = NULL; ACPI_OBJECT_TYPE ObjType; ACPI_OBJECT_TYPE Type; UINT32 BytesToDump; UINT32 DbgLevel; UINT32 i; ACPI_FUNCTION_NAME ("NsDumpOneObject"); /* Is output enabled? */ if (!(AcpiDbgLevel & Info->DebugLevel)) { return (AE_OK); } if (!ObjHandle) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Null object handle\n")); return (AE_OK); } ThisNode = AcpiNsMapHandleToNode (ObjHandle); Type = ThisNode->Type; /* Check if the owner matches */ if ((Info->OwnerId != ACPI_UINT32_MAX) && (Info->OwnerId != ThisNode->OwnerId)) { return (AE_OK); } /* Indent the object according to the level */ AcpiOsPrintf ("%2d%*s", (UINT32) Level - 1, (int) Level * 2, " "); /* Check the node type and name */ if (Type > ACPI_TYPE_LOCAL_MAX) { ACPI_REPORT_WARNING (("Invalid ACPI Type %08X\n", Type)); } if (!AcpiUtValidAcpiName (ThisNode->Name.Integer)) { ACPI_REPORT_WARNING (("Invalid ACPI Name %08X\n", ThisNode->Name.Integer)); } /* * Now we can print out the pertinent information */ AcpiOsPrintf ("%4.4s %-12s %p ", ThisNode->Name.Ascii, AcpiUtGetTypeName (Type), ThisNode); DbgLevel = AcpiDbgLevel; AcpiDbgLevel = 0; ObjDesc = AcpiNsGetAttachedObject (ThisNode); AcpiDbgLevel = DbgLevel; switch (Info->DisplayType) { case ACPI_DISPLAY_SUMMARY: if (!ObjDesc) { /* No attached object, we are done */ AcpiOsPrintf ("\n"); return (AE_OK); } switch (Type) { case ACPI_TYPE_PROCESSOR: AcpiOsPrintf ("ID %X Len %.4X Addr %p\n", ObjDesc->Processor.ProcId, ObjDesc->Processor.Length, (char *) ObjDesc->Processor.Address); break; case ACPI_TYPE_DEVICE: AcpiOsPrintf ("Notify object: %p", ObjDesc); break; case ACPI_TYPE_METHOD: AcpiOsPrintf ("Args %X Len %.4X Aml %p\n", (UINT32) ObjDesc->Method.ParamCount, ObjDesc->Method.AmlLength, ObjDesc->Method.AmlStart); break; case ACPI_TYPE_INTEGER: AcpiOsPrintf ("= %8.8X%8.8X\n", ACPI_HIDWORD (ObjDesc->Integer.Value), ACPI_LODWORD (ObjDesc->Integer.Value)); break; case ACPI_TYPE_PACKAGE: if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) { AcpiOsPrintf ("Elements %.2X\n", ObjDesc->Package.Count); } else { AcpiOsPrintf ("[Length not yet evaluated]\n"); } break; case ACPI_TYPE_BUFFER: if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) { AcpiOsPrintf ("Len %.2X", ObjDesc->Buffer.Length); /* Dump some of the buffer */ if (ObjDesc->Buffer.Length > 0) { AcpiOsPrintf (" ="); for (i = 0; (i < ObjDesc->Buffer.Length && i < 12); i++) { AcpiOsPrintf (" %.2hX", ObjDesc->Buffer.Pointer[i]); } } AcpiOsPrintf ("\n"); } else { AcpiOsPrintf ("[Length not yet evaluated]\n"); } break; case ACPI_TYPE_STRING: AcpiOsPrintf ("Len %.2X ", ObjDesc->String.Length); AcpiUtPrintString (ObjDesc->String.Pointer, 32); AcpiOsPrintf ("\n"); break; case ACPI_TYPE_REGION: AcpiOsPrintf ("[%s]", AcpiUtGetRegionName (ObjDesc->Region.SpaceId)); if (ObjDesc->Region.Flags & AOPOBJ_DATA_VALID) { AcpiOsPrintf (" Addr %8.8X%8.8X Len %.4X\n", ACPI_HIDWORD (ObjDesc->Region.Address), ACPI_LODWORD (ObjDesc->Region.Address), ObjDesc->Region.Length); } else { AcpiOsPrintf (" [Address/Length not yet evaluated]\n"); } break; case ACPI_TYPE_LOCAL_REFERENCE: AcpiOsPrintf ("[%s]\n", AcpiPsGetOpcodeName (ObjDesc->Reference.Opcode)); break; case ACPI_TYPE_BUFFER_FIELD: if (ObjDesc->BufferField.BufferObj && ObjDesc->BufferField.BufferObj->Buffer.Node) { AcpiOsPrintf ("Buf [%4.4s]", ObjDesc->BufferField.BufferObj->Buffer.Node->Name.Ascii); } break; case ACPI_TYPE_LOCAL_REGION_FIELD: AcpiOsPrintf ("Rgn [%4.4s]", ObjDesc->CommonField.RegionObj->Region.Node->Name.Ascii); break; case ACPI_TYPE_LOCAL_BANK_FIELD: AcpiOsPrintf ("Rgn [%4.4s] Bnk [%4.4s]", ObjDesc->CommonField.RegionObj->Region.Node->Name.Ascii, ObjDesc->BankField.BankObj->CommonField.Node->Name.Ascii); break; case ACPI_TYPE_LOCAL_INDEX_FIELD: AcpiOsPrintf ("Idx [%4.4s] Dat [%4.4s]", ObjDesc->IndexField.IndexObj->CommonField.Node->Name.Ascii, ObjDesc->IndexField.DataObj->CommonField.Node->Name.Ascii); break; case ACPI_TYPE_LOCAL_ALIAS: AcpiOsPrintf ("Target %4.4s (%p)\n", ((ACPI_NAMESPACE_NODE *) ObjDesc)->Name.Ascii, ObjDesc); break; default: AcpiOsPrintf ("Object %p\n", ObjDesc); break; } /* Common field handling */ switch (Type) { case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: AcpiOsPrintf (" Off %.2X Len %.2X Acc %.2hd\n", (ObjDesc->CommonField.BaseByteOffset * 8) + ObjDesc->CommonField.StartFieldBitOffset, ObjDesc->CommonField.BitLength, ObjDesc->CommonField.AccessByteWidth); break; default: break; } break; case ACPI_DISPLAY_OBJECTS: AcpiOsPrintf ("O:%p", ObjDesc); if (!ObjDesc) { /* No attached object, we are done */ AcpiOsPrintf ("\n"); return (AE_OK); } AcpiOsPrintf ("(R%d)", ObjDesc->Common.ReferenceCount); switch (Type) { case ACPI_TYPE_METHOD: /* Name is a Method and its AML offset/length are set */ AcpiOsPrintf (" M:%p-%X\n", ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength); break; case ACPI_TYPE_INTEGER: AcpiOsPrintf (" N:%X%X\n", ACPI_HIDWORD(ObjDesc->Integer.Value), ACPI_LODWORD(ObjDesc->Integer.Value)); break; case ACPI_TYPE_STRING: AcpiOsPrintf (" S:%p-%X\n", ObjDesc->String.Pointer, ObjDesc->String.Length); break; case ACPI_TYPE_BUFFER: AcpiOsPrintf (" B:%p-%X\n", ObjDesc->Buffer.Pointer, ObjDesc->Buffer.Length); break; default: AcpiOsPrintf ("\n"); break; } break; default: AcpiOsPrintf ("\n"); break; } /* If debug turned off, done */ if (!(AcpiDbgLevel & ACPI_LV_VALUES)) { return (AE_OK); } /* If there is an attached object, display it */ DbgLevel = AcpiDbgLevel; AcpiDbgLevel = 0; ObjDesc = AcpiNsGetAttachedObject (ThisNode); AcpiDbgLevel = DbgLevel; /* Dump attached objects */ while (ObjDesc) { ObjType = ACPI_TYPE_INVALID; AcpiOsPrintf (" Attached Object %p: ", ObjDesc); /* Decode the type of attached object and dump the contents */ switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) { case ACPI_DESC_TYPE_NAMED: AcpiOsPrintf ("(Ptr to Node)\n"); BytesToDump = sizeof (ACPI_NAMESPACE_NODE); break; case ACPI_DESC_TYPE_OPERAND: ObjType = ACPI_GET_OBJECT_TYPE (ObjDesc); if (ObjType > ACPI_TYPE_LOCAL_MAX) { AcpiOsPrintf ("(Ptr to ACPI Object type %X [UNKNOWN])\n", ObjType); BytesToDump = 32; } else { AcpiOsPrintf ("(Ptr to ACPI Object type %s, %X)\n", AcpiUtGetTypeName (ObjType), ObjType); BytesToDump = sizeof (ACPI_OPERAND_OBJECT); } break; default: AcpiOsPrintf ("(String or Buffer ptr - not an object descriptor)\n"); BytesToDump = 16; break; } ACPI_DUMP_BUFFER (ObjDesc, BytesToDump); /* If value is NOT an internal object, we are done */ if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) { goto Cleanup; } /* * Valid object, get the pointer to next level, if any */ switch (ObjType) { case ACPI_TYPE_STRING: ObjDesc = (void *) ObjDesc->String.Pointer; break; case ACPI_TYPE_BUFFER: ObjDesc = (void *) ObjDesc->Buffer.Pointer; break; case ACPI_TYPE_BUFFER_FIELD: ObjDesc = (ACPI_OPERAND_OBJECT *) ObjDesc->BufferField.BufferObj; break; case ACPI_TYPE_PACKAGE: ObjDesc = (void *) ObjDesc->Package.Elements; break; case ACPI_TYPE_METHOD: ObjDesc = (void *) ObjDesc->Method.AmlStart; break; case ACPI_TYPE_LOCAL_REGION_FIELD: ObjDesc = (void *) ObjDesc->Field.RegionObj; break; case ACPI_TYPE_LOCAL_BANK_FIELD: ObjDesc = (void *) ObjDesc->BankField.RegionObj; break; case ACPI_TYPE_LOCAL_INDEX_FIELD: ObjDesc = (void *) ObjDesc->IndexField.IndexObj; break; default: goto Cleanup; } ObjType = ACPI_TYPE_INVALID; /* Terminate loop after next pass */ } Cleanup: AcpiOsPrintf ("\n"); return (AE_OK); }
BOOLEAN AcpiDsIsResultUsed ( ACPI_PARSE_OBJECT *Op, ACPI_WALK_STATE *WalkState) { const ACPI_OPCODE_INFO *ParentInfo; ACPI_FUNCTION_TRACE_PTR (DsIsResultUsed, Op); /* Must have both an Op and a Result Object */ if (!Op) { ACPI_ERROR ((AE_INFO, "Null Op")); return_UINT8 (TRUE); } /* * We know that this operator is not a * Return() operator (would not come here.) The following code is the * optional support for a so-called "implicit return". Some AML code * assumes that the last value of the method is "implicitly" returned * to the caller. Just save the last result as the return value. * NOTE: this is optional because the ASL language does not actually * support this behavior. */ (void) AcpiDsDoImplicitReturn (WalkState->ResultObj, WalkState, TRUE); /* * Now determine if the parent will use the result * * If there is no parent, or the parent is a ScopeOp, we are executing * at the method level. An executing method typically has no parent, * since each method is parsed separately. A method invoked externally * via ExecuteControlMethod has a ScopeOp as the parent. */ if ((!Op->Common.Parent) || (Op->Common.Parent->Common.AmlOpcode == AML_SCOPE_OP)) { /* No parent, the return value cannot possibly be used */ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "At Method level, result of [%s] not used\n", AcpiPsGetOpcodeName (Op->Common.AmlOpcode))); return_UINT8 (FALSE); } /* Get info on the parent. The RootOp is AML_SCOPE */ ParentInfo = AcpiPsGetOpcodeInfo (Op->Common.Parent->Common.AmlOpcode); if (ParentInfo->Class == AML_CLASS_UNKNOWN) { ACPI_ERROR ((AE_INFO, "Unknown parent opcode Op=%p", Op)); return_UINT8 (FALSE); } /* * Decide what to do with the result based on the parent. If * the parent opcode will not use the result, delete the object. * Otherwise leave it as is, it will be deleted when it is used * as an operand later. */ switch (ParentInfo->Class) { case AML_CLASS_CONTROL: switch (Op->Common.Parent->Common.AmlOpcode) { case AML_RETURN_OP: /* Never delete the return value associated with a return opcode */ goto ResultUsed; case AML_IF_OP: case AML_WHILE_OP: /* * If we are executing the predicate AND this is the predicate op, * we will use the return value */ if ((WalkState->ControlState->Common.State == ACPI_CONTROL_PREDICATE_EXECUTING) && (WalkState->ControlState->Control.PredicateOp == Op)) { goto ResultUsed; } break; default: /* Ignore other control opcodes */ break; } /* The general control opcode returns no result */ goto ResultNotUsed; case AML_CLASS_CREATE: /* * These opcodes allow TermArg(s) as operands and therefore * the operands can be method calls. The result is used. */ goto ResultUsed; case AML_CLASS_NAMED_OBJECT: if ((Op->Common.Parent->Common.AmlOpcode == AML_REGION_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_DATA_REGION_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_BUFFER_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_INT_EVAL_SUBTREE_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_BANK_FIELD_OP)) { /* * These opcodes allow TermArg(s) as operands and therefore * the operands can be method calls. The result is used. */ goto ResultUsed; } goto ResultNotUsed; default: /* * In all other cases. the parent will actually use the return * object, so keep it. */ goto ResultUsed; } ResultUsed: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] used by Parent [%s] Op=%p\n", AcpiPsGetOpcodeName (Op->Common.AmlOpcode), AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); return_UINT8 (TRUE); ResultNotUsed: ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] not used by Parent [%s] Op=%p\n", AcpiPsGetOpcodeName (Op->Common.AmlOpcode), AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode), Op)); return_UINT8 (FALSE); }
void AcpiDmDisplayInternalObject ( ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState) { UINT8 Type; AcpiOsPrintf ("%p ", ObjDesc); if (!ObjDesc) { AcpiOsPrintf ("<NullObj>\n"); return; } /* Decode the object type */ switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) { case ACPI_DESC_TYPE_PARSER: AcpiOsPrintf ("<Parser> "); break; case ACPI_DESC_TYPE_NAMED: AcpiDmDecodeNode ((ACPI_NAMESPACE_NODE *) ObjDesc); break; case ACPI_DESC_TYPE_OPERAND: Type = ACPI_GET_OBJECT_TYPE (ObjDesc); if (Type > ACPI_TYPE_LOCAL_MAX) { AcpiOsPrintf (" Type %X [Invalid Type]", (UINT32) Type); return; } /* Decode the ACPI object type */ switch (ACPI_GET_OBJECT_TYPE (ObjDesc)) { case ACPI_TYPE_LOCAL_REFERENCE: switch (ObjDesc->Reference.Opcode) { case AML_LOCAL_OP: AcpiOsPrintf ("[Local%d] ", ObjDesc->Reference.Offset); if (WalkState) { ObjDesc = WalkState->LocalVariables[ObjDesc->Reference.Offset].Object; AcpiOsPrintf ("%p", ObjDesc); AcpiDmDecodeInternalObject (ObjDesc); } break; case AML_ARG_OP: AcpiOsPrintf ("[Arg%d] ", ObjDesc->Reference.Offset); if (WalkState) { ObjDesc = WalkState->Arguments[ObjDesc->Reference.Offset].Object; AcpiOsPrintf ("%p", ObjDesc); AcpiDmDecodeInternalObject (ObjDesc); } break; case AML_DEBUG_OP: AcpiOsPrintf ("[Debug] "); break; case AML_INDEX_OP: AcpiOsPrintf ("[Index] "); switch (ObjDesc->Reference.TargetType) { case ACPI_TYPE_BUFFER_FIELD: AcpiOsPrintf ("%p", ObjDesc->Reference.Object); AcpiDmDecodeInternalObject (ObjDesc->Reference.Object); break; case ACPI_TYPE_PACKAGE: AcpiOsPrintf ("%p", ObjDesc->Reference.Where); if (!ObjDesc->Reference.Where) { AcpiOsPrintf (" Uninitialized WHERE ptr"); } else { AcpiDmDecodeInternalObject (*(ObjDesc->Reference.Where)); } break; default: AcpiOsPrintf ("Unknown index target type"); break; } break; case AML_LOAD_OP: AcpiOsPrintf ("[DdbHandle] "); break; case AML_REF_OF_OP: AcpiOsPrintf ("[RefOf] "); if (!ObjDesc->Reference.Object) { AcpiOsPrintf ("Uninitialized reference subobject ptr"); break; } /* Reference can be to a Node or an Operand object */ switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc->Reference.Object)) { case ACPI_DESC_TYPE_NAMED: AcpiDmDecodeNode (ObjDesc->Reference.Object); break; case ACPI_DESC_TYPE_OPERAND: AcpiDmDecodeInternalObject (ObjDesc->Reference.Object); break; default: break; } break; default: AcpiOsPrintf ("Unknown Reference opcode %X (%s)\n", ObjDesc->Reference.Opcode, AcpiPsGetOpcodeName (ObjDesc->Reference.Opcode)); break; } break; default: AcpiOsPrintf ("<Obj> "); AcpiDmDecodeInternalObject (ObjDesc); break; } break; default: AcpiOsPrintf ("<Not a valid ACPI Object Descriptor> [%s]", AcpiUtGetDescriptorName (ObjDesc)); break; } AcpiOsPrintf ("\n"); }