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