linux/drivers/acpi/acpica/nsprepkg.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: nsprepkg - Validation of package objects for predefined names
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2014, 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 "acnamesp.h"
  47#include "acpredef.h"
  48
  49#define _COMPONENT          ACPI_NAMESPACE
  50ACPI_MODULE_NAME("nsprepkg")
  51
  52/* Local prototypes */
  53static acpi_status
  54acpi_ns_check_package_list(struct acpi_evaluate_info *info,
  55                           const union acpi_predefined_info *package,
  56                           union acpi_operand_object **elements, u32 count);
  57
  58static acpi_status
  59acpi_ns_check_package_elements(struct acpi_evaluate_info *info,
  60                               union acpi_operand_object **elements,
  61                               u8 type1,
  62                               u32 count1,
  63                               u8 type2, u32 count2, u32 start_index);
  64
  65/*******************************************************************************
  66 *
  67 * FUNCTION:    acpi_ns_check_package
  68 *
  69 * PARAMETERS:  info                - Method execution information block
  70 *              return_object_ptr   - Pointer to the object returned from the
  71 *                                    evaluation of a method or object
  72 *
  73 * RETURN:      Status
  74 *
  75 * DESCRIPTION: Check a returned package object for the correct count and
  76 *              correct type of all sub-objects.
  77 *
  78 ******************************************************************************/
  79
  80acpi_status
  81acpi_ns_check_package(struct acpi_evaluate_info *info,
  82                      union acpi_operand_object **return_object_ptr)
  83{
  84        union acpi_operand_object *return_object = *return_object_ptr;
  85        const union acpi_predefined_info *package;
  86        union acpi_operand_object **elements;
  87        acpi_status status = AE_OK;
  88        u32 expected_count;
  89        u32 count;
  90        u32 i;
  91
  92        ACPI_FUNCTION_NAME(ns_check_package);
  93
  94        /* The package info for this name is in the next table entry */
  95
  96        package = info->predefined + 1;
  97
  98        ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
  99                          "%s Validating return Package of Type %X, Count %X\n",
 100                          info->full_pathname, package->ret_info.type,
 101                          return_object->package.count));
 102
 103        /*
 104         * For variable-length Packages, we can safely remove all embedded
 105         * and trailing NULL package elements
 106         */
 107        acpi_ns_remove_null_elements(info, package->ret_info.type,
 108                                     return_object);
 109
 110        /* Extract package count and elements array */
 111
 112        elements = return_object->package.elements;
 113        count = return_object->package.count;
 114
 115        /*
 116         * Most packages must have at least one element. The only exception
 117         * is the variable-length package (ACPI_PTYPE1_VAR).
 118         */
 119        if (!count) {
 120                if (package->ret_info.type == ACPI_PTYPE1_VAR) {
 121                        return (AE_OK);
 122                }
 123
 124                ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
 125                                      info->node_flags,
 126                                      "Return Package has no elements (empty)"));
 127
 128                return (AE_AML_OPERAND_VALUE);
 129        }
 130
 131        /*
 132         * Decode the type of the expected package contents
 133         *
 134         * PTYPE1 packages contain no subpackages
 135         * PTYPE2 packages contain subpackages
 136         */
 137        switch (package->ret_info.type) {
 138        case ACPI_PTYPE1_FIXED:
 139                /*
 140                 * The package count is fixed and there are no subpackages
 141                 *
 142                 * If package is too small, exit.
 143                 * If package is larger than expected, issue warning but continue
 144                 */
 145                expected_count =
 146                    package->ret_info.count1 + package->ret_info.count2;
 147                if (count < expected_count) {
 148                        goto package_too_small;
 149                } else if (count > expected_count) {
 150                        ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
 151                                          "%s: Return Package is larger than needed - "
 152                                          "found %u, expected %u\n",
 153                                          info->full_pathname, count,
 154                                          expected_count));
 155                }
 156
 157                /* Validate all elements of the returned package */
 158
 159                status = acpi_ns_check_package_elements(info, elements,
 160                                                        package->ret_info.
 161                                                        object_type1,
 162                                                        package->ret_info.
 163                                                        count1,
 164                                                        package->ret_info.
 165                                                        object_type2,
 166                                                        package->ret_info.
 167                                                        count2, 0);
 168                break;
 169
 170        case ACPI_PTYPE1_VAR:
 171                /*
 172                 * The package count is variable, there are no subpackages, and all
 173                 * elements must be of the same type
 174                 */
 175                for (i = 0; i < count; i++) {
 176                        status = acpi_ns_check_object_type(info, elements,
 177                                                           package->ret_info.
 178                                                           object_type1, i);
 179                        if (ACPI_FAILURE(status)) {
 180                                return (status);
 181                        }
 182                        elements++;
 183                }
 184                break;
 185
 186        case ACPI_PTYPE1_OPTION:
 187                /*
 188                 * The package count is variable, there are no subpackages. There are
 189                 * a fixed number of required elements, and a variable number of
 190                 * optional elements.
 191                 *
 192                 * Check if package is at least as large as the minimum required
 193                 */
 194                expected_count = package->ret_info3.count;
 195                if (count < expected_count) {
 196                        goto package_too_small;
 197                }
 198
 199                /* Variable number of sub-objects */
 200
 201                for (i = 0; i < count; i++) {
 202                        if (i < package->ret_info3.count) {
 203
 204                                /* These are the required package elements (0, 1, or 2) */
 205
 206                                status =
 207                                    acpi_ns_check_object_type(info, elements,
 208                                                              package->
 209                                                              ret_info3.
 210                                                              object_type[i],
 211                                                              i);
 212                                if (ACPI_FAILURE(status)) {
 213                                        return (status);
 214                                }
 215                        } else {
 216                                /* These are the optional package elements */
 217
 218                                status =
 219                                    acpi_ns_check_object_type(info, elements,
 220                                                              package->
 221                                                              ret_info3.
 222                                                              tail_object_type,
 223                                                              i);
 224                                if (ACPI_FAILURE(status)) {
 225                                        return (status);
 226                                }
 227                        }
 228                        elements++;
 229                }
 230                break;
 231
 232        case ACPI_PTYPE2_REV_FIXED:
 233
 234                /* First element is the (Integer) revision */
 235
 236                status = acpi_ns_check_object_type(info, elements,
 237                                                   ACPI_RTYPE_INTEGER, 0);
 238                if (ACPI_FAILURE(status)) {
 239                        return (status);
 240                }
 241
 242                elements++;
 243                count--;
 244
 245                /* Examine the subpackages */
 246
 247                status =
 248                    acpi_ns_check_package_list(info, package, elements, count);
 249                break;
 250
 251        case ACPI_PTYPE2_PKG_COUNT:
 252
 253                /* First element is the (Integer) count of subpackages to follow */
 254
 255                status = acpi_ns_check_object_type(info, elements,
 256                                                   ACPI_RTYPE_INTEGER, 0);
 257                if (ACPI_FAILURE(status)) {
 258                        return (status);
 259                }
 260
 261                /*
 262                 * Count cannot be larger than the parent package length, but allow it
 263                 * to be smaller. The >= accounts for the Integer above.
 264                 */
 265                expected_count = (u32)(*elements)->integer.value;
 266                if (expected_count >= count) {
 267                        goto package_too_small;
 268                }
 269
 270                count = expected_count;
 271                elements++;
 272
 273                /* Examine the subpackages */
 274
 275                status =
 276                    acpi_ns_check_package_list(info, package, elements, count);
 277                break;
 278
 279        case ACPI_PTYPE2:
 280        case ACPI_PTYPE2_FIXED:
 281        case ACPI_PTYPE2_MIN:
 282        case ACPI_PTYPE2_COUNT:
 283        case ACPI_PTYPE2_FIX_VAR:
 284                /*
 285                 * These types all return a single Package that consists of a
 286                 * variable number of subpackages.
 287                 *
 288                 * First, ensure that the first element is a subpackage. If not,
 289                 * the BIOS may have incorrectly returned the object as a single
 290                 * package instead of a Package of Packages (a common error if
 291                 * there is only one entry). We may be able to repair this by
 292                 * wrapping the returned Package with a new outer Package.
 293                 */
 294                if (*elements
 295                    && ((*elements)->common.type != ACPI_TYPE_PACKAGE)) {
 296
 297                        /* Create the new outer package and populate it */
 298
 299                        status =
 300                            acpi_ns_wrap_with_package(info, return_object,
 301                                                      return_object_ptr);
 302                        if (ACPI_FAILURE(status)) {
 303                                return (status);
 304                        }
 305
 306                        /* Update locals to point to the new package (of 1 element) */
 307
 308                        return_object = *return_object_ptr;
 309                        elements = return_object->package.elements;
 310                        count = 1;
 311                }
 312
 313                /* Examine the subpackages */
 314
 315                status =
 316                    acpi_ns_check_package_list(info, package, elements, count);
 317                break;
 318
 319        case ACPI_PTYPE2_UUID_PAIR:
 320
 321                /* The package must contain pairs of (UUID + type) */
 322
 323                if (count & 1) {
 324                        expected_count = count + 1;
 325                        goto package_too_small;
 326                }
 327
 328                while (count > 0) {
 329                        status = acpi_ns_check_object_type(info, elements,
 330                                                           package->ret_info.
 331                                                           object_type1, 0);
 332                        if (ACPI_FAILURE(status)) {
 333                                return (status);
 334                        }
 335
 336                        /* Validate length of the UUID buffer */
 337
 338                        if ((*elements)->buffer.length != 16) {
 339                                ACPI_WARN_PREDEFINED((AE_INFO,
 340                                                      info->full_pathname,
 341                                                      info->node_flags,
 342                                                      "Invalid length for UUID Buffer"));
 343                                return (AE_AML_OPERAND_VALUE);
 344                        }
 345
 346                        status = acpi_ns_check_object_type(info, elements + 1,
 347                                                           package->ret_info.
 348                                                           object_type2, 0);
 349                        if (ACPI_FAILURE(status)) {
 350                                return (status);
 351                        }
 352
 353                        elements += 2;
 354                        count -= 2;
 355                }
 356                break;
 357
 358        default:
 359
 360                /* Should not get here if predefined info table is correct */
 361
 362                ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
 363                                      info->node_flags,
 364                                      "Invalid internal return type in table entry: %X",
 365                                      package->ret_info.type));
 366
 367                return (AE_AML_INTERNAL);
 368        }
 369
 370        return (status);
 371
 372package_too_small:
 373
 374        /* Error exit for the case with an incorrect package count */
 375
 376        ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags,
 377                              "Return Package is too small - found %u elements, expected %u",
 378                              count, expected_count));
 379
 380        return (AE_AML_OPERAND_VALUE);
 381}
 382
 383/*******************************************************************************
 384 *
 385 * FUNCTION:    acpi_ns_check_package_list
 386 *
 387 * PARAMETERS:  info            - Method execution information block
 388 *              package         - Pointer to package-specific info for method
 389 *              elements        - Element list of parent package. All elements
 390 *                                of this list should be of type Package.
 391 *              count           - Count of subpackages
 392 *
 393 * RETURN:      Status
 394 *
 395 * DESCRIPTION: Examine a list of subpackages
 396 *
 397 ******************************************************************************/
 398
 399static acpi_status
 400acpi_ns_check_package_list(struct acpi_evaluate_info *info,
 401                           const union acpi_predefined_info *package,
 402                           union acpi_operand_object **elements, u32 count)
 403{
 404        union acpi_operand_object *sub_package;
 405        union acpi_operand_object **sub_elements;
 406        acpi_status status;
 407        u32 expected_count;
 408        u32 i;
 409        u32 j;
 410
 411        /*
 412         * Validate each subpackage in the parent Package
 413         *
 414         * NOTE: assumes list of subpackages contains no NULL elements.
 415         * Any NULL elements should have been removed by earlier call
 416         * to acpi_ns_remove_null_elements.
 417         */
 418        for (i = 0; i < count; i++) {
 419                sub_package = *elements;
 420                sub_elements = sub_package->package.elements;
 421                info->parent_package = sub_package;
 422
 423                /* Each sub-object must be of type Package */
 424
 425                status = acpi_ns_check_object_type(info, &sub_package,
 426                                                   ACPI_RTYPE_PACKAGE, i);
 427                if (ACPI_FAILURE(status)) {
 428                        return (status);
 429                }
 430
 431                /* Examine the different types of expected subpackages */
 432
 433                info->parent_package = sub_package;
 434                switch (package->ret_info.type) {
 435                case ACPI_PTYPE2:
 436                case ACPI_PTYPE2_PKG_COUNT:
 437                case ACPI_PTYPE2_REV_FIXED:
 438
 439                        /* Each subpackage has a fixed number of elements */
 440
 441                        expected_count =
 442                            package->ret_info.count1 + package->ret_info.count2;
 443                        if (sub_package->package.count < expected_count) {
 444                                goto package_too_small;
 445                        }
 446
 447                        status =
 448                            acpi_ns_check_package_elements(info, sub_elements,
 449                                                           package->ret_info.
 450                                                           object_type1,
 451                                                           package->ret_info.
 452                                                           count1,
 453                                                           package->ret_info.
 454                                                           object_type2,
 455                                                           package->ret_info.
 456                                                           count2, 0);
 457                        if (ACPI_FAILURE(status)) {
 458                                return (status);
 459                        }
 460                        break;
 461
 462                case ACPI_PTYPE2_FIX_VAR:
 463                        /*
 464                         * Each subpackage has a fixed number of elements and an
 465                         * optional element
 466                         */
 467                        expected_count =
 468                            package->ret_info.count1 + package->ret_info.count2;
 469                        if (sub_package->package.count < expected_count) {
 470                                goto package_too_small;
 471                        }
 472
 473                        status =
 474                            acpi_ns_check_package_elements(info, sub_elements,
 475                                                           package->ret_info.
 476                                                           object_type1,
 477                                                           package->ret_info.
 478                                                           count1,
 479                                                           package->ret_info.
 480                                                           object_type2,
 481                                                           sub_package->package.
 482                                                           count -
 483                                                           package->ret_info.
 484                                                           count1, 0);
 485                        if (ACPI_FAILURE(status)) {
 486                                return (status);
 487                        }
 488                        break;
 489
 490                case ACPI_PTYPE2_FIXED:
 491
 492                        /* Each subpackage has a fixed length */
 493
 494                        expected_count = package->ret_info2.count;
 495                        if (sub_package->package.count < expected_count) {
 496                                goto package_too_small;
 497                        }
 498
 499                        /* Check the type of each subpackage element */
 500
 501                        for (j = 0; j < expected_count; j++) {
 502                                status =
 503                                    acpi_ns_check_object_type(info,
 504                                                              &sub_elements[j],
 505                                                              package->
 506                                                              ret_info2.
 507                                                              object_type[j],
 508                                                              j);
 509                                if (ACPI_FAILURE(status)) {
 510                                        return (status);
 511                                }
 512                        }
 513                        break;
 514
 515                case ACPI_PTYPE2_MIN:
 516
 517                        /* Each subpackage has a variable but minimum length */
 518
 519                        expected_count = package->ret_info.count1;
 520                        if (sub_package->package.count < expected_count) {
 521                                goto package_too_small;
 522                        }
 523
 524                        /* Check the type of each subpackage element */
 525
 526                        status =
 527                            acpi_ns_check_package_elements(info, sub_elements,
 528                                                           package->ret_info.
 529                                                           object_type1,
 530                                                           sub_package->package.
 531                                                           count, 0, 0, 0);
 532                        if (ACPI_FAILURE(status)) {
 533                                return (status);
 534                        }
 535                        break;
 536
 537                case ACPI_PTYPE2_COUNT:
 538                        /*
 539                         * First element is the (Integer) count of elements, including
 540                         * the count field (the ACPI name is num_elements)
 541                         */
 542                        status = acpi_ns_check_object_type(info, sub_elements,
 543                                                           ACPI_RTYPE_INTEGER,
 544                                                           0);
 545                        if (ACPI_FAILURE(status)) {
 546                                return (status);
 547                        }
 548
 549                        /*
 550                         * Make sure package is large enough for the Count and is
 551                         * is as large as the minimum size
 552                         */
 553                        expected_count = (u32)(*sub_elements)->integer.value;
 554                        if (sub_package->package.count < expected_count) {
 555                                goto package_too_small;
 556                        }
 557                        if (sub_package->package.count <
 558                            package->ret_info.count1) {
 559                                expected_count = package->ret_info.count1;
 560                                goto package_too_small;
 561                        }
 562                        if (expected_count == 0) {
 563                                /*
 564                                 * Either the num_entries element was originally zero or it was
 565                                 * a NULL element and repaired to an Integer of value zero.
 566                                 * In either case, repair it by setting num_entries to be the
 567                                 * actual size of the subpackage.
 568                                 */
 569                                expected_count = sub_package->package.count;
 570                                (*sub_elements)->integer.value = expected_count;
 571                        }
 572
 573                        /* Check the type of each subpackage element */
 574
 575                        status =
 576                            acpi_ns_check_package_elements(info,
 577                                                           (sub_elements + 1),
 578                                                           package->ret_info.
 579                                                           object_type1,
 580                                                           (expected_count - 1),
 581                                                           0, 0, 1);
 582                        if (ACPI_FAILURE(status)) {
 583                                return (status);
 584                        }
 585                        break;
 586
 587                default:        /* Should not get here, type was validated by caller */
 588
 589                        return (AE_AML_INTERNAL);
 590                }
 591
 592                elements++;
 593        }
 594
 595        return (AE_OK);
 596
 597package_too_small:
 598
 599        /* The subpackage count was smaller than required */
 600
 601        ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags,
 602                              "Return SubPackage[%u] is too small - found %u elements, expected %u",
 603                              i, sub_package->package.count, expected_count));
 604
 605        return (AE_AML_OPERAND_VALUE);
 606}
 607
 608/*******************************************************************************
 609 *
 610 * FUNCTION:    acpi_ns_check_package_elements
 611 *
 612 * PARAMETERS:  info            - Method execution information block
 613 *              elements        - Pointer to the package elements array
 614 *              type1           - Object type for first group
 615 *              count1          - Count for first group
 616 *              type2           - Object type for second group
 617 *              count2          - Count for second group
 618 *              start_index     - Start of the first group of elements
 619 *
 620 * RETURN:      Status
 621 *
 622 * DESCRIPTION: Check that all elements of a package are of the correct object
 623 *              type. Supports up to two groups of different object types.
 624 *
 625 ******************************************************************************/
 626
 627static acpi_status
 628acpi_ns_check_package_elements(struct acpi_evaluate_info *info,
 629                               union acpi_operand_object **elements,
 630                               u8 type1,
 631                               u32 count1,
 632                               u8 type2, u32 count2, u32 start_index)
 633{
 634        union acpi_operand_object **this_element = elements;
 635        acpi_status status;
 636        u32 i;
 637
 638        /*
 639         * Up to two groups of package elements are supported by the data
 640         * structure. All elements in each group must be of the same type.
 641         * The second group can have a count of zero.
 642         */
 643        for (i = 0; i < count1; i++) {
 644                status = acpi_ns_check_object_type(info, this_element,
 645                                                   type1, i + start_index);
 646                if (ACPI_FAILURE(status)) {
 647                        return (status);
 648                }
 649                this_element++;
 650        }
 651
 652        for (i = 0; i < count2; i++) {
 653                status = acpi_ns_check_object_type(info, this_element,
 654                                                   type2,
 655                                                   (i + count1 + start_index));
 656                if (ACPI_FAILURE(status)) {
 657                        return (status);
 658                }
 659                this_element++;
 660        }
 661
 662        return (AE_OK);
 663}
 664