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 "acpi.h" 48 #include "accommon.h" 49 #include "acnamesp.h" 50 #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 (AcpiTbVerifyTable ( 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 AcpiTbVerifyTable. 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 (AcpiTbVerifyTable ( 191 &AcpiGbl_RootTableList.Tables[i]))) 192 { 193 continue; 194 } 195 196 /* 197 * Optionally do not load any SSDTs from the RSDT/XSDT. This can 198 * be useful for debugging ACPI problems on some machines. 199 */ 200 if (AcpiGbl_DisableSsdtTableLoad) 201 { 202 ACPI_INFO ((AE_INFO, "Ignoring %4.4s at %p", 203 AcpiGbl_RootTableList.Tables[i].Signature.Ascii, 204 ACPI_CAST_PTR (void, AcpiGbl_RootTableList.Tables[i].Address))); 205 continue; 206 } 207 208 /* Ignore errors while loading tables, get as many as possible */ 209 210 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 211 (void) AcpiNsLoadTable (i, AcpiGbl_RootNode); 212 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 213 } 214 215 ACPI_INFO ((AE_INFO, "All ACPI Tables successfully acquired")); 216 217 UnlockAndExit: 218 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 219 return_ACPI_STATUS (Status); 220 } 221 222 223 /******************************************************************************* 224 * 225 * FUNCTION: AcpiLoadTable 226 * 227 * PARAMETERS: Table - Pointer to a buffer containing the ACPI 228 * table to be loaded. 229 * 230 * RETURN: Status 231 * 232 * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must 233 * be a valid ACPI table with a valid ACPI table header. 234 * Note1: Mainly intended to support hotplug addition of SSDTs. 235 * Note2: Does not copy the incoming table. User is responsible 236 * to ensure that the table is not deleted or unmapped. 237 * 238 ******************************************************************************/ 239 240 ACPI_STATUS 241 AcpiLoadTable ( 242 ACPI_TABLE_HEADER *Table) 243 { 244 ACPI_STATUS Status; 245 ACPI_TABLE_DESC TableDesc; 246 UINT32 TableIndex; 247 248 249 ACPI_FUNCTION_TRACE (AcpiLoadTable); 250 251 252 /* Parameter validation */ 253 254 if (!Table) 255 { 256 return_ACPI_STATUS (AE_BAD_PARAMETER); 257 } 258 259 /* Init local table descriptor */ 260 261 ACPI_MEMSET (&TableDesc, 0, sizeof (ACPI_TABLE_DESC)); 262 TableDesc.Address = ACPI_PTR_TO_PHYSADDR (Table); 263 TableDesc.Pointer = Table; 264 TableDesc.Length = Table->Length; 265 TableDesc.Flags = ACPI_TABLE_ORIGIN_UNKNOWN; 266 267 /* Must acquire the interpreter lock during this operation */ 268 269 Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); 270 if (ACPI_FAILURE (Status)) 271 { 272 return_ACPI_STATUS (Status); 273 } 274 275 /* Install the table and load it into the namespace */ 276 277 ACPI_INFO ((AE_INFO, "Host-directed Dynamic ACPI Table Load:")); 278 Status = AcpiTbAddTable (&TableDesc, &TableIndex); 279 if (ACPI_FAILURE (Status)) 280 { 281 goto UnlockAndExit; 282 } 283 284 Status = AcpiNsLoadTable (TableIndex, AcpiGbl_RootNode); 285 286 /* Invoke table handler if present */ 287 288 if (AcpiGbl_TableHandler) 289 { 290 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, 291 AcpiGbl_TableHandlerContext); 292 } 293 294 UnlockAndExit: 295 (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); 296 return_ACPI_STATUS (Status); 297 } 298 299 ACPI_EXPORT_SYMBOL (AcpiLoadTable) 300 301 302 /******************************************************************************* 303 * 304 * FUNCTION: AcpiUnloadParentTable 305 * 306 * PARAMETERS: Object - Handle to any namespace object owned by 307 * the table to be unloaded 308 * 309 * RETURN: Status 310 * 311 * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads 312 * the table and deletes all namespace objects associated with 313 * that table. Unloading of the DSDT is not allowed. 314 * Note: Mainly intended to support hotplug removal of SSDTs. 315 * 316 ******************************************************************************/ 317 318 ACPI_STATUS 319 AcpiUnloadParentTable ( 320 ACPI_HANDLE Object) 321 { 322 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Object); 323 ACPI_STATUS Status = AE_NOT_EXIST; 324 ACPI_OWNER_ID OwnerId; 325 UINT32 i; 326 327 328 ACPI_FUNCTION_TRACE (AcpiUnloadParentTable); 329 330 331 /* Parameter validation */ 332 333 if (!Object) 334 { 335 return_ACPI_STATUS (AE_BAD_PARAMETER); 336 } 337 338 /* 339 * The node OwnerId is currently the same as the parent table ID. 340 * However, this could change in the future. 341 */ 342 OwnerId = Node->OwnerId; 343 if (!OwnerId) 344 { 345 /* OwnerId==0 means DSDT is the owner. DSDT cannot be unloaded */ 346 347 return_ACPI_STATUS (AE_TYPE); 348 } 349 350 /* Must acquire the interpreter lock during this operation */ 351 352 Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); 353 if (ACPI_FAILURE (Status)) 354 { 355 return_ACPI_STATUS (Status); 356 } 357 358 /* Find the table in the global table list */ 359 360 for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 361 { 362 if (OwnerId != AcpiGbl_RootTableList.Tables[i].OwnerId) 363 { 364 continue; 365 } 366 367 /* 368 * Allow unload of SSDT and OEMx tables only. Do not allow unload 369 * of the DSDT. No other types of tables should get here, since 370 * only these types can contain AML and thus are the only types 371 * that can create namespace objects. 372 */ 373 if (ACPI_COMPARE_NAME ( 374 AcpiGbl_RootTableList.Tables[i].Signature.Ascii, 375 ACPI_SIG_DSDT)) 376 { 377 Status = AE_TYPE; 378 break; 379 } 380 381 /* Ensure the table is actually loaded */ 382 383 if (!AcpiTbIsTableLoaded (i)) 384 { 385 Status = AE_NOT_EXIST; 386 break; 387 } 388 389 /* Invoke table handler if present */ 390 391 if (AcpiGbl_TableHandler) 392 { 393 (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, 394 AcpiGbl_RootTableList.Tables[i].Pointer, 395 AcpiGbl_TableHandlerContext); 396 } 397 398 /* 399 * Delete all namespace objects owned by this table. Note that 400 * these objects can appear anywhere in the namespace by virtue 401 * of the AML "Scope" operator. Thus, we need to track ownership 402 * by an ID, not simply a position within the hierarchy. 403 */ 404 Status = AcpiTbDeleteNamespaceByOwner (i); 405 if (ACPI_FAILURE (Status)) 406 { 407 break; 408 } 409 410 Status = AcpiTbReleaseOwnerId (i); 411 AcpiTbSetTableLoadedFlag (i, FALSE); 412 break; 413 } 414 415 (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); 416 return_ACPI_STATUS (Status); 417 } 418 419 ACPI_EXPORT_SYMBOL (AcpiUnloadParentTable)