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