Example #1
0
ACPI_STATUS
AcpiTbUnloadTable (
    UINT32                  TableIndex)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_TABLE_HEADER       *Table;


    ACPI_FUNCTION_TRACE (TbUnloadTable);


    /* Ensure the table is still loaded */

    if (!AcpiTbIsTableLoaded (TableIndex))
    {
        return_ACPI_STATUS (AE_NOT_EXIST);
    }

    /* Invoke table handler */

    Status = AcpiGetTableByIndex (TableIndex, &Table);
    if (ACPI_SUCCESS (Status))
    {
        AcpiTbNotifyTable (ACPI_TABLE_EVENT_UNLOAD, Table);
    }

    /* Delete the portion of the namespace owned by this table */

    Status = AcpiTbDeleteNamespaceByOwner (TableIndex);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    (void) AcpiTbReleaseOwnerId (TableIndex);
    AcpiTbSetTableLoadedFlag (TableIndex, FALSE);
    return_ACPI_STATUS (Status);
}
Example #2
0
ACPI_STATUS
AcpiUnloadParentTable (
    ACPI_HANDLE             Object)
{
    ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Object);
    ACPI_STATUS             Status = AE_NOT_EXIST;
    ACPI_OWNER_ID           OwnerId;
    UINT32                  i;


    ACPI_FUNCTION_TRACE (AcpiUnloadParentTable);


    /* Parameter validation */

    if (!Object)
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /*
     * The node OwnerId is currently the same as the parent table ID.
     * However, this could change in the future.
     */
    OwnerId = Node->OwnerId;
    if (!OwnerId)
    {
        /* OwnerId==0 means DSDT is the owner. DSDT cannot be unloaded */

        return_ACPI_STATUS (AE_TYPE);
    }

    /* Must acquire the interpreter lock during this operation */

    Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Find the table in the global table list */

    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
    {
        if (OwnerId != AcpiGbl_RootTableList.Tables[i].OwnerId)
        {
            continue;
        }

        /*
         * Allow unload of SSDT and OEMx tables only. Do not allow unload
         * of the DSDT. No other types of tables should get here, since
         * only these types can contain AML and thus are the only types
         * that can create namespace objects.
         */
        if (ACPI_COMPARE_NAME (
            AcpiGbl_RootTableList.Tables[i].Signature.Ascii,
            ACPI_SIG_DSDT))
        {
            Status = AE_TYPE;
            break;
        }

        /* Ensure the table is actually loaded */

        if (!AcpiTbIsTableLoaded (i))
        {
            Status = AE_NOT_EXIST;
            break;
        }

        /* Invoke table handler if present */

        if (AcpiGbl_TableHandler)
        {
            (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD,
                        AcpiGbl_RootTableList.Tables[i].Pointer,
                        AcpiGbl_TableHandlerContext);
        }

        /*
         * Delete all namespace objects owned by this table. Note that
         * these objects can appear anywhere in the namespace by virtue
         * of the AML "Scope" operator. Thus, we need to track ownership
         * by an ID, not simply a position within the hierarchy.
         */
        Status = AcpiTbDeleteNamespaceByOwner (i);
        if (ACPI_FAILURE (Status))
        {
            break;
        }

        Status = AcpiTbReleaseOwnerId (i);
        AcpiTbSetTableLoadedFlag (i, FALSE);
        break;
    }

    (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
    return_ACPI_STATUS (Status);
}
ACPI_STATUS
AcpiNsLoadTable (
    UINT32                  TableIndex,
    ACPI_NAMESPACE_NODE     *Node)
{
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (NsLoadTable);


    /*
     * Parse the table and load the namespace with all named
     * objects found within.  Control methods are NOT parsed
     * at this time.  In fact, the control methods cannot be
     * parsed until the entire namespace is loaded, because
     * if a control method makes a forward reference (call)
     * to another control method, we can't continue parsing
     * because we don't know how many arguments to parse next!
     */
    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* If table already loaded into namespace, just return */

    if (AcpiTbIsTableLoaded (TableIndex))
    {
        Status = AE_ALREADY_EXISTS;
        goto Unlock;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Loading table into namespace ****\n"));

    Status = AcpiTbAllocateOwnerId (TableIndex);
    if (ACPI_FAILURE (Status))
    {
        goto Unlock;
    }

    Status = AcpiNsParseTable (TableIndex, Node);
    if (ACPI_SUCCESS (Status))
    {
        AcpiTbSetTableLoadedFlag (TableIndex, TRUE);
    }
    else
    {
        (void) AcpiTbReleaseOwnerId (TableIndex);
    }

Unlock:
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);

    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /*
     * Now we can parse the control methods.  We always parse
     * them here for a sanity check, and if configured for
     * just-in-time parsing, we delete the control method
     * parse trees.
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Begin Table Method Parsing and Object Initialization\n"));

    Status = AcpiDsInitializeObjects (TableIndex, Node);

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Completed Table Method Parsing and Object Initialization\n"));

    return_ACPI_STATUS (Status);
}
ACPI_STATUS
AcpiExUnloadTable (
    ACPI_OPERAND_OBJECT     *DdbHandle)
{
    ACPI_STATUS             Status = AE_OK;
    ACPI_OPERAND_OBJECT     *TableDesc = DdbHandle;
    UINT32                  TableIndex;
    ACPI_TABLE_HEADER       *Table;


    ACPI_FUNCTION_TRACE (ExUnloadTable);


    /*
     * Validate the handle
     * Although the handle is partially validated in AcpiExReconfiguration()
     * when it calls AcpiExResolveOperands(), the handle is more completely
     * validated here.
     *
     * Handle must be a valid operand object of type reference. Also, the
     * DdbHandle must still be marked valid (table has not been previously
     * unloaded)
     */
    if ((!DdbHandle) ||
        (ACPI_GET_DESCRIPTOR_TYPE (DdbHandle) != ACPI_DESC_TYPE_OPERAND) ||
        (DdbHandle->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) ||
        (!(DdbHandle->Common.Flags & AOPOBJ_DATA_VALID)))
    {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    /* Get the table index from the DdbHandle */

    TableIndex = TableDesc->Reference.Value;

    /* Ensure the table is still loaded */

    if (!AcpiTbIsTableLoaded (TableIndex))
    {
        return_ACPI_STATUS (AE_NOT_EXIST);
    }

    /* Invoke table handler if present */

    if (AcpiGbl_TableHandler)
    {
        Status = AcpiGetTableByIndex (TableIndex, &Table);
        if (ACPI_SUCCESS (Status))
        {
            (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, Table,
                        AcpiGbl_TableHandlerContext);
        }
    }

    /* Delete the portion of the namespace owned by this table */

    Status = AcpiTbDeleteNamespaceByOwner (TableIndex);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    (void) AcpiTbReleaseOwnerId (TableIndex);
    AcpiTbSetTableLoadedFlag (TableIndex, FALSE);

    /*
     * Invalidate the handle. We do this because the handle may be stored
     * in a named object and may not be actually deleted until much later.
     */
    DdbHandle->Common.Flags &= ~AOPOBJ_DATA_VALID;
    return_ACPI_STATUS (AE_OK);
}
Example #5
0
ACPI_STATUS
AcpiNsLoadTable (
    UINT32                  TableIndex,
    ACPI_NAMESPACE_NODE     *Node)
{
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (NsLoadTable);


    /* If table already loaded into namespace, just return */

    if (AcpiTbIsTableLoaded (TableIndex))
    {
        Status = AE_ALREADY_EXISTS;
        goto Unlock;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Loading table into namespace ****\n"));

    Status = AcpiTbAllocateOwnerId (TableIndex);
    if (ACPI_FAILURE (Status))
    {
        goto Unlock;
    }

    /*
     * Parse the table and load the namespace with all named
     * objects found within. Control methods are NOT parsed
     * at this time. In fact, the control methods cannot be
     * parsed until the entire namespace is loaded, because
     * if a control method makes a forward reference (call)
     * to another control method, we can't continue parsing
     * because we don't know how many arguments to parse next!
     */
    Status = AcpiNsParseTable (TableIndex, Node);
    if (ACPI_SUCCESS (Status))
    {
        AcpiTbSetTableLoadedFlag (TableIndex, TRUE);
    }
    else
    {
        /*
         * On error, delete any namespace objects created by this table.
         * We cannot initialize these objects, so delete them. There are
         * a couple of expecially bad cases:
         * AE_ALREADY_EXISTS - namespace collision.
         * AE_NOT_FOUND - the target of a Scope operator does not
         * exist. This target of Scope must already exist in the
         * namespace, as per the ACPI specification.
         */
        AcpiNsDeleteNamespaceByOwner (
            AcpiGbl_RootTableList.Tables[TableIndex].OwnerId);

        AcpiTbReleaseOwnerId (TableIndex);
        return_ACPI_STATUS (Status);
    }

Unlock:
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /*
     * Now we can parse the control methods. We always parse
     * them here for a sanity check, and if configured for
     * just-in-time parsing, we delete the control method
     * parse trees.
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Begin Table Object Initialization\n"));

    AcpiExEnterInterpreter ();
    Status = AcpiDsInitializeObjects (TableIndex, Node);
    AcpiExExitInterpreter ();

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Completed Table Object Initialization\n"));

    /*
     * This case handles the legacy option that groups all module-level
     * code blocks together and defers execution until all of the tables
     * are loaded. Execute all of these blocks at this time.
     * Execute any module-level code that was detected during the table
     * load phase.
     *
     * Note: this option is deprecated and will be eliminated in the
     * future. Use of this option can cause problems with AML code that
     * depends upon in-order immediate execution of module-level code.
     */
    AcpiNsExecModuleCodeList ();
    return_ACPI_STATUS (Status);
}
Example #6
0
ACPI_STATUS
AcpiNsLoadTable (
    UINT32                  TableIndex,
    ACPI_NAMESPACE_NODE     *Node)
{
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (NsLoadTable);


    /* If table already loaded into namespace, just return */

    if (AcpiTbIsTableLoaded (TableIndex))
    {
        Status = AE_ALREADY_EXISTS;
        goto Unlock;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Loading table into namespace ****\n"));

    Status = AcpiTbAllocateOwnerId (TableIndex);
    if (ACPI_FAILURE (Status))
    {
        goto Unlock;
    }

    /*
     * Parse the table and load the namespace with all named
     * objects found within. Control methods are NOT parsed
     * at this time. In fact, the control methods cannot be
     * parsed until the entire namespace is loaded, because
     * if a control method makes a forward reference (call)
     * to another control method, we can't continue parsing
     * because we don't know how many arguments to parse next!
     */
    Status = AcpiNsParseTable (TableIndex, Node);
    if (ACPI_SUCCESS (Status))
    {
        AcpiTbSetTableLoadedFlag (TableIndex, TRUE);
    }
    else
    {
        /*
         * On error, delete any namespace objects created by this table.
         * We cannot initialize these objects, so delete them. There are
         * a couple of expecially bad cases:
         * AE_ALREADY_EXISTS - namespace collision.
         * AE_NOT_FOUND - the target of a Scope operator does not
         * exist. This target of Scope must already exist in the
         * namespace, as per the ACPI specification.
         */
        AcpiNsDeleteNamespaceByOwner (
            AcpiGbl_RootTableList.Tables[TableIndex].OwnerId);

        AcpiTbReleaseOwnerId (TableIndex);
        return_ACPI_STATUS (Status);
    }

Unlock:
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /*
     * Now we can parse the control methods. We always parse
     * them here for a sanity check, and if configured for
     * just-in-time parsing, we delete the control method
     * parse trees.
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Begin Table Object Initialization\n"));

    AcpiExEnterInterpreter ();
    Status = AcpiDsInitializeObjects (TableIndex, Node);
    AcpiExExitInterpreter ();

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Completed Table Object Initialization\n"));

    /*
     * Execute any module-level code that was detected during the table load
     * phase. Although illegal since ACPI 2.0, there are many machines that
     * contain this type of code. Each block of detected executable AML code
     * outside of any control method is wrapped with a temporary control
     * method object and placed on a global list. The methods on this list
     * are executed below.
     *
     * This case executes the module-level code for each table immediately
     * after the table has been loaded. This provides compatibility with
     * other ACPI implementations. Optionally, the execution can be deferred
     * until later, see AcpiInitializeObjects.
     */
    if (!AcpiGbl_ParseTableAsTermList && !AcpiGbl_GroupModuleLevelCode)
    {
        AcpiNsExecModuleCodeList ();
    }

    return_ACPI_STATUS (Status);
}
Example #7
0
ACPI_STATUS
AcpiNsLoadTable (
    UINT32                  TableIndex,
    ACPI_NAMESPACE_NODE     *Node)
{
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (NsLoadTable);


    /*
     * Parse the table and load the namespace with all named
     * objects found within. Control methods are NOT parsed
     * at this time. In fact, the control methods cannot be
     * parsed until the entire namespace is loaded, because
     * if a control method makes a forward reference (call)
     * to another control method, we can't continue parsing
     * because we don't know how many arguments to parse next!
     */
    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* If table already loaded into namespace, just return */

    if (AcpiTbIsTableLoaded (TableIndex))
    {
        Status = AE_ALREADY_EXISTS;
        goto Unlock;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Loading table into namespace ****\n"));

    Status = AcpiTbAllocateOwnerId (TableIndex);
    if (ACPI_FAILURE (Status))
    {
        goto Unlock;
    }

    Status = AcpiNsParseTable (TableIndex, Node);
    if (ACPI_SUCCESS (Status))
    {
        AcpiTbSetTableLoadedFlag (TableIndex, TRUE);
    }
    else
    {
        /*
         * On error, delete any namespace objects created by this table.
         * We cannot initialize these objects, so delete them. There are
         * a couple of expecially bad cases:
         * AE_ALREADY_EXISTS - namespace collision.
         * AE_NOT_FOUND - the target of a Scope operator does not
         * exist. This target of Scope must already exist in the
         * namespace, as per the ACPI specification.
         */
        (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
        AcpiNsDeleteNamespaceByOwner (
            AcpiGbl_RootTableList.Tables[TableIndex].OwnerId);
            AcpiTbReleaseOwnerId (TableIndex);

        return_ACPI_STATUS (Status);
    }

Unlock:
    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);

    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /*
     * Now we can parse the control methods. We always parse
     * them here for a sanity check, and if configured for
     * just-in-time parsing, we delete the control method
     * parse trees.
     */
    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Begin Table Object Initialization\n"));

    Status = AcpiDsInitializeObjects (TableIndex, Node);

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
        "**** Completed Table Object Initialization\n"));

    return_ACPI_STATUS (Status);
}