xref: /reactos/drivers/bus/acpi/acpica/tables/tbdata.c (revision 279107d5)
1 /******************************************************************************
2  *
3  * Module Name: tbdata - Table manager data structure functions
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2019, 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 
55 static ACPI_STATUS
56 AcpiTbCheckDuplication (
57     ACPI_TABLE_DESC         *TableDesc,
58     UINT32                  *TableIndex);
59 
60 static BOOLEAN
61 AcpiTbCompareTables (
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 
80 static BOOLEAN
81 AcpiTbCompareTables (
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 
129 void
130 AcpiTbInitTableDescriptor (
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 
165 ACPI_STATUS
166 AcpiTbAcquireTable (
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 
224 void
225 AcpiTbReleaseTable (
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 
264 ACPI_STATUS
265 AcpiTbAcquireTempTable (
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 
325 void
326 AcpiTbReleaseTempTable (
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 
352 ACPI_STATUS
353 AcpiTbValidateTable (
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 
391 void
392 AcpiTbInvalidateTable (
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 
427 ACPI_STATUS
428 AcpiTbValidateTempTable (
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 
466 static ACPI_STATUS
467 AcpiTbCheckDuplication (
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 
548 ACPI_STATUS
549 AcpiTbVerifyTempTable (
550     ACPI_TABLE_DESC         *TableDesc,
551     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_NAME (&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 
623 InvalidateAndExit:
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 
641 ACPI_STATUS
642 AcpiTbResizeRootTableList (
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 
726 ACPI_STATUS
727 AcpiTbGetNextTableDescriptor (
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 
775 void
776 AcpiTbTerminate (
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 
826 ACPI_STATUS
827 AcpiTbDeleteNamespaceByOwner (
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     AcpiNsDeleteNamespaceByOwner (OwnerId);
869     AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock);
870     return_ACPI_STATUS (Status);
871 }
872 
873 
874 /*******************************************************************************
875  *
876  * FUNCTION:    AcpiTbAllocateOwnerId
877  *
878  * PARAMETERS:  TableIndex          - Table index
879  *
880  * RETURN:      Status
881  *
882  * DESCRIPTION: Allocates OwnerId in TableDesc
883  *
884  ******************************************************************************/
885 
886 ACPI_STATUS
887 AcpiTbAllocateOwnerId (
888     UINT32                  TableIndex)
889 {
890     ACPI_STATUS             Status = AE_BAD_PARAMETER;
891 
892 
893     ACPI_FUNCTION_TRACE (TbAllocateOwnerId);
894 
895 
896     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
897     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
898     {
899         Status = AcpiUtAllocateOwnerId (
900             &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
901     }
902 
903     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
904     return_ACPI_STATUS (Status);
905 }
906 
907 
908 /*******************************************************************************
909  *
910  * FUNCTION:    AcpiTbReleaseOwnerId
911  *
912  * PARAMETERS:  TableIndex          - Table index
913  *
914  * RETURN:      Status
915  *
916  * DESCRIPTION: Releases OwnerId in TableDesc
917  *
918  ******************************************************************************/
919 
920 ACPI_STATUS
921 AcpiTbReleaseOwnerId (
922     UINT32                  TableIndex)
923 {
924     ACPI_STATUS             Status = AE_BAD_PARAMETER;
925 
926 
927     ACPI_FUNCTION_TRACE (TbReleaseOwnerId);
928 
929 
930     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
931     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
932     {
933         AcpiUtReleaseOwnerId (
934             &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
935         Status = AE_OK;
936     }
937 
938     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
939     return_ACPI_STATUS (Status);
940 }
941 
942 
943 /*******************************************************************************
944  *
945  * FUNCTION:    AcpiTbGetOwnerId
946  *
947  * PARAMETERS:  TableIndex          - Table index
948  *              OwnerId             - Where the table OwnerId is returned
949  *
950  * RETURN:      Status
951  *
952  * DESCRIPTION: returns OwnerId for the ACPI table
953  *
954  ******************************************************************************/
955 
956 ACPI_STATUS
957 AcpiTbGetOwnerId (
958     UINT32                  TableIndex,
959     ACPI_OWNER_ID           *OwnerId)
960 {
961     ACPI_STATUS             Status = AE_BAD_PARAMETER;
962 
963 
964     ACPI_FUNCTION_TRACE (TbGetOwnerId);
965 
966 
967     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
968     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
969     {
970         *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
971         Status = AE_OK;
972     }
973 
974     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
975     return_ACPI_STATUS (Status);
976 }
977 
978 
979 /*******************************************************************************
980  *
981  * FUNCTION:    AcpiTbIsTableLoaded
982  *
983  * PARAMETERS:  TableIndex          - Index into the root table
984  *
985  * RETURN:      Table Loaded Flag
986  *
987  ******************************************************************************/
988 
989 BOOLEAN
990 AcpiTbIsTableLoaded (
991     UINT32                  TableIndex)
992 {
993     BOOLEAN                 IsLoaded = FALSE;
994 
995 
996     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
997     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
998     {
999         IsLoaded = (BOOLEAN)
1000             (AcpiGbl_RootTableList.Tables[TableIndex].Flags &
1001             ACPI_TABLE_IS_LOADED);
1002     }
1003 
1004     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
1005     return (IsLoaded);
1006 }
1007 
1008 
1009 /*******************************************************************************
1010  *
1011  * FUNCTION:    AcpiTbSetTableLoadedFlag
1012  *
1013  * PARAMETERS:  TableIndex          - Table index
1014  *              IsLoaded            - TRUE if table is loaded, FALSE otherwise
1015  *
1016  * RETURN:      None
1017  *
1018  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
1019  *
1020  ******************************************************************************/
1021 
1022 void
1023 AcpiTbSetTableLoadedFlag (
1024     UINT32                  TableIndex,
1025     BOOLEAN                 IsLoaded)
1026 {
1027 
1028     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
1029     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
1030     {
1031         if (IsLoaded)
1032         {
1033             AcpiGbl_RootTableList.Tables[TableIndex].Flags |=
1034                 ACPI_TABLE_IS_LOADED;
1035         }
1036         else
1037         {
1038             AcpiGbl_RootTableList.Tables[TableIndex].Flags &=
1039                 ~ACPI_TABLE_IS_LOADED;
1040         }
1041     }
1042 
1043     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
1044 }
1045 
1046 
1047 /*******************************************************************************
1048  *
1049  * FUNCTION:    AcpiTbLoadTable
1050  *
1051  * PARAMETERS:  TableIndex              - Table index
1052  *              ParentNode              - Where table index is returned
1053  *
1054  * RETURN:      Status
1055  *
1056  * DESCRIPTION: Load an ACPI table
1057  *
1058  ******************************************************************************/
1059 
1060 ACPI_STATUS
1061 AcpiTbLoadTable (
1062     UINT32                  TableIndex,
1063     ACPI_NAMESPACE_NODE     *ParentNode)
1064 {
1065     ACPI_TABLE_HEADER       *Table;
1066     ACPI_STATUS             Status;
1067     ACPI_OWNER_ID           OwnerId;
1068 
1069 
1070     ACPI_FUNCTION_TRACE (TbLoadTable);
1071 
1072 
1073     /*
1074      * Note: Now table is "INSTALLED", it must be validated before
1075      * using.
1076      */
1077     Status = AcpiGetTableByIndex (TableIndex, &Table);
1078     if (ACPI_FAILURE (Status))
1079     {
1080         return_ACPI_STATUS (Status);
1081     }
1082 
1083     Status = AcpiNsLoadTable (TableIndex, ParentNode);
1084 
1085     /*
1086      * This case handles the legacy option that groups all module-level
1087      * code blocks together and defers execution until all of the tables
1088      * are loaded. Execute all of these blocks at this time.
1089      * Execute any module-level code that was detected during the table
1090      * load phase.
1091      *
1092      * Note: this option is deprecated and will be eliminated in the
1093      * future. Use of this option can cause problems with AML code that
1094      * depends upon in-order immediate execution of module-level code.
1095      */
1096     AcpiNsExecModuleCodeList ();
1097 
1098     /*
1099      * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
1100      * responsible for discovering any new wake GPEs by running _PRW methods
1101      * that may have been loaded by this table.
1102      */
1103     Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
1104     if (ACPI_SUCCESS (Status))
1105     {
1106         AcpiEvUpdateGpes (OwnerId);
1107     }
1108 
1109     /* Invoke table handler */
1110 
1111     AcpiTbNotifyTable (ACPI_TABLE_EVENT_LOAD, Table);
1112     return_ACPI_STATUS (Status);
1113 }
1114 
1115 
1116 /*******************************************************************************
1117  *
1118  * FUNCTION:    AcpiTbInstallAndLoadTable
1119  *
1120  * PARAMETERS:  Address                 - Physical address of the table
1121  *              Flags                   - Allocation flags of the table
1122  *              Override                - Whether override should be performed
1123  *              TableIndex              - Where table index is returned
1124  *
1125  * RETURN:      Status
1126  *
1127  * DESCRIPTION: Install and load an ACPI table
1128  *
1129  ******************************************************************************/
1130 
1131 ACPI_STATUS
1132 AcpiTbInstallAndLoadTable (
1133     ACPI_PHYSICAL_ADDRESS   Address,
1134     UINT8                   Flags,
1135     BOOLEAN                 Override,
1136     UINT32                  *TableIndex)
1137 {
1138     ACPI_STATUS             Status;
1139     UINT32                  i;
1140 
1141 
1142     ACPI_FUNCTION_TRACE (TbInstallAndLoadTable);
1143 
1144 
1145     /* Install the table and load it into the namespace */
1146 
1147     Status = AcpiTbInstallStandardTable (Address, Flags, TRUE,
1148         Override, &i);
1149     if (ACPI_FAILURE (Status))
1150     {
1151         goto Exit;
1152     }
1153 
1154     Status = AcpiTbLoadTable (i, AcpiGbl_RootNode);
1155 
1156 Exit:
1157     *TableIndex = i;
1158     return_ACPI_STATUS (Status);
1159 }
1160 
1161 
1162 /*******************************************************************************
1163  *
1164  * FUNCTION:    AcpiTbUnloadTable
1165  *
1166  * PARAMETERS:  TableIndex              - Table index
1167  *
1168  * RETURN:      Status
1169  *
1170  * DESCRIPTION: Unload an ACPI table
1171  *
1172  ******************************************************************************/
1173 
1174 ACPI_STATUS
1175 AcpiTbUnloadTable (
1176     UINT32                  TableIndex)
1177 {
1178     ACPI_STATUS             Status = AE_OK;
1179     ACPI_TABLE_HEADER       *Table;
1180 
1181 
1182     ACPI_FUNCTION_TRACE (TbUnloadTable);
1183 
1184 
1185     /* Ensure the table is still loaded */
1186 
1187     if (!AcpiTbIsTableLoaded (TableIndex))
1188     {
1189         return_ACPI_STATUS (AE_NOT_EXIST);
1190     }
1191 
1192     /* Invoke table handler */
1193 
1194     Status = AcpiGetTableByIndex (TableIndex, &Table);
1195     if (ACPI_SUCCESS (Status))
1196     {
1197         AcpiTbNotifyTable (ACPI_TABLE_EVENT_UNLOAD, Table);
1198     }
1199 
1200     /* Delete the portion of the namespace owned by this table */
1201 
1202     Status = AcpiTbDeleteNamespaceByOwner (TableIndex);
1203     if (ACPI_FAILURE (Status))
1204     {
1205         return_ACPI_STATUS (Status);
1206     }
1207 
1208     (void) AcpiTbReleaseOwnerId (TableIndex);
1209     AcpiTbSetTableLoadedFlag (TableIndex, FALSE);
1210     return_ACPI_STATUS (Status);
1211 }
1212 
1213 
1214 /*******************************************************************************
1215  *
1216  * FUNCTION:    AcpiTbNotifyTable
1217  *
1218  * PARAMETERS:  Event               - Table event
1219  *              Table               - Validated table pointer
1220  *
1221  * RETURN:      None
1222  *
1223  * DESCRIPTION: Notify a table event to the users.
1224  *
1225  ******************************************************************************/
1226 
1227 void
1228 AcpiTbNotifyTable (
1229     UINT32                          Event,
1230     void                            *Table)
1231 {
1232     /* Invoke table handler if present */
1233 
1234     if (AcpiGbl_TableHandler)
1235     {
1236         (void) AcpiGbl_TableHandler (Event, Table,
1237             AcpiGbl_TableHandlerContext);
1238     }
1239 }
1240