| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 | 
|  | 2 | /****************************************************************************** | 
|  | 3 | * | 
|  | 4 | * Module Name: dsopcode - Dispatcher support for regions and fields | 
|  | 5 | * | 
|  | 6 | * Copyright (C) 2000 - 2018, Intel Corp. | 
|  | 7 | * | 
|  | 8 | *****************************************************************************/ | 
|  | 9 |  | 
|  | 10 | #include <acpi/acpi.h> | 
|  | 11 | #include "accommon.h" | 
|  | 12 | #include "acparser.h" | 
|  | 13 | #include "amlcode.h" | 
|  | 14 | #include "acdispat.h" | 
|  | 15 | #include "acinterp.h" | 
|  | 16 | #include "acnamesp.h" | 
|  | 17 | #include "acevents.h" | 
|  | 18 | #include "actables.h" | 
|  | 19 |  | 
|  | 20 | #define _COMPONENT          ACPI_DISPATCHER | 
|  | 21 | ACPI_MODULE_NAME("dsopcode") | 
|  | 22 |  | 
|  | 23 | /* Local prototypes */ | 
|  | 24 | static acpi_status | 
|  | 25 | acpi_ds_init_buffer_field(u16 aml_opcode, | 
|  | 26 | union acpi_operand_object *obj_desc, | 
|  | 27 | union acpi_operand_object *buffer_desc, | 
|  | 28 | union acpi_operand_object *offset_desc, | 
|  | 29 | union acpi_operand_object *length_desc, | 
|  | 30 | union acpi_operand_object *result_desc); | 
|  | 31 |  | 
|  | 32 | /******************************************************************************* | 
|  | 33 | * | 
|  | 34 | * FUNCTION:    acpi_ds_initialize_region | 
|  | 35 | * | 
|  | 36 | * PARAMETERS:  obj_handle      - Region namespace node | 
|  | 37 | * | 
|  | 38 | * RETURN:      Status | 
|  | 39 | * | 
|  | 40 | * DESCRIPTION: Front end to ev_initialize_region | 
|  | 41 | * | 
|  | 42 | ******************************************************************************/ | 
|  | 43 |  | 
|  | 44 | acpi_status acpi_ds_initialize_region(acpi_handle obj_handle) | 
|  | 45 | { | 
|  | 46 | union acpi_operand_object *obj_desc; | 
|  | 47 | acpi_status status; | 
|  | 48 |  | 
|  | 49 | obj_desc = acpi_ns_get_attached_object(obj_handle); | 
|  | 50 |  | 
|  | 51 | /* Namespace is NOT locked */ | 
|  | 52 |  | 
|  | 53 | status = acpi_ev_initialize_region(obj_desc); | 
|  | 54 | return (status); | 
|  | 55 | } | 
|  | 56 |  | 
|  | 57 | /******************************************************************************* | 
|  | 58 | * | 
|  | 59 | * FUNCTION:    acpi_ds_init_buffer_field | 
|  | 60 | * | 
|  | 61 | * PARAMETERS:  aml_opcode      - create_xxx_field | 
|  | 62 | *              obj_desc        - buffer_field object | 
|  | 63 | *              buffer_desc     - Host Buffer | 
|  | 64 | *              offset_desc     - Offset into buffer | 
|  | 65 | *              length_desc     - Length of field (CREATE_FIELD_OP only) | 
|  | 66 | *              result_desc     - Where to store the result | 
|  | 67 | * | 
|  | 68 | * RETURN:      Status | 
|  | 69 | * | 
|  | 70 | * DESCRIPTION: Perform actual initialization of a buffer field | 
|  | 71 | * | 
|  | 72 | ******************************************************************************/ | 
|  | 73 |  | 
|  | 74 | static acpi_status | 
|  | 75 | acpi_ds_init_buffer_field(u16 aml_opcode, | 
|  | 76 | union acpi_operand_object *obj_desc, | 
|  | 77 | union acpi_operand_object *buffer_desc, | 
|  | 78 | union acpi_operand_object *offset_desc, | 
|  | 79 | union acpi_operand_object *length_desc, | 
|  | 80 | union acpi_operand_object *result_desc) | 
|  | 81 | { | 
|  | 82 | u32 offset; | 
|  | 83 | u32 bit_offset; | 
|  | 84 | u32 bit_count; | 
|  | 85 | u8 field_flags; | 
|  | 86 | acpi_status status; | 
|  | 87 |  | 
|  | 88 | ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc); | 
|  | 89 |  | 
|  | 90 | /* Host object must be a Buffer */ | 
|  | 91 |  | 
|  | 92 | if (buffer_desc->common.type != ACPI_TYPE_BUFFER) { | 
|  | 93 | ACPI_ERROR((AE_INFO, | 
|  | 94 | "Target of Create Field is not a Buffer object - %s", | 
|  | 95 | acpi_ut_get_object_type_name(buffer_desc))); | 
|  | 96 |  | 
|  | 97 | status = AE_AML_OPERAND_TYPE; | 
|  | 98 | goto cleanup; | 
|  | 99 | } | 
|  | 100 |  | 
|  | 101 | /* | 
|  | 102 | * The last parameter to all of these opcodes (result_desc) started | 
|  | 103 | * out as a name_string, and should therefore now be a NS node | 
|  | 104 | * after resolution in acpi_ex_resolve_operands(). | 
|  | 105 | */ | 
|  | 106 | if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) { | 
|  | 107 | ACPI_ERROR((AE_INFO, | 
|  | 108 | "(%s) destination not a NS Node [%s]", | 
|  | 109 | acpi_ps_get_opcode_name(aml_opcode), | 
|  | 110 | acpi_ut_get_descriptor_name(result_desc))); | 
|  | 111 |  | 
|  | 112 | status = AE_AML_OPERAND_TYPE; | 
|  | 113 | goto cleanup; | 
|  | 114 | } | 
|  | 115 |  | 
|  | 116 | offset = (u32) offset_desc->integer.value; | 
|  | 117 |  | 
|  | 118 | /* | 
|  | 119 | * Setup the Bit offsets and counts, according to the opcode | 
|  | 120 | */ | 
|  | 121 | switch (aml_opcode) { | 
|  | 122 | case AML_CREATE_FIELD_OP: | 
|  | 123 |  | 
|  | 124 | /* Offset is in bits, count is in bits */ | 
|  | 125 |  | 
|  | 126 | field_flags = AML_FIELD_ACCESS_BYTE; | 
|  | 127 | bit_offset = offset; | 
|  | 128 | bit_count = (u32) length_desc->integer.value; | 
|  | 129 |  | 
|  | 130 | /* Must have a valid (>0) bit count */ | 
|  | 131 |  | 
|  | 132 | if (bit_count == 0) { | 
|  | 133 | ACPI_ERROR((AE_INFO, | 
|  | 134 | "Attempt to CreateField of length zero")); | 
|  | 135 | status = AE_AML_OPERAND_VALUE; | 
|  | 136 | goto cleanup; | 
|  | 137 | } | 
|  | 138 | break; | 
|  | 139 |  | 
|  | 140 | case AML_CREATE_BIT_FIELD_OP: | 
|  | 141 |  | 
|  | 142 | /* Offset is in bits, Field is one bit */ | 
|  | 143 |  | 
|  | 144 | bit_offset = offset; | 
|  | 145 | bit_count = 1; | 
|  | 146 | field_flags = AML_FIELD_ACCESS_BYTE; | 
|  | 147 | break; | 
|  | 148 |  | 
|  | 149 | case AML_CREATE_BYTE_FIELD_OP: | 
|  | 150 |  | 
|  | 151 | /* Offset is in bytes, field is one byte */ | 
|  | 152 |  | 
|  | 153 | bit_offset = 8 * offset; | 
|  | 154 | bit_count = 8; | 
|  | 155 | field_flags = AML_FIELD_ACCESS_BYTE; | 
|  | 156 | break; | 
|  | 157 |  | 
|  | 158 | case AML_CREATE_WORD_FIELD_OP: | 
|  | 159 |  | 
|  | 160 | /* Offset is in bytes, field is one word */ | 
|  | 161 |  | 
|  | 162 | bit_offset = 8 * offset; | 
|  | 163 | bit_count = 16; | 
|  | 164 | field_flags = AML_FIELD_ACCESS_WORD; | 
|  | 165 | break; | 
|  | 166 |  | 
|  | 167 | case AML_CREATE_DWORD_FIELD_OP: | 
|  | 168 |  | 
|  | 169 | /* Offset is in bytes, field is one dword */ | 
|  | 170 |  | 
|  | 171 | bit_offset = 8 * offset; | 
|  | 172 | bit_count = 32; | 
|  | 173 | field_flags = AML_FIELD_ACCESS_DWORD; | 
|  | 174 | break; | 
|  | 175 |  | 
|  | 176 | case AML_CREATE_QWORD_FIELD_OP: | 
|  | 177 |  | 
|  | 178 | /* Offset is in bytes, field is one qword */ | 
|  | 179 |  | 
|  | 180 | bit_offset = 8 * offset; | 
|  | 181 | bit_count = 64; | 
|  | 182 | field_flags = AML_FIELD_ACCESS_QWORD; | 
|  | 183 | break; | 
|  | 184 |  | 
|  | 185 | default: | 
|  | 186 |  | 
|  | 187 | ACPI_ERROR((AE_INFO, | 
|  | 188 | "Unknown field creation opcode 0x%02X", | 
|  | 189 | aml_opcode)); | 
|  | 190 | status = AE_AML_BAD_OPCODE; | 
|  | 191 | goto cleanup; | 
|  | 192 | } | 
|  | 193 |  | 
|  | 194 | /* Entire field must fit within the current length of the buffer */ | 
|  | 195 |  | 
|  | 196 | if ((bit_offset + bit_count) > (8 * (u32)buffer_desc->buffer.length)) { | 
|  | 197 | ACPI_ERROR((AE_INFO, | 
|  | 198 | "Field [%4.4s] at bit offset/length %u/%u " | 
|  | 199 | "exceeds size of target Buffer (%u bits)", | 
|  | 200 | acpi_ut_get_node_name(result_desc), bit_offset, | 
|  | 201 | bit_count, 8 * (u32)buffer_desc->buffer.length)); | 
|  | 202 | status = AE_AML_BUFFER_LIMIT; | 
|  | 203 | goto cleanup; | 
|  | 204 | } | 
|  | 205 |  | 
|  | 206 | /* | 
|  | 207 | * Initialize areas of the field object that are common to all fields | 
|  | 208 | * For field_flags, use LOCK_RULE = 0 (NO_LOCK), | 
|  | 209 | * UPDATE_RULE = 0 (UPDATE_PRESERVE) | 
|  | 210 | */ | 
|  | 211 | status = | 
|  | 212 | acpi_ex_prep_common_field_object(obj_desc, field_flags, 0, | 
|  | 213 | bit_offset, bit_count); | 
|  | 214 | if (ACPI_FAILURE(status)) { | 
|  | 215 | goto cleanup; | 
|  | 216 | } | 
|  | 217 |  | 
|  | 218 | obj_desc->buffer_field.buffer_obj = buffer_desc; | 
|  | 219 |  | 
|  | 220 | /* Reference count for buffer_desc inherits obj_desc count */ | 
|  | 221 |  | 
|  | 222 | buffer_desc->common.reference_count = (u16) | 
|  | 223 | (buffer_desc->common.reference_count + | 
|  | 224 | obj_desc->common.reference_count); | 
|  | 225 |  | 
|  | 226 | cleanup: | 
|  | 227 |  | 
|  | 228 | /* Always delete the operands */ | 
|  | 229 |  | 
|  | 230 | acpi_ut_remove_reference(offset_desc); | 
|  | 231 | acpi_ut_remove_reference(buffer_desc); | 
|  | 232 |  | 
|  | 233 | if (aml_opcode == AML_CREATE_FIELD_OP) { | 
|  | 234 | acpi_ut_remove_reference(length_desc); | 
|  | 235 | } | 
|  | 236 |  | 
|  | 237 | /* On failure, delete the result descriptor */ | 
|  | 238 |  | 
|  | 239 | if (ACPI_FAILURE(status)) { | 
|  | 240 | acpi_ut_remove_reference(result_desc);	/* Result descriptor */ | 
|  | 241 | } else { | 
|  | 242 | /* Now the address and length are valid for this buffer_field */ | 
|  | 243 |  | 
|  | 244 | obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; | 
|  | 245 | } | 
|  | 246 |  | 
|  | 247 | return_ACPI_STATUS(status); | 
|  | 248 | } | 
|  | 249 |  | 
|  | 250 | /******************************************************************************* | 
|  | 251 | * | 
|  | 252 | * FUNCTION:    acpi_ds_eval_buffer_field_operands | 
|  | 253 | * | 
|  | 254 | * PARAMETERS:  walk_state      - Current walk | 
|  | 255 | *              op              - A valid buffer_field Op object | 
|  | 256 | * | 
|  | 257 | * RETURN:      Status | 
|  | 258 | * | 
|  | 259 | * DESCRIPTION: Get buffer_field Buffer and Index | 
|  | 260 | *              Called from acpi_ds_exec_end_op during buffer_field parse tree walk | 
|  | 261 | * | 
|  | 262 | ******************************************************************************/ | 
|  | 263 |  | 
|  | 264 | acpi_status | 
|  | 265 | acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, | 
|  | 266 | union acpi_parse_object *op) | 
|  | 267 | { | 
|  | 268 | acpi_status status; | 
|  | 269 | union acpi_operand_object *obj_desc; | 
|  | 270 | struct acpi_namespace_node *node; | 
|  | 271 | union acpi_parse_object *next_op; | 
|  | 272 |  | 
|  | 273 | ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op); | 
|  | 274 |  | 
|  | 275 | /* | 
|  | 276 | * This is where we evaluate the address and length fields of the | 
|  | 277 | * create_xxx_field declaration | 
|  | 278 | */ | 
|  | 279 | node = op->common.node; | 
|  | 280 |  | 
|  | 281 | /* next_op points to the op that holds the Buffer */ | 
|  | 282 |  | 
|  | 283 | next_op = op->common.value.arg; | 
|  | 284 |  | 
|  | 285 | /* Evaluate/create the address and length operands */ | 
|  | 286 |  | 
|  | 287 | status = acpi_ds_create_operands(walk_state, next_op); | 
|  | 288 | if (ACPI_FAILURE(status)) { | 
|  | 289 | return_ACPI_STATUS(status); | 
|  | 290 | } | 
|  | 291 |  | 
|  | 292 | obj_desc = acpi_ns_get_attached_object(node); | 
|  | 293 | if (!obj_desc) { | 
|  | 294 | return_ACPI_STATUS(AE_NOT_EXIST); | 
|  | 295 | } | 
|  | 296 |  | 
|  | 297 | /* Resolve the operands */ | 
|  | 298 |  | 
|  | 299 | status = | 
|  | 300 | acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, | 
|  | 301 | walk_state); | 
|  | 302 | if (ACPI_FAILURE(status)) { | 
|  | 303 | ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X", | 
|  | 304 | acpi_ps_get_opcode_name(op->common.aml_opcode), | 
|  | 305 | status)); | 
|  | 306 |  | 
|  | 307 | return_ACPI_STATUS(status); | 
|  | 308 | } | 
|  | 309 |  | 
|  | 310 | /* Initialize the Buffer Field */ | 
|  | 311 |  | 
|  | 312 | if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { | 
|  | 313 |  | 
|  | 314 | /* NOTE: Slightly different operands for this opcode */ | 
|  | 315 |  | 
|  | 316 | status = | 
|  | 317 | acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, | 
|  | 318 | walk_state->operands[0], | 
|  | 319 | walk_state->operands[1], | 
|  | 320 | walk_state->operands[2], | 
|  | 321 | walk_state->operands[3]); | 
|  | 322 | } else { | 
|  | 323 | /* All other, create_xxx_field opcodes */ | 
|  | 324 |  | 
|  | 325 | status = | 
|  | 326 | acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, | 
|  | 327 | walk_state->operands[0], | 
|  | 328 | walk_state->operands[1], NULL, | 
|  | 329 | walk_state->operands[2]); | 
|  | 330 | } | 
|  | 331 |  | 
|  | 332 | return_ACPI_STATUS(status); | 
|  | 333 | } | 
|  | 334 |  | 
|  | 335 | /******************************************************************************* | 
|  | 336 | * | 
|  | 337 | * FUNCTION:    acpi_ds_eval_region_operands | 
|  | 338 | * | 
|  | 339 | * PARAMETERS:  walk_state      - Current walk | 
|  | 340 | *              op              - A valid region Op object | 
|  | 341 | * | 
|  | 342 | * RETURN:      Status | 
|  | 343 | * | 
|  | 344 | * DESCRIPTION: Get region address and length | 
|  | 345 | *              Called from acpi_ds_exec_end_op during op_region parse tree walk | 
|  | 346 | * | 
|  | 347 | ******************************************************************************/ | 
|  | 348 |  | 
|  | 349 | acpi_status | 
|  | 350 | acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, | 
|  | 351 | union acpi_parse_object *op) | 
|  | 352 | { | 
|  | 353 | acpi_status status; | 
|  | 354 | union acpi_operand_object *obj_desc; | 
|  | 355 | union acpi_operand_object *operand_desc; | 
|  | 356 | struct acpi_namespace_node *node; | 
|  | 357 | union acpi_parse_object *next_op; | 
|  | 358 |  | 
|  | 359 | ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op); | 
|  | 360 |  | 
|  | 361 | /* | 
|  | 362 | * This is where we evaluate the address and length fields of the | 
|  | 363 | * op_region declaration | 
|  | 364 | */ | 
|  | 365 | node = op->common.node; | 
|  | 366 |  | 
|  | 367 | /* next_op points to the op that holds the space_ID */ | 
|  | 368 |  | 
|  | 369 | next_op = op->common.value.arg; | 
|  | 370 |  | 
|  | 371 | /* next_op points to address op */ | 
|  | 372 |  | 
|  | 373 | next_op = next_op->common.next; | 
|  | 374 |  | 
|  | 375 | /* Evaluate/create the address and length operands */ | 
|  | 376 |  | 
|  | 377 | status = acpi_ds_create_operands(walk_state, next_op); | 
|  | 378 | if (ACPI_FAILURE(status)) { | 
|  | 379 | return_ACPI_STATUS(status); | 
|  | 380 | } | 
|  | 381 |  | 
|  | 382 | /* Resolve the length and address operands to numbers */ | 
|  | 383 |  | 
|  | 384 | status = | 
|  | 385 | acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, | 
|  | 386 | walk_state); | 
|  | 387 | if (ACPI_FAILURE(status)) { | 
|  | 388 | return_ACPI_STATUS(status); | 
|  | 389 | } | 
|  | 390 |  | 
|  | 391 | obj_desc = acpi_ns_get_attached_object(node); | 
|  | 392 | if (!obj_desc) { | 
|  | 393 | return_ACPI_STATUS(AE_NOT_EXIST); | 
|  | 394 | } | 
|  | 395 |  | 
|  | 396 | /* | 
|  | 397 | * Get the length operand and save it | 
|  | 398 | * (at Top of stack) | 
|  | 399 | */ | 
|  | 400 | operand_desc = walk_state->operands[walk_state->num_operands - 1]; | 
|  | 401 |  | 
|  | 402 | obj_desc->region.length = (u32) operand_desc->integer.value; | 
|  | 403 | acpi_ut_remove_reference(operand_desc); | 
|  | 404 |  | 
|  | 405 | /* | 
|  | 406 | * Get the address and save it | 
|  | 407 | * (at top of stack - 1) | 
|  | 408 | */ | 
|  | 409 | operand_desc = walk_state->operands[walk_state->num_operands - 2]; | 
|  | 410 |  | 
|  | 411 | obj_desc->region.address = (acpi_physical_address) | 
|  | 412 | operand_desc->integer.value; | 
|  | 413 | acpi_ut_remove_reference(operand_desc); | 
|  | 414 |  | 
|  | 415 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", | 
|  | 416 | obj_desc, | 
|  | 417 | ACPI_FORMAT_UINT64(obj_desc->region.address), | 
|  | 418 | obj_desc->region.length)); | 
|  | 419 |  | 
|  | 420 | status = acpi_ut_add_address_range(obj_desc->region.space_id, | 
|  | 421 | obj_desc->region.address, | 
|  | 422 | obj_desc->region.length, node); | 
|  | 423 |  | 
|  | 424 | /* Now the address and length are valid for this opregion */ | 
|  | 425 |  | 
|  | 426 | obj_desc->region.flags |= AOPOBJ_DATA_VALID; | 
|  | 427 | return_ACPI_STATUS(status); | 
|  | 428 | } | 
|  | 429 |  | 
|  | 430 | /******************************************************************************* | 
|  | 431 | * | 
|  | 432 | * FUNCTION:    acpi_ds_eval_table_region_operands | 
|  | 433 | * | 
|  | 434 | * PARAMETERS:  walk_state      - Current walk | 
|  | 435 | *              op              - A valid region Op object | 
|  | 436 | * | 
|  | 437 | * RETURN:      Status | 
|  | 438 | * | 
|  | 439 | * DESCRIPTION: Get region address and length. | 
|  | 440 | *              Called from acpi_ds_exec_end_op during data_table_region parse | 
|  | 441 | *              tree walk. | 
|  | 442 | * | 
|  | 443 | ******************************************************************************/ | 
|  | 444 |  | 
|  | 445 | acpi_status | 
|  | 446 | acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, | 
|  | 447 | union acpi_parse_object *op) | 
|  | 448 | { | 
|  | 449 | acpi_status status; | 
|  | 450 | union acpi_operand_object *obj_desc; | 
|  | 451 | union acpi_operand_object **operand; | 
|  | 452 | struct acpi_namespace_node *node; | 
|  | 453 | union acpi_parse_object *next_op; | 
|  | 454 | struct acpi_table_header *table; | 
|  | 455 | u32 table_index; | 
|  | 456 |  | 
|  | 457 | ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); | 
|  | 458 |  | 
|  | 459 | /* | 
|  | 460 | * This is where we evaluate the Signature string, oem_id string, | 
|  | 461 | * and oem_table_id string of the Data Table Region declaration | 
|  | 462 | */ | 
|  | 463 | node = op->common.node; | 
|  | 464 |  | 
|  | 465 | /* next_op points to Signature string op */ | 
|  | 466 |  | 
|  | 467 | next_op = op->common.value.arg; | 
|  | 468 |  | 
|  | 469 | /* | 
|  | 470 | * Evaluate/create the Signature string, oem_id string, | 
|  | 471 | * and oem_table_id string operands | 
|  | 472 | */ | 
|  | 473 | status = acpi_ds_create_operands(walk_state, next_op); | 
|  | 474 | if (ACPI_FAILURE(status)) { | 
|  | 475 | return_ACPI_STATUS(status); | 
|  | 476 | } | 
|  | 477 |  | 
|  | 478 | operand = &walk_state->operands[0]; | 
|  | 479 |  | 
|  | 480 | /* | 
|  | 481 | * Resolve the Signature string, oem_id string, | 
|  | 482 | * and oem_table_id string operands | 
|  | 483 | */ | 
|  | 484 | status = | 
|  | 485 | acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, | 
|  | 486 | walk_state); | 
|  | 487 | if (ACPI_FAILURE(status)) { | 
|  | 488 | goto cleanup; | 
|  | 489 | } | 
|  | 490 |  | 
|  | 491 | /* Find the ACPI table */ | 
|  | 492 |  | 
|  | 493 | status = acpi_tb_find_table(operand[0]->string.pointer, | 
|  | 494 | operand[1]->string.pointer, | 
|  | 495 | operand[2]->string.pointer, &table_index); | 
|  | 496 | if (ACPI_FAILURE(status)) { | 
|  | 497 | if (status == AE_NOT_FOUND) { | 
|  | 498 | ACPI_ERROR((AE_INFO, | 
|  | 499 | "ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT", | 
|  | 500 | operand[0]->string.pointer, | 
|  | 501 | operand[1]->string.pointer, | 
|  | 502 | operand[2]->string.pointer)); | 
|  | 503 | } | 
|  | 504 | goto cleanup; | 
|  | 505 | } | 
|  | 506 |  | 
|  | 507 | status = acpi_get_table_by_index(table_index, &table); | 
|  | 508 | if (ACPI_FAILURE(status)) { | 
|  | 509 | goto cleanup; | 
|  | 510 | } | 
|  | 511 |  | 
|  | 512 | obj_desc = acpi_ns_get_attached_object(node); | 
|  | 513 | if (!obj_desc) { | 
|  | 514 | status = AE_NOT_EXIST; | 
|  | 515 | goto cleanup; | 
|  | 516 | } | 
|  | 517 |  | 
|  | 518 | obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table); | 
|  | 519 | obj_desc->region.length = table->length; | 
|  | 520 |  | 
|  | 521 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", | 
|  | 522 | obj_desc, | 
|  | 523 | ACPI_FORMAT_UINT64(obj_desc->region.address), | 
|  | 524 | obj_desc->region.length)); | 
|  | 525 |  | 
|  | 526 | status = acpi_ut_add_address_range(obj_desc->region.space_id, | 
|  | 527 | obj_desc->region.address, | 
|  | 528 | obj_desc->region.length, node); | 
|  | 529 |  | 
|  | 530 | /* Now the address and length are valid for this opregion */ | 
|  | 531 |  | 
|  | 532 | obj_desc->region.flags |= AOPOBJ_DATA_VALID; | 
|  | 533 |  | 
|  | 534 | cleanup: | 
|  | 535 | acpi_ut_remove_reference(operand[0]); | 
|  | 536 | acpi_ut_remove_reference(operand[1]); | 
|  | 537 | acpi_ut_remove_reference(operand[2]); | 
|  | 538 |  | 
|  | 539 | return_ACPI_STATUS(status); | 
|  | 540 | } | 
|  | 541 |  | 
|  | 542 | /******************************************************************************* | 
|  | 543 | * | 
|  | 544 | * FUNCTION:    acpi_ds_eval_data_object_operands | 
|  | 545 | * | 
|  | 546 | * PARAMETERS:  walk_state      - Current walk | 
|  | 547 | *              op              - A valid data_object Op object | 
|  | 548 | *              obj_desc        - data_object | 
|  | 549 | * | 
|  | 550 | * RETURN:      Status | 
|  | 551 | * | 
|  | 552 | * DESCRIPTION: Get the operands and complete the following data object types: | 
|  | 553 | *              Buffer, Package. | 
|  | 554 | * | 
|  | 555 | ******************************************************************************/ | 
|  | 556 |  | 
|  | 557 | acpi_status | 
|  | 558 | acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, | 
|  | 559 | union acpi_parse_object *op, | 
|  | 560 | union acpi_operand_object *obj_desc) | 
|  | 561 | { | 
|  | 562 | acpi_status status; | 
|  | 563 | union acpi_operand_object *arg_desc; | 
|  | 564 | u32 length; | 
|  | 565 |  | 
|  | 566 | ACPI_FUNCTION_TRACE(ds_eval_data_object_operands); | 
|  | 567 |  | 
|  | 568 | /* The first operand (for all of these data objects) is the length */ | 
|  | 569 |  | 
|  | 570 | /* | 
|  | 571 | * Set proper index into operand stack for acpi_ds_obj_stack_push | 
|  | 572 | * invoked inside acpi_ds_create_operand. | 
|  | 573 | */ | 
|  | 574 | walk_state->operand_index = walk_state->num_operands; | 
|  | 575 |  | 
|  | 576 | /* Ignore if child is not valid */ | 
|  | 577 |  | 
|  | 578 | if (!op->common.value.arg) { | 
|  | 579 | ACPI_ERROR((AE_INFO, | 
|  | 580 | "Missing child while evaluating opcode %4.4X, Op %p", | 
|  | 581 | op->common.aml_opcode, op)); | 
|  | 582 | return_ACPI_STATUS(AE_OK); | 
|  | 583 | } | 
|  | 584 |  | 
|  | 585 | status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); | 
|  | 586 | if (ACPI_FAILURE(status)) { | 
|  | 587 | return_ACPI_STATUS(status); | 
|  | 588 | } | 
|  | 589 |  | 
|  | 590 | status = acpi_ex_resolve_operands(walk_state->opcode, | 
|  | 591 | &(walk_state-> | 
|  | 592 | operands[walk_state->num_operands - | 
|  | 593 | 1]), walk_state); | 
|  | 594 | if (ACPI_FAILURE(status)) { | 
|  | 595 | return_ACPI_STATUS(status); | 
|  | 596 | } | 
|  | 597 |  | 
|  | 598 | /* Extract length operand */ | 
|  | 599 |  | 
|  | 600 | arg_desc = walk_state->operands[walk_state->num_operands - 1]; | 
|  | 601 | length = (u32) arg_desc->integer.value; | 
|  | 602 |  | 
|  | 603 | /* Cleanup for length operand */ | 
|  | 604 |  | 
|  | 605 | status = acpi_ds_obj_stack_pop(1, walk_state); | 
|  | 606 | if (ACPI_FAILURE(status)) { | 
|  | 607 | return_ACPI_STATUS(status); | 
|  | 608 | } | 
|  | 609 |  | 
|  | 610 | acpi_ut_remove_reference(arg_desc); | 
|  | 611 |  | 
|  | 612 | /* | 
|  | 613 | * Create the actual data object | 
|  | 614 | */ | 
|  | 615 | switch (op->common.aml_opcode) { | 
|  | 616 | case AML_BUFFER_OP: | 
|  | 617 |  | 
|  | 618 | status = | 
|  | 619 | acpi_ds_build_internal_buffer_obj(walk_state, op, length, | 
|  | 620 | &obj_desc); | 
|  | 621 | break; | 
|  | 622 |  | 
|  | 623 | case AML_PACKAGE_OP: | 
|  | 624 | case AML_VARIABLE_PACKAGE_OP: | 
|  | 625 |  | 
|  | 626 | status = | 
|  | 627 | acpi_ds_build_internal_package_obj(walk_state, op, length, | 
|  | 628 | &obj_desc); | 
|  | 629 | break; | 
|  | 630 |  | 
|  | 631 | default: | 
|  | 632 |  | 
|  | 633 | return_ACPI_STATUS(AE_AML_BAD_OPCODE); | 
|  | 634 | } | 
|  | 635 |  | 
|  | 636 | if (ACPI_SUCCESS(status)) { | 
|  | 637 | /* | 
|  | 638 | * Return the object in the walk_state, unless the parent is a package - | 
|  | 639 | * in this case, the return object will be stored in the parse tree | 
|  | 640 | * for the package. | 
|  | 641 | */ | 
|  | 642 | if ((!op->common.parent) || | 
|  | 643 | ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && | 
|  | 644 | (op->common.parent->common.aml_opcode != | 
|  | 645 | AML_VARIABLE_PACKAGE_OP) | 
|  | 646 | && (op->common.parent->common.aml_opcode != | 
|  | 647 | AML_NAME_OP))) { | 
|  | 648 | walk_state->result_obj = obj_desc; | 
|  | 649 | } | 
|  | 650 | } | 
|  | 651 |  | 
|  | 652 | return_ACPI_STATUS(status); | 
|  | 653 | } | 
|  | 654 |  | 
|  | 655 | /******************************************************************************* | 
|  | 656 | * | 
|  | 657 | * FUNCTION:    acpi_ds_eval_bank_field_operands | 
|  | 658 | * | 
|  | 659 | * PARAMETERS:  walk_state      - Current walk | 
|  | 660 | *              op              - A valid bank_field Op object | 
|  | 661 | * | 
|  | 662 | * RETURN:      Status | 
|  | 663 | * | 
|  | 664 | * DESCRIPTION: Get bank_field bank_value | 
|  | 665 | *              Called from acpi_ds_exec_end_op during bank_field parse tree walk | 
|  | 666 | * | 
|  | 667 | ******************************************************************************/ | 
|  | 668 |  | 
|  | 669 | acpi_status | 
|  | 670 | acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, | 
|  | 671 | union acpi_parse_object *op) | 
|  | 672 | { | 
|  | 673 | acpi_status status; | 
|  | 674 | union acpi_operand_object *obj_desc; | 
|  | 675 | union acpi_operand_object *operand_desc; | 
|  | 676 | struct acpi_namespace_node *node; | 
|  | 677 | union acpi_parse_object *next_op; | 
|  | 678 | union acpi_parse_object *arg; | 
|  | 679 |  | 
|  | 680 | ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op); | 
|  | 681 |  | 
|  | 682 | /* | 
|  | 683 | * This is where we evaluate the bank_value field of the | 
|  | 684 | * bank_field declaration | 
|  | 685 | */ | 
|  | 686 |  | 
|  | 687 | /* next_op points to the op that holds the Region */ | 
|  | 688 |  | 
|  | 689 | next_op = op->common.value.arg; | 
|  | 690 |  | 
|  | 691 | /* next_op points to the op that holds the Bank Register */ | 
|  | 692 |  | 
|  | 693 | next_op = next_op->common.next; | 
|  | 694 |  | 
|  | 695 | /* next_op points to the op that holds the Bank Value */ | 
|  | 696 |  | 
|  | 697 | next_op = next_op->common.next; | 
|  | 698 |  | 
|  | 699 | /* | 
|  | 700 | * Set proper index into operand stack for acpi_ds_obj_stack_push | 
|  | 701 | * invoked inside acpi_ds_create_operand. | 
|  | 702 | * | 
|  | 703 | * We use walk_state->Operands[0] to store the evaluated bank_value | 
|  | 704 | */ | 
|  | 705 | walk_state->operand_index = 0; | 
|  | 706 |  | 
|  | 707 | status = acpi_ds_create_operand(walk_state, next_op, 0); | 
|  | 708 | if (ACPI_FAILURE(status)) { | 
|  | 709 | return_ACPI_STATUS(status); | 
|  | 710 | } | 
|  | 711 |  | 
|  | 712 | status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); | 
|  | 713 | if (ACPI_FAILURE(status)) { | 
|  | 714 | return_ACPI_STATUS(status); | 
|  | 715 | } | 
|  | 716 |  | 
|  | 717 | ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, | 
|  | 718 | acpi_ps_get_opcode_name(op->common.aml_opcode), 1); | 
|  | 719 | /* | 
|  | 720 | * Get the bank_value operand and save it | 
|  | 721 | * (at Top of stack) | 
|  | 722 | */ | 
|  | 723 | operand_desc = walk_state->operands[0]; | 
|  | 724 |  | 
|  | 725 | /* Arg points to the start Bank Field */ | 
|  | 726 |  | 
|  | 727 | arg = acpi_ps_get_arg(op, 4); | 
|  | 728 | while (arg) { | 
|  | 729 |  | 
|  | 730 | /* Ignore OFFSET and ACCESSAS terms here */ | 
|  | 731 |  | 
|  | 732 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { | 
|  | 733 | node = arg->common.node; | 
|  | 734 |  | 
|  | 735 | obj_desc = acpi_ns_get_attached_object(node); | 
|  | 736 | if (!obj_desc) { | 
|  | 737 | return_ACPI_STATUS(AE_NOT_EXIST); | 
|  | 738 | } | 
|  | 739 |  | 
|  | 740 | obj_desc->bank_field.value = | 
|  | 741 | (u32) operand_desc->integer.value; | 
|  | 742 | } | 
|  | 743 |  | 
|  | 744 | /* Move to next field in the list */ | 
|  | 745 |  | 
|  | 746 | arg = arg->common.next; | 
|  | 747 | } | 
|  | 748 |  | 
|  | 749 | acpi_ut_remove_reference(operand_desc); | 
|  | 750 | return_ACPI_STATUS(status); | 
|  | 751 | } |