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