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