Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: nsparse - namespace interface to AML parser
5 : : *
6 : : * Copyright (C) 2000 - 2020, Intel Corp.
7 : : *
8 : : *****************************************************************************/
9 : :
10 : : #include <acpi/acpi.h>
11 : : #include "accommon.h"
12 : : #include "acnamesp.h"
13 : : #include "acparser.h"
14 : : #include "acdispat.h"
15 : : #include "actables.h"
16 : : #include "acinterp.h"
17 : :
18 : : #define _COMPONENT ACPI_NAMESPACE
19 : : ACPI_MODULE_NAME("nsparse")
20 : :
21 : : /*******************************************************************************
22 : : *
23 : : * FUNCTION: ns_execute_table
24 : : *
25 : : * PARAMETERS: table_desc - An ACPI table descriptor for table to parse
26 : : * start_node - Where to enter the table into the namespace
27 : : *
28 : : * RETURN: Status
29 : : *
30 : : * DESCRIPTION: Load ACPI/AML table by executing the entire table as a single
31 : : * large control method.
32 : : *
33 : : * NOTE: The point of this is to execute any module-level code in-place
34 : : * as the table is parsed. Some AML code depends on this behavior.
35 : : *
36 : : * It is a run-time option at this time, but will eventually become
37 : : * the default.
38 : : *
39 : : * Note: This causes the table to only have a single-pass parse.
40 : : * However, this is compatible with other ACPI implementations.
41 : : *
42 : : ******************************************************************************/
43 : : acpi_status
44 : 28 : acpi_ns_execute_table(u32 table_index, struct acpi_namespace_node *start_node)
45 : : {
46 : 28 : acpi_status status;
47 : 28 : struct acpi_table_header *table;
48 : 28 : acpi_owner_id owner_id;
49 : 28 : struct acpi_evaluate_info *info = NULL;
50 : 28 : u32 aml_length;
51 : 28 : u8 *aml_start;
52 : 28 : union acpi_operand_object *method_obj = NULL;
53 : :
54 : 28 : ACPI_FUNCTION_TRACE(ns_execute_table);
55 : :
56 : 28 : status = acpi_get_table_by_index(table_index, &table);
57 [ + - ]: 28 : if (ACPI_FAILURE(status)) {
58 : : return_ACPI_STATUS(status);
59 : : }
60 : :
61 : : /* Table must consist of at least a complete header */
62 : :
63 [ + - ]: 28 : if (table->length < sizeof(struct acpi_table_header)) {
64 : : return_ACPI_STATUS(AE_BAD_HEADER);
65 : : }
66 : :
67 : 28 : aml_start = (u8 *)table + sizeof(struct acpi_table_header);
68 : 28 : aml_length = table->length - sizeof(struct acpi_table_header);
69 : :
70 : 28 : status = acpi_tb_get_owner_id(table_index, &owner_id);
71 [ + - ]: 28 : if (ACPI_FAILURE(status)) {
72 : : return_ACPI_STATUS(status);
73 : : }
74 : :
75 : : /* Create, initialize, and link a new temporary method object */
76 : :
77 : 28 : method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
78 [ + - ]: 28 : if (!method_obj) {
79 : : return_ACPI_STATUS(AE_NO_MEMORY);
80 : : }
81 : :
82 : : /* Allocate the evaluation information block */
83 : :
84 : 28 : info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
85 [ - + ]: 28 : if (!info) {
86 : 0 : status = AE_NO_MEMORY;
87 : 0 : goto cleanup;
88 : : }
89 : :
90 : : ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
91 : : "%s: Create table pseudo-method for [%4.4s] @%p, method %p\n",
92 : : ACPI_GET_FUNCTION_NAME, table->signature, table,
93 : 28 : method_obj));
94 : :
95 : 28 : method_obj->method.aml_start = aml_start;
96 : 28 : method_obj->method.aml_length = aml_length;
97 : 28 : method_obj->method.owner_id = owner_id;
98 : 28 : method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;
99 : :
100 : 28 : info->pass_number = ACPI_IMODE_EXECUTE;
101 : 28 : info->node = start_node;
102 : 28 : info->obj_desc = method_obj;
103 : 28 : info->node_flags = info->node->flags;
104 : 28 : info->full_pathname = acpi_ns_get_normalized_pathname(info->node, TRUE);
105 [ - + ]: 28 : if (!info->full_pathname) {
106 : 0 : status = AE_NO_MEMORY;
107 : 0 : goto cleanup;
108 : : }
109 : :
110 : : /* Optional object evaluation log */
111 : :
112 : : ACPI_DEBUG_PRINT_RAW((ACPI_DB_EVALUATION,
113 : : "%-26s: (Definition Block level)\n",
114 : 28 : "Module-level evaluation"));
115 : :
116 : 28 : status = acpi_ps_execute_table(info);
117 : :
118 : : /* Optional object evaluation log */
119 : :
120 : : ACPI_DEBUG_PRINT_RAW((ACPI_DB_EVALUATION,
121 : : "%-26s: (Definition Block level)\n",
122 : 28 : "Module-level complete"));
123 : :
124 : 28 : cleanup:
125 [ + - ]: 28 : if (info) {
126 : 28 : ACPI_FREE(info->full_pathname);
127 : 28 : info->full_pathname = NULL;
128 : : }
129 : 28 : ACPI_FREE(info);
130 : 28 : acpi_ut_remove_reference(method_obj);
131 : 28 : return_ACPI_STATUS(status);
132 : : }
133 : :
134 : : /*******************************************************************************
135 : : *
136 : : * FUNCTION: ns_one_complete_parse
137 : : *
138 : : * PARAMETERS: pass_number - 1 or 2
139 : : * table_desc - The table to be parsed.
140 : : *
141 : : * RETURN: Status
142 : : *
143 : : * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
144 : : *
145 : : ******************************************************************************/
146 : :
147 : : acpi_status
148 : 0 : acpi_ns_one_complete_parse(u32 pass_number,
149 : : u32 table_index,
150 : : struct acpi_namespace_node *start_node)
151 : : {
152 : 0 : union acpi_parse_object *parse_root;
153 : 0 : acpi_status status;
154 : 0 : u32 aml_length;
155 : 0 : u8 *aml_start;
156 : 0 : struct acpi_walk_state *walk_state;
157 : 0 : struct acpi_table_header *table;
158 : 0 : acpi_owner_id owner_id;
159 : :
160 : 0 : ACPI_FUNCTION_TRACE(ns_one_complete_parse);
161 : :
162 : 0 : status = acpi_get_table_by_index(table_index, &table);
163 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
164 : : return_ACPI_STATUS(status);
165 : : }
166 : :
167 : : /* Table must consist of at least a complete header */
168 : :
169 [ # # ]: 0 : if (table->length < sizeof(struct acpi_table_header)) {
170 : : return_ACPI_STATUS(AE_BAD_HEADER);
171 : : }
172 : :
173 : 0 : aml_start = (u8 *)table + sizeof(struct acpi_table_header);
174 : 0 : aml_length = table->length - sizeof(struct acpi_table_header);
175 : :
176 : 0 : status = acpi_tb_get_owner_id(table_index, &owner_id);
177 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
178 : : return_ACPI_STATUS(status);
179 : : }
180 : :
181 : : /* Create and init a Root Node */
182 : :
183 : 0 : parse_root = acpi_ps_create_scope_op(aml_start);
184 [ # # ]: 0 : if (!parse_root) {
185 : : return_ACPI_STATUS(AE_NO_MEMORY);
186 : : }
187 : :
188 : : /* Create and initialize a new walk state */
189 : :
190 : 0 : walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL);
191 [ # # ]: 0 : if (!walk_state) {
192 : 0 : acpi_ps_free_op(parse_root);
193 : 0 : return_ACPI_STATUS(AE_NO_MEMORY);
194 : : }
195 : :
196 : 0 : status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
197 : : aml_start, aml_length, NULL,
198 : : (u8)pass_number);
199 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
200 : 0 : acpi_ds_delete_walk_state(walk_state);
201 : 0 : goto cleanup;
202 : : }
203 : :
204 : : /* Found OSDT table, enable the namespace override feature */
205 : :
206 [ # # # # ]: 0 : if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_OSDT) &&
207 : : pass_number == ACPI_IMODE_LOAD_PASS1) {
208 : 0 : walk_state->namespace_override = TRUE;
209 : : }
210 : :
211 : : /* start_node is the default location to load the table */
212 : :
213 [ # # # # ]: 0 : if (start_node && start_node != acpi_gbl_root_node) {
214 : 0 : status =
215 : 0 : acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD,
216 : : walk_state);
217 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
218 : 0 : acpi_ds_delete_walk_state(walk_state);
219 : 0 : goto cleanup;
220 : : }
221 : : }
222 : :
223 : : /* Parse the AML */
224 : :
225 : : ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
226 : 0 : "*PARSE* pass %u parse\n", pass_number));
227 : 0 : acpi_ex_enter_interpreter();
228 : 0 : status = acpi_ps_parse_aml(walk_state);
229 : 0 : acpi_ex_exit_interpreter();
230 : :
231 : 0 : cleanup:
232 : 0 : acpi_ps_delete_parse_tree(parse_root);
233 : 0 : return_ACPI_STATUS(status);
234 : : }
235 : :
236 : : /*******************************************************************************
237 : : *
238 : : * FUNCTION: acpi_ns_parse_table
239 : : *
240 : : * PARAMETERS: table_desc - An ACPI table descriptor for table to parse
241 : : * start_node - Where to enter the table into the namespace
242 : : *
243 : : * RETURN: Status
244 : : *
245 : : * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
246 : : *
247 : : ******************************************************************************/
248 : :
249 : : acpi_status
250 : 28 : acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
251 : : {
252 : 28 : acpi_status status;
253 : :
254 : 28 : ACPI_FUNCTION_TRACE(ns_parse_table);
255 : :
256 : : /*
257 : : * Executes the AML table as one large control method.
258 : : * The point of this is to execute any module-level code in-place
259 : : * as the table is parsed. Some AML code depends on this behavior.
260 : : *
261 : : * Note: This causes the table to only have a single-pass parse.
262 : : * However, this is compatible with other ACPI implementations.
263 : : */
264 : : ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
265 : : "%s: **** Start table execution pass\n",
266 : 28 : ACPI_GET_FUNCTION_NAME));
267 : :
268 : 28 : status = acpi_ns_execute_table(table_index, start_node);
269 : :
270 : 28 : return_ACPI_STATUS(status);
271 : : }
|