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