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