375 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: dsargs - Support for execution of dynamic arguments for static5 * objects (regions, fields, buffer fields, etc.)6 *7 * Copyright (C) 2000 - 2023, Intel Corp.8 *9 *****************************************************************************/10 11#include <acpi/acpi.h>12#include "accommon.h"13#include "acparser.h"14#include "amlcode.h"15#include "acdispat.h"16#include "acnamesp.h"17 18#define _COMPONENT ACPI_DISPATCHER19ACPI_MODULE_NAME("dsargs")20 21/* Local prototypes */22static acpi_status23acpi_ds_execute_arguments(struct acpi_namespace_node *node,24 struct acpi_namespace_node *scope_node,25 u32 aml_length, u8 *aml_start);26 27/*******************************************************************************28 *29 * FUNCTION: acpi_ds_execute_arguments30 *31 * PARAMETERS: node - Object NS node32 * scope_node - Parent NS node33 * aml_length - Length of executable AML34 * aml_start - Pointer to the AML35 *36 * RETURN: Status.37 *38 * DESCRIPTION: Late (deferred) execution of region or field arguments39 *40 ******************************************************************************/41 42static acpi_status43acpi_ds_execute_arguments(struct acpi_namespace_node *node,44 struct acpi_namespace_node *scope_node,45 u32 aml_length, u8 *aml_start)46{47 acpi_status status;48 union acpi_parse_object *op;49 struct acpi_walk_state *walk_state;50 51 ACPI_FUNCTION_TRACE_PTR(ds_execute_arguments, aml_start);52 53 /* Allocate a new parser op to be the root of the parsed tree */54 55 op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start);56 if (!op) {57 return_ACPI_STATUS(AE_NO_MEMORY);58 }59 60 /* Save the Node for use in acpi_ps_parse_aml */61 62 op->common.node = scope_node;63 64 /* Create and initialize a new parser state */65 66 walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);67 if (!walk_state) {68 status = AE_NO_MEMORY;69 goto cleanup;70 }71 72 status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,73 aml_length, NULL, ACPI_IMODE_LOAD_PASS1);74 if (ACPI_FAILURE(status)) {75 acpi_ds_delete_walk_state(walk_state);76 goto cleanup;77 }78 79 /* Mark this parse as a deferred opcode */80 81 walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP;82 walk_state->deferred_node = node;83 84 /* Pass1: Parse the entire declaration */85 86 status = acpi_ps_parse_aml(walk_state);87 if (ACPI_FAILURE(status)) {88 goto cleanup;89 }90 91 /* Get and init the Op created above */92 93 op->common.node = node;94 acpi_ps_delete_parse_tree(op);95 96 /* Evaluate the deferred arguments */97 98 op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP, aml_start);99 if (!op) {100 return_ACPI_STATUS(AE_NO_MEMORY);101 }102 103 op->common.node = scope_node;104 105 /* Create and initialize a new parser state */106 107 walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);108 if (!walk_state) {109 status = AE_NO_MEMORY;110 goto cleanup;111 }112 113 /* Execute the opcode and arguments */114 115 status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,116 aml_length, NULL, ACPI_IMODE_EXECUTE);117 if (ACPI_FAILURE(status)) {118 acpi_ds_delete_walk_state(walk_state);119 goto cleanup;120 }121 122 /* Mark this execution as a deferred opcode */123 124 walk_state->deferred_node = node;125 status = acpi_ps_parse_aml(walk_state);126 127cleanup:128 acpi_ps_delete_parse_tree(op);129 return_ACPI_STATUS(status);130}131 132/*******************************************************************************133 *134 * FUNCTION: acpi_ds_get_buffer_field_arguments135 *136 * PARAMETERS: obj_desc - A valid buffer_field object137 *138 * RETURN: Status.139 *140 * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late141 * evaluation of these field attributes.142 *143 ******************************************************************************/144 145acpi_status146acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)147{148 union acpi_operand_object *extra_desc;149 struct acpi_namespace_node *node;150 acpi_status status;151 152 ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc);153 154 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {155 return_ACPI_STATUS(AE_OK);156 }157 158 /* Get the AML pointer (method object) and buffer_field node */159 160 extra_desc = acpi_ns_get_secondary_object(obj_desc);161 node = obj_desc->buffer_field.node;162 163 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname164 (ACPI_TYPE_BUFFER_FIELD, node, NULL));165 166 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",167 acpi_ut_get_node_name(node)));168 169 /* Execute the AML code for the term_arg arguments */170 171 status = acpi_ds_execute_arguments(node, node->parent,172 extra_desc->extra.aml_length,173 extra_desc->extra.aml_start);174 return_ACPI_STATUS(status);175}176 177/*******************************************************************************178 *179 * FUNCTION: acpi_ds_get_bank_field_arguments180 *181 * PARAMETERS: obj_desc - A valid bank_field object182 *183 * RETURN: Status.184 *185 * DESCRIPTION: Get bank_field bank_value. This implements the late186 * evaluation of these field attributes.187 *188 ******************************************************************************/189 190acpi_status191acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)192{193 union acpi_operand_object *extra_desc;194 struct acpi_namespace_node *node;195 acpi_status status;196 197 ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc);198 199 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {200 return_ACPI_STATUS(AE_OK);201 }202 203 /* Get the AML pointer (method object) and bank_field node */204 205 extra_desc = acpi_ns_get_secondary_object(obj_desc);206 node = obj_desc->bank_field.node;207 208 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname209 (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL));210 211 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n",212 acpi_ut_get_node_name(node)));213 214 /* Execute the AML code for the term_arg arguments */215 216 status = acpi_ds_execute_arguments(node, node->parent,217 extra_desc->extra.aml_length,218 extra_desc->extra.aml_start);219 if (ACPI_FAILURE(status)) {220 return_ACPI_STATUS(status);221 }222 223 status = acpi_ut_add_address_range(obj_desc->region.space_id,224 obj_desc->region.address,225 obj_desc->region.length, node);226 return_ACPI_STATUS(status);227}228 229/*******************************************************************************230 *231 * FUNCTION: acpi_ds_get_buffer_arguments232 *233 * PARAMETERS: obj_desc - A valid Buffer object234 *235 * RETURN: Status.236 *237 * DESCRIPTION: Get Buffer length and initializer byte list. This implements238 * the late evaluation of these attributes.239 *240 ******************************************************************************/241 242acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)243{244 struct acpi_namespace_node *node;245 acpi_status status;246 247 ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc);248 249 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {250 return_ACPI_STATUS(AE_OK);251 }252 253 /* Get the Buffer node */254 255 node = obj_desc->buffer.node;256 if (!node) {257 ACPI_ERROR((AE_INFO,258 "No pointer back to namespace node in buffer object %p",259 obj_desc));260 return_ACPI_STATUS(AE_AML_INTERNAL);261 }262 263 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n"));264 265 /* Execute the AML code for the term_arg arguments */266 267 status = acpi_ds_execute_arguments(node, node,268 obj_desc->buffer.aml_length,269 obj_desc->buffer.aml_start);270 return_ACPI_STATUS(status);271}272 273/*******************************************************************************274 *275 * FUNCTION: acpi_ds_get_package_arguments276 *277 * PARAMETERS: obj_desc - A valid Package object278 *279 * RETURN: Status.280 *281 * DESCRIPTION: Get Package length and initializer byte list. This implements282 * the late evaluation of these attributes.283 *284 ******************************************************************************/285 286acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc)287{288 struct acpi_namespace_node *node;289 acpi_status status;290 291 ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc);292 293 if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {294 return_ACPI_STATUS(AE_OK);295 }296 297 /* Get the Package node */298 299 node = obj_desc->package.node;300 if (!node) {301 ACPI_ERROR((AE_INFO,302 "No pointer back to namespace node in package %p",303 obj_desc));304 return_ACPI_STATUS(AE_AML_INTERNAL);305 }306 307 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Argument Init, AML Ptr: %p\n",308 obj_desc->package.aml_start));309 310 /* Execute the AML code for the term_arg arguments */311 312 status = acpi_ds_execute_arguments(node, node,313 obj_desc->package.aml_length,314 obj_desc->package.aml_start);315 316 return_ACPI_STATUS(status);317}318 319/*******************************************************************************320 *321 * FUNCTION: acpi_ds_get_region_arguments322 *323 * PARAMETERS: obj_desc - A valid region object324 *325 * RETURN: Status.326 *327 * DESCRIPTION: Get region address and length. This implements the late328 * evaluation of these region attributes.329 *330 ******************************************************************************/331 332acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)333{334 struct acpi_namespace_node *node;335 acpi_status status;336 union acpi_operand_object *extra_desc;337 338 ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc);339 340 if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {341 return_ACPI_STATUS(AE_OK);342 }343 344 extra_desc = acpi_ns_get_secondary_object(obj_desc);345 if (!extra_desc) {346 return_ACPI_STATUS(AE_NOT_EXIST);347 }348 349 /* Get the Region node */350 351 node = obj_desc->region.node;352 353 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname354 (ACPI_TYPE_REGION, node, NULL));355 356 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,357 "[%4.4s] OpRegion Arg Init at AML %p\n",358 acpi_ut_get_node_name(node),359 extra_desc->extra.aml_start));360 361 /* Execute the argument AML */362 363 status = acpi_ds_execute_arguments(node, extra_desc->extra.scope_node,364 extra_desc->extra.aml_length,365 extra_desc->extra.aml_start);366 if (ACPI_FAILURE(status)) {367 return_ACPI_STATUS(status);368 }369 370 status = acpi_ut_add_address_range(obj_desc->region.space_id,371 obj_desc->region.address,372 obj_desc->region.length, node);373 return_ACPI_STATUS(status);374}375