tbinstal.c revision 250838
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",
163250838Sjkim            AcpiUtValidAcpiName (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:
517250838Sjkim
518167802Sjkim        AcpiOsUnmapMemory (TableDesc->Pointer, TableDesc->Length);
519167802Sjkim        break;
52067754Smsmith
521167802Sjkim    case ACPI_TABLE_ORIGIN_ALLOCATED:
522250838Sjkim
523167802Sjkim        ACPI_FREE (TableDesc->Pointer);
524167802Sjkim        break;
52567754Smsmith
526233250Sjkim    /* Not mapped or allocated, there is nothing we can do */
527233250Sjkim
528167802Sjkim    default:
529250838Sjkim
530233250Sjkim        return;
53167754Smsmith    }
53267754Smsmith
533167802Sjkim    TableDesc->Pointer = NULL;
53467754Smsmith}
53567754Smsmith
53667754Smsmith
53767754Smsmith/*******************************************************************************
53867754Smsmith *
539167802Sjkim * FUNCTION:    AcpiTbTerminate
54067754Smsmith *
541167802Sjkim * PARAMETERS:  None
54267754Smsmith *
543167802Sjkim * RETURN:      None
54467754Smsmith *
54567754Smsmith * DESCRIPTION: Delete all internal ACPI tables
54667754Smsmith *
54767754Smsmith ******************************************************************************/
54867754Smsmith
54967754Smsmithvoid
550167802SjkimAcpiTbTerminate (
551151937Sjkim    void)
55267754Smsmith{
553193267Sjkim    UINT32                  i;
55467754Smsmith
55567754Smsmith
556167802Sjkim    ACPI_FUNCTION_TRACE (TbTerminate);
557167802Sjkim
558167802Sjkim
559167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
560167802Sjkim
561167802Sjkim    /* Delete the individual tables */
562167802Sjkim
563207344Sjkim    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
564167802Sjkim    {
565167802Sjkim        AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[i]);
566167802Sjkim    }
567167802Sjkim
56867754Smsmith    /*
569167802Sjkim     * Delete the root table array if allocated locally. Array cannot be
570167802Sjkim     * mapped, so we don't need to check for that flag.
57167754Smsmith     */
572167802Sjkim    if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
57367754Smsmith    {
574167802Sjkim        ACPI_FREE (AcpiGbl_RootTableList.Tables);
57567754Smsmith    }
576167802Sjkim
577167802Sjkim    AcpiGbl_RootTableList.Tables = NULL;
578167802Sjkim    AcpiGbl_RootTableList.Flags = 0;
579207344Sjkim    AcpiGbl_RootTableList.CurrentTableCount = 0;
580167802Sjkim
581167802Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
582167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
583241973Sjkim
584241973Sjkim    return_VOID;
58567754Smsmith}
58667754Smsmith
58767754Smsmith
58867754Smsmith/*******************************************************************************
58967754Smsmith *
590167802Sjkim * FUNCTION:    AcpiTbDeleteNamespaceByOwner
59167754Smsmith *
592167802Sjkim * PARAMETERS:  TableIndex          - Table index
59367754Smsmith *
594193267Sjkim * RETURN:      Status
59567754Smsmith *
596167802Sjkim * DESCRIPTION: Delete all namespace objects created when this table was loaded.
59767754Smsmith *
59867754Smsmith ******************************************************************************/
59967754Smsmith
600193267SjkimACPI_STATUS
601167802SjkimAcpiTbDeleteNamespaceByOwner (
602193267Sjkim    UINT32                  TableIndex)
60367754Smsmith{
604167802Sjkim    ACPI_OWNER_ID           OwnerId;
605193267Sjkim    ACPI_STATUS             Status;
60667754Smsmith
60767754Smsmith
608193267Sjkim    ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner);
609193267Sjkim
610193267Sjkim
611193267Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES);
612193267Sjkim    if (ACPI_FAILURE (Status))
61367754Smsmith    {
614193267Sjkim        return_ACPI_STATUS (Status);
61567754Smsmith    }
616193267Sjkim
617207344Sjkim    if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
61891116Smsmith    {
619193267Sjkim        /* The table index does not exist */
620193267Sjkim
621167802Sjkim        (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
622193267Sjkim        return_ACPI_STATUS (AE_NOT_EXIST);
62391116Smsmith    }
62467754Smsmith
625193267Sjkim    /* Get the owner ID for this table, used to delete namespace nodes */
626193267Sjkim
627193267Sjkim    OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
628167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
629193267Sjkim
630193267Sjkim    /*
631193267Sjkim     * Need to acquire the namespace writer lock to prevent interference
632193267Sjkim     * with any concurrent namespace walks. The interpreter must be
633193267Sjkim     * released during the deletion since the acquisition of the deletion
634193267Sjkim     * lock may block, and also since the execution of a namespace walk
635193267Sjkim     * must be allowed to use the interpreter.
636193267Sjkim     */
637193267Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
638193267Sjkim    Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock);
639193267Sjkim
640167802Sjkim    AcpiNsDeleteNamespaceByOwner (OwnerId);
641193267Sjkim    if (ACPI_FAILURE (Status))
642193267Sjkim    {
643193267Sjkim        return_ACPI_STATUS (Status);
644193267Sjkim    }
645193267Sjkim
646193267Sjkim    AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock);
647193267Sjkim
648193267Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
649193267Sjkim    return_ACPI_STATUS (Status);
650167802Sjkim}
65167754Smsmith
65267754Smsmith
653167802Sjkim/*******************************************************************************
654167802Sjkim *
655167802Sjkim * FUNCTION:    AcpiTbAllocateOwnerId
656167802Sjkim *
657167802Sjkim * PARAMETERS:  TableIndex          - Table index
658167802Sjkim *
659167802Sjkim * RETURN:      Status
660167802Sjkim *
661167802Sjkim * DESCRIPTION: Allocates OwnerId in TableDesc
662167802Sjkim *
663167802Sjkim ******************************************************************************/
66467754Smsmith
665167802SjkimACPI_STATUS
666167802SjkimAcpiTbAllocateOwnerId (
667193267Sjkim    UINT32                  TableIndex)
668167802Sjkim{
669167802Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
67067754Smsmith
67167754Smsmith
672167802Sjkim    ACPI_FUNCTION_TRACE (TbAllocateOwnerId);
67367754Smsmith
67467754Smsmith
675167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
676207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
67767754Smsmith    {
678167802Sjkim        Status = AcpiUtAllocateOwnerId
679167802Sjkim                    (&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
68067754Smsmith    }
68167754Smsmith
682117521Snjl    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
683167802Sjkim    return_ACPI_STATUS (Status);
68467754Smsmith}
68567754Smsmith
68667754Smsmith
68767754Smsmith/*******************************************************************************
68867754Smsmith *
689167802Sjkim * FUNCTION:    AcpiTbReleaseOwnerId
69067754Smsmith *
691167802Sjkim * PARAMETERS:  TableIndex          - Table index
69267754Smsmith *
693167802Sjkim * RETURN:      Status
69467754Smsmith *
695167802Sjkim * DESCRIPTION: Releases OwnerId in TableDesc
69667754Smsmith *
69767754Smsmith ******************************************************************************/
69867754Smsmith
699167802SjkimACPI_STATUS
700167802SjkimAcpiTbReleaseOwnerId (
701193267Sjkim    UINT32                  TableIndex)
70267754Smsmith{
703167802Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
70467754Smsmith
705117521Snjl
706167802Sjkim    ACPI_FUNCTION_TRACE (TbReleaseOwnerId);
70767754Smsmith
708117521Snjl
709167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
710207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
71167754Smsmith    {
712193267Sjkim        AcpiUtReleaseOwnerId (
713193267Sjkim            &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
714167802Sjkim        Status = AE_OK;
715167802Sjkim    }
71667754Smsmith
717167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
718167802Sjkim    return_ACPI_STATUS (Status);
71967754Smsmith}
72067754Smsmith
72167754Smsmith
72267754Smsmith/*******************************************************************************
72367754Smsmith *
724167802Sjkim * FUNCTION:    AcpiTbGetOwnerId
72567754Smsmith *
726167802Sjkim * PARAMETERS:  TableIndex          - Table index
727167802Sjkim *              OwnerId             - Where the table OwnerId is returned
72867754Smsmith *
729167802Sjkim * RETURN:      Status
73067754Smsmith *
731167802Sjkim * DESCRIPTION: returns OwnerId for the ACPI table
73267754Smsmith *
73367754Smsmith ******************************************************************************/
73467754Smsmith
735167802SjkimACPI_STATUS
736167802SjkimAcpiTbGetOwnerId (
737193267Sjkim    UINT32                  TableIndex,
738167802Sjkim    ACPI_OWNER_ID           *OwnerId)
73967754Smsmith{
740167802Sjkim    ACPI_STATUS             Status = AE_BAD_PARAMETER;
74167754Smsmith
74267754Smsmith
743167802Sjkim    ACPI_FUNCTION_TRACE (TbGetOwnerId);
74467754Smsmith
74567754Smsmith
746167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
747207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
74867754Smsmith    {
749167802Sjkim        *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
750167802Sjkim        Status = AE_OK;
75167754Smsmith    }
75267754Smsmith
753167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
754167802Sjkim    return_ACPI_STATUS (Status);
755167802Sjkim}
75667754Smsmith
75767754Smsmith
758167802Sjkim/*******************************************************************************
759167802Sjkim *
760167802Sjkim * FUNCTION:    AcpiTbIsTableLoaded
761167802Sjkim *
762167802Sjkim * PARAMETERS:  TableIndex          - Table index
763167802Sjkim *
764167802Sjkim * RETURN:      Table Loaded Flag
765167802Sjkim *
766167802Sjkim ******************************************************************************/
767117521Snjl
768167802SjkimBOOLEAN
769167802SjkimAcpiTbIsTableLoaded (
770193267Sjkim    UINT32                  TableIndex)
771167802Sjkim{
772167802Sjkim    BOOLEAN                 IsLoaded = FALSE;
773167802Sjkim
774167802Sjkim
775167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
776207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
77767754Smsmith    {
778167802Sjkim        IsLoaded = (BOOLEAN)
779193267Sjkim            (AcpiGbl_RootTableList.Tables[TableIndex].Flags &
780193267Sjkim            ACPI_TABLE_IS_LOADED);
78167754Smsmith    }
78267754Smsmith
783167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
784167802Sjkim    return (IsLoaded);
785167802Sjkim}
78667754Smsmith
78767754Smsmith
788167802Sjkim/*******************************************************************************
789167802Sjkim *
790167802Sjkim * FUNCTION:    AcpiTbSetTableLoadedFlag
791167802Sjkim *
792167802Sjkim * PARAMETERS:  TableIndex          - Table index
793167802Sjkim *              IsLoaded            - TRUE if table is loaded, FALSE otherwise
794167802Sjkim *
795167802Sjkim * RETURN:      None
796167802Sjkim *
797167802Sjkim * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
798167802Sjkim *
799167802Sjkim ******************************************************************************/
80067754Smsmith
801167802Sjkimvoid
802167802SjkimAcpiTbSetTableLoadedFlag (
803193267Sjkim    UINT32                  TableIndex,
804167802Sjkim    BOOLEAN                 IsLoaded)
805167802Sjkim{
80667754Smsmith
807167802Sjkim    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
808207344Sjkim    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
809167802Sjkim    {
810167802Sjkim        if (IsLoaded)
811167802Sjkim        {
812193267Sjkim            AcpiGbl_RootTableList.Tables[TableIndex].Flags |=
813193267Sjkim                ACPI_TABLE_IS_LOADED;
814167802Sjkim        }
815167802Sjkim        else
816167802Sjkim        {
817193267Sjkim            AcpiGbl_RootTableList.Tables[TableIndex].Flags &=
818193267Sjkim                ~ACPI_TABLE_IS_LOADED;
819167802Sjkim        }
820167802Sjkim    }
82167754Smsmith
822167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
82367754Smsmith}
824