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