1 /****************************************************************************** 2 * 3 * Module Name: tbxfload - Table load/unload external interfaces 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 ACPI_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 ((!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), 186 ACPI_SIG_SSDT) && 187 !ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), 188 ACPI_SIG_PSDT)) || 189 ACPI_FAILURE (AcpiTbValidateTable ( 190 &AcpiGbl_RootTableList.Tables[i]))) 191 { 192 continue; 193 } 194 195 /* Ignore errors while loading tables, get as many as possible */ 196 197 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 198 (void) AcpiNsLoadTable (i, AcpiGbl_RootNode); 199 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 200 } 201 202 ACPI_INFO ((AE_INFO, "All ACPI Tables successfully acquired")); 203 204 UnlockAndExit: 205 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 206 return_ACPI_STATUS (Status); 207 } 208 209 210 /******************************************************************************* 211 * 212 * FUNCTION: AcpiInstallTable 213 * 214 * PARAMETERS: Address - Address of the ACPI table to be installed. 215 * Physical - Whether the address is a physical table 216 * address or not 217 * 218 * RETURN: Status 219 * 220 * DESCRIPTION: Dynamically install an ACPI table. 221 * Note: This function should only be invoked after 222 * AcpiInitializeTables() and before AcpiLoadTables(). 223 * 224 ******************************************************************************/ 225 226 ACPI_STATUS 227 AcpiInstallTable ( 228 ACPI_PHYSICAL_ADDRESS Address, 229 BOOLEAN Physical) 230 { 231 ACPI_STATUS Status; 232 UINT8 Flags; 233 UINT32 TableIndex; 234 235 236 ACPI_FUNCTION_TRACE (AcpiInstallTable); 237 238 239 if (Physical) 240 { 241 Flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL; 242 } 243 else 244 { 245 Flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL; 246 } 247 248 Status = AcpiTbInstallStandardTable (Address, Flags, 249 FALSE, FALSE, &TableIndex); 250 251 return_ACPI_STATUS (Status); 252 } 253 254 ACPI_EXPORT_SYMBOL_INIT (AcpiInstallTable) 255 256 257 /******************************************************************************* 258 * 259 * FUNCTION: AcpiLoadTable 260 * 261 * PARAMETERS: Table - Pointer to a buffer containing the ACPI 262 * table to be loaded. 263 * 264 * RETURN: Status 265 * 266 * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must 267 * be a valid ACPI table with a valid ACPI table header. 268 * Note1: Mainly intended to support hotplug addition of SSDTs. 269 * Note2: Does not copy the incoming table. User is responsible 270 * to ensure that the table is not deleted or unmapped. 271 * 272 ******************************************************************************/ 273 274 ACPI_STATUS 275 AcpiLoadTable ( 276 ACPI_TABLE_HEADER *Table) 277 { 278 ACPI_STATUS Status; 279 UINT32 TableIndex; 280 281 282 ACPI_FUNCTION_TRACE (AcpiLoadTable); 283 284 285 /* Parameter validation */ 286 287 if (!Table) 288 { 289 return_ACPI_STATUS (AE_BAD_PARAMETER); 290 } 291 292 /* Must acquire the interpreter lock during this operation */ 293 294 Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); 295 if (ACPI_FAILURE (Status)) 296 { 297 return_ACPI_STATUS (Status); 298 } 299 300 /* Install the table and load it into the namespace */ 301 302 ACPI_INFO ((AE_INFO, "Host-directed Dynamic ACPI Table Load:")); 303 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 304 305 Status = AcpiTbInstallStandardTable (ACPI_PTR_TO_PHYSADDR (Table), 306 ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, TRUE, FALSE, 307 &TableIndex); 308 309 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 310 if (ACPI_FAILURE (Status)) 311 { 312 goto UnlockAndExit; 313 } 314 315 /* 316 * Note: Now table is "INSTALLED", it must be validated before 317 * using. 318 */ 319 Status = AcpiTbValidateTable (&AcpiGbl_RootTableList.Tables[TableIndex]); 320 if (ACPI_FAILURE (Status)) 321 { 322 goto UnlockAndExit; 323 } 324 325 Status = AcpiNsLoadTable (TableIndex, AcpiGbl_RootNode); 326 327 /* Invoke table handler if present */ 328 329 if (AcpiGbl_TableHandler) 330 { 331 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, 332 AcpiGbl_TableHandlerContext); 333 } 334 335 UnlockAndExit: 336 (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); 337 return_ACPI_STATUS (Status); 338 } 339 340 ACPI_EXPORT_SYMBOL (AcpiLoadTable) 341 342 343 /******************************************************************************* 344 * 345 * FUNCTION: AcpiUnloadParentTable 346 * 347 * PARAMETERS: Object - Handle to any namespace object owned by 348 * the table to be unloaded 349 * 350 * RETURN: Status 351 * 352 * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads 353 * the table and deletes all namespace objects associated with 354 * that table. Unloading of the DSDT is not allowed. 355 * Note: Mainly intended to support hotplug removal of SSDTs. 356 * 357 ******************************************************************************/ 358 359 ACPI_STATUS 360 AcpiUnloadParentTable ( 361 ACPI_HANDLE Object) 362 { 363 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Object); 364 ACPI_STATUS Status = AE_NOT_EXIST; 365 ACPI_OWNER_ID OwnerId; 366 UINT32 i; 367 368 369 ACPI_FUNCTION_TRACE (AcpiUnloadParentTable); 370 371 372 /* Parameter validation */ 373 374 if (!Object) 375 { 376 return_ACPI_STATUS (AE_BAD_PARAMETER); 377 } 378 379 /* 380 * The node OwnerId is currently the same as the parent table ID. 381 * However, this could change in the future. 382 */ 383 OwnerId = Node->OwnerId; 384 if (!OwnerId) 385 { 386 /* OwnerId==0 means DSDT is the owner. DSDT cannot be unloaded */ 387 388 return_ACPI_STATUS (AE_TYPE); 389 } 390 391 /* Must acquire the interpreter lock during this operation */ 392 393 Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); 394 if (ACPI_FAILURE (Status)) 395 { 396 return_ACPI_STATUS (Status); 397 } 398 399 /* Find the table in the global table list */ 400 401 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 402 { 403 if (OwnerId != AcpiGbl_RootTableList.Tables[i].OwnerId) 404 { 405 continue; 406 } 407 408 /* 409 * Allow unload of SSDT and OEMx tables only. Do not allow unload 410 * of the DSDT. No other types of tables should get here, since 411 * only these types can contain AML and thus are the only types 412 * that can create namespace objects. 413 */ 414 if (ACPI_COMPARE_NAME ( 415 AcpiGbl_RootTableList.Tables[i].Signature.Ascii, 416 ACPI_SIG_DSDT)) 417 { 418 Status = AE_TYPE; 419 break; 420 } 421 422 /* Ensure the table is actually loaded */ 423 424 if (!AcpiTbIsTableLoaded (i)) 425 { 426 Status = AE_NOT_EXIST; 427 break; 428 } 429 430 /* Invoke table handler if present */ 431 432 if (AcpiGbl_TableHandler) 433 { 434 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, 435 AcpiGbl_RootTableList.Tables[i].Pointer, 436 AcpiGbl_TableHandlerContext); 437 } 438 439 /* 440 * Delete all namespace objects owned by this table. Note that 441 * these objects can appear anywhere in the namespace by virtue 442 * of the AML "Scope" operator. Thus, we need to track ownership 443 * by an ID, not simply a position within the hierarchy. 444 */ 445 Status = AcpiTbDeleteNamespaceByOwner (i); 446 if (ACPI_FAILURE (Status)) 447 { 448 break; 449 } 450 451 Status = AcpiTbReleaseOwnerId (i); 452 AcpiTbSetTableLoadedFlag (i, FALSE); 453 break; 454 } 455 456 (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); 457 return_ACPI_STATUS (Status); 458 } 459 460 ACPI_EXPORT_SYMBOL (AcpiUnloadParentTable) 461