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