ACPI_STATUS AcpiUtCopyIobjectToIobject ( ACPI_OPERAND_OBJECT *SourceDesc, ACPI_OPERAND_OBJECT **DestDesc, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE (UtCopyIobjectToIobject); /* Create the top level object */ *DestDesc = AcpiUtCreateInternalObject (ACPI_GET_OBJECT_TYPE (SourceDesc)); if (!*DestDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Copy the object and possible subobjects */ if (ACPI_GET_OBJECT_TYPE (SourceDesc) == ACPI_TYPE_PACKAGE) { Status = AcpiUtCopyIpackageToIpackage (SourceDesc, *DestDesc, WalkState); } else { Status = AcpiUtCopySimpleObject (SourceDesc, *DestDesc); } return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiExAddTable ( UINT32 TableIndex, ACPI_OPERAND_OBJECT **DdbHandle) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_FUNCTION_TRACE (ExAddTable); /* Create an object to be the table handle */ ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Init the table handle */ ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID; ObjDesc->Reference.Class = ACPI_REFCLASS_TABLE; ObjDesc->Reference.Value = TableIndex; *DdbHandle = ObjDesc; return_ACPI_STATUS (AE_OK); }
static ACPI_STATUS AcpiDsCreateMethodMutex ( ACPI_OPERAND_OBJECT *MethodDesc) { ACPI_OPERAND_OBJECT *MutexDesc; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (DsCreateMethodMutex); /* Create the new mutex object */ MutexDesc = AcpiUtCreateInternalObject (ACPI_TYPE_MUTEX); if (!MutexDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Create the actual OS Mutex */ Status = AcpiOsCreateMutex (&MutexDesc->Mutex.OsMutex); if (ACPI_FAILURE (Status)) { AcpiUtDeleteObjectDesc (MutexDesc); return_ACPI_STATUS (Status); } MutexDesc->Mutex.SyncLevel = MethodDesc->Method.SyncLevel; MethodDesc->Method.Mutex = MutexDesc; return_ACPI_STATUS (AE_OK); }
ACPI_OPERAND_OBJECT * AcpiUtCreatePackageObject ( UINT32 Count) { ACPI_OPERAND_OBJECT *PackageDesc; ACPI_OPERAND_OBJECT **PackageElements; ACPI_FUNCTION_TRACE_U32 (UtCreatePackageObject, Count); /* Create a new Package object */ PackageDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE); if (!PackageDesc) { return_PTR (NULL); } /* * Create the element array. Count+1 allows the array to be null * terminated. */ PackageElements = ACPI_ALLOCATE_ZEROED ( ((ACPI_SIZE) Count + 1) * sizeof (void *)); if (!PackageElements) { ACPI_FREE (PackageDesc); return_PTR (NULL); } PackageDesc->Package.Count = Count; PackageDesc->Package.Elements = PackageElements; return_PTR (PackageDesc); }
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 AcpiDsBuildInternalObject ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op, ACPI_OPERAND_OBJECT **ObjDescPtr) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_STATUS Status; ACPI_FUNCTION_TRACE ("DsBuildInternalObject"); *ObjDescPtr = NULL; if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) { /* * This is an named object reference. If this name was * previously looked up in the namespace, it was stored in this op. * Otherwise, go ahead and look it up now */ if (!Op->Common.Node) { Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Common.Value.String, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, (ACPI_NAMESPACE_NODE **) &(Op->Common.Node)); if (ACPI_FAILURE (Status)) { ACPI_REPORT_NSERROR (Op->Common.Value.String, Status); return_ACPI_STATUS (Status); } } } /* Create and init the internal ACPI object */ ObjDesc = AcpiUtCreateInternalObject ((AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } Status = AcpiDsInitObjectFromOp (WalkState, Op, Op->Common.AmlOpcode, &ObjDesc); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); return_ACPI_STATUS (Status); } *ObjDescPtr = ObjDesc; return_ACPI_STATUS (AE_OK); }
static void AcpiPsLinkModuleCode ( UINT8 *AmlStart, UINT32 AmlLength, ACPI_OWNER_ID OwnerId) { ACPI_OPERAND_OBJECT *Prev; ACPI_OPERAND_OBJECT *Next; ACPI_OPERAND_OBJECT *MethodObj; /* Get the tail of the list */ Prev = Next = AcpiGbl_ModuleCodeList; while (Next) { Prev = Next; Next = Next->Method.Mutex; } /* * Insert the module level code into the list. Merge it if it is * adjacent to the previous element. */ if (!Prev || ((Prev->Method.AmlStart + Prev->Method.AmlLength) != AmlStart)) { /* Create, initialize, and link a new temporary method object */ MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); if (!MethodObj) { return; } MethodObj->Method.AmlStart = AmlStart; MethodObj->Method.AmlLength = AmlLength; MethodObj->Method.OwnerId = OwnerId; MethodObj->Method.Flags |= AOPOBJ_MODULE_LEVEL; if (!Prev) { AcpiGbl_ModuleCodeList = MethodObj; } else { Prev->Method.Mutex = MethodObj; } } else { Prev->Method.AmlLength += AmlLength; } }
ACPI_STATUS AcpiNsAttachData ( ACPI_NAMESPACE_NODE *Node, ACPI_OBJECT_HANDLER Handler, void *Data) { ACPI_OPERAND_OBJECT *PrevObjDesc; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *DataDesc; /* We only allow one attachment per handler */ PrevObjDesc = NULL; ObjDesc = Node->Object; while (ObjDesc) { if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA) && (ObjDesc->Data.Handler == Handler)) { return (AE_ALREADY_EXISTS); } PrevObjDesc = ObjDesc; ObjDesc = ObjDesc->Common.NextObject; } /* Create an internal object for the data */ DataDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_DATA); if (!DataDesc) { return (AE_NO_MEMORY); } DataDesc->Data.Handler = Handler; DataDesc->Data.Pointer = Data; /* Install the data object */ if (PrevObjDesc) { PrevObjDesc->Common.NextObject = DataDesc; } else { Node->Object = DataDesc; } return (AE_OK); }
static ACPI_STATUS AcpiExAddTable ( UINT32 TableIndex, ACPI_NAMESPACE_NODE *ParentNode, ACPI_OPERAND_OBJECT **DdbHandle) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_FUNCTION_TRACE (ExAddTable); /* Create an object to be the table handle */ ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Init the table handle */ ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID; ObjDesc->Reference.Class = ACPI_REFCLASS_TABLE; *DdbHandle = ObjDesc; /* Install the new table into the local data structures */ ObjDesc->Reference.Value = TableIndex; /* Add the table to the namespace */ Status = AcpiNsLoadTable (TableIndex, ParentNode); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); *DdbHandle = NULL; return_ACPI_STATUS (Status); } /* Execute any module-level code that was found in the table */ AcpiExExitInterpreter (); AcpiNsExecModuleCodeList (); AcpiExEnterInterpreter (); return_ACPI_STATUS (Status); }
ACPI_OPERAND_OBJECT * AcpiUtCreateBufferObject ( ACPI_SIZE BufferSize) { ACPI_OPERAND_OBJECT *BufferDesc; UINT8 *Buffer = NULL; ACPI_FUNCTION_TRACE_U32 (UtCreateBufferObject, BufferSize); /* Create a new Buffer object */ BufferDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER); if (!BufferDesc) { return_PTR (NULL); } /* Create an actual buffer only if size > 0 */ if (BufferSize > 0) { /* Allocate the actual buffer */ Buffer = ACPI_ALLOCATE_ZEROED (BufferSize); if (!Buffer) { ACPI_ERROR ((AE_INFO, "Could not allocate size %u", (UINT32) BufferSize)); AcpiUtRemoveReference (BufferDesc); return_PTR (NULL); } } /* Complete buffer object initialization */ BufferDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; BufferDesc->Buffer.Pointer = Buffer; BufferDesc->Buffer.Length = (UINT32) BufferSize; /* Return the new buffer descriptor */ return_PTR (BufferDesc); }
ACPI_OPERAND_OBJECT * AcpiUtCreateStringObject ( ACPI_SIZE StringSize) { ACPI_OPERAND_OBJECT *StringDesc; char *String; ACPI_FUNCTION_TRACE_U32 (UtCreateStringObject, StringSize); /* Create a new String object */ StringDesc = AcpiUtCreateInternalObject (ACPI_TYPE_STRING); if (!StringDesc) { return_PTR (NULL); } /* * Allocate the actual string buffer -- (Size + 1) for NULL terminator. * NOTE: Zero-length strings are NULL terminated */ String = ACPI_ALLOCATE_ZEROED (StringSize + 1); if (!String) { ACPI_ERROR ((AE_INFO, "Could not allocate size %u", (UINT32) StringSize)); AcpiUtRemoveReference (StringDesc); return_PTR (NULL); } /* Complete string object initialization */ StringDesc->String.Pointer = String; StringDesc->String.Length = (UINT32) StringSize; /* Return the new string descriptor */ return_PTR (StringDesc); }
ACPI_STATUS AcpiUtCopyIobjectToIobject ( ACPI_OPERAND_OBJECT *SourceDesc, ACPI_OPERAND_OBJECT **DestDesc, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE (UtCopyIobjectToIobject); /* Create the top level object */ *DestDesc = AcpiUtCreateInternalObject (SourceDesc->Common.Type); if (!*DestDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Copy the object and possible subobjects */ if (SourceDesc->Common.Type == ACPI_TYPE_PACKAGE) { Status = AcpiUtCopyIpackageToIpackage ( SourceDesc, *DestDesc, WalkState); } else { Status = AcpiUtCopySimpleObject (SourceDesc, *DestDesc); } /* Delete the allocated object if copy failed */ if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (*DestDesc); } return_ACPI_STATUS (Status); }
ACPI_OPERAND_OBJECT * AcpiUtCreateBufferObject ( ACPI_SIZE BufferSize) { ACPI_OPERAND_OBJECT *BufferDesc; UINT8 *Buffer; ACPI_FUNCTION_TRACE_U32 ("UtCreateBufferObject", BufferSize); /* * Create a new Buffer object */ BufferDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER); if (!BufferDesc) { return_PTR (NULL); } /* Allocate the actual buffer */ Buffer = ACPI_MEM_CALLOCATE (BufferSize); if (!Buffer) { ACPI_REPORT_ERROR (("CreateBuffer: could not allocate size %X\n", (UINT32) BufferSize)); AcpiUtRemoveReference (BufferDesc); return_PTR (NULL); } /* Complete buffer object initialization */ BufferDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; BufferDesc->Buffer.Pointer = Buffer; BufferDesc->Buffer.Length = (UINT32) BufferSize; /* Return the new buffer descriptor */ return_PTR (BufferDesc); }
ACPI_OPERAND_OBJECT * AcpiUtCreateIntegerObject ( UINT64 InitialValue) { ACPI_OPERAND_OBJECT *IntegerDesc; ACPI_FUNCTION_TRACE (UtCreateIntegerObject); /* Create and initialize a new integer object */ IntegerDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!IntegerDesc) { return_PTR (NULL); } IntegerDesc->Integer.Value = InitialValue; return_PTR (IntegerDesc); }
void AcpiDmAddExternalsToNamespace ( void) { ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; ACPI_OPERAND_OBJECT *MethodDesc; ACPI_EXTERNAL_LIST *External = AcpiGbl_ExternalList; while (External) { /* Add the external name (object) into the namespace */ Status = AcpiNsLookup (NULL, External->InternalPath, External->Type, ACPI_IMODE_LOAD_PASS1, ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "while adding external to namespace [%s]", External->Path)); } else if (External->Type == ACPI_TYPE_METHOD) { /* For methods, we need to save the argument count */ MethodDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); MethodDesc->Method.ParamCount = (UINT8) External->Value; Node->Object = MethodDesc; } External = External->Next; } }
ACPI_STATUS AcpiDsBuildInternalPackageObj ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op, UINT32 ElementCount, ACPI_OPERAND_OBJECT **ObjDescPtr) { ACPI_PARSE_OBJECT *Arg; ACPI_PARSE_OBJECT *Parent; ACPI_OPERAND_OBJECT *ObjDesc = NULL; ACPI_STATUS Status = AE_OK; UINT32 i; UINT16 Index; UINT16 ReferenceCount; ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj); /* Find the parent of a possibly nested package */ Parent = Op->Common.Parent; while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) || (Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) { Parent = Parent->Common.Parent; } /* * If we are evaluating a Named package object "Name (xxxx, Package)", * the package object already exists, otherwise it must be created. */ ObjDesc = *ObjDescPtr; if (!ObjDesc) { ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE); *ObjDescPtr = ObjDesc; if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } ObjDesc->Package.Node = Parent->Common.Node; } /* * Allocate the element array (array of pointers to the individual * objects) based on the NumElements parameter. Add an extra pointer slot * so that the list is always null terminated. */ ObjDesc->Package.Elements = ACPI_ALLOCATE_ZEROED ( ((ACPI_SIZE) ElementCount + 1) * sizeof (void *)); if (!ObjDesc->Package.Elements) { AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (AE_NO_MEMORY); } ObjDesc->Package.Count = ElementCount; /* * Initialize the elements of the package, up to the NumElements count. * Package is automatically padded with uninitialized (NULL) elements * if NumElements is greater than the package list length. Likewise, * Package is truncated if NumElements is less than the list length. */ Arg = Op->Common.Value.Arg; Arg = Arg->Common.Next; for (i = 0; Arg && (i < ElementCount); i++) { if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) { if (Arg->Common.Node->Type == ACPI_TYPE_METHOD) { /* * A method reference "looks" to the parser to be a method * invocation, so we special case it here */ Arg->Common.AmlOpcode = AML_INT_NAMEPATH_OP; Status = AcpiDsBuildInternalObject (WalkState, Arg, &ObjDesc->Package.Elements[i]); } else { /* This package element is already built, just get it */ ObjDesc->Package.Elements[i] = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node); } } else { Status = AcpiDsBuildInternalObject (WalkState, Arg, &ObjDesc->Package.Elements[i]); } if (*ObjDescPtr) { /* Existing package, get existing reference count */ ReferenceCount = (*ObjDescPtr)->Common.ReferenceCount; if (ReferenceCount > 1) { /* Make new element ref count match original ref count */ for (Index = 0; Index < (ReferenceCount - 1); Index++) { AcpiUtAddReference ((ObjDesc->Package.Elements[i])); } } } Arg = Arg->Common.Next; } /* Check for match between NumElements and actual length of PackageList */ if (Arg) { /* * NumElements was exhausted, but there are remaining elements in the * PackageList. Truncate the package to NumElements. * * Note: technically, this is an error, from ACPI spec: "It is an error * for NumElements to be less than the number of elements in the * PackageList". However, we just print a message and * no exception is returned. This provides Windows compatibility. Some * BIOSs will alter the NumElements on the fly, creating this type * of ill-formed package object. */ while (Arg) { /* * We must delete any package elements that were created earlier * and are not going to be used because of the package truncation. */ if (Arg->Common.Node) { AcpiUtRemoveReference ( ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node)); Arg->Common.Node = NULL; } /* Find out how many elements there really are */ i++; Arg = Arg->Common.Next; } ACPI_INFO ((AE_INFO, "Actual Package length (%u) is larger than NumElements field (%u), truncated", i, ElementCount)); } else if (i < ElementCount) { /* * Arg list (elements) was exhausted, but we did not reach NumElements count. * Note: this is not an error, the package is padded out with NULLs. */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Package List length (%u) smaller than NumElements count (%u), padded with null elements\n", i, ElementCount)); } ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID; Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiDsBuildInternalBufferObj ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op, UINT32 BufferLength, ACPI_OPERAND_OBJECT **ObjDescPtr) { ACPI_PARSE_OBJECT *Arg; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_PARSE_OBJECT *ByteList; UINT32 ByteListLength = 0; ACPI_FUNCTION_TRACE (DsBuildInternalBufferObj); /* * If we are evaluating a Named buffer object "Name (xxxx, Buffer)". * The buffer object already exists (from the NS node), otherwise it must * be created. */ ObjDesc = *ObjDescPtr; if (!ObjDesc) { /* Create a new buffer object */ ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER); *ObjDescPtr = ObjDesc; if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } } /* * Second arg is the buffer data (optional) ByteList can be either * individual bytes or a string initializer. In either case, a * ByteList appears in the AML. */ Arg = Op->Common.Value.Arg; /* skip first arg */ ByteList = Arg->Named.Next; if (ByteList) { if (ByteList->Common.AmlOpcode != AML_INT_BYTELIST_OP) { ACPI_ERROR ((AE_INFO, "Expecting bytelist, found AML opcode 0x%X in op %p", ByteList->Common.AmlOpcode, ByteList)); AcpiUtRemoveReference (ObjDesc); return (AE_TYPE); } ByteListLength = (UINT32) ByteList->Common.Value.Integer; } /* * The buffer length (number of bytes) will be the larger of: * 1) The specified buffer length and * 2) The length of the initializer byte list */ ObjDesc->Buffer.Length = BufferLength; if (ByteListLength > BufferLength) { ObjDesc->Buffer.Length = ByteListLength; } /* Allocate the buffer */ if (ObjDesc->Buffer.Length == 0) { ObjDesc->Buffer.Pointer = NULL; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer defined with zero length in AML, creating\n")); } else { ObjDesc->Buffer.Pointer = ACPI_ALLOCATE_ZEROED ( ObjDesc->Buffer.Length); if (!ObjDesc->Buffer.Pointer) { AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (AE_NO_MEMORY); } /* Initialize buffer from the ByteList (if present) */ if (ByteList) { ACPI_MEMCPY (ObjDesc->Buffer.Pointer, ByteList->Named.Data, ByteListLength); } } ObjDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc); return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiDsBuildInternalObject ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op, ACPI_OPERAND_OBJECT **ObjDescPtr) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (DsBuildInternalObject); *ObjDescPtr = NULL; if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) { /* * This is a named object reference. If this name was * previously looked up in the namespace, it was stored in * this op. Otherwise, go ahead and look it up now */ if (!Op->Common.Node) { /* Check if we are resolving a named reference within a package */ if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)) { /* * We won't resolve package elements here, we will do this * after all ACPI tables are loaded into the namespace. This * behavior supports both forward references to named objects * and external references to objects in other tables. */ goto CreateNewObject; } else { Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Common.Value.String, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, ACPI_CAST_INDIRECT_PTR ( ACPI_NAMESPACE_NODE, &(Op->Common.Node))); if (ACPI_FAILURE (Status)) { ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo, Op->Common.Value.String, Status); return_ACPI_STATUS (Status); } } } } CreateNewObject: /* Create and init a new internal ACPI object */ ObjDesc = AcpiUtCreateInternalObject ( (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } Status = AcpiDsInitObjectFromOp ( WalkState, Op, Op->Common.AmlOpcode, &ObjDesc); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); return_ACPI_STATUS (Status); } /* * Handling for unresolved package reference elements. * These are elements that are namepaths. */ if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)) { ObjDesc->Reference.Resolved = TRUE; if ((Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && !ObjDesc->Reference.Node) { /* * Name was unresolved above. * Get the prefix node for later lookup */ ObjDesc->Reference.Node = WalkState->ScopeInfo->Scope.Node; ObjDesc->Reference.Aml = Op->Common.Aml; ObjDesc->Reference.Resolved = FALSE; } } *ObjDescPtr = ObjDesc; return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExOpcode_1A_0T_1R ( ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_OPERAND_OBJECT *TempDesc; ACPI_OPERAND_OBJECT *ReturnDesc = NULL; ACPI_STATUS Status = AE_OK; UINT32 Type; UINT64 Value; ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_1R, AcpiPsGetOpcodeName (WalkState->Opcode)); /* Examine the AML opcode */ switch (WalkState->Opcode) { case AML_LNOT_OP: /* LNot (Operand) */ ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) 0); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* * Set result to ONES (TRUE) if Value == 0. Note: * ReturnDesc->Integer.Value is initially == 0 (FALSE) from above. */ if (!Operand[0]->Integer.Value) { ReturnDesc->Integer.Value = ACPI_UINT64_MAX; } break; case AML_DECREMENT_OP: /* Decrement (Operand) */ case AML_INCREMENT_OP: /* Increment (Operand) */ /* * Create a new integer. Can't just get the base integer and * increment it because it may be an Arg or Field. */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } /* * Since we are expecting a Reference operand, it can be either a * NS Node or an internal object. */ TempDesc = Operand[0]; if (ACPI_GET_DESCRIPTOR_TYPE (TempDesc) == ACPI_DESC_TYPE_OPERAND) { /* Internal reference object - prevent deletion */ AcpiUtAddReference (TempDesc); } /* * Convert the Reference operand to an Integer (This removes a * reference on the Operand[0] object) * * NOTE: We use LNOT_OP here in order to force resolution of the * reference operand to an actual integer. */ Status = AcpiExResolveOperands (AML_LNOT_OP, &TempDesc, WalkState); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While resolving operands for [%s]", AcpiPsGetOpcodeName (WalkState->Opcode))); goto Cleanup; } /* * TempDesc is now guaranteed to be an Integer object -- * Perform the actual increment or decrement */ if (WalkState->Opcode == AML_INCREMENT_OP) { ReturnDesc->Integer.Value = TempDesc->Integer.Value + 1; } else { ReturnDesc->Integer.Value = TempDesc->Integer.Value - 1; } /* Finished with this Integer object */ AcpiUtRemoveReference (TempDesc); /* * Store the result back (indirectly) through the original * Reference object */ Status = AcpiExStore (ReturnDesc, Operand[0], WalkState); break; case AML_OBJECT_TYPE_OP: /* ObjectType (SourceObject) */ /* * Note: The operand is not resolved at this point because we want to * get the associated object, not its value. For example, we don't * want to resolve a FieldUnit to its value, we want the actual * FieldUnit object. */ /* Get the type of the base object */ Status = AcpiExResolveMultiple (WalkState, Operand[0], &Type, NULL); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Allocate a descriptor to hold the type. */ ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) Type); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } break; case AML_SIZE_OF_OP: /* SizeOf (SourceObject) */ /* * Note: The operand is not resolved at this point because we want to * get the associated object, not its value. */ /* Get the base object */ Status = AcpiExResolveMultiple ( WalkState, Operand[0], &Type, &TempDesc); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* * The type of the base object must be integer, buffer, string, or * package. All others are not supported. * * NOTE: Integer is not specifically supported by the ACPI spec, * but is supported implicitly via implicit operand conversion. * rather than bother with conversion, we just use the byte width * global (4 or 8 bytes). */ switch (Type) { case ACPI_TYPE_INTEGER: Value = AcpiGbl_IntegerByteWidth; break; case ACPI_TYPE_STRING: Value = TempDesc->String.Length; break; case ACPI_TYPE_BUFFER: /* Buffer arguments may not be evaluated at this point */ Status = AcpiDsGetBufferArguments (TempDesc); Value = TempDesc->Buffer.Length; break; case ACPI_TYPE_PACKAGE: /* Package arguments may not be evaluated at this point */ Status = AcpiDsGetPackageArguments (TempDesc); Value = TempDesc->Package.Count; break; default: ACPI_ERROR ((AE_INFO, "Operand must be Buffer/Integer/String/Package" " - found type %s", AcpiUtGetTypeName (Type))); Status = AE_AML_OPERAND_TYPE; goto Cleanup; } if (ACPI_FAILURE (Status)) { goto Cleanup; } /* * Now that we have the size of the object, create a result * object to hold the value */ ReturnDesc = AcpiUtCreateIntegerObject (Value); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } break; case AML_REF_OF_OP: /* RefOf (SourceObject) */ Status = AcpiExGetObjectReference ( Operand[0], &ReturnDesc, WalkState); if (ACPI_FAILURE (Status)) { goto Cleanup; } break; case AML_DEREF_OF_OP: /* DerefOf (ObjReference | String) */ /* Check for a method local or argument, or standalone String */ if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) { TempDesc = AcpiNsGetAttachedObject ( (ACPI_NAMESPACE_NODE *) Operand[0]); if (TempDesc && ((TempDesc->Common.Type == ACPI_TYPE_STRING) || (TempDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE))) { Operand[0] = TempDesc; AcpiUtAddReference (TempDesc); } else { Status = AE_AML_OPERAND_TYPE; goto Cleanup; } } else { switch ((Operand[0])->Common.Type) { case ACPI_TYPE_LOCAL_REFERENCE: /* * This is a DerefOf (LocalX | ArgX) * * Must resolve/dereference the local/arg reference first */ switch (Operand[0]->Reference.Class) { case ACPI_REFCLASS_LOCAL: case ACPI_REFCLASS_ARG: /* Set Operand[0] to the value of the local/arg */ Status = AcpiDsMethodDataGetValue ( Operand[0]->Reference.Class, Operand[0]->Reference.Value, WalkState, &TempDesc); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* * Delete our reference to the input object and * point to the object just retrieved */ AcpiUtRemoveReference (Operand[0]); Operand[0] = TempDesc; break; case ACPI_REFCLASS_REFOF: /* Get the object to which the reference refers */ TempDesc = Operand[0]->Reference.Object; AcpiUtRemoveReference (Operand[0]); Operand[0] = TempDesc; break; default: /* Must be an Index op - handled below */ break; } break; case ACPI_TYPE_STRING: break; default: Status = AE_AML_OPERAND_TYPE; goto Cleanup; } } if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) != ACPI_DESC_TYPE_NAMED) { if ((Operand[0])->Common.Type == ACPI_TYPE_STRING) { /* * This is a DerefOf (String). The string is a reference * to a named ACPI object. * * 1) Find the owning Node * 2) Dereference the node to an actual object. Could be a * Field, so we need to resolve the node to a value. */ Status = AcpiNsGetNodeUnlocked (WalkState->ScopeInfo->Scope.Node, Operand[0]->String.Pointer, ACPI_NS_SEARCH_PARENT, ACPI_CAST_INDIRECT_PTR ( ACPI_NAMESPACE_NODE, &ReturnDesc)); if (ACPI_FAILURE (Status)) { goto Cleanup; } Status = AcpiExResolveNodeToValue ( ACPI_CAST_INDIRECT_PTR ( ACPI_NAMESPACE_NODE, &ReturnDesc), WalkState); goto Cleanup; } } /* Operand[0] may have changed from the code above */ if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED) { /* * This is a DerefOf (ObjectReference) * Get the actual object from the Node (This is the dereference). * This case may only happen when a LocalX or ArgX is * dereferenced above. */ ReturnDesc = AcpiNsGetAttachedObject ( (ACPI_NAMESPACE_NODE *) Operand[0]); AcpiUtAddReference (ReturnDesc); } else { /* * This must be a reference object produced by either the * Index() or RefOf() operator */ switch (Operand[0]->Reference.Class) { case ACPI_REFCLASS_INDEX: /* * The target type for the Index operator must be * either a Buffer or a Package */ switch (Operand[0]->Reference.TargetType) { case ACPI_TYPE_BUFFER_FIELD: TempDesc = Operand[0]->Reference.Object; /* * Create a new object that contains one element of the * buffer -- the element pointed to by the index. * * NOTE: index into a buffer is NOT a pointer to a * sub-buffer of the main buffer, it is only a pointer to a * single element (byte) of the buffer! * * Since we are returning the value of the buffer at the * indexed location, we don't need to add an additional * reference to the buffer itself. */ ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) TempDesc->Buffer.Pointer[Operand[0]->Reference.Value]); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } break; case ACPI_TYPE_PACKAGE: /* * Return the referenced element of the package. We must * add another reference to the referenced object, however. */ ReturnDesc = *(Operand[0]->Reference.Where); if (!ReturnDesc) { /* * Element is NULL, do not allow the dereference. * This provides compatibility with other ACPI * implementations. */ return_ACPI_STATUS (AE_AML_UNINITIALIZED_ELEMENT); } AcpiUtAddReference (ReturnDesc); break; default: ACPI_ERROR ((AE_INFO, "Unknown Index TargetType 0x%X in reference object %p", Operand[0]->Reference.TargetType, Operand[0])); Status = AE_AML_OPERAND_TYPE; goto Cleanup; } break; case ACPI_REFCLASS_REFOF: ReturnDesc = Operand[0]->Reference.Object; if (ACPI_GET_DESCRIPTOR_TYPE (ReturnDesc) == ACPI_DESC_TYPE_NAMED) { ReturnDesc = AcpiNsGetAttachedObject ( (ACPI_NAMESPACE_NODE *) ReturnDesc); if (!ReturnDesc) { break; } /* * June 2013: * BufferFields/FieldUnits require additional resolution */ switch (ReturnDesc->Common.Type) { case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: Status = AcpiExReadDataFromField ( WalkState, ReturnDesc, &TempDesc); if (ACPI_FAILURE (Status)) { goto Cleanup; } ReturnDesc = TempDesc; break; default: /* Add another reference to the object */ AcpiUtAddReference (ReturnDesc); break; } } break; default: ACPI_ERROR ((AE_INFO, "Unknown class in reference(%p) - 0x%2.2X", Operand[0], Operand[0]->Reference.Class)); Status = AE_TYPE; goto Cleanup; } } break; default: ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", WalkState->Opcode)); Status = AE_AML_BAD_OPCODE; goto Cleanup; } Cleanup: /* Delete return object on error */ if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ReturnDesc); } /* Save return object on success */ else { WalkState->ResultObj = ReturnDesc; } return_ACPI_STATUS (Status); }
ACPI_STATUS 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_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); }
static void AcpiPsLinkModuleCode ( ACPI_PARSE_OBJECT *ParentOp, UINT8 *AmlStart, UINT32 AmlLength, ACPI_OWNER_ID OwnerId) { ACPI_OPERAND_OBJECT *Prev; ACPI_OPERAND_OBJECT *Next; ACPI_OPERAND_OBJECT *MethodObj; ACPI_NAMESPACE_NODE *ParentNode; /* Get the tail of the list */ Prev = Next = AcpiGbl_ModuleCodeList; while (Next) { Prev = Next; Next = Next->Method.Mutex; } /* * Insert the module level code into the list. Merge it if it is * adjacent to the previous element. */ if (!Prev || ((Prev->Method.AmlStart + Prev->Method.AmlLength) != AmlStart)) { /* Create, initialize, and link a new temporary method object */ MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); if (!MethodObj) { return; } if (ParentOp->Common.Node) { ParentNode = ParentOp->Common.Node; } else { ParentNode = AcpiGbl_RootNode; } MethodObj->Method.AmlStart = AmlStart; MethodObj->Method.AmlLength = AmlLength; MethodObj->Method.OwnerId = OwnerId; MethodObj->Method.InfoFlags |= ACPI_METHOD_MODULE_LEVEL; /* * Save the parent node in NextObject. This is cheating, but we * don't want to expand the method object. */ MethodObj->Method.NextObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParentNode); if (!Prev) { AcpiGbl_ModuleCodeList = MethodObj; } else { Prev->Method.Mutex = MethodObj; } } else { Prev->Method.AmlLength += AmlLength; } }
ACPI_STATUS AcpiInstallGpeBlock ( ACPI_HANDLE GpeDevice, ACPI_GENERIC_ADDRESS *GpeBlockAddress, UINT32 RegisterCount, UINT32 InterruptNumber) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_NAMESPACE_NODE *Node; ACPI_GPE_BLOCK_INFO *GpeBlock; ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); if ((!GpeDevice) || (!GpeBlockAddress) || (!RegisterCount)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } Node = AcpiNsValidateHandle (GpeDevice); if (!Node) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Validate the parent device */ if (Node->Type != ACPI_TYPE_DEVICE) { Status = AE_TYPE; goto UnlockAndExit; } if (Node->Object) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } /* * For user-installed GPE Block Devices, the GpeBlockBaseNumber * is always zero */ Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address, GpeBlockAddress->SpaceId, RegisterCount, 0, InterruptNumber, &GpeBlock); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } /* Install block in the DeviceObject attached to the node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { /* * No object, create a new one (Device nodes do not always have * an attached object) */ ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); if (!ObjDesc) { Status = AE_NO_MEMORY; goto UnlockAndExit; } Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); /* Remove local reference to the object */ AcpiUtRemoveReference (ObjDesc); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } } /* Now install the GPE block in the DeviceObject */ ObjDesc->Device.GpeBlock = GpeBlock; UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiNsRootInitialize ( void) { ACPI_STATUS Status; const ACPI_PREDEFINED_NAMES *InitVal = NULL; ACPI_NAMESPACE_NODE *NewNode; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_STRING Val = NULL; ACPI_FUNCTION_TRACE (NsRootInitialize); Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * The global root ptr is initially NULL, so a non-NULL value indicates * that AcpiNsRootInitialize() has already been called; just return. */ if (AcpiGbl_RootNode) { Status = AE_OK; goto UnlockAndExit; } /* * Tell the rest of the subsystem that the root is initialized * (This is OK because the namespace is locked) */ AcpiGbl_RootNode = &AcpiGbl_RootNodeStruct; /* Enter the pre-defined names in the name table */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Entering predefined entries into namespace\n")); for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++) { /* _OSI is optional for now, will be permanent later */ if (!strcmp (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod) { continue; } Status = AcpiNsLookup (NULL, ACPI_CAST_PTR (char, InitVal->Name), InitVal->Type, ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, NULL, &NewNode); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Could not create predefined name %s", InitVal->Name)); continue; } /* * Name entered successfully. If entry in PreDefinedNames[] specifies * an initial value, create the initial value. */ if (InitVal->Val) { Status = AcpiOsPredefinedOverride (InitVal, &Val); if (ACPI_FAILURE (Status)) { ACPI_ERROR ((AE_INFO, "Could not override predefined %s", InitVal->Name)); } if (!Val) { Val = InitVal->Val; } /* * Entry requests an initial value, allocate a * descriptor for it. */ ObjDesc = AcpiUtCreateInternalObject (InitVal->Type); if (!ObjDesc) { Status = AE_NO_MEMORY; goto UnlockAndExit; } /* * Convert value string from table entry to * internal representation. Only types actually * used for initial values are implemented here. */ switch (InitVal->Type) { case ACPI_TYPE_METHOD: ObjDesc->Method.ParamCount = (UINT8) ACPI_TO_INTEGER (Val); ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID; #if defined (ACPI_ASL_COMPILER) /* Save the parameter count for the iASL compiler */ NewNode->Value = ObjDesc->Method.ParamCount; #else /* Mark this as a very SPECIAL method */ ObjDesc->Method.InfoFlags = ACPI_METHOD_INTERNAL_ONLY; ObjDesc->Method.Dispatch.Implementation = AcpiUtOsiImplementation; #endif break; case ACPI_TYPE_INTEGER: ObjDesc->Integer.Value = ACPI_TO_INTEGER (Val); break; case ACPI_TYPE_STRING: /* Build an object around the static string */ ObjDesc->String.Length = (UINT32) strlen (Val); ObjDesc->String.Pointer = Val; ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER; break; case ACPI_TYPE_MUTEX: ObjDesc->Mutex.Node = NewNode; ObjDesc->Mutex.SyncLevel = (UINT8) (ACPI_TO_INTEGER (Val) - 1); /* Create a mutex */ Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); goto UnlockAndExit; } /* Special case for ACPI Global Lock */ if (strcmp (InitVal->Name, "_GL_") == 0) { AcpiGbl_GlobalLockMutex = ObjDesc; /* Create additional counting semaphore for global lock */ Status = AcpiOsCreateSemaphore ( 1, 0, &AcpiGbl_GlobalLockSemaphore); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); goto UnlockAndExit; } } break; default: ACPI_ERROR ((AE_INFO, "Unsupported initial type value 0x%X", InitVal->Type)); AcpiUtRemoveReference (ObjDesc); ObjDesc = NULL; continue; } /* Store pointer to value descriptor in the Node */ Status = AcpiNsAttachObject (NewNode, ObjDesc, ObjDesc->Common.Type); /* Remove local reference to the object */ AcpiUtRemoveReference (ObjDesc); } } UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); /* Save a handle to "_GPE", it is always present */ if (ACPI_SUCCESS (Status)) { Status = AcpiNsGetNode (NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH, &AcpiGbl_FadtGpeDevice); } return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiExAddTable ( UINT32 TableIndex, ACPI_NAMESPACE_NODE *ParentNode, ACPI_OPERAND_OBJECT **DdbHandle) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_STATUS Status; ACPI_OWNER_ID OwnerId; ACPI_FUNCTION_TRACE (ExAddTable); /* Create an object to be the table handle */ ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Init the table handle */ ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID; ObjDesc->Reference.Class = ACPI_REFCLASS_TABLE; *DdbHandle = ObjDesc; /* Install the new table into the local data structures */ ObjDesc->Reference.Value = TableIndex; /* Add the table to the namespace */ Status = AcpiNsLoadTable (TableIndex, ParentNode); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); *DdbHandle = NULL; return_ACPI_STATUS (Status); } /* Execute any module-level code that was found in the table */ AcpiExExitInterpreter (); AcpiNsExecModuleCodeList (); AcpiExEnterInterpreter (); /* * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is * responsible for discovering any new wake GPEs by running _PRW methods * that may have been loaded by this table. */ Status = AcpiTbGetOwnerId (TableIndex, &OwnerId); if (ACPI_SUCCESS (Status)) { AcpiEvUpdateGpes (OwnerId); } return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiInstallNotifyHandler ( ACPI_HANDLE Device, UINT32 HandlerType, ACPI_NOTIFY_HANDLER Handler, void *Context) { ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device); ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerObj; ACPI_STATUS Status; UINT32 i; ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler); /* Parameter validation */ if ((!Device) || (!Handler) || (!HandlerType) || (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Root Object: * Registering a notify handler on the root object indicates that the * caller wishes to receive notifications for all objects. Note that * only one global handler can be registered per notify type. * Ensure that a handler is not already installed. */ if (Device == ACPI_ROOT_OBJECT) { for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (HandlerType & (i+1)) { if (AcpiGbl_GlobalNotify[i].Handler) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } AcpiGbl_GlobalNotify[i].Handler = Handler; AcpiGbl_GlobalNotify[i].Context = Context; } } goto UnlockAndExit; /* Global notify handler installed, all done */ } /* * All Other Objects: * Caller will only receive notifications specific to the target * object. Note that only certain object types are allowed to * receive notifications. */ /* Are Notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { Status = AE_TYPE; goto UnlockAndExit; } /* Check for an existing internal object, might not exist */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { /* Create a new object */ ObjDesc = AcpiUtCreateInternalObject (Node->Type); if (!ObjDesc) { Status = AE_NO_MEMORY; goto UnlockAndExit; } /* Attach new object to the Node, remove local reference */ Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type); AcpiUtRemoveReference (ObjDesc); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } } /* Ensure that the handler is not already installed in the lists */ for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (HandlerType & (i+1)) { HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; while (HandlerObj) { if (HandlerObj->Notify.Handler == Handler) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } HandlerObj = HandlerObj->Notify.Next[i]; } } } /* Create and populate a new notify handler object */ HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY); if (!HandlerObj) { Status = AE_NO_MEMORY; goto UnlockAndExit; } HandlerObj->Notify.Node = Node; HandlerObj->Notify.HandlerType = HandlerType; HandlerObj->Notify.Handler = Handler; HandlerObj->Notify.Context = Context; /* Install the handler at the list head(s) */ for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { if (HandlerType & (i+1)) { HandlerObj->Notify.Next[i] = ObjDesc->CommonNotify.NotifyList[i]; ObjDesc->CommonNotify.NotifyList[i] = HandlerObj; } } /* Add an extra reference if handler was installed in both lists */ if (HandlerType == ACPI_ALL_NOTIFY) { AcpiUtAddReference (HandlerObj); } UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiDsBuildInternalPackageObj ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op, UINT32 ElementCount, ACPI_OPERAND_OBJECT **ObjDescPtr) { ACPI_PARSE_OBJECT *Arg; ACPI_PARSE_OBJECT *Parent; ACPI_OPERAND_OBJECT *ObjDesc = NULL; ACPI_STATUS Status = AE_OK; ACPI_NATIVE_UINT i; ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj); /* Find the parent of a possibly nested package */ Parent = Op->Common.Parent; while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) || (Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) { Parent = Parent->Common.Parent; } /* * If we are evaluating a Named package object "Name (xxxx, Package)", * the package object already exists, otherwise it must be created. */ ObjDesc = *ObjDescPtr; if (!ObjDesc) { ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE); *ObjDescPtr = ObjDesc; if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } ObjDesc->Package.Node = Parent->Common.Node; } /* * Allocate the element array (array of pointers to the individual * objects) based on the NumElements parameter. Add an extra pointer slot * so that the list is always null terminated. */ ObjDesc->Package.Elements = ACPI_ALLOCATE_ZEROED ( ((ACPI_SIZE) ElementCount + 1) * sizeof (void *)); if (!ObjDesc->Package.Elements) { AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (AE_NO_MEMORY); } ObjDesc->Package.Count = ElementCount; /* * Initialize the elements of the package, up to the NumElements count. * Package is automatically padded with uninitialized (NULL) elements * if NumElements is greater than the package list length. Likewise, * Package is truncated if NumElements is less than the list length. */ Arg = Op->Common.Value.Arg; Arg = Arg->Common.Next; for (i = 0; Arg && (i < ElementCount); i++) { if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) { /* This package element is already built, just get it */ ObjDesc->Package.Elements[i] = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Arg->Common.Node); } else { Status = AcpiDsBuildInternalObject (WalkState, Arg, &ObjDesc->Package.Elements[i]); } Arg = Arg->Common.Next; } if (!Arg) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Package List length larger than NumElements count (%X), truncated\n", ElementCount)); } ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID; Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc); return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiDsBuildInternalObject ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op, ACPI_OPERAND_OBJECT **ObjDescPtr) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_STATUS Status; ACPI_OBJECT_TYPE Type; ACPI_FUNCTION_TRACE (DsBuildInternalObject); *ObjDescPtr = NULL; if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) { /* * This is a named object reference. If this name was * previously looked up in the namespace, it was stored in this op. * Otherwise, go ahead and look it up now */ if (!Op->Common.Node) { Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Common.Value.String, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &(Op->Common.Node))); if (ACPI_FAILURE (Status)) { /* Check if we are resolving a named reference within a package */ if ((Status == AE_NOT_FOUND) && (AcpiGbl_EnableInterpreterSlack) && ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))) { /* * We didn't find the target and we are populating elements * of a package - ignore if slack enabled. Some ASL code * contains dangling invalid references in packages and * expects that no exception will be issued. Leave the * element as a null element. It cannot be used, but it * can be overwritten by subsequent ASL code - this is * typically the case. */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Ignoring unresolved reference in package [%4.4s]\n", WalkState->ScopeInfo->Scope.Node->Name.Ascii)); return_ACPI_STATUS (AE_OK); } else { ACPI_ERROR_NAMESPACE (Op->Common.Value.String, Status); } return_ACPI_STATUS (Status); } } /* Special object resolution for elements of a package */ if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP)) { /* * Attempt to resolve the node to a value before we insert it into * the package. If this is a reference to a common data type, * resolve it immediately. According to the ACPI spec, package * elements can only be "data objects" or method references. * Attempt to resolve to an Integer, Buffer, String or Package. * If cannot, return the named reference (for things like Devices, * Methods, etc.) Buffer Fields and Fields will resolve to simple * objects (int/buf/str/pkg). * * NOTE: References to things like Devices, Methods, Mutexes, etc. * will remain as named references. This behavior is not described * in the ACPI spec, but it appears to be an oversight. */ ObjDesc = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Op->Common.Node); Status = AcpiExResolveNodeToValue ( ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc), WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Special handling for Alias objects. We need to setup the type * and the Op->Common.Node to point to the Alias target. Note, * Alias has at most one level of indirection internally. */ Type = Op->Common.Node->Type; if (Type == ACPI_TYPE_LOCAL_ALIAS) { Type = ObjDesc->Common.Type; Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Op->Common.Node->Object); } switch (Type) { /* * For these types, we need the actual node, not the subobject. * However, the subobject did not get an extra reference count above. * * TBD: should ExResolveNodeToValue be changed to fix this? */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_THERMAL: AcpiUtAddReference (Op->Common.Node->Object); /*lint -fallthrough */ /* * For these types, we need the actual node, not the subobject. * The subobject got an extra reference count in ExResolveNodeToValue. */ case ACPI_TYPE_MUTEX: case ACPI_TYPE_METHOD: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_EVENT: case ACPI_TYPE_REGION: /* We will create a reference object for these types below */ break; default: /* * All other types - the node was resolved to an actual * object, we are done. */ goto Exit; } } } /* Create and init a new internal ACPI object */ ObjDesc = AcpiUtCreateInternalObject ( (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } Status = AcpiDsInitObjectFromOp (WalkState, Op, Op->Common.AmlOpcode, &ObjDesc); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); return_ACPI_STATUS (Status); } Exit: *ObjDescPtr = ObjDesc; return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiDsCreateOperand ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Arg, UINT32 ArgIndex) { ACPI_STATUS Status = AE_OK; char *NameString; UINT32 NameLength; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_PARSE_OBJECT *ParentOp; UINT16 Opcode; ACPI_INTERPRETER_MODE InterpreterMode; const ACPI_OPCODE_INFO *OpInfo; ACPI_FUNCTION_TRACE_PTR (DsCreateOperand, Arg); /* A valid name must be looked up in the namespace */ if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && (Arg->Common.Value.String) && !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", Arg)); /* Get the entire name string from the AML stream */ Status = AcpiExGetNameString (ACPI_TYPE_ANY, Arg->Common.Value.Buffer, &NameString, &NameLength); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* All prefixes have been handled, and the name is in NameString */ /* * Special handling for BufferField declarations. This is a deferred * opcode that unfortunately defines the field name as the last * parameter instead of the first. We get here when we are performing * the deferred execution, so the actual name of the field is already * in the namespace. We don't want to attempt to look it up again * because we may be executing in a different scope than where the * actual opcode exists. */ if ((WalkState->DeferredNode) && (WalkState->DeferredNode->Type == ACPI_TYPE_BUFFER_FIELD) && (ArgIndex == (UINT32) ((WalkState->Opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) { ObjDesc = ACPI_CAST_PTR ( ACPI_OPERAND_OBJECT, WalkState->DeferredNode); Status = AE_OK; } else /* All other opcodes */ { /* * Differentiate between a namespace "create" operation * versus a "lookup" operation (IMODE_LOAD_PASS2 vs. * IMODE_EXECUTE) in order to support the creation of * namespace objects during the execution of control methods. */ ParentOp = Arg->Common.Parent; OpInfo = AcpiPsGetOpcodeInfo (ParentOp->Common.AmlOpcode); if ((OpInfo->Flags & AML_NSNODE) && (ParentOp->Common.AmlOpcode != AML_INT_METHODCALL_OP) && (ParentOp->Common.AmlOpcode != AML_REGION_OP) && (ParentOp->Common.AmlOpcode != AML_INT_NAMEPATH_OP)) { /* Enter name into namespace if not found */ InterpreterMode = ACPI_IMODE_LOAD_PASS2; } else { /* Return a failure if name not found */ InterpreterMode = ACPI_IMODE_EXECUTE; } Status = AcpiNsLookup (WalkState->ScopeInfo, NameString, ACPI_TYPE_ANY, InterpreterMode, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, WalkState, ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &ObjDesc)); /* * The only case where we pass through (ignore) a NOT_FOUND * error is for the CondRefOf opcode. */ if (Status == AE_NOT_FOUND) { if (ParentOp->Common.AmlOpcode == AML_COND_REF_OF_OP) { /* * For the Conditional Reference op, it's OK if * the name is not found; We just need a way to * indicate this to the interpreter, set the * object to the root */ ObjDesc = ACPI_CAST_PTR ( ACPI_OPERAND_OBJECT, AcpiGbl_RootNode); Status = AE_OK; } else { /* * We just plain didn't find it -- which is a * very serious error at this point */ Status = AE_AML_NAME_NOT_FOUND; } } if (ACPI_FAILURE (Status)) { ACPI_ERROR_NAMESPACE (NameString, Status); } } /* Free the namestring created above */ ACPI_FREE (NameString); /* Check status from the lookup */ if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Put the resulting object onto the current object stack */ Status = AcpiDsObjStackPush (ObjDesc, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); } else { /* Check for null name case */ if ((Arg->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && !(Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) { /* * If the name is null, this means that this is an * optional result parameter that was not specified * in the original ASL. Create a Zero Constant for a * placeholder. (Store to a constant is a Noop.) */ Opcode = AML_ZERO_OP; /* Has no arguments! */ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Null namepath: Arg=%p\n", Arg)); } else { Opcode = Arg->Common.AmlOpcode; } /* Get the object type of the argument */ OpInfo = AcpiPsGetOpcodeInfo (Opcode); if (OpInfo->ObjectType == ACPI_TYPE_INVALID) { return_ACPI_STATUS (AE_NOT_IMPLEMENTED); } if ((OpInfo->Flags & AML_HAS_RETVAL) || (Arg->Common.Flags & ACPI_PARSEOP_IN_STACK)) { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Argument previously created, already stacked\n")); ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject ( WalkState->Operands [WalkState->NumOperands - 1], WalkState)); /* * Use value that was already previously returned * by the evaluation of this argument */ Status = AcpiDsResultPop (&ObjDesc, WalkState); if (ACPI_FAILURE (Status)) { /* * Only error is underflow, and this indicates * a missing or null operand! */ ACPI_EXCEPTION ((AE_INFO, Status, "Missing or null operand")); return_ACPI_STATUS (Status); } } else { /* Create an ACPI_INTERNAL_OBJECT for the argument */ ObjDesc = AcpiUtCreateInternalObject (OpInfo->ObjectType); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Initialize the new object */ Status = AcpiDsInitObjectFromOp ( WalkState, Arg, Opcode, &ObjDesc); if (ACPI_FAILURE (Status)) { AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (Status); } } /* Put the operand object on the object stack */ Status = AcpiDsObjStackPush (ObjDesc, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } ACPI_DEBUGGER_EXEC (AcpiDbDisplayArgumentObject (ObjDesc, WalkState)); } return_ACPI_STATUS (AE_OK); }
static ACPI_STATUS AcpiDsBuildInternalObject ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op, ACPI_OPERAND_OBJECT **ObjDescPtr) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (DsBuildInternalObject); *ObjDescPtr = NULL; if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) { /* * This is a named object reference. If this name was * previously looked up in the namespace, it was stored in this op. * Otherwise, go ahead and look it up now */ if (!Op->Common.Node) { Status = AcpiNsLookup (WalkState->ScopeInfo, Op->Common.Value.String, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, &(Op->Common.Node))); if (ACPI_FAILURE (Status)) { /* Check if we are resolving a named reference within a package */ if ((Status == AE_NOT_FOUND) && (AcpiGbl_EnableInterpreterSlack) && ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || (Op->Common.Parent->Common.AmlOpcode == AML_VAR_PACKAGE_OP))) { /* * We didn't find the target and we are populating elements * of a package - ignore if slack enabled. Some ASL code * contains dangling invalid references in packages and * expects that no exception will be issued. Leave the * element as a null element. It cannot be used, but it * can be overwritten by subsequent ASL code - this is * typically the case. */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Ignoring unresolved reference in package [%4.4s]\n", WalkState->ScopeInfo->Scope.Node->Name.Ascii)); return_ACPI_STATUS (AE_OK); } else { ACPI_ERROR_NAMESPACE (Op->Common.Value.String, Status); } return_ACPI_STATUS (Status); } } } /* Create and init a new internal ACPI object */ ObjDesc = AcpiUtCreateInternalObject ( (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } Status = AcpiDsInitObjectFromOp (WalkState, Op, Op->Common.AmlOpcode, &ObjDesc); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); return_ACPI_STATUS (Status); } *ObjDescPtr = ObjDesc; return_ACPI_STATUS (AE_OK); }