1db2bae30SDana Myers /****************************************************************************** 2db2bae30SDana Myers * 3db2bae30SDana Myers * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes) 4db2bae30SDana Myers * 5db2bae30SDana Myers *****************************************************************************/ 6db2bae30SDana Myers 726f3cdf0SGordon Ross /* 8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp. 9db2bae30SDana Myers * All rights reserved. 10db2bae30SDana Myers * 1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without 1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions 1326f3cdf0SGordon Ross * are met: 1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright 1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer, 1626f3cdf0SGordon Ross * without modification. 1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below 1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon 2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further 2126f3cdf0SGordon Ross * binary redistribution. 2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names 2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived 2426f3cdf0SGordon Ross * from this software without specific prior written permission. 25db2bae30SDana Myers * 2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the 2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free 2826f3cdf0SGordon Ross * Software Foundation. 29db2bae30SDana Myers * 3026f3cdf0SGordon Ross * NO WARRANTY 3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES. 4226f3cdf0SGordon Ross */ 43db2bae30SDana Myers 44db2bae30SDana Myers #include "acpi.h" 45aa2aa9a6SDana Myers #include "accommon.h" 46db2bae30SDana Myers #include "acinterp.h" 47db2bae30SDana Myers #include "acnamesp.h" 48db2bae30SDana Myers #include "actables.h" 49db2bae30SDana Myers #include "acdispat.h" 50aa2aa9a6SDana Myers #include "acevents.h" 51*385cc6b4SJerry Jelinek #include "amlcode.h" 52db2bae30SDana Myers 53db2bae30SDana Myers 54db2bae30SDana Myers #define _COMPONENT ACPI_EXECUTER 55db2bae30SDana Myers ACPI_MODULE_NAME ("exconfig") 56db2bae30SDana Myers 57db2bae30SDana Myers /* Local prototypes */ 58db2bae30SDana Myers 59db2bae30SDana Myers static ACPI_STATUS 60db2bae30SDana Myers AcpiExAddTable ( 61db2bae30SDana Myers UINT32 TableIndex, 62db2bae30SDana Myers ACPI_NAMESPACE_NODE *ParentNode, 63db2bae30SDana Myers ACPI_OPERAND_OBJECT **DdbHandle); 64db2bae30SDana Myers 65aa2aa9a6SDana Myers static ACPI_STATUS 66aa2aa9a6SDana Myers AcpiExRegionRead ( 67aa2aa9a6SDana Myers ACPI_OPERAND_OBJECT *ObjDesc, 68aa2aa9a6SDana Myers UINT32 Length, 69aa2aa9a6SDana Myers UINT8 *Buffer); 70aa2aa9a6SDana Myers 71db2bae30SDana Myers 72db2bae30SDana Myers /******************************************************************************* 73db2bae30SDana Myers * 74db2bae30SDana Myers * FUNCTION: AcpiExAddTable 75db2bae30SDana Myers * 76db2bae30SDana Myers * PARAMETERS: Table - Pointer to raw table 77db2bae30SDana Myers * ParentNode - Where to load the table (scope) 78db2bae30SDana Myers * DdbHandle - Where to return the table handle. 79db2bae30SDana Myers * 80db2bae30SDana Myers * RETURN: Status 81db2bae30SDana Myers * 82db2bae30SDana Myers * DESCRIPTION: Common function to Install and Load an ACPI table with a 83db2bae30SDana Myers * returned table handle. 84db2bae30SDana Myers * 85db2bae30SDana Myers ******************************************************************************/ 86db2bae30SDana Myers 87db2bae30SDana Myers static ACPI_STATUS 88db2bae30SDana Myers AcpiExAddTable ( 89db2bae30SDana Myers UINT32 TableIndex, 90db2bae30SDana Myers ACPI_NAMESPACE_NODE *ParentNode, 91db2bae30SDana Myers ACPI_OPERAND_OBJECT **DdbHandle) 92db2bae30SDana Myers { 93db2bae30SDana Myers ACPI_OPERAND_OBJECT *ObjDesc; 9426f3cdf0SGordon Ross ACPI_STATUS Status; 9526f3cdf0SGordon Ross ACPI_OWNER_ID OwnerId; 96db2bae30SDana Myers 97db2bae30SDana Myers 98db2bae30SDana Myers ACPI_FUNCTION_TRACE (ExAddTable); 99db2bae30SDana Myers 100db2bae30SDana Myers 101db2bae30SDana Myers /* Create an object to be the table handle */ 102db2bae30SDana Myers 103db2bae30SDana Myers ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); 104db2bae30SDana Myers if (!ObjDesc) 105db2bae30SDana Myers { 106db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 107db2bae30SDana Myers } 108db2bae30SDana Myers 109db2bae30SDana Myers /* Init the table handle */ 110db2bae30SDana Myers 111aa2aa9a6SDana Myers ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID; 112db2bae30SDana Myers ObjDesc->Reference.Class = ACPI_REFCLASS_TABLE; 113db2bae30SDana Myers *DdbHandle = ObjDesc; 114db2bae30SDana Myers 115db2bae30SDana Myers /* Install the new table into the local data structures */ 116db2bae30SDana Myers 117db2bae30SDana Myers ObjDesc->Reference.Value = TableIndex; 118db2bae30SDana Myers 119db2bae30SDana Myers /* Add the table to the namespace */ 120db2bae30SDana Myers 121db2bae30SDana Myers Status = AcpiNsLoadTable (TableIndex, ParentNode); 122db2bae30SDana Myers if (ACPI_FAILURE (Status)) 123db2bae30SDana Myers { 124db2bae30SDana Myers AcpiUtRemoveReference (ObjDesc); 125db2bae30SDana Myers *DdbHandle = NULL; 12657190917SDana Myers return_ACPI_STATUS (Status); 127db2bae30SDana Myers } 128db2bae30SDana Myers 12957190917SDana Myers /* Execute any module-level code that was found in the table */ 13057190917SDana Myers 13157190917SDana Myers AcpiExExitInterpreter (); 132*385cc6b4SJerry Jelinek if (AcpiGbl_GroupModuleLevelCode) 133*385cc6b4SJerry Jelinek { 13457190917SDana Myers AcpiNsExecModuleCodeList (); 135*385cc6b4SJerry Jelinek } 13657190917SDana Myers AcpiExEnterInterpreter (); 13757190917SDana Myers 13826f3cdf0SGordon Ross /* 13926f3cdf0SGordon Ross * Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is 14026f3cdf0SGordon Ross * responsible for discovering any new wake GPEs by running _PRW methods 14126f3cdf0SGordon Ross * that may have been loaded by this table. 14226f3cdf0SGordon Ross */ 14326f3cdf0SGordon Ross Status = AcpiTbGetOwnerId (TableIndex, &OwnerId); 14426f3cdf0SGordon Ross if (ACPI_SUCCESS (Status)) 14526f3cdf0SGordon Ross { 14626f3cdf0SGordon Ross AcpiEvUpdateGpes (OwnerId); 14726f3cdf0SGordon Ross } 14826f3cdf0SGordon Ross 14926f3cdf0SGordon Ross return_ACPI_STATUS (AE_OK); 150db2bae30SDana Myers } 151db2bae30SDana Myers 152db2bae30SDana Myers 153db2bae30SDana Myers /******************************************************************************* 154db2bae30SDana Myers * 155db2bae30SDana Myers * FUNCTION: AcpiExLoadTableOp 156db2bae30SDana Myers * 157db2bae30SDana Myers * PARAMETERS: WalkState - Current state with operands 158db2bae30SDana Myers * ReturnDesc - Where to store the return object 159db2bae30SDana Myers * 160db2bae30SDana Myers * RETURN: Status 161db2bae30SDana Myers * 162db2bae30SDana Myers * DESCRIPTION: Load an ACPI table from the RSDT/XSDT 163db2bae30SDana Myers * 164db2bae30SDana Myers ******************************************************************************/ 165db2bae30SDana Myers 166db2bae30SDana Myers ACPI_STATUS 167db2bae30SDana Myers AcpiExLoadTableOp ( 168db2bae30SDana Myers ACPI_WALK_STATE *WalkState, 169db2bae30SDana Myers ACPI_OPERAND_OBJECT **ReturnDesc) 170db2bae30SDana Myers { 171db2bae30SDana Myers ACPI_STATUS Status; 172db2bae30SDana Myers ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 173db2bae30SDana Myers ACPI_NAMESPACE_NODE *ParentNode; 174db2bae30SDana Myers ACPI_NAMESPACE_NODE *StartNode; 175db2bae30SDana Myers ACPI_NAMESPACE_NODE *ParameterNode = NULL; 176db2bae30SDana Myers ACPI_OPERAND_OBJECT *DdbHandle; 177db2bae30SDana Myers ACPI_TABLE_HEADER *Table; 178db2bae30SDana Myers UINT32 TableIndex; 179db2bae30SDana Myers 180db2bae30SDana Myers 181db2bae30SDana Myers ACPI_FUNCTION_TRACE (ExLoadTableOp); 182db2bae30SDana Myers 183db2bae30SDana Myers 184db2bae30SDana Myers /* Find the ACPI table in the RSDT/XSDT */ 185db2bae30SDana Myers 186*385cc6b4SJerry Jelinek Status = AcpiTbFindTable ( 187*385cc6b4SJerry Jelinek Operand[0]->String.Pointer, 188db2bae30SDana Myers Operand[1]->String.Pointer, 189db2bae30SDana Myers Operand[2]->String.Pointer, &TableIndex); 190db2bae30SDana Myers if (ACPI_FAILURE (Status)) 191db2bae30SDana Myers { 192db2bae30SDana Myers if (Status != AE_NOT_FOUND) 193db2bae30SDana Myers { 194db2bae30SDana Myers return_ACPI_STATUS (Status); 195db2bae30SDana Myers } 196db2bae30SDana Myers 197db2bae30SDana Myers /* Table not found, return an Integer=0 and AE_OK */ 198db2bae30SDana Myers 19957190917SDana Myers DdbHandle = AcpiUtCreateIntegerObject ((UINT64) 0); 200db2bae30SDana Myers if (!DdbHandle) 201db2bae30SDana Myers { 202db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 203db2bae30SDana Myers } 204db2bae30SDana Myers 205db2bae30SDana Myers *ReturnDesc = DdbHandle; 206db2bae30SDana Myers return_ACPI_STATUS (AE_OK); 207db2bae30SDana Myers } 208db2bae30SDana Myers 209db2bae30SDana Myers /* Default nodes */ 210db2bae30SDana Myers 211db2bae30SDana Myers StartNode = WalkState->ScopeInfo->Scope.Node; 212db2bae30SDana Myers ParentNode = AcpiGbl_RootNode; 213db2bae30SDana Myers 214db2bae30SDana Myers /* RootPath (optional parameter) */ 215db2bae30SDana Myers 216db2bae30SDana Myers if (Operand[3]->String.Length > 0) 217db2bae30SDana Myers { 218db2bae30SDana Myers /* 219db2bae30SDana Myers * Find the node referenced by the RootPathString. This is the 220db2bae30SDana Myers * location within the namespace where the table will be loaded. 221db2bae30SDana Myers */ 222db2bae30SDana Myers Status = AcpiNsGetNode (StartNode, Operand[3]->String.Pointer, 223db2bae30SDana Myers ACPI_NS_SEARCH_PARENT, &ParentNode); 224db2bae30SDana Myers if (ACPI_FAILURE (Status)) 225db2bae30SDana Myers { 226db2bae30SDana Myers return_ACPI_STATUS (Status); 227db2bae30SDana Myers } 228db2bae30SDana Myers } 229db2bae30SDana Myers 230db2bae30SDana Myers /* ParameterPath (optional parameter) */ 231db2bae30SDana Myers 232db2bae30SDana Myers if (Operand[4]->String.Length > 0) 233db2bae30SDana Myers { 234*385cc6b4SJerry Jelinek if ((Operand[4]->String.Pointer[0] != AML_ROOT_PREFIX) && 235*385cc6b4SJerry Jelinek (Operand[4]->String.Pointer[0] != AML_PARENT_PREFIX)) 236db2bae30SDana Myers { 237db2bae30SDana Myers /* 238db2bae30SDana Myers * Path is not absolute, so it will be relative to the node 239db2bae30SDana Myers * referenced by the RootPathString (or the NS root if omitted) 240db2bae30SDana Myers */ 241db2bae30SDana Myers StartNode = ParentNode; 242db2bae30SDana Myers } 243db2bae30SDana Myers 244db2bae30SDana Myers /* Find the node referenced by the ParameterPathString */ 245db2bae30SDana Myers 246db2bae30SDana Myers Status = AcpiNsGetNode (StartNode, Operand[4]->String.Pointer, 247db2bae30SDana Myers ACPI_NS_SEARCH_PARENT, &ParameterNode); 248db2bae30SDana Myers if (ACPI_FAILURE (Status)) 249db2bae30SDana Myers { 250db2bae30SDana Myers return_ACPI_STATUS (Status); 251db2bae30SDana Myers } 252db2bae30SDana Myers } 253db2bae30SDana Myers 254db2bae30SDana Myers /* Load the table into the namespace */ 255db2bae30SDana Myers 256db2bae30SDana Myers Status = AcpiExAddTable (TableIndex, ParentNode, &DdbHandle); 257db2bae30SDana Myers if (ACPI_FAILURE (Status)) 258db2bae30SDana Myers { 259db2bae30SDana Myers return_ACPI_STATUS (Status); 260db2bae30SDana Myers } 261db2bae30SDana Myers 262db2bae30SDana Myers /* Parameter Data (optional) */ 263db2bae30SDana Myers 264db2bae30SDana Myers if (ParameterNode) 265db2bae30SDana Myers { 266db2bae30SDana Myers /* Store the parameter data into the optional parameter object */ 267db2bae30SDana Myers 268db2bae30SDana Myers Status = AcpiExStore (Operand[5], 269*385cc6b4SJerry Jelinek ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParameterNode), WalkState); 270db2bae30SDana Myers if (ACPI_FAILURE (Status)) 271db2bae30SDana Myers { 272db2bae30SDana Myers (void) AcpiExUnloadTable (DdbHandle); 273aa2aa9a6SDana Myers 274aa2aa9a6SDana Myers AcpiUtRemoveReference (DdbHandle); 275db2bae30SDana Myers return_ACPI_STATUS (Status); 276db2bae30SDana Myers } 277db2bae30SDana Myers } 278db2bae30SDana Myers 279db2bae30SDana Myers Status = AcpiGetTableByIndex (TableIndex, &Table); 280db2bae30SDana Myers if (ACPI_SUCCESS (Status)) 281db2bae30SDana Myers { 282*385cc6b4SJerry Jelinek ACPI_INFO (("Dynamic OEM Table Load:")); 28326f3cdf0SGordon Ross AcpiTbPrintTableHeader (0, Table); 284db2bae30SDana Myers } 285db2bae30SDana Myers 286db2bae30SDana Myers /* Invoke table handler if present */ 287db2bae30SDana Myers 288db2bae30SDana Myers if (AcpiGbl_TableHandler) 289db2bae30SDana Myers { 290db2bae30SDana Myers (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, 291db2bae30SDana Myers AcpiGbl_TableHandlerContext); 292db2bae30SDana Myers } 293db2bae30SDana Myers 294db2bae30SDana Myers *ReturnDesc = DdbHandle; 295db2bae30SDana Myers return_ACPI_STATUS (Status); 296db2bae30SDana Myers } 297db2bae30SDana Myers 298db2bae30SDana Myers 299db2bae30SDana Myers /******************************************************************************* 300db2bae30SDana Myers * 301aa2aa9a6SDana Myers * FUNCTION: AcpiExRegionRead 302aa2aa9a6SDana Myers * 303aa2aa9a6SDana Myers * PARAMETERS: ObjDesc - Region descriptor 304aa2aa9a6SDana Myers * Length - Number of bytes to read 305aa2aa9a6SDana Myers * Buffer - Pointer to where to put the data 306aa2aa9a6SDana Myers * 307aa2aa9a6SDana Myers * RETURN: Status 308aa2aa9a6SDana Myers * 309aa2aa9a6SDana Myers * DESCRIPTION: Read data from an operation region. The read starts from the 310aa2aa9a6SDana Myers * beginning of the region. 311aa2aa9a6SDana Myers * 312aa2aa9a6SDana Myers ******************************************************************************/ 313aa2aa9a6SDana Myers 314aa2aa9a6SDana Myers static ACPI_STATUS 315aa2aa9a6SDana Myers AcpiExRegionRead ( 316aa2aa9a6SDana Myers ACPI_OPERAND_OBJECT *ObjDesc, 317aa2aa9a6SDana Myers UINT32 Length, 318aa2aa9a6SDana Myers UINT8 *Buffer) 319aa2aa9a6SDana Myers { 320aa2aa9a6SDana Myers ACPI_STATUS Status; 32126f3cdf0SGordon Ross UINT64 Value; 322aa2aa9a6SDana Myers UINT32 RegionOffset = 0; 323aa2aa9a6SDana Myers UINT32 i; 324aa2aa9a6SDana Myers 325aa2aa9a6SDana Myers 326aa2aa9a6SDana Myers /* Bytewise reads */ 327aa2aa9a6SDana Myers 328aa2aa9a6SDana Myers for (i = 0; i < Length; i++) 329aa2aa9a6SDana Myers { 330*385cc6b4SJerry Jelinek Status = AcpiEvAddressSpaceDispatch (ObjDesc, NULL, ACPI_READ, 331aa2aa9a6SDana Myers RegionOffset, 8, &Value); 332aa2aa9a6SDana Myers if (ACPI_FAILURE (Status)) 333aa2aa9a6SDana Myers { 334aa2aa9a6SDana Myers return (Status); 335aa2aa9a6SDana Myers } 336aa2aa9a6SDana Myers 337aa2aa9a6SDana Myers *Buffer = (UINT8) Value; 338aa2aa9a6SDana Myers Buffer++; 339aa2aa9a6SDana Myers RegionOffset++; 340aa2aa9a6SDana Myers } 341aa2aa9a6SDana Myers 342aa2aa9a6SDana Myers return (AE_OK); 343aa2aa9a6SDana Myers } 344aa2aa9a6SDana Myers 345aa2aa9a6SDana Myers 346aa2aa9a6SDana Myers /******************************************************************************* 347aa2aa9a6SDana Myers * 348db2bae30SDana Myers * FUNCTION: AcpiExLoadOp 349db2bae30SDana Myers * 350db2bae30SDana Myers * PARAMETERS: ObjDesc - Region or Buffer/Field where the table will be 351db2bae30SDana Myers * obtained 352db2bae30SDana Myers * Target - Where a handle to the table will be stored 353db2bae30SDana Myers * WalkState - Current state 354db2bae30SDana Myers * 355db2bae30SDana Myers * RETURN: Status 356db2bae30SDana Myers * 357db2bae30SDana Myers * DESCRIPTION: Load an ACPI table from a field or operation region 358db2bae30SDana Myers * 359db2bae30SDana Myers * NOTE: Region Fields (Field, BankField, IndexFields) are resolved to buffer 360db2bae30SDana Myers * objects before this code is reached. 361db2bae30SDana Myers * 362db2bae30SDana Myers * If source is an operation region, it must refer to SystemMemory, as 363db2bae30SDana Myers * per the ACPI specification. 364db2bae30SDana Myers * 365db2bae30SDana Myers ******************************************************************************/ 366db2bae30SDana Myers 367db2bae30SDana Myers ACPI_STATUS 368db2bae30SDana Myers AcpiExLoadOp ( 369db2bae30SDana Myers ACPI_OPERAND_OBJECT *ObjDesc, 370db2bae30SDana Myers ACPI_OPERAND_OBJECT *Target, 371db2bae30SDana Myers ACPI_WALK_STATE *WalkState) 372db2bae30SDana Myers { 373db2bae30SDana Myers ACPI_OPERAND_OBJECT *DdbHandle; 374*385cc6b4SJerry Jelinek ACPI_TABLE_HEADER *TableHeader; 375db2bae30SDana Myers ACPI_TABLE_HEADER *Table; 376db2bae30SDana Myers UINT32 TableIndex; 377db2bae30SDana Myers ACPI_STATUS Status; 378db2bae30SDana Myers UINT32 Length; 379db2bae30SDana Myers 380db2bae30SDana Myers 381db2bae30SDana Myers ACPI_FUNCTION_TRACE (ExLoadOp); 382db2bae30SDana Myers 383db2bae30SDana Myers 384db2bae30SDana Myers /* Source Object can be either an OpRegion or a Buffer/Field */ 385db2bae30SDana Myers 386aa2aa9a6SDana Myers switch (ObjDesc->Common.Type) 387db2bae30SDana Myers { 388db2bae30SDana Myers case ACPI_TYPE_REGION: 389db2bae30SDana Myers 390db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 391db2bae30SDana Myers "Load table from Region %p\n", ObjDesc)); 392db2bae30SDana Myers 393db2bae30SDana Myers /* Region must be SystemMemory (from ACPI spec) */ 394db2bae30SDana Myers 395db2bae30SDana Myers if (ObjDesc->Region.SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) 396db2bae30SDana Myers { 397db2bae30SDana Myers return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 398db2bae30SDana Myers } 399db2bae30SDana Myers 400db2bae30SDana Myers /* 401*385cc6b4SJerry Jelinek * If the Region Address and Length have not been previously 402*385cc6b4SJerry Jelinek * evaluated, evaluate them now and save the results. 403db2bae30SDana Myers */ 404db2bae30SDana Myers if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) 405db2bae30SDana Myers { 406db2bae30SDana Myers Status = AcpiDsGetRegionArguments (ObjDesc); 407db2bae30SDana Myers if (ACPI_FAILURE (Status)) 408db2bae30SDana Myers { 409db2bae30SDana Myers return_ACPI_STATUS (Status); 410db2bae30SDana Myers } 411db2bae30SDana Myers } 412db2bae30SDana Myers 413aa2aa9a6SDana Myers /* Get the table header first so we can get the table length */ 414aa2aa9a6SDana Myers 415*385cc6b4SJerry Jelinek TableHeader = ACPI_ALLOCATE (sizeof (ACPI_TABLE_HEADER)); 416*385cc6b4SJerry Jelinek if (!TableHeader) 417db2bae30SDana Myers { 418db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 419db2bae30SDana Myers } 420db2bae30SDana Myers 421aa2aa9a6SDana Myers Status = AcpiExRegionRead (ObjDesc, sizeof (ACPI_TABLE_HEADER), 422*385cc6b4SJerry Jelinek ACPI_CAST_PTR (UINT8, TableHeader)); 423*385cc6b4SJerry Jelinek Length = TableHeader->Length; 424*385cc6b4SJerry Jelinek ACPI_FREE (TableHeader); 425aa2aa9a6SDana Myers 426aa2aa9a6SDana Myers if (ACPI_FAILURE (Status)) 427aa2aa9a6SDana Myers { 428aa2aa9a6SDana Myers return_ACPI_STATUS (Status); 429aa2aa9a6SDana Myers } 430db2bae30SDana Myers 431db2bae30SDana Myers /* Must have at least an ACPI table header */ 432db2bae30SDana Myers 433db2bae30SDana Myers if (Length < sizeof (ACPI_TABLE_HEADER)) 434db2bae30SDana Myers { 435db2bae30SDana Myers return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 436db2bae30SDana Myers } 437db2bae30SDana Myers 438db2bae30SDana Myers /* 439aa2aa9a6SDana Myers * The original implementation simply mapped the table, with no copy. 440aa2aa9a6SDana Myers * However, the memory region is not guaranteed to remain stable and 441aa2aa9a6SDana Myers * we must copy the table to a local buffer. For example, the memory 442aa2aa9a6SDana Myers * region is corrupted after suspend on some machines. Dynamically 443aa2aa9a6SDana Myers * loaded tables are usually small, so this overhead is minimal. 444aa2aa9a6SDana Myers * 445aa2aa9a6SDana Myers * The latest implementation (5/2009) does not use a mapping at all. 446aa2aa9a6SDana Myers * We use the low-level operation region interface to read the table 447aa2aa9a6SDana Myers * instead of the obvious optimization of using a direct mapping. 448aa2aa9a6SDana Myers * This maintains a consistent use of operation regions across the 449aa2aa9a6SDana Myers * entire subsystem. This is important if additional processing must 450aa2aa9a6SDana Myers * be performed in the (possibly user-installed) operation region 451aa2aa9a6SDana Myers * handler. For example, AcpiExec and ASLTS depend on this. 452db2bae30SDana Myers */ 453db2bae30SDana Myers 454db2bae30SDana Myers /* Allocate a buffer for the table */ 455db2bae30SDana Myers 456*385cc6b4SJerry Jelinek Table = ACPI_ALLOCATE (Length); 457*385cc6b4SJerry Jelinek if (!Table) 458db2bae30SDana Myers { 459db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 460db2bae30SDana Myers } 461db2bae30SDana Myers 462aa2aa9a6SDana Myers /* Read the entire table */ 463db2bae30SDana Myers 464aa2aa9a6SDana Myers Status = AcpiExRegionRead (ObjDesc, Length, 465*385cc6b4SJerry Jelinek ACPI_CAST_PTR (UINT8, Table)); 466aa2aa9a6SDana Myers if (ACPI_FAILURE (Status)) 467db2bae30SDana Myers { 468*385cc6b4SJerry Jelinek ACPI_FREE (Table); 469aa2aa9a6SDana Myers return_ACPI_STATUS (Status); 470db2bae30SDana Myers } 471db2bae30SDana Myers break; 472db2bae30SDana Myers 473db2bae30SDana Myers case ACPI_TYPE_BUFFER: /* Buffer or resolved RegionField */ 474db2bae30SDana Myers 475db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 476db2bae30SDana Myers "Load table from Buffer or Field %p\n", ObjDesc)); 477db2bae30SDana Myers 478db2bae30SDana Myers /* Must have at least an ACPI table header */ 479db2bae30SDana Myers 480db2bae30SDana Myers if (ObjDesc->Buffer.Length < sizeof (ACPI_TABLE_HEADER)) 481db2bae30SDana Myers { 482db2bae30SDana Myers return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 483db2bae30SDana Myers } 484db2bae30SDana Myers 485db2bae30SDana Myers /* Get the actual table length from the table header */ 486db2bae30SDana Myers 487*385cc6b4SJerry Jelinek TableHeader = ACPI_CAST_PTR ( 488*385cc6b4SJerry Jelinek ACPI_TABLE_HEADER, ObjDesc->Buffer.Pointer); 489*385cc6b4SJerry Jelinek Length = TableHeader->Length; 490db2bae30SDana Myers 491db2bae30SDana Myers /* Table cannot extend beyond the buffer */ 492db2bae30SDana Myers 493db2bae30SDana Myers if (Length > ObjDesc->Buffer.Length) 494db2bae30SDana Myers { 495db2bae30SDana Myers return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); 496db2bae30SDana Myers } 497db2bae30SDana Myers if (Length < sizeof (ACPI_TABLE_HEADER)) 498db2bae30SDana Myers { 499db2bae30SDana Myers return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 500db2bae30SDana Myers } 501db2bae30SDana Myers 502db2bae30SDana Myers /* 503*385cc6b4SJerry Jelinek * Copy the table from the buffer because the buffer could be 504*385cc6b4SJerry Jelinek * modified or even deleted in the future 505db2bae30SDana Myers */ 506*385cc6b4SJerry Jelinek Table = ACPI_ALLOCATE (Length); 507*385cc6b4SJerry Jelinek if (!Table) 508db2bae30SDana Myers { 509db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 510db2bae30SDana Myers } 511db2bae30SDana Myers 512*385cc6b4SJerry Jelinek memcpy (Table, TableHeader, Length); 513db2bae30SDana Myers break; 514db2bae30SDana Myers 515db2bae30SDana Myers default: 516*385cc6b4SJerry Jelinek 517db2bae30SDana Myers return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 518db2bae30SDana Myers } 519db2bae30SDana Myers 520db2bae30SDana Myers /* Install the new table into the local data structures */ 521db2bae30SDana Myers 522*385cc6b4SJerry Jelinek ACPI_INFO (("Dynamic OEM Table Load:")); 523*385cc6b4SJerry Jelinek (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 524*385cc6b4SJerry Jelinek 525*385cc6b4SJerry Jelinek Status = AcpiTbInstallStandardTable (ACPI_PTR_TO_PHYSADDR (Table), 526*385cc6b4SJerry Jelinek ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, TRUE, TRUE, 527*385cc6b4SJerry Jelinek &TableIndex); 528*385cc6b4SJerry Jelinek 529*385cc6b4SJerry Jelinek (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 530db2bae30SDana Myers if (ACPI_FAILURE (Status)) 531db2bae30SDana Myers { 53226f3cdf0SGordon Ross /* Delete allocated table buffer */ 53326f3cdf0SGordon Ross 534*385cc6b4SJerry Jelinek ACPI_FREE (Table); 535*385cc6b4SJerry Jelinek return_ACPI_STATUS (Status); 536*385cc6b4SJerry Jelinek } 537*385cc6b4SJerry Jelinek 538*385cc6b4SJerry Jelinek /* 539*385cc6b4SJerry Jelinek * Note: Now table is "INSTALLED", it must be validated before 540*385cc6b4SJerry Jelinek * loading. 541*385cc6b4SJerry Jelinek */ 542*385cc6b4SJerry Jelinek Status = AcpiTbValidateTable ( 543*385cc6b4SJerry Jelinek &AcpiGbl_RootTableList.Tables[TableIndex]); 544*385cc6b4SJerry Jelinek if (ACPI_FAILURE (Status)) 545*385cc6b4SJerry Jelinek { 54626f3cdf0SGordon Ross return_ACPI_STATUS (Status); 547db2bae30SDana Myers } 548db2bae30SDana Myers 549db2bae30SDana Myers /* 550db2bae30SDana Myers * Add the table to the namespace. 551db2bae30SDana Myers * 552db2bae30SDana Myers * Note: Load the table objects relative to the root of the namespace. 553db2bae30SDana Myers * This appears to go against the ACPI specification, but we do it for 554db2bae30SDana Myers * compatibility with other ACPI implementations. 555db2bae30SDana Myers */ 556db2bae30SDana Myers Status = AcpiExAddTable (TableIndex, AcpiGbl_RootNode, &DdbHandle); 557db2bae30SDana Myers if (ACPI_FAILURE (Status)) 558db2bae30SDana Myers { 559db2bae30SDana Myers /* On error, TablePtr was deallocated above */ 560db2bae30SDana Myers 561db2bae30SDana Myers return_ACPI_STATUS (Status); 562db2bae30SDana Myers } 563db2bae30SDana Myers 564db2bae30SDana Myers /* Store the DdbHandle into the Target operand */ 565db2bae30SDana Myers 566db2bae30SDana Myers Status = AcpiExStore (DdbHandle, Target, WalkState); 567db2bae30SDana Myers if (ACPI_FAILURE (Status)) 568db2bae30SDana Myers { 569db2bae30SDana Myers (void) AcpiExUnloadTable (DdbHandle); 570db2bae30SDana Myers 571db2bae30SDana Myers /* TablePtr was deallocated above */ 572db2bae30SDana Myers 573db2bae30SDana Myers AcpiUtRemoveReference (DdbHandle); 574db2bae30SDana Myers return_ACPI_STATUS (Status); 575db2bae30SDana Myers } 576db2bae30SDana Myers 577aa2aa9a6SDana Myers /* Remove the reference by added by AcpiExStore above */ 578aa2aa9a6SDana Myers 579aa2aa9a6SDana Myers AcpiUtRemoveReference (DdbHandle); 580aa2aa9a6SDana Myers 581db2bae30SDana Myers /* Invoke table handler if present */ 582db2bae30SDana Myers 583db2bae30SDana Myers if (AcpiGbl_TableHandler) 584db2bae30SDana Myers { 585*385cc6b4SJerry Jelinek (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, 586db2bae30SDana Myers AcpiGbl_TableHandlerContext); 587db2bae30SDana Myers } 588db2bae30SDana Myers 589db2bae30SDana Myers return_ACPI_STATUS (Status); 590db2bae30SDana Myers } 591db2bae30SDana Myers 592db2bae30SDana Myers 593db2bae30SDana Myers /******************************************************************************* 594db2bae30SDana Myers * 595db2bae30SDana Myers * FUNCTION: AcpiExUnloadTable 596db2bae30SDana Myers * 597db2bae30SDana Myers * PARAMETERS: DdbHandle - Handle to a previously loaded table 598db2bae30SDana Myers * 599db2bae30SDana Myers * RETURN: Status 600db2bae30SDana Myers * 601db2bae30SDana Myers * DESCRIPTION: Unload an ACPI table 602db2bae30SDana Myers * 603db2bae30SDana Myers ******************************************************************************/ 604db2bae30SDana Myers 605db2bae30SDana Myers ACPI_STATUS 606db2bae30SDana Myers AcpiExUnloadTable ( 607db2bae30SDana Myers ACPI_OPERAND_OBJECT *DdbHandle) 608db2bae30SDana Myers { 609db2bae30SDana Myers ACPI_STATUS Status = AE_OK; 610db2bae30SDana Myers ACPI_OPERAND_OBJECT *TableDesc = DdbHandle; 611db2bae30SDana Myers UINT32 TableIndex; 612db2bae30SDana Myers ACPI_TABLE_HEADER *Table; 613db2bae30SDana Myers 614db2bae30SDana Myers 615db2bae30SDana Myers ACPI_FUNCTION_TRACE (ExUnloadTable); 616db2bae30SDana Myers 617db2bae30SDana Myers 618db2bae30SDana Myers /* 619*385cc6b4SJerry Jelinek * Temporarily emit a warning so that the ASL for the machine can be 620*385cc6b4SJerry Jelinek * hopefully obtained. This is to say that the Unload() operator is 621*385cc6b4SJerry Jelinek * extremely rare if not completely unused. 622*385cc6b4SJerry Jelinek */ 623*385cc6b4SJerry Jelinek ACPI_WARNING ((AE_INFO, 624*385cc6b4SJerry Jelinek "Received request to unload an ACPI table")); 625*385cc6b4SJerry Jelinek 626*385cc6b4SJerry Jelinek /* 627db2bae30SDana Myers * Validate the handle 628aa2aa9a6SDana Myers * Although the handle is partially validated in AcpiExReconfiguration() 629db2bae30SDana Myers * when it calls AcpiExResolveOperands(), the handle is more completely 630db2bae30SDana Myers * validated here. 631aa2aa9a6SDana Myers * 632aa2aa9a6SDana Myers * Handle must be a valid operand object of type reference. Also, the 633aa2aa9a6SDana Myers * DdbHandle must still be marked valid (table has not been previously 634aa2aa9a6SDana Myers * unloaded) 635db2bae30SDana Myers */ 636db2bae30SDana Myers if ((!DdbHandle) || 637db2bae30SDana Myers (ACPI_GET_DESCRIPTOR_TYPE (DdbHandle) != ACPI_DESC_TYPE_OPERAND) || 638aa2aa9a6SDana Myers (DdbHandle->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) || 639aa2aa9a6SDana Myers (!(DdbHandle->Common.Flags & AOPOBJ_DATA_VALID))) 640db2bae30SDana Myers { 641*385cc6b4SJerry Jelinek return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 642db2bae30SDana Myers } 643db2bae30SDana Myers 644db2bae30SDana Myers /* Get the table index from the DdbHandle */ 645db2bae30SDana Myers 646db2bae30SDana Myers TableIndex = TableDesc->Reference.Value; 647db2bae30SDana Myers 648aa2aa9a6SDana Myers /* Ensure the table is still loaded */ 649aa2aa9a6SDana Myers 650aa2aa9a6SDana Myers if (!AcpiTbIsTableLoaded (TableIndex)) 651aa2aa9a6SDana Myers { 652aa2aa9a6SDana Myers return_ACPI_STATUS (AE_NOT_EXIST); 653aa2aa9a6SDana Myers } 654aa2aa9a6SDana Myers 655db2bae30SDana Myers /* Invoke table handler if present */ 656db2bae30SDana Myers 657db2bae30SDana Myers if (AcpiGbl_TableHandler) 658db2bae30SDana Myers { 659db2bae30SDana Myers Status = AcpiGetTableByIndex (TableIndex, &Table); 660db2bae30SDana Myers if (ACPI_SUCCESS (Status)) 661db2bae30SDana Myers { 662db2bae30SDana Myers (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, Table, 663db2bae30SDana Myers AcpiGbl_TableHandlerContext); 664db2bae30SDana Myers } 665db2bae30SDana Myers } 666db2bae30SDana Myers 667aa2aa9a6SDana Myers /* Delete the portion of the namespace owned by this table */ 668db2bae30SDana Myers 669aa2aa9a6SDana Myers Status = AcpiTbDeleteNamespaceByOwner (TableIndex); 670aa2aa9a6SDana Myers if (ACPI_FAILURE (Status)) 671aa2aa9a6SDana Myers { 672aa2aa9a6SDana Myers return_ACPI_STATUS (Status); 673aa2aa9a6SDana Myers } 674aa2aa9a6SDana Myers 675aa2aa9a6SDana Myers (void) AcpiTbReleaseOwnerId (TableIndex); 676db2bae30SDana Myers AcpiTbSetTableLoadedFlag (TableIndex, FALSE); 677db2bae30SDana Myers 678aa2aa9a6SDana Myers /* 679aa2aa9a6SDana Myers * Invalidate the handle. We do this because the handle may be stored 680aa2aa9a6SDana Myers * in a named object and may not be actually deleted until much later. 681aa2aa9a6SDana Myers */ 682aa2aa9a6SDana Myers DdbHandle->Common.Flags &= ~AOPOBJ_DATA_VALID; 683db2bae30SDana Myers return_ACPI_STATUS (AE_OK); 684db2bae30SDana Myers } 685