tbinstal.c revision 281396
1132718Skan/****************************************************************************** 2117395Skan * 318334Speter * Module Name: tbinstal - ACPI table installation and removal 418334Speter * 518334Speter *****************************************************************************/ 6132718Skan 718334Speter/* 8132718Skan * Copyright (C) 2000 - 2015, Intel Corp. 918334Speter * All rights reserved. 1018334Speter * 1118334Speter * Redistribution and use in source and binary forms, with or without 1218334Speter * modification, are permitted provided that the following conditions 13132718Skan * are met: 1418334Speter * 1. Redistributions of source code must retain the above copyright 1518334Speter * notice, this list of conditions, and the following disclaimer, 1618334Speter * without modification. 1718334Speter * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1818334Speter * substantially similar to the "NO WARRANTY" disclaimer below 19132718Skan * ("Disclaimer") and any redistribution must be conditioned upon 20169689Skan * including a substantially similar Disclaimer requirement for further 21169689Skan * binary redistribution. 2218334Speter * 3. Neither the names of the above-listed copyright holders nor the names 2318334Speter * of any contributors may be used to endorse or promote products derived 2418334Speter * from this software without specific prior written permission. 2518334Speter * 2618334Speter * Alternatively, this software may be distributed under the terms of the 2718334Speter * GNU General Public License ("GPL") version 2 as published by the Free 2818334Speter * Software Foundation. 2918334Speter * 3018334Speter * NO WARRANTY 3190075Sobrien * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3290075Sobrien * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3318334Speter * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3418334Speter * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3518334Speter * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3618334Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37132718Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38132718Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39132718Skan * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4018334Speter * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4118334Speter * POSSIBILITY OF SUCH DAMAGES. 4290075Sobrien */ 4318334Speter 4418334Speter#include <contrib/dev/acpica/include/acpi.h> 4518334Speter#include <contrib/dev/acpica/include/accommon.h> 4618334Speter#include <contrib/dev/acpica/include/actables.h> 4718334Speter 4818334Speter#define _COMPONENT ACPI_TABLES 4918334Speter ACPI_MODULE_NAME ("tbinstal") 5018334Speter 5118334Speter/* Local prototypes */ 5218334Speter 5318334Speterstatic BOOLEAN 5418334SpeterAcpiTbCompareTables ( 55132718Skan ACPI_TABLE_DESC *TableDesc, 5690075Sobrien UINT32 TableIndex); 57132718Skan 58132718Skan 5918334Speter/******************************************************************************* 6018334Speter * 61132718Skan * FUNCTION: AcpiTbCompareTables 6218334Speter * 6318334Speter * PARAMETERS: TableDesc - Table 1 descriptor to be compared 6418334Speter * TableIndex - Index of table 2 to be compared 6518334Speter * 6618334Speter * RETURN: TRUE if both tables are identical. 6718334Speter * 6818334Speter * DESCRIPTION: This function compares a table with another table that has 6990075Sobrien * already been installed in the root table list. 7018334Speter * 7118334Speter ******************************************************************************/ 7218334Speter 7318334Speterstatic BOOLEAN 7418334SpeterAcpiTbCompareTables ( 7518334Speter ACPI_TABLE_DESC *TableDesc, 7618334Speter UINT32 TableIndex) 7718334Speter{ 7818334Speter ACPI_STATUS Status = AE_OK; 7918334Speter BOOLEAN IsIdentical; 8018334Speter ACPI_TABLE_HEADER *Table; 8118334Speter UINT32 TableLength; 8218334Speter UINT8 TableFlags; 8318334Speter 8418334Speter 8518334Speter Status = AcpiTbAcquireTable (&AcpiGbl_RootTableList.Tables[TableIndex], 8618334Speter &Table, &TableLength, &TableFlags); 8718334Speter if (ACPI_FAILURE (Status)) 8818334Speter { 8918334Speter return (FALSE); 9018334Speter } 9118334Speter 9218334Speter /* 9318334Speter * Check for a table match on the entire table length, 9450397Sobrien * not just the header. 9550397Sobrien */ 9650397Sobrien IsIdentical = (BOOLEAN)((TableDesc->Length != TableLength || 9750397Sobrien ACPI_MEMCMP (TableDesc->Pointer, Table, TableLength)) ? 9850397Sobrien FALSE : TRUE); 9950397Sobrien 10050397Sobrien /* Release the acquired table */ 10190075Sobrien 10290075Sobrien AcpiTbReleaseTable (Table, TableLength, TableFlags); 10390075Sobrien return (IsIdentical); 10490075Sobrien} 10590075Sobrien 10690075Sobrien 10790075Sobrien/******************************************************************************* 10890075Sobrien * 10990075Sobrien * FUNCTION: AcpiTbInstallTableWithOverride 11090075Sobrien * 11190075Sobrien * PARAMETERS: TableIndex - Index into root table array 11290075Sobrien * NewTableDesc - New table descriptor to install 11390075Sobrien * Override - Whether override should be performed 11490075Sobrien * 11590075Sobrien * RETURN: None 11690075Sobrien * 11790075Sobrien * DESCRIPTION: Install an ACPI table into the global data structure. The 11890075Sobrien * table override mechanism is called to allow the host 11990075Sobrien * OS to replace any table before it is installed in the root 12090075Sobrien * table array. 12190075Sobrien * 12290075Sobrien ******************************************************************************/ 12390075Sobrien 12490075Sobrienvoid 12590075SobrienAcpiTbInstallTableWithOverride ( 12690075Sobrien UINT32 TableIndex, 12790075Sobrien ACPI_TABLE_DESC *NewTableDesc, 12890075Sobrien BOOLEAN Override) 12990075Sobrien{ 13090075Sobrien 13190075Sobrien if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount) 13290075Sobrien { 13390075Sobrien return; 134 } 135 136 /* 137 * ACPI Table Override: 138 * 139 * Before we install the table, let the host OS override it with a new 140 * one if desired. Any table within the RSDT/XSDT can be replaced, 141 * including the DSDT which is pointed to by the FADT. 142 */ 143 if (Override) 144 { 145 AcpiTbOverrideTable (NewTableDesc); 146 } 147 148 AcpiTbInitTableDescriptor (&AcpiGbl_RootTableList.Tables[TableIndex], 149 NewTableDesc->Address, NewTableDesc->Flags, NewTableDesc->Pointer); 150 151 AcpiTbPrintTableHeader (NewTableDesc->Address, NewTableDesc->Pointer); 152 153 /* Set the global integer width (based upon revision of the DSDT) */ 154 155 if (TableIndex == ACPI_TABLE_INDEX_DSDT) 156 { 157 AcpiUtSetIntegerWidth (NewTableDesc->Pointer->Revision); 158 } 159} 160 161 162/******************************************************************************* 163 * 164 * FUNCTION: AcpiTbInstallFixedTable 165 * 166 * PARAMETERS: Address - Physical address of DSDT or FACS 167 * Signature - Table signature, NULL if no need to 168 * match 169 * TableIndex - Index into root table array 170 * 171 * RETURN: Status 172 * 173 * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data 174 * structure. 175 * 176 ******************************************************************************/ 177 178ACPI_STATUS 179AcpiTbInstallFixedTable ( 180 ACPI_PHYSICAL_ADDRESS Address, 181 char *Signature, 182 UINT32 TableIndex) 183{ 184 ACPI_TABLE_DESC NewTableDesc; 185 ACPI_STATUS Status; 186 187 188 ACPI_FUNCTION_TRACE (TbInstallFixedTable); 189 190 191 if (!Address) 192 { 193 ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]", 194 Signature)); 195 return (AE_NO_MEMORY); 196 } 197 198 /* Fill a table descriptor for validation */ 199 200 Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, 201 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); 202 if (ACPI_FAILURE (Status)) 203 { 204 ACPI_ERROR ((AE_INFO, "Could not acquire table length at %8.8X%8.8X", 205 ACPI_FORMAT_UINT64 (Address))); 206 return_ACPI_STATUS (Status); 207 } 208 209 /* Validate and verify a table before installation */ 210 211 Status = AcpiTbVerifyTempTable (&NewTableDesc, Signature); 212 if (ACPI_FAILURE (Status)) 213 { 214 goto ReleaseAndExit; 215 } 216 217 AcpiTbInstallTableWithOverride (TableIndex, &NewTableDesc, TRUE); 218 219ReleaseAndExit: 220 221 /* Release the temporary table descriptor */ 222 223 AcpiTbReleaseTempTable (&NewTableDesc); 224 return_ACPI_STATUS (Status); 225} 226 227 228/******************************************************************************* 229 * 230 * FUNCTION: AcpiTbInstallStandardTable 231 * 232 * PARAMETERS: Address - Address of the table (might be a virtual 233 * address depending on the TableFlags) 234 * Flags - Flags for the table 235 * Reload - Whether reload should be performed 236 * Override - Whether override should be performed 237 * TableIndex - Where the table index is returned 238 * 239 * RETURN: Status 240 * 241 * DESCRIPTION: This function is called to install an ACPI table that is 242 * neither DSDT nor FACS (a "standard" table.) 243 * When this function is called by "Load" or "LoadTable" opcodes, 244 * or by AcpiLoadTable() API, the "Reload" parameter is set. 245 * After sucessfully returning from this function, table is 246 * "INSTALLED" but not "VALIDATED". 247 * 248 ******************************************************************************/ 249 250ACPI_STATUS 251AcpiTbInstallStandardTable ( 252 ACPI_PHYSICAL_ADDRESS Address, 253 UINT8 Flags, 254 BOOLEAN Reload, 255 BOOLEAN Override, 256 UINT32 *TableIndex) 257{ 258 UINT32 i; 259 ACPI_STATUS Status = AE_OK; 260 ACPI_TABLE_DESC NewTableDesc; 261 262 263 ACPI_FUNCTION_TRACE (TbInstallStandardTable); 264 265 266 /* Acquire a temporary table descriptor for validation */ 267 268 Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, Flags); 269 if (ACPI_FAILURE (Status)) 270 { 271 ACPI_ERROR ((AE_INFO, "Could not acquire table length at %8.8X%8.8X", 272 ACPI_FORMAT_UINT64 (Address))); 273 return_ACPI_STATUS (Status); 274 } 275 276 /* 277 * Optionally do not load any SSDTs from the RSDT/XSDT. This can 278 * be useful for debugging ACPI problems on some machines. 279 */ 280 if (!Reload && 281 AcpiGbl_DisableSsdtTableInstall && 282 ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT)) 283 { 284 ACPI_INFO ((AE_INFO, "Ignoring installation of %4.4s at %8.8X%8.8X", 285 NewTableDesc.Signature.Ascii, ACPI_FORMAT_UINT64 (Address))); 286 goto ReleaseAndExit; 287 } 288 289 /* Validate and verify a table before installation */ 290 291 Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL); 292 if (ACPI_FAILURE (Status)) 293 { 294 goto ReleaseAndExit; 295 } 296 297 if (Reload) 298 { 299 /* 300 * Validate the incoming table signature. 301 * 302 * 1) Originally, we checked the table signature for "SSDT" or "PSDT". 303 * 2) We added support for OEMx tables, signature "OEM". 304 * 3) Valid tables were encountered with a null signature, so we just 305 * gave up on validating the signature, (05/2008). 306 * 4) We encountered non-AML tables such as the MADT, which caused 307 * interpreter errors and kernel faults. So now, we once again allow 308 * only "SSDT", "OEMx", and now, also a null signature. (05/2011). 309 */ 310 if ((NewTableDesc.Signature.Ascii[0] != 0x00) && 311 (!ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT)) && 312 (ACPI_STRNCMP (NewTableDesc.Signature.Ascii, "OEM", 3))) 313 { 314 ACPI_BIOS_ERROR ((AE_INFO, 315 "Table has invalid signature [%4.4s] (0x%8.8X), " 316 "must be SSDT or OEMx", 317 AcpiUtValidAcpiName (NewTableDesc.Signature.Ascii) ? 318 NewTableDesc.Signature.Ascii : "????", 319 NewTableDesc.Signature.Integer)); 320 321 Status = AE_BAD_SIGNATURE; 322 goto ReleaseAndExit; 323 } 324 325 /* Check if table is already registered */ 326 327 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) 328 { 329 /* 330 * Check for a table match on the entire table length, 331 * not just the header. 332 */ 333 if (!AcpiTbCompareTables (&NewTableDesc, i)) 334 { 335 continue; 336 } 337 338 /* 339 * Note: the current mechanism does not unregister a table if it is 340 * dynamically unloaded. The related namespace entries are deleted, 341 * but the table remains in the root table list. 342 * 343 * The assumption here is that the number of different tables that 344 * will be loaded is actually small, and there is minimal overhead 345 * in just keeping the table in case it is needed again. 346 * 347 * If this assumption changes in the future (perhaps on large 348 * machines with many table load/unload operations), tables will 349 * need to be unregistered when they are unloaded, and slots in the 350 * root table list should be reused when empty. 351 */ 352 if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED) 353 { 354 /* Table is still loaded, this is an error */ 355 356 Status = AE_ALREADY_EXISTS; 357 goto ReleaseAndExit; 358 } 359 else 360 { 361 /* 362 * Table was unloaded, allow it to be reloaded. 363 * As we are going to return AE_OK to the caller, we should 364 * take the responsibility of freeing the input descriptor. 365 * Refill the input descriptor to ensure 366 * AcpiTbInstallTableWithOverride() can be called again to 367 * indicate the re-installation. 368 */ 369 AcpiTbUninstallTable (&NewTableDesc); 370 *TableIndex = i; 371 return_ACPI_STATUS (AE_OK); 372 } 373 } 374 } 375 376 /* Add the table to the global root table list */ 377 378 Status = AcpiTbGetNextTableDescriptor (&i, NULL); 379 if (ACPI_FAILURE (Status)) 380 { 381 goto ReleaseAndExit; 382 } 383 384 *TableIndex = i; 385 AcpiTbInstallTableWithOverride (i, &NewTableDesc, Override); 386 387ReleaseAndExit: 388 389 /* Release the temporary table descriptor */ 390 391 AcpiTbReleaseTempTable (&NewTableDesc); 392 return_ACPI_STATUS (Status); 393} 394 395 396/******************************************************************************* 397 * 398 * FUNCTION: AcpiTbOverrideTable 399 * 400 * PARAMETERS: OldTableDesc - Validated table descriptor to be 401 * overridden 402 * 403 * RETURN: None 404 * 405 * DESCRIPTION: Attempt table override by calling the OSL override functions. 406 * Note: If the table is overridden, then the entire new table 407 * is acquired and returned by this function. 408 * Before/after invocation, the table descriptor is in a state 409 * that is "VALIDATED". 410 * 411 ******************************************************************************/ 412 413void 414AcpiTbOverrideTable ( 415 ACPI_TABLE_DESC *OldTableDesc) 416{ 417 ACPI_STATUS Status; 418 char *OverrideType; 419 ACPI_TABLE_DESC NewTableDesc; 420 ACPI_TABLE_HEADER *Table; 421 ACPI_PHYSICAL_ADDRESS Address; 422 UINT32 Length; 423 424 425 /* (1) Attempt logical override (returns a logical address) */ 426 427 Status = AcpiOsTableOverride (OldTableDesc->Pointer, &Table); 428 if (ACPI_SUCCESS (Status) && Table) 429 { 430 AcpiTbAcquireTempTable (&NewTableDesc, ACPI_PTR_TO_PHYSADDR (Table), 431 ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); 432 OverrideType = "Logical"; 433 goto FinishOverride; 434 } 435 436 /* (2) Attempt physical override (returns a physical address) */ 437 438 Status = AcpiOsPhysicalTableOverride (OldTableDesc->Pointer, 439 &Address, &Length); 440 if (ACPI_SUCCESS (Status) && Address && Length) 441 { 442 AcpiTbAcquireTempTable (&NewTableDesc, Address, 443 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); 444 OverrideType = "Physical"; 445 goto FinishOverride; 446 } 447 448 return; /* There was no override */ 449 450 451FinishOverride: 452 453 /* Validate and verify a table before overriding */ 454 455 Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL); 456 if (ACPI_FAILURE (Status)) 457 { 458 return; 459 } 460 461 ACPI_INFO ((AE_INFO, "%4.4s 0x%8.8X%8.8X" 462 " %s table override, new table: 0x%8.8X%8.8X", 463 OldTableDesc->Signature.Ascii, 464 ACPI_FORMAT_UINT64 (OldTableDesc->Address), 465 OverrideType, ACPI_FORMAT_UINT64 (NewTableDesc.Address))); 466 467 /* We can now uninstall the original table */ 468 469 AcpiTbUninstallTable (OldTableDesc); 470 471 /* 472 * Replace the original table descriptor and keep its state as 473 * "VALIDATED". 474 */ 475 AcpiTbInitTableDescriptor (OldTableDesc, NewTableDesc.Address, 476 NewTableDesc.Flags, NewTableDesc.Pointer); 477 AcpiTbValidateTempTable (OldTableDesc); 478 479 /* Release the temporary table descriptor */ 480 481 AcpiTbReleaseTempTable (&NewTableDesc); 482} 483 484 485/******************************************************************************* 486 * 487 * FUNCTION: AcpiTbUninstallTable 488 * 489 * PARAMETERS: TableDesc - Table descriptor 490 * 491 * RETURN: None 492 * 493 * DESCRIPTION: Delete one internal ACPI table 494 * 495 ******************************************************************************/ 496 497void 498AcpiTbUninstallTable ( 499 ACPI_TABLE_DESC *TableDesc) 500{ 501 502 ACPI_FUNCTION_TRACE (TbUninstallTable); 503 504 505 /* Table must be installed */ 506 507 if (!TableDesc->Address) 508 { 509 return_VOID; 510 } 511 512 AcpiTbInvalidateTable (TableDesc); 513 514 if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) == 515 ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) 516 { 517 ACPI_FREE (ACPI_PHYSADDR_TO_PTR (TableDesc->Address)); 518 } 519 520 TableDesc->Address = ACPI_PTR_TO_PHYSADDR (NULL); 521 return_VOID; 522} 523