167754Smsmith/****************************************************************************** 267754Smsmith * 377424Smsmith * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes) 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 970243Smsmith * All rights reserved. 1067754Smsmith * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 2567754Smsmith * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 2967754Smsmith * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 4367754Smsmith 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 46193341Sjkim#include <contrib/dev/acpica/include/acinterp.h> 47193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 48193341Sjkim#include <contrib/dev/acpica/include/actables.h> 49193341Sjkim#include <contrib/dev/acpica/include/acdispat.h> 50193341Sjkim#include <contrib/dev/acpica/include/acevents.h> 51245582Sjkim#include <contrib/dev/acpica/include/amlcode.h> 5267754Smsmith 5367754Smsmith 5477424Smsmith#define _COMPONENT ACPI_EXECUTER 5591116Smsmith ACPI_MODULE_NAME ("exconfig") 5667754Smsmith 57151937Sjkim/* Local prototypes */ 5867754Smsmith 59151937Sjkimstatic ACPI_STATUS 60151937SjkimAcpiExAddTable ( 61193267Sjkim UINT32 TableIndex, 62151937Sjkim ACPI_NAMESPACE_NODE *ParentNode, 63151937Sjkim ACPI_OPERAND_OBJECT **DdbHandle); 64151937Sjkim 65193267Sjkimstatic ACPI_STATUS 66193267SjkimAcpiExRegionRead ( 67193267Sjkim ACPI_OPERAND_OBJECT *ObjDesc, 68193267Sjkim UINT32 Length, 69193267Sjkim UINT8 *Buffer); 70151937Sjkim 71193267Sjkim 7291116Smsmith/******************************************************************************* 7367754Smsmith * 7491116Smsmith * FUNCTION: AcpiExAddTable 7591116Smsmith * 7691116Smsmith * PARAMETERS: Table - Pointer to raw table 7791116Smsmith * ParentNode - Where to load the table (scope) 7891116Smsmith * DdbHandle - Where to return the table handle. 7991116Smsmith * 8091116Smsmith * RETURN: Status 8191116Smsmith * 8291116Smsmith * DESCRIPTION: Common function to Install and Load an ACPI table with a 8391116Smsmith * returned table handle. 8491116Smsmith * 8591116Smsmith ******************************************************************************/ 8691116Smsmith 87151937Sjkimstatic ACPI_STATUS 8891116SmsmithAcpiExAddTable ( 89193267Sjkim UINT32 TableIndex, 9091116Smsmith ACPI_NAMESPACE_NODE *ParentNode, 9191116Smsmith ACPI_OPERAND_OBJECT **DdbHandle) 9291116Smsmith{ 93207344Sjkim ACPI_OPERAND_OBJECT *ObjDesc; 9491116Smsmith ACPI_STATUS Status; 95207344Sjkim ACPI_OWNER_ID OwnerId; 9691116Smsmith 9791116Smsmith 98167802Sjkim ACPI_FUNCTION_TRACE (ExAddTable); 9991116Smsmith 10091116Smsmith 10191116Smsmith /* Create an object to be the table handle */ 10291116Smsmith 103107325Siwasaki ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); 10491116Smsmith if (!ObjDesc) 10591116Smsmith { 10691116Smsmith return_ACPI_STATUS (AE_NO_MEMORY); 10791116Smsmith } 10891116Smsmith 109151937Sjkim /* Init the table handle */ 110151937Sjkim 111193267Sjkim ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID; 112193267Sjkim ObjDesc->Reference.Class = ACPI_REFCLASS_TABLE; 113151937Sjkim *DdbHandle = ObjDesc; 114151937Sjkim 11591116Smsmith /* Install the new table into the local data structures */ 11691116Smsmith 117193267Sjkim ObjDesc->Reference.Value = TableIndex; 118123315Snjl 11991116Smsmith /* Add the table to the namespace */ 12091116Smsmith 121167802Sjkim Status = AcpiNsLoadTable (TableIndex, ParentNode); 12291116Smsmith if (ACPI_FAILURE (Status)) 12391116Smsmith { 124167802Sjkim AcpiUtRemoveReference (ObjDesc); 125167802Sjkim *DdbHandle = NULL; 126197104Sjkim return_ACPI_STATUS (Status); 12791116Smsmith } 12891116Smsmith 129197104Sjkim /* Execute any module-level code that was found in the table */ 130197104Sjkim 131197104Sjkim AcpiExExitInterpreter (); 132306536Sjkim if (AcpiGbl_GroupModuleLevelCode) 133306536Sjkim { 134306536Sjkim AcpiNsExecModuleCodeList (); 135306536Sjkim } 136197104Sjkim AcpiExEnterInterpreter (); 137197104Sjkim 138216471Sjkim /* 139216471Sjkim * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is 140216471Sjkim * responsible for discovering any new wake GPEs by running _PRW methods 141216471Sjkim * that may have been loaded by this table. 142216471Sjkim */ 143207344Sjkim Status = AcpiTbGetOwnerId (TableIndex, &OwnerId); 144207344Sjkim if (ACPI_SUCCESS (Status)) 145207344Sjkim { 146207344Sjkim AcpiEvUpdateGpes (OwnerId); 147207344Sjkim } 148207344Sjkim 149207344Sjkim return_ACPI_STATUS (AE_OK); 15091116Smsmith} 15191116Smsmith 15291116Smsmith 15391116Smsmith/******************************************************************************* 15491116Smsmith * 15577424Smsmith * FUNCTION: AcpiExLoadTableOp 15667754Smsmith * 15791116Smsmith * PARAMETERS: WalkState - Current state with operands 15891116Smsmith * ReturnDesc - Where to store the return object 15967754Smsmith * 16067754Smsmith * RETURN: Status 16167754Smsmith * 162167802Sjkim * DESCRIPTION: Load an ACPI table from the RSDT/XSDT 16367754Smsmith * 16491116Smsmith ******************************************************************************/ 16567754Smsmith 16685756SmsmithACPI_STATUS 16791116SmsmithAcpiExLoadTableOp ( 16891116Smsmith ACPI_WALK_STATE *WalkState, 16991116Smsmith ACPI_OPERAND_OBJECT **ReturnDesc) 17067754Smsmith{ 17167754Smsmith ACPI_STATUS Status; 17291116Smsmith ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 17391116Smsmith ACPI_NAMESPACE_NODE *ParentNode; 17491116Smsmith ACPI_NAMESPACE_NODE *StartNode; 17591116Smsmith ACPI_NAMESPACE_NODE *ParameterNode = NULL; 17691116Smsmith ACPI_OPERAND_OBJECT *DdbHandle; 177167802Sjkim ACPI_TABLE_HEADER *Table; 178193267Sjkim UINT32 TableIndex; 17967754Smsmith 18067754Smsmith 181167802Sjkim ACPI_FUNCTION_TRACE (ExLoadTableOp); 18267754Smsmith 18367754Smsmith 184167802Sjkim /* Find the ACPI table in the RSDT/XSDT */ 18567754Smsmith 186245582Sjkim Status = AcpiTbFindTable ( 187306536Sjkim Operand[0]->String.Pointer, 188306536Sjkim Operand[1]->String.Pointer, 189306536Sjkim Operand[2]->String.Pointer, &TableIndex); 19091116Smsmith if (ACPI_FAILURE (Status)) 19167754Smsmith { 19291116Smsmith if (Status != AE_NOT_FOUND) 19391116Smsmith { 19491116Smsmith return_ACPI_STATUS (Status); 19591116Smsmith } 19691116Smsmith 197123315Snjl /* Table not found, return an Integer=0 and AE_OK */ 19891116Smsmith 199199337Sjkim DdbHandle = AcpiUtCreateIntegerObject ((UINT64) 0); 20091116Smsmith if (!DdbHandle) 20191116Smsmith { 20291116Smsmith return_ACPI_STATUS (AE_NO_MEMORY); 20391116Smsmith } 20491116Smsmith 20591116Smsmith *ReturnDesc = DdbHandle; 20691116Smsmith return_ACPI_STATUS (AE_OK); 20791116Smsmith } 20891116Smsmith 20991116Smsmith /* Default nodes */ 21091116Smsmith 21191116Smsmith StartNode = WalkState->ScopeInfo->Scope.Node; 21291116Smsmith ParentNode = AcpiGbl_RootNode; 21391116Smsmith 21491116Smsmith /* RootPath (optional parameter) */ 21591116Smsmith 21691116Smsmith if (Operand[3]->String.Length > 0) 21791116Smsmith { 21891116Smsmith /* 219241973Sjkim * Find the node referenced by the RootPathString. This is the 22091116Smsmith * location within the namespace where the table will be loaded. 22191116Smsmith */ 222167802Sjkim Status = AcpiNsGetNode (StartNode, Operand[3]->String.Pointer, 223306536Sjkim ACPI_NS_SEARCH_PARENT, &ParentNode); 22467754Smsmith if (ACPI_FAILURE (Status)) 22567754Smsmith { 22667754Smsmith return_ACPI_STATUS (Status); 22767754Smsmith } 22867754Smsmith } 22967754Smsmith 23091116Smsmith /* ParameterPath (optional parameter) */ 23167754Smsmith 23291116Smsmith if (Operand[4]->String.Length > 0) 23367754Smsmith { 234245582Sjkim if ((Operand[4]->String.Pointer[0] != AML_ROOT_PREFIX) && 235245582Sjkim (Operand[4]->String.Pointer[0] != AML_PARENT_PREFIX)) 23691116Smsmith { 23791116Smsmith /* 23891116Smsmith * Path is not absolute, so it will be relative to the node 23991116Smsmith * referenced by the RootPathString (or the NS root if omitted) 24091116Smsmith */ 24191116Smsmith StartNode = ParentNode; 24291116Smsmith } 24391116Smsmith 244151937Sjkim /* Find the node referenced by the ParameterPathString */ 245151937Sjkim 246167802Sjkim Status = AcpiNsGetNode (StartNode, Operand[4]->String.Pointer, 247306536Sjkim ACPI_NS_SEARCH_PARENT, &ParameterNode); 24891116Smsmith if (ACPI_FAILURE (Status)) 24991116Smsmith { 25091116Smsmith return_ACPI_STATUS (Status); 25191116Smsmith } 25267754Smsmith } 25367754Smsmith 25491116Smsmith /* Load the table into the namespace */ 25567754Smsmith 256167802Sjkim Status = AcpiExAddTable (TableIndex, ParentNode, &DdbHandle); 25791116Smsmith if (ACPI_FAILURE (Status)) 25891116Smsmith { 25991116Smsmith return_ACPI_STATUS (Status); 26091116Smsmith } 26167754Smsmith 26291116Smsmith /* Parameter Data (optional) */ 26367754Smsmith 26491116Smsmith if (ParameterNode) 26591116Smsmith { 26691116Smsmith /* Store the parameter data into the optional parameter object */ 26767754Smsmith 268151937Sjkim Status = AcpiExStore (Operand[5], 269306536Sjkim ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParameterNode), WalkState); 27091116Smsmith if (ACPI_FAILURE (Status)) 27191116Smsmith { 27299679Siwasaki (void) AcpiExUnloadTable (DdbHandle); 273193267Sjkim 274193267Sjkim AcpiUtRemoveReference (DdbHandle); 275123315Snjl return_ACPI_STATUS (Status); 27691116Smsmith } 27791116Smsmith } 27891116Smsmith 279167802Sjkim Status = AcpiGetTableByIndex (TableIndex, &Table); 280167802Sjkim if (ACPI_SUCCESS (Status)) 281167802Sjkim { 282306536Sjkim ACPI_INFO (("Dynamic OEM Table Load:")); 283207344Sjkim AcpiTbPrintTableHeader (0, Table); 284167802Sjkim } 285167802Sjkim 286193267Sjkim /* Invoke table handler if present */ 287193267Sjkim 288193267Sjkim if (AcpiGbl_TableHandler) 289193267Sjkim { 290193267Sjkim (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, 291306536Sjkim AcpiGbl_TableHandlerContext); 292193267Sjkim } 293193267Sjkim 294123315Snjl *ReturnDesc = DdbHandle; 295245582Sjkim return_ACPI_STATUS (Status); 29691116Smsmith} 29791116Smsmith 29891116Smsmith 29991116Smsmith/******************************************************************************* 30091116Smsmith * 301193267Sjkim * FUNCTION: AcpiExRegionRead 302193267Sjkim * 303193267Sjkim * PARAMETERS: ObjDesc - Region descriptor 304193267Sjkim * Length - Number of bytes to read 305193267Sjkim * Buffer - Pointer to where to put the data 306193267Sjkim * 307193267Sjkim * RETURN: Status 308193267Sjkim * 309193267Sjkim * DESCRIPTION: Read data from an operation region. The read starts from the 310193267Sjkim * beginning of the region. 311193267Sjkim * 312193267Sjkim ******************************************************************************/ 313193267Sjkim 314193267Sjkimstatic ACPI_STATUS 315193267SjkimAcpiExRegionRead ( 316193267Sjkim ACPI_OPERAND_OBJECT *ObjDesc, 317193267Sjkim UINT32 Length, 318193267Sjkim UINT8 *Buffer) 319193267Sjkim{ 320193267Sjkim ACPI_STATUS Status; 321202771Sjkim UINT64 Value; 322193267Sjkim UINT32 RegionOffset = 0; 323193267Sjkim UINT32 i; 324193267Sjkim 325193267Sjkim 326193267Sjkim /* Bytewise reads */ 327193267Sjkim 328193267Sjkim for (i = 0; i < Length; i++) 329193267Sjkim { 330228110Sjkim Status = AcpiEvAddressSpaceDispatch (ObjDesc, NULL, ACPI_READ, 331306536Sjkim RegionOffset, 8, &Value); 332193267Sjkim if (ACPI_FAILURE (Status)) 333193267Sjkim { 334193267Sjkim return (Status); 335193267Sjkim } 336193267Sjkim 337193267Sjkim *Buffer = (UINT8) Value; 338193267Sjkim Buffer++; 339193267Sjkim RegionOffset++; 340193267Sjkim } 341193267Sjkim 342193267Sjkim return (AE_OK); 343193267Sjkim} 344193267Sjkim 345193267Sjkim 346193267Sjkim/******************************************************************************* 347193267Sjkim * 34891116Smsmith * FUNCTION: AcpiExLoadOp 34991116Smsmith * 350167802Sjkim * PARAMETERS: ObjDesc - Region or Buffer/Field where the table will be 35191116Smsmith * obtained 35291116Smsmith * Target - Where a handle to the table will be stored 35391116Smsmith * WalkState - Current state 35491116Smsmith * 35591116Smsmith * RETURN: Status 35691116Smsmith * 35791116Smsmith * DESCRIPTION: Load an ACPI table from a field or operation region 35891116Smsmith * 359167802Sjkim * NOTE: Region Fields (Field, BankField, IndexFields) are resolved to buffer 360167802Sjkim * objects before this code is reached. 361167802Sjkim * 362167802Sjkim * If source is an operation region, it must refer to SystemMemory, as 363167802Sjkim * per the ACPI specification. 364167802Sjkim * 36591116Smsmith ******************************************************************************/ 36691116Smsmith 36791116SmsmithACPI_STATUS 36891116SmsmithAcpiExLoadOp ( 36991116Smsmith ACPI_OPERAND_OBJECT *ObjDesc, 37091116Smsmith ACPI_OPERAND_OBJECT *Target, 37191116Smsmith ACPI_WALK_STATE *WalkState) 37291116Smsmith{ 373167802Sjkim ACPI_OPERAND_OBJECT *DdbHandle; 374281075Sdim ACPI_TABLE_HEADER *TableHeader; 375193267Sjkim ACPI_TABLE_HEADER *Table; 376193267Sjkim UINT32 TableIndex; 37791116Smsmith ACPI_STATUS Status; 378193267Sjkim UINT32 Length; 37991116Smsmith 38091116Smsmith 381167802Sjkim ACPI_FUNCTION_TRACE (ExLoadOp); 38291116Smsmith 38391116Smsmith 384167802Sjkim /* Source Object can be either an OpRegion or a Buffer/Field */ 385167802Sjkim 386193267Sjkim switch (ObjDesc->Common.Type) 38767754Smsmith { 38891116Smsmith case ACPI_TYPE_REGION: 38991116Smsmith 390193267Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 391193267Sjkim "Load table from Region %p\n", ObjDesc)); 392193267Sjkim 393167802Sjkim /* Region must be SystemMemory (from ACPI spec) */ 394167802Sjkim 395167802Sjkim if (ObjDesc->Region.SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) 396167802Sjkim { 397167802Sjkim return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 398167802Sjkim } 399167802Sjkim 400129684Snjl /* 401306536Sjkim * If the Region Address and Length have not been previously 402306536Sjkim * evaluated, evaluate them now and save the results. 403129684Snjl */ 404129684Snjl if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 405129684Snjl { 406129684Snjl Status = AcpiDsGetRegionArguments (ObjDesc); 407129684Snjl if (ACPI_FAILURE (Status)) 408129684Snjl { 409129684Snjl return_ACPI_STATUS (Status); 410129684Snjl } 411129684Snjl } 41291116Smsmith 413193267Sjkim /* Get the table header first so we can get the table length */ 414193267Sjkim 415281075Sdim TableHeader = ACPI_ALLOCATE (sizeof (ACPI_TABLE_HEADER)); 416281075Sdim if (!TableHeader) 417193267Sjkim { 418193267Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 419193267Sjkim } 420193267Sjkim 421193267Sjkim Status = AcpiExRegionRead (ObjDesc, sizeof (ACPI_TABLE_HEADER), 422306536Sjkim ACPI_CAST_PTR (UINT8, TableHeader)); 423281075Sdim Length = TableHeader->Length; 424281075Sdim ACPI_FREE (TableHeader); 425193267Sjkim 426193267Sjkim if (ACPI_FAILURE (Status)) 427193267Sjkim { 428193267Sjkim return_ACPI_STATUS (Status); 429193267Sjkim } 430193267Sjkim 431193267Sjkim /* Must have at least an ACPI table header */ 432193267Sjkim 433193267Sjkim if (Length < sizeof (ACPI_TABLE_HEADER)) 434193267Sjkim { 435193267Sjkim return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 436193267Sjkim } 437193267Sjkim 438193267Sjkim /* 439193267Sjkim * The original implementation simply mapped the table, with no copy. 440193267Sjkim * However, the memory region is not guaranteed to remain stable and 441193267Sjkim * we must copy the table to a local buffer. For example, the memory 442193267Sjkim * region is corrupted after suspend on some machines. Dynamically 443193267Sjkim * loaded tables are usually small, so this overhead is minimal. 444193267Sjkim * 445193267Sjkim * The latest implementation (5/2009) does not use a mapping at all. 446193267Sjkim * We use the low-level operation region interface to read the table 447193267Sjkim * instead of the obvious optimization of using a direct mapping. 448193267Sjkim * This maintains a consistent use of operation regions across the 449193267Sjkim * entire subsystem. This is important if additional processing must 450193267Sjkim * be performed in the (possibly user-installed) operation region 451193267Sjkim * handler. For example, AcpiExec and ASLTS depend on this. 452193267Sjkim */ 453193267Sjkim 454193267Sjkim /* Allocate a buffer for the table */ 455193267Sjkim 456281075Sdim Table = ACPI_ALLOCATE (Length); 457281075Sdim if (!Table) 458193267Sjkim { 459193267Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 460193267Sjkim } 461193267Sjkim 462193267Sjkim /* Read the entire table */ 463193267Sjkim 464193267Sjkim Status = AcpiExRegionRead (ObjDesc, Length, 465306536Sjkim ACPI_CAST_PTR (UINT8, Table)); 466193267Sjkim if (ACPI_FAILURE (Status)) 467193267Sjkim { 468281075Sdim ACPI_FREE (Table); 469193267Sjkim return_ACPI_STATUS (Status); 470193267Sjkim } 47191116Smsmith break; 47291116Smsmith 473167802Sjkim case ACPI_TYPE_BUFFER: /* Buffer or resolved RegionField */ 47491116Smsmith 475193267Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 476193267Sjkim "Load table from Buffer or Field %p\n", ObjDesc)); 47791116Smsmith 478193267Sjkim /* Must have at least an ACPI table header */ 47991116Smsmith 480193267Sjkim if (ObjDesc->Buffer.Length < sizeof (ACPI_TABLE_HEADER)) 481193267Sjkim { 482193267Sjkim return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 483193267Sjkim } 48491116Smsmith 485193267Sjkim /* Get the actual table length from the table header */ 486193267Sjkim 487306536Sjkim TableHeader = ACPI_CAST_PTR ( 488306536Sjkim ACPI_TABLE_HEADER, ObjDesc->Buffer.Pointer); 489281075Sdim Length = TableHeader->Length; 490193267Sjkim 491193267Sjkim /* Table cannot extend beyond the buffer */ 492193267Sjkim 493193267Sjkim if (Length > ObjDesc->Buffer.Length) 494193267Sjkim { 495193267Sjkim return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); 496193267Sjkim } 497193267Sjkim if (Length < sizeof (ACPI_TABLE_HEADER)) 498193267Sjkim { 499193267Sjkim return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 500193267Sjkim } 501193267Sjkim 502193267Sjkim /* 503306536Sjkim * Copy the table from the buffer because the buffer could be 504306536Sjkim * modified or even deleted in the future 505193267Sjkim */ 506281075Sdim Table = ACPI_ALLOCATE (Length); 507281075Sdim if (!Table) 508193267Sjkim { 509193267Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 510193267Sjkim } 511193267Sjkim 512306536Sjkim memcpy (Table, TableHeader, Length); 51391116Smsmith break; 51491116Smsmith 515250838Sjkim default: 516193267Sjkim 51791116Smsmith return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 51867754Smsmith } 51967754Smsmith 520281075Sdim /* Install the new table into the local data structures */ 521193267Sjkim 522306536Sjkim ACPI_INFO (("Dynamic OEM Table Load:")); 523281075Sdim (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 524281075Sdim 525281075Sdim Status = AcpiTbInstallStandardTable (ACPI_PTR_TO_PHYSADDR (Table), 526306536Sjkim ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, TRUE, TRUE, 527306536Sjkim &TableIndex); 528281075Sdim 529281075Sdim (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 530193267Sjkim if (ACPI_FAILURE (Status)) 531193267Sjkim { 532281075Sdim /* Delete allocated table buffer */ 533281075Sdim 534281075Sdim ACPI_FREE (Table); 535193267Sjkim return_ACPI_STATUS (Status); 536193267Sjkim } 537193267Sjkim 538281075Sdim /* 539281075Sdim * Note: Now table is "INSTALLED", it must be validated before 540281075Sdim * loading. 541281075Sdim */ 542306536Sjkim Status = AcpiTbValidateTable ( 543306536Sjkim &AcpiGbl_RootTableList.Tables[TableIndex]); 544167802Sjkim if (ACPI_FAILURE (Status)) 54567754Smsmith { 546202771Sjkim return_ACPI_STATUS (Status); 54767754Smsmith } 54867754Smsmith 549193267Sjkim /* 550193267Sjkim * Add the table to the namespace. 551193267Sjkim * 552193267Sjkim * Note: Load the table objects relative to the root of the namespace. 553193267Sjkim * This appears to go against the ACPI specification, but we do it for 554193267Sjkim * compatibility with other ACPI implementations. 555193267Sjkim */ 556167802Sjkim Status = AcpiExAddTable (TableIndex, AcpiGbl_RootNode, &DdbHandle); 55767754Smsmith if (ACPI_FAILURE (Status)) 55867754Smsmith { 559151937Sjkim /* On error, TablePtr was deallocated above */ 560151937Sjkim 561151937Sjkim return_ACPI_STATUS (Status); 56267754Smsmith } 56367754Smsmith 56491116Smsmith /* Store the DdbHandle into the Target operand */ 56567754Smsmith 56691116Smsmith Status = AcpiExStore (DdbHandle, Target, WalkState); 56767754Smsmith if (ACPI_FAILURE (Status)) 56867754Smsmith { 56999679Siwasaki (void) AcpiExUnloadTable (DdbHandle); 57067754Smsmith 571151937Sjkim /* TablePtr was deallocated above */ 57267754Smsmith 573193267Sjkim AcpiUtRemoveReference (DdbHandle); 574151937Sjkim return_ACPI_STATUS (Status); 575151937Sjkim } 57667754Smsmith 577193267Sjkim /* Remove the reference by added by AcpiExStore above */ 578193267Sjkim 579193267Sjkim AcpiUtRemoveReference (DdbHandle); 580193267Sjkim 581193267Sjkim /* Invoke table handler if present */ 582193267Sjkim 583193267Sjkim if (AcpiGbl_TableHandler) 584193267Sjkim { 585281075Sdim (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, 586306536Sjkim AcpiGbl_TableHandlerContext); 587193267Sjkim } 588193267Sjkim 58967754Smsmith return_ACPI_STATUS (Status); 59067754Smsmith} 59167754Smsmith 59267754Smsmith 59391116Smsmith/******************************************************************************* 59467754Smsmith * 59577424Smsmith * FUNCTION: AcpiExUnloadTable 59667754Smsmith * 59767754Smsmith * PARAMETERS: DdbHandle - Handle to a previously loaded table 59867754Smsmith * 59967754Smsmith * RETURN: Status 60067754Smsmith * 60167754Smsmith * DESCRIPTION: Unload an ACPI table 60267754Smsmith * 60391116Smsmith ******************************************************************************/ 60467754Smsmith 60585756SmsmithACPI_STATUS 60677424SmsmithAcpiExUnloadTable ( 60783174Smsmith ACPI_OPERAND_OBJECT *DdbHandle) 60867754Smsmith{ 609123315Snjl ACPI_STATUS Status = AE_OK; 61083174Smsmith ACPI_OPERAND_OBJECT *TableDesc = DdbHandle; 611193267Sjkim UINT32 TableIndex; 612193267Sjkim ACPI_TABLE_HEADER *Table; 61367754Smsmith 61467754Smsmith 615167802Sjkim ACPI_FUNCTION_TRACE (ExUnloadTable); 61667754Smsmith 61767754Smsmith 61883174Smsmith /* 619281075Sdim * Temporarily emit a warning so that the ASL for the machine can be 620281075Sdim * hopefully obtained. This is to say that the Unload() operator is 621281075Sdim * extremely rare if not completely unused. 622281075Sdim */ 623281075Sdim ACPI_WARNING ((AE_INFO, 624281075Sdim "Received request to unload an ACPI table")); 625281075Sdim 626281075Sdim /* 62783174Smsmith * Validate the handle 628193267Sjkim * Although the handle is partially validated in AcpiExReconfiguration() 62983174Smsmith * when it calls AcpiExResolveOperands(), the handle is more completely 63083174Smsmith * validated here. 631193267Sjkim * 632193267Sjkim * Handle must be a valid operand object of type reference. Also, the 633193267Sjkim * DdbHandle must still be marked valid (table has not been previously 634193267Sjkim * unloaded) 63567754Smsmith */ 63667754Smsmith if ((!DdbHandle) || 63799679Siwasaki (ACPI_GET_DESCRIPTOR_TYPE (DdbHandle) != ACPI_DESC_TYPE_OPERAND) || 638193267Sjkim (DdbHandle->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) || 639193267Sjkim (!(DdbHandle->Common.Flags & AOPOBJ_DATA_VALID))) 64067754Smsmith { 641249663Sjkim return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 64267754Smsmith } 64367754Smsmith 644167802Sjkim /* Get the table index from the DdbHandle */ 64567754Smsmith 646193267Sjkim TableIndex = TableDesc->Reference.Value; 64767754Smsmith 648193267Sjkim /* Ensure the table is still loaded */ 64967754Smsmith 650193267Sjkim if (!AcpiTbIsTableLoaded (TableIndex)) 651193267Sjkim { 652193267Sjkim return_ACPI_STATUS (AE_NOT_EXIST); 653193267Sjkim } 654193267Sjkim 655193267Sjkim /* Invoke table handler if present */ 656193267Sjkim 657193267Sjkim if (AcpiGbl_TableHandler) 658193267Sjkim { 659193267Sjkim Status = AcpiGetTableByIndex (TableIndex, &Table); 660193267Sjkim if (ACPI_SUCCESS (Status)) 661193267Sjkim { 662193267Sjkim (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, Table, 663306536Sjkim AcpiGbl_TableHandlerContext); 664193267Sjkim } 665193267Sjkim } 666193267Sjkim 667193267Sjkim /* Delete the portion of the namespace owned by this table */ 668193267Sjkim 669193267Sjkim Status = AcpiTbDeleteNamespaceByOwner (TableIndex); 670193267Sjkim if (ACPI_FAILURE (Status)) 671193267Sjkim { 672193267Sjkim return_ACPI_STATUS (Status); 673193267Sjkim } 674193267Sjkim 675193267Sjkim (void) AcpiTbReleaseOwnerId (TableIndex); 676167802Sjkim AcpiTbSetTableLoadedFlag (TableIndex, FALSE); 67767754Smsmith 678193267Sjkim /* 679193267Sjkim * Invalidate the handle. We do this because the handle may be stored 680193267Sjkim * in a named object and may not be actually deleted until much later. 681193267Sjkim */ 682193267Sjkim DdbHandle->Common.Flags &= ~AOPOBJ_DATA_VALID; 683193267Sjkim return_ACPI_STATUS (AE_OK); 68467754Smsmith} 685