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