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