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