tbdata.c revision 1.15
1/******************************************************************************
2 *
3 * Module Name: tbdata - Table manager data structure functions
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2020, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include "acpi.h"
45#include "accommon.h"
46#include "acnamesp.h"
47#include "actables.h"
48#include "acevents.h"
49
50#define _COMPONENT          ACPI_TABLES
51        ACPI_MODULE_NAME    ("tbdata")
52
53/* Local prototypes */
54
55static ACPI_STATUS
56AcpiTbCheckDuplication (
57    ACPI_TABLE_DESC         *TableDesc,
58    UINT32                  *TableIndex);
59
60static BOOLEAN
61AcpiTbCompareTables (
62    ACPI_TABLE_DESC         *TableDesc,
63    UINT32                  TableIndex);
64
65
66/*******************************************************************************
67 *
68 * FUNCTION:    AcpiTbCompareTables
69 *
70 * PARAMETERS:  TableDesc           - Table 1 descriptor to be compared
71 *              TableIndex          - Index of table 2 to be compared
72 *
73 * RETURN:      TRUE if both tables are identical.
74 *
75 * DESCRIPTION: This function compares a table with another table that has
76 *              already been installed in the root table list.
77 *
78 ******************************************************************************/
79
80static BOOLEAN
81AcpiTbCompareTables (
82    ACPI_TABLE_DESC         *TableDesc,
83    UINT32                  TableIndex)
84{
85    ACPI_STATUS             Status = AE_OK;
86    BOOLEAN                 IsIdentical;
87    ACPI_TABLE_HEADER       *Table;
88    UINT32                  TableLength;
89    UINT8                   TableFlags;
90
91
92    Status = AcpiTbAcquireTable (&AcpiGbl_RootTableList.Tables[TableIndex],
93        &Table, &TableLength, &TableFlags);
94    if (ACPI_FAILURE (Status))
95    {
96        return (FALSE);
97    }
98
99    /*
100     * Check for a table match on the entire table length,
101     * not just the header.
102     */
103    IsIdentical = (BOOLEAN)((TableDesc->Length != TableLength ||
104        memcmp (TableDesc->Pointer, Table, TableLength)) ?
105        FALSE : TRUE);
106
107    /* Release the acquired table */
108
109    AcpiTbReleaseTable (Table, TableLength, TableFlags);
110    return (IsIdentical);
111}
112
113
114/*******************************************************************************
115 *
116 * FUNCTION:    AcpiTbInitTableDescriptor
117 *
118 * PARAMETERS:  TableDesc               - Table descriptor
119 *              Address                 - Physical address of the table
120 *              Flags                   - Allocation flags of the table
121 *              Table                   - Pointer to the table
122 *
123 * RETURN:      None
124 *
125 * DESCRIPTION: Initialize a new table descriptor
126 *
127 ******************************************************************************/
128
129void
130AcpiTbInitTableDescriptor (
131    ACPI_TABLE_DESC         *TableDesc,
132    ACPI_PHYSICAL_ADDRESS   Address,
133    UINT8                   Flags,
134    ACPI_TABLE_HEADER       *Table)
135{
136
137    /*
138     * Initialize the table descriptor. Set the pointer to NULL, since the
139     * table is not fully mapped at this time.
140     */
141    memset (TableDesc, 0, sizeof (ACPI_TABLE_DESC));
142    TableDesc->Address = Address;
143    TableDesc->Length = Table->Length;
144    TableDesc->Flags = Flags;
145    ACPI_MOVE_32_TO_32 (TableDesc->Signature.Ascii, Table->Signature);
146}
147
148
149/*******************************************************************************
150 *
151 * FUNCTION:    AcpiTbAcquireTable
152 *
153 * PARAMETERS:  TableDesc           - Table descriptor
154 *              TablePtr            - Where table is returned
155 *              TableLength         - Where table length is returned
156 *              TableFlags          - Where table allocation flags are returned
157 *
158 * RETURN:      Status
159 *
160 * DESCRIPTION: Acquire an ACPI table. It can be used for tables not
161 *              maintained in the AcpiGbl_RootTableList.
162 *
163 ******************************************************************************/
164
165ACPI_STATUS
166AcpiTbAcquireTable (
167    ACPI_TABLE_DESC         *TableDesc,
168    ACPI_TABLE_HEADER       **TablePtr,
169    UINT32                  *TableLength,
170    UINT8                   *TableFlags)
171{
172    ACPI_TABLE_HEADER       *Table = NULL;
173
174
175    switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK)
176    {
177    case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
178
179        Table = AcpiOsMapMemory (TableDesc->Address, TableDesc->Length);
180        break;
181
182    case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
183    case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
184
185        Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER,
186            ACPI_PHYSADDR_TO_PTR (TableDesc->Address));
187        break;
188
189    default:
190
191        break;
192    }
193
194    /* Table is not valid yet */
195
196    if (!Table)
197    {
198        return (AE_NO_MEMORY);
199    }
200
201    /* Fill the return values */
202
203    *TablePtr = Table;
204    *TableLength = TableDesc->Length;
205    *TableFlags = TableDesc->Flags;
206    return (AE_OK);
207}
208
209
210/*******************************************************************************
211 *
212 * FUNCTION:    AcpiTbReleaseTable
213 *
214 * PARAMETERS:  Table               - Pointer for the table
215 *              TableLength         - Length for the table
216 *              TableFlags          - Allocation flags for the table
217 *
218 * RETURN:      None
219 *
220 * DESCRIPTION: Release a table. The inverse of AcpiTbAcquireTable().
221 *
222 ******************************************************************************/
223
224void
225AcpiTbReleaseTable (
226    ACPI_TABLE_HEADER       *Table,
227    UINT32                  TableLength,
228    UINT8                   TableFlags)
229{
230
231    switch (TableFlags & ACPI_TABLE_ORIGIN_MASK)
232    {
233    case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
234
235        AcpiOsUnmapMemory (Table, TableLength);
236        break;
237
238    case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
239    case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
240    default:
241
242        break;
243    }
244}
245
246
247/*******************************************************************************
248 *
249 * FUNCTION:    AcpiTbAcquireTempTable
250 *
251 * PARAMETERS:  TableDesc           - Table descriptor to be acquired
252 *              Address             - Address of the table
253 *              Flags               - Allocation flags of the table
254 *
255 * RETURN:      Status
256 *
257 * DESCRIPTION: This function validates the table header to obtain the length
258 *              of a table and fills the table descriptor to make its state as
259 *              "INSTALLED". Such a table descriptor is only used for verified
260 *              installation.
261 *
262 ******************************************************************************/
263
264ACPI_STATUS
265AcpiTbAcquireTempTable (
266    ACPI_TABLE_DESC         *TableDesc,
267    ACPI_PHYSICAL_ADDRESS   Address,
268    UINT8                   Flags)
269{
270    ACPI_TABLE_HEADER       *TableHeader;
271
272
273    switch (Flags & ACPI_TABLE_ORIGIN_MASK)
274    {
275    case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL:
276
277        /* Get the length of the full table from the header */
278
279        TableHeader = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
280        if (!TableHeader)
281        {
282            return (AE_NO_MEMORY);
283        }
284
285        AcpiTbInitTableDescriptor (TableDesc, Address, Flags, TableHeader);
286        AcpiOsUnmapMemory (TableHeader, sizeof (ACPI_TABLE_HEADER));
287        return (AE_OK);
288
289    case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL:
290    case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL:
291
292        TableHeader = ACPI_CAST_PTR (ACPI_TABLE_HEADER,
293            ACPI_PHYSADDR_TO_PTR (Address));
294        if (!TableHeader)
295        {
296            return (AE_NO_MEMORY);
297        }
298
299        AcpiTbInitTableDescriptor (TableDesc, Address, Flags, TableHeader);
300        return (AE_OK);
301
302    default:
303
304        break;
305    }
306
307    /* Table is not valid yet */
308
309    return (AE_NO_MEMORY);
310}
311
312
313/*******************************************************************************
314 *
315 * FUNCTION:    AcpiTbReleaseTempTable
316 *
317 * PARAMETERS:  TableDesc           - Table descriptor to be released
318 *
319 * RETURN:      Status
320 *
321 * DESCRIPTION: The inverse of AcpiTbAcquireTempTable().
322 *
323 *****************************************************************************/
324
325void
326AcpiTbReleaseTempTable (
327    ACPI_TABLE_DESC         *TableDesc)
328{
329
330    /*
331     * Note that the .Address is maintained by the callers of
332     * AcpiTbAcquireTempTable(), thus do not invoke AcpiTbUninstallTable()
333     * where .Address will be freed.
334     */
335    AcpiTbInvalidateTable (TableDesc);
336}
337
338
339/******************************************************************************
340 *
341 * FUNCTION:    AcpiTbValidateTable
342 *
343 * PARAMETERS:  TableDesc           - Table descriptor
344 *
345 * RETURN:      Status
346 *
347 * DESCRIPTION: This function is called to validate the table, the returned
348 *              table descriptor is in "VALIDATED" state.
349 *
350 *****************************************************************************/
351
352ACPI_STATUS
353AcpiTbValidateTable (
354    ACPI_TABLE_DESC         *TableDesc)
355{
356    ACPI_STATUS             Status = AE_OK;
357
358
359    ACPI_FUNCTION_TRACE (TbValidateTable);
360
361
362    /* Validate the table if necessary */
363
364    if (!TableDesc->Pointer)
365    {
366        Status = AcpiTbAcquireTable (TableDesc, &TableDesc->Pointer,
367            &TableDesc->Length, &TableDesc->Flags);
368        if (!TableDesc->Pointer)
369        {
370            Status = AE_NO_MEMORY;
371        }
372    }
373
374    return_ACPI_STATUS (Status);
375}
376
377
378/*******************************************************************************
379 *
380 * FUNCTION:    AcpiTbInvalidateTable
381 *
382 * PARAMETERS:  TableDesc           - Table descriptor
383 *
384 * RETURN:      None
385 *
386 * DESCRIPTION: Invalidate one internal ACPI table, this is the inverse of
387 *              AcpiTbValidateTable().
388 *
389 ******************************************************************************/
390
391void
392AcpiTbInvalidateTable (
393    ACPI_TABLE_DESC         *TableDesc)
394{
395
396    ACPI_FUNCTION_TRACE (TbInvalidateTable);
397
398
399    /* Table must be validated */
400
401    if (!TableDesc->Pointer)
402    {
403        return_VOID;
404    }
405
406    AcpiTbReleaseTable (TableDesc->Pointer, TableDesc->Length,
407        TableDesc->Flags);
408    TableDesc->Pointer = NULL;
409
410    return_VOID;
411}
412
413
414/******************************************************************************
415 *
416 * FUNCTION:    AcpiTbValidateTempTable
417 *
418 * PARAMETERS:  TableDesc           - Table descriptor
419 *
420 * RETURN:      Status
421 *
422 * DESCRIPTION: This function is called to validate the table, the returned
423 *              table descriptor is in "VALIDATED" state.
424 *
425 *****************************************************************************/
426
427ACPI_STATUS
428AcpiTbValidateTempTable (
429    ACPI_TABLE_DESC         *TableDesc)
430{
431
432    if (!TableDesc->Pointer && !AcpiGbl_EnableTableValidation)
433    {
434        /*
435         * Only validates the header of the table.
436         * Note that Length contains the size of the mapping after invoking
437         * this work around, this value is required by
438         * AcpiTbReleaseTempTable().
439         * We can do this because in AcpiInitTableDescriptor(), the Length
440         * field of the installed descriptor is filled with the actual
441         * table length obtaining from the table header.
442         */
443        TableDesc->Length = sizeof (ACPI_TABLE_HEADER);
444    }
445
446    return (AcpiTbValidateTable (TableDesc));
447}
448
449
450/*******************************************************************************
451 *
452 * FUNCTION:    AcpiTbCheckDuplication
453 *
454 * PARAMETERS:  TableDesc           - Table descriptor
455 *              TableIndex          - Where the table index is returned
456 *
457 * RETURN:      Status
458 *
459 * DESCRIPTION: Avoid installing duplicated tables. However table override and
460 *              user aided dynamic table load is allowed, thus comparing the
461 *              address of the table is not sufficient, and checking the entire
462 *              table content is required.
463 *
464 ******************************************************************************/
465
466static ACPI_STATUS
467AcpiTbCheckDuplication (
468    ACPI_TABLE_DESC         *TableDesc,
469    UINT32                  *TableIndex)
470{
471    UINT32                  i;
472
473
474    ACPI_FUNCTION_TRACE (TbCheckDuplication);
475
476
477    /* Check if table is already registered */
478
479    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
480    {
481        /* Do not compare with unverified tables */
482
483        if (!(AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_VERIFIED))
484        {
485            continue;
486        }
487
488        /*
489         * Check for a table match on the entire table length,
490         * not just the header.
491         */
492        if (!AcpiTbCompareTables (TableDesc, i))
493        {
494            continue;
495        }
496
497        /*
498         * Note: the current mechanism does not unregister a table if it is
499         * dynamically unloaded. The related namespace entries are deleted,
500         * but the table remains in the root table list.
501         *
502         * The assumption here is that the number of different tables that
503         * will be loaded is actually small, and there is minimal overhead
504         * in just keeping the table in case it is needed again.
505         *
506         * If this assumption changes in the future (perhaps on large
507         * machines with many table load/unload operations), tables will
508         * need to be unregistered when they are unloaded, and slots in the
509         * root table list should be reused when empty.
510         */
511        if (AcpiGbl_RootTableList.Tables[i].Flags &
512            ACPI_TABLE_IS_LOADED)
513        {
514            /* Table is still loaded, this is an error */
515
516            return_ACPI_STATUS (AE_ALREADY_EXISTS);
517        }
518        else
519        {
520            *TableIndex = i;
521            return_ACPI_STATUS (AE_CTRL_TERMINATE);
522        }
523    }
524
525    /* Indicate no duplication to the caller */
526
527    return_ACPI_STATUS (AE_OK);
528}
529
530
531/******************************************************************************
532 *
533 * FUNCTION:    AcpiTbVerifyTempTable
534 *
535 * PARAMETERS:  TableDesc           - Table descriptor
536 *              Signature           - Table signature to verify
537 *              TableIndex          - Where the table index is returned
538 *
539 * RETURN:      Status
540 *
541 * DESCRIPTION: This function is called to validate and verify the table, the
542 *              returned table descriptor is in "VALIDATED" state.
543 *              Note that 'TableIndex' is required to be set to !NULL to
544 *              enable duplication check.
545 *
546 *****************************************************************************/
547
548ACPI_STATUS
549AcpiTbVerifyTempTable (
550    ACPI_TABLE_DESC         *TableDesc,
551    const char              *Signature,
552    UINT32                  *TableIndex)
553{
554    ACPI_STATUS             Status = AE_OK;
555
556
557    ACPI_FUNCTION_TRACE (TbVerifyTempTable);
558
559
560    /* Validate the table */
561
562    Status = AcpiTbValidateTempTable (TableDesc);
563    if (ACPI_FAILURE (Status))
564    {
565        return_ACPI_STATUS (AE_NO_MEMORY);
566    }
567
568    /* If a particular signature is expected (DSDT/FACS), it must match */
569
570    if (Signature &&
571        !ACPI_COMPARE_NAMESEG (&TableDesc->Signature, Signature))
572    {
573        ACPI_BIOS_ERROR ((AE_INFO,
574            "Invalid signature 0x%X for ACPI table, expected [%s]",
575            TableDesc->Signature.Integer, Signature));
576        Status = AE_BAD_SIGNATURE;
577        goto InvalidateAndExit;
578    }
579
580    if (AcpiGbl_EnableTableValidation)
581    {
582        /* Verify the checksum */
583
584        Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length);
585        if (ACPI_FAILURE (Status))
586        {
587            ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
588                "%4.4s 0x%8.8X%8.8X"
589                " Attempted table install failed",
590                AcpiUtValidNameseg (TableDesc->Signature.Ascii) ?
591                    TableDesc->Signature.Ascii : "????",
592                ACPI_FORMAT_UINT64 (TableDesc->Address)));
593
594            goto InvalidateAndExit;
595        }
596
597        /* Avoid duplications */
598
599        if (TableIndex)
600        {
601            Status = AcpiTbCheckDuplication (TableDesc, TableIndex);
602            if (ACPI_FAILURE (Status))
603            {
604                if (Status != AE_CTRL_TERMINATE)
605                {
606                    ACPI_EXCEPTION ((AE_INFO, Status,
607                        "%4.4s 0x%8.8X%8.8X"
608                        " Table is already loaded",
609                        AcpiUtValidNameseg (TableDesc->Signature.Ascii) ?
610                            TableDesc->Signature.Ascii : "????",
611                        ACPI_FORMAT_UINT64 (TableDesc->Address)));
612                }
613
614                goto InvalidateAndExit;
615            }
616        }
617
618        TableDesc->Flags |= ACPI_TABLE_IS_VERIFIED;
619    }
620
621    return_ACPI_STATUS (Status);
622
623InvalidateAndExit:
624    AcpiTbInvalidateTable (TableDesc);
625    return_ACPI_STATUS (Status);
626}
627
628
629/*******************************************************************************
630 *
631 * FUNCTION:    AcpiTbResizeRootTableList
632 *
633 * PARAMETERS:  None
634 *
635 * RETURN:      Status
636 *
637 * DESCRIPTION: Expand the size of global table array
638 *
639 ******************************************************************************/
640
641ACPI_STATUS
642AcpiTbResizeRootTableList (
643    void)
644{
645    ACPI_TABLE_DESC         *Tables;
646    UINT32                  TableCount;
647    UINT32                  CurrentTableCount, MaxTableCount;
648    UINT32                  i;
649
650
651    ACPI_FUNCTION_TRACE (TbResizeRootTableList);
652
653
654    /* AllowResize flag is a parameter to AcpiInitializeTables */
655
656    if (!(AcpiGbl_RootTableList.Flags & ACPI_ROOT_ALLOW_RESIZE))
657    {
658        ACPI_ERROR ((AE_INFO, "Resize of Root Table Array is not allowed"));
659        return_ACPI_STATUS (AE_SUPPORT);
660    }
661
662    /* Increase the Table Array size */
663
664    if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
665    {
666        TableCount = AcpiGbl_RootTableList.MaxTableCount;
667    }
668    else
669    {
670        TableCount = AcpiGbl_RootTableList.CurrentTableCount;
671    }
672
673    MaxTableCount = TableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT;
674    Tables = ACPI_ALLOCATE_ZEROED (
675        ((ACPI_SIZE) MaxTableCount) * sizeof (ACPI_TABLE_DESC));
676    if (!Tables)
677    {
678        ACPI_ERROR ((AE_INFO, "Could not allocate new root table array"));
679        return_ACPI_STATUS (AE_NO_MEMORY);
680    }
681
682    /* Copy and free the previous table array */
683
684    CurrentTableCount = 0;
685    if (AcpiGbl_RootTableList.Tables)
686    {
687        for (i = 0; i < TableCount; i++)
688        {
689            if (AcpiGbl_RootTableList.Tables[i].Address)
690            {
691                memcpy (Tables + CurrentTableCount,
692                    AcpiGbl_RootTableList.Tables + i,
693                    sizeof (ACPI_TABLE_DESC));
694                CurrentTableCount++;
695            }
696        }
697
698        if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
699        {
700            ACPI_FREE (AcpiGbl_RootTableList.Tables);
701        }
702    }
703
704    AcpiGbl_RootTableList.Tables = Tables;
705    AcpiGbl_RootTableList.MaxTableCount = MaxTableCount;
706    AcpiGbl_RootTableList.CurrentTableCount = CurrentTableCount;
707    AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
708
709    return_ACPI_STATUS (AE_OK);
710}
711
712
713/*******************************************************************************
714 *
715 * FUNCTION:    AcpiTbGetNextTableDescriptor
716 *
717 * PARAMETERS:  TableIndex          - Where table index is returned
718 *              TableDesc           - Where table descriptor is returned
719 *
720 * RETURN:      Status and table index/descriptor.
721 *
722 * DESCRIPTION: Allocate a new ACPI table entry to the global table list
723 *
724 ******************************************************************************/
725
726ACPI_STATUS
727AcpiTbGetNextTableDescriptor (
728    UINT32                  *TableIndex,
729    ACPI_TABLE_DESC         **TableDesc)
730{
731    ACPI_STATUS             Status;
732    UINT32                  i;
733
734
735    /* Ensure that there is room for the table in the Root Table List */
736
737    if (AcpiGbl_RootTableList.CurrentTableCount >=
738        AcpiGbl_RootTableList.MaxTableCount)
739    {
740        Status = AcpiTbResizeRootTableList();
741        if (ACPI_FAILURE (Status))
742        {
743            return (Status);
744        }
745    }
746
747    i = AcpiGbl_RootTableList.CurrentTableCount;
748    AcpiGbl_RootTableList.CurrentTableCount++;
749
750    if (TableIndex)
751    {
752        *TableIndex = i;
753    }
754    if (TableDesc)
755    {
756        *TableDesc = &AcpiGbl_RootTableList.Tables[i];
757    }
758
759    return (AE_OK);
760}
761
762
763/*******************************************************************************
764 *
765 * FUNCTION:    AcpiTbTerminate
766 *
767 * PARAMETERS:  None
768 *
769 * RETURN:      None
770 *
771 * DESCRIPTION: Delete all internal ACPI tables
772 *
773 ******************************************************************************/
774
775void
776AcpiTbTerminate (
777    void)
778{
779    UINT32                  i;
780
781
782    ACPI_FUNCTION_TRACE (TbTerminate);
783
784
785    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
786
787    /* Delete the individual tables */
788
789    for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
790    {
791        AcpiTbUninstallTable (&AcpiGbl_RootTableList.Tables[i]);
792    }
793
794    /*
795     * Delete the root table array if allocated locally. Array cannot be
796     * mapped, so we don't need to check for that flag.
797     */
798    if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
799    {
800        ACPI_FREE (AcpiGbl_RootTableList.Tables);
801    }
802
803    AcpiGbl_RootTableList.Tables = NULL;
804    AcpiGbl_RootTableList.Flags = 0;
805    AcpiGbl_RootTableList.CurrentTableCount = 0;
806
807    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
808
809    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
810    return_VOID;
811}
812
813
814/*******************************************************************************
815 *
816 * FUNCTION:    AcpiTbDeleteNamespaceByOwner
817 *
818 * PARAMETERS:  TableIndex          - Table index
819 *
820 * RETURN:      Status
821 *
822 * DESCRIPTION: Delete all namespace objects created when this table was loaded.
823 *
824 ******************************************************************************/
825
826ACPI_STATUS
827AcpiTbDeleteNamespaceByOwner (
828    UINT32                  TableIndex)
829{
830    ACPI_OWNER_ID           OwnerId;
831    ACPI_STATUS             Status;
832
833
834    ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner);
835
836
837    Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES);
838    if (ACPI_FAILURE (Status))
839    {
840        return_ACPI_STATUS (Status);
841    }
842
843    if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
844    {
845        /* The table index does not exist */
846
847        (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
848        return_ACPI_STATUS (AE_NOT_EXIST);
849    }
850
851    /* Get the owner ID for this table, used to delete namespace nodes */
852
853    OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
854    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
855
856    /*
857     * Need to acquire the namespace writer lock to prevent interference
858     * with any concurrent namespace walks. The interpreter must be
859     * released during the deletion since the acquisition of the deletion
860     * lock may block, and also since the execution of a namespace walk
861     * must be allowed to use the interpreter.
862     */
863    Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock);
864    if (ACPI_FAILURE (Status))
865    {
866        return_ACPI_STATUS (Status);
867    }
868
869    AcpiNsDeleteNamespaceByOwner (OwnerId);
870    AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock);
871    return_ACPI_STATUS (Status);
872}
873
874
875/*******************************************************************************
876 *
877 * FUNCTION:    AcpiTbAllocateOwnerId
878 *
879 * PARAMETERS:  TableIndex          - Table index
880 *
881 * RETURN:      Status
882 *
883 * DESCRIPTION: Allocates OwnerId in TableDesc
884 *
885 ******************************************************************************/
886
887ACPI_STATUS
888AcpiTbAllocateOwnerId (
889    UINT32                  TableIndex)
890{
891    ACPI_STATUS             Status = AE_BAD_PARAMETER;
892
893
894    ACPI_FUNCTION_TRACE (TbAllocateOwnerId);
895
896
897    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
898    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
899    {
900        Status = AcpiUtAllocateOwnerId (
901            &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
902    }
903
904    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
905    return_ACPI_STATUS (Status);
906}
907
908
909/*******************************************************************************
910 *
911 * FUNCTION:    AcpiTbReleaseOwnerId
912 *
913 * PARAMETERS:  TableIndex          - Table index
914 *
915 * RETURN:      Status
916 *
917 * DESCRIPTION: Releases OwnerId in TableDesc
918 *
919 ******************************************************************************/
920
921ACPI_STATUS
922AcpiTbReleaseOwnerId (
923    UINT32                  TableIndex)
924{
925    ACPI_STATUS             Status = AE_BAD_PARAMETER;
926
927
928    ACPI_FUNCTION_TRACE (TbReleaseOwnerId);
929
930
931    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
932    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
933    {
934        AcpiUtReleaseOwnerId (
935            &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
936        Status = AE_OK;
937    }
938
939    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
940    return_ACPI_STATUS (Status);
941}
942
943
944/*******************************************************************************
945 *
946 * FUNCTION:    AcpiTbGetOwnerId
947 *
948 * PARAMETERS:  TableIndex          - Table index
949 *              OwnerId             - Where the table OwnerId is returned
950 *
951 * RETURN:      Status
952 *
953 * DESCRIPTION: returns OwnerId for the ACPI table
954 *
955 ******************************************************************************/
956
957ACPI_STATUS
958AcpiTbGetOwnerId (
959    UINT32                  TableIndex,
960    ACPI_OWNER_ID           *OwnerId)
961{
962    ACPI_STATUS             Status = AE_BAD_PARAMETER;
963
964
965    ACPI_FUNCTION_TRACE (TbGetOwnerId);
966
967
968    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
969    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
970    {
971        *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
972        Status = AE_OK;
973    }
974
975    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
976    return_ACPI_STATUS (Status);
977}
978
979
980/*******************************************************************************
981 *
982 * FUNCTION:    AcpiTbIsTableLoaded
983 *
984 * PARAMETERS:  TableIndex          - Index into the root table
985 *
986 * RETURN:      Table Loaded Flag
987 *
988 ******************************************************************************/
989
990BOOLEAN
991AcpiTbIsTableLoaded (
992    UINT32                  TableIndex)
993{
994    BOOLEAN                 IsLoaded = FALSE;
995
996
997    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
998    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
999    {
1000        IsLoaded = (BOOLEAN)
1001            (AcpiGbl_RootTableList.Tables[TableIndex].Flags &
1002            ACPI_TABLE_IS_LOADED);
1003    }
1004
1005    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
1006    return (IsLoaded);
1007}
1008
1009
1010/*******************************************************************************
1011 *
1012 * FUNCTION:    AcpiTbSetTableLoadedFlag
1013 *
1014 * PARAMETERS:  TableIndex          - Table index
1015 *              IsLoaded            - TRUE if table is loaded, FALSE otherwise
1016 *
1017 * RETURN:      None
1018 *
1019 * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
1020 *
1021 ******************************************************************************/
1022
1023void
1024AcpiTbSetTableLoadedFlag (
1025    UINT32                  TableIndex,
1026    BOOLEAN                 IsLoaded)
1027{
1028
1029    (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
1030    if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
1031    {
1032        if (IsLoaded)
1033        {
1034            AcpiGbl_RootTableList.Tables[TableIndex].Flags |=
1035                ACPI_TABLE_IS_LOADED;
1036        }
1037        else
1038        {
1039            AcpiGbl_RootTableList.Tables[TableIndex].Flags &=
1040                ~ACPI_TABLE_IS_LOADED;
1041        }
1042    }
1043
1044    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
1045}
1046
1047
1048/*******************************************************************************
1049 *
1050 * FUNCTION:    AcpiTbLoadTable
1051 *
1052 * PARAMETERS:  TableIndex              - Table index
1053 *              ParentNode              - Where table index is returned
1054 *
1055 * RETURN:      Status
1056 *
1057 * DESCRIPTION: Load an ACPI table
1058 *
1059 ******************************************************************************/
1060
1061ACPI_STATUS
1062AcpiTbLoadTable (
1063    UINT32                  TableIndex,
1064    ACPI_NAMESPACE_NODE     *ParentNode)
1065{
1066    ACPI_TABLE_HEADER       *Table;
1067    ACPI_STATUS             Status;
1068    ACPI_OWNER_ID           OwnerId;
1069
1070
1071    ACPI_FUNCTION_TRACE (TbLoadTable);
1072
1073
1074    /*
1075     * Note: Now table is "INSTALLED", it must be validated before
1076     * using.
1077     */
1078    Status = AcpiGetTableByIndex (TableIndex, &Table);
1079    if (ACPI_FAILURE (Status))
1080    {
1081        return_ACPI_STATUS (Status);
1082    }
1083
1084    Status = AcpiNsLoadTable (TableIndex, ParentNode);
1085    if (ACPI_FAILURE (Status))
1086    {
1087        return_ACPI_STATUS (Status);
1088    }
1089
1090    /*
1091     * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
1092     * responsible for discovering any new wake GPEs by running _PRW methods
1093     * that may have been loaded by this table.
1094     */
1095    Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
1096    if (ACPI_SUCCESS (Status))
1097    {
1098        AcpiEvUpdateGpes (OwnerId);
1099    }
1100
1101    /* Invoke table handler */
1102
1103    AcpiTbNotifyTable (ACPI_TABLE_EVENT_LOAD, Table);
1104    return_ACPI_STATUS (Status);
1105}
1106
1107
1108/*******************************************************************************
1109 *
1110 * FUNCTION:    AcpiTbInstallAndLoadTable
1111 *
1112 * PARAMETERS:  Address                 - Physical address of the table
1113 *              Flags                   - Allocation flags of the table
1114 *              Override                - Whether override should be performed
1115 *              TableIndex              - Where table index is returned
1116 *
1117 * RETURN:      Status
1118 *
1119 * DESCRIPTION: Install and load an ACPI table
1120 *
1121 ******************************************************************************/
1122
1123ACPI_STATUS
1124AcpiTbInstallAndLoadTable (
1125    ACPI_PHYSICAL_ADDRESS   Address,
1126    UINT8                   Flags,
1127    BOOLEAN                 Override,
1128    UINT32                  *TableIndex)
1129{
1130    ACPI_STATUS             Status;
1131    UINT32                  i;
1132
1133
1134    ACPI_FUNCTION_TRACE (TbInstallAndLoadTable);
1135
1136
1137    /* Install the table and load it into the namespace */
1138
1139    Status = AcpiTbInstallStandardTable (Address, Flags, TRUE,
1140        Override, &i);
1141    if (ACPI_FAILURE (Status))
1142    {
1143        goto Exit;
1144    }
1145
1146    Status = AcpiTbLoadTable (i, AcpiGbl_RootNode);
1147
1148Exit:
1149    *TableIndex = i;
1150    return_ACPI_STATUS (Status);
1151}
1152
1153
1154/*******************************************************************************
1155 *
1156 * FUNCTION:    AcpiTbUnloadTable
1157 *
1158 * PARAMETERS:  TableIndex              - Table index
1159 *
1160 * RETURN:      Status
1161 *
1162 * DESCRIPTION: Unload an ACPI table
1163 *
1164 ******************************************************************************/
1165
1166ACPI_STATUS
1167AcpiTbUnloadTable (
1168    UINT32                  TableIndex)
1169{
1170    ACPI_STATUS             Status = AE_OK;
1171    ACPI_TABLE_HEADER       *Table;
1172
1173
1174    ACPI_FUNCTION_TRACE (TbUnloadTable);
1175
1176
1177    /* Ensure the table is still loaded */
1178
1179    if (!AcpiTbIsTableLoaded (TableIndex))
1180    {
1181        return_ACPI_STATUS (AE_NOT_EXIST);
1182    }
1183
1184    /* Invoke table handler */
1185
1186    Status = AcpiGetTableByIndex (TableIndex, &Table);
1187    if (ACPI_SUCCESS (Status))
1188    {
1189        AcpiTbNotifyTable (ACPI_TABLE_EVENT_UNLOAD, Table);
1190    }
1191
1192    /* Delete the portion of the namespace owned by this table */
1193
1194    Status = AcpiTbDeleteNamespaceByOwner (TableIndex);
1195    if (ACPI_FAILURE (Status))
1196    {
1197        return_ACPI_STATUS (Status);
1198    }
1199
1200    (void) AcpiTbReleaseOwnerId (TableIndex);
1201    AcpiTbSetTableLoadedFlag (TableIndex, FALSE);
1202    return_ACPI_STATUS (Status);
1203}
1204
1205
1206/*******************************************************************************
1207 *
1208 * FUNCTION:    AcpiTbNotifyTable
1209 *
1210 * PARAMETERS:  Event               - Table event
1211 *              Table               - Validated table pointer
1212 *
1213 * RETURN:      None
1214 *
1215 * DESCRIPTION: Notify a table event to the users.
1216 *
1217 ******************************************************************************/
1218
1219void
1220AcpiTbNotifyTable (
1221    UINT32                          Event,
1222    void                            *Table)
1223{
1224    /* Invoke table handler if present */
1225
1226    if (AcpiGbl_TableHandler)
1227    {
1228        (void) AcpiGbl_TableHandler (Event, Table,
1229            AcpiGbl_TableHandlerContext);
1230    }
1231}
1232