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