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