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