aslprepkg.c revision 306536
1321369Sdim/****************************************************************************** 2303231Sdim * 3353358Sdim * Module Name: aslprepkg - support for ACPI predefined name package objects 4353358Sdim * 5353358Sdim *****************************************************************************/ 6303231Sdim 7303231Sdim/* 8303231Sdim * Copyright (C) 2000 - 2016, Intel Corp. 9303231Sdim * All rights reserved. 10303231Sdim * 11303231Sdim * Redistribution and use in source and binary forms, with or without 12303231Sdim * modification, are permitted provided that the following conditions 13303231Sdim * are met: 14321369Sdim * 1. Redistributions of source code must retain the above copyright 15321369Sdim * notice, this list of conditions, and the following disclaimer, 16303231Sdim * without modification. 17303231Sdim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18303231Sdim * substantially similar to the "NO WARRANTY" disclaimer below 19341825Sdim * ("Disclaimer") and any redistribution must be conditioned upon 20303231Sdim * including a substantially similar Disclaimer requirement for further 21321369Sdim * binary redistribution. 22321369Sdim * 3. Neither the names of the above-listed copyright holders nor the names 23314564Sdim * of any contributors may be used to endorse or promote products derived 24303231Sdim * from this software without specific prior written permission. 25321369Sdim * 26303231Sdim * Alternatively, this software may be distributed under the terms of the 27321369Sdim * GNU General Public License ("GPL") version 2 as published by the Free 28303231Sdim * Software Foundation. 29303231Sdim * 30321369Sdim * NO WARRANTY 31303231Sdim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32321369Sdim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33321369Sdim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34321369Sdim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35321369Sdim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36321369Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37303231Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38303231Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39321369Sdim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40321369Sdim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41303231Sdim * POSSIBILITY OF SUCH DAMAGES. 42303231Sdim */ 43321369Sdim 44321369Sdim#include <contrib/dev/acpica/compiler/aslcompiler.h> 45321369Sdim#include "aslcompiler.y.h" 46303231Sdim#include <contrib/dev/acpica/include/acpredef.h> 47303231Sdim 48321369Sdim 49321369Sdim#define _COMPONENT ACPI_COMPILER 50321369Sdim ACPI_MODULE_NAME ("aslprepkg") 51303231Sdim 52303231Sdim 53303231Sdim/* Local prototypes */ 54303231Sdim 55303231Sdimstatic ACPI_PARSE_OBJECT * 56303231SdimApCheckPackageElements ( 57303231Sdim const char *PredefinedName, 58303231Sdim ACPI_PARSE_OBJECT *Op, 59303231Sdim UINT8 Type1, 60303231Sdim UINT32 Count1, 61303231Sdim UINT8 Type2, 62303231Sdim UINT32 Count2); 63303231Sdim 64303231Sdimstatic void 65303231SdimApCheckPackageList ( 66303231Sdim const char *PredefinedName, 67303231Sdim ACPI_PARSE_OBJECT *ParentOp, 68303231Sdim const ACPI_PREDEFINED_INFO *Package, 69303231Sdim UINT32 StartIndex, 70303231Sdim UINT32 Count); 71303231Sdim 72303231Sdimstatic void 73303231SdimApPackageTooSmall ( 74303231Sdim const char *PredefinedName, 75303231Sdim ACPI_PARSE_OBJECT *Op, 76303231Sdim UINT32 Count, 77303231Sdim UINT32 ExpectedCount); 78303231Sdim 79303231Sdimstatic void 80303231SdimApZeroLengthPackage ( 81303231Sdim const char *PredefinedName, 82303231Sdim ACPI_PARSE_OBJECT *Op); 83303231Sdim 84303231Sdimstatic void 85303231SdimApPackageTooLarge ( 86303231Sdim const char *PredefinedName, 87303231Sdim ACPI_PARSE_OBJECT *Op, 88327952Sdim UINT32 Count, 89303231Sdim UINT32 ExpectedCount); 90303231Sdim 91303231Sdimstatic void 92303231SdimApCustomPackage ( 93303231Sdim ACPI_PARSE_OBJECT *ParentOp, 94303231Sdim const ACPI_PREDEFINED_INFO *Predefined); 95303231Sdim 96303231Sdim 97303231Sdim/******************************************************************************* 98321369Sdim * 99321369Sdim * FUNCTION: ApCheckPackage 100303231Sdim * 101303231Sdim * PARAMETERS: ParentOp - Parser op for the package 102303231Sdim * Predefined - Pointer to package-specific info for 103303231Sdim * the method 104321369Sdim * 105303231Sdim * RETURN: None 106303231Sdim * 107303231Sdim * DESCRIPTION: Top-level validation for predefined name return package 108303231Sdim * objects. 109303231Sdim * 110303231Sdim ******************************************************************************/ 111303231Sdim 112303231Sdimvoid 113303231SdimApCheckPackage ( 114303231Sdim ACPI_PARSE_OBJECT *ParentOp, 115303231Sdim const ACPI_PREDEFINED_INFO *Predefined) 116303231Sdim{ 117303231Sdim ACPI_PARSE_OBJECT *Op; 118303231Sdim const ACPI_PREDEFINED_INFO *Package; 119303231Sdim ACPI_STATUS Status; 120303231Sdim UINT32 ExpectedCount; 121303231Sdim UINT32 Count; 122303231Sdim UINT32 i; 123303231Sdim 124303231Sdim 125303231Sdim /* The package info for this name is in the next table entry */ 126303231Sdim 127303231Sdim Package = Predefined + 1; 128327952Sdim 129303231Sdim /* First child is the package length */ 130303231Sdim 131327952Sdim Op = ParentOp->Asl.Child; 132303231Sdim Count = (UINT32) Op->Asl.Value.Integer; 133303231Sdim 134303231Sdim /* 135303231Sdim * Many of the variable-length top-level packages are allowed to simply 136327952Sdim * have zero elements. This allows the BIOS to tell the host that even 137327952Sdim * though the predefined name/method exists, the feature is not supported. 138303231Sdim * Other package types require one or more elements. In any case, there 139303231Sdim * is no need to continue validation. 140303231Sdim */ 141303231Sdim if (!Count) 142303231Sdim { 143327952Sdim switch (Package->RetInfo.Type) 144327952Sdim { 145303231Sdim case ACPI_PTYPE1_FIXED: 146303231Sdim case ACPI_PTYPE1_OPTION: 147303231Sdim case ACPI_PTYPE2_PKG_COUNT: 148303231Sdim case ACPI_PTYPE2_REV_FIXED: 149303231Sdim 150303231Sdim ApZeroLengthPackage (Predefined->Info.Name, ParentOp); 151303231Sdim break; 152303231Sdim 153303231Sdim case ACPI_PTYPE1_VAR: 154327952Sdim case ACPI_PTYPE2: 155327952Sdim case ACPI_PTYPE2_COUNT: 156303231Sdim case ACPI_PTYPE2_FIXED: 157327952Sdim case ACPI_PTYPE2_MIN: 158303231Sdim case ACPI_PTYPE2_FIX_VAR: 159321369Sdim case ACPI_PTYPE2_VAR_VAR: 160327952Sdim default: 161321369Sdim 162303231Sdim break; 163327952Sdim } 164303231Sdim 165303231Sdim return; 166303231Sdim } 167303231Sdim 168303231Sdim /* Get the first element of the package */ 169303231Sdim 170321369Sdim Op = Op->Asl.Next; 171321369Sdim 172321369Sdim /* Decode the package type */ 173321369Sdim 174321369Sdim switch (Package->RetInfo.Type) 175321369Sdim { 176321369Sdim case ACPI_PTYPE_CUSTOM: 177321369Sdim 178321369Sdim ApCustomPackage (ParentOp, Predefined); 179327952Sdim break; 180303231Sdim 181303231Sdim case ACPI_PTYPE1_FIXED: 182303231Sdim /* 183303231Sdim * The package count is fixed and there are no subpackages 184321369Sdim * 185303231Sdim * If package is too small, exit. 186327952Sdim * If package is larger than expected, issue warning but continue 187303231Sdim */ 188303231Sdim ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 189303231Sdim if (Count < ExpectedCount) 190303231Sdim { 191303231Sdim goto PackageTooSmall; 192303231Sdim } 193327952Sdim else if (Count > ExpectedCount) 194303231Sdim { 195303231Sdim ApPackageTooLarge (Predefined->Info.Name, ParentOp, 196327952Sdim Count, ExpectedCount); 197327952Sdim } 198303231Sdim 199303231Sdim /* Validate all elements of the package */ 200303231Sdim 201327952Sdim ApCheckPackageElements (Predefined->Info.Name, Op, 202327952Sdim Package->RetInfo.ObjectType1, Package->RetInfo.Count1, 203327952Sdim Package->RetInfo.ObjectType2, Package->RetInfo.Count2); 204303231Sdim break; 205303231Sdim 206327952Sdim case ACPI_PTYPE1_VAR: 207303231Sdim /* 208303231Sdim * The package count is variable, there are no subpackages, 209341825Sdim * and all elements must be of the same type 210327952Sdim */ 211327952Sdim for (i = 0; i < Count; i++) 212303231Sdim { 213303231Sdim ApCheckObjectType (Predefined->Info.Name, Op, 214327952Sdim Package->RetInfo.ObjectType1, i); 215327952Sdim Op = Op->Asl.Next; 216327952Sdim } 217327952Sdim break; 218327952Sdim 219327952Sdim case ACPI_PTYPE1_OPTION: 220327952Sdim /* 221303231Sdim * The package count is variable, there are no subpackages. 222303231Sdim * There are a fixed number of required elements, and a variable 223303231Sdim * number of optional elements. 224303231Sdim * 225303231Sdim * Check if package is at least as large as the minimum required 226303231Sdim */ 227303231Sdim ExpectedCount = Package->RetInfo3.Count; 228303231Sdim if (Count < ExpectedCount) 229303231Sdim { 230303231Sdim goto PackageTooSmall; 231303231Sdim } 232303231Sdim 233303231Sdim /* Variable number of sub-objects */ 234303231Sdim 235303231Sdim for (i = 0; i < Count; i++) 236303231Sdim { 237303231Sdim if (i < Package->RetInfo3.Count) 238303231Sdim { 239303231Sdim /* These are the required package elements (0, 1, or 2) */ 240303231Sdim 241303231Sdim ApCheckObjectType (Predefined->Info.Name, Op, 242303231Sdim Package->RetInfo3.ObjectType[i], i); 243303231Sdim } 244303231Sdim else 245303231Sdim { 246303231Sdim /* These are the optional package elements */ 247303231Sdim 248303231Sdim ApCheckObjectType (Predefined->Info.Name, Op, 249303231Sdim Package->RetInfo3.TailObjectType, i); 250303231Sdim } 251303231Sdim 252303231Sdim Op = Op->Asl.Next; 253303231Sdim } 254303231Sdim break; 255303231Sdim 256303231Sdim case ACPI_PTYPE2_REV_FIXED: 257327952Sdim 258327952Sdim /* First element is the (Integer) revision */ 259327952Sdim 260327952Sdim ApCheckObjectType (Predefined->Info.Name, Op, 261327952Sdim ACPI_RTYPE_INTEGER, 0); 262303231Sdim 263303231Sdim Op = Op->Asl.Next; 264327952Sdim Count--; 265327952Sdim 266303231Sdim /* Examine the subpackages */ 267327952Sdim 268327952Sdim ApCheckPackageList (Predefined->Info.Name, Op, 269303231Sdim Package, 1, Count); 270303231Sdim break; 271327952Sdim 272303231Sdim case ACPI_PTYPE2_PKG_COUNT: 273303231Sdim 274303231Sdim /* First element is the (Integer) count of subpackages to follow */ 275303231Sdim 276303231Sdim Status = ApCheckObjectType (Predefined->Info.Name, Op, 277303231Sdim ACPI_RTYPE_INTEGER, 0); 278303231Sdim 279327952Sdim /* We must have an integer count from above (otherwise, use Count) */ 280327952Sdim 281303231Sdim if (ACPI_SUCCESS (Status)) 282303231Sdim { 283303231Sdim /* 284303231Sdim * Count cannot be larger than the parent package length, but 285303231Sdim * allow it to be smaller. The >= accounts for the Integer above. 286303231Sdim */ 287303231Sdim ExpectedCount = (UINT32) Op->Asl.Value.Integer; 288303231Sdim if (ExpectedCount >= Count) 289303231Sdim { 290303231Sdim goto PackageTooSmall; 291303231Sdim } 292321369Sdim 293303231Sdim Count = ExpectedCount; 294303231Sdim } 295327952Sdim 296327952Sdim Op = Op->Asl.Next; 297303231Sdim 298303231Sdim /* Examine the subpackages */ 299303231Sdim 300327952Sdim ApCheckPackageList (Predefined->Info.Name, Op, 301303231Sdim Package, 1, Count); 302327952Sdim break; 303303231Sdim 304360784Sdim case ACPI_PTYPE2_UUID_PAIR: 305360784Sdim 306360784Sdim /* The package contains a variable list of UUID Buffer/Package pairs */ 307360784Sdim 308360784Sdim /* The length of the package must be even */ 309360784Sdim 310303231Sdim if (Count & 1) 311327952Sdim { 312303231Sdim sprintf (MsgBuffer, "%4.4s: Package length, %d, must be even.", 313327952Sdim Predefined->Info.Name, Count); 314360784Sdim 315303231Sdim AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, 316303231Sdim ParentOp->Asl.Child, MsgBuffer); 317303231Sdim } 318303231Sdim 319314564Sdim /* Validate the alternating types */ 320314564Sdim 321314564Sdim for (i = 0; i < Count; ++i) 322303231Sdim { 323303231Sdim if (i & 1) 324303231Sdim { 325303231Sdim ApCheckObjectType (Predefined->Info.Name, Op, 326303231Sdim Package->RetInfo.ObjectType2, i); 327303231Sdim } 328303231Sdim else 329327952Sdim { 330303231Sdim ApCheckObjectType (Predefined->Info.Name, Op, 331303231Sdim Package->RetInfo.ObjectType1, i); 332303231Sdim } 333303231Sdim 334303231Sdim Op = Op->Asl.Next; 335303231Sdim } 336303231Sdim 337327952Sdim break; 338303231Sdim 339303231Sdim case ACPI_PTYPE2_VAR_VAR: 340303231Sdim 341303231Sdim /* Check for minimum size (ints at beginning + 1 subpackage) */ 342303231Sdim 343303231Sdim ExpectedCount = Package->RetInfo4.Count1 + 1; 344303231Sdim if (Count < ExpectedCount) 345303231Sdim { 346303231Sdim goto PackageTooSmall; 347303231Sdim } 348303231Sdim 349303231Sdim /* Check the non-package elements at beginning of main package */ 350303231Sdim 351303231Sdim for (i = 0; i < Package->RetInfo4.Count1; ++i) 352303231Sdim { 353303231Sdim Status = ApCheckObjectType (Predefined->Info.Name, Op, 354303231Sdim Package->RetInfo4.ObjectType1, i); 355303231Sdim Op = Op->Asl.Next; 356303231Sdim } 357303231Sdim 358303231Sdim /* Examine the variable-length list of subpackages */ 359303231Sdim 360303231Sdim ApCheckPackageList (Predefined->Info.Name, Op, 361303231Sdim Package, Package->RetInfo4.Count1, Count); 362303231Sdim 363327952Sdim break; 364303231Sdim 365303231Sdim case ACPI_PTYPE2: 366303231Sdim case ACPI_PTYPE2_FIXED: 367303231Sdim case ACPI_PTYPE2_MIN: 368303231Sdim case ACPI_PTYPE2_COUNT: 369327952Sdim case ACPI_PTYPE2_FIX_VAR: 370303231Sdim /* 371327952Sdim * These types all return a single Package that consists of a 372303231Sdim * variable number of subpackages. 373327952Sdim */ 374303231Sdim 375303231Sdim /* Examine the subpackages */ 376303231Sdim 377303231Sdim ApCheckPackageList (Predefined->Info.Name, Op, 378303231Sdim Package, 0, Count); 379303231Sdim break; 380303231Sdim 381327952Sdim default: 382303231Sdim return; 383303231Sdim } 384303231Sdim 385303231Sdim return; 386327952Sdim 387303231SdimPackageTooSmall: 388327952Sdim ApPackageTooSmall (Predefined->Info.Name, ParentOp, 389303231Sdim Count, ExpectedCount); 390327952Sdim} 391303231Sdim 392327952Sdim 393303231Sdim/******************************************************************************* 394327952Sdim * 395303231Sdim * FUNCTION: ApCustomPackage 396327952Sdim * 397327952Sdim * PARAMETERS: ParentOp - Parse op for the package 398303231Sdim * Predefined - Pointer to package-specific info for 399303231Sdim * the method 400303231Sdim * 401327952Sdim * RETURN: None 402303231Sdim * 403303231Sdim * DESCRIPTION: Validate packages that don't fit into the standard model and 404327952Sdim * require custom code. 405303231Sdim * 406327952Sdim * NOTE: Currently used for the _BIX method only. When needed for two or more 407303231Sdim * methods, probably a detect/dispatch mechanism will be required. 408303231Sdim * 409327952Sdim ******************************************************************************/ 410327952Sdim 411327952Sdimstatic void 412327952SdimApCustomPackage ( 413303231Sdim ACPI_PARSE_OBJECT *ParentOp, 414303231Sdim const ACPI_PREDEFINED_INFO *Predefined) 415303231Sdim{ 416327952Sdim ACPI_PARSE_OBJECT *Op; 417327952Sdim UINT32 Count; 418303231Sdim UINT32 ExpectedCount; 419327952Sdim UINT32 Version; 420327952Sdim 421327952Sdim 422327952Sdim /* First child is the package length */ 423327952Sdim 424327952Sdim Op = ParentOp->Asl.Child; 425327952Sdim Count = (UINT32) Op->Asl.Value.Integer; 426327952Sdim 427327952Sdim /* Get the version number, must be Integer */ 428327952Sdim 429327952Sdim Op = Op->Asl.Next; 430327952Sdim Version = (UINT32) Op->Asl.Value.Integer; 431327952Sdim if (Op->Asl.ParseOpcode != PARSEOP_INTEGER) 432327952Sdim { 433327952Sdim AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Op, MsgBuffer); 434327952Sdim return; 435327952Sdim } 436327952Sdim 437327952Sdim /* Validate count (# of elements) */ 438327952Sdim 439327952Sdim ExpectedCount = 21; /* Version 1 */ 440327952Sdim if (Version == 0) 441327952Sdim { 442327952Sdim ExpectedCount = 20; /* Version 0 */ 443327952Sdim } 444327952Sdim 445327952Sdim if (Count < ExpectedCount) 446327952Sdim { 447327952Sdim ApPackageTooSmall (Predefined->Info.Name, ParentOp, 448327952Sdim Count, ExpectedCount); 449327952Sdim return; 450327952Sdim } 451327952Sdim else if (Count > ExpectedCount) 452327952Sdim { 453327952Sdim ApPackageTooLarge (Predefined->Info.Name, ParentOp, 454327952Sdim Count, ExpectedCount); 455327952Sdim } 456327952Sdim 457327952Sdim /* Validate all elements of the package */ 458327952Sdim 459327952Sdim Op = ApCheckPackageElements (Predefined->Info.Name, Op, 460327952Sdim ACPI_RTYPE_INTEGER, 16, 461327952Sdim ACPI_RTYPE_STRING, 4); 462327952Sdim 463327952Sdim /* Version 1 has a single trailing integer */ 464327952Sdim 465327952Sdim if (Version > 0) 466327952Sdim { 467327952Sdim ApCheckPackageElements (Predefined->Info.Name, Op, 468327952Sdim ACPI_RTYPE_INTEGER, 1, 0, 0); 469327952Sdim } 470327952Sdim} 471327952Sdim 472327952Sdim 473327952Sdim/******************************************************************************* 474327952Sdim * 475303231Sdim * FUNCTION: ApCheckPackageElements 476303231Sdim * 477303231Sdim * PARAMETERS: PredefinedName - Name of the predefined object 478303231Sdim * Op - Parser op for the package 479321369Sdim * Type1 - Object type for first group 480321369Sdim * Count1 - Count for first group 481303231Sdim * Type2 - Object type for second group 482303231Sdim * Count2 - Count for second group 483303231Sdim * 484303231Sdim * RETURN: Next Op peer in the parse tree, after all specified elements 485303231Sdim * have been validated. Used for multiple validations (calls 486321369Sdim * to this function). 487303231Sdim * 488303231Sdim * DESCRIPTION: Validate all elements of a package. Works with packages that 489303231Sdim * are defined to contain up to two groups of different object 490327952Sdim * types. 491303231Sdim * 492303231Sdim ******************************************************************************/ 493327952Sdim 494327952Sdimstatic ACPI_PARSE_OBJECT * 495314564SdimApCheckPackageElements ( 496314564Sdim const char *PredefinedName, 497314564Sdim ACPI_PARSE_OBJECT *Op, 498321369Sdim UINT8 Type1, 499314564Sdim UINT32 Count1, 500314564Sdim UINT8 Type2, 501314564Sdim UINT32 Count2) 502321369Sdim{ 503314564Sdim UINT32 i; 504303231Sdim 505327952Sdim 506314564Sdim /* 507303231Sdim * Up to two groups of package elements are supported by the data 508303231Sdim * structure. All elements in each group must be of the same type. 509327952Sdim * The second group can have a count of zero. 510303231Sdim * 511303231Sdim * Aborts check upon a NULL package element, as this means (at compile 512303231Sdim * time) that the remainder of the package elements are also NULL 513303231Sdim * (This is the only way to create NULL package elements.) 514341825Sdim */ 515303231Sdim for (i = 0; (i < Count1) && Op; i++) 516360784Sdim { 517327952Sdim ApCheckObjectType (PredefinedName, Op, Type1, i); 518303231Sdim Op = Op->Asl.Next; 519321369Sdim } 520303231Sdim 521327952Sdim for (i = 0; (i < Count2) && Op; i++) 522314564Sdim { 523314564Sdim ApCheckObjectType (PredefinedName, Op, Type2, (i + Count1)); 524314564Sdim Op = Op->Asl.Next; 525360784Sdim } 526360784Sdim 527360784Sdim return (Op); 528360784Sdim} 529360784Sdim 530360784Sdim 531360784Sdim/******************************************************************************* 532303231Sdim * 533321369Sdim * FUNCTION: ApCheckPackageList 534321369Sdim * 535321369Sdim * PARAMETERS: PredefinedName - Name of the predefined object 536327952Sdim * ParentOp - Parser op of the parent package 537303231Sdim * Package - Package info for this predefined name 538314564Sdim * StartIndex - Index in parent package where list begins 539314564Sdim * ParentCount - Element count of parent package 540314564Sdim * 541327952Sdim * RETURN: None 542327952Sdim * 543360784Sdim * DESCRIPTION: Validate the individual package elements for a predefined name. 544303231Sdim * Handles the cases where the predefined name is defined as a 545314564Sdim * Package of Packages (subpackages). These are the types: 546327952Sdim * 547303231Sdim * ACPI_PTYPE2 548327952Sdim * ACPI_PTYPE2_FIXED 549303231Sdim * ACPI_PTYPE2_MIN 550303231Sdim * ACPI_PTYPE2_COUNT 551303231Sdim * ACPI_PTYPE2_FIX_VAR 552344779Sdim * ACPI_PTYPE2_VAR_VAR 553303231Sdim * 554327952Sdim ******************************************************************************/ 555327952Sdim 556327952Sdimstatic void 557327952SdimApCheckPackageList ( 558327952Sdim const char *PredefinedName, 559327952Sdim ACPI_PARSE_OBJECT *ParentOp, 560327952Sdim const ACPI_PREDEFINED_INFO *Package, 561327952Sdim UINT32 StartIndex, 562327952Sdim UINT32 ParentCount) 563314564Sdim{ 564303231Sdim ACPI_PARSE_OBJECT *SubPackageOp = ParentOp; 565303231Sdim ACPI_PARSE_OBJECT *Op; 566327952Sdim ACPI_STATUS Status; 567303231Sdim UINT32 Count; 568303231Sdim UINT32 ExpectedCount; 569303231Sdim UINT32 i; 570303231Sdim UINT32 j; 571303231Sdim 572303231Sdim 573327952Sdim /* 574327952Sdim * Validate each subpackage in the parent Package 575327952Sdim * 576327952Sdim * Note: We ignore NULL package elements on the assumption that 577327952Sdim * they will be initialized by the BIOS or other ASL code. 578327952Sdim */ 579327952Sdim for (i = 0; (i < ParentCount) && SubPackageOp; i++) 580303231Sdim { 581303231Sdim /* Each object in the list must be of type Package */ 582303231Sdim 583303231Sdim Status = ApCheckObjectType (PredefinedName, SubPackageOp, 584303231Sdim ACPI_RTYPE_PACKAGE, i + StartIndex); 585327952Sdim if (ACPI_FAILURE (Status)) 586303231Sdim { 587303231Sdim goto NextSubpackage; 588303231Sdim } 589303231Sdim 590303231Sdim /* Examine the different types of expected subpackages */ 591303231Sdim 592327952Sdim Op = SubPackageOp->Asl.Child; 593303231Sdim 594327952Sdim /* First child is the package length */ 595327952Sdim 596327952Sdim Count = (UINT32) Op->Asl.Value.Integer; 597327952Sdim Op = Op->Asl.Next; 598327952Sdim 599303231Sdim /* 600327952Sdim * Most subpackage must have at least one element, with 601327952Sdim * only rare exceptions. (_RDI) 602327952Sdim */ 603327952Sdim if (!Count && 604327952Sdim (Package->RetInfo.Type != ACPI_PTYPE2_VAR_VAR)) 605327952Sdim { 606327952Sdim ApZeroLengthPackage (PredefinedName, SubPackageOp); 607327952Sdim goto NextSubpackage; 608303231Sdim } 609327952Sdim 610327952Sdim /* 611327952Sdim * Decode the package type. 612327952Sdim * PTYPE2 indicates that a "package of packages" is expected for 613327952Sdim * this name. The various flavors of PTYPE2 indicate the number 614327952Sdim * and format of the subpackages. 615327952Sdim */ 616327952Sdim switch (Package->RetInfo.Type) 617327952Sdim { 618327952Sdim case ACPI_PTYPE2: 619327952Sdim case ACPI_PTYPE2_PKG_COUNT: 620327952Sdim case ACPI_PTYPE2_REV_FIXED: 621327952Sdim 622327952Sdim /* Each subpackage has a fixed number of elements */ 623327952Sdim 624327952Sdim ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 625327952Sdim if (Count < ExpectedCount) 626327952Sdim { 627327952Sdim ApPackageTooSmall (PredefinedName, SubPackageOp, 628327952Sdim Count, ExpectedCount); 629303231Sdim break; 630303231Sdim } 631327952Sdim if (Count > ExpectedCount) 632327952Sdim { 633327952Sdim ApPackageTooLarge (PredefinedName, SubPackageOp, 634327952Sdim Count, ExpectedCount); 635327952Sdim break; 636327952Sdim } 637327952Sdim 638327952Sdim ApCheckPackageElements (PredefinedName, Op, 639327952Sdim Package->RetInfo.ObjectType1, Package->RetInfo.Count1, 640327952Sdim Package->RetInfo.ObjectType2, Package->RetInfo.Count2); 641327952Sdim break; 642327952Sdim 643327952Sdim case ACPI_PTYPE2_FIX_VAR: 644327952Sdim /* 645327952Sdim * Each subpackage has a fixed number of elements and an 646327952Sdim * optional element 647327952Sdim */ 648327952Sdim ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 649327952Sdim if (Count < ExpectedCount) 650327952Sdim { 651327952Sdim ApPackageTooSmall (PredefinedName, SubPackageOp, 652327952Sdim Count, ExpectedCount); 653327952Sdim break; 654327952Sdim } 655327952Sdim 656327952Sdim ApCheckPackageElements (PredefinedName, Op, 657327952Sdim Package->RetInfo.ObjectType1, Package->RetInfo.Count1, 658327952Sdim Package->RetInfo.ObjectType2, 659327952Sdim Count - Package->RetInfo.Count1); 660327952Sdim break; 661327952Sdim 662327952Sdim case ACPI_PTYPE2_VAR_VAR: 663327952Sdim /* 664327952Sdim * Must have at least the minimum number elements. 665327952Sdim * A zero PkgCount means the number of elements is variable. 666327952Sdim */ 667327952Sdim ExpectedCount = Package->RetInfo4.PkgCount; 668327952Sdim if (ExpectedCount && (Count < ExpectedCount)) 669327952Sdim { 670327952Sdim ApPackageTooSmall (PredefinedName, SubPackageOp, 671327952Sdim Count, 1); 672327952Sdim break; 673327952Sdim } 674327952Sdim 675327952Sdim ApCheckPackageElements (PredefinedName, Op, 676327952Sdim Package->RetInfo4.SubObjectTypes, 677327952Sdim Package->RetInfo4.PkgCount, 678327952Sdim 0, 0); 679327952Sdim break; 680327952Sdim 681303231Sdim case ACPI_PTYPE2_FIXED: 682303231Sdim 683303231Sdim /* Each subpackage has a fixed length */ 684303231Sdim 685303231Sdim ExpectedCount = Package->RetInfo2.Count; 686303231Sdim if (Count < ExpectedCount) 687303231Sdim { 688303231Sdim ApPackageTooSmall (PredefinedName, SubPackageOp, 689303231Sdim Count, ExpectedCount); 690303231Sdim break; 691303231Sdim } 692303231Sdim if (Count > ExpectedCount) 693303231Sdim { 694303231Sdim ApPackageTooLarge (PredefinedName, SubPackageOp, 695303231Sdim Count, ExpectedCount); 696303231Sdim break; 697303231Sdim } 698303231Sdim 699303231Sdim /* Check each object/type combination */ 700321369Sdim 701303231Sdim for (j = 0; j < ExpectedCount; j++) 702303231Sdim { 703303231Sdim ApCheckObjectType (PredefinedName, Op, 704303231Sdim Package->RetInfo2.ObjectType[j], j); 705321369Sdim 706303231Sdim Op = Op->Asl.Next; 707303231Sdim } 708303231Sdim break; 709303231Sdim 710321369Sdim case ACPI_PTYPE2_MIN: 711303231Sdim 712303231Sdim /* Each subpackage has a variable but minimum length */ 713303231Sdim 714303231Sdim ExpectedCount = Package->RetInfo.Count1; 715303231Sdim if (Count < ExpectedCount) 716303231Sdim { 717303231Sdim ApPackageTooSmall (PredefinedName, SubPackageOp, 718303231Sdim Count, ExpectedCount); 719303231Sdim break; 720303231Sdim } 721303231Sdim 722303231Sdim /* Check the type of each subpackage element */ 723303231Sdim 724303231Sdim ApCheckPackageElements (PredefinedName, Op, 725303231Sdim Package->RetInfo.ObjectType1, Count, 0, 0); 726303231Sdim break; 727303231Sdim 728303231Sdim case ACPI_PTYPE2_COUNT: 729303231Sdim /* 730303231Sdim * First element is the (Integer) count of elements, including 731321369Sdim * the count field (the ACPI name is NumElements) 732303231Sdim */ 733303231Sdim Status = ApCheckObjectType (PredefinedName, Op, 734303231Sdim ACPI_RTYPE_INTEGER, 0); 735303231Sdim 736321369Sdim /* We must have an integer count from above (otherwise, use Count) */ 737303231Sdim 738303231Sdim if (ACPI_SUCCESS (Status)) 739303231Sdim { 740303231Sdim /* 741321369Sdim * Make sure package is large enough for the Count and is 742303231Sdim * is as large as the minimum size 743303231Sdim */ 744303231Sdim ExpectedCount = (UINT32) Op->Asl.Value.Integer; 745303231Sdim 746303231Sdim if (Count < ExpectedCount) 747303231Sdim { 748303231Sdim ApPackageTooSmall (PredefinedName, SubPackageOp, 749303231Sdim Count, ExpectedCount); 750303231Sdim break; 751303231Sdim } 752303231Sdim else if (Count > ExpectedCount) 753303231Sdim { 754303231Sdim ApPackageTooLarge (PredefinedName, SubPackageOp, 755303231Sdim Count, ExpectedCount); 756303231Sdim } 757303231Sdim 758303231Sdim /* Some names of this type have a minimum length */ 759321369Sdim 760303231Sdim if (Count < Package->RetInfo.Count1) 761303231Sdim { 762303231Sdim ExpectedCount = Package->RetInfo.Count1; 763321369Sdim ApPackageTooSmall (PredefinedName, SubPackageOp, 764303231Sdim Count, ExpectedCount); 765303231Sdim break; 766303231Sdim } 767321369Sdim 768303231Sdim Count = ExpectedCount; 769303231Sdim } 770303231Sdim 771303231Sdim /* Check the type of each subpackage element */ 772303231Sdim 773303231Sdim Op = Op->Asl.Next; 774303231Sdim ApCheckPackageElements (PredefinedName, Op, 775303231Sdim Package->RetInfo.ObjectType1, (Count - 1), 0, 0); 776303231Sdim break; 777303231Sdim 778303231Sdim default: 779303231Sdim break; 780303231Sdim } 781327952Sdim 782327952SdimNextSubpackage: 783327952Sdim SubPackageOp = SubPackageOp->Asl.Next; 784327952Sdim } 785303231Sdim} 786303231Sdim 787303231Sdim 788303231Sdim/******************************************************************************* 789321369Sdim * 790321369Sdim * FUNCTION: ApPackageTooSmall 791303231Sdim * 792303231Sdim * PARAMETERS: PredefinedName - Name of the predefined object 793303231Sdim * Op - Current parser op 794321369Sdim * Count - Actual package element count 795321369Sdim * ExpectedCount - Expected package element count 796303231Sdim * 797303231Sdim * RETURN: None 798303231Sdim * 799303231Sdim * DESCRIPTION: Issue error message for a package that is smaller than 800327952Sdim * required. 801303231Sdim * 802303231Sdim ******************************************************************************/ 803303231Sdim 804321369Sdimstatic void 805303231SdimApPackageTooSmall ( 806303231Sdim const char *PredefinedName, 807303231Sdim ACPI_PARSE_OBJECT *Op, 808303231Sdim UINT32 Count, 809303231Sdim UINT32 ExpectedCount) 810303231Sdim{ 811303231Sdim 812321369Sdim sprintf (MsgBuffer, "%s: length %u, required minimum is %u", 813303231Sdim PredefinedName, Count, ExpectedCount); 814303231Sdim 815303231Sdim AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer); 816303231Sdim} 817303231Sdim 818303231Sdim 819303231Sdim/******************************************************************************* 820303231Sdim * 821303231Sdim * FUNCTION: ApZeroLengthPackage 822303231Sdim * 823303231Sdim * PARAMETERS: PredefinedName - Name of the predefined object 824303231Sdim * Op - Current parser op 825303231Sdim * 826303231Sdim * RETURN: None 827303231Sdim * 828303231Sdim * DESCRIPTION: Issue error message for a zero-length package (a package that 829303231Sdim * is required to have a non-zero length). Variable length 830303231Sdim * packages seem to be allowed to have zero length, however. 831303231Sdim * Even if not allowed, BIOS code does it. 832321369Sdim * 833 ******************************************************************************/ 834 835static void 836ApZeroLengthPackage ( 837 const char *PredefinedName, 838 ACPI_PARSE_OBJECT *Op) 839{ 840 841 sprintf (MsgBuffer, "%s: length is zero", PredefinedName); 842 843 AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer); 844} 845 846 847/******************************************************************************* 848 * 849 * FUNCTION: ApPackageTooLarge 850 * 851 * PARAMETERS: PredefinedName - Name of the predefined object 852 * Op - Current parser op 853 * Count - Actual package element count 854 * ExpectedCount - Expected package element count 855 * 856 * RETURN: None 857 * 858 * DESCRIPTION: Issue a remark for a package that is larger than expected. 859 * 860 ******************************************************************************/ 861 862static void 863ApPackageTooLarge ( 864 const char *PredefinedName, 865 ACPI_PARSE_OBJECT *Op, 866 UINT32 Count, 867 UINT32 ExpectedCount) 868{ 869 870 sprintf (MsgBuffer, "%s: length is %u, only %u required", 871 PredefinedName, Count, ExpectedCount); 872 873 AslError (ASL_REMARK, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer); 874} 875