1/****************************************************************************** 2 * 3 * Module Name: exfldio - Aml Field I/O 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2015, 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 52ACPI_MODULE_NAME("exfldio") 53 54/* Local prototypes */ 55static acpi_status 56acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, 57 u32 field_datum_byte_offset, u64 *value, u32 read_write); 58 59static u8 60acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value); 61 62static acpi_status 63acpi_ex_setup_region(union acpi_operand_object *obj_desc, 64 u32 field_datum_byte_offset); 65 66/******************************************************************************* 67 * 68 * FUNCTION: acpi_ex_setup_region 69 * 70 * PARAMETERS: obj_desc - Field to be read or written 71 * field_datum_byte_offset - Byte offset of this datum within the 72 * parent field 73 * 74 * RETURN: Status 75 * 76 * DESCRIPTION: Common processing for acpi_ex_extract_from_field and 77 * acpi_ex_insert_into_field. Initialize the Region if necessary and 78 * validate the request. 79 * 80 ******************************************************************************/ 81 82static acpi_status 83acpi_ex_setup_region(union acpi_operand_object *obj_desc, 84 u32 field_datum_byte_offset) 85{ 86 acpi_status status = AE_OK; 87 union acpi_operand_object *rgn_desc; 88 u8 space_id; 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 space_id = rgn_desc->region.space_id; 105 106 /* Validate the Space ID */ 107 108 if (!acpi_is_valid_space_id(space_id)) { 109 ACPI_ERROR((AE_INFO, 110 "Invalid/unknown Address Space ID: 0x%2.2X", 111 space_id)); 112 return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); 113 } 114 115 /* 116 * If the Region Address and Length have not been previously evaluated, 117 * evaluate them now and save the results. 118 */ 119 if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) { 120 status = acpi_ds_get_region_arguments(rgn_desc); 121 if (ACPI_FAILURE(status)) { 122 return_ACPI_STATUS(status); 123 } 124 } 125 126 /* 127 * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear 128 * address space and the request cannot be directly validated 129 */ 130 if (space_id == ACPI_ADR_SPACE_SMBUS || 131 space_id == ACPI_ADR_SPACE_GSBUS || 132 space_id == ACPI_ADR_SPACE_IPMI) { 133 134 /* SMBus or IPMI has a non-linear address space */ 135 136 return_ACPI_STATUS(AE_OK); 137 } 138#ifdef ACPI_UNDER_DEVELOPMENT 139 /* 140 * If the Field access is any_acc, we can now compute the optimal 141 * access (because we know know the length of the parent region) 142 */ 143 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { 144 if (ACPI_FAILURE(status)) { 145 return_ACPI_STATUS(status); 146 } 147 } 148#endif 149 150 /* 151 * Validate the request. The entire request from the byte offset for a 152 * length of one field datum (access width) must fit within the region. 153 * (Region length is specified in bytes) 154 */ 155 if (rgn_desc->region.length < 156 (obj_desc->common_field.base_byte_offset + field_datum_byte_offset + 157 obj_desc->common_field.access_byte_width)) { 158 if (acpi_gbl_enable_interpreter_slack) { 159 /* 160 * Slack mode only: We will go ahead and allow access to this 161 * field if it is within the region length rounded up to the next 162 * access width boundary. acpi_size cast for 64-bit compile. 163 */ 164 if (ACPI_ROUND_UP(rgn_desc->region.length, 165 obj_desc->common_field. 166 access_byte_width) >= 167 ((acpi_size) obj_desc->common_field. 168 base_byte_offset + 169 obj_desc->common_field.access_byte_width + 170 field_datum_byte_offset)) { 171 return_ACPI_STATUS(AE_OK); 172 } 173 } 174 175 if (rgn_desc->region.length < 176 obj_desc->common_field.access_byte_width) { 177 /* 178 * This is the case where the access_type (acc_word, etc.) is wider 179 * than the region itself. For example, a region of length one 180 * byte, and a field with Dword access specified. 181 */ 182 ACPI_ERROR((AE_INFO, 183 "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)", 184 acpi_ut_get_node_name(obj_desc-> 185 common_field.node), 186 obj_desc->common_field.access_byte_width, 187 acpi_ut_get_node_name(rgn_desc->region. 188 node), 189 rgn_desc->region.length)); 190 } 191 192 /* 193 * Offset rounded up to next multiple of field width 194 * exceeds region length, indicate an error 195 */ 196 ACPI_ERROR((AE_INFO, 197 "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)", 198 acpi_ut_get_node_name(obj_desc->common_field.node), 199 obj_desc->common_field.base_byte_offset, 200 field_datum_byte_offset, 201 obj_desc->common_field.access_byte_width, 202 acpi_ut_get_node_name(rgn_desc->region.node), 203 rgn_desc->region.length)); 204 205 return_ACPI_STATUS(AE_AML_REGION_LIMIT); 206 } 207 208 return_ACPI_STATUS(AE_OK); 209} 210 211/******************************************************************************* 212 * 213 * FUNCTION: acpi_ex_access_region 214 * 215 * PARAMETERS: obj_desc - Field to be read 216 * field_datum_byte_offset - Byte offset of this datum within the 217 * parent field 218 * value - Where to store value (must at least 219 * 64 bits) 220 * function - Read or Write flag plus other region- 221 * dependent flags 222 * 223 * RETURN: Status 224 * 225 * DESCRIPTION: Read or Write a single field datum to an Operation Region. 226 * 227 ******************************************************************************/ 228 229acpi_status 230acpi_ex_access_region(union acpi_operand_object *obj_desc, 231 u32 field_datum_byte_offset, u64 *value, u32 function) 232{ 233 acpi_status status; 234 union acpi_operand_object *rgn_desc; 235 u32 region_offset; 236 237 ACPI_FUNCTION_TRACE(ex_access_region); 238 239 /* 240 * Ensure that the region operands are fully evaluated and verify 241 * the validity of the request 242 */ 243 status = acpi_ex_setup_region(obj_desc, field_datum_byte_offset); 244 if (ACPI_FAILURE(status)) { 245 return_ACPI_STATUS(status); 246 } 247 248 /* 249 * The physical address of this field datum is: 250 * 251 * 1) The base of the region, plus 252 * 2) The base offset of the field, plus 253 * 3) The current offset into the field 254 */ 255 rgn_desc = obj_desc->common_field.region_obj; 256 region_offset = 257 obj_desc->common_field.base_byte_offset + field_datum_byte_offset; 258 259 if ((function & ACPI_IO_MASK) == ACPI_READ) { 260 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[READ]")); 261 } else { 262 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "[WRITE]")); 263 } 264 265 ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, 266 " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n", 267 acpi_ut_get_region_name(rgn_desc->region. 268 space_id), 269 rgn_desc->region.space_id, 270 obj_desc->common_field.access_byte_width, 271 obj_desc->common_field.base_byte_offset, 272 field_datum_byte_offset, 273 ACPI_FORMAT_UINT64(rgn_desc->region.address + 274 region_offset))); 275 276 /* Invoke the appropriate address_space/op_region handler */ 277 278 status = acpi_ev_address_space_dispatch(rgn_desc, obj_desc, 279 function, region_offset, 280 ACPI_MUL_8(obj_desc-> 281 common_field. 282 access_byte_width), 283 value); 284 285 if (ACPI_FAILURE(status)) { 286 if (status == AE_NOT_IMPLEMENTED) { 287 ACPI_ERROR((AE_INFO, 288 "Region %s (ID=%u) not implemented", 289 acpi_ut_get_region_name(rgn_desc->region. 290 space_id), 291 rgn_desc->region.space_id)); 292 } else if (status == AE_NOT_EXIST) { 293 ACPI_ERROR((AE_INFO, 294 "Region %s (ID=%u) has no handler", 295 acpi_ut_get_region_name(rgn_desc->region. 296 space_id), 297 rgn_desc->region.space_id)); 298 } 299 } 300 301 return_ACPI_STATUS(status); 302} 303 304/******************************************************************************* 305 * 306 * FUNCTION: acpi_ex_register_overflow 307 * 308 * PARAMETERS: obj_desc - Register(Field) to be written 309 * value - Value to be stored 310 * 311 * RETURN: TRUE if value overflows the field, FALSE otherwise 312 * 313 * DESCRIPTION: Check if a value is out of range of the field being written. 314 * Used to check if the values written to Index and Bank registers 315 * are out of range. Normally, the value is simply truncated 316 * to fit the field, but this case is most likely a serious 317 * coding error in the ASL. 318 * 319 ******************************************************************************/ 320 321static u8 322acpi_ex_register_overflow(union acpi_operand_object *obj_desc, u64 value) 323{ 324 325 if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) { 326 /* 327 * The field is large enough to hold the maximum integer, so we can 328 * never overflow it. 329 */ 330 return (FALSE); 331 } 332 333 if (value >= ((u64) 1 << obj_desc->common_field.bit_length)) { 334 /* 335 * The Value is larger than the maximum value that can fit into 336 * the register. 337 */ 338 ACPI_ERROR((AE_INFO, 339 "Index value 0x%8.8X%8.8X overflows field width 0x%X", 340 ACPI_FORMAT_UINT64(value), 341 obj_desc->common_field.bit_length)); 342 343 return (TRUE); 344 } 345 346 /* The Value will fit into the field with no truncation */ 347 348 return (FALSE); 349} 350 351/******************************************************************************* 352 * 353 * FUNCTION: acpi_ex_field_datum_io 354 * 355 * PARAMETERS: obj_desc - Field to be read 356 * field_datum_byte_offset - Byte offset of this datum within the 357 * parent field 358 * value - Where to store value (must be 64 bits) 359 * read_write - Read or Write flag 360 * 361 * RETURN: Status 362 * 363 * DESCRIPTION: Read or Write a single datum of a field. The field_type is 364 * demultiplexed here to handle the different types of fields 365 * (buffer_field, region_field, index_field, bank_field) 366 * 367 ******************************************************************************/ 368 369static acpi_status 370acpi_ex_field_datum_io(union acpi_operand_object *obj_desc, 371 u32 field_datum_byte_offset, u64 *value, u32 read_write) 372{ 373 acpi_status status; 374 u64 local_value; 375 376 ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset); 377 378 if (read_write == ACPI_READ) { 379 if (!value) { 380 local_value = 0; 381 382 /* To support reads without saving return value */ 383 value = &local_value; 384 } 385 386 /* Clear the entire return buffer first, [Very Important!] */ 387 388 *value = 0; 389 } 390 391 /* 392 * The four types of fields are: 393 * 394 * buffer_field - Read/write from/to a Buffer 395 * region_field - Read/write from/to a Operation Region. 396 * bank_field - Write to a Bank Register, then read/write from/to an 397 * operation_region 398 * index_field - Write to an Index Register, then read/write from/to a 399 * Data Register 400 */ 401 switch (obj_desc->common.type) { 402 case ACPI_TYPE_BUFFER_FIELD: 403 /* 404 * If the buffer_field arguments have not been previously evaluated, 405 * evaluate them now and save the results. 406 */ 407 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { 408 status = acpi_ds_get_buffer_field_arguments(obj_desc); 409 if (ACPI_FAILURE(status)) { 410 return_ACPI_STATUS(status); 411 } 412 } 413 414 if (read_write == ACPI_READ) { 415 /* 416 * Copy the data from the source buffer. 417 * Length is the field width in bytes. 418 */ 419 ACPI_MEMCPY(value, 420 (obj_desc->buffer_field.buffer_obj)->buffer. 421 pointer + 422 obj_desc->buffer_field.base_byte_offset + 423 field_datum_byte_offset, 424 obj_desc->common_field.access_byte_width); 425 } else { 426 /* 427 * Copy the data to the target buffer. 428 * Length is the field width in bytes. 429 */ 430 ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer. 431 pointer + 432 obj_desc->buffer_field.base_byte_offset + 433 field_datum_byte_offset, value, 434 obj_desc->common_field.access_byte_width); 435 } 436 437 status = AE_OK; 438 break; 439 440 case ACPI_TYPE_LOCAL_BANK_FIELD: 441 /* 442 * Ensure that the bank_value is not beyond the capacity of 443 * the register 444 */ 445 if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj, 446 (u64) obj_desc->bank_field. 447 value)) { 448 return_ACPI_STATUS(AE_AML_REGISTER_LIMIT); 449 } 450 451 /* 452 * For bank_fields, we must write the bank_value to the bank_register 453 * (itself a region_field) before we can access the data. 454 */ 455 status = 456 acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj, 457 &obj_desc->bank_field.value, 458 sizeof(obj_desc->bank_field. 459 value)); 460 if (ACPI_FAILURE(status)) { 461 return_ACPI_STATUS(status); 462 } 463 464 /* 465 * Now that the Bank has been selected, fall through to the 466 * region_field case and write the datum to the Operation Region 467 */ 468 469 /*lint -fallthrough */ 470 471 case ACPI_TYPE_LOCAL_REGION_FIELD: 472 /* 473 * For simple region_fields, we just directly access the owning 474 * Operation Region. 475 */ 476 status = 477 acpi_ex_access_region(obj_desc, field_datum_byte_offset, 478 value, read_write); 479 break; 480 481 case ACPI_TYPE_LOCAL_INDEX_FIELD: 482 /* 483 * Ensure that the index_value is not beyond the capacity of 484 * the register 485 */ 486 if (acpi_ex_register_overflow(obj_desc->index_field.index_obj, 487 (u64) obj_desc->index_field. 488 value)) { 489 return_ACPI_STATUS(AE_AML_REGISTER_LIMIT); 490 } 491 492 /* Write the index value to the index_register (itself a region_field) */ 493 494 field_datum_byte_offset += obj_desc->index_field.value; 495 496 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 497 "Write to Index Register: Value %8.8X\n", 498 field_datum_byte_offset)); 499 500 status = 501 acpi_ex_insert_into_field(obj_desc->index_field.index_obj, 502 &field_datum_byte_offset, 503 sizeof(field_datum_byte_offset)); 504 if (ACPI_FAILURE(status)) { 505 return_ACPI_STATUS(status); 506 } 507 508 if (read_write == ACPI_READ) { 509 510 /* Read the datum from the data_register */ 511 512 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 513 "Read from Data Register\n")); 514 515 status = 516 acpi_ex_extract_from_field(obj_desc->index_field. 517 data_obj, value, 518 sizeof(u64)); 519 } else { 520 /* Write the datum to the data_register */ 521 522 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 523 "Write to Data Register: Value %8.8X%8.8X\n", 524 ACPI_FORMAT_UINT64(*value))); 525 526 status = 527 acpi_ex_insert_into_field(obj_desc->index_field. 528 data_obj, value, 529 sizeof(u64)); 530 } 531 break; 532 533 default: 534 535 ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %u", 536 obj_desc->common.type)); 537 status = AE_AML_INTERNAL; 538 break; 539 } 540 541 if (ACPI_SUCCESS(status)) { 542 if (read_write == ACPI_READ) { 543 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 544 "Value Read %8.8X%8.8X, Width %u\n", 545 ACPI_FORMAT_UINT64(*value), 546 obj_desc->common_field. 547 access_byte_width)); 548 } else { 549 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 550 "Value Written %8.8X%8.8X, Width %u\n", 551 ACPI_FORMAT_UINT64(*value), 552 obj_desc->common_field. 553 access_byte_width)); 554 } 555 } 556 557 return_ACPI_STATUS(status); 558} 559 560/******************************************************************************* 561 * 562 * FUNCTION: acpi_ex_write_with_update_rule 563 * 564 * PARAMETERS: obj_desc - Field to be written 565 * mask - bitmask within field datum 566 * field_value - Value to write 567 * field_datum_byte_offset - Offset of datum within field 568 * 569 * RETURN: Status 570 * 571 * DESCRIPTION: Apply the field update rule to a field write 572 * 573 ******************************************************************************/ 574 575acpi_status 576acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, 577 u64 mask, 578 u64 field_value, u32 field_datum_byte_offset) 579{ 580 acpi_status status = AE_OK; 581 u64 merged_value; 582 u64 current_value; 583 584 ACPI_FUNCTION_TRACE_U32(ex_write_with_update_rule, mask); 585 586 /* Start with the new bits */ 587 588 merged_value = field_value; 589 590 /* If the mask is all ones, we don't need to worry about the update rule */ 591 592 if (mask != ACPI_UINT64_MAX) { 593 594 /* Decode the update rule */ 595 596 switch (obj_desc->common_field. 597 field_flags & AML_FIELD_UPDATE_RULE_MASK) { 598 case AML_FIELD_UPDATE_PRESERVE: 599 /* 600 * Check if update rule needs to be applied (not if mask is all 601 * ones) The left shift drops the bits we want to ignore. 602 */ 603 if ((~mask << (ACPI_MUL_8(sizeof(mask)) - 604 ACPI_MUL_8(obj_desc->common_field. 605 access_byte_width))) != 0) { 606 /* 607 * Read the current contents of the byte/word/dword containing 608 * the field, and merge with the new field value. 609 */ 610 status = 611 acpi_ex_field_datum_io(obj_desc, 612 field_datum_byte_offset, 613 ¤t_value, 614 ACPI_READ); 615 if (ACPI_FAILURE(status)) { 616 return_ACPI_STATUS(status); 617 } 618 619 merged_value |= (current_value & ~mask); 620 } 621 break; 622 623 case AML_FIELD_UPDATE_WRITE_AS_ONES: 624 625 /* Set positions outside the field to all ones */ 626 627 merged_value |= ~mask; 628 break; 629 630 case AML_FIELD_UPDATE_WRITE_AS_ZEROS: 631 632 /* Set positions outside the field to all zeros */ 633 634 merged_value &= mask; 635 break; 636 637 default: 638 639 ACPI_ERROR((AE_INFO, 640 "Unknown UpdateRule value: 0x%X", 641 (obj_desc->common_field. 642 field_flags & 643 AML_FIELD_UPDATE_RULE_MASK))); 644 return_ACPI_STATUS(AE_AML_OPERAND_VALUE); 645 } 646 } 647 648 ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, 649 "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n", 650 ACPI_FORMAT_UINT64(mask), 651 field_datum_byte_offset, 652 obj_desc->common_field.access_byte_width, 653 ACPI_FORMAT_UINT64(field_value), 654 ACPI_FORMAT_UINT64(merged_value))); 655 656 /* Write the merged value */ 657 658 status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset, 659 &merged_value, ACPI_WRITE); 660 661 return_ACPI_STATUS(status); 662} 663 664/******************************************************************************* 665 * 666 * FUNCTION: acpi_ex_extract_from_field 667 * 668 * PARAMETERS: obj_desc - Field to be read 669 * buffer - Where to store the field data 670 * buffer_length - Length of Buffer 671 * 672 * RETURN: Status 673 * 674 * DESCRIPTION: Retrieve the current value of the given field 675 * 676 ******************************************************************************/ 677 678acpi_status 679acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, 680 void *buffer, u32 buffer_length) 681{ 682 acpi_status status; 683 u64 raw_datum; 684 u64 merged_datum; 685 u32 field_offset = 0; 686 u32 buffer_offset = 0; 687 u32 buffer_tail_bits; 688 u32 datum_count; 689 u32 field_datum_count; 690 u32 access_bit_width; 691 u32 i; 692 693 ACPI_FUNCTION_TRACE(ex_extract_from_field); 694 695 /* Validate target buffer and clear it */ 696 697 if (buffer_length < 698 ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { 699 ACPI_ERROR((AE_INFO, 700 "Field size %u (bits) is too large for buffer (%u)", 701 obj_desc->common_field.bit_length, buffer_length)); 702 703 return_ACPI_STATUS(AE_BUFFER_OVERFLOW); 704 } 705 706 ACPI_MEMSET(buffer, 0, buffer_length); 707 access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width); 708 709 /* Handle the simple case here */ 710 711 if ((obj_desc->common_field.start_field_bit_offset == 0) && 712 (obj_desc->common_field.bit_length == access_bit_width)) { 713 if (buffer_length >= sizeof(u64)) { 714 status = 715 acpi_ex_field_datum_io(obj_desc, 0, buffer, 716 ACPI_READ); 717 } else { 718 /* Use raw_datum (u64) to handle buffers < 64 bits */ 719 720 status = 721 acpi_ex_field_datum_io(obj_desc, 0, &raw_datum, 722 ACPI_READ); 723 ACPI_MEMCPY(buffer, &raw_datum, buffer_length); 724 } 725 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 835acpi_status 836acpi_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 997exit: 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