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