tbinstal.c revision 245582
167754Smsmith/******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: tbinstal - ACPI table installation and removal
467754Smsmith *
567754Smsmith *****************************************************************************/
667754Smsmith
7217365Sjkim/*
8245582Sjkim * Copyright (C) 2000 - 2013, 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    {
160238381Sjkim        ACPI_BIOS_ERROR ((AE_INFO,
161238381Sjkim            "Table has invalid signature [%4.4s] (0x%8.8X), "
162238381Sjkim            "must be SSDT or OEMx",
163222544Sjkim            AcpiUtValidAcpiName (*(UINT32 *) TableDesc->Pointer->Signature) ?
164222544Sjkim                TableDesc->Pointer->Signature : "????",
165222544Sjkim            *(UINT32 *) TableDesc->Pointer->Signature));
166167802Sjkim
167222544Sjkim        return_ACPI_STATUS (AE_BAD_SIGNATURE);
168222544Sjkim    }
169222544Sjkim
170167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
171167802Sjkim
172167802Sjkim    /* Check if table is already registered */
173167802Sjkim
174207344Sjkim    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
175151937Sjkim    {
176167802Sjkim        if (!AcpiGbl_RootTableList.Tables[i].Pointer)
177167802Sjkim        {
178167802Sjkim            Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]);
179193267Sjkim            if (ACPI_FAILURE (Status) ||
180193267Sjkim                !AcpiGbl_RootTableList.Tables[i].Pointer)
181167802Sjkim            {
182167802Sjkim                continue;
183167802Sjkim            }
184167802Sjkim        }
185167802Sjkim
186193267Sjkim        /*
187193267Sjkim         * Check for a table match on the entire table length,
188193267Sjkim         * not just the header.
189193267Sjkim         */
190193267Sjkim        if (TableDesc->Length != AcpiGbl_RootTableList.Tables[i].Length)
191193267Sjkim        {
192193267Sjkim            continue;
193193267Sjkim        }
194193267Sjkim
195167802Sjkim        if (ACPI_MEMCMP (TableDesc->Pointer,
196193267Sjkim                AcpiGbl_RootTableList.Tables[i].Pointer,
197193267Sjkim                AcpiGbl_RootTableList.Tables[i].Length))
198167802Sjkim        {
199167802Sjkim            continue;
200167802Sjkim        }
201167802Sjkim
202193267Sjkim        /*
203193267Sjkim         * Note: the current mechanism does not unregister a table if it is
204193267Sjkim         * dynamically unloaded. The related namespace entries are deleted,
205193267Sjkim         * but the table remains in the root table list.
206193267Sjkim         *
207193267Sjkim         * The assumption here is that the number of different tables that
208193267Sjkim         * will be loaded is actually small, and there is minimal overhead
209193267Sjkim         * in just keeping the table in case it is needed again.
210193267Sjkim         *
211193267Sjkim         * If this assumption changes in the future (perhaps on large
212193267Sjkim         * machines with many table load/unload operations), tables will
213193267Sjkim         * need to be unregistered when they are unloaded, and slots in the
214193267Sjkim         * root table list should be reused when empty.
215193267Sjkim         */
216167802Sjkim
217193267Sjkim        /*
218193267Sjkim         * Table is already registered.
219193267Sjkim         * We can delete the table that was passed as a parameter.
220193267Sjkim         */
221167802Sjkim        AcpiTbDeleteTable (TableDesc);
222167802Sjkim        *TableIndex = i;
223193267Sjkim
224193267Sjkim        if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED)
225193267Sjkim        {
226193267Sjkim            /* Table is still loaded, this is an error */
227193267Sjkim
228193267Sjkim            Status = AE_ALREADY_EXISTS;
229193267Sjkim            goto Release;
230193267Sjkim        }
231193267Sjkim        else
232193267Sjkim        {
233193267Sjkim            /* Table was unloaded, allow it to be reloaded */
234193267Sjkim
235193267Sjkim            TableDesc->Pointer = AcpiGbl_RootTableList.Tables[i].Pointer;
236193267Sjkim            TableDesc->Address = AcpiGbl_RootTableList.Tables[i].Address;
237193267Sjkim            Status = AE_OK;
238193267Sjkim            goto PrintHeader;
239193267Sjkim        }
240151937Sjkim    }
241151937Sjkim
242167802Sjkim    /*
243193267Sjkim     * ACPI Table Override:
244193267Sjkim     * Allow the host to override dynamically loaded tables.
245231844Sjkim     * NOTE: the table is fully mapped at this point, and the mapping will
246231844Sjkim     * be deleted by TbTableOverride if the table is actually overridden.
247167802Sjkim     */
248231844Sjkim    (void) AcpiTbTableOverride (TableDesc->Pointer, TableDesc);
249193267Sjkim
250193267Sjkim    /* Add the table to the global root table list */
251193267Sjkim
252167802Sjkim    Status = AcpiTbStoreTable (TableDesc->Address, TableDesc->Pointer,
253167802Sjkim                TableDesc->Length, TableDesc->Flags, TableIndex);
254100966Siwasaki    if (ACPI_FAILURE (Status))
255100966Siwasaki    {
256167802Sjkim        goto Release;
257100966Siwasaki    }
25867754Smsmith
259193267SjkimPrintHeader:
260167802Sjkim    AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer);
26167754Smsmith
262167802SjkimRelease:
26391116Smsmith    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
26467754Smsmith    return_ACPI_STATUS (Status);
26567754Smsmith}
26667754Smsmith
26767754Smsmith
26867754Smsmith/*******************************************************************************
26967754Smsmith *
270231844Sjkim * FUNCTION:    AcpiTbTableOverride
271231844Sjkim *
272231844Sjkim * PARAMETERS:  TableHeader         - Header for the original table
273231844Sjkim *              TableDesc           - Table descriptor initialized for the
274231844Sjkim *                                    original table. May or may not be mapped.
275231844Sjkim *
276231844Sjkim * RETURN:      Pointer to the entire new table. NULL if table not overridden.
277231844Sjkim *              If overridden, installs the new table within the input table
278231844Sjkim *              descriptor.
279231844Sjkim *
280231844Sjkim * DESCRIPTION: Attempt table override by calling the OSL override functions.
281231844Sjkim *              Note: If the table is overridden, then the entire new table
282231844Sjkim *              is mapped and returned by this function.
283231844Sjkim *
284231844Sjkim ******************************************************************************/
285231844Sjkim
286231844SjkimACPI_TABLE_HEADER *
287231844SjkimAcpiTbTableOverride (
288231844Sjkim    ACPI_TABLE_HEADER       *TableHeader,
289231844Sjkim    ACPI_TABLE_DESC         *TableDesc)
290231844Sjkim{
291231844Sjkim    ACPI_STATUS             Status;
292231844Sjkim    ACPI_TABLE_HEADER       *NewTable = NULL;
293231844Sjkim    ACPI_PHYSICAL_ADDRESS   NewAddress = 0;
294231844Sjkim    UINT32                  NewTableLength = 0;
295231844Sjkim    UINT8                   NewFlags;
296231844Sjkim    char                    *OverrideType;
297231844Sjkim
298231844Sjkim
299231844Sjkim    /* (1) Attempt logical override (returns a logical address) */
300231844Sjkim
301231844Sjkim    Status = AcpiOsTableOverride (TableHeader, &NewTable);
302231844Sjkim    if (ACPI_SUCCESS (Status) && NewTable)
303231844Sjkim    {
304231844Sjkim        NewAddress = ACPI_PTR_TO_PHYSADDR (NewTable);
305231844Sjkim        NewTableLength = NewTable->Length;
306231844Sjkim        NewFlags = ACPI_TABLE_ORIGIN_OVERRIDE;
307231844Sjkim        OverrideType = "Logical";
308231844Sjkim        goto FinishOverride;
309231844Sjkim    }
310231844Sjkim
311231844Sjkim    /* (2) Attempt physical override (returns a physical address) */
312231844Sjkim
313231844Sjkim    Status = AcpiOsPhysicalTableOverride (TableHeader,
314231844Sjkim        &NewAddress, &NewTableLength);
315231844Sjkim    if (ACPI_SUCCESS (Status) && NewAddress && NewTableLength)
316231844Sjkim    {
317231844Sjkim        /* Map the entire new table */
318231844Sjkim
319231844Sjkim        NewTable = AcpiOsMapMemory (NewAddress, NewTableLength);
320231844Sjkim        if (!NewTable)
321231844Sjkim        {
322231844Sjkim            ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
323231844Sjkim                "%4.4s %p Attempted physical table override failed",
324231844Sjkim                TableHeader->Signature,
325231844Sjkim                ACPI_CAST_PTR (void, TableDesc->Address)));
326231844Sjkim            return (NULL);
327231844Sjkim        }
328231844Sjkim
329231844Sjkim        OverrideType = "Physical";
330231844Sjkim        NewFlags = ACPI_TABLE_ORIGIN_MAPPED;
331231844Sjkim        goto FinishOverride;
332231844Sjkim    }
333231844Sjkim
334231844Sjkim    return (NULL); /* There was no override */
335231844Sjkim
336231844Sjkim
337231844SjkimFinishOverride:
338231844Sjkim
339231844Sjkim    ACPI_INFO ((AE_INFO,
340231844Sjkim        "%4.4s %p %s table override, new table: %p",
341231844Sjkim        TableHeader->Signature,
342231844Sjkim        ACPI_CAST_PTR (void, TableDesc->Address),
343231844Sjkim        OverrideType, NewTable));
344231844Sjkim
345231844Sjkim    /* We can now unmap/delete the original table (if fully mapped) */
346231844Sjkim
347231844Sjkim    AcpiTbDeleteTable (TableDesc);
348231844Sjkim
349231844Sjkim    /* Setup descriptor for the new table */
350231844Sjkim
351231844Sjkim    TableDesc->Address = NewAddress;
352231844Sjkim    TableDesc->Pointer = NewTable;
353231844Sjkim    TableDesc->Length = NewTableLength;
354231844Sjkim    TableDesc->Flags = NewFlags;
355231844Sjkim
356231844Sjkim    return (NewTable);
357231844Sjkim}
358231844Sjkim
359231844Sjkim
360231844Sjkim/*******************************************************************************
361231844Sjkim *
362167802Sjkim * FUNCTION:    AcpiTbResizeRootTableList
36367754Smsmith *
364167802Sjkim * PARAMETERS:  None
36567754Smsmith *
36667754Smsmith * RETURN:      Status
36767754Smsmith *
368167802Sjkim * DESCRIPTION: Expand the size of global table array
36967754Smsmith *
37067754Smsmith ******************************************************************************/
37167754Smsmith
37267754SmsmithACPI_STATUS
373167802SjkimAcpiTbResizeRootTableList (
374167802Sjkim    void)
37567754Smsmith{
376167802Sjkim    ACPI_TABLE_DESC         *Tables;
377240716Sjkim    UINT32                  TableCount;
37867754Smsmith
37967754Smsmith
380167802Sjkim    ACPI_FUNCTION_TRACE (TbResizeRootTableList);
38167754Smsmith
38267754Smsmith
383167802Sjkim    /* AllowResize flag is a parameter to AcpiInitializeTables */
38467754Smsmith
385167802Sjkim    if (!(AcpiGbl_RootTableList.Flags & ACPI_ROOT_ALLOW_RESIZE))
38667754Smsmith    {
387167802Sjkim        ACPI_ERROR ((AE_INFO, "Resize of Root Table Array is not allowed"));
388167802Sjkim        return_ACPI_STATUS (AE_SUPPORT);
38967754Smsmith    }
39067754Smsmith
391167802Sjkim    /* Increase the Table Array size */
392167802Sjkim
393240716Sjkim    if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
394240716Sjkim    {
395240716Sjkim        TableCount = AcpiGbl_RootTableList.MaxTableCount;
396240716Sjkim    }
397240716Sjkim    else
398240716Sjkim    {
399240716Sjkim        TableCount = AcpiGbl_RootTableList.CurrentTableCount;
400240716Sjkim    }
401240716Sjkim
402167802Sjkim    Tables = ACPI_ALLOCATE_ZEROED (
403240716Sjkim        ((ACPI_SIZE) TableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT) *
404193267Sjkim        sizeof (ACPI_TABLE_DESC));
405167802Sjkim    if (!Tables)
40667754Smsmith    {
407167802Sjkim        ACPI_ERROR ((AE_INFO, "Could not allocate new root table array"));
408167802Sjkim        return_ACPI_STATUS (AE_NO_MEMORY);
40999146Siwasaki    }
41091116Smsmith
411167802Sjkim    /* Copy and free the previous table array */
412167802Sjkim
413167802Sjkim    if (AcpiGbl_RootTableList.Tables)
41499146Siwasaki    {
415167802Sjkim        ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables,
416240716Sjkim            (ACPI_SIZE) TableCount * sizeof (ACPI_TABLE_DESC));
417167802Sjkim
418167802Sjkim        if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
419167802Sjkim        {
420167802Sjkim            ACPI_FREE (AcpiGbl_RootTableList.Tables);
421167802Sjkim        }
42299146Siwasaki    }
42391116Smsmith
424167802Sjkim    AcpiGbl_RootTableList.Tables = Tables;
425240716Sjkim    AcpiGbl_RootTableList.MaxTableCount =
426240716Sjkim        TableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT;
427240716Sjkim    AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
42899146Siwasaki
429167802Sjkim    return_ACPI_STATUS (AE_OK);
43067754Smsmith}
43167754Smsmith
43267754Smsmith
43367754Smsmith/*******************************************************************************
43467754Smsmith *
435167802Sjkim * FUNCTION:    AcpiTbStoreTable
43667754Smsmith *
437167802Sjkim * PARAMETERS:  Address             - Table address
438167802Sjkim *              Table               - Table header
439167802Sjkim *              Length              - Table length
440167802Sjkim *              Flags               - flags
44167754Smsmith *
442167802Sjkim * RETURN:      Status and table index.
44367754Smsmith *
444167802Sjkim * DESCRIPTION: Add an ACPI table to the global table list
44567754Smsmith *
44667754Smsmith ******************************************************************************/
44767754Smsmith
44867754SmsmithACPI_STATUS
449167802SjkimAcpiTbStoreTable (
450167802Sjkim    ACPI_PHYSICAL_ADDRESS   Address,
451167802Sjkim    ACPI_TABLE_HEADER       *Table,
452167802Sjkim    UINT32                  Length,
453167802Sjkim    UINT8                   Flags,
454193267Sjkim    UINT32                  *TableIndex)
45567754Smsmith{
456207344Sjkim    ACPI_STATUS             Status;
457207344Sjkim    ACPI_TABLE_DESC         *NewTable;
45867754Smsmith
45967754Smsmith
460167802Sjkim    /* Ensure that there is room for the table in the Root Table List */
46167754Smsmith
462207344Sjkim    if (AcpiGbl_RootTableList.CurrentTableCount >=
463207344Sjkim        AcpiGbl_RootTableList.MaxTableCount)
464117521Snjl    {
465167802Sjkim        Status = AcpiTbResizeRootTableList();
466167802Sjkim        if (ACPI_FAILURE (Status))
467167802Sjkim        {
468167802Sjkim            return (Status);
469167802Sjkim        }
470117521Snjl    }
471117521Snjl
472207344Sjkim    NewTable = &AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount];
473207344Sjkim
474167802Sjkim    /* Initialize added table */
475151937Sjkim
476207344Sjkim    NewTable->Address = Address;
477207344Sjkim    NewTable->Pointer = Table;
478207344Sjkim    NewTable->Length = Length;
479207344Sjkim    NewTable->OwnerId = 0;
480207344Sjkim    NewTable->Flags = Flags;
481151937Sjkim
482207344Sjkim    ACPI_MOVE_32_TO_32 (&NewTable->Signature, Table->Signature);
483151937Sjkim
484207344Sjkim    *TableIndex = AcpiGbl_RootTableList.CurrentTableCount;
485207344Sjkim    AcpiGbl_RootTableList.CurrentTableCount++;
486207344Sjkim    return (AE_OK);
487167802Sjkim}
48867754Smsmith
489123315Snjl
490167802Sjkim/*******************************************************************************
491167802Sjkim *
492167802Sjkim * FUNCTION:    AcpiTbDeleteTable
493167802Sjkim *
494167802Sjkim * PARAMETERS:  TableIndex          - Table index
495167802Sjkim *
496167802Sjkim * RETURN:      None
497167802Sjkim *
498167802Sjkim * DESCRIPTION: Delete one internal ACPI table
499167802Sjkim *
500167802Sjkim ******************************************************************************/
501123315Snjl
502167802Sjkimvoid
503167802SjkimAcpiTbDeleteTable (
504167802Sjkim    ACPI_TABLE_DESC         *TableDesc)
505167802Sjkim{
506123315Snjl
507167802Sjkim    /* Table must be mapped or allocated */
508167802Sjkim
509167802Sjkim    if (!TableDesc->Pointer)
510123315Snjl    {
511167802Sjkim        return;
512117521Snjl    }
51367754Smsmith
514167802Sjkim    switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK)
515167802Sjkim    {
516167802Sjkim    case ACPI_TABLE_ORIGIN_MAPPED:
517167802Sjkim        AcpiOsUnmapMemory (TableDesc->Pointer, TableDesc->Length);
518167802Sjkim        break;
51967754Smsmith
520167802Sjkim    case ACPI_TABLE_ORIGIN_ALLOCATED:
521167802Sjkim        ACPI_FREE (TableDesc->Pointer);
522167802Sjkim        break;
52367754Smsmith
524233250Sjkim    /* Not mapped or allocated, there is nothing we can do */
525233250Sjkim
526167802Sjkim    default:
527233250Sjkim        return;
52867754Smsmith    }
52967754Smsmith
530167802Sjkim    TableDesc->Pointer = NULL;
53167754Smsmith}
53267754Smsmith
53367754Smsmith
53467754Smsmith/*******************************************************************************
53567754Smsmith *
536167802Sjkim * FUNCTION:    AcpiTbTerminate
53767754Smsmith *
538167802Sjkim * PARAMETERS:  None
53967754Smsmith *
540167802Sjkim * RETURN:      None
54167754Smsmith *
54267754Smsmith * DESCRIPTION: Delete all internal ACPI tables
54367754Smsmith *
54467754Smsmith ******************************************************************************/
54567754Smsmith
54667754Smsmithvoid
547167802SjkimAcpiTbTerminate (
548151937Sjkim    void)
54967754Smsmith{
550193267Sjkim    UINT32                  i;
55167754Smsmith
55267754Smsmith
553167802Sjkim    ACPI_FUNCTION_TRACE (TbTerminate);
554167802Sjkim
555167802Sjkim
556167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
557167802Sjkim
558167802Sjkim    /* Delete the individual tables */
559167802Sjkim
560207344Sjkim    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
561167802Sjkim    {
562167802Sjkim        AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[i]);
563167802Sjkim    }
564167802Sjkim
56567754Smsmith    /*
566167802Sjkim     * Delete the root table array if allocated locally. Array cannot be
567167802Sjkim     * mapped, so we don't need to check for that flag.
56867754Smsmith     */
569167802Sjkim    if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
57067754Smsmith    {
571167802Sjkim        ACPI_FREE (AcpiGbl_RootTableList.Tables);
57267754Smsmith    }
573167802Sjkim
574167802Sjkim    AcpiGbl_RootTableList.Tables = NULL;
575167802Sjkim    AcpiGbl_RootTableList.Flags = 0;
576207344Sjkim    AcpiGbl_RootTableList.CurrentTableCount = 0;
577167802Sjkim
578167802Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
579167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
580241973Sjkim
581241973Sjkim    return_VOID;
58267754Smsmith}
58367754Smsmith
58467754Smsmith
58567754Smsmith/*******************************************************************************
58667754Smsmith *
587167802Sjkim * FUNCTION:    AcpiTbDeleteNamespaceByOwner
58867754Smsmith *
589167802Sjkim * PARAMETERS:  TableIndex          - Table index
59067754Smsmith *
591193267Sjkim * RETURN:      Status
59267754Smsmith *
593167802Sjkim * DESCRIPTION: Delete all namespace objects created when this table was loaded.
59467754Smsmith *
59567754Smsmith ******************************************************************************/
59667754Smsmith
597193267SjkimACPI_STATUS
598167802SjkimAcpiTbDeleteNamespaceByOwner (
599193267Sjkim    UINT32                  TableIndex)
60067754Smsmith{
601167802Sjkim    ACPI_OWNER_ID           OwnerId;
602193267Sjkim    ACPI_STATUS             Status;
60367754Smsmith
60467754Smsmith
605193267Sjkim    ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner);
606193267Sjkim
607193267Sjkim
608193267Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES);
609193267Sjkim    if (ACPI_FAILURE (Status))
61067754Smsmith    {
611193267Sjkim        return_ACPI_STATUS (Status);
61267754Smsmith    }
613193267Sjkim
614207344Sjkim    if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
61591116Smsmith    {
616193267Sjkim        /* The table index does not exist */
617193267Sjkim
618167802Sjkim        (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
619193267Sjkim        return_ACPI_STATUS (AE_NOT_EXIST);
62091116Smsmith    }
62167754Smsmith
622193267Sjkim    /* Get the owner ID for this table, used to delete namespace nodes */
623193267Sjkim
624193267Sjkim    OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
625167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
626193267Sjkim
627193267Sjkim    /*
628193267Sjkim     * Need to acquire the namespace writer lock to prevent interference
629193267Sjkim     * with any concurrent namespace walks. The interpreter must be
630193267Sjkim     * released during the deletion since the acquisition of the deletion
631193267Sjkim     * lock may block, and also since the execution of a namespace walk
632193267Sjkim     * must be allowed to use the interpreter.
633193267Sjkim     */
634193267Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
635193267Sjkim    Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock);
636193267Sjkim
637167802Sjkim    AcpiNsDeleteNamespaceByOwner (OwnerId);
638193267Sjkim    if (ACPI_FAILURE (Status))
639193267Sjkim    {
640193267Sjkim        return_ACPI_STATUS (Status);
641193267Sjkim    }
642193267Sjkim
643193267Sjkim    AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock);
644193267Sjkim
645193267Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
646193267Sjkim    return_ACPI_STATUS (Status);
647167802Sjkim}
64867754Smsmith
64967754Smsmith
650167802Sjkim/*******************************************************************************
651167802Sjkim *
652167802Sjkim * FUNCTION:    AcpiTbAllocateOwnerId
653167802Sjkim *
654167802Sjkim * PARAMETERS:  TableIndex          - Table index
655167802Sjkim *
656167802Sjkim * RETURN:      Status
657167802Sjkim *
658167802Sjkim * DESCRIPTION: Allocates OwnerId in TableDesc
659167802Sjkim *
660167802Sjkim ******************************************************************************/
66167754Smsmith
662167802SjkimACPI_STATUS
663167802SjkimAcpiTbAllocateOwnerId (
664193267Sjkim    UINT32                  TableIndex)
665167802Sjkim{
666167802Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
66767754Smsmith
66867754Smsmith
669167802Sjkim    ACPI_FUNCTION_TRACE (TbAllocateOwnerId);
67067754Smsmith
67167754Smsmith
672167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
673207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
67467754Smsmith    {
675167802Sjkim        Status = AcpiUtAllocateOwnerId
676167802Sjkim                    (&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
67767754Smsmith    }
67867754Smsmith
679117521Snjl    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
680167802Sjkim    return_ACPI_STATUS (Status);
68167754Smsmith}
68267754Smsmith
68367754Smsmith
68467754Smsmith/*******************************************************************************
68567754Smsmith *
686167802Sjkim * FUNCTION:    AcpiTbReleaseOwnerId
68767754Smsmith *
688167802Sjkim * PARAMETERS:  TableIndex          - Table index
68967754Smsmith *
690167802Sjkim * RETURN:      Status
69167754Smsmith *
692167802Sjkim * DESCRIPTION: Releases OwnerId in TableDesc
69367754Smsmith *
69467754Smsmith ******************************************************************************/
69567754Smsmith
696167802SjkimACPI_STATUS
697167802SjkimAcpiTbReleaseOwnerId (
698193267Sjkim    UINT32                  TableIndex)
69967754Smsmith{
700167802Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
70167754Smsmith
702117521Snjl
703167802Sjkim    ACPI_FUNCTION_TRACE (TbReleaseOwnerId);
70467754Smsmith
705117521Snjl
706167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
707207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
70867754Smsmith    {
709193267Sjkim        AcpiUtReleaseOwnerId (
710193267Sjkim            &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
711167802Sjkim        Status = AE_OK;
712167802Sjkim    }
71367754Smsmith
714167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
715167802Sjkim    return_ACPI_STATUS (Status);
71667754Smsmith}
71767754Smsmith
71867754Smsmith
71967754Smsmith/*******************************************************************************
72067754Smsmith *
721167802Sjkim * FUNCTION:    AcpiTbGetOwnerId
72267754Smsmith *
723167802Sjkim * PARAMETERS:  TableIndex          - Table index
724167802Sjkim *              OwnerId             - Where the table OwnerId is returned
72567754Smsmith *
726167802Sjkim * RETURN:      Status
72767754Smsmith *
728167802Sjkim * DESCRIPTION: returns OwnerId for the ACPI table
72967754Smsmith *
73067754Smsmith ******************************************************************************/
73167754Smsmith
732167802SjkimACPI_STATUS
733167802SjkimAcpiTbGetOwnerId (
734193267Sjkim    UINT32                  TableIndex,
735167802Sjkim    ACPI_OWNER_ID           *OwnerId)
73667754Smsmith{
737167802Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
73867754Smsmith
73967754Smsmith
740167802Sjkim    ACPI_FUNCTION_TRACE (TbGetOwnerId);
74167754Smsmith
74267754Smsmith
743167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
744207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
74567754Smsmith    {
746167802Sjkim        *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
747167802Sjkim        Status = AE_OK;
74867754Smsmith    }
74967754Smsmith
750167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
751167802Sjkim    return_ACPI_STATUS (Status);
752167802Sjkim}
75367754Smsmith
75467754Smsmith
755167802Sjkim/*******************************************************************************
756167802Sjkim *
757167802Sjkim * FUNCTION:    AcpiTbIsTableLoaded
758167802Sjkim *
759167802Sjkim * PARAMETERS:  TableIndex          - Table index
760167802Sjkim *
761167802Sjkim * RETURN:      Table Loaded Flag
762167802Sjkim *
763167802Sjkim ******************************************************************************/
764117521Snjl
765167802SjkimBOOLEAN
766167802SjkimAcpiTbIsTableLoaded (
767193267Sjkim    UINT32                  TableIndex)
768167802Sjkim{
769167802Sjkim    BOOLEAN                 IsLoaded = FALSE;
770167802Sjkim
771167802Sjkim
772167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
773207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
77467754Smsmith    {
775167802Sjkim        IsLoaded = (BOOLEAN)
776193267Sjkim            (AcpiGbl_RootTableList.Tables[TableIndex].Flags &
777193267Sjkim            ACPI_TABLE_IS_LOADED);
77867754Smsmith    }
77967754Smsmith
780167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
781167802Sjkim    return (IsLoaded);
782167802Sjkim}
78367754Smsmith
78467754Smsmith
785167802Sjkim/*******************************************************************************
786167802Sjkim *
787167802Sjkim * FUNCTION:    AcpiTbSetTableLoadedFlag
788167802Sjkim *
789167802Sjkim * PARAMETERS:  TableIndex          - Table index
790167802Sjkim *              IsLoaded            - TRUE if table is loaded, FALSE otherwise
791167802Sjkim *
792167802Sjkim * RETURN:      None
793167802Sjkim *
794167802Sjkim * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
795167802Sjkim *
796167802Sjkim ******************************************************************************/
79767754Smsmith
798167802Sjkimvoid
799167802SjkimAcpiTbSetTableLoadedFlag (
800193267Sjkim    UINT32                  TableIndex,
801167802Sjkim    BOOLEAN                 IsLoaded)
802167802Sjkim{
80367754Smsmith
804167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
805207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
806167802Sjkim    {
807167802Sjkim        if (IsLoaded)
808167802Sjkim        {
809193267Sjkim            AcpiGbl_RootTableList.Tables[TableIndex].Flags |=
810193267Sjkim                ACPI_TABLE_IS_LOADED;
811167802Sjkim        }
812167802Sjkim        else
813167802Sjkim        {
814193267Sjkim            AcpiGbl_RootTableList.Tables[TableIndex].Flags &=
815193267Sjkim                ~ACPI_TABLE_IS_LOADED;
816167802Sjkim        }
817167802Sjkim    }
81867754Smsmith
819167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
82067754Smsmith}
821