nsprepkg.c (19991B)
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 - 2022, 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}