128c506b8Sjruoho /******************************************************************************
228c506b8Sjruoho *
328c506b8Sjruoho * Module Name: nsparse - namespace interface to AML parser
428c506b8Sjruoho *
528c506b8Sjruoho *****************************************************************************/
628c506b8Sjruoho
7124f4c82Sjruoho /*
8*046a2985Schristos * Copyright (C) 2000 - 2023, Intel Corp.
928c506b8Sjruoho * All rights reserved.
1028c506b8Sjruoho *
11124f4c82Sjruoho * Redistribution and use in source and binary forms, with or without
12124f4c82Sjruoho * modification, are permitted provided that the following conditions
13124f4c82Sjruoho * are met:
14124f4c82Sjruoho * 1. Redistributions of source code must retain the above copyright
15124f4c82Sjruoho * notice, this list of conditions, and the following disclaimer,
16124f4c82Sjruoho * without modification.
17124f4c82Sjruoho * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18124f4c82Sjruoho * substantially similar to the "NO WARRANTY" disclaimer below
19124f4c82Sjruoho * ("Disclaimer") and any redistribution must be conditioned upon
20124f4c82Sjruoho * including a substantially similar Disclaimer requirement for further
21124f4c82Sjruoho * binary redistribution.
22124f4c82Sjruoho * 3. Neither the names of the above-listed copyright holders nor the names
23124f4c82Sjruoho * of any contributors may be used to endorse or promote products derived
24124f4c82Sjruoho * from this software without specific prior written permission.
2528c506b8Sjruoho *
26124f4c82Sjruoho * Alternatively, this software may be distributed under the terms of the
27124f4c82Sjruoho * GNU General Public License ("GPL") version 2 as published by the Free
28124f4c82Sjruoho * Software Foundation.
2928c506b8Sjruoho *
30124f4c82Sjruoho * NO WARRANTY
31124f4c82Sjruoho * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32124f4c82Sjruoho * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3346a330b4Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34124f4c82Sjruoho * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35124f4c82Sjruoho * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36124f4c82Sjruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37124f4c82Sjruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38124f4c82Sjruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39124f4c82Sjruoho * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40124f4c82Sjruoho * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41124f4c82Sjruoho * POSSIBILITY OF SUCH DAMAGES.
42124f4c82Sjruoho */
4328c506b8Sjruoho
4428c506b8Sjruoho #include "acpi.h"
4528c506b8Sjruoho #include "accommon.h"
4628c506b8Sjruoho #include "acnamesp.h"
4728c506b8Sjruoho #include "acparser.h"
4828c506b8Sjruoho #include "acdispat.h"
4928c506b8Sjruoho #include "actables.h"
50d0e1da26Schristos #include "acinterp.h"
5128c506b8Sjruoho
5228c506b8Sjruoho
5328c506b8Sjruoho #define _COMPONENT ACPI_NAMESPACE
5428c506b8Sjruoho ACPI_MODULE_NAME ("nsparse")
5528c506b8Sjruoho
5628c506b8Sjruoho
5728c506b8Sjruoho /*******************************************************************************
5828c506b8Sjruoho *
59d0e1da26Schristos * FUNCTION: NsExecuteTable
60d0e1da26Schristos *
61d0e1da26Schristos * PARAMETERS: TableDesc - An ACPI table descriptor for table to parse
62d0e1da26Schristos * StartNode - Where to enter the table into the namespace
63d0e1da26Schristos *
64d0e1da26Schristos * RETURN: Status
65d0e1da26Schristos *
66062782b3Schristos * DESCRIPTION: Load ACPI/AML table by executing the entire table as a single
67062782b3Schristos * large control method.
68062782b3Schristos *
69062782b3Schristos * NOTE: The point of this is to execute any module-level code in-place
70062782b3Schristos * as the table is parsed. Some AML code depends on this behavior.
71062782b3Schristos *
72062782b3Schristos * It is a run-time option at this time, but will eventually become
73062782b3Schristos * the default.
74062782b3Schristos *
75062782b3Schristos * Note: This causes the table to only have a single-pass parse.
76062782b3Schristos * However, this is compatible with other ACPI implementations.
77d0e1da26Schristos *
78d0e1da26Schristos ******************************************************************************/
79d0e1da26Schristos
80d0e1da26Schristos ACPI_STATUS
AcpiNsExecuteTable(UINT32 TableIndex,ACPI_NAMESPACE_NODE * StartNode)81d0e1da26Schristos AcpiNsExecuteTable (
82d0e1da26Schristos UINT32 TableIndex,
83d0e1da26Schristos ACPI_NAMESPACE_NODE *StartNode)
84d0e1da26Schristos {
85d0e1da26Schristos ACPI_STATUS Status;
86d0e1da26Schristos ACPI_TABLE_HEADER *Table;
87d0e1da26Schristos ACPI_OWNER_ID OwnerId;
88d0e1da26Schristos ACPI_EVALUATE_INFO *Info = NULL;
89d0e1da26Schristos UINT32 AmlLength;
90d0e1da26Schristos UINT8 *AmlStart;
91d0e1da26Schristos ACPI_OPERAND_OBJECT *MethodObj = NULL;
92d0e1da26Schristos
93d0e1da26Schristos
94d0e1da26Schristos ACPI_FUNCTION_TRACE (NsExecuteTable);
95d0e1da26Schristos
96d0e1da26Schristos
97d0e1da26Schristos Status = AcpiGetTableByIndex (TableIndex, &Table);
98d0e1da26Schristos if (ACPI_FAILURE (Status))
99d0e1da26Schristos {
100d0e1da26Schristos return_ACPI_STATUS (Status);
101d0e1da26Schristos }
102d0e1da26Schristos
103d0e1da26Schristos /* Table must consist of at least a complete header */
104d0e1da26Schristos
105d0e1da26Schristos if (Table->Length < sizeof (ACPI_TABLE_HEADER))
106d0e1da26Schristos {
107d0e1da26Schristos return_ACPI_STATUS (AE_BAD_HEADER);
108d0e1da26Schristos }
109d0e1da26Schristos
110d0e1da26Schristos AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER);
111d0e1da26Schristos AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
112d0e1da26Schristos
113d0e1da26Schristos Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
114d0e1da26Schristos if (ACPI_FAILURE (Status))
115d0e1da26Schristos {
116d0e1da26Schristos return_ACPI_STATUS (Status);
117d0e1da26Schristos }
118d0e1da26Schristos
119d0e1da26Schristos /* Create, initialize, and link a new temporary method object */
120d0e1da26Schristos
121d0e1da26Schristos MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
122d0e1da26Schristos if (!MethodObj)
123d0e1da26Schristos {
124d0e1da26Schristos return_ACPI_STATUS (AE_NO_MEMORY);
125d0e1da26Schristos }
126d0e1da26Schristos
127d0e1da26Schristos /* Allocate the evaluation information block */
128d0e1da26Schristos
129d0e1da26Schristos Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
130d0e1da26Schristos if (!Info)
131d0e1da26Schristos {
132d0e1da26Schristos Status = AE_NO_MEMORY;
133d0e1da26Schristos goto Cleanup;
134d0e1da26Schristos }
135d0e1da26Schristos
136062782b3Schristos ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,
137062782b3Schristos "%s: Create table pseudo-method for [%4.4s] @%p, method %p\n",
138062782b3Schristos ACPI_GET_FUNCTION_NAME, Table->Signature, Table, MethodObj));
139d0e1da26Schristos
140d0e1da26Schristos MethodObj->Method.AmlStart = AmlStart;
141d0e1da26Schristos MethodObj->Method.AmlLength = AmlLength;
142d0e1da26Schristos MethodObj->Method.OwnerId = OwnerId;
143d0e1da26Schristos MethodObj->Method.InfoFlags |= ACPI_METHOD_MODULE_LEVEL;
144d0e1da26Schristos
145d0e1da26Schristos Info->PassNumber = ACPI_IMODE_EXECUTE;
146d0e1da26Schristos Info->Node = StartNode;
147d0e1da26Schristos Info->ObjDesc = MethodObj;
148d0e1da26Schristos Info->NodeFlags = Info->Node->Flags;
149d0e1da26Schristos Info->FullPathname = AcpiNsGetNormalizedPathname (Info->Node, TRUE);
150d0e1da26Schristos if (!Info->FullPathname)
151d0e1da26Schristos {
152d0e1da26Schristos Status = AE_NO_MEMORY;
153d0e1da26Schristos goto Cleanup;
154d0e1da26Schristos }
155d0e1da26Schristos
1564c4e8184Schristos /* Optional object evaluation log */
1574c4e8184Schristos
1584c4e8184Schristos ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION,
1594c4e8184Schristos "%-26s: (Definition Block level)\n", "Module-level evaluation"));
1604c4e8184Schristos
161d0e1da26Schristos Status = AcpiPsExecuteTable (Info);
162d0e1da26Schristos
1634c4e8184Schristos /* Optional object evaluation log */
1644c4e8184Schristos
1654c4e8184Schristos ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION,
1664c4e8184Schristos "%-26s: (Definition Block level)\n", "Module-level complete"));
1674c4e8184Schristos
168d0e1da26Schristos Cleanup:
169d0e1da26Schristos if (Info)
170d0e1da26Schristos {
171d0e1da26Schristos ACPI_FREE (Info->FullPathname);
172d0e1da26Schristos Info->FullPathname = NULL;
173d0e1da26Schristos }
174d0e1da26Schristos ACPI_FREE (Info);
175d0e1da26Schristos AcpiUtRemoveReference (MethodObj);
176d0e1da26Schristos return_ACPI_STATUS (Status);
177d0e1da26Schristos }
178d0e1da26Schristos
179d0e1da26Schristos
180d0e1da26Schristos /*******************************************************************************
181d0e1da26Schristos *
18228c506b8Sjruoho * FUNCTION: NsOneCompleteParse
18328c506b8Sjruoho *
18428c506b8Sjruoho * PARAMETERS: PassNumber - 1 or 2
18528c506b8Sjruoho * TableDesc - The table to be parsed.
18628c506b8Sjruoho *
18728c506b8Sjruoho * RETURN: Status
18828c506b8Sjruoho *
18928c506b8Sjruoho * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
19028c506b8Sjruoho *
19128c506b8Sjruoho ******************************************************************************/
19228c506b8Sjruoho
19328c506b8Sjruoho ACPI_STATUS
AcpiNsOneCompleteParse(UINT32 PassNumber,UINT32 TableIndex,ACPI_NAMESPACE_NODE * StartNode)19428c506b8Sjruoho AcpiNsOneCompleteParse (
19528c506b8Sjruoho UINT32 PassNumber,
19628c506b8Sjruoho UINT32 TableIndex,
19728c506b8Sjruoho ACPI_NAMESPACE_NODE *StartNode)
19828c506b8Sjruoho {
19928c506b8Sjruoho ACPI_PARSE_OBJECT *ParseRoot;
20028c506b8Sjruoho ACPI_STATUS Status;
20128c506b8Sjruoho UINT32 AmlLength;
20228c506b8Sjruoho UINT8 *AmlStart;
20328c506b8Sjruoho ACPI_WALK_STATE *WalkState;
20428c506b8Sjruoho ACPI_TABLE_HEADER *Table;
20528c506b8Sjruoho ACPI_OWNER_ID OwnerId;
20628c506b8Sjruoho
20728c506b8Sjruoho
20828c506b8Sjruoho ACPI_FUNCTION_TRACE (NsOneCompleteParse);
20928c506b8Sjruoho
21028c506b8Sjruoho
211c72da027Schristos Status = AcpiGetTableByIndex (TableIndex, &Table);
212c72da027Schristos if (ACPI_FAILURE (Status))
213c72da027Schristos {
214c72da027Schristos return_ACPI_STATUS (Status);
215c72da027Schristos }
216c72da027Schristos
217c72da027Schristos /* Table must consist of at least a complete header */
218c72da027Schristos
219c72da027Schristos if (Table->Length < sizeof (ACPI_TABLE_HEADER))
220c72da027Schristos {
221c72da027Schristos return_ACPI_STATUS (AE_BAD_HEADER);
222c72da027Schristos }
223c72da027Schristos
224c72da027Schristos AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER);
225c72da027Schristos AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
226c72da027Schristos
22728c506b8Sjruoho Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
22828c506b8Sjruoho if (ACPI_FAILURE (Status))
22928c506b8Sjruoho {
23028c506b8Sjruoho return_ACPI_STATUS (Status);
23128c506b8Sjruoho }
23228c506b8Sjruoho
23328c506b8Sjruoho /* Create and init a Root Node */
23428c506b8Sjruoho
235c72da027Schristos ParseRoot = AcpiPsCreateScopeOp (AmlStart);
23628c506b8Sjruoho if (!ParseRoot)
23728c506b8Sjruoho {
23828c506b8Sjruoho return_ACPI_STATUS (AE_NO_MEMORY);
23928c506b8Sjruoho }
24028c506b8Sjruoho
24128c506b8Sjruoho /* Create and initialize a new walk state */
24228c506b8Sjruoho
24328c506b8Sjruoho WalkState = AcpiDsCreateWalkState (OwnerId, NULL, NULL, NULL);
24428c506b8Sjruoho if (!WalkState)
24528c506b8Sjruoho {
24628c506b8Sjruoho AcpiPsFreeOp (ParseRoot);
24728c506b8Sjruoho return_ACPI_STATUS (AE_NO_MEMORY);
24828c506b8Sjruoho }
24928c506b8Sjruoho
25028c506b8Sjruoho Status = AcpiDsInitAmlWalk (WalkState, ParseRoot, NULL,
25128c506b8Sjruoho AmlStart, AmlLength, NULL, (UINT8) PassNumber);
25228c506b8Sjruoho if (ACPI_FAILURE (Status))
25328c506b8Sjruoho {
25428c506b8Sjruoho AcpiDsDeleteWalkState (WalkState);
25528c506b8Sjruoho goto Cleanup;
25628c506b8Sjruoho }
25728c506b8Sjruoho
258c72da027Schristos /* Found OSDT table, enable the namespace override feature */
259c72da027Schristos
26094783addSchristos if (ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_OSDT) &&
261c72da027Schristos PassNumber == ACPI_IMODE_LOAD_PASS1)
262c72da027Schristos {
263c72da027Schristos WalkState->NamespaceOverride = TRUE;
264c72da027Schristos }
265c72da027Schristos
26628c506b8Sjruoho /* StartNode is the default location to load the table */
26728c506b8Sjruoho
26828c506b8Sjruoho if (StartNode && StartNode != AcpiGbl_RootNode)
26928c506b8Sjruoho {
27071e38f1dSchristos Status = AcpiDsScopeStackPush (
27171e38f1dSchristos StartNode, ACPI_TYPE_METHOD, WalkState);
27228c506b8Sjruoho if (ACPI_FAILURE (Status))
27328c506b8Sjruoho {
27428c506b8Sjruoho AcpiDsDeleteWalkState (WalkState);
27528c506b8Sjruoho goto Cleanup;
27628c506b8Sjruoho }
27728c506b8Sjruoho }
27828c506b8Sjruoho
27928c506b8Sjruoho /* Parse the AML */
28028c506b8Sjruoho
28171e38f1dSchristos ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
28271e38f1dSchristos "*PARSE* pass %u parse\n", PassNumber));
283d0e1da26Schristos AcpiExEnterInterpreter ();
28428c506b8Sjruoho Status = AcpiPsParseAml (WalkState);
285d0e1da26Schristos AcpiExExitInterpreter ();
28628c506b8Sjruoho
28728c506b8Sjruoho Cleanup:
28828c506b8Sjruoho AcpiPsDeleteParseTree (ParseRoot);
28928c506b8Sjruoho return_ACPI_STATUS (Status);
29028c506b8Sjruoho }
29128c506b8Sjruoho
29228c506b8Sjruoho
29328c506b8Sjruoho /*******************************************************************************
29428c506b8Sjruoho *
29528c506b8Sjruoho * FUNCTION: AcpiNsParseTable
29628c506b8Sjruoho *
29728c506b8Sjruoho * PARAMETERS: TableDesc - An ACPI table descriptor for table to parse
29828c506b8Sjruoho * StartNode - Where to enter the table into the namespace
29928c506b8Sjruoho *
30028c506b8Sjruoho * RETURN: Status
30128c506b8Sjruoho *
30228c506b8Sjruoho * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
30328c506b8Sjruoho *
30428c506b8Sjruoho ******************************************************************************/
30528c506b8Sjruoho
30628c506b8Sjruoho ACPI_STATUS
AcpiNsParseTable(UINT32 TableIndex,ACPI_NAMESPACE_NODE * StartNode)30728c506b8Sjruoho AcpiNsParseTable (
30828c506b8Sjruoho UINT32 TableIndex,
30928c506b8Sjruoho ACPI_NAMESPACE_NODE *StartNode)
31028c506b8Sjruoho {
31128c506b8Sjruoho ACPI_STATUS Status;
31228c506b8Sjruoho
31328c506b8Sjruoho
31428c506b8Sjruoho ACPI_FUNCTION_TRACE (NsParseTable);
31528c506b8Sjruoho
31628c506b8Sjruoho
317062782b3Schristos /*
31894783addSchristos * Executes the AML table as one large control method.
319062782b3Schristos * The point of this is to execute any module-level code in-place
320062782b3Schristos * as the table is parsed. Some AML code depends on this behavior.
321062782b3Schristos *
322062782b3Schristos * Note: This causes the table to only have a single-pass parse.
323062782b3Schristos * However, this is compatible with other ACPI implementations.
324062782b3Schristos */
325062782b3Schristos ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE,
326062782b3Schristos "%s: **** Start table execution pass\n", ACPI_GET_FUNCTION_NAME));
327d0e1da26Schristos
328d0e1da26Schristos Status = AcpiNsExecuteTable (TableIndex, StartNode);
32928c506b8Sjruoho
33028c506b8Sjruoho return_ACPI_STATUS (Status);
33128c506b8Sjruoho }
332