195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown *
495b482a8SLen Brown * Module Name: nsparse - namespace interface to AML parser
595b482a8SLen Brown *
6*612c2932SBob Moore * Copyright (C) 2000 - 2023, Intel Corp.
795b482a8SLen Brown *
895857638SErik Schmauss *****************************************************************************/
995b482a8SLen Brown
1095b482a8SLen Brown #include <acpi/acpi.h>
11e2f7a777SLen Brown #include "accommon.h"
12e2f7a777SLen Brown #include "acnamesp.h"
13e2f7a777SLen Brown #include "acparser.h"
14e2f7a777SLen Brown #include "acdispat.h"
15e2f7a777SLen Brown #include "actables.h"
1674f51b80SLv Zheng #include "acinterp.h"
1795b482a8SLen Brown
1895b482a8SLen Brown #define _COMPONENT ACPI_NAMESPACE
1995b482a8SLen Brown ACPI_MODULE_NAME("nsparse")
2095b482a8SLen Brown
2195b482a8SLen Brown /*******************************************************************************
2295b482a8SLen Brown *
23de56ba95SLv Zheng * FUNCTION: ns_execute_table
24de56ba95SLv Zheng *
25de56ba95SLv Zheng * PARAMETERS: table_desc - An ACPI table descriptor for table to parse
26de56ba95SLv Zheng * start_node - Where to enter the table into the namespace
27de56ba95SLv Zheng *
28de56ba95SLv Zheng * RETURN: Status
29de56ba95SLv Zheng *
30a406dea8SBob Moore * DESCRIPTION: Load ACPI/AML table by executing the entire table as a single
31a406dea8SBob Moore * large control method.
32a406dea8SBob Moore *
33a406dea8SBob Moore * NOTE: The point of this is to execute any module-level code in-place
34a406dea8SBob Moore * as the table is parsed. Some AML code depends on this behavior.
35a406dea8SBob Moore *
36a406dea8SBob Moore * It is a run-time option at this time, but will eventually become
37a406dea8SBob Moore * the default.
38a406dea8SBob Moore *
39a406dea8SBob Moore * Note: This causes the table to only have a single-pass parse.
40a406dea8SBob Moore * However, this is compatible with other ACPI implementations.
41de56ba95SLv Zheng *
42de56ba95SLv Zheng ******************************************************************************/
43de56ba95SLv Zheng acpi_status
acpi_ns_execute_table(u32 table_index,struct acpi_namespace_node * start_node)44de56ba95SLv Zheng acpi_ns_execute_table(u32 table_index, struct acpi_namespace_node *start_node)
45de56ba95SLv Zheng {
46de56ba95SLv Zheng acpi_status status;
47de56ba95SLv Zheng struct acpi_table_header *table;
48de56ba95SLv Zheng acpi_owner_id owner_id;
49de56ba95SLv Zheng struct acpi_evaluate_info *info = NULL;
50de56ba95SLv Zheng u32 aml_length;
51de56ba95SLv Zheng u8 *aml_start;
52de56ba95SLv Zheng union acpi_operand_object *method_obj = NULL;
53de56ba95SLv Zheng
54de56ba95SLv Zheng ACPI_FUNCTION_TRACE(ns_execute_table);
55de56ba95SLv Zheng
56de56ba95SLv Zheng status = acpi_get_table_by_index(table_index, &table);
57de56ba95SLv Zheng if (ACPI_FAILURE(status)) {
58de56ba95SLv Zheng return_ACPI_STATUS(status);
59de56ba95SLv Zheng }
60de56ba95SLv Zheng
61de56ba95SLv Zheng /* Table must consist of at least a complete header */
62de56ba95SLv Zheng
63de56ba95SLv Zheng if (table->length < sizeof(struct acpi_table_header)) {
64de56ba95SLv Zheng return_ACPI_STATUS(AE_BAD_HEADER);
65de56ba95SLv Zheng }
66de56ba95SLv Zheng
67de56ba95SLv Zheng aml_start = (u8 *)table + sizeof(struct acpi_table_header);
68de56ba95SLv Zheng aml_length = table->length - sizeof(struct acpi_table_header);
69de56ba95SLv Zheng
70de56ba95SLv Zheng status = acpi_tb_get_owner_id(table_index, &owner_id);
71de56ba95SLv Zheng if (ACPI_FAILURE(status)) {
72de56ba95SLv Zheng return_ACPI_STATUS(status);
73de56ba95SLv Zheng }
74de56ba95SLv Zheng
75de56ba95SLv Zheng /* Create, initialize, and link a new temporary method object */
76de56ba95SLv Zheng
77de56ba95SLv Zheng method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
78de56ba95SLv Zheng if (!method_obj) {
79de56ba95SLv Zheng return_ACPI_STATUS(AE_NO_MEMORY);
80de56ba95SLv Zheng }
81de56ba95SLv Zheng
82de56ba95SLv Zheng /* Allocate the evaluation information block */
83de56ba95SLv Zheng
84de56ba95SLv Zheng info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
85de56ba95SLv Zheng if (!info) {
86de56ba95SLv Zheng status = AE_NO_MEMORY;
87de56ba95SLv Zheng goto cleanup;
88de56ba95SLv Zheng }
89de56ba95SLv Zheng
901ef63231SBob Moore ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
911ef63231SBob Moore "%s: Create table pseudo-method for [%4.4s] @%p, method %p\n",
921ef63231SBob Moore ACPI_GET_FUNCTION_NAME, table->signature, table,
931ef63231SBob Moore method_obj));
94de56ba95SLv Zheng
95de56ba95SLv Zheng method_obj->method.aml_start = aml_start;
96de56ba95SLv Zheng method_obj->method.aml_length = aml_length;
97de56ba95SLv Zheng method_obj->method.owner_id = owner_id;
98de56ba95SLv Zheng method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;
99de56ba95SLv Zheng
100de56ba95SLv Zheng info->pass_number = ACPI_IMODE_EXECUTE;
101de56ba95SLv Zheng info->node = start_node;
102de56ba95SLv Zheng info->obj_desc = method_obj;
103de56ba95SLv Zheng info->node_flags = info->node->flags;
104de56ba95SLv Zheng info->full_pathname = acpi_ns_get_normalized_pathname(info->node, TRUE);
105de56ba95SLv Zheng if (!info->full_pathname) {
106de56ba95SLv Zheng status = AE_NO_MEMORY;
107de56ba95SLv Zheng goto cleanup;
108de56ba95SLv Zheng }
109de56ba95SLv Zheng
1104c1379d7SBob Moore /* Optional object evaluation log */
1114c1379d7SBob Moore
1124c1379d7SBob Moore ACPI_DEBUG_PRINT_RAW((ACPI_DB_EVALUATION,
1134c1379d7SBob Moore "%-26s: (Definition Block level)\n",
1144c1379d7SBob Moore "Module-level evaluation"));
1154c1379d7SBob Moore
116de56ba95SLv Zheng status = acpi_ps_execute_table(info);
117de56ba95SLv Zheng
1184c1379d7SBob Moore /* Optional object evaluation log */
1194c1379d7SBob Moore
1204c1379d7SBob Moore ACPI_DEBUG_PRINT_RAW((ACPI_DB_EVALUATION,
1214c1379d7SBob Moore "%-26s: (Definition Block level)\n",
1224c1379d7SBob Moore "Module-level complete"));
1234c1379d7SBob Moore
124de56ba95SLv Zheng cleanup:
125de56ba95SLv Zheng if (info) {
126de56ba95SLv Zheng ACPI_FREE(info->full_pathname);
127de56ba95SLv Zheng info->full_pathname = NULL;
128de56ba95SLv Zheng }
129de56ba95SLv Zheng ACPI_FREE(info);
130de56ba95SLv Zheng acpi_ut_remove_reference(method_obj);
131de56ba95SLv Zheng return_ACPI_STATUS(status);
132de56ba95SLv Zheng }
133de56ba95SLv Zheng
134de56ba95SLv Zheng /*******************************************************************************
135de56ba95SLv Zheng *
13695b482a8SLen Brown * FUNCTION: ns_one_complete_parse
13795b482a8SLen Brown *
13895b482a8SLen Brown * PARAMETERS: pass_number - 1 or 2
13995b482a8SLen Brown * table_desc - The table to be parsed.
14095b482a8SLen Brown *
14195b482a8SLen Brown * RETURN: Status
14295b482a8SLen Brown *
14395b482a8SLen Brown * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
14495b482a8SLen Brown *
14595b482a8SLen Brown ******************************************************************************/
146de56ba95SLv Zheng
14795b482a8SLen Brown acpi_status
acpi_ns_one_complete_parse(u32 pass_number,u32 table_index,struct acpi_namespace_node * start_node)14895b482a8SLen Brown acpi_ns_one_complete_parse(u32 pass_number,
14995b482a8SLen Brown u32 table_index,
15095b482a8SLen Brown struct acpi_namespace_node *start_node)
15195b482a8SLen Brown {
15295b482a8SLen Brown union acpi_parse_object *parse_root;
15395b482a8SLen Brown acpi_status status;
15495b482a8SLen Brown u32 aml_length;
15595b482a8SLen Brown u8 *aml_start;
15695b482a8SLen Brown struct acpi_walk_state *walk_state;
15795b482a8SLen Brown struct acpi_table_header *table;
15895b482a8SLen Brown acpi_owner_id owner_id;
15995b482a8SLen Brown
16095b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_one_complete_parse);
16195b482a8SLen Brown
16262eb935bSLv Zheng status = acpi_get_table_by_index(table_index, &table);
16362eb935bSLv Zheng if (ACPI_FAILURE(status)) {
16462eb935bSLv Zheng return_ACPI_STATUS(status);
16562eb935bSLv Zheng }
16662eb935bSLv Zheng
16762eb935bSLv Zheng /* Table must consist of at least a complete header */
16862eb935bSLv Zheng
16962eb935bSLv Zheng if (table->length < sizeof(struct acpi_table_header)) {
17062eb935bSLv Zheng return_ACPI_STATUS(AE_BAD_HEADER);
17162eb935bSLv Zheng }
17262eb935bSLv Zheng
17362eb935bSLv Zheng aml_start = (u8 *)table + sizeof(struct acpi_table_header);
17462eb935bSLv Zheng aml_length = table->length - sizeof(struct acpi_table_header);
17562eb935bSLv Zheng
17695b482a8SLen Brown status = acpi_tb_get_owner_id(table_index, &owner_id);
17795b482a8SLen Brown if (ACPI_FAILURE(status)) {
17895b482a8SLen Brown return_ACPI_STATUS(status);
17995b482a8SLen Brown }
18095b482a8SLen Brown
18195b482a8SLen Brown /* Create and init a Root Node */
18295b482a8SLen Brown
18362eb935bSLv Zheng parse_root = acpi_ps_create_scope_op(aml_start);
18495b482a8SLen Brown if (!parse_root) {
18595b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY);
18695b482a8SLen Brown }
18795b482a8SLen Brown
18895b482a8SLen Brown /* Create and initialize a new walk state */
18995b482a8SLen Brown
19095b482a8SLen Brown walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL);
19195b482a8SLen Brown if (!walk_state) {
19295b482a8SLen Brown acpi_ps_free_op(parse_root);
19395b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY);
19495b482a8SLen Brown }
19595b482a8SLen Brown
19695b482a8SLen Brown status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
19795b482a8SLen Brown aml_start, aml_length, NULL,
19895b482a8SLen Brown (u8)pass_number);
19962eb935bSLv Zheng if (ACPI_FAILURE(status)) {
20062eb935bSLv Zheng acpi_ds_delete_walk_state(walk_state);
20162eb935bSLv Zheng goto cleanup;
20295b482a8SLen Brown }
20395b482a8SLen Brown
204fe536995SBob Moore /* Found OSDT table, enable the namespace override feature */
205fe536995SBob Moore
2065599fb69SBob Moore if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_OSDT) &&
207fe536995SBob Moore pass_number == ACPI_IMODE_LOAD_PASS1) {
208fe536995SBob Moore walk_state->namespace_override = TRUE;
209fe536995SBob Moore }
210fe536995SBob Moore
21195b482a8SLen Brown /* start_node is the default location to load the table */
21295b482a8SLen Brown
21395b482a8SLen Brown if (start_node && start_node != acpi_gbl_root_node) {
21495b482a8SLen Brown status =
21595b482a8SLen Brown acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD,
21695b482a8SLen Brown walk_state);
21795b482a8SLen Brown if (ACPI_FAILURE(status)) {
21895b482a8SLen Brown acpi_ds_delete_walk_state(walk_state);
21995b482a8SLen Brown goto cleanup;
22095b482a8SLen Brown }
22195b482a8SLen Brown }
22295b482a8SLen Brown
22395b482a8SLen Brown /* Parse the AML */
22495b482a8SLen Brown
2251fad8738SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
2261fad8738SBob Moore "*PARSE* pass %u parse\n", pass_number));
22774f51b80SLv Zheng acpi_ex_enter_interpreter();
22895b482a8SLen Brown status = acpi_ps_parse_aml(walk_state);
22974f51b80SLv Zheng acpi_ex_exit_interpreter();
23095b482a8SLen Brown
23195b482a8SLen Brown cleanup:
23295b482a8SLen Brown acpi_ps_delete_parse_tree(parse_root);
23395b482a8SLen Brown return_ACPI_STATUS(status);
23495b482a8SLen Brown }
23595b482a8SLen Brown
23695b482a8SLen Brown /*******************************************************************************
23795b482a8SLen Brown *
23895b482a8SLen Brown * FUNCTION: acpi_ns_parse_table
23995b482a8SLen Brown *
24095b482a8SLen Brown * PARAMETERS: table_desc - An ACPI table descriptor for table to parse
24195b482a8SLen Brown * start_node - Where to enter the table into the namespace
24295b482a8SLen Brown *
24395b482a8SLen Brown * RETURN: Status
24495b482a8SLen Brown *
24595b482a8SLen Brown * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
24695b482a8SLen Brown *
24795b482a8SLen Brown ******************************************************************************/
24895b482a8SLen Brown
24995b482a8SLen Brown acpi_status
acpi_ns_parse_table(u32 table_index,struct acpi_namespace_node * start_node)25095b482a8SLen Brown acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
25195b482a8SLen Brown {
25295b482a8SLen Brown acpi_status status;
25395b482a8SLen Brown
25495b482a8SLen Brown ACPI_FUNCTION_TRACE(ns_parse_table);
25595b482a8SLen Brown
256a406dea8SBob Moore /*
257aa342261SErik Schmauss * Executes the AML table as one large control method.
258a406dea8SBob Moore * The point of this is to execute any module-level code in-place
259a406dea8SBob Moore * as the table is parsed. Some AML code depends on this behavior.
260a406dea8SBob Moore *
261a406dea8SBob Moore * Note: This causes the table to only have a single-pass parse.
262a406dea8SBob Moore * However, this is compatible with other ACPI implementations.
263a406dea8SBob Moore */
2645a8361f7SSchmauss, Erik ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
2655a8361f7SSchmauss, Erik "%s: **** Start table execution pass\n",
2665a8361f7SSchmauss, Erik ACPI_GET_FUNCTION_NAME));
267de56ba95SLv Zheng
268de56ba95SLv Zheng status = acpi_ns_execute_table(table_index, start_node);
26995b482a8SLen Brown
27095b482a8SLen Brown return_ACPI_STATUS(status);
27195b482a8SLen Brown }
272