1 /******************************************************************************
3 * Module Name: tbinstal - ACPI table installation and removal
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2011, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
45 #define __TBINSTAL_C__
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>
53 #define _COMPONENT ACPI_TABLES
54 ACPI_MODULE_NAME ("tbinstal")
57 /******************************************************************************
59 * FUNCTION: AcpiTbVerifyTable
61 * PARAMETERS: TableDesc - table
65 * DESCRIPTION: this function is called to verify and map table
67 *****************************************************************************/
71 ACPI_TABLE_DESC *TableDesc)
73 ACPI_STATUS Status = AE_OK;
76 ACPI_FUNCTION_TRACE (TbVerifyTable);
79 /* Map the table if necessary */
81 if (!TableDesc->Pointer)
83 if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) ==
84 ACPI_TABLE_ORIGIN_MAPPED)
86 TableDesc->Pointer = AcpiOsMapMemory (
87 TableDesc->Address, TableDesc->Length);
90 if (!TableDesc->Pointer)
92 return_ACPI_STATUS (AE_NO_MEMORY);
96 /* FACS is the odd table, has no standard ACPI header and no checksum */
98 if (!ACPI_COMPARE_NAME (&TableDesc->Signature, ACPI_SIG_FACS))
100 /* Always calculate checksum, ignore bad checksum if requested */
102 Status = AcpiTbVerifyChecksum (TableDesc->Pointer, TableDesc->Length);
105 return_ACPI_STATUS (Status);
109 /*******************************************************************************
111 * FUNCTION: AcpiTbAddTable
113 * PARAMETERS: TableDesc - Table descriptor
114 * TableIndex - Where the table index is returned
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
122 ******************************************************************************/
126 ACPI_TABLE_DESC *TableDesc,
130 ACPI_STATUS Status = AE_OK;
131 ACPI_TABLE_HEADER *OverrideTable = NULL;
134 ACPI_FUNCTION_TRACE (TbAddTable);
137 if (!TableDesc->Pointer)
139 Status = AcpiTbVerifyTable (TableDesc);
140 if (ACPI_FAILURE (Status) || !TableDesc->Pointer)
142 return_ACPI_STATUS (Status);
147 * Validate the incoming table signature.
149 * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
150 * 2) We added support for OEMx tables, signature "OEM".
151 * 3) Valid tables were encountered with a null signature, so we just
152 * gave up on validating the signature, (05/2008).
153 * 4) We encountered non-AML tables such as the MADT, which caused
154 * interpreter errors and kernel faults. So now, we once again allow
155 * only "SSDT", "OEMx", and now, also a null signature. (05/2011).
157 if ((TableDesc->Pointer->Signature[0] != 0x00) &&
158 (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) &&
159 (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3)))
161 ACPI_ERROR ((AE_INFO,
162 "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx",
163 AcpiUtValidAcpiName (*(UINT32 *) TableDesc->Pointer->Signature) ?
164 TableDesc->Pointer->Signature : "????",
165 *(UINT32 *) TableDesc->Pointer->Signature));
167 return_ACPI_STATUS (AE_BAD_SIGNATURE);
170 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
172 /* Check if table is already registered */
174 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
176 if (!AcpiGbl_RootTableList.Tables[i].Pointer)
178 Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]);
179 if (ACPI_FAILURE (Status) ||
180 !AcpiGbl_RootTableList.Tables[i].Pointer)
187 * Check for a table match on the entire table length,
188 * not just the header.
190 if (TableDesc->Length != AcpiGbl_RootTableList.Tables[i].Length)
195 if (ACPI_MEMCMP (TableDesc->Pointer,
196 AcpiGbl_RootTableList.Tables[i].Pointer,
197 AcpiGbl_RootTableList.Tables[i].Length))
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.
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.
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.
218 * Table is already registered.
219 * We can delete the table that was passed as a parameter.
221 AcpiTbDeleteTable (TableDesc);
224 if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED)
226 /* Table is still loaded, this is an error */
228 Status = AE_ALREADY_EXISTS;
233 /* Table was unloaded, allow it to be reloaded */
235 TableDesc->Pointer = AcpiGbl_RootTableList.Tables[i].Pointer;
236 TableDesc->Address = AcpiGbl_RootTableList.Tables[i].Address;
243 * ACPI Table Override:
244 * Allow the host to override dynamically loaded tables.
246 Status = AcpiOsTableOverride (TableDesc->Pointer, &OverrideTable);
247 if (ACPI_SUCCESS (Status) && OverrideTable)
250 "%4.4s @ 0x%p Table override, replaced with:",
251 TableDesc->Pointer->Signature,
252 ACPI_CAST_PTR (void, TableDesc->Address)));
254 /* We can delete the table that was passed as a parameter */
256 AcpiTbDeleteTable (TableDesc);
258 /* Setup descriptor for the new table */
260 TableDesc->Address = ACPI_PTR_TO_PHYSADDR (OverrideTable);
261 TableDesc->Pointer = OverrideTable;
262 TableDesc->Length = OverrideTable->Length;
263 TableDesc->Flags = ACPI_TABLE_ORIGIN_OVERRIDE;
266 /* Add the table to the global root table list */
268 Status = AcpiTbStoreTable (TableDesc->Address, TableDesc->Pointer,
269 TableDesc->Length, TableDesc->Flags, TableIndex);
270 if (ACPI_FAILURE (Status))
276 AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer);
279 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
280 return_ACPI_STATUS (Status);
284 /*******************************************************************************
286 * FUNCTION: AcpiTbResizeRootTableList
292 * DESCRIPTION: Expand the size of global table array
294 ******************************************************************************/
297 AcpiTbResizeRootTableList (
300 ACPI_TABLE_DESC *Tables;
303 ACPI_FUNCTION_TRACE (TbResizeRootTableList);
306 /* AllowResize flag is a parameter to AcpiInitializeTables */
308 if (!(AcpiGbl_RootTableList.Flags & ACPI_ROOT_ALLOW_RESIZE))
310 ACPI_ERROR ((AE_INFO, "Resize of Root Table Array is not allowed"));
311 return_ACPI_STATUS (AE_SUPPORT);
314 /* Increase the Table Array size */
316 Tables = ACPI_ALLOCATE_ZEROED (
317 ((ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount +
318 ACPI_ROOT_TABLE_SIZE_INCREMENT) *
319 sizeof (ACPI_TABLE_DESC));
322 ACPI_ERROR ((AE_INFO, "Could not allocate new root table array"));
323 return_ACPI_STATUS (AE_NO_MEMORY);
326 /* Copy and free the previous table array */
328 if (AcpiGbl_RootTableList.Tables)
330 ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables,
331 (ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount * sizeof (ACPI_TABLE_DESC));
333 if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
335 ACPI_FREE (AcpiGbl_RootTableList.Tables);
339 AcpiGbl_RootTableList.Tables = Tables;
340 AcpiGbl_RootTableList.MaxTableCount += ACPI_ROOT_TABLE_SIZE_INCREMENT;
341 AcpiGbl_RootTableList.Flags |= (UINT8) ACPI_ROOT_ORIGIN_ALLOCATED;
343 return_ACPI_STATUS (AE_OK);
347 /*******************************************************************************
349 * FUNCTION: AcpiTbStoreTable
351 * PARAMETERS: Address - Table address
352 * Table - Table header
353 * Length - Table length
356 * RETURN: Status and table index.
358 * DESCRIPTION: Add an ACPI table to the global table list
360 ******************************************************************************/
364 ACPI_PHYSICAL_ADDRESS Address,
365 ACPI_TABLE_HEADER *Table,
371 ACPI_TABLE_DESC *NewTable;
374 /* Ensure that there is room for the table in the Root Table List */
376 if (AcpiGbl_RootTableList.CurrentTableCount >=
377 AcpiGbl_RootTableList.MaxTableCount)
379 Status = AcpiTbResizeRootTableList();
380 if (ACPI_FAILURE (Status))
386 NewTable = &AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount];
388 /* Initialize added table */
390 NewTable->Address = Address;
391 NewTable->Pointer = Table;
392 NewTable->Length = Length;
393 NewTable->OwnerId = 0;
394 NewTable->Flags = Flags;
396 ACPI_MOVE_32_TO_32 (&NewTable->Signature, Table->Signature);
398 *TableIndex = AcpiGbl_RootTableList.CurrentTableCount;
399 AcpiGbl_RootTableList.CurrentTableCount++;
404 /*******************************************************************************
406 * FUNCTION: AcpiTbDeleteTable
408 * PARAMETERS: TableIndex - Table index
412 * DESCRIPTION: Delete one internal ACPI table
414 ******************************************************************************/
418 ACPI_TABLE_DESC *TableDesc)
421 /* Table must be mapped or allocated */
423 if (!TableDesc->Pointer)
428 switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK)
430 case ACPI_TABLE_ORIGIN_MAPPED:
431 AcpiOsUnmapMemory (TableDesc->Pointer, TableDesc->Length);
434 case ACPI_TABLE_ORIGIN_ALLOCATED:
435 ACPI_FREE (TableDesc->Pointer);
442 TableDesc->Pointer = NULL;
446 /*******************************************************************************
448 * FUNCTION: AcpiTbTerminate
454 * DESCRIPTION: Delete all internal ACPI tables
456 ******************************************************************************/
465 ACPI_FUNCTION_TRACE (TbTerminate);
468 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
470 /* Delete the individual tables */
472 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
474 AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[i]);
478 * Delete the root table array if allocated locally. Array cannot be
479 * mapped, so we don't need to check for that flag.
481 if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
483 ACPI_FREE (AcpiGbl_RootTableList.Tables);
486 AcpiGbl_RootTableList.Tables = NULL;
487 AcpiGbl_RootTableList.Flags = 0;
488 AcpiGbl_RootTableList.CurrentTableCount = 0;
490 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n"));
491 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
495 /*******************************************************************************
497 * FUNCTION: AcpiTbDeleteNamespaceByOwner
499 * PARAMETERS: TableIndex - Table index
503 * DESCRIPTION: Delete all namespace objects created when this table was loaded.
505 ******************************************************************************/
508 AcpiTbDeleteNamespaceByOwner (
511 ACPI_OWNER_ID OwnerId;
515 ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner);
518 Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES);
519 if (ACPI_FAILURE (Status))
521 return_ACPI_STATUS (Status);
524 if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
526 /* The table index does not exist */
528 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
529 return_ACPI_STATUS (AE_NOT_EXIST);
532 /* Get the owner ID for this table, used to delete namespace nodes */
534 OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
535 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
538 * Need to acquire the namespace writer lock to prevent interference
539 * with any concurrent namespace walks. The interpreter must be
540 * released during the deletion since the acquisition of the deletion
541 * lock may block, and also since the execution of a namespace walk
542 * must be allowed to use the interpreter.
544 (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER);
545 Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock);
547 AcpiNsDeleteNamespaceByOwner (OwnerId);
548 if (ACPI_FAILURE (Status))
550 return_ACPI_STATUS (Status);
553 AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock);
555 Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER);
556 return_ACPI_STATUS (Status);
560 /*******************************************************************************
562 * FUNCTION: AcpiTbAllocateOwnerId
564 * PARAMETERS: TableIndex - Table index
568 * DESCRIPTION: Allocates OwnerId in TableDesc
570 ******************************************************************************/
573 AcpiTbAllocateOwnerId (
576 ACPI_STATUS Status = AE_BAD_PARAMETER;
579 ACPI_FUNCTION_TRACE (TbAllocateOwnerId);
582 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
583 if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
585 Status = AcpiUtAllocateOwnerId
586 (&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
589 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
590 return_ACPI_STATUS (Status);
594 /*******************************************************************************
596 * FUNCTION: AcpiTbReleaseOwnerId
598 * PARAMETERS: TableIndex - Table index
602 * DESCRIPTION: Releases OwnerId in TableDesc
604 ******************************************************************************/
607 AcpiTbReleaseOwnerId (
610 ACPI_STATUS Status = AE_BAD_PARAMETER;
613 ACPI_FUNCTION_TRACE (TbReleaseOwnerId);
616 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
617 if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
619 AcpiUtReleaseOwnerId (
620 &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId));
624 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
625 return_ACPI_STATUS (Status);
629 /*******************************************************************************
631 * FUNCTION: AcpiTbGetOwnerId
633 * PARAMETERS: TableIndex - Table index
634 * OwnerId - Where the table OwnerId is returned
638 * DESCRIPTION: returns OwnerId for the ACPI table
640 ******************************************************************************/
645 ACPI_OWNER_ID *OwnerId)
647 ACPI_STATUS Status = AE_BAD_PARAMETER;
650 ACPI_FUNCTION_TRACE (TbGetOwnerId);
653 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
654 if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
656 *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId;
660 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
661 return_ACPI_STATUS (Status);
665 /*******************************************************************************
667 * FUNCTION: AcpiTbIsTableLoaded
669 * PARAMETERS: TableIndex - Table index
671 * RETURN: Table Loaded Flag
673 ******************************************************************************/
676 AcpiTbIsTableLoaded (
679 BOOLEAN IsLoaded = FALSE;
682 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
683 if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
686 (AcpiGbl_RootTableList.Tables[TableIndex].Flags &
687 ACPI_TABLE_IS_LOADED);
690 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
695 /*******************************************************************************
697 * FUNCTION: AcpiTbSetTableLoadedFlag
699 * PARAMETERS: TableIndex - Table index
700 * IsLoaded - TRUE if table is loaded, FALSE otherwise
704 * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
706 ******************************************************************************/
709 AcpiTbSetTableLoadedFlag (
714 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
715 if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount)
719 AcpiGbl_RootTableList.Tables[TableIndex].Flags |=
720 ACPI_TABLE_IS_LOADED;
724 AcpiGbl_RootTableList.Tables[TableIndex].Flags &=
725 ~ACPI_TABLE_IS_LOADED;
729 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);