1 /****************************************************************************** 2 * 3 * Module Name: tbinstal - ACPI table installation and removal 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 <contrib/dev/acpica/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 #include <contrib/dev/acpica/include/actables.h> 47 48 #define _COMPONENT ACPI_TABLES 49 ACPI_MODULE_NAME ("tbinstal") 50 51 /* Local prototypes */ 52 53 static BOOLEAN 54 AcpiTbCompareTables ( 55 ACPI_TABLE_DESC *TableDesc, 56 UINT32 TableIndex); 57 58 59 /******************************************************************************* 60 * 61 * FUNCTION: AcpiTbCompareTables 62 * 63 * PARAMETERS: TableDesc - Table 1 descriptor to be compared 64 * TableIndex - Index of table 2 to be compared 65 * 66 * RETURN: TRUE if both tables are identical. 67 * 68 * DESCRIPTION: This function compares a table with another table that has 69 * already been installed in the root table list. 70 * 71 ******************************************************************************/ 72 73 static BOOLEAN 74 AcpiTbCompareTables ( 75 ACPI_TABLE_DESC *TableDesc, 76 UINT32 TableIndex) 77 { 78 ACPI_STATUS Status = AE_OK; 79 BOOLEAN IsIdentical; 80 ACPI_TABLE_HEADER *Table; 81 UINT32 TableLength; 82 UINT8 TableFlags; 83 84 85 Status = AcpiTbAcquireTable (&AcpiGbl_RootTableList.Tables[TableIndex], 86 &Table, &TableLength, &TableFlags); 87 if (ACPI_FAILURE (Status)) 88 { 89 return (FALSE); 90 } 91 92 /* 93 * Check for a table match on the entire table length, 94 * not just the header. 95 */ 96 IsIdentical = (BOOLEAN)((TableDesc->Length != TableLength || 97 memcmp (TableDesc->Pointer, Table, TableLength)) ? 98 FALSE : TRUE); 99 100 /* Release the acquired table */ 101 102 AcpiTbReleaseTable (Table, TableLength, TableFlags); 103 return (IsIdentical); 104 } 105 106 107 /******************************************************************************* 108 * 109 * FUNCTION: AcpiTbInstallTableWithOverride 110 * 111 * PARAMETERS: NewTableDesc - New table descriptor to install 112 * Override - Whether override should be performed 113 * TableIndex - Where the table index is returned 114 * 115 * RETURN: None 116 * 117 * DESCRIPTION: Install an ACPI table into the global data structure. The 118 * table override mechanism is called to allow the host 119 * OS to replace any table before it is installed in the root 120 * table array. 121 * 122 ******************************************************************************/ 123 124 void 125 AcpiTbInstallTableWithOverride ( 126 ACPI_TABLE_DESC *NewTableDesc, 127 BOOLEAN Override, 128 UINT32 *TableIndex) 129 { 130 UINT32 i; 131 ACPI_STATUS Status; 132 133 134 Status = AcpiTbGetNextTableDescriptor (&i, NULL); 135 if (ACPI_FAILURE (Status)) 136 { 137 return; 138 } 139 140 /* 141 * ACPI Table Override: 142 * 143 * Before we install the table, let the host OS override it with a new 144 * one if desired. Any table within the RSDT/XSDT can be replaced, 145 * including the DSDT which is pointed to by the FADT. 146 */ 147 if (Override) 148 { 149 AcpiTbOverrideTable (NewTableDesc); 150 } 151 152 AcpiTbInitTableDescriptor (&AcpiGbl_RootTableList.Tables[i], 153 NewTableDesc->Address, NewTableDesc->Flags, NewTableDesc->Pointer); 154 155 AcpiTbPrintTableHeader (NewTableDesc->Address, NewTableDesc->Pointer); 156 157 /* This synchronizes AcpiGbl_DsdtIndex */ 158 159 *TableIndex = i; 160 161 /* Set the global integer width (based upon revision of the DSDT) */ 162 163 if (i == AcpiGbl_DsdtIndex) 164 { 165 AcpiUtSetIntegerWidth (NewTableDesc->Pointer->Revision); 166 } 167 } 168 169 170 /******************************************************************************* 171 * 172 * FUNCTION: AcpiTbInstallFixedTable 173 * 174 * PARAMETERS: Address - Physical address of DSDT or FACS 175 * Signature - Table signature, NULL if no need to 176 * match 177 * TableIndex - Where the table index is returned 178 * 179 * RETURN: Status 180 * 181 * DESCRIPTION: Install a fixed ACPI table (DSDT/FACS) into the global data 182 * structure. 183 * 184 ******************************************************************************/ 185 186 ACPI_STATUS 187 AcpiTbInstallFixedTable ( 188 ACPI_PHYSICAL_ADDRESS Address, 189 char *Signature, 190 UINT32 *TableIndex) 191 { 192 ACPI_TABLE_DESC NewTableDesc; 193 ACPI_STATUS Status; 194 195 196 ACPI_FUNCTION_TRACE (TbInstallFixedTable); 197 198 199 if (!Address) 200 { 201 ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]", 202 Signature)); 203 return (AE_NO_MEMORY); 204 } 205 206 /* Fill a table descriptor for validation */ 207 208 Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, 209 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); 210 if (ACPI_FAILURE (Status)) 211 { 212 ACPI_ERROR ((AE_INFO, "Could not acquire table length at %8.8X%8.8X", 213 ACPI_FORMAT_UINT64 (Address))); 214 return_ACPI_STATUS (Status); 215 } 216 217 /* Validate and verify a table before installation */ 218 219 Status = AcpiTbVerifyTempTable (&NewTableDesc, Signature); 220 if (ACPI_FAILURE (Status)) 221 { 222 goto ReleaseAndExit; 223 } 224 225 /* Add the table to the global root table list */ 226 227 AcpiTbInstallTableWithOverride (&NewTableDesc, TRUE, TableIndex); 228 229 ReleaseAndExit: 230 231 /* Release the temporary table descriptor */ 232 233 AcpiTbReleaseTempTable (&NewTableDesc); 234 return_ACPI_STATUS (Status); 235 } 236 237 238 /******************************************************************************* 239 * 240 * FUNCTION: AcpiTbInstallStandardTable 241 * 242 * PARAMETERS: Address - Address of the table (might be a virtual 243 * address depending on the TableFlags) 244 * Flags - Flags for the table 245 * Reload - Whether reload should be performed 246 * Override - Whether override should be performed 247 * TableIndex - Where the table index is returned 248 * 249 * RETURN: Status 250 * 251 * DESCRIPTION: This function is called to install an ACPI table that is 252 * neither DSDT nor FACS (a "standard" table.) 253 * When this function is called by "Load" or "LoadTable" opcodes, 254 * or by AcpiLoadTable() API, the "Reload" parameter is set. 255 * After sucessfully returning from this function, table is 256 * "INSTALLED" but not "VALIDATED". 257 * 258 ******************************************************************************/ 259 260 ACPI_STATUS 261 AcpiTbInstallStandardTable ( 262 ACPI_PHYSICAL_ADDRESS Address, 263 UINT8 Flags, 264 BOOLEAN Reload, 265 BOOLEAN Override, 266 UINT32 *TableIndex) 267 { 268 UINT32 i; 269 ACPI_STATUS Status = AE_OK; 270 ACPI_TABLE_DESC NewTableDesc; 271 272 273 ACPI_FUNCTION_TRACE (TbInstallStandardTable); 274 275 276 /* Acquire a temporary table descriptor for validation */ 277 278 Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, Flags); 279 if (ACPI_FAILURE (Status)) 280 { 281 ACPI_ERROR ((AE_INFO, "Could not acquire table length at %8.8X%8.8X", 282 ACPI_FORMAT_UINT64 (Address))); 283 return_ACPI_STATUS (Status); 284 } 285 286 /* 287 * Optionally do not load any SSDTs from the RSDT/XSDT. This can 288 * be useful for debugging ACPI problems on some machines. 289 */ 290 if (!Reload && 291 AcpiGbl_DisableSsdtTableInstall && 292 ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT)) 293 { 294 ACPI_INFO ((AE_INFO, "Ignoring installation of %4.4s at %8.8X%8.8X", 295 NewTableDesc.Signature.Ascii, ACPI_FORMAT_UINT64 (Address))); 296 goto ReleaseAndExit; 297 } 298 299 /* Validate and verify a table before installation */ 300 301 Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL); 302 if (ACPI_FAILURE (Status)) 303 { 304 goto ReleaseAndExit; 305 } 306 307 if (Reload) 308 { 309 /* 310 * Validate the incoming table signature. 311 * 312 * 1) Originally, we checked the table signature for "SSDT" or "PSDT". 313 * 2) We added support for OEMx tables, signature "OEM". 314 * 3) Valid tables were encountered with a null signature, so we just 315 * gave up on validating the signature, (05/2008). 316 * 4) We encountered non-AML tables such as the MADT, which caused 317 * interpreter errors and kernel faults. So now, we once again allow 318 * only "SSDT", "OEMx", and now, also a null signature. (05/2011). 319 */ 320 if ((NewTableDesc.Signature.Ascii[0] != 0x00) && 321 (!ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT)) && 322 (strncmp (NewTableDesc.Signature.Ascii, "OEM", 3))) 323 { 324 ACPI_BIOS_ERROR ((AE_INFO, 325 "Table has invalid signature [%4.4s] (0x%8.8X), " 326 "must be SSDT or OEMx", 327 AcpiUtValidAcpiName (NewTableDesc.Signature.Ascii) ? 328 NewTableDesc.Signature.Ascii : "????", 329 NewTableDesc.Signature.Integer)); 330 331 Status = AE_BAD_SIGNATURE; 332 goto ReleaseAndExit; 333 } 334 335 /* Check if table is already registered */ 336 337 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) 338 { 339 /* 340 * Check for a table match on the entire table length, 341 * not just the header. 342 */ 343 if (!AcpiTbCompareTables (&NewTableDesc, i)) 344 { 345 continue; 346 } 347 348 /* 349 * Note: the current mechanism does not unregister a table if it is 350 * dynamically unloaded. The related namespace entries are deleted, 351 * but the table remains in the root table list. 352 * 353 * The assumption here is that the number of different tables that 354 * will be loaded is actually small, and there is minimal overhead 355 * in just keeping the table in case it is needed again. 356 * 357 * If this assumption changes in the future (perhaps on large 358 * machines with many table load/unload operations), tables will 359 * need to be unregistered when they are unloaded, and slots in the 360 * root table list should be reused when empty. 361 */ 362 if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED) 363 { 364 /* Table is still loaded, this is an error */ 365 366 Status = AE_ALREADY_EXISTS; 367 goto ReleaseAndExit; 368 } 369 else 370 { 371 /* 372 * Table was unloaded, allow it to be reloaded. 373 * As we are going to return AE_OK to the caller, we should 374 * take the responsibility of freeing the input descriptor. 375 * Refill the input descriptor to ensure 376 * AcpiTbInstallTableWithOverride() can be called again to 377 * indicate the re-installation. 378 */ 379 AcpiTbUninstallTable (&NewTableDesc); 380 *TableIndex = i; 381 return_ACPI_STATUS (AE_OK); 382 } 383 } 384 } 385 386 /* Add the table to the global root table list */ 387 388 AcpiTbInstallTableWithOverride (&NewTableDesc, Override, TableIndex); 389 390 ReleaseAndExit: 391 392 /* Release the temporary table descriptor */ 393 394 AcpiTbReleaseTempTable (&NewTableDesc); 395 return_ACPI_STATUS (Status); 396 } 397 398 399 /******************************************************************************* 400 * 401 * FUNCTION: AcpiTbOverrideTable 402 * 403 * PARAMETERS: OldTableDesc - Validated table descriptor to be 404 * overridden 405 * 406 * RETURN: None 407 * 408 * DESCRIPTION: Attempt table override by calling the OSL override functions. 409 * Note: If the table is overridden, then the entire new table 410 * is acquired and returned by this function. 411 * Before/after invocation, the table descriptor is in a state 412 * that is "VALIDATED". 413 * 414 ******************************************************************************/ 415 416 void 417 AcpiTbOverrideTable ( 418 ACPI_TABLE_DESC *OldTableDesc) 419 { 420 ACPI_STATUS Status; 421 char *OverrideType; 422 ACPI_TABLE_DESC NewTableDesc; 423 ACPI_TABLE_HEADER *Table; 424 ACPI_PHYSICAL_ADDRESS Address; 425 UINT32 Length; 426 427 428 /* (1) Attempt logical override (returns a logical address) */ 429 430 Status = AcpiOsTableOverride (OldTableDesc->Pointer, &Table); 431 if (ACPI_SUCCESS (Status) && Table) 432 { 433 AcpiTbAcquireTempTable (&NewTableDesc, ACPI_PTR_TO_PHYSADDR (Table), 434 ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); 435 OverrideType = "Logical"; 436 goto FinishOverride; 437 } 438 439 /* (2) Attempt physical override (returns a physical address) */ 440 441 Status = AcpiOsPhysicalTableOverride (OldTableDesc->Pointer, 442 &Address, &Length); 443 if (ACPI_SUCCESS (Status) && Address && Length) 444 { 445 AcpiTbAcquireTempTable (&NewTableDesc, Address, 446 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); 447 OverrideType = "Physical"; 448 goto FinishOverride; 449 } 450 451 return; /* There was no override */ 452 453 454 FinishOverride: 455 456 /* Validate and verify a table before overriding */ 457 458 Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL); 459 if (ACPI_FAILURE (Status)) 460 { 461 return; 462 } 463 464 ACPI_INFO ((AE_INFO, "%4.4s 0x%8.8X%8.8X" 465 " %s table override, new table: 0x%8.8X%8.8X", 466 OldTableDesc->Signature.Ascii, 467 ACPI_FORMAT_UINT64 (OldTableDesc->Address), 468 OverrideType, ACPI_FORMAT_UINT64 (NewTableDesc.Address))); 469 470 /* We can now uninstall the original table */ 471 472 AcpiTbUninstallTable (OldTableDesc); 473 474 /* 475 * Replace the original table descriptor and keep its state as 476 * "VALIDATED". 477 */ 478 AcpiTbInitTableDescriptor (OldTableDesc, NewTableDesc.Address, 479 NewTableDesc.Flags, NewTableDesc.Pointer); 480 AcpiTbValidateTempTable (OldTableDesc); 481 482 /* Release the temporary table descriptor */ 483 484 AcpiTbReleaseTempTable (&NewTableDesc); 485 } 486 487 488 /******************************************************************************* 489 * 490 * FUNCTION: AcpiTbUninstallTable 491 * 492 * PARAMETERS: TableDesc - Table descriptor 493 * 494 * RETURN: None 495 * 496 * DESCRIPTION: Delete one internal ACPI table 497 * 498 ******************************************************************************/ 499 500 void 501 AcpiTbUninstallTable ( 502 ACPI_TABLE_DESC *TableDesc) 503 { 504 505 ACPI_FUNCTION_TRACE (TbUninstallTable); 506 507 508 /* Table must be installed */ 509 510 if (!TableDesc->Address) 511 { 512 return_VOID; 513 } 514 515 AcpiTbInvalidateTable (TableDesc); 516 517 if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) == 518 ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) 519 { 520 ACPI_FREE (ACPI_PHYSADDR_TO_PTR (TableDesc->Address)); 521 } 522 523 TableDesc->Address = ACPI_PTR_TO_PHYSADDR (NULL); 524 return_VOID; 525 } 526