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