1 /****************************************************************************** 2 * 3 * Module Name: exfldio - Aml Field I/O 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2010, 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 "acinterp.h" 47 #include "amlcode.h" 48 #include "acevents.h" 49 #include "acdispat.h" 50 51 #define _COMPONENT ACPI_EXECUTER 52 ACPI_MODULE_NAME("exfldio") 53 54 /* Local prototypes */ 55 static acpi_status 56 acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, 57 u32 field_datum_byte_offset, 58 u64 *value, u32 read_write); 59 60 static u8 61 acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value); 62 63 static acpi_status 64 acpi_ex_setup_region(union acpi_operand_object *obj_desc, 65 u32 field_datum_byte_offset); 66 67 /******************************************************************************* 68 * 69 * FUNCTION: acpi_ex_setup_region 70 * 71 * PARAMETERS: obj_desc - Field to be read or written 72 * field_datum_byte_offset - Byte offset of this datum within the 73 * parent field 74 * 75 * RETURN: Status 76 * 77 * DESCRIPTION: Common processing for acpi_ex_extract_from_field and 78 * acpi_ex_insert_into_field. Initialize the Region if necessary and 79 * validate the request. 80 * 81 ******************************************************************************/ 82 83 static acpi_status 84 acpi_ex_setup_region(union acpi_operand_object *obj_desc, 85 u32 field_datum_byte_offset) 86 { 87 acpi_status status = AE_OK; 88 union acpi_operand_object *rgn_desc; 89 90 ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset); 91 92 rgn_desc = obj_desc->common_field.region_obj; 93 94 /* We must have a valid region */ 95 96 if (rgn_desc->common.type != ACPI_TYPE_REGION) { 97 ACPI_ERROR((AE_INFO, "Needed Region, found type 0x%X (%s)", 98 rgn_desc->common.type, 99 acpi_ut_get_object_type_name(rgn_desc))); 100 101 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 102 } 103 104 /* 105 * If the Region Address and Length have not been previously evaluated, 106 * evaluate them now and save the results. 107 */ 108 if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) { 109 status = acpi_ds_get_region_arguments(rgn_desc); 110 if (ACPI_FAILURE(status)) { 111 return_ACPI_STATUS(status); 112 } 113 } 114 115 /* Exit if Address/Length have been disallowed by the host OS */ 116 117 if (rgn_desc->common.flags & AOPOBJ_INVALID) { 118 return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); 119 } 120 121 /* 122 * Exit now for SMBus or IPMI address space, it has a non-linear 123 * address space and the request cannot be directly validated 124 */ 125 if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS || 126 rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) { 127 128 /* SMBus or IPMI has a non-linear address space */ 129 130 return_ACPI_STATUS(AE_OK); 131 } 132 #ifdef ACPI_UNDER_DEVELOPMENT 133 /* 134 * If the Field access is any_acc, we can now compute the optimal 135 * access (because we know know the length of the parent region) 136 */ 137 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { 138 if (ACPI_FAILURE(status)) { 139 return_ACPI_STATUS(status); 140 } 141 } 142 #endif 143 144 /* 145 * Validate the request. The entire request from the byte offset for a 146 * length of one field datum (access width) must fit within the region. 147 * (Region length is specified in bytes) 148 */ 149 if (rgn_desc->region.length < 150 (obj_desc->common_field.base_byte_offset + field_datum_byte_offset + 151 obj_desc->common_field.access_byte_width)) { 152 if (acpi_gbl_enable_interpreter_slack) { 153 /* 154 * Slack mode only: We will go ahead and allow access to this 155 * field if it is within the region length rounded up to the next 156 * access width boundary. acpi_size cast for 64-bit compile. 157 */ 158 if (ACPI_ROUND_UP(rgn_desc->region.length, 159 obj_desc->common_field. 160 access_byte_width) >= 161 ((acpi_size) obj_desc->common_field. 162 base_byte_offset + 163 obj_desc->common_field.access_byte_width + 164 field_datum_byte_offset)) { 165 return_ACPI_STATUS(AE_OK); 166 } 167 } 168 169 if (rgn_desc->region.length < 170 obj_desc->common_field.access_byte_width) { 171 /* 172 * This is the case where the access_type (acc_word, etc.) is wider 173 * than the region itself. For example, a region of length one 174 * byte, and a field with Dword access specified. 175 */ 176 ACPI_ERROR((AE_INFO, 177 "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)", 178 acpi_ut_get_node_name(obj_desc-> 179 common_field.node), 180 obj_desc->common_field.access_byte_width, 181 acpi_ut_get_node_name(rgn_desc->region. 182 node), 183 rgn_desc->region.length)); 184 } 185 186 /* 187 * Offset rounded up to next multiple of field width 188 * exceeds region length, indicate an error 189 */ 190 ACPI_ERROR((AE_INFO, 191 "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)", 192 acpi_ut_get_node_name(obj_desc->common_field.node), 193 obj_desc->common_field.base_byte_offset, 194 field_datum_byte_offset, 195 obj_desc->common_field.access_byte_width, 196 acpi_ut_get_node_name(rgn_desc->region.node), 197 rgn_desc->region.length)); 198 199 return_ACPI_STATUS(AE_AML_REGION_LIMIT); 200 } 201 202 return_ACPI_STATUS(AE_OK); 203 } 204 205 /******************************************************************************* 206 * 207 * FUNCTION: acpi_ex_access_region 208 * 209 * PARAMETERS: obj_desc - Field to be read 210 * field_datum_byte_offset - Byte offset of this datum within the 211 * parent field 212 * Value - Where to store value (must at least 213 * 64 bits) 214 * Function - Read or Write flag plus other region- 215 * dependent flags 216 * 217 * RETURN: Status 218 * 219 * DESCRIPTION: Read or Write a single field datum to an Operation Region. 220 * 221 ******************************************************************************/ 222 223 acpi_status 224 acpi_ex_access_region(union acpi_operand_object *obj_desc, 225 u32 field_datum_byte_offset, u64 *value, u32 function) 226 { 227 acpi_status status; 228 union acpi_operand_object *rgn_desc; 229 u32 region_offset; 230 231 ACPI_FUNCTION_TRACE(ex_access_region); 232 233 /* 234 * Ensure that the region operands are fully evaluated and verify 235 * the validity of the request 236 */ 237 status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset); 238 if (ACPI_FAILURE(status)) { 239 return_ACPI_STATUS(status); 240 } 241 242 /* 243 * The physical address of this field datum is: 244 * 245 * 1) The base of the region, plus 246 * 2) The base offset of the field, plus 247 * 3) The current offset into the field 248 */ 249 rgn_desc = obj_desc->common_field.region_obj; 250 region_offset = 251 obj_desc->common_field.base_byte_offset + field_datum_byte_offset; 252 253 if ((function & ACPI_IO_MASK) == ACPI_READ) { 254 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]")); 255 } else { 256 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]")); 257 } 258 259 ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, 260 " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n", 261 acpi_ut_get_region_name(rgn_desc->region. 262 space_id), 263 rgn_desc->region.space_id, 264 obj_desc->common_field.access_byte_width, 265 obj_desc->common_field.base_byte_offset, 266 field_datum_byte_offset, ACPI_CAST_PTR(void, 267 (rgn_desc-> 268 region. 269 address + 270 region_offset)))); 271 272 /* Invoke the appropriate address_space/op_region handler */ 273 274 status = 275 acpi_ev_address_space_dispatch(rgn_desc, function, region_offset, 276 ACPI_MUL_8(obj_desc->common_field. 277 access_byte_width), 278 value); 279 280 if (ACPI_FAILURE(status)) { 281 if (status == AE_NOT_IMPLEMENTED) { 282 ACPI_ERROR((AE_INFO, 283 "Region %s(0x%X) not implemented", 284 acpi_ut_get_region_name(rgn_desc->region. 285 space_id), 286 rgn_desc->region.space_id)); 287 } else if (status == AE_NOT_EXIST) { 288 ACPI_ERROR((AE_INFO, 289 "Region %s(0x%X) has no handler", 290 acpi_ut_get_region_name(rgn_desc->region. 291 space_id), 292 rgn_desc->region.space_id)); 293 } 294 } 295 296 return_ACPI_STATUS(status); 297 } 298 299 /******************************************************************************* 300 * 301 * FUNCTION: acpi_ex_register_overflow 302 * 303 * PARAMETERS: obj_desc - Register(Field) to be written 304 * Value - Value to be stored 305 * 306 * RETURN: TRUE if value overflows the field, FALSE otherwise 307 * 308 * DESCRIPTION: Check if a value is out of range of the field being written. 309 * Used to check if the values written to Index and Bank registers 310 * are out of range. Normally, the value is simply truncated 311 * to fit the field, but this case is most likely a serious 312 * coding error in the ASL. 313 * 314 ******************************************************************************/ 315 316 static u8 317 acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value) 318 { 319 320 if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) { 321 /* 322 * The field is large enough to hold the maximum integer, so we can 323 * never overflow it. 324 */ 325 return (FALSE); 326 } 327 328 if (value >= ((u64) 1 << obj_desc->common_field.bit_length)) { 329 /* 330 * The Value is larger than the maximum value that can fit into 331 * the register. 332 */ 333 return (TRUE); 334 } 335 336 /* The Value will fit into the field with no truncation */ 337 338 return (FALSE); 339 } 340 341 /******************************************************************************* 342 * 343 * FUNCTION: acpi_ex_field_datum_io 344 * 345 * PARAMETERS: obj_desc - Field to be read 346 * field_datum_byte_offset - Byte offset of this datum within the 347 * parent field 348 * Value - Where to store value (must be 64 bits) 349 * read_write - Read or Write flag 350 * 351 * RETURN: Status 352 * 353 * DESCRIPTION: Read or Write a single datum of a field. The field_type is 354 * demultiplexed here to handle the different types of fields 355 * (buffer_field, region_field, index_field, bank_field) 356 * 357 ******************************************************************************/ 358 359 static acpi_status 360 acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, 361 u32 field_datum_byte_offset, u64 *value, u32 read_write) 362 { 363 acpi_status status; 364 u64 local_value; 365 366 ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset); 367 368 if (read_write == ACPI_READ) { 369 if (!value) { 370 local_value = 0; 371 372 /* To support reads without saving return value */ 373 value = &local_value; 374 } 375 376 /* Clear the entire return buffer first, [Very Important!] */ 377 378 *value = 0; 379 } 380 381 /* 382 * The four types of fields are: 383 * 384 * buffer_field - Read/write from/to a Buffer 385 * region_field - Read/write from/to a Operation Region. 386 * bank_field - Write to a Bank Register, then read/write from/to an 387 * operation_region 388 * index_field - Write to an Index Register, then read/write from/to a 389 * Data Register 390 */ 391 switch (obj_desc->common.type) { 392 case ACPI_TYPE_BUFFER_FIELD: 393 /* 394 * If the buffer_field arguments have not been previously evaluated, 395 * evaluate them now and save the results. 396 */ 397 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { 398 status = acpi_ds_get_buffer_field_arguments(obj_desc); 399 if (ACPI_FAILURE(status)) { 400 return_ACPI_STATUS(status); 401 } 402 } 403 404 if (read_write == ACPI_READ) { 405 /* 406 * Copy the data from the source buffer. 407 * Length is the field width in bytes. 408 */ 409 ACPI_MEMCPY(value, 410 (obj_desc->buffer_field.buffer_obj)->buffer. 411 pointer + 412 obj_desc->buffer_field.base_byte_offset + 413 field_datum_byte_offset, 414 obj_desc->common_field.access_byte_width); 415 } else { 416 /* 417 * Copy the data to the target buffer. 418 * Length is the field width in bytes. 419 */ 420 ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer. 421 pointer + 422 obj_desc->buffer_field.base_byte_offset + 423 field_datum_byte_offset, value, 424 obj_desc->common_field.access_byte_width); 425 } 426 427 status = AE_OK; 428 break; 429 430 case ACPI_TYPE_LOCAL_BANK_FIELD: 431 432 /* 433 * Ensure that the bank_value is not beyond the capacity of 434 * the register 435 */ 436 if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj, 437 (u64) obj_desc->bank_field. 438 value)) { 439 return_ACPI_STATUS(AE_AML_REGISTER_LIMIT); 440 } 441 442 /* 443 * For bank_fields, we must write the bank_value to the bank_register 444 * (itself a region_field) before we can access the data. 445 */ 446 status = 447 acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj, 448 &obj_desc->bank_field.value, 449 sizeof(obj_desc->bank_field. 450 value)); 451 if (ACPI_FAILURE(status)) { 452 return_ACPI_STATUS(status); 453 } 454 455 /* 456 * Now that the Bank has been selected, fall through to the 457 * region_field case and write the datum to the Operation Region 458 */ 459 460 /*lint -fallthrough */ 461 462 case ACPI_TYPE_LOCAL_REGION_FIELD: 463 /* 464 * For simple region_fields, we just directly access the owning 465 * Operation Region. 466 */ 467 status = 468 acpi_ex_access_region(obj_desc, field_datum_byte_offset, 469 value, read_write); 470 break; 471 472 case ACPI_TYPE_LOCAL_INDEX_FIELD: 473 474 /* 475 * Ensure that the index_value is not beyond the capacity of 476 * the register 477 */ 478 if (acpi_ex_register_overflow(obj_desc->index_field.index_obj, 479 (u64) obj_desc->index_field. 480 value)) { 481 return_ACPI_STATUS(AE_AML_REGISTER_LIMIT); 482 } 483 484 /* Write the index value to the index_register (itself a region_field) */ 485 486 field_datum_byte_offset += obj_desc->index_field.value; 487 488 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 489 "Write to Index Register: Value %8.8X\n", 490 field_datum_byte_offset)); 491 492 status = 493 acpi_ex_insert_into_field(obj_desc->index_field.index_obj, 494 &field_datum_byte_offset, 495 sizeof(field_datum_byte_offset)); 496 if (ACPI_FAILURE(status)) { 497 return_ACPI_STATUS(status); 498 } 499 500 if (read_write == ACPI_READ) { 501 502 /* Read the datum from the data_register */ 503 504 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 505 "Read from Data Register\n")); 506 507 status = 508 acpi_ex_extract_from_field(obj_desc->index_field. 509 data_obj, value, 510 sizeof(u64)); 511 } else { 512 /* Write the datum to the data_register */ 513 514 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 515 "Write to Data Register: Value %8.8X%8.8X\n", 516 ACPI_FORMAT_UINT64(*value))); 517 518 status = 519 acpi_ex_insert_into_field(obj_desc->index_field. 520 data_obj, value, 521 sizeof(u64)); 522 } 523 break; 524 525 default: 526 527 ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %u", 528 obj_desc->common.type)); 529 status = AE_AML_INTERNAL; 530 break; 531 } 532 533 if (ACPI_SUCCESS(status)) { 534 if (read_write == ACPI_READ) { 535 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 536 "Value Read %8.8X%8.8X, Width %u\n", 537 ACPI_FORMAT_UINT64(*value), 538 obj_desc->common_field. 539 access_byte_width)); 540 } else { 541 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 542 "Value Written %8.8X%8.8X, Width %u\n", 543 ACPI_FORMAT_UINT64(*value), 544 obj_desc->common_field. 545 access_byte_width)); 546 } 547 } 548 549 return_ACPI_STATUS(status); 550 } 551 552 /******************************************************************************* 553 * 554 * FUNCTION: acpi_ex_write_with_update_rule 555 * 556 * PARAMETERS: obj_desc - Field to be written 557 * Mask - bitmask within field datum 558 * field_value - Value to write 559 * field_datum_byte_offset - Offset of datum within field 560 * 561 * RETURN: Status 562 * 563 * DESCRIPTION: Apply the field update rule to a field write 564 * 565 ******************************************************************************/ 566 567 acpi_status 568 acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, 569 u64 mask, 570 u64 field_value, u32 field_datum_byte_offset) 571 { 572 acpi_status status = AE_OK; 573 u64 merged_value; 574 u64 current_value; 575 576 ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask); 577 578 /* Start with the new bits */ 579 580 merged_value = field_value; 581 582 /* If the mask is all ones, we don't need to worry about the update rule */ 583 584 if (mask != ACPI_UINT64_MAX) { 585 586 /* Decode the update rule */ 587 588 switch (obj_desc->common_field. 589 field_flags & AML_FIELD_UPDATE_RULE_MASK) { 590 case AML_FIELD_UPDATE_PRESERVE: 591 /* 592 * Check if update rule needs to be applied (not if mask is all 593 * ones) The left shift drops the bits we want to ignore. 594 */ 595 if ((~mask << (ACPI_MUL_8(sizeof(mask)) - 596 ACPI_MUL_8(obj_desc->common_field. 597 access_byte_width))) != 0) { 598 /* 599 * Read the current contents of the byte/word/dword containing 600 * the field, and merge with the new field value. 601 */ 602 status = 603 acpi_ex_field_datum_io(obj_desc, 604 field_datum_byte_offset, 605 ¤t_value, 606 ACPI_READ); 607 if (ACPI_FAILURE(status)) { 608 return_ACPI_STATUS(status); 609 } 610 611 merged_value |= (current_value & ~mask); 612 } 613 break; 614 615 case AML_FIELD_UPDATE_WRITE_AS_ONES: 616 617 /* Set positions outside the field to all ones */ 618 619 merged_value |= ~mask; 620 break; 621 622 case AML_FIELD_UPDATE_WRITE_AS_ZEROS: 623 624 /* Set positions outside the field to all zeros */ 625 626 merged_value &= mask; 627 break; 628 629 default: 630 631 ACPI_ERROR((AE_INFO, 632 "Unknown UpdateRule value: 0x%X", 633 (obj_desc->common_field. 634 field_flags & 635 AML_FIELD_UPDATE_RULE_MASK))); 636 return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 637 } 638 } 639 640 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 641 "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n", 642 ACPI_FORMAT_UINT64(mask), 643 field_datum_byte_offset, 644 obj_desc->common_field.access_byte_width, 645 ACPI_FORMAT_UINT64(field_value), 646 ACPI_FORMAT_UINT64(merged_value))); 647 648 /* Write the merged value */ 649 650 status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset, 651 &merged_value, ACPI_WRITE); 652 653 return_ACPI_STATUS(status); 654 } 655 656 /******************************************************************************* 657 * 658 * FUNCTION: acpi_ex_extract_from_field 659 * 660 * PARAMETERS: obj_desc - Field to be read 661 * Buffer - Where to store the field data 662 * buffer_length - Length of Buffer 663 * 664 * RETURN: Status 665 * 666 * DESCRIPTION: Retrieve the current value of the given field 667 * 668 ******************************************************************************/ 669 670 acpi_status 671 acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, 672 void *buffer, u32 buffer_length) 673 { 674 acpi_status status; 675 u64 raw_datum; 676 u64 merged_datum; 677 u32 field_offset = 0; 678 u32 buffer_offset = 0; 679 u32 buffer_tail_bits; 680 u32 datum_count; 681 u32 field_datum_count; 682 u32 access_bit_width; 683 u32 i; 684 685 ACPI_FUNCTION_TRACE(ex_extract_from_field); 686 687 /* Validate target buffer and clear it */ 688 689 if (buffer_length < 690 ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { 691 ACPI_ERROR((AE_INFO, 692 "Field size %u (bits) is too large for buffer (%u)", 693 obj_desc->common_field.bit_length, buffer_length)); 694 695 return_ACPI_STATUS(AE_BUFFER_OVERFLOW); 696 } 697 698 ACPI_MEMSET(buffer, 0, buffer_length); 699 access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width); 700 701 /* Handle the simple case here */ 702 703 if ((obj_desc->common_field.start_field_bit_offset == 0) && 704 (obj_desc->common_field.bit_length == access_bit_width)) { 705 status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ); 706 return_ACPI_STATUS(status); 707 } 708 709 /* TBD: Move to common setup code */ 710 711 /* Field algorithm is limited to sizeof(u64), truncate if needed */ 712 713 if (obj_desc->common_field.access_byte_width > sizeof(u64)) { 714 obj_desc->common_field.access_byte_width = sizeof(u64); 715 access_bit_width = sizeof(u64) * 8; 716 } 717 718 /* Compute the number of datums (access width data items) */ 719 720 datum_count = 721 ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, 722 access_bit_width); 723 724 field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + 725 obj_desc->common_field. 726 start_field_bit_offset, 727 access_bit_width); 728 729 /* Priming read from the field */ 730 731 status = 732 acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum, 733 ACPI_READ); 734 if (ACPI_FAILURE(status)) { 735 return_ACPI_STATUS(status); 736 } 737 merged_datum = 738 raw_datum >> obj_desc->common_field.start_field_bit_offset; 739 740 /* Read the rest of the field */ 741 742 for (i = 1; i < field_datum_count; i++) { 743 744 /* Get next input datum from the field */ 745 746 field_offset += obj_desc->common_field.access_byte_width; 747 status = acpi_ex_field_datum_io(obj_desc, field_offset, 748 &raw_datum, ACPI_READ); 749 if (ACPI_FAILURE(status)) { 750 return_ACPI_STATUS(status); 751 } 752 753 /* 754 * Merge with previous datum if necessary. 755 * 756 * Note: Before the shift, check if the shift value will be larger than 757 * the integer size. If so, there is no need to perform the operation. 758 * This avoids the differences in behavior between different compilers 759 * concerning shift values larger than the target data width. 760 */ 761 if (access_bit_width - 762 obj_desc->common_field.start_field_bit_offset < 763 ACPI_INTEGER_BIT_SIZE) { 764 merged_datum |= 765 raw_datum << (access_bit_width - 766 obj_desc->common_field. 767 start_field_bit_offset); 768 } 769 770 if (i == datum_count) { 771 break; 772 } 773 774 /* Write merged datum to target buffer */ 775 776 ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum, 777 ACPI_MIN(obj_desc->common_field.access_byte_width, 778 buffer_length - buffer_offset)); 779 780 buffer_offset += obj_desc->common_field.access_byte_width; 781 merged_datum = 782 raw_datum >> obj_desc->common_field.start_field_bit_offset; 783 } 784 785 /* Mask off any extra bits in the last datum */ 786 787 buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width; 788 if (buffer_tail_bits) { 789 merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); 790 } 791 792 /* Write the last datum to the buffer */ 793 794 ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum, 795 ACPI_MIN(obj_desc->common_field.access_byte_width, 796 buffer_length - buffer_offset)); 797 798 return_ACPI_STATUS(AE_OK); 799 } 800 801 /******************************************************************************* 802 * 803 * FUNCTION: acpi_ex_insert_into_field 804 * 805 * PARAMETERS: obj_desc - Field to be written 806 * Buffer - Data to be written 807 * buffer_length - Length of Buffer 808 * 809 * RETURN: Status 810 * 811 * DESCRIPTION: Store the Buffer contents into the given field 812 * 813 ******************************************************************************/ 814 815 acpi_status 816 acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, 817 void *buffer, u32 buffer_length) 818 { 819 void *new_buffer; 820 acpi_status status; 821 u64 mask; 822 u64 width_mask; 823 u64 merged_datum; 824 u64 raw_datum = 0; 825 u32 field_offset = 0; 826 u32 buffer_offset = 0; 827 u32 buffer_tail_bits; 828 u32 datum_count; 829 u32 field_datum_count; 830 u32 access_bit_width; 831 u32 required_length; 832 u32 i; 833 834 ACPI_FUNCTION_TRACE(ex_insert_into_field); 835 836 /* Validate input buffer */ 837 838 new_buffer = NULL; 839 required_length = 840 ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); 841 /* 842 * We must have a buffer that is at least as long as the field 843 * we are writing to. This is because individual fields are 844 * indivisible and partial writes are not supported -- as per 845 * the ACPI specification. 846 */ 847 if (buffer_length < required_length) { 848 849 /* We need to create a new buffer */ 850 851 new_buffer = ACPI_ALLOCATE_ZEROED(required_length); 852 if (!new_buffer) { 853 return_ACPI_STATUS(AE_NO_MEMORY); 854 } 855 856 /* 857 * Copy the original data to the new buffer, starting 858 * at Byte zero. All unused (upper) bytes of the 859 * buffer will be 0. 860 */ 861 ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length); 862 buffer = new_buffer; 863 buffer_length = required_length; 864 } 865 866 /* TBD: Move to common setup code */ 867 868 /* Algo is limited to sizeof(u64), so cut the access_byte_width */ 869 if (obj_desc->common_field.access_byte_width > sizeof(u64)) { 870 obj_desc->common_field.access_byte_width = sizeof(u64); 871 } 872 873 access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width); 874 875 /* 876 * Create the bitmasks used for bit insertion. 877 * Note: This if/else is used to bypass compiler differences with the 878 * shift operator 879 */ 880 if (access_bit_width == ACPI_INTEGER_BIT_SIZE) { 881 width_mask = ACPI_UINT64_MAX; 882 } else { 883 width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width); 884 } 885 886 mask = width_mask & 887 ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset); 888 889 /* Compute the number of datums (access width data items) */ 890 891 datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length, 892 access_bit_width); 893 894 field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length + 895 obj_desc->common_field. 896 start_field_bit_offset, 897 access_bit_width); 898 899 /* Get initial Datum from the input buffer */ 900 901 ACPI_MEMCPY(&raw_datum, buffer, 902 ACPI_MIN(obj_desc->common_field.access_byte_width, 903 buffer_length - buffer_offset)); 904 905 merged_datum = 906 raw_datum << obj_desc->common_field.start_field_bit_offset; 907 908 /* Write the entire field */ 909 910 for (i = 1; i < field_datum_count; i++) { 911 912 /* Write merged datum to the target field */ 913 914 merged_datum &= mask; 915 status = acpi_ex_write_with_update_rule(obj_desc, mask, 916 merged_datum, 917 field_offset); 918 if (ACPI_FAILURE(status)) { 919 goto exit; 920 } 921 922 field_offset += obj_desc->common_field.access_byte_width; 923 924 /* 925 * Start new output datum by merging with previous input datum 926 * if necessary. 927 * 928 * Note: Before the shift, check if the shift value will be larger than 929 * the integer size. If so, there is no need to perform the operation. 930 * This avoids the differences in behavior between different compilers 931 * concerning shift values larger than the target data width. 932 */ 933 if ((access_bit_width - 934 obj_desc->common_field.start_field_bit_offset) < 935 ACPI_INTEGER_BIT_SIZE) { 936 merged_datum = 937 raw_datum >> (access_bit_width - 938 obj_desc->common_field. 939 start_field_bit_offset); 940 } else { 941 merged_datum = 0; 942 } 943 944 mask = width_mask; 945 946 if (i == datum_count) { 947 break; 948 } 949 950 /* Get the next input datum from the buffer */ 951 952 buffer_offset += obj_desc->common_field.access_byte_width; 953 ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset, 954 ACPI_MIN(obj_desc->common_field.access_byte_width, 955 buffer_length - buffer_offset)); 956 957 merged_datum |= 958 raw_datum << obj_desc->common_field.start_field_bit_offset; 959 } 960 961 /* Mask off any extra bits in the last datum */ 962 963 buffer_tail_bits = (obj_desc->common_field.bit_length + 964 obj_desc->common_field.start_field_bit_offset) % 965 access_bit_width; 966 if (buffer_tail_bits) { 967 mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits); 968 } 969 970 /* Write the last datum to the field */ 971 972 merged_datum &= mask; 973 status = acpi_ex_write_with_update_rule(obj_desc, 974 mask, merged_datum, 975 field_offset); 976 977 exit: 978 /* Free temporary buffer if we used one */ 979 980 if (new_buffer) { 981 ACPI_FREE(new_buffer); 982 } 983 return_ACPI_STATUS(status); 984 } 985