xref: /freebsd/sys/contrib/dev/acpica/components/tables/tbinstal.c (revision c6ec7d31830ab1c80edae95ad5e4b9dba10c47ac)
1 /******************************************************************************
2  *
3  * Module Name: tbinstal - ACPI table installation and removal
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2012, 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 <contrib/dev/acpica/include/acpi.h>
48 #include <contrib/dev/acpica/include/accommon.h>
49 #include <contrib/dev/acpica/include/acnamesp.h>
50 #include <contrib/dev/acpica/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 
132 
133     ACPI_FUNCTION_TRACE (TbAddTable);
134 
135 
136     if (!TableDesc->Pointer)
137     {
138         Status = AcpiTbVerifyTable (TableDesc);
139         if (ACPI_FAILURE (Status) || !TableDesc->Pointer)
140         {
141             return_ACPI_STATUS (Status);
142         }
143     }
144 
145     /*
146      * Validate the incoming table signature.
147      *
148      * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
149      * 2) We added support for OEMx tables, signature "OEM".
150      * 3) Valid tables were encountered with a null signature, so we just
151      *    gave up on validating the signature, (05/2008).
152      * 4) We encountered non-AML tables such as the MADT, which caused
153      *    interpreter errors and kernel faults. So now, we once again allow
154      *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
155      */
156     if ((TableDesc->Pointer->Signature[0] != 0x00) &&
157        (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) &&
158        (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3)))
159     {
160         ACPI_BIOS_ERROR ((AE_INFO,
161             "Table has invalid signature [%4.4s] (0x%8.8X), "
162             "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      * NOTE: the table is fully mapped at this point, and the mapping will
246      * be deleted by TbTableOverride if the table is actually overridden.
247      */
248     (void) AcpiTbTableOverride (TableDesc->Pointer, TableDesc);
249 
250     /* Add the table to the global root table list */
251 
252     Status = AcpiTbStoreTable (TableDesc->Address, TableDesc->Pointer,
253                 TableDesc->Length, TableDesc->Flags, TableIndex);
254     if (ACPI_FAILURE (Status))
255     {
256         goto Release;
257     }
258 
259 PrintHeader:
260     AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer);
261 
262 Release:
263     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
264     return_ACPI_STATUS (Status);
265 }
266 
267 
268 /*******************************************************************************
269  *
270  * FUNCTION:    AcpiTbTableOverride
271  *
272  * PARAMETERS:  TableHeader         - Header for the original table
273  *              TableDesc           - Table descriptor initialized for the
274  *                                    original table. May or may not be mapped.
275  *
276  * RETURN:      Pointer to the entire new table. NULL if table not overridden.
277  *              If overridden, installs the new table within the input table
278  *              descriptor.
279  *
280  * DESCRIPTION: Attempt table override by calling the OSL override functions.
281  *              Note: If the table is overridden, then the entire new table
282  *              is mapped and returned by this function.
283  *
284  ******************************************************************************/
285 
286 ACPI_TABLE_HEADER *
287 AcpiTbTableOverride (
288     ACPI_TABLE_HEADER       *TableHeader,
289     ACPI_TABLE_DESC         *TableDesc)
290 {
291     ACPI_STATUS             Status;
292     ACPI_TABLE_HEADER       *NewTable = NULL;
293     ACPI_PHYSICAL_ADDRESS   NewAddress = 0;
294     UINT32                  NewTableLength = 0;
295     UINT8                   NewFlags;
296     char                    *OverrideType;
297 
298 
299     /* (1) Attempt logical override (returns a logical address) */
300 
301     Status = AcpiOsTableOverride (TableHeader, &NewTable);
302     if (ACPI_SUCCESS (Status) && NewTable)
303     {
304         NewAddress = ACPI_PTR_TO_PHYSADDR (NewTable);
305         NewTableLength = NewTable->Length;
306         NewFlags = ACPI_TABLE_ORIGIN_OVERRIDE;
307         OverrideType = "Logical";
308         goto FinishOverride;
309     }
310 
311     /* (2) Attempt physical override (returns a physical address) */
312 
313     Status = AcpiOsPhysicalTableOverride (TableHeader,
314         &NewAddress, &NewTableLength);
315     if (ACPI_SUCCESS (Status) && NewAddress && NewTableLength)
316     {
317         /* Map the entire new table */
318 
319         NewTable = AcpiOsMapMemory (NewAddress, NewTableLength);
320         if (!NewTable)
321         {
322             ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
323                 "%4.4s %p Attempted physical table override failed",
324                 TableHeader->Signature,
325                 ACPI_CAST_PTR (void, TableDesc->Address)));
326             return (NULL);
327         }
328 
329         OverrideType = "Physical";
330         NewFlags = ACPI_TABLE_ORIGIN_MAPPED;
331         goto FinishOverride;
332     }
333 
334     return (NULL); /* There was no override */
335 
336 
337 FinishOverride:
338 
339     ACPI_INFO ((AE_INFO,
340         "%4.4s %p %s table override, new table: %p",
341         TableHeader->Signature,
342         ACPI_CAST_PTR (void, TableDesc->Address),
343         OverrideType, NewTable));
344 
345     /* We can now unmap/delete the original table (if fully mapped) */
346 
347     AcpiTbDeleteTable (TableDesc);
348 
349     /* Setup descriptor for the new table */
350 
351     TableDesc->Address = NewAddress;
352     TableDesc->Pointer = NewTable;
353     TableDesc->Length = NewTableLength;
354     TableDesc->Flags = NewFlags;
355 
356     return (NewTable);
357 }
358 
359 
360 /*******************************************************************************
361  *
362  * FUNCTION:    AcpiTbResizeRootTableList
363  *
364  * PARAMETERS:  None
365  *
366  * RETURN:      Status
367  *
368  * DESCRIPTION: Expand the size of global table array
369  *
370  ******************************************************************************/
371 
372 ACPI_STATUS
373 AcpiTbResizeRootTableList (
374     void)
375 {
376     ACPI_TABLE_DESC         *Tables;
377     UINT32                  TableCount;
378 
379 
380     ACPI_FUNCTION_TRACE (TbResizeRootTableList);
381 
382 
383     /* AllowResize flag is a parameter to AcpiInitializeTables */
384 
385     if (!(AcpiGbl_RootTableList.Flags & ACPI_ROOT_ALLOW_RESIZE))
386     {
387         ACPI_ERROR ((AE_INFO, "Resize of Root Table Array is not allowed"));
388         return_ACPI_STATUS (AE_SUPPORT);
389     }
390 
391     /* Increase the Table Array size */
392 
393     if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
394     {
395         TableCount = AcpiGbl_RootTableList.MaxTableCount;
396     }
397     else
398     {
399         TableCount = AcpiGbl_RootTableList.CurrentTableCount;
400     }
401 
402     Tables = ACPI_ALLOCATE_ZEROED (
403         ((ACPI_SIZE) TableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT) *
404         sizeof (ACPI_TABLE_DESC));
405     if (!Tables)
406     {
407         ACPI_ERROR ((AE_INFO, "Could not allocate new root table array"));
408         return_ACPI_STATUS (AE_NO_MEMORY);
409     }
410 
411     /* Copy and free the previous table array */
412 
413     if (AcpiGbl_RootTableList.Tables)
414     {
415         ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables,
416             (ACPI_SIZE) TableCount * sizeof (ACPI_TABLE_DESC));
417 
418         if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
419         {
420             ACPI_FREE (AcpiGbl_RootTableList.Tables);
421         }
422     }
423 
424     AcpiGbl_RootTableList.Tables = Tables;
425     AcpiGbl_RootTableList.MaxTableCount =
426         TableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT;
427     AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
428 
429     return_ACPI_STATUS (AE_OK);
430 }
431 
432 
433 /*******************************************************************************
434  *
435  * FUNCTION:    AcpiTbStoreTable
436  *
437  * PARAMETERS:  Address             - Table address
438  *              Table               - Table header
439  *              Length              - Table length
440  *              Flags               - flags
441  *
442  * RETURN:      Status and table index.
443  *
444  * DESCRIPTION: Add an ACPI table to the global table list
445  *
446  ******************************************************************************/
447 
448 ACPI_STATUS
449 AcpiTbStoreTable (
450     ACPI_PHYSICAL_ADDRESS   Address,
451     ACPI_TABLE_HEADER       *Table,
452     UINT32                  Length,
453     UINT8                   Flags,
454     UINT32                  *TableIndex)
455 {
456     ACPI_STATUS             Status;
457     ACPI_TABLE_DESC         *NewTable;
458 
459 
460     /* Ensure that there is room for the table in the Root Table List */
461 
462     if (AcpiGbl_RootTableList.CurrentTableCount >=
463         AcpiGbl_RootTableList.MaxTableCount)
464     {
465         Status = AcpiTbResizeRootTableList();
466         if (ACPI_FAILURE (Status))
467         {
468             return (Status);
469         }
470     }
471 
472     NewTable = &AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount];
473 
474     /* Initialize added table */
475 
476     NewTable->Address = Address;
477     NewTable->Pointer = Table;
478     NewTable->Length = Length;
479     NewTable->OwnerId = 0;
480     NewTable->Flags = Flags;
481 
482     ACPI_MOVE_32_TO_32 (&NewTable->Signature, Table->Signature);
483 
484     *TableIndex = AcpiGbl_RootTableList.CurrentTableCount;
485     AcpiGbl_RootTableList.CurrentTableCount++;
486     return (AE_OK);
487 }
488 
489 
490 /*******************************************************************************
491  *
492  * FUNCTION:    AcpiTbDeleteTable
493  *
494  * PARAMETERS:  TableIndex          - Table index
495  *
496  * RETURN:      None
497  *
498  * DESCRIPTION: Delete one internal ACPI table
499  *
500  ******************************************************************************/
501 
502 void
503 AcpiTbDeleteTable (
504     ACPI_TABLE_DESC         *TableDesc)
505 {
506 
507     /* Table must be mapped or allocated */
508 
509     if (!TableDesc->Pointer)
510     {
511         return;
512     }
513 
514     switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK)
515     {
516     case ACPI_TABLE_ORIGIN_MAPPED:
517         AcpiOsUnmapMemory (TableDesc->Pointer, TableDesc->Length);
518         break;
519 
520     case ACPI_TABLE_ORIGIN_ALLOCATED:
521         ACPI_FREE (TableDesc->Pointer);
522         break;
523 
524     /* Not mapped or allocated, there is nothing we can do */
525 
526     default:
527         return;
528     }
529 
530     TableDesc->Pointer = NULL;
531 }
532 
533 
534 /*******************************************************************************
535  *
536  * FUNCTION:    AcpiTbTerminate
537  *
538  * PARAMETERS:  None
539  *
540  * RETURN:      None
541  *
542  * DESCRIPTION: Delete all internal ACPI tables
543  *
544  ******************************************************************************/
545 
546 void
547 AcpiTbTerminate (
548     void)
549 {
550     UINT32                  i;
551 
552 
553     ACPI_FUNCTION_TRACE (TbTerminate);
554 
555 
556     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
557 
558     /* Delete the individual tables */
559 
560     for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
561     {
562         AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[i]);
563     }
564 
565     /*
566      * Delete the root table array if allocated locally. Array cannot be
567      * mapped, so we don't need to check for that flag.
568      */
569     if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
570     {
571         ACPI_FREE (AcpiGbl_RootTableList.Tables);
572     }
573 
574     AcpiGbl_RootTableList.Tables = NULL;
575     AcpiGbl_RootTableList.Flags = 0;
576     AcpiGbl_RootTableList.CurrentTableCount = 0;
577 
578     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
579     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
580 
581     return_VOID;
582 }
583 
584 
585 /*******************************************************************************
586  *
587  * FUNCTION:    AcpiTbDeleteNamespaceByOwner
588  *
589  * PARAMETERS:  TableIndex          - Table index
590  *
591  * RETURN:      Status
592  *
593  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
594  *
595  ******************************************************************************/
596 
597 ACPI_STATUS
598 AcpiTbDeleteNamespaceByOwner (
599     UINT32                  TableIndex)
600 {
601     ACPI_OWNER_ID           OwnerId;
602     ACPI_STATUS             Status;
603 
604 
605     ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner);
606 
607 
608     Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES);
609     if (ACPI_FAILURE (Status))
610     {
611         return_ACPI_STATUS (Status);
612     }
613 
614     if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
615     {
616         /* The table index does not exist */
617 
618         (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
619         return_ACPI_STATUS (AE_NOT_EXIST);
620     }
621 
622     /* Get the owner ID for this table, used to delete namespace nodes */
623 
624     OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
625     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
626 
627     /*
628      * Need to acquire the namespace writer lock to prevent interference
629      * with any concurrent namespace walks. The interpreter must be
630      * released during the deletion since the acquisition of the deletion
631      * lock may block, and also since the execution of a namespace walk
632      * must be allowed to use the interpreter.
633      */
634     (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
635     Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock);
636 
637     AcpiNsDeleteNamespaceByOwner (OwnerId);
638     if (ACPI_FAILURE (Status))
639     {
640         return_ACPI_STATUS (Status);
641     }
642 
643     AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock);
644 
645     Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
646     return_ACPI_STATUS (Status);
647 }
648 
649 
650 /*******************************************************************************
651  *
652  * FUNCTION:    AcpiTbAllocateOwnerId
653  *
654  * PARAMETERS:  TableIndex          - Table index
655  *
656  * RETURN:      Status
657  *
658  * DESCRIPTION: Allocates OwnerId in TableDesc
659  *
660  ******************************************************************************/
661 
662 ACPI_STATUS
663 AcpiTbAllocateOwnerId (
664     UINT32                  TableIndex)
665 {
666     ACPI_STATUS             Status = AE_BAD_PARAMETER;
667 
668 
669     ACPI_FUNCTION_TRACE (TbAllocateOwnerId);
670 
671 
672     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
673     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
674     {
675         Status = AcpiUtAllocateOwnerId
676                     (&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
677     }
678 
679     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
680     return_ACPI_STATUS (Status);
681 }
682 
683 
684 /*******************************************************************************
685  *
686  * FUNCTION:    AcpiTbReleaseOwnerId
687  *
688  * PARAMETERS:  TableIndex          - Table index
689  *
690  * RETURN:      Status
691  *
692  * DESCRIPTION: Releases OwnerId in TableDesc
693  *
694  ******************************************************************************/
695 
696 ACPI_STATUS
697 AcpiTbReleaseOwnerId (
698     UINT32                  TableIndex)
699 {
700     ACPI_STATUS             Status = AE_BAD_PARAMETER;
701 
702 
703     ACPI_FUNCTION_TRACE (TbReleaseOwnerId);
704 
705 
706     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
707     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
708     {
709         AcpiUtReleaseOwnerId (
710             &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
711         Status = AE_OK;
712     }
713 
714     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
715     return_ACPI_STATUS (Status);
716 }
717 
718 
719 /*******************************************************************************
720  *
721  * FUNCTION:    AcpiTbGetOwnerId
722  *
723  * PARAMETERS:  TableIndex          - Table index
724  *              OwnerId             - Where the table OwnerId is returned
725  *
726  * RETURN:      Status
727  *
728  * DESCRIPTION: returns OwnerId for the ACPI table
729  *
730  ******************************************************************************/
731 
732 ACPI_STATUS
733 AcpiTbGetOwnerId (
734     UINT32                  TableIndex,
735     ACPI_OWNER_ID           *OwnerId)
736 {
737     ACPI_STATUS             Status = AE_BAD_PARAMETER;
738 
739 
740     ACPI_FUNCTION_TRACE (TbGetOwnerId);
741 
742 
743     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
744     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
745     {
746         *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
747         Status = AE_OK;
748     }
749 
750     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
751     return_ACPI_STATUS (Status);
752 }
753 
754 
755 /*******************************************************************************
756  *
757  * FUNCTION:    AcpiTbIsTableLoaded
758  *
759  * PARAMETERS:  TableIndex          - Table index
760  *
761  * RETURN:      Table Loaded Flag
762  *
763  ******************************************************************************/
764 
765 BOOLEAN
766 AcpiTbIsTableLoaded (
767     UINT32                  TableIndex)
768 {
769     BOOLEAN                 IsLoaded = FALSE;
770 
771 
772     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
773     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
774     {
775         IsLoaded = (BOOLEAN)
776             (AcpiGbl_RootTableList.Tables[TableIndex].Flags &
777             ACPI_TABLE_IS_LOADED);
778     }
779 
780     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
781     return (IsLoaded);
782 }
783 
784 
785 /*******************************************************************************
786  *
787  * FUNCTION:    AcpiTbSetTableLoadedFlag
788  *
789  * PARAMETERS:  TableIndex          - Table index
790  *              IsLoaded            - TRUE if table is loaded, FALSE otherwise
791  *
792  * RETURN:      None
793  *
794  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
795  *
796  ******************************************************************************/
797 
798 void
799 AcpiTbSetTableLoadedFlag (
800     UINT32                  TableIndex,
801     BOOLEAN                 IsLoaded)
802 {
803 
804     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
805     if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
806     {
807         if (IsLoaded)
808         {
809             AcpiGbl_RootTableList.Tables[TableIndex].Flags |=
810                 ACPI_TABLE_IS_LOADED;
811         }
812         else
813         {
814             AcpiGbl_RootTableList.Tables[TableIndex].Flags &=
815                 ~ACPI_TABLE_IS_LOADED;
816         }
817     }
818 
819     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
820 }
821