tbxfload.c revision 256281
167754Smsmith/****************************************************************************** 267754Smsmith * 367754Smsmith * Module Name: tbxfload - Table load/unload external interfaces 467754Smsmith * 5117521Snjl *****************************************************************************/ 667754Smsmith 767754Smsmith/* 867754Smsmith * Copyright (C) 2000 - 2013, Intel Corp. 967754Smsmith * All rights reserved. 1067754Smsmith * 1167754Smsmith * Redistribution and use in source and binary forms, with or without 1267754Smsmith * modification, are permitted provided that the following conditions 13114237Snjl * are met: 1470243Smsmith * 1. Redistributions of source code must retain the above copyright 1567754Smsmith * notice, this list of conditions, and the following disclaimer, 1667754Smsmith * without modification. 1767754Smsmith * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1867754Smsmith * substantially similar to the "NO WARRANTY" disclaimer below 1967754Smsmith * ("Disclaimer") and any redistribution must be conditioned upon 2067754Smsmith * including a substantially similar Disclaimer requirement for further 2167754Smsmith * binary redistribution. 2267754Smsmith * 3. Neither the names of the above-listed copyright holders nor the names 2367754Smsmith * of any contributors may be used to endorse or promote products derived 2467754Smsmith * from this software without specific prior written permission. 2567754Smsmith * 2667754Smsmith * Alternatively, this software may be distributed under the terms of the 2767754Smsmith * GNU General Public License ("GPL") version 2 as published by the Free 2867754Smsmith * Software Foundation. 2967754Smsmith * 3067754Smsmith * NO WARRANTY 3167754Smsmith * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3267754Smsmith * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3367754Smsmith * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3467754Smsmith * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3567754Smsmith * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3667754Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3767754Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3867754Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3967754Smsmith * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4067754Smsmith * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4167754Smsmith * POSSIBILITY OF SUCH DAMAGES. 4267754Smsmith */ 4367754Smsmith 4467754Smsmith#define __TBXFLOAD_C__ 4567754Smsmith 4667754Smsmith#include <contrib/dev/acpica/include/acpi.h> 4767754Smsmith#include <contrib/dev/acpica/include/accommon.h> 4867754Smsmith#include <contrib/dev/acpica/include/acnamesp.h> 4967754Smsmith#include <contrib/dev/acpica/include/actables.h> 5067754Smsmith 5167754Smsmith#define _COMPONENT ACPI_TABLES 5267754Smsmith ACPI_MODULE_NAME ("tbxfload") 5367754Smsmith 5467754Smsmith/* Local prototypes */ 5567754Smsmith 5667754Smsmithstatic ACPI_STATUS 5767754SmsmithAcpiTbLoadNamespace ( 5867754Smsmith void); 5967754Smsmith 6067754Smsmith 6167754Smsmith/******************************************************************************* 6267754Smsmith * 6367754Smsmith * FUNCTION: AcpiLoadTables 6467754Smsmith * 6567754Smsmith * PARAMETERS: None 6667754Smsmith * 6767754Smsmith * RETURN: Status 6867754Smsmith * 6967754Smsmith * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT 7067754Smsmith * 7167754Smsmith ******************************************************************************/ 7267754Smsmith 7367754SmsmithACPI_STATUS 7467754SmsmithAcpiLoadTables ( 7567754Smsmith void) 7667754Smsmith{ 7767754Smsmith ACPI_STATUS Status; 7867754Smsmith 7967754Smsmith 8067754Smsmith ACPI_FUNCTION_TRACE (AcpiLoadTables); 8167754Smsmith 8267754Smsmith 8367754Smsmith /* Load the namespace from the tables */ 8467754Smsmith 8567754Smsmith Status = AcpiTbLoadNamespace (); 8667754Smsmith if (ACPI_FAILURE (Status)) 8767754Smsmith { 8867754Smsmith ACPI_EXCEPTION ((AE_INFO, Status, 8967754Smsmith "While loading namespace from ACPI tables")); 9067754Smsmith } 9167754Smsmith 9267754Smsmith return_ACPI_STATUS (Status); 9367754Smsmith} 9467754Smsmith 9567754SmsmithACPI_EXPORT_SYMBOL (AcpiLoadTables) 9667754Smsmith 9767754Smsmith 9867754Smsmith/******************************************************************************* 9967754Smsmith * 10067754Smsmith * FUNCTION: AcpiTbLoadNamespace 10167754Smsmith * 10267754Smsmith * PARAMETERS: None 10367754Smsmith * 10467754Smsmith * RETURN: Status 10567754Smsmith * 10667754Smsmith * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in 10767754Smsmith * the RSDT/XSDT. 10867754Smsmith * 10967754Smsmith ******************************************************************************/ 11067754Smsmith 11167754Smsmithstatic ACPI_STATUS 11267754SmsmithAcpiTbLoadNamespace ( 11367754Smsmith void) 11467754Smsmith{ 11567754Smsmith ACPI_STATUS Status; 11667754Smsmith UINT32 i; 11767754Smsmith ACPI_TABLE_HEADER *NewDsdt; 11867754Smsmith 11967754Smsmith 12067754Smsmith ACPI_FUNCTION_TRACE (TbLoadNamespace); 12167754Smsmith 12267754Smsmith 12367754Smsmith (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 12467754Smsmith 12577424Smsmith /* 12691116Smsmith * Load the namespace. The DSDT is required, but any SSDT and 12767754Smsmith * PSDT tables are optional. Verify the DSDT. 12867754Smsmith */ 12977424Smsmith if (!AcpiGbl_RootTableList.CurrentTableCount || 13067754Smsmith !ACPI_COMPARE_NAME ( 13167754Smsmith &(AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Signature), 13267754Smsmith ACPI_SIG_DSDT) || 13367754Smsmith ACPI_FAILURE (AcpiTbVerifyTable ( 13467754Smsmith &AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT]))) 13567754Smsmith { 13667754Smsmith Status = AE_NO_ACPI_TABLES; 13767754Smsmith goto UnlockAndExit; 13867754Smsmith } 13967754Smsmith 14067754Smsmith /* 14167754Smsmith * Save the DSDT pointer for simple access. This is the mapped memory 14267754Smsmith * address. We must take care here because the address of the .Tables 14367754Smsmith * array can change dynamically as tables are loaded at run-time. Note: 14467754Smsmith * .Pointer field is not validated until after call to AcpiTbVerifyTable. 14567754Smsmith */ 14667754Smsmith AcpiGbl_DSDT = AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer; 14767754Smsmith 14877424Smsmith /* 14977424Smsmith * Optionally copy the entire DSDT to local memory (instead of simply 15077424Smsmith * mapping it.) There are some BIOSs that corrupt or replace the original 15167754Smsmith * DSDT, creating the need for this option. Default is FALSE, do not copy 15267754Smsmith * the DSDT. 15367754Smsmith */ 15467754Smsmith if (AcpiGbl_CopyDsdtLocally) 15567754Smsmith { 15691116Smsmith NewDsdt = AcpiTbCopyDsdt (ACPI_TABLE_INDEX_DSDT); 15791116Smsmith if (NewDsdt) 15867754Smsmith { 15967754Smsmith AcpiGbl_DSDT = NewDsdt; 16067754Smsmith } 16191116Smsmith } 16267754Smsmith 16377424Smsmith /* 16467754Smsmith * Save the original DSDT header for detection of table corruption 16567754Smsmith * and/or replacement of the DSDT from outside the OS. 16691116Smsmith */ 16767754Smsmith ACPI_MEMCPY (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, 16867754Smsmith sizeof (ACPI_TABLE_HEADER)); 16967754Smsmith 17067754Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 17191116Smsmith 17291116Smsmith /* Load and parse tables */ 17391116Smsmith 17491116Smsmith Status = AcpiNsLoadTable (ACPI_TABLE_INDEX_DSDT, AcpiGbl_RootNode); 17591116Smsmith if (ACPI_FAILURE (Status)) 17667754Smsmith { 17767754Smsmith return_ACPI_STATUS (Status); 17867754Smsmith } 17985756Smsmith 18067754Smsmith /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ 18167754Smsmith 18267754Smsmith (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 18367754Smsmith for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) 18467754Smsmith { 18567754Smsmith if ((!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), 18667754Smsmith ACPI_SIG_SSDT) && 18785756Smsmith !ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), 18885756Smsmith ACPI_SIG_PSDT)) || 18985756Smsmith ACPI_FAILURE (AcpiTbVerifyTable ( 19067754Smsmith &AcpiGbl_RootTableList.Tables[i]))) 19167754Smsmith { 19267754Smsmith continue; 19367754Smsmith } 19467754Smsmith 19567754Smsmith /* 19667754Smsmith * Optionally do not load any SSDTs from the RSDT/XSDT. This can 19767754Smsmith * be useful for debugging ACPI problems on some machines. 19867754Smsmith */ 19967754Smsmith if (AcpiGbl_DisableSsdtTableLoad) 20067754Smsmith { 20167754Smsmith ACPI_INFO ((AE_INFO, "Ignoring %4.4s at %p", 20291116Smsmith AcpiGbl_RootTableList.Tables[i].Signature.Ascii, 20367754Smsmith ACPI_CAST_PTR (void, AcpiGbl_RootTableList.Tables[i].Address))); 20467754Smsmith continue; 20567754Smsmith } 20677424Smsmith 20777424Smsmith /* Ignore errors while loading tables, get as many as possible */ 20884491Smsmith 20967754Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 21067754Smsmith (void) AcpiNsLoadTable (i, AcpiGbl_RootNode); 21177424Smsmith (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 21277424Smsmith } 21384491Smsmith 21467754Smsmith ACPI_INFO ((AE_INFO, "All ACPI Tables successfully acquired")); 21567754Smsmith 21677424SmsmithUnlockAndExit: 21777424Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 21884491Smsmith return_ACPI_STATUS (Status); 21967754Smsmith} 22067754Smsmith 22184491Smsmith 22284491Smsmith/******************************************************************************* 22384491Smsmith * 22484491Smsmith * FUNCTION: AcpiLoadTable 22584491Smsmith * 22684491Smsmith * PARAMETERS: Table - Pointer to a buffer containing the ACPI 22784491Smsmith * table to be loaded. 22884491Smsmith * 22984491Smsmith * RETURN: Status 23084491Smsmith * 23191116Smsmith * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must 23291116Smsmith * be a valid ACPI table with a valid ACPI table header. 23391116Smsmith * Note1: Mainly intended to support hotplug addition of SSDTs. 23491116Smsmith * Note2: Does not copy the incoming table. User is responsible 23591116Smsmith * to ensure that the table is not deleted or unmapped. 23667754Smsmith * 237117521Snjl ******************************************************************************/ 23867754Smsmith 23967754SmsmithACPI_STATUS 24067754SmsmithAcpiLoadTable ( 24167754Smsmith ACPI_TABLE_HEADER *Table) 242117521Snjl{ 243117521Snjl ACPI_STATUS Status; 24467754Smsmith ACPI_TABLE_DESC TableDesc; 24567754Smsmith UINT32 TableIndex; 24667754Smsmith 24767754Smsmith 24867754Smsmith ACPI_FUNCTION_TRACE (AcpiLoadTable); 249117521Snjl 250117521Snjl 25177424Smsmith /* Parameter validation */ 25267754Smsmith 25367754Smsmith if (!Table) 25467754Smsmith { 255117521Snjl return_ACPI_STATUS (AE_BAD_PARAMETER); 25685756Smsmith } 25767754Smsmith 258117521Snjl /* Init local table descriptor */ 25967754Smsmith 260117521Snjl ACPI_MEMSET (&TableDesc, 0, sizeof (ACPI_TABLE_DESC)); 26167754Smsmith TableDesc.Address = ACPI_PTR_TO_PHYSADDR (Table); 26267754Smsmith TableDesc.Pointer = Table; 26367754Smsmith TableDesc.Length = Table->Length; 264117521Snjl TableDesc.Flags = ACPI_TABLE_ORIGIN_UNKNOWN; 265117521Snjl 266117521Snjl /* Must acquire the interpreter lock during this operation */ 26767754Smsmith 268117521Snjl Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); 269117521Snjl if (ACPI_FAILURE (Status)) 270117521Snjl { 271117521Snjl return_ACPI_STATUS (Status); 272117521Snjl } 273117521Snjl 274117521Snjl /* Install the table and load it into the namespace */ 275117521Snjl 276117521Snjl ACPI_INFO ((AE_INFO, "Host-directed Dynamic ACPI Table Load:")); 277117521Snjl Status = AcpiTbAddTable (&TableDesc, &TableIndex); 278117521Snjl if (ACPI_FAILURE (Status)) 279117521Snjl { 280117521Snjl goto UnlockAndExit; 281117521Snjl } 282117521Snjl 28367754Smsmith Status = AcpiNsLoadTable (TableIndex, AcpiGbl_RootNode); 28467754Smsmith 28567754Smsmith /* Invoke table handler if present */ 286117521Snjl 287117521Snjl if (AcpiGbl_TableHandler) 288117521Snjl { 28967754Smsmith (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, 29067754Smsmith AcpiGbl_TableHandlerContext); 29167754Smsmith } 29267754Smsmith 29382367SmsmithUnlockAndExit: 29482367Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); 29567754Smsmith return_ACPI_STATUS (Status); 29667754Smsmith} 29767754Smsmith 29867754SmsmithACPI_EXPORT_SYMBOL (AcpiLoadTable) 29967754Smsmith 30067754Smsmith 30167754Smsmith/******************************************************************************* 30267754Smsmith * 30367754Smsmith * FUNCTION: AcpiUnloadParentTable 30467754Smsmith * 30567754Smsmith * PARAMETERS: Object - Handle to any namespace object owned by 30667754Smsmith * the table to be unloaded 30777424Smsmith * 30867754Smsmith * RETURN: Status 30967754Smsmith * 31067754Smsmith * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads 31167754Smsmith * the table and deletes all namespace objects associated with 31267754Smsmith * that table. Unloading of the DSDT is not allowed. 31367754Smsmith * Note: Mainly intended to support hotplug removal of SSDTs. 31467754Smsmith * 31567754Smsmith ******************************************************************************/ 31667754Smsmith 31767754SmsmithACPI_STATUS 31867754SmsmithAcpiUnloadParentTable ( 31967754Smsmith ACPI_HANDLE Object) 32091116Smsmith{ 321117521Snjl ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Object); 322117521Snjl ACPI_STATUS Status = AE_NOT_EXIST; 323117521Snjl ACPI_OWNER_ID OwnerId; 324117521Snjl UINT32 i; 325117521Snjl 32667754Smsmith 32767754Smsmith ACPI_FUNCTION_TRACE (AcpiUnloadParentTable); 32867754Smsmith 32967754Smsmith 33067754Smsmith /* Parameter validation */ 33167754Smsmith 33282367Smsmith if (!Object) 333107325Siwasaki { 334107325Siwasaki return_ACPI_STATUS (AE_BAD_PARAMETER); 33567754Smsmith } 33667754Smsmith 337117521Snjl /* 33867754Smsmith * The node OwnerId is currently the same as the parent table ID. 339117521Snjl * However, this could change in the future. 340117521Snjl */ 34185756Smsmith OwnerId = Node->OwnerId; 34267754Smsmith if (!OwnerId) 343107325Siwasaki { 34467754Smsmith /* OwnerId==0 means DSDT is the owner. DSDT cannot be unloaded */ 34567754Smsmith 34667754Smsmith return_ACPI_STATUS (AE_TYPE); 34767754Smsmith } 34867754Smsmith 34967754Smsmith /* Must acquire the interpreter lock during this operation */ 350117521Snjl 35167754Smsmith Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); 352117521Snjl if (ACPI_FAILURE (Status)) 353117521Snjl { 354117521Snjl return_ACPI_STATUS (Status); 355117521Snjl } 356117521Snjl 357117521Snjl /* Find the table in the global table list */ 358117521Snjl 359117521Snjl for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 360117521Snjl { 361117521Snjl if (OwnerId != AcpiGbl_RootTableList.Tables[i].OwnerId) 362117521Snjl { 363117521Snjl continue; 36467754Smsmith } 365117521Snjl 366117521Snjl /* 367117521Snjl * Allow unload of SSDT and OEMx tables only. Do not allow unload 368117521Snjl * of the DSDT. No other types of tables should get here, since 369117521Snjl * only these types can contain AML and thus are the only types 370117521Snjl * that can create namespace objects. 371117521Snjl */ 37285756Smsmith if (ACPI_COMPARE_NAME ( 37367754Smsmith AcpiGbl_RootTableList.Tables[i].Signature.Ascii, 374117521Snjl ACPI_SIG_DSDT)) 37585756Smsmith { 37685756Smsmith Status = AE_TYPE; 37785756Smsmith break; 37867754Smsmith } 379117521Snjl 38085756Smsmith /* Ensure the table is actually loaded */ 38167754Smsmith 382117521Snjl if (!AcpiTbIsTableLoaded (i)) 383117521Snjl { 384117521Snjl Status = AE_NOT_EXIST; 38567754Smsmith break; 38667754Smsmith } 38791116Smsmith 38867754Smsmith /* Invoke table handler if present */ 38967754Smsmith 39067754Smsmith if (AcpiGbl_TableHandler) 39167754Smsmith { 39277424Smsmith (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, 39367754Smsmith AcpiGbl_RootTableList.Tables[i].Pointer, 39467754Smsmith AcpiGbl_TableHandlerContext); 39567754Smsmith } 396117521Snjl 397117521Snjl /* 39867754Smsmith * Delete all namespace objects owned by this table. Note that 39967754Smsmith * these objects can appear anywhere in the namespace by virtue 40067754Smsmith * of the AML "Scope" operator. Thus, we need to track ownership 40167754Smsmith * by an ID, not simply a position within the hierarchy. 402117521Snjl */ 40367754Smsmith Status = AcpiTbDeleteNamespaceByOwner (i); 40467754Smsmith if (ACPI_FAILURE (Status)) 40567754Smsmith { 40667754Smsmith break; 40767754Smsmith } 40867754Smsmith 40977424Smsmith Status = AcpiTbReleaseOwnerId (i); 41077424Smsmith AcpiTbSetTableLoadedFlag (i, FALSE); 41167754Smsmith break; 41267754Smsmith } 41367754Smsmith 41467754Smsmith (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); 41567754Smsmith return_ACPI_STATUS (Status); 41667754Smsmith} 41791116Smsmith 41867754SmsmithACPI_EXPORT_SYMBOL (AcpiUnloadParentTable) 41967754Smsmith