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