tbxfload.c revision 256281
167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: tbxfload - Table load/unload external interfaces
467754Smsmith *
5117521Snjl *****************************************************************************/
667754Smsmith
767754Smsmith/*
867754Smsmith * Copyright (C) 2000 - 2013, Intel Corp.
967754Smsmith * All rights reserved.
1067754Smsmith *
1167754Smsmith * Redistribution and use in source and binary forms, with or without
1267754Smsmith * modification, are permitted provided that the following conditions
13114237Snjl * are met:
1470243Smsmith * 1. Redistributions of source code must retain the above copyright
1567754Smsmith *    notice, this list of conditions, and the following disclaimer,
1667754Smsmith *    without modification.
1767754Smsmith * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1867754Smsmith *    substantially similar to the "NO WARRANTY" disclaimer below
1967754Smsmith *    ("Disclaimer") and any redistribution must be conditioned upon
2067754Smsmith *    including a substantially similar Disclaimer requirement for further
2167754Smsmith *    binary redistribution.
2267754Smsmith * 3. Neither the names of the above-listed copyright holders nor the names
2367754Smsmith *    of any contributors may be used to endorse or promote products derived
2467754Smsmith *    from this software without specific prior written permission.
2567754Smsmith *
2667754Smsmith * Alternatively, this software may be distributed under the terms of the
2767754Smsmith * GNU General Public License ("GPL") version 2 as published by the Free
2867754Smsmith * Software Foundation.
2967754Smsmith *
3067754Smsmith * NO WARRANTY
3167754Smsmith * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3267754Smsmith * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3367754Smsmith * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3467754Smsmith * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3567754Smsmith * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3667754Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3767754Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3867754Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3967754Smsmith * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4067754Smsmith * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4167754Smsmith * POSSIBILITY OF SUCH DAMAGES.
4267754Smsmith */
4367754Smsmith
4467754Smsmith#define __TBXFLOAD_C__
4567754Smsmith
4667754Smsmith#include <contrib/dev/acpica/include/acpi.h>
4767754Smsmith#include <contrib/dev/acpica/include/accommon.h>
4867754Smsmith#include <contrib/dev/acpica/include/acnamesp.h>
4967754Smsmith#include <contrib/dev/acpica/include/actables.h>
5067754Smsmith
5167754Smsmith#define _COMPONENT          ACPI_TABLES
5267754Smsmith        ACPI_MODULE_NAME    ("tbxfload")
5367754Smsmith
5467754Smsmith/* Local prototypes */
5567754Smsmith
5667754Smsmithstatic ACPI_STATUS
5767754SmsmithAcpiTbLoadNamespace (
5867754Smsmith    void);
5967754Smsmith
6067754Smsmith
6167754Smsmith/*******************************************************************************
6267754Smsmith *
6367754Smsmith * FUNCTION:    AcpiLoadTables
6467754Smsmith *
6567754Smsmith * PARAMETERS:  None
6667754Smsmith *
6767754Smsmith * RETURN:      Status
6867754Smsmith *
6967754Smsmith * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT
7067754Smsmith *
7167754Smsmith ******************************************************************************/
7267754Smsmith
7367754SmsmithACPI_STATUS
7467754SmsmithAcpiLoadTables (
7567754Smsmith    void)
7667754Smsmith{
7767754Smsmith    ACPI_STATUS             Status;
7867754Smsmith
7967754Smsmith
8067754Smsmith    ACPI_FUNCTION_TRACE (AcpiLoadTables);
8167754Smsmith
8267754Smsmith
8367754Smsmith    /* Load the namespace from the tables */
8467754Smsmith
8567754Smsmith    Status = AcpiTbLoadNamespace ();
8667754Smsmith    if (ACPI_FAILURE (Status))
8767754Smsmith    {
8867754Smsmith        ACPI_EXCEPTION ((AE_INFO, Status,
8967754Smsmith            "While loading namespace from ACPI tables"));
9067754Smsmith    }
9167754Smsmith
9267754Smsmith    return_ACPI_STATUS (Status);
9367754Smsmith}
9467754Smsmith
9567754SmsmithACPI_EXPORT_SYMBOL (AcpiLoadTables)
9667754Smsmith
9767754Smsmith
9867754Smsmith/*******************************************************************************
9967754Smsmith *
10067754Smsmith * FUNCTION:    AcpiTbLoadNamespace
10167754Smsmith *
10267754Smsmith * PARAMETERS:  None
10367754Smsmith *
10467754Smsmith * RETURN:      Status
10567754Smsmith *
10667754Smsmith * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in
10767754Smsmith *              the RSDT/XSDT.
10867754Smsmith *
10967754Smsmith ******************************************************************************/
11067754Smsmith
11167754Smsmithstatic ACPI_STATUS
11267754SmsmithAcpiTbLoadNamespace (
11367754Smsmith    void)
11467754Smsmith{
11567754Smsmith    ACPI_STATUS             Status;
11667754Smsmith    UINT32                  i;
11767754Smsmith    ACPI_TABLE_HEADER       *NewDsdt;
11867754Smsmith
11967754Smsmith
12067754Smsmith    ACPI_FUNCTION_TRACE (TbLoadNamespace);
12167754Smsmith
12267754Smsmith
12367754Smsmith    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
12467754Smsmith
12577424Smsmith    /*
12691116Smsmith     * Load the namespace. The DSDT is required, but any SSDT and
12767754Smsmith     * PSDT tables are optional. Verify the DSDT.
12867754Smsmith     */
12977424Smsmith    if (!AcpiGbl_RootTableList.CurrentTableCount ||
13067754Smsmith        !ACPI_COMPARE_NAME (
13167754Smsmith            &(AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Signature),
13267754Smsmith            ACPI_SIG_DSDT) ||
13367754Smsmith         ACPI_FAILURE (AcpiTbVerifyTable (
13467754Smsmith            &AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT])))
13567754Smsmith    {
13667754Smsmith        Status = AE_NO_ACPI_TABLES;
13767754Smsmith        goto UnlockAndExit;
13867754Smsmith    }
13967754Smsmith
14067754Smsmith    /*
14167754Smsmith     * Save the DSDT pointer for simple access. This is the mapped memory
14267754Smsmith     * address. We must take care here because the address of the .Tables
14367754Smsmith     * array can change dynamically as tables are loaded at run-time. Note:
14467754Smsmith     * .Pointer field is not validated until after call to AcpiTbVerifyTable.
14567754Smsmith     */
14667754Smsmith    AcpiGbl_DSDT = AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer;
14767754Smsmith
14877424Smsmith    /*
14977424Smsmith     * Optionally copy the entire DSDT to local memory (instead of simply
15077424Smsmith     * mapping it.) There are some BIOSs that corrupt or replace the original
15167754Smsmith     * DSDT, creating the need for this option. Default is FALSE, do not copy
15267754Smsmith     * the DSDT.
15367754Smsmith     */
15467754Smsmith    if (AcpiGbl_CopyDsdtLocally)
15567754Smsmith    {
15691116Smsmith        NewDsdt = AcpiTbCopyDsdt (ACPI_TABLE_INDEX_DSDT);
15791116Smsmith        if (NewDsdt)
15867754Smsmith        {
15967754Smsmith            AcpiGbl_DSDT = NewDsdt;
16067754Smsmith        }
16191116Smsmith    }
16267754Smsmith
16377424Smsmith    /*
16467754Smsmith     * Save the original DSDT header for detection of table corruption
16567754Smsmith     * and/or replacement of the DSDT from outside the OS.
16691116Smsmith     */
16767754Smsmith    ACPI_MEMCPY (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT,
16867754Smsmith        sizeof (ACPI_TABLE_HEADER));
16967754Smsmith
17067754Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
17191116Smsmith
17291116Smsmith    /* Load and parse tables */
17391116Smsmith
17491116Smsmith    Status = AcpiNsLoadTable (ACPI_TABLE_INDEX_DSDT, AcpiGbl_RootNode);
17591116Smsmith    if (ACPI_FAILURE (Status))
17667754Smsmith    {
17767754Smsmith        return_ACPI_STATUS (Status);
17867754Smsmith    }
17985756Smsmith
18067754Smsmith    /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */
18167754Smsmith
18267754Smsmith    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
18367754Smsmith    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
18467754Smsmith    {
18567754Smsmith        if ((!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature),
18667754Smsmith                    ACPI_SIG_SSDT) &&
18785756Smsmith             !ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature),
18885756Smsmith                    ACPI_SIG_PSDT)) ||
18985756Smsmith             ACPI_FAILURE (AcpiTbVerifyTable (
19067754Smsmith                &AcpiGbl_RootTableList.Tables[i])))
19167754Smsmith        {
19267754Smsmith            continue;
19367754Smsmith        }
19467754Smsmith
19567754Smsmith        /*
19667754Smsmith         * Optionally do not load any SSDTs from the RSDT/XSDT. This can
19767754Smsmith         * be useful for debugging ACPI problems on some machines.
19867754Smsmith         */
19967754Smsmith        if (AcpiGbl_DisableSsdtTableLoad)
20067754Smsmith        {
20167754Smsmith            ACPI_INFO ((AE_INFO, "Ignoring %4.4s at %p",
20291116Smsmith                AcpiGbl_RootTableList.Tables[i].Signature.Ascii,
20367754Smsmith                ACPI_CAST_PTR (void, AcpiGbl_RootTableList.Tables[i].Address)));
20467754Smsmith            continue;
20567754Smsmith        }
20677424Smsmith
20777424Smsmith        /* Ignore errors while loading tables, get as many as possible */
20884491Smsmith
20967754Smsmith        (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
21067754Smsmith        (void) AcpiNsLoadTable (i, AcpiGbl_RootNode);
21177424Smsmith        (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
21277424Smsmith    }
21384491Smsmith
21467754Smsmith    ACPI_INFO ((AE_INFO, "All ACPI Tables successfully acquired"));
21567754Smsmith
21677424SmsmithUnlockAndExit:
21777424Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
21884491Smsmith    return_ACPI_STATUS (Status);
21967754Smsmith}
22067754Smsmith
22184491Smsmith
22284491Smsmith/*******************************************************************************
22384491Smsmith *
22484491Smsmith * FUNCTION:    AcpiLoadTable
22584491Smsmith *
22684491Smsmith * PARAMETERS:  Table               - Pointer to a buffer containing the ACPI
22784491Smsmith *                                    table to be loaded.
22884491Smsmith *
22984491Smsmith * RETURN:      Status
23084491Smsmith *
23191116Smsmith * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must
23291116Smsmith *              be a valid ACPI table with a valid ACPI table header.
23391116Smsmith *              Note1: Mainly intended to support hotplug addition of SSDTs.
23491116Smsmith *              Note2: Does not copy the incoming table. User is responsible
23591116Smsmith *              to ensure that the table is not deleted or unmapped.
23667754Smsmith *
237117521Snjl ******************************************************************************/
23867754Smsmith
23967754SmsmithACPI_STATUS
24067754SmsmithAcpiLoadTable (
24167754Smsmith    ACPI_TABLE_HEADER       *Table)
242117521Snjl{
243117521Snjl    ACPI_STATUS             Status;
24467754Smsmith    ACPI_TABLE_DESC         TableDesc;
24567754Smsmith    UINT32                  TableIndex;
24667754Smsmith
24767754Smsmith
24867754Smsmith    ACPI_FUNCTION_TRACE (AcpiLoadTable);
249117521Snjl
250117521Snjl
25177424Smsmith    /* Parameter validation */
25267754Smsmith
25367754Smsmith    if (!Table)
25467754Smsmith    {
255117521Snjl        return_ACPI_STATUS (AE_BAD_PARAMETER);
25685756Smsmith    }
25767754Smsmith
258117521Snjl    /* Init local table descriptor */
25967754Smsmith
260117521Snjl    ACPI_MEMSET (&TableDesc, 0, sizeof (ACPI_TABLE_DESC));
26167754Smsmith    TableDesc.Address = ACPI_PTR_TO_PHYSADDR (Table);
26267754Smsmith    TableDesc.Pointer = Table;
26367754Smsmith    TableDesc.Length = Table->Length;
264117521Snjl    TableDesc.Flags = ACPI_TABLE_ORIGIN_UNKNOWN;
265117521Snjl
266117521Snjl    /* Must acquire the interpreter lock during this operation */
26767754Smsmith
268117521Snjl    Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
269117521Snjl    if (ACPI_FAILURE (Status))
270117521Snjl    {
271117521Snjl        return_ACPI_STATUS (Status);
272117521Snjl    }
273117521Snjl
274117521Snjl    /* Install the table and load it into the namespace */
275117521Snjl
276117521Snjl    ACPI_INFO ((AE_INFO, "Host-directed Dynamic ACPI Table Load:"));
277117521Snjl    Status = AcpiTbAddTable (&TableDesc, &TableIndex);
278117521Snjl    if (ACPI_FAILURE (Status))
279117521Snjl    {
280117521Snjl        goto UnlockAndExit;
281117521Snjl    }
282117521Snjl
28367754Smsmith    Status = AcpiNsLoadTable (TableIndex, AcpiGbl_RootNode);
28467754Smsmith
28567754Smsmith    /* Invoke table handler if present */
286117521Snjl
287117521Snjl    if (AcpiGbl_TableHandler)
288117521Snjl    {
28967754Smsmith        (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table,
29067754Smsmith                    AcpiGbl_TableHandlerContext);
29167754Smsmith    }
29267754Smsmith
29382367SmsmithUnlockAndExit:
29482367Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
29567754Smsmith    return_ACPI_STATUS (Status);
29667754Smsmith}
29767754Smsmith
29867754SmsmithACPI_EXPORT_SYMBOL (AcpiLoadTable)
29967754Smsmith
30067754Smsmith
30167754Smsmith/*******************************************************************************
30267754Smsmith *
30367754Smsmith * FUNCTION:    AcpiUnloadParentTable
30467754Smsmith *
30567754Smsmith * PARAMETERS:  Object              - Handle to any namespace object owned by
30667754Smsmith *                                    the table to be unloaded
30777424Smsmith *
30867754Smsmith * RETURN:      Status
30967754Smsmith *
31067754Smsmith * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads
31167754Smsmith *              the table and deletes all namespace objects associated with
31267754Smsmith *              that table. Unloading of the DSDT is not allowed.
31367754Smsmith *              Note: Mainly intended to support hotplug removal of SSDTs.
31467754Smsmith *
31567754Smsmith ******************************************************************************/
31667754Smsmith
31767754SmsmithACPI_STATUS
31867754SmsmithAcpiUnloadParentTable (
31967754Smsmith    ACPI_HANDLE             Object)
32091116Smsmith{
321117521Snjl    ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Object);
322117521Snjl    ACPI_STATUS             Status = AE_NOT_EXIST;
323117521Snjl    ACPI_OWNER_ID           OwnerId;
324117521Snjl    UINT32                  i;
325117521Snjl
32667754Smsmith
32767754Smsmith    ACPI_FUNCTION_TRACE (AcpiUnloadParentTable);
32867754Smsmith
32967754Smsmith
33067754Smsmith    /* Parameter validation */
33167754Smsmith
33282367Smsmith    if (!Object)
333107325Siwasaki    {
334107325Siwasaki        return_ACPI_STATUS (AE_BAD_PARAMETER);
33567754Smsmith    }
33667754Smsmith
337117521Snjl    /*
33867754Smsmith     * The node OwnerId is currently the same as the parent table ID.
339117521Snjl     * However, this could change in the future.
340117521Snjl     */
34185756Smsmith    OwnerId = Node->OwnerId;
34267754Smsmith    if (!OwnerId)
343107325Siwasaki    {
34467754Smsmith        /* OwnerId==0 means DSDT is the owner. DSDT cannot be unloaded */
34567754Smsmith
34667754Smsmith        return_ACPI_STATUS (AE_TYPE);
34767754Smsmith    }
34867754Smsmith
34967754Smsmith    /* Must acquire the interpreter lock during this operation */
350117521Snjl
35167754Smsmith    Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
352117521Snjl    if (ACPI_FAILURE (Status))
353117521Snjl    {
354117521Snjl        return_ACPI_STATUS (Status);
355117521Snjl    }
356117521Snjl
357117521Snjl    /* Find the table in the global table list */
358117521Snjl
359117521Snjl    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
360117521Snjl    {
361117521Snjl        if (OwnerId != AcpiGbl_RootTableList.Tables[i].OwnerId)
362117521Snjl        {
363117521Snjl            continue;
36467754Smsmith        }
365117521Snjl
366117521Snjl        /*
367117521Snjl         * Allow unload of SSDT and OEMx tables only. Do not allow unload
368117521Snjl         * of the DSDT. No other types of tables should get here, since
369117521Snjl         * only these types can contain AML and thus are the only types
370117521Snjl         * that can create namespace objects.
371117521Snjl         */
37285756Smsmith        if (ACPI_COMPARE_NAME (
37367754Smsmith            AcpiGbl_RootTableList.Tables[i].Signature.Ascii,
374117521Snjl            ACPI_SIG_DSDT))
37585756Smsmith        {
37685756Smsmith            Status = AE_TYPE;
37785756Smsmith            break;
37867754Smsmith        }
379117521Snjl
38085756Smsmith        /* Ensure the table is actually loaded */
38167754Smsmith
382117521Snjl        if (!AcpiTbIsTableLoaded (i))
383117521Snjl        {
384117521Snjl            Status = AE_NOT_EXIST;
38567754Smsmith            break;
38667754Smsmith        }
38791116Smsmith
38867754Smsmith        /* Invoke table handler if present */
38967754Smsmith
39067754Smsmith        if (AcpiGbl_TableHandler)
39167754Smsmith        {
39277424Smsmith            (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD,
39367754Smsmith                        AcpiGbl_RootTableList.Tables[i].Pointer,
39467754Smsmith                        AcpiGbl_TableHandlerContext);
39567754Smsmith        }
396117521Snjl
397117521Snjl        /*
39867754Smsmith         * Delete all namespace objects owned by this table. Note that
39967754Smsmith         * these objects can appear anywhere in the namespace by virtue
40067754Smsmith         * of the AML "Scope" operator. Thus, we need to track ownership
40167754Smsmith         * by an ID, not simply a position within the hierarchy.
402117521Snjl         */
40367754Smsmith        Status = AcpiTbDeleteNamespaceByOwner (i);
40467754Smsmith        if (ACPI_FAILURE (Status))
40567754Smsmith        {
40667754Smsmith            break;
40767754Smsmith        }
40867754Smsmith
40977424Smsmith        Status = AcpiTbReleaseOwnerId (i);
41077424Smsmith        AcpiTbSetTableLoadedFlag (i, FALSE);
41167754Smsmith        break;
41267754Smsmith    }
41367754Smsmith
41467754Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
41567754Smsmith    return_ACPI_STATUS (Status);
41667754Smsmith}
41791116Smsmith
41867754SmsmithACPI_EXPORT_SYMBOL (AcpiUnloadParentTable)
41967754Smsmith