1 /****************************************************************************** 2 * 3 * Module Name: dsfield - Dispatcher field routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2008, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <acpi/acpi.h> 45 #include "accommon.h" 46 #include "amlcode.h" 47 #include "acdispat.h" 48 #include "acinterp.h" 49 #include "acnamesp.h" 50 #include "acparser.h" 51 52 #define _COMPONENT ACPI_DISPATCHER 53 ACPI_MODULE_NAME("dsfield") 54 55 /* Local prototypes */ 56 static acpi_status 57 acpi_ds_get_field_names(struct acpi_create_field_info *info, 58 struct acpi_walk_state *walk_state, 59 union acpi_parse_object *arg); 60 61 /******************************************************************************* 62 * 63 * FUNCTION: acpi_ds_create_buffer_field 64 * 65 * PARAMETERS: Op - Current parse op (create_xXField) 66 * walk_state - Current state 67 * 68 * RETURN: Status 69 * 70 * DESCRIPTION: Execute the create_field operators: 71 * create_bit_field_op, 72 * create_byte_field_op, 73 * create_word_field_op, 74 * create_dword_field_op, 75 * create_qword_field_op, 76 * create_field_op (all of which define a field in a buffer) 77 * 78 ******************************************************************************/ 79 80 acpi_status 81 acpi_ds_create_buffer_field(union acpi_parse_object *op, 82 struct acpi_walk_state *walk_state) 83 { 84 union acpi_parse_object *arg; 85 struct acpi_namespace_node *node; 86 acpi_status status; 87 union acpi_operand_object *obj_desc; 88 union acpi_operand_object *second_desc = NULL; 89 u32 flags; 90 91 ACPI_FUNCTION_TRACE(ds_create_buffer_field); 92 93 /* 94 * Get the name_string argument (name of the new buffer_field) 95 */ 96 if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { 97 98 /* For create_field, name is the 4th argument */ 99 100 arg = acpi_ps_get_arg(op, 3); 101 } else { 102 /* For all other create_xXXField operators, name is the 3rd argument */ 103 104 arg = acpi_ps_get_arg(op, 2); 105 } 106 107 if (!arg) { 108 return_ACPI_STATUS(AE_AML_NO_OPERAND); 109 } 110 111 if (walk_state->deferred_node) { 112 node = walk_state->deferred_node; 113 status = AE_OK; 114 } else { 115 /* Execute flag should always be set when this function is entered */ 116 117 if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { 118 return_ACPI_STATUS(AE_AML_INTERNAL); 119 } 120 121 /* Creating new namespace node, should not already exist */ 122 123 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | 124 ACPI_NS_ERROR_IF_FOUND; 125 126 /* Mark node temporary if we are executing a method */ 127 128 if (walk_state->method_node) { 129 flags |= ACPI_NS_TEMPORARY; 130 } 131 132 /* Enter the name_string into the namespace */ 133 134 status = 135 acpi_ns_lookup(walk_state->scope_info, 136 arg->common.value.string, ACPI_TYPE_ANY, 137 ACPI_IMODE_LOAD_PASS1, flags, walk_state, 138 &node); 139 if (ACPI_FAILURE(status)) { 140 ACPI_ERROR_NAMESPACE(arg->common.value.string, status); 141 return_ACPI_STATUS(status); 142 } 143 } 144 145 /* 146 * We could put the returned object (Node) on the object stack for later, 147 * but for now, we will put it in the "op" object that the parser uses, 148 * so we can get it again at the end of this scope. 149 */ 150 op->common.node = node; 151 152 /* 153 * If there is no object attached to the node, this node was just created 154 * and we need to create the field object. Otherwise, this was a lookup 155 * of an existing node and we don't want to create the field object again. 156 */ 157 obj_desc = acpi_ns_get_attached_object(node); 158 if (obj_desc) { 159 return_ACPI_STATUS(AE_OK); 160 } 161 162 /* 163 * The Field definition is not fully parsed at this time. 164 * (We must save the address of the AML for the buffer and index operands) 165 */ 166 167 /* Create the buffer field object */ 168 169 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD); 170 if (!obj_desc) { 171 status = AE_NO_MEMORY; 172 goto cleanup; 173 } 174 175 /* 176 * Remember location in AML stream of the field unit opcode and operands -- 177 * since the buffer and index operands must be evaluated. 178 */ 179 second_desc = obj_desc->common.next_object; 180 second_desc->extra.aml_start = op->named.data; 181 second_desc->extra.aml_length = op->named.length; 182 obj_desc->buffer_field.node = node; 183 184 /* Attach constructed field descriptors to parent node */ 185 186 status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD); 187 if (ACPI_FAILURE(status)) { 188 goto cleanup; 189 } 190 191 cleanup: 192 193 /* Remove local reference to the object */ 194 195 acpi_ut_remove_reference(obj_desc); 196 return_ACPI_STATUS(status); 197 } 198 199 /******************************************************************************* 200 * 201 * FUNCTION: acpi_ds_get_field_names 202 * 203 * PARAMETERS: Info - create_field info structure 204 * ` walk_state - Current method state 205 * Arg - First parser arg for the field name list 206 * 207 * RETURN: Status 208 * 209 * DESCRIPTION: Process all named fields in a field declaration. Names are 210 * entered into the namespace. 211 * 212 ******************************************************************************/ 213 214 static acpi_status 215 acpi_ds_get_field_names(struct acpi_create_field_info *info, 216 struct acpi_walk_state *walk_state, 217 union acpi_parse_object *arg) 218 { 219 acpi_status status; 220 acpi_integer position; 221 222 ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); 223 224 /* First field starts at bit zero */ 225 226 info->field_bit_position = 0; 227 228 /* Process all elements in the field list (of parse nodes) */ 229 230 while (arg) { 231 /* 232 * Three types of field elements are handled: 233 * 1) Offset - specifies a bit offset 234 * 2) access_as - changes the access mode 235 * 3) Name - Enters a new named field into the namespace 236 */ 237 switch (arg->common.aml_opcode) { 238 case AML_INT_RESERVEDFIELD_OP: 239 240 position = (acpi_integer) info->field_bit_position 241 + (acpi_integer) arg->common.value.size; 242 243 if (position > ACPI_UINT32_MAX) { 244 ACPI_ERROR((AE_INFO, 245 "Bit offset within field too large (> 0xFFFFFFFF)")); 246 return_ACPI_STATUS(AE_SUPPORT); 247 } 248 249 info->field_bit_position = (u32) position; 250 break; 251 252 case AML_INT_ACCESSFIELD_OP: 253 254 /* 255 * Get a new access_type and access_attribute -- to be used for all 256 * field units that follow, until field end or another access_as 257 * keyword. 258 * 259 * In field_flags, preserve the flag bits other than the 260 * ACCESS_TYPE bits 261 */ 262 info->field_flags = (u8) 263 ((info-> 264 field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | 265 ((u8) ((u32) arg->common.value.integer >> 8))); 266 267 info->attribute = (u8) (arg->common.value.integer); 268 break; 269 270 case AML_INT_NAMEDFIELD_OP: 271 272 /* Lookup the name, it should already exist */ 273 274 status = acpi_ns_lookup(walk_state->scope_info, 275 (char *)&arg->named.name, 276 info->field_type, 277 ACPI_IMODE_EXECUTE, 278 ACPI_NS_DONT_OPEN_SCOPE, 279 walk_state, &info->field_node); 280 if (ACPI_FAILURE(status)) { 281 ACPI_ERROR_NAMESPACE((char *)&arg->named.name, 282 status); 283 return_ACPI_STATUS(status); 284 } else { 285 arg->common.node = info->field_node; 286 info->field_bit_length = arg->common.value.size; 287 288 /* 289 * If there is no object attached to the node, this node was 290 * just created and we need to create the field object. 291 * Otherwise, this was a lookup of an existing node and we 292 * don't want to create the field object again. 293 */ 294 if (!acpi_ns_get_attached_object 295 (info->field_node)) { 296 status = acpi_ex_prep_field_value(info); 297 if (ACPI_FAILURE(status)) { 298 return_ACPI_STATUS(status); 299 } 300 } 301 } 302 303 /* Keep track of bit position for the next field */ 304 305 position = (acpi_integer) info->field_bit_position 306 + (acpi_integer) arg->common.value.size; 307 308 if (position > ACPI_UINT32_MAX) { 309 ACPI_ERROR((AE_INFO, 310 "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)", 311 ACPI_CAST_PTR(char, 312 &info->field_node-> 313 name))); 314 return_ACPI_STATUS(AE_SUPPORT); 315 } 316 317 info->field_bit_position += info->field_bit_length; 318 break; 319 320 default: 321 322 ACPI_ERROR((AE_INFO, 323 "Invalid opcode in field list: %X", 324 arg->common.aml_opcode)); 325 return_ACPI_STATUS(AE_AML_BAD_OPCODE); 326 } 327 328 arg = arg->common.next; 329 } 330 331 return_ACPI_STATUS(AE_OK); 332 } 333 334 /******************************************************************************* 335 * 336 * FUNCTION: acpi_ds_create_field 337 * 338 * PARAMETERS: Op - Op containing the Field definition and args 339 * region_node - Object for the containing Operation Region 340 * ` walk_state - Current method state 341 * 342 * RETURN: Status 343 * 344 * DESCRIPTION: Create a new field in the specified operation region 345 * 346 ******************************************************************************/ 347 348 acpi_status 349 acpi_ds_create_field(union acpi_parse_object *op, 350 struct acpi_namespace_node *region_node, 351 struct acpi_walk_state *walk_state) 352 { 353 acpi_status status; 354 union acpi_parse_object *arg; 355 struct acpi_create_field_info info; 356 357 ACPI_FUNCTION_TRACE_PTR(ds_create_field, op); 358 359 /* First arg is the name of the parent op_region (must already exist) */ 360 361 arg = op->common.value.arg; 362 if (!region_node) { 363 status = 364 acpi_ns_lookup(walk_state->scope_info, 365 arg->common.value.name, ACPI_TYPE_REGION, 366 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 367 walk_state, ®ion_node); 368 if (ACPI_FAILURE(status)) { 369 ACPI_ERROR_NAMESPACE(arg->common.value.name, status); 370 return_ACPI_STATUS(status); 371 } 372 } 373 374 /* Second arg is the field flags */ 375 376 arg = arg->common.next; 377 info.field_flags = (u8) arg->common.value.integer; 378 info.attribute = 0; 379 380 /* Each remaining arg is a Named Field */ 381 382 info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD; 383 info.region_node = region_node; 384 385 status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); 386 387 return_ACPI_STATUS(status); 388 } 389 390 /******************************************************************************* 391 * 392 * FUNCTION: acpi_ds_init_field_objects 393 * 394 * PARAMETERS: Op - Op containing the Field definition and args 395 * ` walk_state - Current method state 396 * 397 * RETURN: Status 398 * 399 * DESCRIPTION: For each "Field Unit" name in the argument list that is 400 * part of the field declaration, enter the name into the 401 * namespace. 402 * 403 ******************************************************************************/ 404 405 acpi_status 406 acpi_ds_init_field_objects(union acpi_parse_object *op, 407 struct acpi_walk_state *walk_state) 408 { 409 acpi_status status; 410 union acpi_parse_object *arg = NULL; 411 struct acpi_namespace_node *node; 412 u8 type = 0; 413 u32 flags; 414 415 ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); 416 417 /* Execute flag should always be set when this function is entered */ 418 419 if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { 420 if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { 421 422 /* bank_field Op is deferred, just return OK */ 423 424 return_ACPI_STATUS(AE_OK); 425 } 426 427 return_ACPI_STATUS(AE_AML_INTERNAL); 428 } 429 430 /* 431 * Get the field_list argument for this opcode. This is the start of the 432 * list of field elements. 433 */ 434 switch (walk_state->opcode) { 435 case AML_FIELD_OP: 436 arg = acpi_ps_get_arg(op, 2); 437 type = ACPI_TYPE_LOCAL_REGION_FIELD; 438 break; 439 440 case AML_BANK_FIELD_OP: 441 arg = acpi_ps_get_arg(op, 4); 442 type = ACPI_TYPE_LOCAL_BANK_FIELD; 443 break; 444 445 case AML_INDEX_FIELD_OP: 446 arg = acpi_ps_get_arg(op, 3); 447 type = ACPI_TYPE_LOCAL_INDEX_FIELD; 448 break; 449 450 default: 451 return_ACPI_STATUS(AE_BAD_PARAMETER); 452 } 453 454 /* Creating new namespace node(s), should not already exist */ 455 456 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | 457 ACPI_NS_ERROR_IF_FOUND; 458 459 /* Mark node(s) temporary if we are executing a method */ 460 461 if (walk_state->method_node) { 462 flags |= ACPI_NS_TEMPORARY; 463 } 464 465 /* 466 * Walk the list of entries in the field_list 467 * Note: field_list can be of zero length. In this case, Arg will be NULL. 468 */ 469 while (arg) { 470 /* 471 * Ignore OFFSET and ACCESSAS terms here; we are only interested in the 472 * field names in order to enter them into the namespace. 473 */ 474 if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { 475 status = acpi_ns_lookup(walk_state->scope_info, 476 (char *)&arg->named.name, type, 477 ACPI_IMODE_LOAD_PASS1, flags, 478 walk_state, &node); 479 if (ACPI_FAILURE(status)) { 480 ACPI_ERROR_NAMESPACE((char *)&arg->named.name, 481 status); 482 if (status != AE_ALREADY_EXISTS) { 483 return_ACPI_STATUS(status); 484 } 485 486 /* Name already exists, just ignore this error */ 487 488 status = AE_OK; 489 } 490 491 arg->common.node = node; 492 } 493 494 /* Get the next field element in the list */ 495 496 arg = arg->common.next; 497 } 498 499 return_ACPI_STATUS(AE_OK); 500 } 501 502 /******************************************************************************* 503 * 504 * FUNCTION: acpi_ds_create_bank_field 505 * 506 * PARAMETERS: Op - Op containing the Field definition and args 507 * region_node - Object for the containing Operation Region 508 * walk_state - Current method state 509 * 510 * RETURN: Status 511 * 512 * DESCRIPTION: Create a new bank field in the specified operation region 513 * 514 ******************************************************************************/ 515 516 acpi_status 517 acpi_ds_create_bank_field(union acpi_parse_object *op, 518 struct acpi_namespace_node *region_node, 519 struct acpi_walk_state *walk_state) 520 { 521 acpi_status status; 522 union acpi_parse_object *arg; 523 struct acpi_create_field_info info; 524 525 ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op); 526 527 /* First arg is the name of the parent op_region (must already exist) */ 528 529 arg = op->common.value.arg; 530 if (!region_node) { 531 status = 532 acpi_ns_lookup(walk_state->scope_info, 533 arg->common.value.name, ACPI_TYPE_REGION, 534 ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, 535 walk_state, ®ion_node); 536 if (ACPI_FAILURE(status)) { 537 ACPI_ERROR_NAMESPACE(arg->common.value.name, status); 538 return_ACPI_STATUS(status); 539 } 540 } 541 542 /* Second arg is the Bank Register (Field) (must already exist) */ 543 544 arg = arg->common.next; 545 status = 546 acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, 547 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 548 ACPI_NS_SEARCH_PARENT, walk_state, 549 &info.register_node); 550 if (ACPI_FAILURE(status)) { 551 ACPI_ERROR_NAMESPACE(arg->common.value.string, status); 552 return_ACPI_STATUS(status); 553 } 554 555 /* 556 * Third arg is the bank_value 557 * This arg is a term_arg, not a constant 558 * It will be evaluated later, by acpi_ds_eval_bank_field_operands 559 */ 560 arg = arg->common.next; 561 562 /* Fourth arg is the field flags */ 563 564 arg = arg->common.next; 565 info.field_flags = (u8) arg->common.value.integer; 566 567 /* Each remaining arg is a Named Field */ 568 569 info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; 570 info.region_node = region_node; 571 572 /* 573 * Use Info.data_register_node to store bank_field Op 574 * It's safe because data_register_node will never be used when create bank field 575 * We store aml_start and aml_length in the bank_field Op for late evaluation 576 * Used in acpi_ex_prep_field_value(Info) 577 * 578 * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"? 579 */ 580 info.data_register_node = (struct acpi_namespace_node *)op; 581 582 status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); 583 return_ACPI_STATUS(status); 584 } 585 586 /******************************************************************************* 587 * 588 * FUNCTION: acpi_ds_create_index_field 589 * 590 * PARAMETERS: Op - Op containing the Field definition and args 591 * region_node - Object for the containing Operation Region 592 * ` walk_state - Current method state 593 * 594 * RETURN: Status 595 * 596 * DESCRIPTION: Create a new index field in the specified operation region 597 * 598 ******************************************************************************/ 599 600 acpi_status 601 acpi_ds_create_index_field(union acpi_parse_object *op, 602 struct acpi_namespace_node *region_node, 603 struct acpi_walk_state *walk_state) 604 { 605 acpi_status status; 606 union acpi_parse_object *arg; 607 struct acpi_create_field_info info; 608 609 ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op); 610 611 /* First arg is the name of the Index register (must already exist) */ 612 613 arg = op->common.value.arg; 614 status = 615 acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, 616 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 617 ACPI_NS_SEARCH_PARENT, walk_state, 618 &info.register_node); 619 if (ACPI_FAILURE(status)) { 620 ACPI_ERROR_NAMESPACE(arg->common.value.string, status); 621 return_ACPI_STATUS(status); 622 } 623 624 /* Second arg is the data register (must already exist) */ 625 626 arg = arg->common.next; 627 status = 628 acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, 629 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 630 ACPI_NS_SEARCH_PARENT, walk_state, 631 &info.data_register_node); 632 if (ACPI_FAILURE(status)) { 633 ACPI_ERROR_NAMESPACE(arg->common.value.string, status); 634 return_ACPI_STATUS(status); 635 } 636 637 /* Next arg is the field flags */ 638 639 arg = arg->common.next; 640 info.field_flags = (u8) arg->common.value.integer; 641 642 /* Each remaining arg is a Named Field */ 643 644 info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD; 645 info.region_node = region_node; 646 647 status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); 648 649 return_ACPI_STATUS(status); 650 } 651