ACPI_STATUS AcpiEvQueueNotifyRequest ( ACPI_NAMESPACE_NODE *Node, UINT32 NotifyValue) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerObj = NULL; ACPI_GENERIC_STATE *NotifyInfo; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_NAME (EvQueueNotifyRequest); /* * For value 3 (Ejection Request), some device method may need to be run. * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need * to be run. * For value 0x80 (Status Change) on the power button or sleep button, * initiate soft-off or sleep operation? */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n", AcpiUtGetNodeName (Node), Node, NotifyValue, AcpiUtGetNotifyName (NotifyValue))); /* Get the notify object attached to the NS Node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* We have the notify object, Get the right handler */ switch (Node->Type) { /* Notify allowed only on these types */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_THERMAL: case ACPI_TYPE_PROCESSOR: if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) { HandlerObj = ObjDesc->CommonNotify.SystemNotify; } else { HandlerObj = ObjDesc->CommonNotify.DeviceNotify; } break; default: /* All other types are not supported */ return (AE_TYPE); } } /* * If there is any handler to run, schedule the dispatcher. * Check for: * 1) Global system notify handler * 2) Global device notify handler * 3) Per-device notify handler */ if ((AcpiGbl_SystemNotify.Handler && (NotifyValue <= ACPI_MAX_SYS_NOTIFY)) || (AcpiGbl_DeviceNotify.Handler && (NotifyValue > ACPI_MAX_SYS_NOTIFY)) || HandlerObj) { NotifyInfo = AcpiUtCreateGenericState (); if (!NotifyInfo) { return (AE_NO_MEMORY); } if (!HandlerObj) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Executing system notify handler for Notify (%4.4s, %X) node %p\n", AcpiUtGetNodeName (Node), NotifyValue, Node)); } NotifyInfo->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY; NotifyInfo->Notify.Node = Node; NotifyInfo->Notify.Value = (UINT16) NotifyValue; NotifyInfo->Notify.HandlerObj = HandlerObj; Status = AcpiOsExecute ( OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch, NotifyInfo); if (ACPI_FAILURE (Status)) { AcpiUtDeleteGenericState (NotifyInfo); } } else { /* * There is no notify handler (per-device or system) for this device. */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for Notify (%4.4s, %X) node %p\n", AcpiUtGetNodeName (Node), NotifyValue, Node)); } return (Status); }
static ACPI_STATUS AcpiDsInitOneObject ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context; ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_FUNCTION_ENTRY (); /* * We are only interested in NS nodes owned by the table that * was just loaded */ if (Node->OwnerId != Info->OwnerId) { return (AE_OK); } Info->ObjectCount++; /* And even then, we are only interested in a few object types */ switch (AcpiNsGetType (ObjHandle)) { case ACPI_TYPE_REGION: Status = AcpiDsInitializeRegion (ObjHandle); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "During Region initialization %p [%4.4s]", ObjHandle, AcpiUtGetNodeName (ObjHandle))); } Info->OpRegionCount++; break; case ACPI_TYPE_METHOD: /* * Auto-serialization support. We will examine each method that is * NotSerialized to determine if it creates any Named objects. If * it does, it will be marked serialized to prevent problems if * the method is entered by two or more threads and an attempt is * made to create the same named object twice -- which results in * an AE_ALREADY_EXISTS exception and method abort. */ Info->MethodCount++; ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { break; } /* Ignore if already serialized */ if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED) { Info->SerialMethodCount++; break; } if (AcpiGbl_AutoSerializeMethods) { /* Parse/scan method and serialize it if necessary */ AcpiDsAutoSerializeMethod (Node, ObjDesc); if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED) { /* Method was just converted to Serialized */ Info->SerialMethodCount++; Info->SerializedMethodCount++; break; } } Info->NonSerialMethodCount++; break; case ACPI_TYPE_DEVICE: Info->DeviceCount++; break; default: break; } /* * We ignore errors from above, and always return OK, since * we don't want to abort the walk on a single error. */ return (AE_OK); }
void AcpiUtDumpAllocations ( UINT32 Component, const char *Module) { ACPI_DEBUG_MEM_BLOCK *Element; ACPI_DESCRIPTOR *Descriptor; UINT32 NumOutstanding = 0; UINT8 DescriptorType; ACPI_FUNCTION_TRACE (UtDumpAllocations); if (AcpiGbl_DisableMemTracking) { return_VOID; } /* * Walk the allocation list. */ if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY))) { return_VOID; } Element = AcpiGbl_GlobalList->ListHead; while (Element) { if ((Element->Component & Component) && ((Module == NULL) || (0 == ACPI_STRCMP (Module, Element->Module)))) { Descriptor = ACPI_CAST_PTR (ACPI_DESCRIPTOR, &Element->UserSpace); if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR)) { AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u " "[Not a Descriptor - too small]\n", Descriptor, Element->Size, Element->Module, Element->Line); } else { /* Ignore allocated objects that are in a cache */ if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != ACPI_DESC_TYPE_CACHED) { AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u [%s] ", Descriptor, Element->Size, Element->Module, Element->Line, AcpiUtGetDescriptorName (Descriptor)); /* Validate the descriptor type using Type field and length */ DescriptorType = 0; /* Not a valid descriptor type */ switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor)) { case ACPI_DESC_TYPE_OPERAND: if (Element->Size == sizeof (ACPI_OPERAND_OBJECT)) { DescriptorType = ACPI_DESC_TYPE_OPERAND; } break; case ACPI_DESC_TYPE_PARSER: if (Element->Size == sizeof (ACPI_PARSE_OBJECT)) { DescriptorType = ACPI_DESC_TYPE_PARSER; } break; case ACPI_DESC_TYPE_NAMED: if (Element->Size == sizeof (ACPI_NAMESPACE_NODE)) { DescriptorType = ACPI_DESC_TYPE_NAMED; } break; default: break; } /* Display additional info for the major descriptor types */ switch (DescriptorType) { case ACPI_DESC_TYPE_OPERAND: AcpiOsPrintf ("%12.12s RefCount 0x%04X\n", AcpiUtGetTypeName (Descriptor->Object.Common.Type), Descriptor->Object.Common.ReferenceCount); break; case ACPI_DESC_TYPE_PARSER: AcpiOsPrintf ("AmlOpcode 0x%04hX\n", Descriptor->Op.Asl.AmlOpcode); break; case ACPI_DESC_TYPE_NAMED: AcpiOsPrintf ("%4.4s\n", AcpiUtGetNodeName (&Descriptor->Node)); break; default: AcpiOsPrintf ( "\n"); break; } } } NumOutstanding++; } Element = Element->Next; } (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY); /* Print summary */ if (!NumOutstanding) { ACPI_INFO ((AE_INFO, "No outstanding allocations")); } else { ACPI_ERROR ((AE_INFO, "%u(0x%X) Outstanding allocations", NumOutstanding, NumOutstanding)); } return_VOID; }
void AcpiDbDisplayMethodInfo ( ACPI_PARSE_OBJECT *StartOp) { ACPI_WALK_STATE *WalkState; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_NAMESPACE_NODE *Node; ACPI_PARSE_OBJECT *RootOp; ACPI_PARSE_OBJECT *Op; const ACPI_OPCODE_INFO *OpInfo; UINT32 NumOps = 0; UINT32 NumOperands = 0; UINT32 NumOperators = 0; UINT32 NumRemainingOps = 0; UINT32 NumRemainingOperands = 0; UINT32 NumRemainingOperators = 0; BOOLEAN CountRemaining = FALSE; WalkState = AcpiDsGetCurrentWalkState (AcpiGbl_CurrentWalkList); if (!WalkState) { AcpiOsPrintf ("There is no method currently executing\n"); return; } ObjDesc = WalkState->MethodDesc; Node = WalkState->MethodNode; AcpiOsPrintf ("Currently executing control method is [%4.4s]\n", AcpiUtGetNodeName (Node)); AcpiOsPrintf ("%X Arguments, SyncLevel = %X\n", (UINT32) ObjDesc->Method.ParamCount, (UINT32) ObjDesc->Method.SyncLevel); RootOp = StartOp; while (RootOp->Common.Parent) { RootOp = RootOp->Common.Parent; } Op = RootOp; while (Op) { if (Op == StartOp) { CountRemaining = TRUE; } NumOps++; if (CountRemaining) { NumRemainingOps++; } /* Decode the opcode */ OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); switch (OpInfo->Class) { case AML_CLASS_ARGUMENT: if (CountRemaining) { NumRemainingOperands++; } NumOperands++; break; case AML_CLASS_UNKNOWN: /* Bad opcode or ASCII character */ continue; default: if (CountRemaining) { NumRemainingOperators++; } NumOperators++; break; } Op = AcpiPsGetDepthNext (StartOp, Op); } AcpiOsPrintf ( "Method contains: %X AML Opcodes - %X Operators, %X Operands\n", NumOps, NumOperators, NumOperands); AcpiOsPrintf ( "Remaining to execute: %X AML Opcodes - %X Operators, %X Operands\n", NumRemainingOps, NumRemainingOperators, NumRemainingOperands); }
ACPI_STATUS AcpiDsLoad1BeginOp ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT **OutOp) { ACPI_PARSE_OBJECT *Op; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_OBJECT_TYPE ObjectType; char *Path; UINT32 Flags; ACPI_FUNCTION_TRACE (DsLoad1BeginOp); Op = WalkState->Op; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState)); /* We are only interested in opcodes that have an associated name */ if (Op) { if (!(WalkState->OpInfo->Flags & AML_NAMED)) { *OutOp = Op; return_ACPI_STATUS (AE_OK); } /* Check if this object has already been installed in the namespace */ if (Op->Common.Node) { *OutOp = Op; return_ACPI_STATUS (AE_OK); } } Path = AcpiPsGetNextNamestring (&WalkState->ParserState); /* Map the raw opcode into an internal object type */ ObjectType = WalkState->OpInfo->ObjectType; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "State=%p Op=%p [%s]\n", WalkState, Op, AcpiUtGetTypeName (ObjectType))); switch (WalkState->Opcode) { case AML_SCOPE_OP: /* * The target name of the Scope() operator must exist at this point so * that we can actually open the scope to enter new names underneath it. * Allow search-to-root for single namesegs. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &(Node)); #ifdef ACPI_ASL_COMPILER if (Status == AE_NOT_FOUND) { /* * Table disassembly: * Target of Scope() not found. Generate an External for it, and * insert the name into the namespace. */ AcpiDmAddOpToExternalList (Op, Path, ACPI_TYPE_DEVICE, 0, 0); Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, WalkState, &Node); } #endif if (ACPI_FAILURE (Status)) { ACPI_ERROR_NAMESPACE (Path, Status); return_ACPI_STATUS (Status); } /* * Check to make sure that the target is * one of the opcodes that actually opens a scope */ switch (Node->Type) { case ACPI_TYPE_ANY: case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ case ACPI_TYPE_DEVICE: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: /* These are acceptable types */ break; case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * These types we will allow, but we will change the type. * This enables some existing code of the form: * * Name (DEB, 0) * Scope (DEB) { ... } * * Note: silently change the type here. On the second pass, * we will report a warning */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Type override - [%4.4s] had invalid type (%s) " "for Scope operator, changed to type ANY\n", AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type))); Node->Type = ACPI_TYPE_ANY; WalkState->ScopeInfo->Common.Value = ACPI_TYPE_ANY; break; case ACPI_TYPE_METHOD: /* * Allow scope change to root during execution of module-level * code. Root is typed METHOD during this time. */ if ((Node == AcpiGbl_RootNode) && (WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) { break; } /*lint -fallthrough */ default: /* All other types are an error */ ACPI_ERROR ((AE_INFO, "Invalid type (%s) for target of " "Scope operator [%4.4s] (Cannot override)", AcpiUtGetTypeName (Node->Type), AcpiUtGetNodeName (Node))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } break; default: /* * For all other named opcodes, we will enter the name into * the namespace. * * Setup the search flags. * Since we are entering a name into the namespace, we do not want to * enable the search-to-root upsearch. * * There are only two conditions where it is acceptable that the name * already exists: * 1) the Scope() operator can reopen a scoping object that was * previously defined (Scope, Method, Device, etc.) * 2) Whenever we are parsing a deferred opcode (OpRegion, Buffer, * BufferField, or Package), the name of the object is already * in the namespace. */ if (WalkState->DeferredNode) { /* This name is already in the namespace, get the node */ Node = WalkState->DeferredNode; Status = AE_OK; break; } /* * If we are executing a method, do not create any namespace objects * during the load phase, only during execution. */ if (WalkState->MethodNode) { Node = NULL; Status = AE_OK; break; } Flags = ACPI_NS_NO_UPSEARCH; if ((WalkState->Opcode != AML_SCOPE_OP) && (!(WalkState->ParseFlags & ACPI_PARSE_DEFERRED_OP))) { if (WalkState->NamespaceOverride) { Flags |= ACPI_NS_OVERRIDE_IF_FOUND; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Override allowed\n", AcpiUtGetTypeName (ObjectType))); } else { Flags |= ACPI_NS_ERROR_IF_FOUND; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n", AcpiUtGetTypeName (ObjectType))); } } else { ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Both Find or Create allowed\n", AcpiUtGetTypeName (ObjectType))); } /* * Enter the named type into the internal namespace. We enter the name * as we go downward in the parse tree. Any necessary subobjects that * involve arguments to the opcode must be created as we go back up the * parse tree later. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); if (ACPI_FAILURE (Status)) { if (Status == AE_ALREADY_EXISTS) { /* The name already exists in this scope */ if (Node->Flags & ANOBJ_IS_EXTERNAL) { /* * Allow one create on an object or segment that was * previously declared External */ Node->Flags &= ~ANOBJ_IS_EXTERNAL; Node->Type = (UINT8) ObjectType; /* Just retyped a node, probably will need to open a scope */ if (AcpiNsOpensScope (ObjectType)) { Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } Status = AE_OK; } } if (ACPI_FAILURE (Status)) { ACPI_ERROR_NAMESPACE (Path, Status); return_ACPI_STATUS (Status); } } break; } /* Common exit */ if (!Op) { /* Create a new op */ Op = AcpiPsAllocOp (WalkState->Opcode, WalkState->Aml); if (!Op) { return_ACPI_STATUS (AE_NO_MEMORY); } } /* Initialize the op */ #if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)) Op->Named.Path = ACPI_CAST_PTR (UINT8, Path); #endif if (Node) { /* * Put the Node in the "op" object that the parser uses, so we * can get it again quickly when this scope is closed */ Op->Common.Node = Node; Op->Named.Name = Node->Name.Integer; } AcpiPsAppendArg (AcpiPsGetParentScope (&WalkState->ParserState), Op); *OutOp = Op; return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiNsAttachObject ( ACPI_NAMESPACE_NODE *Node, ACPI_OPERAND_OBJECT *Object, ACPI_OBJECT_TYPE Type) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *LastObjDesc; ACPI_OBJECT_TYPE ObjectType = ACPI_TYPE_ANY; ACPI_FUNCTION_TRACE (NsAttachObject); /* * Parameter validation */ if (!Node) { /* Invalid handle */ ACPI_ERROR ((AE_INFO, "Null NamedObj handle")); return_ACPI_STATUS (AE_BAD_PARAMETER); } if (!Object && (ACPI_TYPE_ANY != Type)) { /* Null object */ ACPI_ERROR ((AE_INFO, "Null object, but type not ACPI_TYPE_ANY")); return_ACPI_STATUS (AE_BAD_PARAMETER); } if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) { /* Not a name handle */ ACPI_ERROR ((AE_INFO, "Invalid handle %p [%s]", Node, AcpiUtGetDescriptorName (Node))); return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Check if this object is already attached */ if (Node->Object == Object) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj %p already installed in NameObj %p\n", Object, Node)); return_ACPI_STATUS (AE_OK); } /* If null object, we will just install it */ if (!Object) { ObjDesc = NULL; ObjectType = ACPI_TYPE_ANY; } /* * If the source object is a namespace Node with an attached object, * we will use that (attached) object */ else if ((ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) && ((ACPI_NAMESPACE_NODE *) Object)->Object) { /* * Value passed is a name handle and that name has a * non-null value. Use that name's value and type. */ ObjDesc = ((ACPI_NAMESPACE_NODE *) Object)->Object; ObjectType = ((ACPI_NAMESPACE_NODE *) Object)->Type; } /* * Otherwise, we will use the parameter object, but we must type * it first */ else { ObjDesc = (ACPI_OPERAND_OBJECT *) Object; /* Use the given type */ ObjectType = Type; } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Installing %p into Node %p [%4.4s]\n", ObjDesc, Node, AcpiUtGetNodeName (Node))); /* Detach an existing attached object if present */ if (Node->Object) { AcpiNsDetachObject (Node); } if (ObjDesc) { /* * Must increment the new value's reference count * (if it is an internal object) */ AcpiUtAddReference (ObjDesc); /* * Handle objects with multiple descriptors - walk * to the end of the descriptor list */ LastObjDesc = ObjDesc; while (LastObjDesc->Common.NextObject) { LastObjDesc = LastObjDesc->Common.NextObject; } /* Install the object at the front of the object list */ LastObjDesc->Common.NextObject = Node->Object; } Node->Type = (UINT8) ObjectType; Node->Object = ObjDesc; return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiDsBeginMethodExecution ( ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE_PTR (DsBeginMethodExecution, MethodNode); if (!MethodNode) { return_ACPI_STATUS (AE_NULL_ENTRY); } AcpiExStartTraceMethod (MethodNode, ObjDesc, WalkState); /* Prevent wraparound of thread count */ if (ObjDesc->Method.ThreadCount == ACPI_UINT8_MAX) { ACPI_ERROR ((AE_INFO, "Method reached maximum reentrancy limit (255)")); return_ACPI_STATUS (AE_AML_METHOD_LIMIT); } /* * If this method is serialized, we need to acquire the method mutex. */ if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED) { /* * Create a mutex for the method if it is defined to be Serialized * and a mutex has not already been created. We defer the mutex creation * until a method is actually executed, to minimize the object count */ if (!ObjDesc->Method.Mutex) { Status = AcpiDsCreateMethodMutex (ObjDesc); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } /* * The CurrentSyncLevel (per-thread) must be less than or equal to * the sync level of the method. This mechanism provides some * deadlock prevention. * * If the method was auto-serialized, we just ignore the sync level * mechanism, because auto-serialization of methods can interfere * with ASL code that actually uses sync levels. * * Top-level method invocation has no walk state at this point */ if (WalkState && (!(ObjDesc->Method.InfoFlags & ACPI_METHOD_IGNORE_SYNC_LEVEL)) && (WalkState->Thread->CurrentSyncLevel > ObjDesc->Method.Mutex->Mutex.SyncLevel)) { ACPI_ERROR ((AE_INFO, "Cannot acquire Mutex for method [%4.4s]" ", current SyncLevel is too large (%u)", AcpiUtGetNodeName (MethodNode), WalkState->Thread->CurrentSyncLevel)); return_ACPI_STATUS (AE_AML_MUTEX_ORDER); } /* * Obtain the method mutex if necessary. Do not acquire mutex for a * recursive call. */ if (!WalkState || !ObjDesc->Method.Mutex->Mutex.ThreadId || (WalkState->Thread->ThreadId != ObjDesc->Method.Mutex->Mutex.ThreadId)) { /* * Acquire the method mutex. This releases the interpreter if we * block (and reacquires it before it returns) */ Status = AcpiExSystemWaitMutex ( ObjDesc->Method.Mutex->Mutex.OsMutex, ACPI_WAIT_FOREVER); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Update the mutex and walk info and save the original SyncLevel */ if (WalkState) { ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel = WalkState->Thread->CurrentSyncLevel; ObjDesc->Method.Mutex->Mutex.ThreadId = WalkState->Thread->ThreadId; /* * Update the current SyncLevel only if this is not an auto- * serialized method. In the auto case, we have to ignore * the sync level for the method mutex (created for the * auto-serialization) because we have no idea of what the * sync level should be. Therefore, just ignore it. */ if (!(ObjDesc->Method.InfoFlags & ACPI_METHOD_IGNORE_SYNC_LEVEL)) { WalkState->Thread->CurrentSyncLevel = ObjDesc->Method.SyncLevel; } } else { ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel = ObjDesc->Method.Mutex->Mutex.SyncLevel; ObjDesc->Method.Mutex->Mutex.ThreadId = AcpiOsGetThreadId (); } } /* Always increase acquisition depth */ ObjDesc->Method.Mutex->Mutex.AcquisitionDepth++; } /* * Allocate an Owner ID for this method, only if this is the first thread * to begin concurrent execution. We only need one OwnerId, even if the * method is invoked recursively. */ if (!ObjDesc->Method.OwnerId) { Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId); if (ACPI_FAILURE (Status)) { goto Cleanup; } } /* * Increment the method parse tree thread count since it has been * reentered one more time (even if it is the same thread) */ ObjDesc->Method.ThreadCount++; AcpiMethodCount++; return_ACPI_STATUS (Status); Cleanup: /* On error, must release the method mutex (if present) */ if (ObjDesc->Method.Mutex) { AcpiOsReleaseMutex (ObjDesc->Method.Mutex->Mutex.OsMutex); } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiUtEvaluateObject ( ACPI_NAMESPACE_NODE *PrefixNode, char *Path, UINT32 ExpectedReturnBtypes, ACPI_OPERAND_OBJECT **ReturnDesc) { ACPI_EVALUATE_INFO *Info; ACPI_STATUS Status; UINT32 ReturnBtype; ACPI_FUNCTION_TRACE (UtEvaluateObject); /* Allocate the evaluation information block */ Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); if (!Info) { return_ACPI_STATUS (AE_NO_MEMORY); } Info->PrefixNode = PrefixNode; Info->Pathname = Path; /* Evaluate the object/method */ Status = AcpiNsEvaluate (Info); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_FOUND) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n", AcpiUtGetNodeName (PrefixNode), Path)); } else { ACPI_ERROR_METHOD ("Method execution failed", PrefixNode, Path, Status); } goto Cleanup; } /* Did we get a return object? */ if (!Info->ReturnObject) { if (ExpectedReturnBtypes) { ACPI_ERROR_METHOD ("No object was returned from", PrefixNode, Path, AE_NOT_EXIST); Status = AE_NOT_EXIST; } goto Cleanup; } /* Map the return object type to the bitmapped type */ switch ((Info->ReturnObject)->Common.Type) { case ACPI_TYPE_INTEGER: ReturnBtype = ACPI_BTYPE_INTEGER; break; case ACPI_TYPE_BUFFER: ReturnBtype = ACPI_BTYPE_BUFFER; break; case ACPI_TYPE_STRING: ReturnBtype = ACPI_BTYPE_STRING; break; case ACPI_TYPE_PACKAGE: ReturnBtype = ACPI_BTYPE_PACKAGE; break; default: ReturnBtype = 0; break; } if ((AcpiGbl_EnableInterpreterSlack) && (!ExpectedReturnBtypes)) { /* * We received a return object, but one was not expected. This can * happen frequently if the "implicit return" feature is enabled. * Just delete the return object and return AE_OK. */ AcpiUtRemoveReference (Info->ReturnObject); goto Cleanup; } /* Is the return object one of the expected types? */ if (!(ExpectedReturnBtypes & ReturnBtype)) { ACPI_ERROR_METHOD ("Return object type is incorrect", PrefixNode, Path, AE_TYPE); ACPI_ERROR ((AE_INFO, "Type returned from %s was incorrect: %s, expected Btypes: %X", Path, AcpiUtGetObjectTypeName (Info->ReturnObject), ExpectedReturnBtypes)); /* On error exit, we must delete the return object */ AcpiUtRemoveReference (Info->ReturnObject); Status = AE_TYPE; goto Cleanup; } /* Object type is OK, return it */ *ReturnDesc = Info->ReturnObject; Cleanup: ACPI_FREE (Info); return_ACPI_STATUS (Status); }
static void ACPI_SYSTEM_XFACE AcpiEvAsynchExecuteGpeMethod ( void *Context) { ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; ACPI_STATUS Status; ACPI_GPE_EVENT_INFO *LocalGpeEventInfo; ACPI_EVALUATE_INFO *Info; ACPI_GPE_NOTIFY_INFO *Notify; ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); /* Allocate a local GPE block */ LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO)); if (!LocalGpeEventInfo) { ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, "while handling a GPE")); return_VOID; } Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { return_VOID; } /* Must revalidate the GpeNumber/GpeBlock */ if (!AcpiEvValidGpeEvent (GpeEventInfo)) { Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); return_VOID; } /* * Take a snapshot of the GPE info for this level - we copy the info to * prevent a race condition with RemoveHandler/RemoveBlock. */ ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo, sizeof (ACPI_GPE_EVENT_INFO)); Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { return_VOID; } /* Do the correct dispatch - normal method or implicit notify */ switch (LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) { case ACPI_GPE_DISPATCH_NOTIFY: /* * Implicit notify. * Dispatch a DEVICE_WAKE 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. * * June 2012: Expand implicit notify mechanism to support * notifies on multiple device objects. */ Notify = LocalGpeEventInfo->Dispatch.NotifyList; while (ACPI_SUCCESS (Status) && Notify) { Status = AcpiEvQueueNotifyRequest (Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE); Notify = Notify->Next; } break; case ACPI_GPE_DISPATCH_METHOD: /* Allocate the evaluation information block */ Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); if (!Info) { Status = AE_NO_MEMORY; } else { /* * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the * _Lxx/_Exx control method that corresponds to this GPE */ Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode; Info->Flags = ACPI_IGNORE_RETURN_VALUE; Status = AcpiNsEvaluate (Info); ACPI_FREE (Info); } if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "while evaluating GPE method [%4.4s]", AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode))); } break; default: return_VOID; /* Should never happen */ } /* Defer enabling of GPE until all notify handlers are done */ Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, AcpiEvAsynchEnableGpe, LocalGpeEventInfo); if (ACPI_FAILURE (Status)) { ACPI_FREE (LocalGpeEventInfo); } return_VOID; }
ACPI_STATUS AcpiExAcquireMutex ( ACPI_OPERAND_OBJECT *TimeDesc, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status; ACPI_FUNCTION_TRACE_PTR (ExAcquireMutex, ObjDesc); if (!ObjDesc) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Sanity check: we must have a valid thread ID */ if (!WalkState->Thread) { ACPI_ERROR ((AE_INFO, "Cannot acquire Mutex [%4.4s], null thread info", AcpiUtGetNodeName (ObjDesc->Mutex.Node))); return_ACPI_STATUS (AE_AML_INTERNAL); } /* * Current Sync must be less than or equal to the sync level of the * mutex. This mechanism provides some deadlock prevention */ if (WalkState->Thread->CurrentSyncLevel > ObjDesc->Mutex.SyncLevel) { ACPI_ERROR ((AE_INFO, "Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%d)", AcpiUtGetNodeName (ObjDesc->Mutex.Node), WalkState->Thread->CurrentSyncLevel)); return_ACPI_STATUS (AE_AML_MUTEX_ORDER); } /* Support for multiple acquires by the owning thread */ if (ObjDesc->Mutex.OwnerThread) { if (ObjDesc->Mutex.OwnerThread->ThreadId == WalkState->Thread->ThreadId) { /* * The mutex is already owned by this thread, just increment the * acquisition depth */ ObjDesc->Mutex.AcquisitionDepth++; return_ACPI_STATUS (AE_OK); } } /* Acquire the mutex, wait if necessary. Special case for Global Lock */ if (ObjDesc->Mutex.OsMutex == AcpiGbl_GlobalLockMutex) { Status = AcpiEvAcquireGlobalLock ((UINT16) TimeDesc->Integer.Value); } else { Status = AcpiExSystemWaitMutex (ObjDesc->Mutex.OsMutex, (UINT16) TimeDesc->Integer.Value); } if (ACPI_FAILURE (Status)) { /* Includes failure from a timeout on TimeDesc */ return_ACPI_STATUS (Status); } /* Have the mutex: update mutex and walk info and save the SyncLevel */ ObjDesc->Mutex.OwnerThread = WalkState->Thread; ObjDesc->Mutex.AcquisitionDepth = 1; ObjDesc->Mutex.OriginalSyncLevel = WalkState->Thread->CurrentSyncLevel; WalkState->Thread->CurrentSyncLevel = ObjDesc->Mutex.SyncLevel; /* Link the mutex to the current thread for force-unlock at method exit */ AcpiExLinkMutex (ObjDesc, WalkState->Thread); return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiExReleaseMutex ( ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE (ExReleaseMutex); if (!ObjDesc) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* The mutex must have been previously acquired in order to release it */ if (!ObjDesc->Mutex.OwnerThread) { ACPI_ERROR ((AE_INFO, "Cannot release Mutex [%4.4s], not acquired", AcpiUtGetNodeName (ObjDesc->Mutex.Node))); return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED); } /* Sanity check: we must have a valid thread ID */ if (!WalkState->Thread) { ACPI_ERROR ((AE_INFO, "Cannot release Mutex [%4.4s], null thread info", AcpiUtGetNodeName (ObjDesc->Mutex.Node))); return_ACPI_STATUS (AE_AML_INTERNAL); } /* * The Mutex is owned, but this thread must be the owner. * Special case for Global Lock, any thread can release */ if ((ObjDesc->Mutex.OwnerThread->ThreadId != WalkState->Thread->ThreadId) && (ObjDesc->Mutex.OsMutex != AcpiGbl_GlobalLockMutex)) { ACPI_ERROR ((AE_INFO, "Thread %X cannot release Mutex [%4.4s] acquired by thread %X", WalkState->Thread->ThreadId, AcpiUtGetNodeName (ObjDesc->Mutex.Node), ObjDesc->Mutex.OwnerThread->ThreadId)); return_ACPI_STATUS (AE_AML_NOT_OWNER); } /* * The sync level of the mutex must be less than or equal to the current * sync level */ if (ObjDesc->Mutex.SyncLevel > WalkState->Thread->CurrentSyncLevel) { ACPI_ERROR ((AE_INFO, "Cannot release Mutex [%4.4s], incorrect SyncLevel", AcpiUtGetNodeName (ObjDesc->Mutex.Node))); return_ACPI_STATUS (AE_AML_MUTEX_ORDER); } /* Match multiple Acquires with multiple Releases */ ObjDesc->Mutex.AcquisitionDepth--; if (ObjDesc->Mutex.AcquisitionDepth != 0) { /* Just decrement the depth and return */ return_ACPI_STATUS (AE_OK); } /* Unlink the mutex from the owner's list */ AcpiExUnlinkMutex (ObjDesc); /* Release the mutex, special case for Global Lock */ if (ObjDesc->Mutex.OsMutex == AcpiGbl_GlobalLockMutex) { Status = AcpiEvReleaseGlobalLock (); } else { AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex); } /* Update the mutex and restore SyncLevel */ ObjDesc->Mutex.OwnerThread = NULL; WalkState->Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel; return_ACPI_STATUS (Status); }
void AcpiNsInstallNode ( ACPI_WALK_STATE *WalkState, ACPI_NAMESPACE_NODE *ParentNode, /* Parent */ ACPI_NAMESPACE_NODE *Node, /* New Child*/ ACPI_OBJECT_TYPE Type) { ACPI_OWNER_ID OwnerId = 0; ACPI_NAMESPACE_NODE *ChildNode; ACPI_FUNCTION_TRACE (NsInstallNode); if (WalkState) { /* * Get the owner ID from the Walk state. The owner ID is used to * track table deletion and deletion of objects created by methods. */ OwnerId = WalkState->OwnerId; if ((WalkState->MethodDesc) && (ParentNode != WalkState->MethodNode)) { /* * A method is creating a new node that is not a child of the * method (it is non-local). Mark the executing method as having * modified the namespace. This is used for cleanup when the * method exits. */ WalkState->MethodDesc->Method.InfoFlags |= ACPI_METHOD_MODIFIED_NAMESPACE; } } /* Link the new entry into the parent and existing children */ Node->Peer = NULL; Node->Parent = ParentNode; ChildNode = ParentNode->Child; if (!ChildNode) { ParentNode->Child = Node; } else { /* Add node to the end of the peer list */ while (ChildNode->Peer) { ChildNode = ChildNode->Peer; } ChildNode->Peer = Node; } /* Init the new entry */ Node->OwnerId = OwnerId; Node->Type = (UINT8) Type; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n", AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), Node, OwnerId, AcpiUtGetNodeName (ParentNode), AcpiUtGetTypeName (ParentNode->Type), ParentNode)); return_VOID; }
ACPI_STATUS AcpiEvQueueNotifyRequest ( ACPI_NAMESPACE_NODE *Node, UINT32 NotifyValue) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerListHead = NULL; ACPI_GENERIC_STATE *Info; UINT8 HandlerListId = 0; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_NAME (EvQueueNotifyRequest); /* Are Notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { return (AE_TYPE); } /* Get the correct notify list type (System or Device) */ if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) { HandlerListId = ACPI_SYSTEM_HANDLER_LIST; } else { HandlerListId = ACPI_DEVICE_HANDLER_LIST; } /* Get the notify object attached to the namespace Node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* We have an attached object, Get the correct handler list */ HandlerListHead = ObjDesc->CommonNotify.NotifyList[HandlerListId]; } /* * If there is no notify handler (Global or Local) * for this object, just ignore the notify */ if (!AcpiGbl_GlobalNotify[HandlerListId].Handler && !HandlerListHead) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n", AcpiUtGetNodeName (Node), NotifyValue, Node)); return (AE_OK); } /* Setup notify info and schedule the notify dispatcher */ Info = AcpiUtCreateGenericState (); if (!Info) { return (AE_NO_MEMORY); } Info->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY; Info->Notify.Node = Node; Info->Notify.Value = (UINT16) NotifyValue; Info->Notify.HandlerListId = HandlerListId; Info->Notify.HandlerListHead = HandlerListHead; Info->Notify.Global = &AcpiGbl_GlobalNotify[HandlerListId]; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), NotifyValue, AcpiUtGetNotifyName (NotifyValue), Node)); Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch, Info); if (ACPI_FAILURE (Status)) { AcpiUtDeleteGenericState (Info); } return (Status); }
static void AeCommonNotifyHandler ( ACPI_HANDLE Device, UINT32 Value, UINT32 HandlerId) { char *Type; Type = "Device"; if (Value <= ACPI_MAX_SYS_NOTIFY) { Type = "System"; } switch (Value) { #if 0 case 0: printf ("[AcpiExec] Method Error 0x%X: Results not equal\n", Value); if (AcpiGbl_DebugFile) { AcpiOsPrintf ("[AcpiExec] Method Error: Results not equal\n"); } break; case 1: printf ("[AcpiExec] Method Error: Incorrect numeric result\n"); if (AcpiGbl_DebugFile) { AcpiOsPrintf ("[AcpiExec] Method Error: Incorrect numeric result\n"); } break; case 2: printf ("[AcpiExec] Method Error: An operand was overwritten\n"); if (AcpiGbl_DebugFile) { AcpiOsPrintf ("[AcpiExec] Method Error: An operand was overwritten\n"); } break; #endif default: printf ("[AcpiExec] Handler %u: Received a %s Notify on [%4.4s] %p Value 0x%2.2X (%s)\n", HandlerId, Type, AcpiUtGetNodeName (Device), Device, Value, AcpiUtGetNotifyName (Value, ACPI_TYPE_ANY)); if (AcpiGbl_DebugFile) { AcpiOsPrintf ("[AcpiExec] Handler %u: Received a %s notify, Value 0x%2.2X\n", HandlerId, Type, Value); } (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL); break; } }
static void ACPI_SYSTEM_XFACE AcpiEvAsynchExecuteGpeMethod ( void *Context) { ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; ACPI_STATUS Status = AE_OK; ACPI_EVALUATE_INFO *Info; ACPI_GPE_NOTIFY_INFO *Notify; ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); /* Do the correct dispatch - normal method or implicit notify */ switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags)) { case ACPI_GPE_DISPATCH_NOTIFY: /* * Implicit notify. * Dispatch a DEVICE_WAKE 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. * * June 2012: Expand implicit notify mechanism to support * notifies on multiple device objects. */ Notify = GpeEventInfo->Dispatch.NotifyList; while (ACPI_SUCCESS (Status) && Notify) { Status = AcpiEvQueueNotifyRequest ( Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE); Notify = Notify->Next; } break; case ACPI_GPE_DISPATCH_METHOD: /* Allocate the evaluation information block */ Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); if (!Info) { Status = AE_NO_MEMORY; } else { /* * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the * _Lxx/_Exx control method that corresponds to this GPE */ Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode; Info->Flags = ACPI_IGNORE_RETURN_VALUE; Status = AcpiNsEvaluate (Info); ACPI_FREE (Info); } if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "while evaluating GPE method [%4.4s]", AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode))); } break; default: goto ErrorExit; /* Should never happen */ } /* Defer enabling of GPE until all notify handlers are done */ Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, AcpiEvAsynchEnableGpe, GpeEventInfo); if (ACPI_SUCCESS (Status)) { return_VOID; } ErrorExit: AcpiEvAsynchEnableGpe (GpeEventInfo); return_VOID; }
ACPI_STATUS AcpiExPrepFieldValue ( ACPI_CREATE_FIELD_INFO *Info) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *SecondDesc = NULL; ACPI_STATUS Status; UINT32 AccessByteWidth; UINT32 Type; ACPI_FUNCTION_TRACE (ExPrepFieldValue); /* Parameter validation */ if (Info->FieldType != ACPI_TYPE_LOCAL_INDEX_FIELD) { if (!Info->RegionNode) { ACPI_ERROR ((AE_INFO, "Null RegionNode")); return_ACPI_STATUS (AE_AML_NO_OPERAND); } Type = AcpiNsGetType (Info->RegionNode); if (Type != ACPI_TYPE_REGION) { ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)", Type, AcpiUtGetTypeName (Type))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } } /* Allocate a new field object */ ObjDesc = AcpiUtCreateInternalObject (Info->FieldType); if (!ObjDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Initialize areas of the object that are common to all fields */ ObjDesc->CommonField.Node = Info->FieldNode; Status = AcpiExPrepCommonFieldObject (ObjDesc, Info->FieldFlags, Info->Attribute, Info->FieldBitPosition, Info->FieldBitLength); if (ACPI_FAILURE (Status)) { AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (Status); } /* Initialize areas of the object that are specific to the field type */ switch (Info->FieldType) { case ACPI_TYPE_LOCAL_REGION_FIELD: ObjDesc->Field.RegionObj = AcpiNsGetAttachedObject (Info->RegionNode); /* Fields specific to GenericSerialBus fields */ ObjDesc->Field.AccessLength = Info->AccessLength; if (Info->ConnectionNode) { SecondDesc = Info->ConnectionNode->Object; if (!(SecondDesc->Common.Flags & AOPOBJ_DATA_VALID)) { Status = AcpiDsGetBufferArguments (SecondDesc); if (ACPI_FAILURE (Status)) { AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (Status); } } ObjDesc->Field.ResourceBuffer = SecondDesc->Buffer.Pointer; ObjDesc->Field.ResourceLength = (UINT16) SecondDesc->Buffer.Length; } else if (Info->ResourceBuffer) { ObjDesc->Field.ResourceBuffer = Info->ResourceBuffer; ObjDesc->Field.ResourceLength = Info->ResourceLength; } ObjDesc->Field.PinNumberIndex = Info->PinNumberIndex; /* Allow full data read from EC address space */ if ((ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) && (ObjDesc->CommonField.BitLength > 8)) { AccessByteWidth = ACPI_ROUND_BITS_UP_TO_BYTES ( ObjDesc->CommonField.BitLength); /* Maximum byte width supported is 255 */ if (AccessByteWidth < 256) { ObjDesc->CommonField.AccessByteWidth = (UINT8) AccessByteWidth; } } /* An additional reference for the container */ AcpiUtAddReference (ObjDesc->Field.RegionObj); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", ObjDesc->Field.StartFieldBitOffset, ObjDesc->Field.BaseByteOffset, ObjDesc->Field.AccessByteWidth, ObjDesc->Field.RegionObj)); break; case ACPI_TYPE_LOCAL_BANK_FIELD: ObjDesc->BankField.Value = Info->BankValue; ObjDesc->BankField.RegionObj = AcpiNsGetAttachedObject (Info->RegionNode); ObjDesc->BankField.BankObj = AcpiNsGetAttachedObject (Info->RegisterNode); /* An additional reference for the attached objects */ AcpiUtAddReference (ObjDesc->BankField.RegionObj); AcpiUtAddReference (ObjDesc->BankField.BankObj); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Bank Field: BitOff %X, Off %X, Gran %X, Region %p, BankReg %p\n", ObjDesc->BankField.StartFieldBitOffset, ObjDesc->BankField.BaseByteOffset, ObjDesc->Field.AccessByteWidth, ObjDesc->BankField.RegionObj, ObjDesc->BankField.BankObj)); /* * Remember location in AML stream of the field unit * opcode and operands -- since the BankValue * operands must be evaluated. */ SecondDesc = ObjDesc->Common.NextObject; SecondDesc->Extra.AmlStart = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Info->DataRegisterNode)->Named.Data; SecondDesc->Extra.AmlLength = ACPI_CAST_PTR (ACPI_PARSE_OBJECT, Info->DataRegisterNode)->Named.Length; break; case ACPI_TYPE_LOCAL_INDEX_FIELD: /* Get the Index and Data registers */ ObjDesc->IndexField.IndexObj = AcpiNsGetAttachedObject (Info->RegisterNode); ObjDesc->IndexField.DataObj = AcpiNsGetAttachedObject (Info->DataRegisterNode); if (!ObjDesc->IndexField.DataObj || !ObjDesc->IndexField.IndexObj) { ACPI_ERROR ((AE_INFO, "Null Index Object during field prep")); AcpiUtDeleteObjectDesc (ObjDesc); return_ACPI_STATUS (AE_AML_INTERNAL); } /* An additional reference for the attached objects */ AcpiUtAddReference (ObjDesc->IndexField.DataObj); AcpiUtAddReference (ObjDesc->IndexField.IndexObj); /* * April 2006: Changed to match MS behavior * * The value written to the Index register is the byte offset of the * target field in units of the granularity of the IndexField * * Previously, the value was calculated as an index in terms of the * width of the Data register, as below: * * ObjDesc->IndexField.Value = (UINT32) * (Info->FieldBitPosition / ACPI_MUL_8 ( * ObjDesc->Field.AccessByteWidth)); * * February 2006: Tried value as a byte offset: * ObjDesc->IndexField.Value = (UINT32) * ACPI_DIV_8 (Info->FieldBitPosition); */ ObjDesc->IndexField.Value = (UINT32) ACPI_ROUND_DOWN ( ACPI_DIV_8 (Info->FieldBitPosition), ObjDesc->IndexField.AccessByteWidth); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "IndexField: BitOff %X, Off %X, Value %X, " "Gran %X, Index %p, Data %p\n", ObjDesc->IndexField.StartFieldBitOffset, ObjDesc->IndexField.BaseByteOffset, ObjDesc->IndexField.Value, ObjDesc->Field.AccessByteWidth, ObjDesc->IndexField.IndexObj, ObjDesc->IndexField.DataObj)); break; default: /* No other types should get here */ break; } /* * Store the constructed descriptor (ObjDesc) into the parent Node, * preserving the current type of that NamedObj. */ Status = AcpiNsAttachObject ( Info->FieldNode, ObjDesc, AcpiNsGetType (Info->FieldNode)); ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set NamedObj %p [%4.4s], ObjDesc %p\n", Info->FieldNode, AcpiUtGetNodeName (Info->FieldNode), ObjDesc)); /* Remove local reference to the object */ AcpiUtRemoveReference (ObjDesc); return_ACPI_STATUS (Status); }
void AcpiNsDetachObject ( ACPI_NAMESPACE_NODE *Node) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_FUNCTION_TRACE (NsDetachObject); ObjDesc = Node->Object; if (!ObjDesc || (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA)) { return_VOID; } if (Node->Flags & ANOBJ_ALLOCATED_BUFFER) { /* Free the dynamic aml buffer */ if (ObjDesc->Common.Type == ACPI_TYPE_METHOD) { ACPI_FREE (ObjDesc->Method.AmlStart); } } /* Clear the Node entry in all cases */ Node->Object = NULL; if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND) { /* Unlink object from front of possible object list */ Node->Object = ObjDesc->Common.NextObject; /* Handle possible 2-descriptor object */ if (Node->Object && (Node->Object->Common.Type != ACPI_TYPE_LOCAL_DATA)) { Node->Object = Node->Object->Common.NextObject; } /* * Detach the object from any data objects (which are still held by * the namespace node) */ if (ObjDesc->Common.NextObject && ((ObjDesc->Common.NextObject)->Common.Type == ACPI_TYPE_LOCAL_DATA)) { ObjDesc->Common.NextObject = NULL; } } /* Reset the node type to untyped */ Node->Type = ACPI_TYPE_ANY; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Node %p [%4.4s] Object %p\n", Node, AcpiUtGetNodeName (Node), ObjDesc)); /* Remove one reference on the object (and all subobjects) */ AcpiUtRemoveReference (ObjDesc); return_VOID; }
ACPI_STATUS AcpiDsScopeStackPush ( ACPI_NAMESPACE_NODE *Node, ACPI_OBJECT_TYPE Type, ACPI_WALK_STATE *WalkState) { ACPI_GENERIC_STATE *ScopeInfo; ACPI_GENERIC_STATE *OldScopeInfo; ACPI_FUNCTION_TRACE (DsScopeStackPush); if (!Node) { /* Invalid scope */ ACPI_ERROR ((AE_INFO, "Null scope parameter")); return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Make sure object type is valid */ if (!AcpiUtValidObjectType (Type)) { ACPI_WARNING ((AE_INFO, "Invalid object type: 0x%X", Type)); } /* Allocate a new scope object */ ScopeInfo = AcpiUtCreateGenericState (); if (!ScopeInfo) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Init new scope object */ ScopeInfo->Common.DescriptorType = ACPI_DESC_TYPE_STATE_WSCOPE; ScopeInfo->Scope.Node = Node; ScopeInfo->Common.Value = (UINT16) Type; WalkState->ScopeDepth++; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%.2d] Pushed scope ", (UINT32) WalkState->ScopeDepth)); OldScopeInfo = WalkState->ScopeInfo; if (OldScopeInfo) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "[%4.4s] (%s)", AcpiUtGetNodeName (OldScopeInfo->Scope.Node), AcpiUtGetTypeName (OldScopeInfo->Common.Value))); } else { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "[\\___] (%s)", "ROOT")); } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, ", New scope -> [%4.4s] (%s)\n", AcpiUtGetNodeName (ScopeInfo->Scope.Node), AcpiUtGetTypeName (ScopeInfo->Common.Value))); /* Push new scope object onto stack */ AcpiUtPushGenericState (&WalkState->ScopeInfo, ScopeInfo); return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiEvAddressSpaceDispatch ( ACPI_OPERAND_OBJECT *RegionObj, ACPI_OPERAND_OBJECT *FieldObj, UINT32 Function, UINT32 RegionOffset, UINT32 BitWidth, UINT64 *Value) { ACPI_STATUS Status; ACPI_ADR_SPACE_HANDLER Handler; ACPI_ADR_SPACE_SETUP RegionSetup; ACPI_OPERAND_OBJECT *HandlerDesc; ACPI_OPERAND_OBJECT *RegionObj2; void *RegionContext = NULL; ACPI_CONNECTION_INFO *Context; ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch); RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); if (!RegionObj2) { return_ACPI_STATUS (AE_NOT_EXIST); } /* Ensure that there is a handler associated with this region */ HandlerDesc = RegionObj->Region.Handler; if (!HandlerDesc) { ACPI_ERROR ((AE_INFO, "No handler for Region [%4.4s] (%p) [%s]", AcpiUtGetNodeName (RegionObj->Region.Node), RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); return_ACPI_STATUS (AE_NOT_EXIST); } Context = HandlerDesc->AddressSpace.Context; /* * It may be the case that the region has never been initialized. * Some types of regions require special init code */ if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) { /* This region has not been initialized yet, do it */ RegionSetup = HandlerDesc->AddressSpace.Setup; if (!RegionSetup) { /* No initialization routine, exit with error */ ACPI_ERROR ((AE_INFO, "No init routine for region(%p) [%s]", RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); return_ACPI_STATUS (AE_NOT_EXIST); } /* * We must exit the interpreter because the region setup will * potentially execute control methods (for example, the _REG method * for this region) */ AcpiExExitInterpreter (); Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE, Context, &RegionContext); /* Re-enter the interpreter */ AcpiExEnterInterpreter (); /* Check for failure of the Region Setup */ if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "During region initialization: [%s]", AcpiUtGetRegionName (RegionObj->Region.SpaceId))); return_ACPI_STATUS (Status); } /* Region initialization may have been completed by RegionSetup */ if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) { RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE; if (RegionObj2->Extra.RegionContext) { /* The handler for this region was already installed */ ACPI_FREE (RegionContext); } else { /* * Save the returned context for use in all accesses to * this particular region */ RegionObj2->Extra.RegionContext = RegionContext; } } } /* We have everything we need, we can invoke the address space handler */ Handler = HandlerDesc->AddressSpace.Handler; ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", &RegionObj->Region.Handler->AddressSpace, Handler, ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset), AcpiUtGetRegionName (RegionObj->Region.SpaceId))); /* * Special handling for GenericSerialBus and GeneralPurposeIo: * There are three extra parameters that must be passed to the * handler via the context: * 1) Connection buffer, a resource template from Connection() op. * 2) Length of the above buffer. * 3) Actual access length from the AccessAs() op. */ if (((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS) || (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) && Context && FieldObj) { /* Get the Connection (ResourceTemplate) buffer */ Context->Connection = FieldObj->Field.ResourceBuffer; Context->Length = FieldObj->Field.ResourceLength; Context->AccessLength = FieldObj->Field.AccessLength; } if (!(HandlerDesc->AddressSpace.HandlerFlags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * For handlers other than the default (supplied) handlers, we must * exit the interpreter because the handler *might* block -- we don't * know what it will do, so we can't hold the lock on the intepreter. */ AcpiExExitInterpreter(); } /* Call the handler */ Status = Handler (Function, (RegionObj->Region.Address + RegionOffset), BitWidth, Value, Context, RegionObj2->Extra.RegionContext); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]", AcpiUtGetRegionName (RegionObj->Region.SpaceId))); } if (!(HandlerDesc->AddressSpace.HandlerFlags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * We just returned from a non-default handler, we must re-enter the * interpreter */ AcpiExEnterInterpreter (); } return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiNsInitOneObject ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_OBJECT_TYPE Type; ACPI_STATUS Status = AE_OK; ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context; ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_FUNCTION_NAME (NsInitOneObject); Info->ObjectCount++; /* And even then, we are only interested in a few object types */ Type = AcpiNsGetType (ObjHandle); ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { return (AE_OK); } /* Increment counters for object types we are looking for */ switch (Type) { case ACPI_TYPE_REGION: Info->OpRegionCount++; break; case ACPI_TYPE_BUFFER_FIELD: Info->FieldCount++; break; case ACPI_TYPE_LOCAL_BANK_FIELD: Info->FieldCount++; break; case ACPI_TYPE_BUFFER: Info->BufferCount++; break; case ACPI_TYPE_PACKAGE: Info->PackageCount++; break; default: /* No init required, just exit now */ return (AE_OK); } /* If the object is already initialized, nothing else to do */ if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) { return (AE_OK); } /* Must lock the interpreter before executing AML code */ AcpiExEnterInterpreter (); /* * Each of these types can contain executable AML code within the * declaration. */ switch (Type) { case ACPI_TYPE_REGION: Info->OpRegionInit++; Status = AcpiDsGetRegionArguments (ObjDesc); break; case ACPI_TYPE_BUFFER_FIELD: Info->FieldInit++; Status = AcpiDsGetBufferFieldArguments (ObjDesc); break; case ACPI_TYPE_LOCAL_BANK_FIELD: Info->FieldInit++; Status = AcpiDsGetBankFieldArguments (ObjDesc); break; case ACPI_TYPE_BUFFER: Info->BufferInit++; Status = AcpiDsGetBufferArguments (ObjDesc); break; case ACPI_TYPE_PACKAGE: Info->PackageInit++; Status = AcpiDsGetPackageArguments (ObjDesc); break; default: /* No other types can get here */ break; } if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Could not execute arguments for [%4.4s] (%s)", AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type))); } /* * Print a dot for each object unless we are going to print the entire * pathname */ if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES)) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, ".")); } /* * We ignore errors from above, and always return OK, since we don't want * to abort the walk on any single error. */ AcpiExExitInterpreter (); return (AE_OK); }
ACPI_STATUS AcpiDsRestartControlMethod ( ACPI_WALK_STATE *WalkState, ACPI_OPERAND_OBJECT *ReturnDesc) { ACPI_STATUS Status; int SameAsImplicitReturn; ACPI_FUNCTION_TRACE_PTR (DsRestartControlMethod, WalkState); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n", AcpiUtGetNodeName (WalkState->MethodNode), WalkState->MethodCallOp, ReturnDesc)); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n", WalkState->ReturnUsed, WalkState->Results, WalkState)); /* Did the called method return a value? */ if (ReturnDesc) { /* Is the implicit return object the same as the return desc? */ SameAsImplicitReturn = (WalkState->ImplicitReturnObj == ReturnDesc); /* Are we actually going to use the return value? */ if (WalkState->ReturnUsed) { /* Save the return value from the previous method */ Status = AcpiDsResultPush (ReturnDesc, WalkState); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ReturnDesc); return_ACPI_STATUS (Status); } /* * Save as THIS method's return value in case it is returned * immediately to yet another method */ WalkState->ReturnDesc = ReturnDesc; } /* * The following code is the optional support for the so-called * "implicit return". Some AML code assumes that the last value of the * method is "implicitly" returned to the caller, in the absence of an * explicit return value. * * Just save the last result of the method as the return value. * * NOTE: this is optional because the ASL language does not actually * support this behavior. */ else if (!AcpiDsDoImplicitReturn (ReturnDesc, WalkState, FALSE) || SameAsImplicitReturn) { /* * Delete the return value if it will not be used by the * calling method or remove one reference if the explicit return * is the same as the implicit return value. */ AcpiUtRemoveReference (ReturnDesc); } } return_ACPI_STATUS (AE_OK); }
void AcpiDmDumpMethodInfo ( ACPI_STATUS Status, ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op) { ACPI_PARSE_OBJECT *Next; ACPI_THREAD_STATE *Thread; ACPI_WALK_STATE *NextWalkState; ACPI_NAMESPACE_NODE *PreviousMethod = NULL; /* Ignore control codes, they are not errors */ if ((Status & AE_CODE_MASK) == AE_CODE_CONTROL) { return; } /* We may be executing a deferred opcode */ if (WalkState->DeferredNode) { AcpiOsPrintf ("Executing subtree for Buffer/Package/Region\n"); return; } /* * If there is no Thread, we are not actually executing a method. * This can happen when the iASL compiler calls the interpreter * to perform constant folding. */ Thread = WalkState->Thread; if (!Thread) { return; } /* Display exception and method name */ AcpiOsPrintf ("\n**** Exception %s during execution of method ", AcpiFormatException (Status)); AcpiNsPrintNodePathname (WalkState->MethodNode, NULL); /* Display stack of executing methods */ AcpiOsPrintf ("\n\nMethod Execution Stack:\n"); NextWalkState = Thread->WalkStateList; /* Walk list of linked walk states */ while (NextWalkState) { AcpiOsPrintf (" Method [%4.4s] executing: ", AcpiUtGetNodeName (NextWalkState->MethodNode)); /* First method is the currently executing method */ if (NextWalkState == WalkState) { if (Op) { /* Display currently executing ASL statement */ Next = Op->Common.Next; Op->Common.Next = NULL; AcpiDmDisassemble (NextWalkState, Op, ACPI_UINT32_MAX); Op->Common.Next = Next; } } else { /* * This method has called another method * NOTE: the method call parse subtree is already deleted at this * point, so we cannot disassemble the method invocation. */ AcpiOsPrintf ("Call to method "); AcpiNsPrintNodePathname (PreviousMethod, NULL); } PreviousMethod = NextWalkState->MethodNode; NextWalkState = NextWalkState->Next; AcpiOsPrintf ("\n"); } /* Display the method locals and arguments */ AcpiOsPrintf ("\n"); AcpiDmDisplayLocals (WalkState); AcpiOsPrintf ("\n"); AcpiDmDisplayArguments (WalkState); AcpiOsPrintf ("\n"); }
ACPI_STATUS AcpiNsLookup ( ACPI_GENERIC_STATE *ScopeInfo, char *Pathname, ACPI_OBJECT_TYPE Type, ACPI_INTERPRETER_MODE InterpreterMode, UINT32 Flags, ACPI_WALK_STATE *WalkState, ACPI_NAMESPACE_NODE **ReturnNode) { ACPI_STATUS Status; char *Path = Pathname; ACPI_NAMESPACE_NODE *PrefixNode; ACPI_NAMESPACE_NODE *CurrentNode = NULL; ACPI_NAMESPACE_NODE *ThisNode = NULL; UINT32 NumSegments; UINT32 NumCarats; ACPI_NAME SimpleName; ACPI_OBJECT_TYPE TypeToCheckFor; ACPI_OBJECT_TYPE ThisSearchType; UINT32 SearchParentFlag = ACPI_NS_SEARCH_PARENT; UINT32 LocalFlags; ACPI_FUNCTION_TRACE (NsLookup); if (!ReturnNode) { return_ACPI_STATUS (AE_BAD_PARAMETER); } LocalFlags = Flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT); *ReturnNode = ACPI_ENTRY_NOT_FOUND; AcpiGbl_NsLookupCount++; if (!AcpiGbl_RootNode) { return_ACPI_STATUS (AE_NO_NAMESPACE); } /* Get the prefix scope. A null scope means use the root scope */ if ((!ScopeInfo) || (!ScopeInfo->Scope.Node)) { ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Null scope prefix, using root node (%p)\n", AcpiGbl_RootNode)); PrefixNode = AcpiGbl_RootNode; } else { PrefixNode = ScopeInfo->Scope.Node; if (ACPI_GET_DESCRIPTOR_TYPE (PrefixNode) != ACPI_DESC_TYPE_NAMED) { ACPI_ERROR ((AE_INFO, "%p is not a namespace node [%s]", PrefixNode, AcpiUtGetDescriptorName (PrefixNode))); return_ACPI_STATUS (AE_AML_INTERNAL); } if (!(Flags & ACPI_NS_PREFIX_IS_SCOPE)) { /* * This node might not be a actual "scope" node (such as a * Device/Method, etc.) It could be a Package or other object * node. Backup up the tree to find the containing scope node. */ while (!AcpiNsOpensScope (PrefixNode->Type) && PrefixNode->Type != ACPI_TYPE_ANY) { PrefixNode = PrefixNode->Parent; } } } /* Save type. TBD: may be no longer necessary */ TypeToCheckFor = Type; /* * Begin examination of the actual pathname */ if (!Pathname) { /* A Null NamePath is allowed and refers to the root */ NumSegments = 0; ThisNode = AcpiGbl_RootNode; Path = ""; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Null Pathname (Zero segments), Flags=%X\n", Flags)); } else { /* * Name pointer is valid (and must be in internal name format) * * Check for scope prefixes: * * As represented in the AML stream, a namepath consists of an * optional scope prefix followed by a name segment part. * * If present, the scope prefix is either a Root Prefix (in * which case the name is fully qualified), or one or more * Parent Prefixes (in which case the name's scope is relative * to the current scope). */ if (*Path == (UINT8) AML_ROOT_PREFIX) { /* Pathname is fully qualified, start from the root */ ThisNode = AcpiGbl_RootNode; SearchParentFlag = ACPI_NS_NO_UPSEARCH; /* Point to name segment part */ Path++; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Path is absolute from root [%p]\n", ThisNode)); } else { /* Pathname is relative to current scope, start there */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Searching relative to prefix scope [%4.4s] (%p)\n", AcpiUtGetNodeName (PrefixNode), PrefixNode)); /* * Handle multiple Parent Prefixes (carat) by just getting * the parent node for each prefix instance. */ ThisNode = PrefixNode; NumCarats = 0; while (*Path == (UINT8) AML_PARENT_PREFIX) { /* Name is fully qualified, no search rules apply */ SearchParentFlag = ACPI_NS_NO_UPSEARCH; /* * Point past this prefix to the name segment * part or the next Parent Prefix */ Path++; /* Backup to the parent node */ NumCarats++; ThisNode = ThisNode->Parent; if (!ThisNode) { /* Current scope has no parent scope */ ACPI_ERROR ((AE_INFO, "ACPI path has too many parent prefixes (^) " "- reached beyond root node")); return_ACPI_STATUS (AE_NOT_FOUND); } } if (SearchParentFlag == ACPI_NS_NO_UPSEARCH) { ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Search scope is [%4.4s], path has %u carat(s)\n", AcpiUtGetNodeName (ThisNode), NumCarats)); } } /* * Determine the number of ACPI name segments in this pathname. * * The segment part consists of either: * - A Null name segment (0) * - A DualNamePrefix followed by two 4-byte name segments * - A MultiNamePrefix followed by a byte indicating the * number of segments and the segments themselves. * - A single 4-byte name segment * * Examine the name prefix opcode, if any, to determine the number of * segments. */ switch (*Path) { case 0: /* * Null name after a root or parent prefixes. We already * have the correct target node and there are no name segments. */ NumSegments = 0; Type = ThisNode->Type; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Prefix-only Pathname (Zero name segments), Flags=%X\n", Flags)); break; case AML_DUAL_NAME_PREFIX: /* More than one NameSeg, search rules do not apply */ SearchParentFlag = ACPI_NS_NO_UPSEARCH; /* Two segments, point to first name segment */ NumSegments = 2; Path++; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Dual Pathname (2 segments, Flags=%X)\n", Flags)); break; case AML_MULTI_NAME_PREFIX_OP: /* More than one NameSeg, search rules do not apply */ SearchParentFlag = ACPI_NS_NO_UPSEARCH; /* Extract segment count, point to first name segment */ Path++; NumSegments = (UINT32) (UINT8) *Path; Path++; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Multi Pathname (%u Segments, Flags=%X)\n", NumSegments, Flags)); break; default: /* * Not a Null name, no Dual or Multi prefix, hence there is * only one name segment and Pathname is already pointing to it. */ NumSegments = 1; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Simple Pathname (1 segment, Flags=%X)\n", Flags)); break; } ACPI_DEBUG_EXEC (AcpiNsPrintPathname (NumSegments, Path)); } /* * Search namespace for each segment of the name. Loop through and * verify (or add to the namespace) each name segment. * * The object type is significant only at the last name * segment. (We don't care about the types along the path, only * the type of the final target object.) */ ThisSearchType = ACPI_TYPE_ANY; CurrentNode = ThisNode; while (NumSegments && CurrentNode) { NumSegments--; if (!NumSegments) { /* This is the last segment, enable typechecking */ ThisSearchType = Type; /* * Only allow automatic parent search (search rules) if the caller * requested it AND we have a single, non-fully-qualified NameSeg */ if ((SearchParentFlag != ACPI_NS_NO_UPSEARCH) && (Flags & ACPI_NS_SEARCH_PARENT)) { LocalFlags |= ACPI_NS_SEARCH_PARENT; } /* Set error flag according to caller */ if (Flags & ACPI_NS_ERROR_IF_FOUND) { LocalFlags |= ACPI_NS_ERROR_IF_FOUND; } } /* Extract one ACPI name from the front of the pathname */ ACPI_MOVE_32_TO_32 (&SimpleName, Path); /* Try to find the single (4 character) ACPI name */ Status = AcpiNsSearchAndEnter (SimpleName, WalkState, CurrentNode, InterpreterMode, ThisSearchType, LocalFlags, &ThisNode); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_FOUND) { /* Name not found in ACPI namespace */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Name [%4.4s] not found in scope [%4.4s] %p\n", (char *) &SimpleName, (char *) &CurrentNode->Name, CurrentNode)); } *ReturnNode = ThisNode; return_ACPI_STATUS (Status); } /* More segments to follow? */ if (NumSegments > 0) { /* * If we have an alias to an object that opens a scope (such as a * device or processor), we need to dereference the alias here so * that we can access any children of the original node (via the * remaining segments). */ if (ThisNode->Type == ACPI_TYPE_LOCAL_ALIAS) { if (!ThisNode->Object) { return_ACPI_STATUS (AE_NOT_EXIST); } if (AcpiNsOpensScope (((ACPI_NAMESPACE_NODE *) ThisNode->Object)->Type)) { ThisNode = (ACPI_NAMESPACE_NODE *) ThisNode->Object; } } } /* Special handling for the last segment (NumSegments == 0) */ else { /* * Sanity typecheck of the target object: * * If 1) This is the last segment (NumSegments == 0) * 2) And we are looking for a specific type * (Not checking for TYPE_ANY) * 3) Which is not an alias * 4) Which is not a local type (TYPE_SCOPE) * 5) And the type of target object is known (not TYPE_ANY) * 6) And target object does not match what we are looking for * * Then we have a type mismatch. Just warn and ignore it. */ if ((TypeToCheckFor != ACPI_TYPE_ANY) && (TypeToCheckFor != ACPI_TYPE_LOCAL_ALIAS) && (TypeToCheckFor != ACPI_TYPE_LOCAL_METHOD_ALIAS) && (TypeToCheckFor != ACPI_TYPE_LOCAL_SCOPE) && (ThisNode->Type != ACPI_TYPE_ANY) && (ThisNode->Type != TypeToCheckFor)) { /* Complain about a type mismatch */ ACPI_WARNING ((AE_INFO, "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", ACPI_CAST_PTR (char, &SimpleName), AcpiUtGetTypeName (ThisNode->Type), AcpiUtGetTypeName (TypeToCheckFor))); } /* * If this is the last name segment and we are not looking for a * specific type, but the type of found object is known, use that * type to (later) see if it opens a scope. */ if (Type == ACPI_TYPE_ANY) { Type = ThisNode->Type; } } /* Point to next name segment and make this node current */ Path += ACPI_NAME_SIZE; CurrentNode = ThisNode; }
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 = AcpiNsValidateHandle (ObjHandle); if (!ThisNode) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Invalid object handle %p\n", ObjHandle)); return (AE_OK); } Type = ThisNode->Type; /* Check if the owner matches */ if ((Info->OwnerId != ACPI_OWNER_ID_MAX) && (Info->OwnerId != ThisNode->OwnerId)) { return (AE_OK); } if (!(Info->DisplayType & ACPI_DISPLAY_SHORT)) { /* 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_WARNING ((AE_INFO, "Invalid ACPI Object Type 0x%08X", Type)); } AcpiOsPrintf ("%4.4s", AcpiUtGetNodeName (ThisNode)); } /* Now we can print out the pertinent information */ AcpiOsPrintf (" %-12s %p %2.2X ", AcpiUtGetTypeName (Type), ThisNode, ThisNode->OwnerId); DbgLevel = AcpiDbgLevel; AcpiDbgLevel = 0; ObjDesc = AcpiNsGetAttachedObject (ThisNode); AcpiDbgLevel = DbgLevel; /* Temp nodes are those nodes created by a control method */ if (ThisNode->Flags & ANOBJ_TEMPORARY) { AcpiOsPrintf ("(T) "); } switch (Info->DisplayType & ACPI_DISPLAY_MASK) { case ACPI_DISPLAY_SUMMARY: if (!ObjDesc) { /* No attached object. Some types should always have an object */ switch (Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_PACKAGE: case ACPI_TYPE_BUFFER: case ACPI_TYPE_STRING: case ACPI_TYPE_METHOD: AcpiOsPrintf ("<No attached object>"); break; default: break; } AcpiOsPrintf ("\n"); return (AE_OK); } switch (Type) { case ACPI_TYPE_PROCESSOR: AcpiOsPrintf ("ID %02X Len %02X Addr %8.8X%8.8X\n", ObjDesc->Processor.ProcId, ObjDesc->Processor.Length, ACPI_FORMAT_UINT64 (ObjDesc->Processor.Address)); break; case ACPI_TYPE_DEVICE: AcpiOsPrintf ("Notify Object: %p\n", 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_FORMAT_UINT64 (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, 80); 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_FORMAT_UINT64 (ObjDesc->Region.Address), ObjDesc->Region.Length); } else { AcpiOsPrintf (" [Address/Length not yet evaluated]\n"); } break; case ACPI_TYPE_LOCAL_REFERENCE: AcpiOsPrintf ("[%s]\n", AcpiUtGetReferenceName (ObjDesc)); break; case ACPI_TYPE_BUFFER_FIELD: if (ObjDesc->BufferField.BufferObj && ObjDesc->BufferField.BufferObj->Buffer.Node) { AcpiOsPrintf ("Buf [%4.4s]", AcpiUtGetNodeName ( ObjDesc->BufferField.BufferObj->Buffer.Node)); } break; case ACPI_TYPE_LOCAL_REGION_FIELD: AcpiOsPrintf ("Rgn [%4.4s]", AcpiUtGetNodeName ( ObjDesc->CommonField.RegionObj->Region.Node)); break; case ACPI_TYPE_LOCAL_BANK_FIELD: AcpiOsPrintf ("Rgn [%4.4s] Bnk [%4.4s]", AcpiUtGetNodeName ( ObjDesc->CommonField.RegionObj->Region.Node), AcpiUtGetNodeName ( ObjDesc->BankField.BankObj->CommonField.Node)); break; case ACPI_TYPE_LOCAL_INDEX_FIELD: AcpiOsPrintf ("Idx [%4.4s] Dat [%4.4s]", AcpiUtGetNodeName ( ObjDesc->IndexField.IndexObj->CommonField.Node), AcpiUtGetNodeName ( ObjDesc->IndexField.DataObj->CommonField.Node)); break; case ACPI_TYPE_LOCAL_ALIAS: case ACPI_TYPE_LOCAL_METHOD_ALIAS: AcpiOsPrintf ("Target %4.4s (%p)\n", AcpiUtGetNodeName (ObjDesc), 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 %.3X 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%u)", 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 (" I:%8.8X8.8%X\n", ACPI_FORMAT_UINT64 (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); ACPI_DUMP_BUFFER (ObjDesc, BytesToDump); break; case ACPI_DESC_TYPE_OPERAND: ObjType = ObjDesc->Common.Type; if (ObjType > ACPI_TYPE_LOCAL_MAX) { AcpiOsPrintf ( "(Pointer to ACPI Object type %.2X [UNKNOWN])\n", ObjType); BytesToDump = 32; } else { AcpiOsPrintf ( "(Pointer to ACPI Object type %.2X [%s])\n", ObjType, AcpiUtGetTypeName (ObjType)); BytesToDump = sizeof (ACPI_OPERAND_OBJECT); } ACPI_DUMP_BUFFER (ObjDesc, BytesToDump); break; default: break; } /* 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_BUFFER: case ACPI_TYPE_STRING: /* * NOTE: takes advantage of common fields between string/buffer */ BytesToDump = ObjDesc->String.Length; ObjDesc = (void *) ObjDesc->String.Pointer; AcpiOsPrintf ("(Buffer/String pointer %p length %X)\n", ObjDesc, BytesToDump); ACPI_DUMP_BUFFER (ObjDesc, BytesToDump); goto Cleanup; 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); }
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); }
static ACPI_STATUS AcpiDsInitOneObject ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context; ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; ACPI_OBJECT_TYPE Type; ACPI_STATUS Status; ACPI_FUNCTION_ENTRY (); /* * We are only interested in NS nodes owned by the table that * was just loaded */ if (Node->OwnerId != Info->OwnerId) { return (AE_OK); } Info->ObjectCount++; /* And even then, we are only interested in a few object types */ Type = AcpiNsGetType (ObjHandle); switch (Type) { case ACPI_TYPE_REGION: Status = AcpiDsInitializeRegion (ObjHandle); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "During Region initialization %p [%4.4s]", ObjHandle, AcpiUtGetNodeName (ObjHandle))); } Info->OpRegionCount++; break; case ACPI_TYPE_METHOD: Info->MethodCount++; break; case ACPI_TYPE_DEVICE: Info->DeviceCount++; break; default: break; } /* * We ignore errors from above, and always return OK, since * we don't want to abort the walk on a single error. */ return (AE_OK); }
static ACPI_STATUS AcpiExSetupRegion ( ACPI_OPERAND_OBJECT *ObjDesc, UINT32 FieldDatumByteOffset) { ACPI_STATUS Status = AE_OK; ACPI_OPERAND_OBJECT *RgnDesc; UINT8 SpaceId; ACPI_FUNCTION_TRACE_U32 (ExSetupRegion, FieldDatumByteOffset); RgnDesc = ObjDesc->CommonField.RegionObj; /* We must have a valid region */ if (RgnDesc->Common.Type != ACPI_TYPE_REGION) { ACPI_ERROR ((AE_INFO, "Needed Region, found type 0x%X (%s)", RgnDesc->Common.Type, AcpiUtGetObjectTypeName (RgnDesc))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } SpaceId = RgnDesc->Region.SpaceId; /* Validate the Space ID */ if (!AcpiIsValidSpaceId (SpaceId)) { ACPI_ERROR ((AE_INFO, "Invalid/unknown Address Space ID: 0x%2.2X", SpaceId)); return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID); } /* * If the Region Address and Length have not been previously evaluated, * evaluate them now and save the results. */ if (!(RgnDesc->Common.Flags & AOPOBJ_DATA_VALID)) { Status = AcpiDsGetRegionArguments (RgnDesc); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } /* * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear * address space and the request cannot be directly validated */ if (SpaceId == ACPI_ADR_SPACE_SMBUS || SpaceId == ACPI_ADR_SPACE_GSBUS || SpaceId == ACPI_ADR_SPACE_IPMI) { /* SMBus or IPMI has a non-linear address space */ return_ACPI_STATUS (AE_OK); } #ifdef ACPI_UNDER_DEVELOPMENT /* * If the Field access is AnyAcc, we can now compute the optimal * access (because we know know the length of the parent region) */ if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) { if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } #endif /* * Validate the request. The entire request from the byte offset for a * length of one field datum (access width) must fit within the region. * (Region length is specified in bytes) */ if (RgnDesc->Region.Length < (ObjDesc->CommonField.BaseByteOffset + FieldDatumByteOffset + ObjDesc->CommonField.AccessByteWidth)) { if (AcpiGbl_EnableInterpreterSlack) { /* * Slack mode only: We will go ahead and allow access to this * field if it is within the region length rounded up to the next * access width boundary. ACPI_SIZE cast for 64-bit compile. */ if (ACPI_ROUND_UP (RgnDesc->Region.Length, ObjDesc->CommonField.AccessByteWidth) >= ((ACPI_SIZE) ObjDesc->CommonField.BaseByteOffset + ObjDesc->CommonField.AccessByteWidth + FieldDatumByteOffset)) { return_ACPI_STATUS (AE_OK); } } if (RgnDesc->Region.Length < ObjDesc->CommonField.AccessByteWidth) { /* * This is the case where the AccessType (AccWord, etc.) is wider * than the region itself. For example, a region of length one * byte, and a field with Dword access specified. */ ACPI_ERROR ((AE_INFO, "Field [%4.4s] access width (%u bytes) " "too large for region [%4.4s] (length %u)", AcpiUtGetNodeName (ObjDesc->CommonField.Node), ObjDesc->CommonField.AccessByteWidth, AcpiUtGetNodeName (RgnDesc->Region.Node), RgnDesc->Region.Length)); } /* * Offset rounded up to next multiple of field width * exceeds region length, indicate an error */ ACPI_ERROR ((AE_INFO, "Field [%4.4s] Base+Offset+Width %u+%u+%u " "is beyond end of region [%4.4s] (length %u)", AcpiUtGetNodeName (ObjDesc->CommonField.Node), ObjDesc->CommonField.BaseByteOffset, FieldDatumByteOffset, ObjDesc->CommonField.AccessByteWidth, AcpiUtGetNodeName (RgnDesc->Region.Node), RgnDesc->Region.Length)); return_ACPI_STATUS (AE_AML_REGION_LIMIT); } return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiEvInstallSpaceHandler ( ACPI_NAMESPACE_NODE *Node, ACPI_ADR_SPACE_TYPE SpaceId, ACPI_ADR_SPACE_HANDLER Handler, ACPI_ADR_SPACE_SETUP Setup, void *Context) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerObj; ACPI_STATUS Status; ACPI_OBJECT_TYPE Type; UINT8 Flags = 0; ACPI_FUNCTION_TRACE (EvInstallSpaceHandler); /* * This registration is valid for only the types below and the root. This * is where the default handlers get placed. */ if ((Node->Type != ACPI_TYPE_DEVICE) && (Node->Type != ACPI_TYPE_PROCESSOR) && (Node->Type != ACPI_TYPE_THERMAL) && (Node != AcpiGbl_RootNode)) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } if (Handler == ACPI_DEFAULT_HANDLER) { Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; switch (SpaceId) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: Handler = AcpiExSystemMemorySpaceHandler; Setup = AcpiEvSystemMemoryRegionSetup; break; case ACPI_ADR_SPACE_SYSTEM_IO: Handler = AcpiExSystemIoSpaceHandler; Setup = AcpiEvIoSpaceRegionSetup; break; case ACPI_ADR_SPACE_PCI_CONFIG: Handler = AcpiExPciConfigSpaceHandler; Setup = AcpiEvPciConfigRegionSetup; break; case ACPI_ADR_SPACE_CMOS: Handler = AcpiExCmosSpaceHandler; Setup = AcpiEvCmosRegionSetup; break; case ACPI_ADR_SPACE_PCI_BAR_TARGET: Handler = AcpiExPciBarSpaceHandler; Setup = AcpiEvPciBarRegionSetup; break; case ACPI_ADR_SPACE_DATA_TABLE: Handler = AcpiExDataTableSpaceHandler; Setup = NULL; break; default: Status = AE_BAD_PARAMETER; goto UnlockAndExit; } } /* If the caller hasn't specified a setup routine, use the default */ if (!Setup) { Setup = AcpiEvDefaultRegionSetup; } /* Check for an existing internal object */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* * The attached device object already exists. Make sure the handler * is not already installed. */ HandlerObj = ObjDesc->Device.Handler; /* Walk the handler list for this device */ while (HandlerObj) { /* Same SpaceId indicates a handler already installed */ if (HandlerObj->AddressSpace.SpaceId == SpaceId) { if (HandlerObj->AddressSpace.Handler == Handler) { /* * It is (relatively) OK to attempt to install the SAME * handler twice. This can easily happen with the * PCI_Config space. */ Status = AE_SAME_HANDLER; goto UnlockAndExit; } else { /* A handler is already installed */ Status = AE_ALREADY_EXISTS; } goto UnlockAndExit; } /* Walk the linked list of handlers */ HandlerObj = HandlerObj->AddressSpace.Next; } } else { ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Creating object on Device %p while installing handler\n", Node)); /* ObjDesc does not exist, create one */ if (Node->Type == ACPI_TYPE_ANY) { Type = ACPI_TYPE_DEVICE; } else { Type = Node->Type; } ObjDesc = AcpiUtCreateInternalObject (Type); if (!ObjDesc) { Status = AE_NO_MEMORY; goto UnlockAndExit; } /* Init new descriptor */ ObjDesc->Common.Type = (UINT8) Type; /* Attach the new object to the Node */ Status = AcpiNsAttachObject (Node, ObjDesc, Type); /* Remove local reference to the object */ AcpiUtRemoveReference (ObjDesc); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } } ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", AcpiUtGetRegionName (SpaceId), SpaceId, AcpiUtGetNodeName (Node), Node, ObjDesc)); /* * Install the handler * * At this point there is no existing handler. Just allocate the object * for the handler and link it into the list. */ HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER); if (!HandlerObj) { Status = AE_NO_MEMORY; goto UnlockAndExit; } /* Init handler obj */ HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId; HandlerObj->AddressSpace.HandlerFlags = Flags; HandlerObj->AddressSpace.RegionList = NULL; HandlerObj->AddressSpace.Node = Node; HandlerObj->AddressSpace.Handler = Handler; HandlerObj->AddressSpace.Context = Context; HandlerObj->AddressSpace.Setup = Setup; /* Install at head of Device.AddressSpace list */ HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler; /* * The Device object is the first reference on the HandlerObj. * Each region that uses the handler adds a reference. */ ObjDesc->Device.Handler = HandlerObj; /* * Walk the namespace finding all of the regions this * handler will manage. * * Start at the device and search the branch toward * the leaf nodes until either the leaf is encountered or * a device is detected that has an address handler of the * same type. * * In either case, back up and search down the remainder * of the branch */ Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL, HandlerObj, NULL); UnlockAndExit: return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiEvPciConfigRegionSetup ( ACPI_HANDLE Handle, UINT32 Function, void *HandlerContext, void **RegionContext) { ACPI_STATUS Status = AE_OK; UINT64 PciValue; ACPI_PCI_ID *PciId = *RegionContext; ACPI_OPERAND_OBJECT *HandlerObj; ACPI_NAMESPACE_NODE *ParentNode; ACPI_NAMESPACE_NODE *PciRootNode; ACPI_NAMESPACE_NODE *PciDeviceNode; ACPI_OPERAND_OBJECT *RegionObj = (ACPI_OPERAND_OBJECT *) Handle; ACPI_FUNCTION_TRACE (EvPciConfigRegionSetup); HandlerObj = RegionObj->Region.Handler; if (!HandlerObj) { /* * No installed handler. This shouldn't happen because the dispatch * routine checks before we get here, but we check again just in case. */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Attempting to init a region %p, with no handler\n", RegionObj)); return_ACPI_STATUS (AE_NOT_EXIST); } *RegionContext = NULL; if (Function == ACPI_REGION_DEACTIVATE) { if (PciId) { ACPI_FREE (PciId); } return_ACPI_STATUS (Status); } ParentNode = RegionObj->Region.Node->Parent; /* * Get the _SEG and _BBN values from the device upon which the handler * is installed. * * We need to get the _SEG and _BBN objects relative to the PCI BUS device. * This is the device the handler has been registered to handle. */ /* * If the AddressSpace.Node is still pointing to the root, we need * to scan upward for a PCI Root bridge and re-associate the OpRegion * handlers with that device. */ if (HandlerObj->AddressSpace.Node == AcpiGbl_RootNode) { /* Start search from the parent object */ PciRootNode = ParentNode; while (PciRootNode != AcpiGbl_RootNode) { /* Get the _HID/_CID in order to detect a RootBridge */ if (AcpiEvIsPciRootBridge (PciRootNode)) { /* Install a handler for this PCI root bridge */ Status = AcpiInstallAddressSpaceHandler ( (ACPI_HANDLE) PciRootNode, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if (ACPI_FAILURE (Status)) { if (Status == AE_SAME_HANDLER) { /* * It is OK if the handler is already installed on the * root bridge. Still need to return a context object * for the new PCI_Config operation region, however. */ Status = AE_OK; } else { ACPI_EXCEPTION ((AE_INFO, Status, "Could not install PciConfig handler " "for Root Bridge %4.4s", AcpiUtGetNodeName (PciRootNode))); } } break; } PciRootNode = PciRootNode->Parent; } /* PCI root bridge not found, use namespace root node */ } else { PciRootNode = HandlerObj->AddressSpace.Node; } /* * If this region is now initialized, we are done. * (InstallAddressSpaceHandler could have initialized it) */ if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) { return_ACPI_STATUS (AE_OK); } /* Region is still not initialized. Create a new context */ PciId = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PCI_ID)); if (!PciId) { return_ACPI_STATUS (AE_NO_MEMORY); } /* * For PCI_Config space access, we need the segment, bus, device and * function numbers. Acquire them here. * * Find the parent device object. (This allows the operation region to be * within a subscope under the device, such as a control method.) */ PciDeviceNode = RegionObj->Region.Node; while (PciDeviceNode && (PciDeviceNode->Type != ACPI_TYPE_DEVICE)) { PciDeviceNode = PciDeviceNode->Parent; } if (!PciDeviceNode) { ACPI_FREE (PciId); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* * Get the PCI device and function numbers from the _ADR object * contained in the parent's scope. */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, PciDeviceNode, &PciValue); /* * The default is zero, and since the allocation above zeroed the data, * just do nothing on failure. */ if (ACPI_SUCCESS (Status)) { PciId->Device = ACPI_HIWORD (ACPI_LODWORD (PciValue)); PciId->Function = ACPI_LOWORD (ACPI_LODWORD (PciValue)); } /* The PCI segment number comes from the _SEG method */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__SEG, PciRootNode, &PciValue); if (ACPI_SUCCESS (Status)) { PciId->Segment = ACPI_LOWORD (PciValue); } /* The PCI bus number comes from the _BBN method */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__BBN, PciRootNode, &PciValue); if (ACPI_SUCCESS (Status)) { PciId->Bus = ACPI_LOWORD (PciValue); } /* Complete/update the PCI ID for this device */ Status = AcpiHwDerivePciId (PciId, PciRootNode, RegionObj->Region.Node); if (ACPI_FAILURE (Status)) { ACPI_FREE (PciId); return_ACPI_STATUS (Status); } *RegionContext = PciId; return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiExReleaseMutex ( ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status = AE_OK; UINT8 PreviousSyncLevel; ACPI_THREAD_STATE *OwnerThread; ACPI_FUNCTION_TRACE (ExReleaseMutex); if (!ObjDesc) { return_ACPI_STATUS (AE_BAD_PARAMETER); } OwnerThread = ObjDesc->Mutex.OwnerThread; /* The mutex must have been previously acquired in order to release it */ if (!OwnerThread) { ACPI_ERROR ((AE_INFO, "Cannot release Mutex [%4.4s], not acquired", AcpiUtGetNodeName (ObjDesc->Mutex.Node))); return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED); } /* Must have a valid thread ID */ if (!WalkState->Thread) { ACPI_ERROR ((AE_INFO, "Cannot release Mutex [%4.4s], null thread info", AcpiUtGetNodeName (ObjDesc->Mutex.Node))); return_ACPI_STATUS (AE_AML_INTERNAL); } /* * The Mutex is owned, but this thread must be the owner. * Special case for Global Lock, any thread can release */ if ((OwnerThread->ThreadId != WalkState->Thread->ThreadId) && (ObjDesc != AcpiGbl_GlobalLockMutex)) { ACPI_ERROR ((AE_INFO, "Thread %u cannot release Mutex [%4.4s] acquired by thread %u", (UINT32) WalkState->Thread->ThreadId, AcpiUtGetNodeName (ObjDesc->Mutex.Node), (UINT32) OwnerThread->ThreadId)); return_ACPI_STATUS (AE_AML_NOT_OWNER); } /* * The sync level of the mutex must be equal to the current sync level. In * other words, the current level means that at least one mutex at that * level is currently being held. Attempting to release a mutex of a * different level can only mean that the mutex ordering rule is being * violated. This behavior is clarified in ACPI 4.0 specification. */ if (ObjDesc->Mutex.SyncLevel != OwnerThread->CurrentSyncLevel) { ACPI_ERROR ((AE_INFO, "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u", AcpiUtGetNodeName (ObjDesc->Mutex.Node), ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel)); return_ACPI_STATUS (AE_AML_MUTEX_ORDER); } /* * Get the previous SyncLevel from the head of the acquired mutex list. * This handles the case where several mutexes at the same level have been * acquired, but are not released in reverse order. */ PreviousSyncLevel = OwnerThread->AcquiredMutexList->Mutex.OriginalSyncLevel; Status = AcpiExReleaseMutexObject (ObjDesc); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (ObjDesc->Mutex.AcquisitionDepth == 0) { /* Restore the previous SyncLevel */ OwnerThread->CurrentSyncLevel = PreviousSyncLevel; } return_ACPI_STATUS (Status); }