dmdeferred.c revision 243044
167754Smsmith/****************************************************************************** 267754Smsmith * 367754Smsmith * Module Name: dmdeferred - Disassembly of deferred AML opcodes 467754Smsmith * 573561Smsmith *****************************************************************************/ 667754Smsmith 767754Smsmith/* 867754Smsmith * Copyright (C) 2000 - 2012, 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 1371867Smsmith * 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 4567754Smsmith#include "acpi.h" 4667754Smsmith#include "accommon.h" 4767754Smsmith#include "acdispat.h" 4867754Smsmith#include "amlcode.h" 4967754Smsmith#include "acdisasm.h" 5067754Smsmith#include "acparser.h" 5167754Smsmith 5267754Smsmith#define _COMPONENT ACPI_CA_DISASSEMBLER 5367754Smsmith ACPI_MODULE_NAME ("dmdeferred") 5467754Smsmith 5567754Smsmith 5667754Smsmith/* Local prototypes */ 5767754Smsmith 5867754Smsmithstatic ACPI_STATUS 5967754SmsmithAcpiDmDeferredParse ( 6067754Smsmith ACPI_PARSE_OBJECT *Op, 6167754Smsmith UINT8 *Aml, 6267754Smsmith UINT32 AmlLength); 6367754Smsmith 6467754Smsmith 6567754Smsmith/****************************************************************************** 6667754Smsmith * 6767754Smsmith * FUNCTION: AcpiDmParseDeferredOps 6867754Smsmith * 6967754Smsmith * PARAMETERS: Root - Root of the parse tree 7067754Smsmith * 7167754Smsmith * RETURN: Status 7267754Smsmith * 7367754Smsmith * DESCRIPTION: Parse the deferred opcodes (Methods, regions, etc.) 7467754Smsmith * 7567754Smsmith *****************************************************************************/ 7667754Smsmith 7767754SmsmithACPI_STATUS 7867754SmsmithAcpiDmParseDeferredOps ( 7967754Smsmith ACPI_PARSE_OBJECT *Root) 8067754Smsmith{ 8167754Smsmith const ACPI_OPCODE_INFO *OpInfo; 8267754Smsmith ACPI_PARSE_OBJECT *Op = Root; 8367754Smsmith ACPI_STATUS Status; 8467754Smsmith 8567754Smsmith 8667754Smsmith ACPI_FUNCTION_NAME (DmParseDeferredOps); 8767754Smsmith 8867754Smsmith 8967754Smsmith /* Traverse the entire parse tree */ 9067754Smsmith 9167754Smsmith while (Op) 9267754Smsmith { 9367754Smsmith OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); 9467754Smsmith if (!(OpInfo->Flags & AML_DEFER)) 9567754Smsmith { 9667754Smsmith Op = AcpiPsGetDepthNext (Root, Op); 9767754Smsmith continue; 9867754Smsmith } 9967754Smsmith 10067754Smsmith /* Now we know we have a deferred opcode */ 10167754Smsmith 10267754Smsmith switch (Op->Common.AmlOpcode) 10367754Smsmith { 10467754Smsmith case AML_METHOD_OP: 10567754Smsmith case AML_BUFFER_OP: 10667754Smsmith case AML_PACKAGE_OP: 10767754Smsmith case AML_VAR_PACKAGE_OP: 10867754Smsmith 10967754Smsmith Status = AcpiDmDeferredParse (Op, Op->Named.Data, Op->Named.Length); 11067754Smsmith if (ACPI_FAILURE (Status)) 11167754Smsmith { 11267754Smsmith return (Status); 11367754Smsmith } 11467754Smsmith break; 11567754Smsmith 11667754Smsmith /* We don't need to do anything for these deferred opcodes */ 11767754Smsmith 11867754Smsmith case AML_REGION_OP: 11967754Smsmith case AML_DATA_REGION_OP: 12067754Smsmith case AML_CREATE_QWORD_FIELD_OP: 12167754Smsmith case AML_CREATE_DWORD_FIELD_OP: 12267754Smsmith case AML_CREATE_WORD_FIELD_OP: 12367754Smsmith case AML_CREATE_BYTE_FIELD_OP: 12467754Smsmith case AML_CREATE_BIT_FIELD_OP: 12567754Smsmith case AML_CREATE_FIELD_OP: 12667754Smsmith case AML_BANK_FIELD_OP: 12767754Smsmith 12867754Smsmith break; 12967754Smsmith 13067754Smsmith default: 13167754Smsmith ACPI_ERROR ((AE_INFO, "Unhandled deferred AML opcode [0x%.4X]", 13267754Smsmith Op->Common.AmlOpcode)); 13367754Smsmith break; 13467754Smsmith } 13567754Smsmith 13667754Smsmith Op = AcpiPsGetDepthNext (Root, Op); 13767754Smsmith } 13867754Smsmith 13967754Smsmith return (AE_OK); 14067754Smsmith} 14167754Smsmith 14267754Smsmith 14367754Smsmith/****************************************************************************** 14467754Smsmith * 14567754Smsmith * FUNCTION: AcpiDmDeferredParse 14667754Smsmith * 14767754Smsmith * PARAMETERS: Op - Root Op of the deferred opcode 14867754Smsmith * Aml - Pointer to the raw AML 14967754Smsmith * AmlLength - Length of the AML 15067754Smsmith * 15167754Smsmith * RETURN: Status 15267754Smsmith * 15367754Smsmith * DESCRIPTION: Parse one deferred opcode 15467754Smsmith * (Methods, operation regions, etc.) 15567754Smsmith * 15667754Smsmith *****************************************************************************/ 15767754Smsmith 15867754Smsmithstatic ACPI_STATUS 15967754SmsmithAcpiDmDeferredParse ( 16067754Smsmith ACPI_PARSE_OBJECT *Op, 16167754Smsmith UINT8 *Aml, 16267754Smsmith UINT32 AmlLength) 16367754Smsmith{ 16467754Smsmith ACPI_WALK_STATE *WalkState; 16567754Smsmith ACPI_STATUS Status; 16667754Smsmith ACPI_PARSE_OBJECT *SearchOp; 16767754Smsmith ACPI_PARSE_OBJECT *StartOp; 16867754Smsmith UINT32 BaseAmlOffset; 16967754Smsmith ACPI_PARSE_OBJECT *NewRootOp; 17067754Smsmith ACPI_PARSE_OBJECT *ExtraOp; 17167754Smsmith 17267754Smsmith 17367754Smsmith ACPI_FUNCTION_TRACE (DmDeferredParse); 17467754Smsmith 17567754Smsmith 17667754Smsmith if (!Aml || !AmlLength) 17767754Smsmith { 17867754Smsmith return_ACPI_STATUS (AE_OK); 17967754Smsmith } 18067754Smsmith 18167754Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Parsing deferred opcode %s [%4.4s]\n", 18267754Smsmith Op->Common.AmlOpName, (char *) &Op->Named.Name)); 18367754Smsmith 18467754Smsmith /* Need a new walk state to parse the AML */ 18567754Smsmith 18667754Smsmith WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL); 18767754Smsmith if (!WalkState) 18867754Smsmith { 18967754Smsmith return_ACPI_STATUS (AE_NO_MEMORY); 19067754Smsmith } 19167754Smsmith 19267754Smsmith Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, Aml, 19367754Smsmith AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); 19467754Smsmith if (ACPI_FAILURE (Status)) 19567754Smsmith { 19667754Smsmith return_ACPI_STATUS (Status); 19767754Smsmith } 19867754Smsmith 19967754Smsmith /* Parse the AML for this deferred opcode */ 20067754Smsmith 20167754Smsmith WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; 20267754Smsmith WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; 20367754Smsmith Status = AcpiPsParseAml (WalkState); 20467754Smsmith 20567754Smsmith /* 20667754Smsmith * We need to update all of the AML offsets, since the parser thought 20767754Smsmith * that the method began at offset zero. In reality, it began somewhere 20867754Smsmith * within the ACPI table, at the BaseAmlOffset. Walk the entire tree that 20967754Smsmith * was just created and update the AmlOffset in each Op. 21067754Smsmith */ 21167754Smsmith BaseAmlOffset = (Op->Common.Value.Arg)->Common.AmlOffset + 1; 21267754Smsmith StartOp = (Op->Common.Value.Arg)->Common.Next; 21367754Smsmith SearchOp = StartOp; 21467754Smsmith 21567754Smsmith while (SearchOp) 21667754Smsmith { 21767754Smsmith SearchOp->Common.AmlOffset += BaseAmlOffset; 21867754Smsmith SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp); 21967754Smsmith } 22067754Smsmith 22167754Smsmith /* 22267754Smsmith * For Buffer and Package opcodes, link the newly parsed subtree 22367754Smsmith * into the main parse tree 22467754Smsmith */ 22567754Smsmith switch (Op->Common.AmlOpcode) 22667754Smsmith { 22767754Smsmith case AML_BUFFER_OP: 22867754Smsmith case AML_PACKAGE_OP: 22967754Smsmith case AML_VAR_PACKAGE_OP: 23067754Smsmith 23167754Smsmith switch (Op->Common.AmlOpcode) 23267754Smsmith { 23367754Smsmith case AML_PACKAGE_OP: 23467754Smsmith 23567754Smsmith ExtraOp = Op->Common.Value.Arg; 23667754Smsmith NewRootOp = ExtraOp->Common.Next; 23767754Smsmith ACPI_FREE (ExtraOp); 23867754Smsmith break; 23967754Smsmith 24067754Smsmith case AML_VAR_PACKAGE_OP: 24167754Smsmith case AML_BUFFER_OP: 24267754Smsmith default: 24373561Smsmith 24473561Smsmith NewRootOp = Op->Common.Value.Arg; 24573561Smsmith break; 24673561Smsmith } 24767754Smsmith 24867754Smsmith Op->Common.Value.Arg = NewRootOp->Common.Value.Arg; 24967754Smsmith 25067754Smsmith /* Must point all parents to the main tree */ 25167754Smsmith 25267754Smsmith StartOp = Op; 25367754Smsmith SearchOp = StartOp; 25467754Smsmith while (SearchOp) 25567754Smsmith { 25667754Smsmith if (SearchOp->Common.Parent == NewRootOp) 25767754Smsmith { 25867754Smsmith SearchOp->Common.Parent = Op; 25967754Smsmith } 26067754Smsmith 26167754Smsmith SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp); 26267754Smsmith } 26367754Smsmith 26467754Smsmith ACPI_FREE (NewRootOp); 26567754Smsmith break; 26667754Smsmith 26767754Smsmith default: 26867754Smsmith break; 26967754Smsmith } 27067754Smsmith 27167754Smsmith return_ACPI_STATUS (AE_OK); 27267754Smsmith} 27367754Smsmith