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