xref: /freebsd/sys/contrib/dev/acpica/components/disassembler/dmdeferred.c (revision efcc2a30547c400649a351e85e6cd97dab8f3817)
1ed17e06eSJung-uk Kim /******************************************************************************
2ed17e06eSJung-uk Kim  *
3ed17e06eSJung-uk Kim  * Module Name: dmdeferred - Disassembly of deferred AML opcodes
4ed17e06eSJung-uk Kim  *
5ed17e06eSJung-uk Kim  *****************************************************************************/
6ed17e06eSJung-uk Kim 
7ed17e06eSJung-uk Kim /*
8*efcc2a30SJung-uk Kim  * Copyright (C) 2000 - 2013, Intel Corp.
9ed17e06eSJung-uk Kim  * All rights reserved.
10ed17e06eSJung-uk Kim  *
11ed17e06eSJung-uk Kim  * Redistribution and use in source and binary forms, with or without
12ed17e06eSJung-uk Kim  * modification, are permitted provided that the following conditions
13ed17e06eSJung-uk Kim  * are met:
14ed17e06eSJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
15ed17e06eSJung-uk Kim  *    notice, this list of conditions, and the following disclaimer,
16ed17e06eSJung-uk Kim  *    without modification.
17ed17e06eSJung-uk Kim  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18ed17e06eSJung-uk Kim  *    substantially similar to the "NO WARRANTY" disclaimer below
19ed17e06eSJung-uk Kim  *    ("Disclaimer") and any redistribution must be conditioned upon
20ed17e06eSJung-uk Kim  *    including a substantially similar Disclaimer requirement for further
21ed17e06eSJung-uk Kim  *    binary redistribution.
22ed17e06eSJung-uk Kim  * 3. Neither the names of the above-listed copyright holders nor the names
23ed17e06eSJung-uk Kim  *    of any contributors may be used to endorse or promote products derived
24ed17e06eSJung-uk Kim  *    from this software without specific prior written permission.
25ed17e06eSJung-uk Kim  *
26ed17e06eSJung-uk Kim  * Alternatively, this software may be distributed under the terms of the
27ed17e06eSJung-uk Kim  * GNU General Public License ("GPL") version 2 as published by the Free
28ed17e06eSJung-uk Kim  * Software Foundation.
29ed17e06eSJung-uk Kim  *
30ed17e06eSJung-uk Kim  * NO WARRANTY
31ed17e06eSJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32ed17e06eSJung-uk Kim  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33ed17e06eSJung-uk Kim  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34ed17e06eSJung-uk Kim  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35ed17e06eSJung-uk Kim  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36ed17e06eSJung-uk Kim  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37ed17e06eSJung-uk Kim  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38ed17e06eSJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39ed17e06eSJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40ed17e06eSJung-uk Kim  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41ed17e06eSJung-uk Kim  * POSSIBILITY OF SUCH DAMAGES.
42ed17e06eSJung-uk Kim  */
43ed17e06eSJung-uk Kim 
44ed17e06eSJung-uk Kim 
45ed17e06eSJung-uk Kim #include <contrib/dev/acpica/include/acpi.h>
46ed17e06eSJung-uk Kim #include <contrib/dev/acpica/include/accommon.h>
47ed17e06eSJung-uk Kim #include <contrib/dev/acpica/include/acdispat.h>
48ed17e06eSJung-uk Kim #include <contrib/dev/acpica/include/amlcode.h>
49ed17e06eSJung-uk Kim #include <contrib/dev/acpica/include/acdisasm.h>
50ed17e06eSJung-uk Kim #include <contrib/dev/acpica/include/acparser.h>
51ed17e06eSJung-uk Kim 
52ed17e06eSJung-uk Kim #define _COMPONENT          ACPI_CA_DISASSEMBLER
53ed17e06eSJung-uk Kim         ACPI_MODULE_NAME    ("dmdeferred")
54ed17e06eSJung-uk Kim 
55ed17e06eSJung-uk Kim 
56ed17e06eSJung-uk Kim /* Local prototypes */
57ed17e06eSJung-uk Kim 
58ed17e06eSJung-uk Kim static ACPI_STATUS
59ed17e06eSJung-uk Kim AcpiDmDeferredParse (
60ed17e06eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op,
61ed17e06eSJung-uk Kim     UINT8                   *Aml,
62ed17e06eSJung-uk Kim     UINT32                  AmlLength);
63ed17e06eSJung-uk Kim 
64ed17e06eSJung-uk Kim 
65ed17e06eSJung-uk Kim /******************************************************************************
66ed17e06eSJung-uk Kim  *
67ed17e06eSJung-uk Kim  * FUNCTION:    AcpiDmParseDeferredOps
68ed17e06eSJung-uk Kim  *
69ed17e06eSJung-uk Kim  * PARAMETERS:  Root                - Root of the parse tree
70ed17e06eSJung-uk Kim  *
71ed17e06eSJung-uk Kim  * RETURN:      Status
72ed17e06eSJung-uk Kim  *
73ed17e06eSJung-uk Kim  * DESCRIPTION: Parse the deferred opcodes (Methods, regions, etc.)
74ed17e06eSJung-uk Kim  *
75ed17e06eSJung-uk Kim  *****************************************************************************/
76ed17e06eSJung-uk Kim 
77ed17e06eSJung-uk Kim ACPI_STATUS
78ed17e06eSJung-uk Kim AcpiDmParseDeferredOps (
79ed17e06eSJung-uk Kim     ACPI_PARSE_OBJECT       *Root)
80ed17e06eSJung-uk Kim {
81ed17e06eSJung-uk Kim     const ACPI_OPCODE_INFO  *OpInfo;
82ed17e06eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op = Root;
83ed17e06eSJung-uk Kim     ACPI_STATUS             Status;
84ed17e06eSJung-uk Kim 
85ed17e06eSJung-uk Kim 
86*efcc2a30SJung-uk Kim     ACPI_FUNCTION_ENTRY ();
87ed17e06eSJung-uk Kim 
88ed17e06eSJung-uk Kim 
89ed17e06eSJung-uk Kim     /* Traverse the entire parse tree */
90ed17e06eSJung-uk Kim 
91ed17e06eSJung-uk Kim     while (Op)
92ed17e06eSJung-uk Kim     {
93ed17e06eSJung-uk Kim         OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode);
94ed17e06eSJung-uk Kim         if (!(OpInfo->Flags & AML_DEFER))
95ed17e06eSJung-uk Kim         {
96ed17e06eSJung-uk Kim             Op = AcpiPsGetDepthNext (Root, Op);
97ed17e06eSJung-uk Kim             continue;
98ed17e06eSJung-uk Kim         }
99ed17e06eSJung-uk Kim 
100ed17e06eSJung-uk Kim         /* Now we know we have a deferred opcode */
101ed17e06eSJung-uk Kim 
102ed17e06eSJung-uk Kim         switch (Op->Common.AmlOpcode)
103ed17e06eSJung-uk Kim         {
104ed17e06eSJung-uk Kim         case AML_METHOD_OP:
105ed17e06eSJung-uk Kim         case AML_BUFFER_OP:
106ed17e06eSJung-uk Kim         case AML_PACKAGE_OP:
107ed17e06eSJung-uk Kim         case AML_VAR_PACKAGE_OP:
108ed17e06eSJung-uk Kim 
109ed17e06eSJung-uk Kim             Status = AcpiDmDeferredParse (Op, Op->Named.Data, Op->Named.Length);
110ed17e06eSJung-uk Kim             if (ACPI_FAILURE (Status))
111ed17e06eSJung-uk Kim             {
112ed17e06eSJung-uk Kim                 return (Status);
113ed17e06eSJung-uk Kim             }
114ed17e06eSJung-uk Kim             break;
115ed17e06eSJung-uk Kim 
116ed17e06eSJung-uk Kim         /* We don't need to do anything for these deferred opcodes */
117ed17e06eSJung-uk Kim 
118ed17e06eSJung-uk Kim         case AML_REGION_OP:
119ed17e06eSJung-uk Kim         case AML_DATA_REGION_OP:
120ed17e06eSJung-uk Kim         case AML_CREATE_QWORD_FIELD_OP:
121ed17e06eSJung-uk Kim         case AML_CREATE_DWORD_FIELD_OP:
122ed17e06eSJung-uk Kim         case AML_CREATE_WORD_FIELD_OP:
123ed17e06eSJung-uk Kim         case AML_CREATE_BYTE_FIELD_OP:
124ed17e06eSJung-uk Kim         case AML_CREATE_BIT_FIELD_OP:
125ed17e06eSJung-uk Kim         case AML_CREATE_FIELD_OP:
126ed17e06eSJung-uk Kim         case AML_BANK_FIELD_OP:
127ed17e06eSJung-uk Kim 
128ed17e06eSJung-uk Kim             break;
129ed17e06eSJung-uk Kim 
130ed17e06eSJung-uk Kim         default:
131ed17e06eSJung-uk Kim             ACPI_ERROR ((AE_INFO, "Unhandled deferred AML opcode [0x%.4X]",
132ed17e06eSJung-uk Kim                  Op->Common.AmlOpcode));
133ed17e06eSJung-uk Kim             break;
134ed17e06eSJung-uk Kim         }
135ed17e06eSJung-uk Kim 
136ed17e06eSJung-uk Kim         Op = AcpiPsGetDepthNext (Root, Op);
137ed17e06eSJung-uk Kim     }
138ed17e06eSJung-uk Kim 
139ed17e06eSJung-uk Kim     return (AE_OK);
140ed17e06eSJung-uk Kim }
141ed17e06eSJung-uk Kim 
142ed17e06eSJung-uk Kim 
143ed17e06eSJung-uk Kim /******************************************************************************
144ed17e06eSJung-uk Kim  *
145ed17e06eSJung-uk Kim  * FUNCTION:    AcpiDmDeferredParse
146ed17e06eSJung-uk Kim  *
147ed17e06eSJung-uk Kim  * PARAMETERS:  Op                  - Root Op of the deferred opcode
148ed17e06eSJung-uk Kim  *              Aml                 - Pointer to the raw AML
149ed17e06eSJung-uk Kim  *              AmlLength           - Length of the AML
150ed17e06eSJung-uk Kim  *
151ed17e06eSJung-uk Kim  * RETURN:      Status
152ed17e06eSJung-uk Kim  *
153ed17e06eSJung-uk Kim  * DESCRIPTION: Parse one deferred opcode
154ed17e06eSJung-uk Kim  *              (Methods, operation regions, etc.)
155ed17e06eSJung-uk Kim  *
156ed17e06eSJung-uk Kim  *****************************************************************************/
157ed17e06eSJung-uk Kim 
158ed17e06eSJung-uk Kim static ACPI_STATUS
159ed17e06eSJung-uk Kim AcpiDmDeferredParse (
160ed17e06eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op,
161ed17e06eSJung-uk Kim     UINT8                   *Aml,
162ed17e06eSJung-uk Kim     UINT32                  AmlLength)
163ed17e06eSJung-uk Kim {
164ed17e06eSJung-uk Kim     ACPI_WALK_STATE         *WalkState;
165ed17e06eSJung-uk Kim     ACPI_STATUS             Status;
166ed17e06eSJung-uk Kim     ACPI_PARSE_OBJECT       *SearchOp;
167ed17e06eSJung-uk Kim     ACPI_PARSE_OBJECT       *StartOp;
168ed17e06eSJung-uk Kim     UINT32                  BaseAmlOffset;
169ed17e06eSJung-uk Kim     ACPI_PARSE_OBJECT       *NewRootOp;
170ed17e06eSJung-uk Kim     ACPI_PARSE_OBJECT       *ExtraOp;
171ed17e06eSJung-uk Kim 
172ed17e06eSJung-uk Kim 
173ed17e06eSJung-uk Kim     ACPI_FUNCTION_TRACE (DmDeferredParse);
174ed17e06eSJung-uk Kim 
175ed17e06eSJung-uk Kim 
176ed17e06eSJung-uk Kim     if (!Aml || !AmlLength)
177ed17e06eSJung-uk Kim     {
178ed17e06eSJung-uk Kim         return_ACPI_STATUS (AE_OK);
179ed17e06eSJung-uk Kim     }
180ed17e06eSJung-uk Kim 
181ed17e06eSJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Parsing deferred opcode %s [%4.4s]\n",
182ed17e06eSJung-uk Kim         Op->Common.AmlOpName, (char *) &Op->Named.Name));
183ed17e06eSJung-uk Kim 
184ed17e06eSJung-uk Kim     /* Need a new walk state to parse the AML */
185ed17e06eSJung-uk Kim 
186ed17e06eSJung-uk Kim     WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL);
187ed17e06eSJung-uk Kim     if (!WalkState)
188ed17e06eSJung-uk Kim     {
189ed17e06eSJung-uk Kim         return_ACPI_STATUS (AE_NO_MEMORY);
190ed17e06eSJung-uk Kim     }
191ed17e06eSJung-uk Kim 
192ed17e06eSJung-uk Kim     Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, Aml,
193ed17e06eSJung-uk Kim         AmlLength, NULL, ACPI_IMODE_LOAD_PASS1);
194ed17e06eSJung-uk Kim     if (ACPI_FAILURE (Status))
195ed17e06eSJung-uk Kim     {
196ed17e06eSJung-uk Kim         return_ACPI_STATUS (Status);
197ed17e06eSJung-uk Kim     }
198ed17e06eSJung-uk Kim 
199ed17e06eSJung-uk Kim     /* Parse the AML for this deferred opcode */
200ed17e06eSJung-uk Kim 
201ed17e06eSJung-uk Kim     WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE;
202ed17e06eSJung-uk Kim     WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE;
203ed17e06eSJung-uk Kim     Status = AcpiPsParseAml (WalkState);
204ed17e06eSJung-uk Kim 
205ed17e06eSJung-uk Kim     /*
206ed17e06eSJung-uk Kim      * We need to update all of the AML offsets, since the parser thought
207ed17e06eSJung-uk Kim      * that the method began at offset zero. In reality, it began somewhere
208ed17e06eSJung-uk Kim      * within the ACPI table, at the BaseAmlOffset. Walk the entire tree that
209ed17e06eSJung-uk Kim      * was just created and update the AmlOffset in each Op.
210ed17e06eSJung-uk Kim      */
211ed17e06eSJung-uk Kim     BaseAmlOffset = (Op->Common.Value.Arg)->Common.AmlOffset + 1;
212ed17e06eSJung-uk Kim     StartOp = (Op->Common.Value.Arg)->Common.Next;
213ed17e06eSJung-uk Kim     SearchOp = StartOp;
214ed17e06eSJung-uk Kim 
215ed17e06eSJung-uk Kim     while (SearchOp)
216ed17e06eSJung-uk Kim     {
217ed17e06eSJung-uk Kim         SearchOp->Common.AmlOffset += BaseAmlOffset;
218ed17e06eSJung-uk Kim         SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
219ed17e06eSJung-uk Kim     }
220ed17e06eSJung-uk Kim 
221ed17e06eSJung-uk Kim     /*
222ed17e06eSJung-uk Kim      * For Buffer and Package opcodes, link the newly parsed subtree
223ed17e06eSJung-uk Kim      * into the main parse tree
224ed17e06eSJung-uk Kim      */
225ed17e06eSJung-uk Kim     switch (Op->Common.AmlOpcode)
226ed17e06eSJung-uk Kim     {
227ed17e06eSJung-uk Kim     case AML_BUFFER_OP:
228ed17e06eSJung-uk Kim     case AML_PACKAGE_OP:
229ed17e06eSJung-uk Kim     case AML_VAR_PACKAGE_OP:
230ed17e06eSJung-uk Kim 
231ed17e06eSJung-uk Kim         switch (Op->Common.AmlOpcode)
232ed17e06eSJung-uk Kim         {
233ed17e06eSJung-uk Kim         case AML_PACKAGE_OP:
234ed17e06eSJung-uk Kim 
235ed17e06eSJung-uk Kim             ExtraOp = Op->Common.Value.Arg;
236ed17e06eSJung-uk Kim             NewRootOp = ExtraOp->Common.Next;
237ed17e06eSJung-uk Kim             ACPI_FREE (ExtraOp);
238ed17e06eSJung-uk Kim             break;
239ed17e06eSJung-uk Kim 
240ed17e06eSJung-uk Kim         case AML_VAR_PACKAGE_OP:
241ed17e06eSJung-uk Kim         case AML_BUFFER_OP:
242ed17e06eSJung-uk Kim         default:
243ed17e06eSJung-uk Kim 
244ed17e06eSJung-uk Kim             NewRootOp = Op->Common.Value.Arg;
245ed17e06eSJung-uk Kim             break;
246ed17e06eSJung-uk Kim         }
247ed17e06eSJung-uk Kim 
248ed17e06eSJung-uk Kim         Op->Common.Value.Arg = NewRootOp->Common.Value.Arg;
249ed17e06eSJung-uk Kim 
250ed17e06eSJung-uk Kim         /* Must point all parents to the main tree */
251ed17e06eSJung-uk Kim 
252ed17e06eSJung-uk Kim         StartOp = Op;
253ed17e06eSJung-uk Kim         SearchOp = StartOp;
254ed17e06eSJung-uk Kim         while (SearchOp)
255ed17e06eSJung-uk Kim         {
256ed17e06eSJung-uk Kim             if (SearchOp->Common.Parent == NewRootOp)
257ed17e06eSJung-uk Kim             {
258ed17e06eSJung-uk Kim                 SearchOp->Common.Parent = Op;
259ed17e06eSJung-uk Kim             }
260ed17e06eSJung-uk Kim 
261ed17e06eSJung-uk Kim             SearchOp = AcpiPsGetDepthNext (StartOp, SearchOp);
262ed17e06eSJung-uk Kim         }
263ed17e06eSJung-uk Kim 
264ed17e06eSJung-uk Kim         ACPI_FREE (NewRootOp);
265ed17e06eSJung-uk Kim         break;
266ed17e06eSJung-uk Kim 
267ed17e06eSJung-uk Kim     default:
268ed17e06eSJung-uk Kim         break;
269ed17e06eSJung-uk Kim     }
270ed17e06eSJung-uk Kim 
271ed17e06eSJung-uk Kim     return_ACPI_STATUS (AE_OK);
272ed17e06eSJung-uk Kim }
273