741 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: nsprepkg - Validation of package objects for predefined names5 *6 * Copyright (C) 2000 - 2023, 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_NAMESPACE16ACPI_MODULE_NAME("nsprepkg")17 18/* Local prototypes */19static acpi_status20acpi_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_status25acpi_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_status32acpi_ns_custom_package(struct acpi_evaluate_info *info,33 union acpi_operand_object **elements, u32 count);34 35/*******************************************************************************36 *37 * FUNCTION: acpi_ns_check_package38 *39 * PARAMETERS: info - Method execution information block40 * return_object_ptr - Pointer to the object returned from the41 * evaluation of a method or object42 *43 * RETURN: Status44 *45 * DESCRIPTION: Check a returned package object for the correct count and46 * correct type of all sub-objects.47 *48 ******************************************************************************/49 50acpi_status51acpi_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 embedded75 * and trailing NULL package elements76 */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 exception87 * 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 contents103 *104 * PTYPE1 packages contain no subpackages105 * PTYPE2 packages contain subpackages106 */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 subpackages116 *117 * If package is too small, exit.118 * If package is larger than expected, issue warning but continue119 */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 all148 * elements must be of the same type149 */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 are165 * a fixed number of required elements, and a variable number of166 * optional elements.167 *168 * Check if package is at least as large as the minimum required169 */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 it242 * 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 a265 * 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 single269 * package instead of a Package of Packages (a common error if270 * there is only one entry). We may be able to repair this by271 * wrapping the returned Package with a new outer Package.272 */273 if (*elements274 && ((*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 list301 * 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_list372 *373 * PARAMETERS: info - Method execution information block374 * package - Pointer to package-specific info for method375 * elements - Element list of parent package. All elements376 * of this list should be of type Package.377 * count - Count of subpackages378 *379 * RETURN: Status380 *381 * DESCRIPTION: Examine a list of subpackages382 *383 ******************************************************************************/384 385static acpi_status386acpi_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 Package399 *400 * NOTE: assumes list of subpackages contains no NULL elements.401 * Any NULL elements should have been removed by earlier call402 * 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 an451 * optional element452 */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 elements479 */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, including532 * 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 is543 * is as large as the minimum size544 */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 was559 * a NULL element and repaired to an Integer of value zero.560 * In either case, repair it by setting num_entries to be the561 * 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_package607 *608 * PARAMETERS: info - Method execution information block609 * elements - Pointer to the package elements array610 * count - Element count for the package611 *612 * RETURN: Status613 *614 * DESCRIPTION: Check a returned package object for the correct count and615 * correct type of all sub-objects.616 *617 * NOTE: Currently used for the _BIX method only. When needed for two or more618 * methods, probably a detect/dispatch mechanism will be required.619 *620 ******************************************************************************/621 622static acpi_status623acpi_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_elements684 *685 * PARAMETERS: info - Method execution information block686 * elements - Pointer to the package elements array687 * type1 - Object type for first group688 * count1 - Count for first group689 * type2 - Object type for second group690 * count2 - Count for second group691 * start_index - Start of the first group of elements692 *693 * RETURN: Status694 *695 * DESCRIPTION: Check that all elements of a package are of the correct object696 * type. Supports up to two groups of different object types.697 *698 ******************************************************************************/699 700static acpi_status701acpi_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 data715 * 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