1 /******************************************************************************
3 * Module Name: tbinstal - ACPI table installation and removal
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2013, 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__
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 /* Always calculate checksum, ignore bad checksum if requested */
98 Status
= AcpiTbVerifyChecksum (TableDesc
->Pointer
, TableDesc
->Length
);
100 return_ACPI_STATUS (Status
);
104 /*******************************************************************************
106 * FUNCTION: AcpiTbAddTable
108 * PARAMETERS: TableDesc - Table descriptor
109 * TableIndex - Where the table index is returned
113 * DESCRIPTION: This function is called to add an ACPI table. It is used to
114 * dynamically load tables via the Load and LoadTable AML
117 ******************************************************************************/
121 ACPI_TABLE_DESC
*TableDesc
,
125 ACPI_STATUS Status
= AE_OK
;
128 ACPI_FUNCTION_TRACE (TbAddTable
);
131 if (!TableDesc
->Pointer
)
133 Status
= AcpiTbVerifyTable (TableDesc
);
134 if (ACPI_FAILURE (Status
) || !TableDesc
->Pointer
)
136 return_ACPI_STATUS (Status
);
141 * Validate the incoming table signature.
143 * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
144 * 2) We added support for OEMx tables, signature "OEM".
145 * 3) Valid tables were encountered with a null signature, so we just
146 * gave up on validating the signature, (05/2008).
147 * 4) We encountered non-AML tables such as the MADT, which caused
148 * interpreter errors and kernel faults. So now, we once again allow
149 * only "SSDT", "OEMx", and now, also a null signature. (05/2011).
151 if ((TableDesc
->Pointer
->Signature
[0] != 0x00) &&
152 (!ACPI_COMPARE_NAME (TableDesc
->Pointer
->Signature
, ACPI_SIG_SSDT
)) &&
153 (ACPI_STRNCMP (TableDesc
->Pointer
->Signature
, "OEM", 3)))
155 ACPI_BIOS_ERROR ((AE_INFO
,
156 "Table has invalid signature [%4.4s] (0x%8.8X), "
157 "must be SSDT or OEMx",
158 AcpiUtValidAcpiName (TableDesc
->Pointer
->Signature
) ?
159 TableDesc
->Pointer
->Signature
: "????",
160 *(UINT32
*) TableDesc
->Pointer
->Signature
));
162 return_ACPI_STATUS (AE_BAD_SIGNATURE
);
165 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES
);
167 /* Check if table is already registered */
169 for (i
= 0; i
< AcpiGbl_RootTableList
.CurrentTableCount
; ++i
)
171 if (!AcpiGbl_RootTableList
.Tables
[i
].Pointer
)
173 Status
= AcpiTbVerifyTable (&AcpiGbl_RootTableList
.Tables
[i
]);
174 if (ACPI_FAILURE (Status
) ||
175 !AcpiGbl_RootTableList
.Tables
[i
].Pointer
)
182 * Check for a table match on the entire table length,
183 * not just the header.
185 if (TableDesc
->Length
!= AcpiGbl_RootTableList
.Tables
[i
].Length
)
190 if (ACPI_MEMCMP (TableDesc
->Pointer
,
191 AcpiGbl_RootTableList
.Tables
[i
].Pointer
,
192 AcpiGbl_RootTableList
.Tables
[i
].Length
))
198 * Note: the current mechanism does not unregister a table if it is
199 * dynamically unloaded. The related namespace entries are deleted,
200 * but the table remains in the root table list.
202 * The assumption here is that the number of different tables that
203 * will be loaded is actually small, and there is minimal overhead
204 * in just keeping the table in case it is needed again.
206 * If this assumption changes in the future (perhaps on large
207 * machines with many table load/unload operations), tables will
208 * need to be unregistered when they are unloaded, and slots in the
209 * root table list should be reused when empty.
213 * Table is already registered.
214 * We can delete the table that was passed as a parameter.
216 AcpiTbDeleteTable (TableDesc
);
219 if (AcpiGbl_RootTableList
.Tables
[i
].Flags
& ACPI_TABLE_IS_LOADED
)
221 /* Table is still loaded, this is an error */
223 Status
= AE_ALREADY_EXISTS
;
228 /* Table was unloaded, allow it to be reloaded */
230 TableDesc
->Pointer
= AcpiGbl_RootTableList
.Tables
[i
].Pointer
;
231 TableDesc
->Address
= AcpiGbl_RootTableList
.Tables
[i
].Address
;
238 * ACPI Table Override:
239 * Allow the host to override dynamically loaded tables.
240 * NOTE: the table is fully mapped at this point, and the mapping will
241 * be deleted by TbTableOverride if the table is actually overridden.
243 (void) AcpiTbTableOverride (TableDesc
->Pointer
, TableDesc
);
245 /* Add the table to the global root table list */
247 Status
= AcpiTbStoreTable (TableDesc
->Address
, TableDesc
->Pointer
,
248 TableDesc
->Length
, TableDesc
->Flags
, TableIndex
);
249 if (ACPI_FAILURE (Status
))
255 AcpiTbPrintTableHeader (TableDesc
->Address
, TableDesc
->Pointer
);
258 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES
);
259 return_ACPI_STATUS (Status
);
263 /*******************************************************************************
265 * FUNCTION: AcpiTbTableOverride
267 * PARAMETERS: TableHeader - Header for the original table
268 * TableDesc - Table descriptor initialized for the
269 * original table. May or may not be mapped.
271 * RETURN: Pointer to the entire new table. NULL if table not overridden.
272 * If overridden, installs the new table within the input table
275 * DESCRIPTION: Attempt table override by calling the OSL override functions.
276 * Note: If the table is overridden, then the entire new table
277 * is mapped and returned by this function.
279 ******************************************************************************/
282 AcpiTbTableOverride (
283 ACPI_TABLE_HEADER
*TableHeader
,
284 ACPI_TABLE_DESC
*TableDesc
)
287 ACPI_TABLE_HEADER
*NewTable
= NULL
;
288 ACPI_PHYSICAL_ADDRESS NewAddress
= 0;
289 UINT32 NewTableLength
= 0;
294 /* (1) Attempt logical override (returns a logical address) */
296 Status
= AcpiOsTableOverride (TableHeader
, &NewTable
);
297 if (ACPI_SUCCESS (Status
) && NewTable
)
299 NewAddress
= ACPI_PTR_TO_PHYSADDR (NewTable
);
300 NewTableLength
= NewTable
->Length
;
301 NewFlags
= ACPI_TABLE_ORIGIN_OVERRIDE
;
302 OverrideType
= "Logical";
306 /* (2) Attempt physical override (returns a physical address) */
308 Status
= AcpiOsPhysicalTableOverride (TableHeader
,
309 &NewAddress
, &NewTableLength
);
310 if (ACPI_SUCCESS (Status
) && NewAddress
&& NewTableLength
)
312 /* Map the entire new table */
314 NewTable
= AcpiOsMapMemory (NewAddress
, NewTableLength
);
317 ACPI_EXCEPTION ((AE_INFO
, AE_NO_MEMORY
,
318 "%4.4s %p Attempted physical table override failed",
319 TableHeader
->Signature
,
320 ACPI_CAST_PTR (void, TableDesc
->Address
)));
324 OverrideType
= "Physical";
325 NewFlags
= ACPI_TABLE_ORIGIN_MAPPED
;
329 return (NULL
); /* There was no override */
335 "%4.4s %p %s table override, new table: %p",
336 TableHeader
->Signature
,
337 ACPI_CAST_PTR (void, TableDesc
->Address
),
338 OverrideType
, NewTable
));
340 /* We can now unmap/delete the original table (if fully mapped) */
342 AcpiTbDeleteTable (TableDesc
);
344 /* Setup descriptor for the new table */
346 TableDesc
->Address
= NewAddress
;
347 TableDesc
->Pointer
= NewTable
;
348 TableDesc
->Length
= NewTableLength
;
349 TableDesc
->Flags
= NewFlags
;
355 /*******************************************************************************
357 * FUNCTION: AcpiTbResizeRootTableList
363 * DESCRIPTION: Expand the size of global table array
365 ******************************************************************************/
368 AcpiTbResizeRootTableList (
371 ACPI_TABLE_DESC
*Tables
;
375 ACPI_FUNCTION_TRACE (TbResizeRootTableList
);
378 /* AllowResize flag is a parameter to AcpiInitializeTables */
380 if (!(AcpiGbl_RootTableList
.Flags
& ACPI_ROOT_ALLOW_RESIZE
))
382 ACPI_ERROR ((AE_INFO
, "Resize of Root Table Array is not allowed"));
383 return_ACPI_STATUS (AE_SUPPORT
);
386 /* Increase the Table Array size */
388 if (AcpiGbl_RootTableList
.Flags
& ACPI_ROOT_ORIGIN_ALLOCATED
)
390 TableCount
= AcpiGbl_RootTableList
.MaxTableCount
;
394 TableCount
= AcpiGbl_RootTableList
.CurrentTableCount
;
397 Tables
= ACPI_ALLOCATE_ZEROED (
398 ((ACPI_SIZE
) TableCount
+ ACPI_ROOT_TABLE_SIZE_INCREMENT
) *
399 sizeof (ACPI_TABLE_DESC
));
402 ACPI_ERROR ((AE_INFO
, "Could not allocate new root table array"));
403 return_ACPI_STATUS (AE_NO_MEMORY
);
406 /* Copy and free the previous table array */
408 if (AcpiGbl_RootTableList
.Tables
)
410 ACPI_MEMCPY (Tables
, AcpiGbl_RootTableList
.Tables
,
411 (ACPI_SIZE
) TableCount
* sizeof (ACPI_TABLE_DESC
));
413 if (AcpiGbl_RootTableList
.Flags
& ACPI_ROOT_ORIGIN_ALLOCATED
)
415 ACPI_FREE (AcpiGbl_RootTableList
.Tables
);
419 AcpiGbl_RootTableList
.Tables
= Tables
;
420 AcpiGbl_RootTableList
.MaxTableCount
=
421 TableCount
+ ACPI_ROOT_TABLE_SIZE_INCREMENT
;
422 AcpiGbl_RootTableList
.Flags
|= ACPI_ROOT_ORIGIN_ALLOCATED
;
424 return_ACPI_STATUS (AE_OK
);
428 /*******************************************************************************
430 * FUNCTION: AcpiTbStoreTable
432 * PARAMETERS: Address - Table address
433 * Table - Table header
434 * Length - Table length
437 * RETURN: Status and table index.
439 * DESCRIPTION: Add an ACPI table to the global table list
441 ******************************************************************************/
445 ACPI_PHYSICAL_ADDRESS Address
,
446 ACPI_TABLE_HEADER
*Table
,
452 ACPI_TABLE_DESC
*NewTable
;
455 /* Ensure that there is room for the table in the Root Table List */
457 if (AcpiGbl_RootTableList
.CurrentTableCount
>=
458 AcpiGbl_RootTableList
.MaxTableCount
)
460 Status
= AcpiTbResizeRootTableList();
461 if (ACPI_FAILURE (Status
))
467 NewTable
= &AcpiGbl_RootTableList
.Tables
[AcpiGbl_RootTableList
.CurrentTableCount
];
469 /* Initialize added table */
471 NewTable
->Address
= Address
;
472 NewTable
->Pointer
= Table
;
473 NewTable
->Length
= Length
;
474 NewTable
->OwnerId
= 0;
475 NewTable
->Flags
= Flags
;
477 ACPI_MOVE_32_TO_32 (&NewTable
->Signature
, Table
->Signature
);
479 *TableIndex
= AcpiGbl_RootTableList
.CurrentTableCount
;
480 AcpiGbl_RootTableList
.CurrentTableCount
++;
485 /*******************************************************************************
487 * FUNCTION: AcpiTbDeleteTable
489 * PARAMETERS: TableIndex - Table index
493 * DESCRIPTION: Delete one internal ACPI table
495 ******************************************************************************/
499 ACPI_TABLE_DESC
*TableDesc
)
502 /* Table must be mapped or allocated */
504 if (!TableDesc
->Pointer
)
509 switch (TableDesc
->Flags
& ACPI_TABLE_ORIGIN_MASK
)
511 case ACPI_TABLE_ORIGIN_MAPPED
:
513 AcpiOsUnmapMemory (TableDesc
->Pointer
, TableDesc
->Length
);
516 case ACPI_TABLE_ORIGIN_ALLOCATED
:
518 ACPI_FREE (TableDesc
->Pointer
);
521 /* Not mapped or allocated, there is nothing we can do */
528 TableDesc
->Pointer
= NULL
;
532 /*******************************************************************************
534 * FUNCTION: AcpiTbTerminate
540 * DESCRIPTION: Delete all internal ACPI tables
542 ******************************************************************************/
551 ACPI_FUNCTION_TRACE (TbTerminate
);
554 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES
);
556 /* Delete the individual tables */
558 for (i
= 0; i
< AcpiGbl_RootTableList
.CurrentTableCount
; i
++)
560 AcpiTbDeleteTable (&AcpiGbl_RootTableList
.Tables
[i
]);
564 * Delete the root table array if allocated locally. Array cannot be
565 * mapped, so we don't need to check for that flag.
567 if (AcpiGbl_RootTableList
.Flags
& ACPI_ROOT_ORIGIN_ALLOCATED
)
569 ACPI_FREE (AcpiGbl_RootTableList
.Tables
);
572 AcpiGbl_RootTableList
.Tables
= NULL
;
573 AcpiGbl_RootTableList
.Flags
= 0;
574 AcpiGbl_RootTableList
.CurrentTableCount
= 0;
576 ACPI_DEBUG_PRINT ((ACPI_DB_INFO
, "ACPI Tables freed\n"));
577 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES
);
583 /*******************************************************************************
585 * FUNCTION: AcpiTbDeleteNamespaceByOwner
587 * PARAMETERS: TableIndex - Table index
591 * DESCRIPTION: Delete all namespace objects created when this table was loaded.
593 ******************************************************************************/
596 AcpiTbDeleteNamespaceByOwner (
599 ACPI_OWNER_ID OwnerId
;
603 ACPI_FUNCTION_TRACE (TbDeleteNamespaceByOwner
);
606 Status
= AcpiUtAcquireMutex (ACPI_MTX_TABLES
);
607 if (ACPI_FAILURE (Status
))
609 return_ACPI_STATUS (Status
);
612 if (TableIndex
>= AcpiGbl_RootTableList
.CurrentTableCount
)
614 /* The table index does not exist */
616 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES
);
617 return_ACPI_STATUS (AE_NOT_EXIST
);
620 /* Get the owner ID for this table, used to delete namespace nodes */
622 OwnerId
= AcpiGbl_RootTableList
.Tables
[TableIndex
].OwnerId
;
623 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES
);
626 * Need to acquire the namespace writer lock to prevent interference
627 * with any concurrent namespace walks. The interpreter must be
628 * released during the deletion since the acquisition of the deletion
629 * lock may block, and also since the execution of a namespace walk
630 * must be allowed to use the interpreter.
632 (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER
);
633 Status
= AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock
);
635 AcpiNsDeleteNamespaceByOwner (OwnerId
);
636 if (ACPI_FAILURE (Status
))
638 return_ACPI_STATUS (Status
);
641 AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock
);
643 Status
= AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER
);
644 return_ACPI_STATUS (Status
);
648 /*******************************************************************************
650 * FUNCTION: AcpiTbAllocateOwnerId
652 * PARAMETERS: TableIndex - Table index
656 * DESCRIPTION: Allocates OwnerId in TableDesc
658 ******************************************************************************/
661 AcpiTbAllocateOwnerId (
664 ACPI_STATUS Status
= AE_BAD_PARAMETER
;
667 ACPI_FUNCTION_TRACE (TbAllocateOwnerId
);
670 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES
);
671 if (TableIndex
< AcpiGbl_RootTableList
.CurrentTableCount
)
673 Status
= AcpiUtAllocateOwnerId
674 (&(AcpiGbl_RootTableList
.Tables
[TableIndex
].OwnerId
));
677 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES
);
678 return_ACPI_STATUS (Status
);
682 /*******************************************************************************
684 * FUNCTION: AcpiTbReleaseOwnerId
686 * PARAMETERS: TableIndex - Table index
690 * DESCRIPTION: Releases OwnerId in TableDesc
692 ******************************************************************************/
695 AcpiTbReleaseOwnerId (
698 ACPI_STATUS Status
= AE_BAD_PARAMETER
;
701 ACPI_FUNCTION_TRACE (TbReleaseOwnerId
);
704 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES
);
705 if (TableIndex
< AcpiGbl_RootTableList
.CurrentTableCount
)
707 AcpiUtReleaseOwnerId (
708 &(AcpiGbl_RootTableList
.Tables
[TableIndex
].OwnerId
));
712 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES
);
713 return_ACPI_STATUS (Status
);
717 /*******************************************************************************
719 * FUNCTION: AcpiTbGetOwnerId
721 * PARAMETERS: TableIndex - Table index
722 * OwnerId - Where the table OwnerId is returned
726 * DESCRIPTION: returns OwnerId for the ACPI table
728 ******************************************************************************/
733 ACPI_OWNER_ID
*OwnerId
)
735 ACPI_STATUS Status
= AE_BAD_PARAMETER
;
738 ACPI_FUNCTION_TRACE (TbGetOwnerId
);
741 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES
);
742 if (TableIndex
< AcpiGbl_RootTableList
.CurrentTableCount
)
744 *OwnerId
= AcpiGbl_RootTableList
.Tables
[TableIndex
].OwnerId
;
748 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES
);
749 return_ACPI_STATUS (Status
);
753 /*******************************************************************************
755 * FUNCTION: AcpiTbIsTableLoaded
757 * PARAMETERS: TableIndex - Table index
759 * RETURN: Table Loaded Flag
761 ******************************************************************************/
764 AcpiTbIsTableLoaded (
767 BOOLEAN IsLoaded
= FALSE
;
770 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES
);
771 if (TableIndex
< AcpiGbl_RootTableList
.CurrentTableCount
)
774 (AcpiGbl_RootTableList
.Tables
[TableIndex
].Flags
&
775 ACPI_TABLE_IS_LOADED
);
778 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES
);
783 /*******************************************************************************
785 * FUNCTION: AcpiTbSetTableLoadedFlag
787 * PARAMETERS: TableIndex - Table index
788 * IsLoaded - TRUE if table is loaded, FALSE otherwise
792 * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
794 ******************************************************************************/
797 AcpiTbSetTableLoadedFlag (
802 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES
);
803 if (TableIndex
< AcpiGbl_RootTableList
.CurrentTableCount
)
807 AcpiGbl_RootTableList
.Tables
[TableIndex
].Flags
|=
808 ACPI_TABLE_IS_LOADED
;
812 AcpiGbl_RootTableList
.Tables
[TableIndex
].Flags
&=
813 ~ACPI_TABLE_IS_LOADED
;
817 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES
);