Example #1
0
ACPI_NAMESPACE_NODE *
AcpiNsGetNextNodeTyped (
    ACPI_OBJECT_TYPE        Type,
    ACPI_NAMESPACE_NODE     *ParentNode,
    ACPI_NAMESPACE_NODE     *ChildNode)
{
    ACPI_NAMESPACE_NODE     *NextNode = NULL;


    ACPI_FUNCTION_ENTRY ();


    NextNode = AcpiNsGetNextNode (ParentNode, ChildNode);

    /* If any type is OK, we are done */

    if (Type == ACPI_TYPE_ANY)
    {
        /* NextNode is NULL if we are at the end-of-list */

        return (NextNode);
    }

    /* Must search for the node -- but within this scope only */

    while (NextNode)
    {
        /* If type matches, we are done */

        if (NextNode->Type == Type)
        {
            return (NextNode);
        }

        /* Otherwise, move on to the next peer node */

        NextNode = NextNode->Peer;
    }

    /* Not found */

    return (NULL);
}
Example #2
0
void
AcpiNsDeleteNamespaceByOwner (
    ACPI_OWNER_ID            OwnerId)
{
    ACPI_NAMESPACE_NODE     *ChildNode;
    ACPI_NAMESPACE_NODE     *DeletionNode;
    ACPI_NAMESPACE_NODE     *ParentNode;
    UINT32                  Level;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE_U32 (NsDeleteNamespaceByOwner, OwnerId);


    if (OwnerId == 0)
    {
        return_VOID;
    }

    /* Lock namespace for possible update */

    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return_VOID;
    }

    DeletionNode = NULL;
    ParentNode = AcpiGbl_RootNode;
    ChildNode = NULL;
    Level = 1;

    /*
     * Traverse the tree of nodes until we bubble back up
     * to where we started.
     */
    while (Level > 0)
    {
        /*
         * Get the next child of this parent node. When ChildNode is NULL,
         * the first child of the parent is returned
         */
        ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);

        if (DeletionNode)
        {
            AcpiNsDeleteChildren (DeletionNode);
            AcpiNsRemoveNode (DeletionNode);
            DeletionNode = NULL;
        }

        if (ChildNode)
        {
            if (ChildNode->OwnerId == OwnerId)
            {
                /* Found a matching child node - detach any attached object */

                AcpiNsDetachObject (ChildNode);
            }

            /* Check if this node has any children */

            if (ChildNode->Child)
            {
                /*
                 * There is at least one child of this node,
                 * visit the node
                 */
                Level++;
                ParentNode = ChildNode;
                ChildNode  = NULL;
            }
            else if (ChildNode->OwnerId == OwnerId)
            {
                DeletionNode = ChildNode;
            }
        }
        else
        {
            /*
             * No more children of this parent node.
             * Move up to the grandparent.
             */
            Level--;
            if (Level != 0)
            {
                if (ParentNode->OwnerId == OwnerId)
                {
                    DeletionNode = ParentNode;
                }
            }

            /* New "last child" is this parent node */

            ChildNode = ParentNode;

            /* Move up the tree to the grandparent */

            ParentNode = ParentNode->Parent;
        }
    }

    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    return_VOID;
}
Example #3
0
void
AcpiNsDeleteNamespaceSubtree (
    ACPI_NAMESPACE_NODE     *ParentNode)
{
    ACPI_NAMESPACE_NODE     *ChildNode = NULL;
    UINT32                  Level = 1;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree);


    if (!ParentNode)
    {
        return_VOID;
    }

    /* Lock namespace for possible update */

    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return_VOID;
    }

    /*
     * Traverse the tree of objects until we bubble back up
     * to where we started.
     */
    while (Level > 0)
    {
        /* Get the next node in this scope (NULL if none) */

        ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
        if (ChildNode)
        {
            /* Found a child node - detach any attached object */

            AcpiNsDetachObject (ChildNode);

            /* Check if this node has any children */

            if (ChildNode->Child)
            {
                /*
                 * There is at least one child of this node,
                 * visit the node
                 */
                Level++;
                ParentNode = ChildNode;
                ChildNode  = NULL;
            }
        }
        else
        {
            /*
             * No more children of this parent node.
             * Move up to the grandparent.
             */
            Level--;

            /*
             * Now delete all of the children of this parent
             * all at the same time.
             */
            AcpiNsDeleteChildren (ParentNode);

            /* New "last child" is this parent node */

            ChildNode = ParentNode;

            /* Move up the tree to the grandparent */

            ParentNode = ParentNode->Parent;
        }
    }

    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    return_VOID;
}
Example #4
0
ACPI_STATUS
AcpiNsWalkNamespace (
    ACPI_OBJECT_TYPE        Type,
    ACPI_HANDLE             StartNode,
    UINT32                  MaxDepth,
    UINT32                  Flags,
    ACPI_WALK_CALLBACK      DescendingCallback,
    ACPI_WALK_CALLBACK      AscendingCallback,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_STATUS             Status;
    ACPI_STATUS             MutexStatus;
    ACPI_NAMESPACE_NODE     *ChildNode;
    ACPI_NAMESPACE_NODE     *ParentNode;
    ACPI_OBJECT_TYPE        ChildType;
    UINT32                  Level;
    BOOLEAN                 NodePreviouslyVisited = FALSE;


    ACPI_FUNCTION_TRACE (NsWalkNamespace);


    /* Special case for the namespace Root Node */

    if (StartNode == ACPI_ROOT_OBJECT)
    {
        StartNode = AcpiGbl_RootNode;
    }

    /* Null child means "get first node" */

    ParentNode  = StartNode;
    ChildNode   = AcpiNsGetNextNode (ParentNode, NULL);
    ChildType   = ACPI_TYPE_ANY;
    Level       = 1;

    /*
     * Traverse the tree of nodes until we bubble back up to where we
     * started. When Level is zero, the loop is done because we have
     * bubbled up to (and passed) the original parent handle (StartEntry)
     */
    while (Level > 0 && ChildNode)
    {
        Status = AE_OK;

        /* Found next child, get the type if we are not searching for ANY */

        if (Type != ACPI_TYPE_ANY)
        {
            ChildType = ChildNode->Type;
        }

        /*
         * Ignore all temporary namespace nodes (created during control
         * method execution) unless told otherwise. These temporary nodes
         * can cause a race condition because they can be deleted during
         * the execution of the user function (if the namespace is
         * unlocked before invocation of the user function.) Only the
         * debugger namespace dump will examine the temporary nodes.
         */
        if ((ChildNode->Flags & ANOBJ_TEMPORARY) &&
            !(Flags & ACPI_NS_WALK_TEMP_NODES))
        {
            Status = AE_CTRL_DEPTH;
        }

        /* Type must match requested type */

        else if (ChildType == Type)
        {
            /*
             * Found a matching node, invoke the user callback function.
             * Unlock the namespace if flag is set.
             */
            if (Flags & ACPI_NS_WALK_UNLOCK)
            {
                MutexStatus = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
                if (ACPI_FAILURE (MutexStatus))
                {
                    return_ACPI_STATUS (MutexStatus);
                }
            }

            /*
             * Invoke the user function, either descending, ascending,
             * or both.
             */
            if (!NodePreviouslyVisited)
            {
                if (DescendingCallback)
                {
                    Status = DescendingCallback (ChildNode, Level,
                                Context, ReturnValue);
                }
            }
            else
            {
                if (AscendingCallback)
                {
                    Status = AscendingCallback (ChildNode, Level,
                                Context, ReturnValue);
                }
            }

            if (Flags & ACPI_NS_WALK_UNLOCK)
            {
                MutexStatus = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
                if (ACPI_FAILURE (MutexStatus))
                {
                    return_ACPI_STATUS (MutexStatus);
                }
            }

            switch (Status)
            {
            case AE_OK:
            case AE_CTRL_DEPTH:

                /* Just keep going */
                break;

            case AE_CTRL_TERMINATE:

                /* Exit now, with OK status */

                return_ACPI_STATUS (AE_OK);

            default:

                /* All others are valid exceptions */

                return_ACPI_STATUS (Status);
            }
        }

        /*
         * Depth first search: Attempt to go down another level in the
         * namespace if we are allowed to. Don't go any further if we have
         * reached the caller specified maximum depth or if the user
         * function has specified that the maximum depth has been reached.
         */
        if (!NodePreviouslyVisited &&
            (Level < MaxDepth) &&
            (Status != AE_CTRL_DEPTH))
        {
            if (ChildNode->Child)
            {
                /* There is at least one child of this node, visit it */

                Level++;
                ParentNode = ChildNode;
                ChildNode = AcpiNsGetNextNode (ParentNode, NULL);
                continue;
            }
        }

        /* No more children, re-visit this node */

        if (!NodePreviouslyVisited)
        {
            NodePreviouslyVisited = TRUE;
            continue;
        }

        /* No more children, visit peers */

        ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
        if (ChildNode)
        {
            NodePreviouslyVisited = FALSE;
        }

        /* No peers, re-visit parent */

        else
        {
            /*
             * No more children of this node (AcpiNsGetNextNode failed), go
             * back upwards in the namespace tree to the node's parent.
             */
            Level--;
            ChildNode = ParentNode;
            ParentNode = ParentNode->Parent;

            NodePreviouslyVisited = TRUE;
        }
    }

    /* Complete walk, not terminated by user function */

    return_ACPI_STATUS (AE_OK);
}
Example #5
0
void
AcpiNsDeleteNamespaceSubtree (
    ACPI_NAMESPACE_NODE     *ParentNode)
{
    ACPI_NAMESPACE_NODE     *ChildNode = NULL;
    UINT32                  Level = 1;


    ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree);


    if (!ParentNode)
    {
        return_VOID;
    }

    /*
     * Traverse the tree of objects until we bubble back up
     * to where we started.
     */
    while (Level > 0)
    {
        /* Get the next node in this scope (NULL if none) */

        ChildNode = AcpiNsGetNextNode (ACPI_TYPE_ANY, ParentNode, ChildNode);
        if (ChildNode)
        {
            /* Found a child node - detach any attached object */

            AcpiNsDetachObject (ChildNode);

            /* Check if this node has any children */

            if (AcpiNsGetNextNode (ACPI_TYPE_ANY, ChildNode, NULL))
            {
                /*
                 * There is at least one child of this node,
                 * visit the node
                 */
                Level++;
                ParentNode = ChildNode;
                ChildNode  = NULL;
            }
        }
        else
        {
            /*
             * No more children of this parent node.
             * Move up to the grandparent.
             */
            Level--;

            /*
             * Now delete all of the children of this parent
             * all at the same time.
             */
            AcpiNsDeleteChildren (ParentNode);

            /* New "last child" is this parent node */

            ChildNode = ParentNode;

            /* Move up the tree to the grandparent */

            ParentNode = AcpiNsGetParentNode (ParentNode);
        }
    }

    return_VOID;
}
Example #6
0
static void
AcpiEvOrphanEcRegMethod (
    ACPI_NAMESPACE_NODE     *EcDeviceNode)
{
    ACPI_HANDLE             RegMethod;
    ACPI_NAMESPACE_NODE     *NextNode;
    ACPI_STATUS             Status;
    ACPI_OBJECT_LIST        Args;
    ACPI_OBJECT             Objects[2];


    ACPI_FUNCTION_TRACE (EvOrphanEcRegMethod);


    if (!EcDeviceNode)
    {
        return_VOID;
    }

    /* Namespace is currently locked, must release */

    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);

    /* Get a handle to a _REG method immediately under the EC device */

    Status = AcpiGetHandle (EcDeviceNode, METHOD_NAME__REG, &RegMethod);
    if (ACPI_FAILURE (Status))
    {
        goto Exit; /* There is no _REG method present */
    }

    /*
     * Execute the _REG method only if there is no Operation Region in
     * this scope with the Embedded Controller space ID. Otherwise, it
     * will already have been executed. Note, this allows for Regions
     * with other space IDs to be present; but the code below will then
     * execute the _REG method with the EmbeddedControl SpaceID argument.
     */
    NextNode = AcpiNsGetNextNode (EcDeviceNode, NULL);
    while (NextNode)
    {
        if ((NextNode->Type == ACPI_TYPE_REGION) &&
            (NextNode->Object) &&
            (NextNode->Object->Region.SpaceId == ACPI_ADR_SPACE_EC))
        {
            goto Exit; /* Do not execute the _REG */
        }

        NextNode = AcpiNsGetNextNode (EcDeviceNode, NextNode);
    }

    /* Evaluate the _REG(EmbeddedControl,Connect) method */

    Args.Count = 2;
    Args.Pointer = Objects;
    Objects[0].Type = ACPI_TYPE_INTEGER;
    Objects[0].Integer.Value = ACPI_ADR_SPACE_EC;
    Objects[1].Type = ACPI_TYPE_INTEGER;
    Objects[1].Integer.Value = ACPI_REG_CONNECT;

    Status = AcpiEvaluateObject (RegMethod, NULL, &Args, NULL);

Exit:
    /* We ignore all errors from above, don't care */

    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    return_VOID;
}
Example #7
0
ACPI_STATUS
AcpiGetNextObject (
    ACPI_OBJECT_TYPE        Type,
    ACPI_HANDLE             Parent,
    ACPI_HANDLE             Child,
    ACPI_HANDLE             *RetHandle)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_NAMESPACE_NODE     *ParentNode = NULL;
    ACPI_NAMESPACE_NODE     *ChildNode = NULL;


    /* Parameter validation */

    if (Type > ACPI_TYPE_EXTERNAL_MAX)
    {
        return (AE_BAD_PARAMETER);
    }

    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    /* If null handle, use the parent */

    if (!Child)
    {
        /* Start search at the beginning of the specified scope */

        ParentNode = AcpiNsMapHandleToNode (Parent);
        if (!ParentNode)
        {
            Status = AE_BAD_PARAMETER;
            goto UnlockAndExit;
        }
    }
    else
    {
        /* Non-null handle, ignore the parent */
        /* Convert and validate the handle */

        ChildNode = AcpiNsMapHandleToNode (Child);
        if (!ChildNode)
        {
            Status = AE_BAD_PARAMETER;
            goto UnlockAndExit;
        }
    }

    /* Internal function does the real work */

    Node = AcpiNsGetNextNode (Type, ParentNode, ChildNode);
    if (!Node)
    {
        Status = AE_NOT_FOUND;
        goto UnlockAndExit;
    }

    if (RetHandle)
    {
        *RetHandle = AcpiNsConvertEntryToHandle (Node);
    }


UnlockAndExit:

    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    return (Status);
}