1 /****************************************************************************** 2 * 3 * Module Name: tbxfload - Table load/unload external interfaces 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 #define EXPORT_ACPI_INTERFACES 45 46 #include <contrib/dev/acpica/include/acpi.h> 47 #include <contrib/dev/acpica/include/accommon.h> 48 #include <contrib/dev/acpica/include/acnamesp.h> 49 #include <contrib/dev/acpica/include/actables.h> 50 #include <contrib/dev/acpica/include/acevents.h> 51 52 #define _COMPONENT ACPI_TABLES 53 ACPI_MODULE_NAME ("tbxfload") 54 55 56 /******************************************************************************* 57 * 58 * FUNCTION: AcpiLoadTables 59 * 60 * PARAMETERS: None 61 * 62 * RETURN: Status 63 * 64 * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT 65 * 66 ******************************************************************************/ 67 68 ACPI_STATUS 69 AcpiLoadTables ( 70 void) 71 { 72 ACPI_STATUS Status; 73 74 75 ACPI_FUNCTION_TRACE (AcpiLoadTables); 76 77 78 /* 79 * Install the default operation region handlers. These are the 80 * handlers that are defined by the ACPI specification to be 81 * "always accessible" -- namely, SystemMemory, SystemIO, and 82 * PCI_Config. This also means that no _REG methods need to be 83 * run for these address spaces. We need to have these handlers 84 * installed before any AML code can be executed, especially any 85 * module-level code (11/2015). 86 * Note that we allow OSPMs to install their own region handlers 87 * between AcpiInitializeSubsystem() and AcpiLoadTables() to use 88 * their customized default region handlers. 89 */ 90 Status = AcpiEvInstallRegionHandlers (); 91 if (ACPI_FAILURE (Status)) 92 { 93 ACPI_EXCEPTION ((AE_INFO, Status, "During Region initialization")); 94 return_ACPI_STATUS (Status); 95 } 96 97 /* Load the namespace from the tables */ 98 99 Status = AcpiTbLoadNamespace (); 100 101 /* Don't let single failures abort the load */ 102 103 if (Status == AE_CTRL_TERMINATE) 104 { 105 Status = AE_OK; 106 } 107 108 if (ACPI_FAILURE (Status)) 109 { 110 ACPI_EXCEPTION ((AE_INFO, Status, 111 "While loading namespace from ACPI tables")); 112 } 113 114 if (!AcpiGbl_GroupModuleLevelCode) 115 { 116 /* 117 * Initialize the objects that remain uninitialized. This 118 * runs the executable AML that may be part of the 119 * declaration of these objects: 120 * OperationRegions, BufferFields, Buffers, and Packages. 121 */ 122 Status = AcpiNsInitializeObjects (); 123 if (ACPI_FAILURE (Status)) 124 { 125 return_ACPI_STATUS (Status); 126 } 127 } 128 129 AcpiGbl_NamespaceInitialized = TRUE; 130 return_ACPI_STATUS (Status); 131 } 132 133 ACPI_EXPORT_SYMBOL_INIT (AcpiLoadTables) 134 135 136 /******************************************************************************* 137 * 138 * FUNCTION: AcpiTbLoadNamespace 139 * 140 * PARAMETERS: None 141 * 142 * RETURN: Status 143 * 144 * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in 145 * the RSDT/XSDT. 146 * 147 ******************************************************************************/ 148 149 ACPI_STATUS 150 AcpiTbLoadNamespace ( 151 void) 152 { 153 ACPI_STATUS Status; 154 UINT32 i; 155 ACPI_TABLE_HEADER *NewDsdt; 156 ACPI_TABLE_DESC *Table; 157 UINT32 TablesLoaded = 0; 158 UINT32 TablesFailed = 0; 159 160 161 ACPI_FUNCTION_TRACE (TbLoadNamespace); 162 163 164 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 165 166 /* 167 * Load the namespace. The DSDT is required, but any SSDT and 168 * PSDT tables are optional. Verify the DSDT. 169 */ 170 Table = &AcpiGbl_RootTableList.Tables[AcpiGbl_DsdtIndex]; 171 172 if (!AcpiGbl_RootTableList.CurrentTableCount || 173 !ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_DSDT) || 174 ACPI_FAILURE (AcpiTbValidateTable (Table))) 175 { 176 Status = AE_NO_ACPI_TABLES; 177 goto UnlockAndExit; 178 } 179 180 /* 181 * Save the DSDT pointer for simple access. This is the mapped memory 182 * address. We must take care here because the address of the .Tables 183 * array can change dynamically as tables are loaded at run-time. Note: 184 * .Pointer field is not validated until after call to AcpiTbValidateTable. 185 */ 186 AcpiGbl_DSDT = Table->Pointer; 187 188 /* 189 * Optionally copy the entire DSDT to local memory (instead of simply 190 * mapping it.) There are some BIOSs that corrupt or replace the original 191 * DSDT, creating the need for this option. Default is FALSE, do not copy 192 * the DSDT. 193 */ 194 if (AcpiGbl_CopyDsdtLocally) 195 { 196 NewDsdt = AcpiTbCopyDsdt (AcpiGbl_DsdtIndex); 197 if (NewDsdt) 198 { 199 AcpiGbl_DSDT = NewDsdt; 200 } 201 } 202 203 /* 204 * Save the original DSDT header for detection of table corruption 205 * and/or replacement of the DSDT from outside the OS. 206 */ 207 memcpy (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, 208 sizeof (ACPI_TABLE_HEADER)); 209 210 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 211 212 /* Load and parse tables */ 213 214 Status = AcpiNsLoadTable (AcpiGbl_DsdtIndex, AcpiGbl_RootNode); 215 if (ACPI_FAILURE (Status)) 216 { 217 ACPI_EXCEPTION ((AE_INFO, Status, "[DSDT] table load failed")); 218 TablesFailed++; 219 } 220 else 221 { 222 TablesLoaded++; 223 } 224 225 /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ 226 227 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 228 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) 229 { 230 Table = &AcpiGbl_RootTableList.Tables[i]; 231 232 if (!AcpiGbl_RootTableList.Tables[i].Address || 233 (!ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_SSDT) && 234 !ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_PSDT) && 235 !ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_OSDT)) || 236 ACPI_FAILURE (AcpiTbValidateTable (Table))) 237 { 238 continue; 239 } 240 241 /* Ignore errors while loading tables, get as many as possible */ 242 243 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 244 Status = AcpiNsLoadTable (i, AcpiGbl_RootNode); 245 if (ACPI_FAILURE (Status)) 246 { 247 ACPI_EXCEPTION ((AE_INFO, Status, "(%4.4s:%8.8s) while loading table", 248 Table->Signature.Ascii, Table->Pointer->OemTableId)); 249 250 TablesFailed++; 251 252 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, 253 "Table [%4.4s:%8.8s] (id FF) - Table namespace load failed\n\n", 254 Table->Signature.Ascii, Table->Pointer->OemTableId)); 255 } 256 else 257 { 258 TablesLoaded++; 259 } 260 261 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 262 } 263 264 if (!TablesFailed) 265 { 266 ACPI_INFO (( 267 "%u ACPI AML tables successfully acquired and loaded\n", 268 TablesLoaded)); 269 } 270 else 271 { 272 ACPI_ERROR ((AE_INFO, 273 "%u table load failures, %u successful", 274 TablesFailed, TablesLoaded)); 275 276 /* Indicate at least one failure */ 277 278 Status = AE_CTRL_TERMINATE; 279 } 280 281 UnlockAndExit: 282 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 283 return_ACPI_STATUS (Status); 284 } 285 286 287 /******************************************************************************* 288 * 289 * FUNCTION: AcpiInstallTable 290 * 291 * PARAMETERS: Address - Address of the ACPI table to be installed. 292 * Physical - Whether the address is a physical table 293 * address or not 294 * 295 * RETURN: Status 296 * 297 * DESCRIPTION: Dynamically install an ACPI table. 298 * Note: This function should only be invoked after 299 * AcpiInitializeTables() and before AcpiLoadTables(). 300 * 301 ******************************************************************************/ 302 303 ACPI_STATUS 304 AcpiInstallTable ( 305 ACPI_PHYSICAL_ADDRESS Address, 306 BOOLEAN Physical) 307 { 308 ACPI_STATUS Status; 309 UINT8 Flags; 310 UINT32 TableIndex; 311 312 313 ACPI_FUNCTION_TRACE (AcpiInstallTable); 314 315 316 if (Physical) 317 { 318 Flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL; 319 } 320 else 321 { 322 Flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL; 323 } 324 325 Status = AcpiTbInstallStandardTable (Address, Flags, 326 FALSE, FALSE, &TableIndex); 327 328 return_ACPI_STATUS (Status); 329 } 330 331 ACPI_EXPORT_SYMBOL_INIT (AcpiInstallTable) 332 333 334 /******************************************************************************* 335 * 336 * FUNCTION: AcpiLoadTable 337 * 338 * PARAMETERS: Table - Pointer to a buffer containing the ACPI 339 * table to be loaded. 340 * 341 * RETURN: Status 342 * 343 * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must 344 * be a valid ACPI table with a valid ACPI table header. 345 * Note1: Mainly intended to support hotplug addition of SSDTs. 346 * Note2: Does not copy the incoming table. User is responsible 347 * to ensure that the table is not deleted or unmapped. 348 * 349 ******************************************************************************/ 350 351 ACPI_STATUS 352 AcpiLoadTable ( 353 ACPI_TABLE_HEADER *Table) 354 { 355 ACPI_STATUS Status; 356 UINT32 TableIndex; 357 358 359 ACPI_FUNCTION_TRACE (AcpiLoadTable); 360 361 362 /* Parameter validation */ 363 364 if (!Table) 365 { 366 return_ACPI_STATUS (AE_BAD_PARAMETER); 367 } 368 369 /* Must acquire the interpreter lock during this operation */ 370 371 Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); 372 if (ACPI_FAILURE (Status)) 373 { 374 return_ACPI_STATUS (Status); 375 } 376 377 /* Install the table and load it into the namespace */ 378 379 ACPI_INFO (("Host-directed Dynamic ACPI Table Load:")); 380 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 381 382 Status = AcpiTbInstallStandardTable (ACPI_PTR_TO_PHYSADDR (Table), 383 ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, TRUE, FALSE, 384 &TableIndex); 385 386 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 387 if (ACPI_FAILURE (Status)) 388 { 389 goto UnlockAndExit; 390 } 391 392 /* 393 * Note: Now table is "INSTALLED", it must be validated before 394 * using. 395 */ 396 Status = AcpiTbValidateTable ( 397 &AcpiGbl_RootTableList.Tables[TableIndex]); 398 if (ACPI_FAILURE (Status)) 399 { 400 goto UnlockAndExit; 401 } 402 403 Status = AcpiNsLoadTable (TableIndex, AcpiGbl_RootNode); 404 405 /* Invoke table handler if present */ 406 407 if (AcpiGbl_TableHandler) 408 { 409 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, 410 AcpiGbl_TableHandlerContext); 411 } 412 413 UnlockAndExit: 414 (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); 415 return_ACPI_STATUS (Status); 416 } 417 418 ACPI_EXPORT_SYMBOL (AcpiLoadTable) 419 420 421 /******************************************************************************* 422 * 423 * FUNCTION: AcpiUnloadParentTable 424 * 425 * PARAMETERS: Object - Handle to any namespace object owned by 426 * the table to be unloaded 427 * 428 * RETURN: Status 429 * 430 * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads 431 * the table and deletes all namespace objects associated with 432 * that table. Unloading of the DSDT is not allowed. 433 * Note: Mainly intended to support hotplug removal of SSDTs. 434 * 435 ******************************************************************************/ 436 437 ACPI_STATUS 438 AcpiUnloadParentTable ( 439 ACPI_HANDLE Object) 440 { 441 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Object); 442 ACPI_STATUS Status = AE_NOT_EXIST; 443 ACPI_OWNER_ID OwnerId; 444 UINT32 i; 445 446 447 ACPI_FUNCTION_TRACE (AcpiUnloadParentTable); 448 449 450 /* Parameter validation */ 451 452 if (!Object) 453 { 454 return_ACPI_STATUS (AE_BAD_PARAMETER); 455 } 456 457 /* 458 * The node OwnerId is currently the same as the parent table ID. 459 * However, this could change in the future. 460 */ 461 OwnerId = Node->OwnerId; 462 if (!OwnerId) 463 { 464 /* OwnerId==0 means DSDT is the owner. DSDT cannot be unloaded */ 465 466 return_ACPI_STATUS (AE_TYPE); 467 } 468 469 /* Must acquire the interpreter lock during this operation */ 470 471 Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); 472 if (ACPI_FAILURE (Status)) 473 { 474 return_ACPI_STATUS (Status); 475 } 476 477 /* Find the table in the global table list */ 478 479 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 480 { 481 if (OwnerId != AcpiGbl_RootTableList.Tables[i].OwnerId) 482 { 483 continue; 484 } 485 486 /* 487 * Allow unload of SSDT and OEMx tables only. Do not allow unload 488 * of the DSDT. No other types of tables should get here, since 489 * only these types can contain AML and thus are the only types 490 * that can create namespace objects. 491 */ 492 if (ACPI_COMPARE_NAME ( 493 AcpiGbl_RootTableList.Tables[i].Signature.Ascii, 494 ACPI_SIG_DSDT)) 495 { 496 Status = AE_TYPE; 497 break; 498 } 499 500 /* Ensure the table is actually loaded */ 501 502 if (!AcpiTbIsTableLoaded (i)) 503 { 504 Status = AE_NOT_EXIST; 505 break; 506 } 507 508 /* Invoke table handler if present */ 509 510 if (AcpiGbl_TableHandler) 511 { 512 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, 513 AcpiGbl_RootTableList.Tables[i].Pointer, 514 AcpiGbl_TableHandlerContext); 515 } 516 517 /* 518 * Delete all namespace objects owned by this table. Note that 519 * these objects can appear anywhere in the namespace by virtue 520 * of the AML "Scope" operator. Thus, we need to track ownership 521 * by an ID, not simply a position within the hierarchy. 522 */ 523 Status = AcpiTbDeleteNamespaceByOwner (i); 524 if (ACPI_FAILURE (Status)) 525 { 526 break; 527 } 528 529 Status = AcpiTbReleaseOwnerId (i); 530 AcpiTbSetTableLoadedFlag (i, FALSE); 531 break; 532 } 533 534 (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); 535 return_ACPI_STATUS (Status); 536 } 537 538 ACPI_EXPORT_SYMBOL (AcpiUnloadParentTable) 539