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