xref: /titanic_51/usr/src/uts/intel/io/acpica/tables/tbinstal.c (revision f5c2e7ea56aaa46a9976476fb0cb1f02b9426f07)
1 /******************************************************************************
2  *
3  * Module Name: tbinstal - ACPI table installation and removal
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2011, 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 
45 #define __TBINSTAL_C__
46 
47 #include "acpi.h"
48 #include "accommon.h"
49 #include "acnamesp.h"
50 #include "actables.h"
51 
52 
53 #define _COMPONENT          ACPI_TABLES
54         ACPI_MODULE_NAME    ("tbinstal")
55 
56 
57 /******************************************************************************
58  *
59  * FUNCTION:    AcpiTbVerifyTable
60  *
61  * PARAMETERS:  TableDesc           - table
62  *
63  * RETURN:      Status
64  *
65  * DESCRIPTION: this function is called to verify and map table
66  *
67  *****************************************************************************/
68 
69 ACPI_STATUS
70 AcpiTbVerifyTable (
71     ACPI_TABLE_DESC         *TableDesc)
72 {
73     ACPI_STATUS             Status = AE_OK;
74 
75 
76     ACPI_FUNCTION_TRACE (TbVerifyTable);
77 
78 
79     /* Map the table if necessary */
80 
81     if (!TableDesc->Pointer)
82     {
83         if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) ==
84             ACPI_TABLE_ORIGIN_MAPPED)
85         {
86             TableDesc->Pointer = AcpiOsMapMemory (
87                 TableDesc->Address, TableDesc->Length);
88         }
89 
90         if (!TableDesc->Pointer)
91         {
92             return_ACPI_STATUS (AE_NO_MEMORY);
93         }
94     }
95 
96     /* FACS is the odd table, has no standard ACPI header and no checksum */
97 
98     if (!ACPI_COMPARE_NAME (&TableDesc->Signature, ACPI_SIG_FACS))
99     {
100         /* Always calculate checksum, ignore bad checksum if requested */
101 
102         Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length);
103     }
104 
105     return_ACPI_STATUS (Status);
106 }
107 
108 
109 /*******************************************************************************
110  *
111  * FUNCTION:    AcpiTbAddTable
112  *
113  * PARAMETERS:  TableDesc           - Table descriptor
114  *              TableIndex          - Where the table index is returned
115  *
116  * RETURN:      Status
117  *
118  * DESCRIPTION: This function is called to add an ACPI table. It is used to
119  *              dynamically load tables via the Load and LoadTable AML
120  *              operators.
121  *
122  ******************************************************************************/
123 
124 ACPI_STATUS
125 AcpiTbAddTable (
126     ACPI_TABLE_DESC         *TableDesc,
127     UINT32                  *TableIndex)
128 {
129     UINT32                  i;
130     ACPI_STATUS             Status = AE_OK;
131     ACPI_TABLE_HEADER       *OverrideTable = NULL;
132 
133 
134     ACPI_FUNCTION_TRACE (TbAddTable);
135 
136 
137     if (!TableDesc->Pointer)
138     {
139         Status = AcpiTbVerifyTable (TableDesc);
140         if (ACPI_FAILURE (Status) || !TableDesc->Pointer)
141         {
142             return_ACPI_STATUS (Status);
143         }
144     }
145 
146     /*
147      * Validate the incoming table signature.
148      *
149      * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
150      * 2) We added support for OEMx tables, signature "OEM".
151      * 3) Valid tables were encountered with a null signature, so we just
152      *    gave up on validating the signature, (05/2008).
153      * 4) We encountered non-AML tables such as the MADT, which caused
154      *    interpreter errors and kernel faults. So now, we once again allow
155      *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
156      */
157     if ((TableDesc->Pointer->Signature[0] != 0x00) &&
158        (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) &&
159        (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3)))
160     {
161         ACPI_ERROR ((AE_INFO,
162             "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx",
163             AcpiUtValidAcpiName (*(UINT32 *) TableDesc->Pointer->Signature) ?
164                 TableDesc->Pointer->Signature : "????",
165             *(UINT32 *) TableDesc->Pointer->Signature));
166 
167         return_ACPI_STATUS (AE_BAD_SIGNATURE);
168     }
169 
170     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
171 
172     /* Check if table is already registered */
173 
174     for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
175     {
176         if (!AcpiGbl_RootTableList.Tables[i].Pointer)
177         {
178             Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]);
179             if (ACPI_FAILURE (Status) ||
180                 !AcpiGbl_RootTableList.Tables[i].Pointer)
181             {
182                 continue;
183             }
184         }
185 
186         /*
187          * Check for a table match on the entire table length,
188          * not just the header.
189          */
190         if (TableDesc->Length != AcpiGbl_RootTableList.Tables[i].Length)
191         {
192             continue;
193         }
194 
195         if (ACPI_MEMCMP (TableDesc->Pointer,
196                 AcpiGbl_RootTableList.Tables[i].Pointer,
197                 AcpiGbl_RootTableList.Tables[i].Length))
198         {
199             continue;
200         }
201 
202         /*
203          * Note: the current mechanism does not unregister a table if it is
204          * dynamically unloaded. The related namespace entries are deleted,
205          * but the table remains in the root table list.
206          *
207          * The assumption here is that the number of different tables that
208          * will be loaded is actually small, and there is minimal overhead
209          * in just keeping the table in case it is needed again.
210          *
211          * If this assumption changes in the future (perhaps on large
212          * machines with many table load/unload operations), tables will
213          * need to be unregistered when they are unloaded, and slots in the
214          * root table list should be reused when empty.
215          */
216 
217         /*
218          * Table is already registered.
219          * We can delete the table that was passed as a parameter.
220          */
221         AcpiTbDeleteTable (TableDesc);
222         *TableIndex = i;
223 
224         if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED)
225         {
226             /* Table is still loaded, this is an error */
227 
228             Status = AE_ALREADY_EXISTS;
229             goto Release;
230         }
231         else
232         {
233             /* Table was unloaded, allow it to be reloaded */
234 
235             TableDesc->Pointer = AcpiGbl_RootTableList.Tables[i].Pointer;
236             TableDesc->Address = AcpiGbl_RootTableList.Tables[i].Address;
237             Status = AE_OK;
238             goto PrintHeader;
239         }
240     }
241 
242     /*
243      * ACPI Table Override:
244      * Allow the host to override dynamically loaded tables.
245      */
246     Status = AcpiOsTableOverride (TableDesc->Pointer, &OverrideTable);
247     if (ACPI_SUCCESS (Status) && OverrideTable)
248     {
249         ACPI_INFO ((AE_INFO,
250             "%4.4s @ 0x%p Table override, replaced with:",
251             TableDesc->Pointer->Signature,
252             ACPI_CAST_PTR (void, TableDesc->Address)));
253 
254         /* We can delete the table that was passed as a parameter */
255 
256         AcpiTbDeleteTable (TableDesc);
257 
258         /* Setup descriptor for the new table */
259 
260         TableDesc->Address = ACPI_PTR_TO_PHYSADDR (OverrideTable);
261         TableDesc->Pointer = OverrideTable;
262         TableDesc->Length = OverrideTable->Length;
263         TableDesc->Flags = ACPI_TABLE_ORIGIN_OVERRIDE;
264     }
265 
266     /* Add the table to the global root table list */
267 
268     Status = AcpiTbStoreTable (TableDesc->Address, TableDesc->Pointer,
269                 TableDesc->Length, TableDesc->Flags, TableIndex);
270     if (ACPI_FAILURE (Status))
271     {
272         goto Release;
273     }
274 
275 PrintHeader:
276     AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer);
277 
278 Release:
279     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
280     return_ACPI_STATUS (Status);
281 }
282 
283 
284 /*******************************************************************************
285  *
286  * FUNCTION:    AcpiTbResizeRootTableList
287  *
288  * PARAMETERS:  None
289  *
290  * RETURN:      Status
291  *
292  * DESCRIPTION: Expand the size of global table array
293  *
294  ******************************************************************************/
295 
296 ACPI_STATUS
297 AcpiTbResizeRootTableList (
298     void)
299 {
300     ACPI_TABLE_DESC         *Tables;
301 
302 
303     ACPI_FUNCTION_TRACE (TbResizeRootTableList);
304 
305 
306     /* AllowResize flag is a parameter to AcpiInitializeTables */
307 
308     if (!(AcpiGbl_RootTableList.Flags & ACPI_ROOT_ALLOW_RESIZE))
309     {
310         ACPI_ERROR ((AE_INFO, "Resize of Root Table Array is not allowed"));
311         return_ACPI_STATUS (AE_SUPPORT);
312     }
313 
314     /* Increase the Table Array size */
315 
316     Tables = ACPI_ALLOCATE_ZEROED (
317         ((ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount +
318             ACPI_ROOT_TABLE_SIZE_INCREMENT) *
319         sizeof (ACPI_TABLE_DESC));
320     if (!Tables)
321     {
322         ACPI_ERROR ((AE_INFO, "Could not allocate new root table array"));
323         return_ACPI_STATUS (AE_NO_MEMORY);
324     }
325 
326     /* Copy and free the previous table array */
327 
328     if (AcpiGbl_RootTableList.Tables)
329     {
330         ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables,
331             (ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount * sizeof (ACPI_TABLE_DESC));
332 
333         if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
334         {
335             ACPI_FREE (AcpiGbl_RootTableList.Tables);
336         }
337     }
338 
339     AcpiGbl_RootTableList.Tables = Tables;
340     AcpiGbl_RootTableList.MaxTableCount += ACPI_ROOT_TABLE_SIZE_INCREMENT;
341     AcpiGbl_RootTableList.Flags |= (UINT8) ACPI_ROOT_ORIGIN_ALLOCATED;
342 
343     return_ACPI_STATUS (AE_OK);
344 }
345 
346 
347 /*******************************************************************************
348  *
349  * FUNCTION:    AcpiTbStoreTable
350  *
351  * PARAMETERS:  Address             - Table address
352  *              Table               - Table header
353  *              Length              - Table length
354  *              Flags               - flags
355  *
356  * RETURN:      Status and table index.
357  *
358  * DESCRIPTION: Add an ACPI table to the global table list
359  *
360  ******************************************************************************/
361 
362 ACPI_STATUS
363 AcpiTbStoreTable (
364     ACPI_PHYSICAL_ADDRESS   Address,
365     ACPI_TABLE_HEADER       *Table,
366     UINT32                  Length,
367     UINT8                   Flags,
368     UINT32                  *TableIndex)
369 {
370     ACPI_STATUS             Status;
371     ACPI_TABLE_DESC         *NewTable;
372 
373 
374     /* Ensure that there is room for the table in the Root Table List */
375 
376     if (AcpiGbl_RootTableList.CurrentTableCount >=
377         AcpiGbl_RootTableList.MaxTableCount)
378     {
379         Status = AcpiTbResizeRootTableList();
380         if (ACPI_FAILURE (Status))
381         {
382             return (Status);
383         }
384     }
385 
386     NewTable = &AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount];
387 
388     /* Initialize added table */
389 
390     NewTable->Address = Address;
391     NewTable->Pointer = Table;
392     NewTable->Length = Length;
393     NewTable->OwnerId = 0;
394     NewTable->Flags = Flags;
395 
396     ACPI_MOVE_32_TO_32 (&NewTable->Signature, Table->Signature);
397 
398     *TableIndex = AcpiGbl_RootTableList.CurrentTableCount;
399     AcpiGbl_RootTableList.CurrentTableCount++;
400     return (AE_OK);
401 }
402 
403 
404 /*******************************************************************************
405  *
406  * FUNCTION:    AcpiTbDeleteTable
407  *
408  * PARAMETERS:  TableIndex          - Table index
409  *
410  * RETURN:      None
411  *
412  * DESCRIPTION: Delete one internal ACPI table
413  *
414  ******************************************************************************/
415 
416 void
417 AcpiTbDeleteTable (
418     ACPI_TABLE_DESC         *TableDesc)
419 {
420 
421     /* Table must be mapped or allocated */
422 
423     if (!TableDesc->Pointer)
424     {
425         return;
426     }
427 
428     switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK)
429     {
430     case ACPI_TABLE_ORIGIN_MAPPED:
431         AcpiOsUnmapMemory (TableDesc->Pointer, TableDesc->Length);
432         break;
433 
434     case ACPI_TABLE_ORIGIN_ALLOCATED:
435         ACPI_FREE (TableDesc->Pointer);
436         break;
437 
438     default:
439         break;
440     }
441 
442     TableDesc->Pointer = NULL;
443 }
444 
445 
446 /*******************************************************************************
447  *
448  * FUNCTION:    AcpiTbTerminate
449  *
450  * PARAMETERS:  None
451  *
452  * RETURN:      None
453  *
454  * DESCRIPTION: Delete all internal ACPI tables
455  *
456  ******************************************************************************/
457 
458 void
459 AcpiTbTerminate (
460     void)
461 {
462     UINT32                  i;
463 
464 
465     ACPI_FUNCTION_TRACE (TbTerminate);
466 
467 
468     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
469 
470     /* Delete the individual tables */
471 
472     for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
473     {
474         AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[i]);
475     }
476 
477     /*
478      * Delete the root table array if allocated locally. Array cannot be
479      * mapped, so we don't need to check for that flag.
480      */
481     if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
482     {
483         ACPI_FREE (AcpiGbl_RootTableList.Tables);
484     }
485 
486     AcpiGbl_RootTableList.Tables = NULL;
487     AcpiGbl_RootTableList.Flags = 0;
488     AcpiGbl_RootTableList.CurrentTableCount = 0;
489 
490     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
491     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
492 }
493 
494 
495 /*******************************************************************************
496  *
497  * FUNCTION:    AcpiTbDeleteNamespaceByOwner
498  *
499  * PARAMETERS:  TableIndex          - Table index
500  *
501  * RETURN:      Status
502  *
503  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
504  *
505  ******************************************************************************/
506 
507 ACPI_STATUS
508 AcpiTbDeleteNamespaceByOwner (
509     UINT32                  TableIndex)
510 {
511     ACPI_OWNER_ID           OwnerId;
512     ACPI_STATUS             Status;
513 
514 
515     ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner);
516 
517 
518     Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES);
519     if (ACPI_FAILURE (Status))
520     {
521         return_ACPI_STATUS (Status);
522     }
523 
524     if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
525     {
526         /* The table index does not exist */
527 
528         (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
529         return_ACPI_STATUS (AE_NOT_EXIST);
530     }
531 
532     /* Get the owner ID for this table, used to delete namespace nodes */
533 
534     OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
535     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
536 
537     /*
538      * Need to acquire the namespace writer lock to prevent interference
539      * with any concurrent namespace walks. The interpreter must be
540      * released during the deletion since the acquisition of the deletion
541      * lock may block, and also since the execution of a namespace walk
542      * must be allowed to use the interpreter.
543      */
544     (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
545     Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock);
546 
547     AcpiNsDeleteNamespaceByOwner (OwnerId);
548     if (ACPI_FAILURE (Status))
549     {
550         return_ACPI_STATUS (Status);
551     }
552 
553     AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock);
554 
555     Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
556     return_ACPI_STATUS (Status);
557 }
558 
559 
560 /*******************************************************************************
561  *
562  * FUNCTION:    AcpiTbAllocateOwnerId
563  *
564  * PARAMETERS:  TableIndex          - Table index
565  *
566  * RETURN:      Status
567  *
568  * DESCRIPTION: Allocates OwnerId in TableDesc
569  *
570  ******************************************************************************/
571 
572 ACPI_STATUS
573 AcpiTbAllocateOwnerId (
574     UINT32                  TableIndex)
575 {
576     ACPI_STATUS             Status = AE_BAD_PARAMETER;
577 
578 
579     ACPI_FUNCTION_TRACE (TbAllocateOwnerId);
580 
581 
582     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
583     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
584     {
585         Status = AcpiUtAllocateOwnerId
586                     (&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
587     }
588 
589     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
590     return_ACPI_STATUS (Status);
591 }
592 
593 
594 /*******************************************************************************
595  *
596  * FUNCTION:    AcpiTbReleaseOwnerId
597  *
598  * PARAMETERS:  TableIndex          - Table index
599  *
600  * RETURN:      Status
601  *
602  * DESCRIPTION: Releases OwnerId in TableDesc
603  *
604  ******************************************************************************/
605 
606 ACPI_STATUS
607 AcpiTbReleaseOwnerId (
608     UINT32                  TableIndex)
609 {
610     ACPI_STATUS             Status = AE_BAD_PARAMETER;
611 
612 
613     ACPI_FUNCTION_TRACE (TbReleaseOwnerId);
614 
615 
616     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
617     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
618     {
619         AcpiUtReleaseOwnerId (
620             &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
621         Status = AE_OK;
622     }
623 
624     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
625     return_ACPI_STATUS (Status);
626 }
627 
628 
629 /*******************************************************************************
630  *
631  * FUNCTION:    AcpiTbGetOwnerId
632  *
633  * PARAMETERS:  TableIndex          - Table index
634  *              OwnerId             - Where the table OwnerId is returned
635  *
636  * RETURN:      Status
637  *
638  * DESCRIPTION: returns OwnerId for the ACPI table
639  *
640  ******************************************************************************/
641 
642 ACPI_STATUS
643 AcpiTbGetOwnerId (
644     UINT32                  TableIndex,
645     ACPI_OWNER_ID           *OwnerId)
646 {
647     ACPI_STATUS             Status = AE_BAD_PARAMETER;
648 
649 
650     ACPI_FUNCTION_TRACE (TbGetOwnerId);
651 
652 
653     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
654     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
655     {
656         *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
657         Status = AE_OK;
658     }
659 
660     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
661     return_ACPI_STATUS (Status);
662 }
663 
664 
665 /*******************************************************************************
666  *
667  * FUNCTION:    AcpiTbIsTableLoaded
668  *
669  * PARAMETERS:  TableIndex          - Table index
670  *
671  * RETURN:      Table Loaded Flag
672  *
673  ******************************************************************************/
674 
675 BOOLEAN
676 AcpiTbIsTableLoaded (
677     UINT32                  TableIndex)
678 {
679     BOOLEAN                 IsLoaded = FALSE;
680 
681 
682     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
683     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
684     {
685         IsLoaded = (BOOLEAN)
686             (AcpiGbl_RootTableList.Tables[TableIndex].Flags &
687             ACPI_TABLE_IS_LOADED);
688     }
689 
690     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
691     return (IsLoaded);
692 }
693 
694 
695 /*******************************************************************************
696  *
697  * FUNCTION:    AcpiTbSetTableLoadedFlag
698  *
699  * PARAMETERS:  TableIndex          - Table index
700  *              IsLoaded            - TRUE if table is loaded, FALSE otherwise
701  *
702  * RETURN:      None
703  *
704  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
705  *
706  ******************************************************************************/
707 
708 void
709 AcpiTbSetTableLoadedFlag (
710     UINT32                  TableIndex,
711     BOOLEAN                 IsLoaded)
712 {
713 
714     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
715     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
716     {
717         if (IsLoaded)
718         {
719             AcpiGbl_RootTableList.Tables[TableIndex].Flags |=
720                 ACPI_TABLE_IS_LOADED;
721         }
722         else
723         {
724             AcpiGbl_RootTableList.Tables[TableIndex].Flags &=
725                 ~ACPI_TABLE_IS_LOADED;
726         }
727     }
728 
729     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
730 }
731 
732