tbinstal.c revision 231844
167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: tbinstal - ACPI table installation and removal
467754Smsmith *
567754Smsmith *****************************************************************************/
667754Smsmith
7217365Sjkim/*
8229989Sjkim * Copyright (C) 2000 - 2012, Intel Corp.
970243Smsmith * All rights reserved.
1067754Smsmith *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
2567754Smsmith *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
2967754Smsmith *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
4367754Smsmith
4467754Smsmith
4567754Smsmith#define __TBINSTAL_C__
4667754Smsmith
47193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
48193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
49193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
50193341Sjkim#include <contrib/dev/acpica/include/actables.h>
5167754Smsmith
5267754Smsmith
5377424Smsmith#define _COMPONENT          ACPI_TABLES
5491116Smsmith        ACPI_MODULE_NAME    ("tbinstal")
5567754Smsmith
5667754Smsmith
57167802Sjkim/******************************************************************************
5867754Smsmith *
59167802Sjkim * FUNCTION:    AcpiTbVerifyTable
6091116Smsmith *
61167802Sjkim * PARAMETERS:  TableDesc           - table
6291116Smsmith *
6391116Smsmith * RETURN:      Status
6491116Smsmith *
65167802Sjkim * DESCRIPTION: this function is called to verify and map table
6691116Smsmith *
67167802Sjkim *****************************************************************************/
6891116Smsmith
69167802SjkimACPI_STATUS
70167802SjkimAcpiTbVerifyTable (
71167802Sjkim    ACPI_TABLE_DESC         *TableDesc)
7291116Smsmith{
73167802Sjkim    ACPI_STATUS             Status = AE_OK;
7491116Smsmith
7591116Smsmith
76167802Sjkim    ACPI_FUNCTION_TRACE (TbVerifyTable);
7791116Smsmith
7891116Smsmith
79167802Sjkim    /* Map the table if necessary */
80151937Sjkim
81167802Sjkim    if (!TableDesc->Pointer)
8291116Smsmith    {
83167802Sjkim        if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) ==
84167802Sjkim            ACPI_TABLE_ORIGIN_MAPPED)
85100966Siwasaki        {
86193267Sjkim            TableDesc->Pointer = AcpiOsMapMemory (
87193267Sjkim                TableDesc->Address, TableDesc->Length);
88100966Siwasaki        }
89100966Siwasaki
90167802Sjkim        if (!TableDesc->Pointer)
9191116Smsmith        {
92167802Sjkim            return_ACPI_STATUS (AE_NO_MEMORY);
93167802Sjkim        }
94167802Sjkim    }
9591116Smsmith
96167802Sjkim    /* FACS is the odd table, has no standard ACPI header and no checksum */
9791116Smsmith
98167802Sjkim    if (!ACPI_COMPARE_NAME (&TableDesc->Signature, ACPI_SIG_FACS))
99167802Sjkim    {
100167802Sjkim        /* Always calculate checksum, ignore bad checksum if requested */
10191116Smsmith
102167802Sjkim        Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length);
10391116Smsmith    }
10491116Smsmith
105167802Sjkim    return_ACPI_STATUS (Status);
10691116Smsmith}
10791116Smsmith
10891116Smsmith
10991116Smsmith/*******************************************************************************
11091116Smsmith *
111167802Sjkim * FUNCTION:    AcpiTbAddTable
11267754Smsmith *
113167802Sjkim * PARAMETERS:  TableDesc           - Table descriptor
114167802Sjkim *              TableIndex          - Where the table index is returned
11567754Smsmith *
11667754Smsmith * RETURN:      Status
11767754Smsmith *
118193267Sjkim * DESCRIPTION: This function is called to add an ACPI table. It is used to
119193267Sjkim *              dynamically load tables via the Load and LoadTable AML
120193267Sjkim *              operators.
12167754Smsmith *
12267754Smsmith ******************************************************************************/
12367754Smsmith
12467754SmsmithACPI_STATUS
125167802SjkimAcpiTbAddTable (
126167802Sjkim    ACPI_TABLE_DESC         *TableDesc,
127193267Sjkim    UINT32                  *TableIndex)
12867754Smsmith{
129193267Sjkim    UINT32                  i;
130167802Sjkim    ACPI_STATUS             Status = AE_OK;
13167754Smsmith
132151937Sjkim
133167802Sjkim    ACPI_FUNCTION_TRACE (TbAddTable);
13467754Smsmith
13567754Smsmith
136167802Sjkim    if (!TableDesc->Pointer)
137167802Sjkim    {
138167802Sjkim        Status = AcpiTbVerifyTable (TableDesc);
139167802Sjkim        if (ACPI_FAILURE (Status) || !TableDesc->Pointer)
140167802Sjkim        {
141167802Sjkim            return_ACPI_STATUS (Status);
142167802Sjkim        }
143167802Sjkim    }
14467754Smsmith
145193267Sjkim    /*
146222544Sjkim     * Validate the incoming table signature.
147222544Sjkim     *
148222544Sjkim     * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
149222544Sjkim     * 2) We added support for OEMx tables, signature "OEM".
150222544Sjkim     * 3) Valid tables were encountered with a null signature, so we just
151222544Sjkim     *    gave up on validating the signature, (05/2008).
152222544Sjkim     * 4) We encountered non-AML tables such as the MADT, which caused
153222544Sjkim     *    interpreter errors and kernel faults. So now, we once again allow
154222544Sjkim     *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
155193267Sjkim     */
156222544Sjkim    if ((TableDesc->Pointer->Signature[0] != 0x00) &&
157222544Sjkim       (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) &&
158222544Sjkim       (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3)))
159222544Sjkim    {
160222544Sjkim        ACPI_ERROR ((AE_INFO,
161222544Sjkim            "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx",
162222544Sjkim            AcpiUtValidAcpiName (*(UINT32 *) TableDesc->Pointer->Signature) ?
163222544Sjkim                TableDesc->Pointer->Signature : "????",
164222544Sjkim            *(UINT32 *) TableDesc->Pointer->Signature));
165167802Sjkim
166222544Sjkim        return_ACPI_STATUS (AE_BAD_SIGNATURE);
167222544Sjkim    }
168222544Sjkim
169167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
170167802Sjkim
171167802Sjkim    /* Check if table is already registered */
172167802Sjkim
173207344Sjkim    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
174151937Sjkim    {
175167802Sjkim        if (!AcpiGbl_RootTableList.Tables[i].Pointer)
176167802Sjkim        {
177167802Sjkim            Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]);
178193267Sjkim            if (ACPI_FAILURE (Status) ||
179193267Sjkim                !AcpiGbl_RootTableList.Tables[i].Pointer)
180167802Sjkim            {
181167802Sjkim                continue;
182167802Sjkim            }
183167802Sjkim        }
184167802Sjkim
185193267Sjkim        /*
186193267Sjkim         * Check for a table match on the entire table length,
187193267Sjkim         * not just the header.
188193267Sjkim         */
189193267Sjkim        if (TableDesc->Length != AcpiGbl_RootTableList.Tables[i].Length)
190193267Sjkim        {
191193267Sjkim            continue;
192193267Sjkim        }
193193267Sjkim
194167802Sjkim        if (ACPI_MEMCMP (TableDesc->Pointer,
195193267Sjkim                AcpiGbl_RootTableList.Tables[i].Pointer,
196193267Sjkim                AcpiGbl_RootTableList.Tables[i].Length))
197167802Sjkim        {
198167802Sjkim            continue;
199167802Sjkim        }
200167802Sjkim
201193267Sjkim        /*
202193267Sjkim         * Note: the current mechanism does not unregister a table if it is
203193267Sjkim         * dynamically unloaded. The related namespace entries are deleted,
204193267Sjkim         * but the table remains in the root table list.
205193267Sjkim         *
206193267Sjkim         * The assumption here is that the number of different tables that
207193267Sjkim         * will be loaded is actually small, and there is minimal overhead
208193267Sjkim         * in just keeping the table in case it is needed again.
209193267Sjkim         *
210193267Sjkim         * If this assumption changes in the future (perhaps on large
211193267Sjkim         * machines with many table load/unload operations), tables will
212193267Sjkim         * need to be unregistered when they are unloaded, and slots in the
213193267Sjkim         * root table list should be reused when empty.
214193267Sjkim         */
215167802Sjkim
216193267Sjkim        /*
217193267Sjkim         * Table is already registered.
218193267Sjkim         * We can delete the table that was passed as a parameter.
219193267Sjkim         */
220167802Sjkim        AcpiTbDeleteTable (TableDesc);
221167802Sjkim        *TableIndex = i;
222193267Sjkim
223193267Sjkim        if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED)
224193267Sjkim        {
225193267Sjkim            /* Table is still loaded, this is an error */
226193267Sjkim
227193267Sjkim            Status = AE_ALREADY_EXISTS;
228193267Sjkim            goto Release;
229193267Sjkim        }
230193267Sjkim        else
231193267Sjkim        {
232193267Sjkim            /* Table was unloaded, allow it to be reloaded */
233193267Sjkim
234193267Sjkim            TableDesc->Pointer = AcpiGbl_RootTableList.Tables[i].Pointer;
235193267Sjkim            TableDesc->Address = AcpiGbl_RootTableList.Tables[i].Address;
236193267Sjkim            Status = AE_OK;
237193267Sjkim            goto PrintHeader;
238193267Sjkim        }
239151937Sjkim    }
240151937Sjkim
241167802Sjkim    /*
242193267Sjkim     * ACPI Table Override:
243193267Sjkim     * Allow the host to override dynamically loaded tables.
244231844Sjkim     * NOTE: the table is fully mapped at this point, and the mapping will
245231844Sjkim     * be deleted by TbTableOverride if the table is actually overridden.
246167802Sjkim     */
247231844Sjkim    (void) AcpiTbTableOverride (TableDesc->Pointer, TableDesc);
248193267Sjkim
249193267Sjkim    /* Add the table to the global root table list */
250193267Sjkim
251167802Sjkim    Status = AcpiTbStoreTable (TableDesc->Address, TableDesc->Pointer,
252167802Sjkim                TableDesc->Length, TableDesc->Flags, TableIndex);
253100966Siwasaki    if (ACPI_FAILURE (Status))
254100966Siwasaki    {
255167802Sjkim        goto Release;
256100966Siwasaki    }
25767754Smsmith
258193267SjkimPrintHeader:
259167802Sjkim    AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer);
26067754Smsmith
261167802SjkimRelease:
26291116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
26367754Smsmith    return_ACPI_STATUS (Status);
26467754Smsmith}
26567754Smsmith
26667754Smsmith
26767754Smsmith/*******************************************************************************
26867754Smsmith *
269231844Sjkim * FUNCTION:    AcpiTbTableOverride
270231844Sjkim *
271231844Sjkim * PARAMETERS:  TableHeader         - Header for the original table
272231844Sjkim *              TableDesc           - Table descriptor initialized for the
273231844Sjkim *                                    original table. May or may not be mapped.
274231844Sjkim *
275231844Sjkim * RETURN:      Pointer to the entire new table. NULL if table not overridden.
276231844Sjkim *              If overridden, installs the new table within the input table
277231844Sjkim *              descriptor.
278231844Sjkim *
279231844Sjkim * DESCRIPTION: Attempt table override by calling the OSL override functions.
280231844Sjkim *              Note: If the table is overridden, then the entire new table
281231844Sjkim *              is mapped and returned by this function.
282231844Sjkim *
283231844Sjkim ******************************************************************************/
284231844Sjkim
285231844SjkimACPI_TABLE_HEADER *
286231844SjkimAcpiTbTableOverride (
287231844Sjkim    ACPI_TABLE_HEADER       *TableHeader,
288231844Sjkim    ACPI_TABLE_DESC         *TableDesc)
289231844Sjkim{
290231844Sjkim    ACPI_STATUS             Status;
291231844Sjkim    ACPI_TABLE_HEADER       *NewTable = NULL;
292231844Sjkim    ACPI_PHYSICAL_ADDRESS   NewAddress = 0;
293231844Sjkim    UINT32                  NewTableLength = 0;
294231844Sjkim    UINT8                   NewFlags;
295231844Sjkim    char                    *OverrideType;
296231844Sjkim
297231844Sjkim
298231844Sjkim    /* (1) Attempt logical override (returns a logical address) */
299231844Sjkim
300231844Sjkim    Status = AcpiOsTableOverride (TableHeader, &NewTable);
301231844Sjkim    if (ACPI_SUCCESS (Status) && NewTable)
302231844Sjkim    {
303231844Sjkim        NewAddress = ACPI_PTR_TO_PHYSADDR (NewTable);
304231844Sjkim        NewTableLength = NewTable->Length;
305231844Sjkim        NewFlags = ACPI_TABLE_ORIGIN_OVERRIDE;
306231844Sjkim        OverrideType = "Logical";
307231844Sjkim        goto FinishOverride;
308231844Sjkim    }
309231844Sjkim
310231844Sjkim    /* (2) Attempt physical override (returns a physical address) */
311231844Sjkim
312231844Sjkim    Status = AcpiOsPhysicalTableOverride (TableHeader,
313231844Sjkim        &NewAddress, &NewTableLength);
314231844Sjkim    if (ACPI_SUCCESS (Status) && NewAddress && NewTableLength)
315231844Sjkim    {
316231844Sjkim        /* Map the entire new table */
317231844Sjkim
318231844Sjkim        NewTable = AcpiOsMapMemory (NewAddress, NewTableLength);
319231844Sjkim        if (!NewTable)
320231844Sjkim        {
321231844Sjkim            ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
322231844Sjkim                "%4.4s %p Attempted physical table override failed",
323231844Sjkim                TableHeader->Signature,
324231844Sjkim                ACPI_CAST_PTR (void, TableDesc->Address)));
325231844Sjkim            return (NULL);
326231844Sjkim        }
327231844Sjkim
328231844Sjkim        OverrideType = "Physical";
329231844Sjkim        NewFlags = ACPI_TABLE_ORIGIN_MAPPED;
330231844Sjkim        goto FinishOverride;
331231844Sjkim    }
332231844Sjkim
333231844Sjkim    return (NULL); /* There was no override */
334231844Sjkim
335231844Sjkim
336231844SjkimFinishOverride:
337231844Sjkim
338231844Sjkim    ACPI_INFO ((AE_INFO,
339231844Sjkim        "%4.4s %p %s table override, new table: %p",
340231844Sjkim        TableHeader->Signature,
341231844Sjkim        ACPI_CAST_PTR (void, TableDesc->Address),
342231844Sjkim        OverrideType, NewTable));
343231844Sjkim
344231844Sjkim    /* We can now unmap/delete the original table (if fully mapped) */
345231844Sjkim
346231844Sjkim    AcpiTbDeleteTable (TableDesc);
347231844Sjkim
348231844Sjkim    /* Setup descriptor for the new table */
349231844Sjkim
350231844Sjkim    TableDesc->Address = NewAddress;
351231844Sjkim    TableDesc->Pointer = NewTable;
352231844Sjkim    TableDesc->Length = NewTableLength;
353231844Sjkim    TableDesc->Flags = NewFlags;
354231844Sjkim
355231844Sjkim    return (NewTable);
356231844Sjkim}
357231844Sjkim
358231844Sjkim
359231844Sjkim/*******************************************************************************
360231844Sjkim *
361167802Sjkim * FUNCTION:    AcpiTbResizeRootTableList
36267754Smsmith *
363167802Sjkim * PARAMETERS:  None
36467754Smsmith *
36567754Smsmith * RETURN:      Status
36667754Smsmith *
367167802Sjkim * DESCRIPTION: Expand the size of global table array
36867754Smsmith *
36967754Smsmith ******************************************************************************/
37067754Smsmith
37167754SmsmithACPI_STATUS
372167802SjkimAcpiTbResizeRootTableList (
373167802Sjkim    void)
37467754Smsmith{
375167802Sjkim    ACPI_TABLE_DESC         *Tables;
37667754Smsmith
37767754Smsmith
378167802Sjkim    ACPI_FUNCTION_TRACE (TbResizeRootTableList);
37967754Smsmith
38067754Smsmith
381167802Sjkim    /* AllowResize flag is a parameter to AcpiInitializeTables */
38267754Smsmith
383167802Sjkim    if (!(AcpiGbl_RootTableList.Flags & ACPI_ROOT_ALLOW_RESIZE))
38467754Smsmith    {
385167802Sjkim        ACPI_ERROR ((AE_INFO, "Resize of Root Table Array is not allowed"));
386167802Sjkim        return_ACPI_STATUS (AE_SUPPORT);
38767754Smsmith    }
38867754Smsmith
389167802Sjkim    /* Increase the Table Array size */
390167802Sjkim
391167802Sjkim    Tables = ACPI_ALLOCATE_ZEROED (
392207344Sjkim        ((ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount +
393193267Sjkim            ACPI_ROOT_TABLE_SIZE_INCREMENT) *
394193267Sjkim        sizeof (ACPI_TABLE_DESC));
395167802Sjkim    if (!Tables)
39667754Smsmith    {
397167802Sjkim        ACPI_ERROR ((AE_INFO, "Could not allocate new root table array"));
398167802Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
39999146Siwasaki    }
40091116Smsmith
401167802Sjkim    /* Copy and free the previous table array */
402167802Sjkim
403167802Sjkim    if (AcpiGbl_RootTableList.Tables)
40499146Siwasaki    {
405167802Sjkim        ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables,
406207344Sjkim            (ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount * sizeof (ACPI_TABLE_DESC));
407167802Sjkim
408167802Sjkim        if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
409167802Sjkim        {
410167802Sjkim            ACPI_FREE (AcpiGbl_RootTableList.Tables);
411167802Sjkim        }
41299146Siwasaki    }
41391116Smsmith
414167802Sjkim    AcpiGbl_RootTableList.Tables = Tables;
415207344Sjkim    AcpiGbl_RootTableList.MaxTableCount += ACPI_ROOT_TABLE_SIZE_INCREMENT;
416167802Sjkim    AcpiGbl_RootTableList.Flags |= (UINT8) ACPI_ROOT_ORIGIN_ALLOCATED;
41799146Siwasaki
418167802Sjkim    return_ACPI_STATUS (AE_OK);
41967754Smsmith}
42067754Smsmith
42167754Smsmith
42267754Smsmith/*******************************************************************************
42367754Smsmith *
424167802Sjkim * FUNCTION:    AcpiTbStoreTable
42567754Smsmith *
426167802Sjkim * PARAMETERS:  Address             - Table address
427167802Sjkim *              Table               - Table header
428167802Sjkim *              Length              - Table length
429167802Sjkim *              Flags               - flags
43067754Smsmith *
431167802Sjkim * RETURN:      Status and table index.
43267754Smsmith *
433167802Sjkim * DESCRIPTION: Add an ACPI table to the global table list
43467754Smsmith *
43567754Smsmith ******************************************************************************/
43667754Smsmith
43767754SmsmithACPI_STATUS
438167802SjkimAcpiTbStoreTable (
439167802Sjkim    ACPI_PHYSICAL_ADDRESS   Address,
440167802Sjkim    ACPI_TABLE_HEADER       *Table,
441167802Sjkim    UINT32                  Length,
442167802Sjkim    UINT8                   Flags,
443193267Sjkim    UINT32                  *TableIndex)
44467754Smsmith{
445207344Sjkim    ACPI_STATUS             Status;
446207344Sjkim    ACPI_TABLE_DESC         *NewTable;
44767754Smsmith
44867754Smsmith
449167802Sjkim    /* Ensure that there is room for the table in the Root Table List */
45067754Smsmith
451207344Sjkim    if (AcpiGbl_RootTableList.CurrentTableCount >=
452207344Sjkim        AcpiGbl_RootTableList.MaxTableCount)
453117521Snjl    {
454167802Sjkim        Status = AcpiTbResizeRootTableList();
455167802Sjkim        if (ACPI_FAILURE (Status))
456167802Sjkim        {
457167802Sjkim            return (Status);
458167802Sjkim        }
459117521Snjl    }
460117521Snjl
461207344Sjkim    NewTable = &AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount];
462207344Sjkim
463167802Sjkim    /* Initialize added table */
464151937Sjkim
465207344Sjkim    NewTable->Address = Address;
466207344Sjkim    NewTable->Pointer = Table;
467207344Sjkim    NewTable->Length = Length;
468207344Sjkim    NewTable->OwnerId = 0;
469207344Sjkim    NewTable->Flags = Flags;
470151937Sjkim
471207344Sjkim    ACPI_MOVE_32_TO_32 (&NewTable->Signature, Table->Signature);
472151937Sjkim
473207344Sjkim    *TableIndex = AcpiGbl_RootTableList.CurrentTableCount;
474207344Sjkim    AcpiGbl_RootTableList.CurrentTableCount++;
475207344Sjkim    return (AE_OK);
476167802Sjkim}
47767754Smsmith
478123315Snjl
479167802Sjkim/*******************************************************************************
480167802Sjkim *
481167802Sjkim * FUNCTION:    AcpiTbDeleteTable
482167802Sjkim *
483167802Sjkim * PARAMETERS:  TableIndex          - Table index
484167802Sjkim *
485167802Sjkim * RETURN:      None
486167802Sjkim *
487167802Sjkim * DESCRIPTION: Delete one internal ACPI table
488167802Sjkim *
489167802Sjkim ******************************************************************************/
490123315Snjl
491167802Sjkimvoid
492167802SjkimAcpiTbDeleteTable (
493167802Sjkim    ACPI_TABLE_DESC         *TableDesc)
494167802Sjkim{
495123315Snjl
496167802Sjkim    /* Table must be mapped or allocated */
497167802Sjkim
498167802Sjkim    if (!TableDesc->Pointer)
499123315Snjl    {
500167802Sjkim        return;
501117521Snjl    }
50267754Smsmith
503167802Sjkim    switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK)
504167802Sjkim    {
505167802Sjkim    case ACPI_TABLE_ORIGIN_MAPPED:
506167802Sjkim        AcpiOsUnmapMemory (TableDesc->Pointer, TableDesc->Length);
507167802Sjkim        break;
50867754Smsmith
509167802Sjkim    case ACPI_TABLE_ORIGIN_ALLOCATED:
510167802Sjkim        ACPI_FREE (TableDesc->Pointer);
511167802Sjkim        break;
51267754Smsmith
513167802Sjkim    default:
514167802Sjkim        break;
51567754Smsmith    }
51667754Smsmith
517167802Sjkim    TableDesc->Pointer = NULL;
51867754Smsmith}
51967754Smsmith
52067754Smsmith
52167754Smsmith/*******************************************************************************
52267754Smsmith *
523167802Sjkim * FUNCTION:    AcpiTbTerminate
52467754Smsmith *
525167802Sjkim * PARAMETERS:  None
52667754Smsmith *
527167802Sjkim * RETURN:      None
52867754Smsmith *
52967754Smsmith * DESCRIPTION: Delete all internal ACPI tables
53067754Smsmith *
53167754Smsmith ******************************************************************************/
53267754Smsmith
53367754Smsmithvoid
534167802SjkimAcpiTbTerminate (
535151937Sjkim    void)
53667754Smsmith{
537193267Sjkim    UINT32                  i;
53867754Smsmith
53967754Smsmith
540167802Sjkim    ACPI_FUNCTION_TRACE (TbTerminate);
541167802Sjkim
542167802Sjkim
543167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
544167802Sjkim
545167802Sjkim    /* Delete the individual tables */
546167802Sjkim
547207344Sjkim    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
548167802Sjkim    {
549167802Sjkim        AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[i]);
550167802Sjkim    }
551167802Sjkim
55267754Smsmith    /*
553167802Sjkim     * Delete the root table array if allocated locally. Array cannot be
554167802Sjkim     * mapped, so we don't need to check for that flag.
55567754Smsmith     */
556167802Sjkim    if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
55767754Smsmith    {
558167802Sjkim        ACPI_FREE (AcpiGbl_RootTableList.Tables);
55967754Smsmith    }
560167802Sjkim
561167802Sjkim    AcpiGbl_RootTableList.Tables = NULL;
562167802Sjkim    AcpiGbl_RootTableList.Flags = 0;
563207344Sjkim    AcpiGbl_RootTableList.CurrentTableCount = 0;
564167802Sjkim
565167802Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
566167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
56767754Smsmith}
56867754Smsmith
56967754Smsmith
57067754Smsmith/*******************************************************************************
57167754Smsmith *
572167802Sjkim * FUNCTION:    AcpiTbDeleteNamespaceByOwner
57367754Smsmith *
574167802Sjkim * PARAMETERS:  TableIndex          - Table index
57567754Smsmith *
576193267Sjkim * RETURN:      Status
57767754Smsmith *
578167802Sjkim * DESCRIPTION: Delete all namespace objects created when this table was loaded.
57967754Smsmith *
58067754Smsmith ******************************************************************************/
58167754Smsmith
582193267SjkimACPI_STATUS
583167802SjkimAcpiTbDeleteNamespaceByOwner (
584193267Sjkim    UINT32                  TableIndex)
58567754Smsmith{
586167802Sjkim    ACPI_OWNER_ID           OwnerId;
587193267Sjkim    ACPI_STATUS             Status;
58867754Smsmith
58967754Smsmith
590193267Sjkim    ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner);
591193267Sjkim
592193267Sjkim
593193267Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES);
594193267Sjkim    if (ACPI_FAILURE (Status))
59567754Smsmith    {
596193267Sjkim        return_ACPI_STATUS (Status);
59767754Smsmith    }
598193267Sjkim
599207344Sjkim    if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
60091116Smsmith    {
601193267Sjkim        /* The table index does not exist */
602193267Sjkim
603167802Sjkim        (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
604193267Sjkim        return_ACPI_STATUS (AE_NOT_EXIST);
60591116Smsmith    }
60667754Smsmith
607193267Sjkim    /* Get the owner ID for this table, used to delete namespace nodes */
608193267Sjkim
609193267Sjkim    OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
610167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
611193267Sjkim
612193267Sjkim    /*
613193267Sjkim     * Need to acquire the namespace writer lock to prevent interference
614193267Sjkim     * with any concurrent namespace walks. The interpreter must be
615193267Sjkim     * released during the deletion since the acquisition of the deletion
616193267Sjkim     * lock may block, and also since the execution of a namespace walk
617193267Sjkim     * must be allowed to use the interpreter.
618193267Sjkim     */
619193267Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
620193267Sjkim    Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock);
621193267Sjkim
622167802Sjkim    AcpiNsDeleteNamespaceByOwner (OwnerId);
623193267Sjkim    if (ACPI_FAILURE (Status))
624193267Sjkim    {
625193267Sjkim        return_ACPI_STATUS (Status);
626193267Sjkim    }
627193267Sjkim
628193267Sjkim    AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock);
629193267Sjkim
630193267Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
631193267Sjkim    return_ACPI_STATUS (Status);
632167802Sjkim}
63367754Smsmith
63467754Smsmith
635167802Sjkim/*******************************************************************************
636167802Sjkim *
637167802Sjkim * FUNCTION:    AcpiTbAllocateOwnerId
638167802Sjkim *
639167802Sjkim * PARAMETERS:  TableIndex          - Table index
640167802Sjkim *
641167802Sjkim * RETURN:      Status
642167802Sjkim *
643167802Sjkim * DESCRIPTION: Allocates OwnerId in TableDesc
644167802Sjkim *
645167802Sjkim ******************************************************************************/
64667754Smsmith
647167802SjkimACPI_STATUS
648167802SjkimAcpiTbAllocateOwnerId (
649193267Sjkim    UINT32                  TableIndex)
650167802Sjkim{
651167802Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
65267754Smsmith
65367754Smsmith
654167802Sjkim    ACPI_FUNCTION_TRACE (TbAllocateOwnerId);
65567754Smsmith
65667754Smsmith
657167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
658207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
65967754Smsmith    {
660167802Sjkim        Status = AcpiUtAllocateOwnerId
661167802Sjkim                    (&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
66267754Smsmith    }
66367754Smsmith
664117521Snjl    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
665167802Sjkim    return_ACPI_STATUS (Status);
66667754Smsmith}
66767754Smsmith
66867754Smsmith
66967754Smsmith/*******************************************************************************
67067754Smsmith *
671167802Sjkim * FUNCTION:    AcpiTbReleaseOwnerId
67267754Smsmith *
673167802Sjkim * PARAMETERS:  TableIndex          - Table index
67467754Smsmith *
675167802Sjkim * RETURN:      Status
67667754Smsmith *
677167802Sjkim * DESCRIPTION: Releases OwnerId in TableDesc
67867754Smsmith *
67967754Smsmith ******************************************************************************/
68067754Smsmith
681167802SjkimACPI_STATUS
682167802SjkimAcpiTbReleaseOwnerId (
683193267Sjkim    UINT32                  TableIndex)
68467754Smsmith{
685167802Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
68667754Smsmith
687117521Snjl
688167802Sjkim    ACPI_FUNCTION_TRACE (TbReleaseOwnerId);
68967754Smsmith
690117521Snjl
691167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
692207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
69367754Smsmith    {
694193267Sjkim        AcpiUtReleaseOwnerId (
695193267Sjkim            &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
696167802Sjkim        Status = AE_OK;
697167802Sjkim    }
69867754Smsmith
699167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
700167802Sjkim    return_ACPI_STATUS (Status);
70167754Smsmith}
70267754Smsmith
70367754Smsmith
70467754Smsmith/*******************************************************************************
70567754Smsmith *
706167802Sjkim * FUNCTION:    AcpiTbGetOwnerId
70767754Smsmith *
708167802Sjkim * PARAMETERS:  TableIndex          - Table index
709167802Sjkim *              OwnerId             - Where the table OwnerId is returned
71067754Smsmith *
711167802Sjkim * RETURN:      Status
71267754Smsmith *
713167802Sjkim * DESCRIPTION: returns OwnerId for the ACPI table
71467754Smsmith *
71567754Smsmith ******************************************************************************/
71667754Smsmith
717167802SjkimACPI_STATUS
718167802SjkimAcpiTbGetOwnerId (
719193267Sjkim    UINT32                  TableIndex,
720167802Sjkim    ACPI_OWNER_ID           *OwnerId)
72167754Smsmith{
722167802Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
72367754Smsmith
72467754Smsmith
725167802Sjkim    ACPI_FUNCTION_TRACE (TbGetOwnerId);
72667754Smsmith
72767754Smsmith
728167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
729207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
73067754Smsmith    {
731167802Sjkim        *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
732167802Sjkim        Status = AE_OK;
73367754Smsmith    }
73467754Smsmith
735167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
736167802Sjkim    return_ACPI_STATUS (Status);
737167802Sjkim}
73867754Smsmith
73967754Smsmith
740167802Sjkim/*******************************************************************************
741167802Sjkim *
742167802Sjkim * FUNCTION:    AcpiTbIsTableLoaded
743167802Sjkim *
744167802Sjkim * PARAMETERS:  TableIndex          - Table index
745167802Sjkim *
746167802Sjkim * RETURN:      Table Loaded Flag
747167802Sjkim *
748167802Sjkim ******************************************************************************/
749117521Snjl
750167802SjkimBOOLEAN
751167802SjkimAcpiTbIsTableLoaded (
752193267Sjkim    UINT32                  TableIndex)
753167802Sjkim{
754167802Sjkim    BOOLEAN                 IsLoaded = FALSE;
755167802Sjkim
756167802Sjkim
757167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
758207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
75967754Smsmith    {
760167802Sjkim        IsLoaded = (BOOLEAN)
761193267Sjkim            (AcpiGbl_RootTableList.Tables[TableIndex].Flags &
762193267Sjkim            ACPI_TABLE_IS_LOADED);
76367754Smsmith    }
76467754Smsmith
765167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
766167802Sjkim    return (IsLoaded);
767167802Sjkim}
76867754Smsmith
76967754Smsmith
770167802Sjkim/*******************************************************************************
771167802Sjkim *
772167802Sjkim * FUNCTION:    AcpiTbSetTableLoadedFlag
773167802Sjkim *
774167802Sjkim * PARAMETERS:  TableIndex          - Table index
775167802Sjkim *              IsLoaded            - TRUE if table is loaded, FALSE otherwise
776167802Sjkim *
777167802Sjkim * RETURN:      None
778167802Sjkim *
779167802Sjkim * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
780167802Sjkim *
781167802Sjkim ******************************************************************************/
78267754Smsmith
783167802Sjkimvoid
784167802SjkimAcpiTbSetTableLoadedFlag (
785193267Sjkim    UINT32                  TableIndex,
786167802Sjkim    BOOLEAN                 IsLoaded)
787167802Sjkim{
78867754Smsmith
789167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
790207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
791167802Sjkim    {
792167802Sjkim        if (IsLoaded)
793167802Sjkim        {
794193267Sjkim            AcpiGbl_RootTableList.Tables[TableIndex].Flags |=
795193267Sjkim                ACPI_TABLE_IS_LOADED;
796167802Sjkim        }
797167802Sjkim        else
798167802Sjkim        {
799193267Sjkim            AcpiGbl_RootTableList.Tables[TableIndex].Flags &=
800193267Sjkim                ~ACPI_TABLE_IS_LOADED;
801167802Sjkim        }
802167802Sjkim    }
80367754Smsmith
804167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
80567754Smsmith}
80667754Smsmith
807