1246847Sjkim/****************************************************************************** 2246847Sjkim * 3246847Sjkim * Module Name: aslprepkg - support for ACPI predefined name package objects 4246847Sjkim * 5246847Sjkim *****************************************************************************/ 6246847Sjkim 7246847Sjkim/* 8298714Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 9246847Sjkim * All rights reserved. 10246847Sjkim * 11246847Sjkim * Redistribution and use in source and binary forms, with or without 12246847Sjkim * modification, are permitted provided that the following conditions 13246847Sjkim * are met: 14246847Sjkim * 1. Redistributions of source code must retain the above copyright 15246847Sjkim * notice, this list of conditions, and the following disclaimer, 16246847Sjkim * without modification. 17246847Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18246847Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19246847Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20246847Sjkim * including a substantially similar Disclaimer requirement for further 21246847Sjkim * binary redistribution. 22246847Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23246847Sjkim * of any contributors may be used to endorse or promote products derived 24246847Sjkim * from this software without specific prior written permission. 25246847Sjkim * 26246847Sjkim * Alternatively, this software may be distributed under the terms of the 27246847Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28246847Sjkim * Software Foundation. 29246847Sjkim * 30246847Sjkim * NO WARRANTY 31246847Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32246847Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33246847Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34246847Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35246847Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36246847Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37246847Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38246847Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39246847Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40246847Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41246847Sjkim * POSSIBILITY OF SUCH DAMAGES. 42246847Sjkim */ 43246847Sjkim 44246849Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 45246847Sjkim#include "aslcompiler.y.h" 46246849Sjkim#include <contrib/dev/acpica/include/acpredef.h> 47246847Sjkim 48246847Sjkim 49246847Sjkim#define _COMPONENT ACPI_COMPILER 50246847Sjkim ACPI_MODULE_NAME ("aslprepkg") 51246847Sjkim 52246847Sjkim 53246847Sjkim/* Local prototypes */ 54246847Sjkim 55298714Sjkimstatic ACPI_PARSE_OBJECT * 56246847SjkimApCheckPackageElements ( 57249663Sjkim const char *PredefinedName, 58249663Sjkim ACPI_PARSE_OBJECT *Op, 59249663Sjkim UINT8 Type1, 60249663Sjkim UINT32 Count1, 61249663Sjkim UINT8 Type2, 62249663Sjkim UINT32 Count2); 63246847Sjkim 64246847Sjkimstatic void 65246847SjkimApCheckPackageList ( 66246847Sjkim const char *PredefinedName, 67246847Sjkim ACPI_PARSE_OBJECT *ParentOp, 68246847Sjkim const ACPI_PREDEFINED_INFO *Package, 69246847Sjkim UINT32 StartIndex, 70246847Sjkim UINT32 Count); 71246847Sjkim 72246847Sjkimstatic void 73246847SjkimApPackageTooSmall ( 74246847Sjkim const char *PredefinedName, 75246847Sjkim ACPI_PARSE_OBJECT *Op, 76246847Sjkim UINT32 Count, 77246847Sjkim UINT32 ExpectedCount); 78246847Sjkim 79246847Sjkimstatic void 80246847SjkimApZeroLengthPackage ( 81246847Sjkim const char *PredefinedName, 82246847Sjkim ACPI_PARSE_OBJECT *Op); 83246847Sjkim 84246847Sjkimstatic void 85246847SjkimApPackageTooLarge ( 86246847Sjkim const char *PredefinedName, 87246847Sjkim ACPI_PARSE_OBJECT *Op, 88246847Sjkim UINT32 Count, 89246847Sjkim UINT32 ExpectedCount); 90246847Sjkim 91298714Sjkimstatic void 92298714SjkimApCustomPackage ( 93298714Sjkim ACPI_PARSE_OBJECT *ParentOp, 94298714Sjkim const ACPI_PREDEFINED_INFO *Predefined); 95246847Sjkim 96298714Sjkim 97246847Sjkim/******************************************************************************* 98246847Sjkim * 99246847Sjkim * FUNCTION: ApCheckPackage 100246847Sjkim * 101249663Sjkim * PARAMETERS: ParentOp - Parser op for the package 102249663Sjkim * Predefined - Pointer to package-specific info for 103249663Sjkim * the method 104246847Sjkim * 105246847Sjkim * RETURN: None 106246847Sjkim * 107246847Sjkim * DESCRIPTION: Top-level validation for predefined name return package 108246847Sjkim * objects. 109246847Sjkim * 110246847Sjkim ******************************************************************************/ 111246847Sjkim 112246847Sjkimvoid 113246847SjkimApCheckPackage ( 114246847Sjkim ACPI_PARSE_OBJECT *ParentOp, 115246847Sjkim const ACPI_PREDEFINED_INFO *Predefined) 116246847Sjkim{ 117246847Sjkim ACPI_PARSE_OBJECT *Op; 118246847Sjkim const ACPI_PREDEFINED_INFO *Package; 119246847Sjkim ACPI_STATUS Status; 120246847Sjkim UINT32 ExpectedCount; 121246847Sjkim UINT32 Count; 122246847Sjkim UINT32 i; 123246847Sjkim 124246847Sjkim 125246847Sjkim /* The package info for this name is in the next table entry */ 126246847Sjkim 127246847Sjkim Package = Predefined + 1; 128246847Sjkim 129246847Sjkim /* First child is the package length */ 130246847Sjkim 131246847Sjkim Op = ParentOp->Asl.Child; 132246847Sjkim Count = (UINT32) Op->Asl.Value.Integer; 133246847Sjkim 134246847Sjkim /* 135249112Sjkim * Many of the variable-length top-level packages are allowed to simply 136249112Sjkim * have zero elements. This allows the BIOS to tell the host that even 137249112Sjkim * though the predefined name/method exists, the feature is not supported. 138249112Sjkim * Other package types require one or more elements. In any case, there 139249112Sjkim * is no need to continue validation. 140246847Sjkim */ 141246847Sjkim if (!Count) 142246847Sjkim { 143249112Sjkim switch (Package->RetInfo.Type) 144246847Sjkim { 145249112Sjkim case ACPI_PTYPE1_FIXED: 146249112Sjkim case ACPI_PTYPE1_OPTION: 147249112Sjkim case ACPI_PTYPE2_PKG_COUNT: 148249112Sjkim case ACPI_PTYPE2_REV_FIXED: 149249112Sjkim 150246847Sjkim ApZeroLengthPackage (Predefined->Info.Name, ParentOp); 151249112Sjkim break; 152249112Sjkim 153249112Sjkim case ACPI_PTYPE1_VAR: 154249112Sjkim case ACPI_PTYPE2: 155249112Sjkim case ACPI_PTYPE2_COUNT: 156249112Sjkim case ACPI_PTYPE2_FIXED: 157249112Sjkim case ACPI_PTYPE2_MIN: 158249112Sjkim case ACPI_PTYPE2_FIX_VAR: 159283092Sjkim case ACPI_PTYPE2_VAR_VAR: 160249112Sjkim default: 161249112Sjkim 162249112Sjkim break; 163246847Sjkim } 164249112Sjkim 165246847Sjkim return; 166246847Sjkim } 167246847Sjkim 168246847Sjkim /* Get the first element of the package */ 169246847Sjkim 170246847Sjkim Op = Op->Asl.Next; 171246847Sjkim 172246847Sjkim /* Decode the package type */ 173246847Sjkim 174246847Sjkim switch (Package->RetInfo.Type) 175246847Sjkim { 176298714Sjkim case ACPI_PTYPE_CUSTOM: 177298714Sjkim 178298714Sjkim ApCustomPackage (ParentOp, Predefined); 179298714Sjkim break; 180298714Sjkim 181246847Sjkim case ACPI_PTYPE1_FIXED: 182246847Sjkim /* 183272444Sjkim * The package count is fixed and there are no subpackages 184246847Sjkim * 185246847Sjkim * If package is too small, exit. 186246847Sjkim * If package is larger than expected, issue warning but continue 187246847Sjkim */ 188246847Sjkim ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 189246847Sjkim if (Count < ExpectedCount) 190246847Sjkim { 191246847Sjkim goto PackageTooSmall; 192246847Sjkim } 193246847Sjkim else if (Count > ExpectedCount) 194246847Sjkim { 195246847Sjkim ApPackageTooLarge (Predefined->Info.Name, ParentOp, 196246847Sjkim Count, ExpectedCount); 197246847Sjkim } 198246847Sjkim 199246847Sjkim /* Validate all elements of the package */ 200246847Sjkim 201246847Sjkim ApCheckPackageElements (Predefined->Info.Name, Op, 202246847Sjkim Package->RetInfo.ObjectType1, Package->RetInfo.Count1, 203246847Sjkim Package->RetInfo.ObjectType2, Package->RetInfo.Count2); 204246847Sjkim break; 205246847Sjkim 206246847Sjkim case ACPI_PTYPE1_VAR: 207246847Sjkim /* 208272444Sjkim * The package count is variable, there are no subpackages, 209249663Sjkim * and all elements must be of the same type 210246847Sjkim */ 211246847Sjkim for (i = 0; i < Count; i++) 212246847Sjkim { 213246847Sjkim ApCheckObjectType (Predefined->Info.Name, Op, 214246847Sjkim Package->RetInfo.ObjectType1, i); 215246847Sjkim Op = Op->Asl.Next; 216246847Sjkim } 217246847Sjkim break; 218246847Sjkim 219246847Sjkim case ACPI_PTYPE1_OPTION: 220246847Sjkim /* 221272444Sjkim * The package count is variable, there are no subpackages. 222249663Sjkim * There are a fixed number of required elements, and a variable 223249663Sjkim * number of optional elements. 224246847Sjkim * 225246847Sjkim * Check if package is at least as large as the minimum required 226246847Sjkim */ 227246847Sjkim ExpectedCount = Package->RetInfo3.Count; 228246847Sjkim if (Count < ExpectedCount) 229246847Sjkim { 230246847Sjkim goto PackageTooSmall; 231246847Sjkim } 232246847Sjkim 233246847Sjkim /* Variable number of sub-objects */ 234246847Sjkim 235246847Sjkim for (i = 0; i < Count; i++) 236246847Sjkim { 237246847Sjkim if (i < Package->RetInfo3.Count) 238246847Sjkim { 239246847Sjkim /* These are the required package elements (0, 1, or 2) */ 240246847Sjkim 241246847Sjkim ApCheckObjectType (Predefined->Info.Name, Op, 242246847Sjkim Package->RetInfo3.ObjectType[i], i); 243246847Sjkim } 244246847Sjkim else 245246847Sjkim { 246246847Sjkim /* These are the optional package elements */ 247246847Sjkim 248246847Sjkim ApCheckObjectType (Predefined->Info.Name, Op, 249246847Sjkim Package->RetInfo3.TailObjectType, i); 250246847Sjkim } 251298714Sjkim 252246847Sjkim Op = Op->Asl.Next; 253246847Sjkim } 254246847Sjkim break; 255246847Sjkim 256246847Sjkim case ACPI_PTYPE2_REV_FIXED: 257246847Sjkim 258246847Sjkim /* First element is the (Integer) revision */ 259246847Sjkim 260246847Sjkim ApCheckObjectType (Predefined->Info.Name, Op, 261246847Sjkim ACPI_RTYPE_INTEGER, 0); 262246847Sjkim 263246847Sjkim Op = Op->Asl.Next; 264246847Sjkim Count--; 265246847Sjkim 266272444Sjkim /* Examine the subpackages */ 267246847Sjkim 268246847Sjkim ApCheckPackageList (Predefined->Info.Name, Op, 269246847Sjkim Package, 1, Count); 270246847Sjkim break; 271246847Sjkim 272246847Sjkim case ACPI_PTYPE2_PKG_COUNT: 273246847Sjkim 274272444Sjkim /* First element is the (Integer) count of subpackages to follow */ 275246847Sjkim 276246847Sjkim Status = ApCheckObjectType (Predefined->Info.Name, Op, 277246847Sjkim ACPI_RTYPE_INTEGER, 0); 278246847Sjkim 279246847Sjkim /* We must have an integer count from above (otherwise, use Count) */ 280246847Sjkim 281246847Sjkim if (ACPI_SUCCESS (Status)) 282246847Sjkim { 283246847Sjkim /* 284249663Sjkim * Count cannot be larger than the parent package length, but 285249663Sjkim * allow it to be smaller. The >= accounts for the Integer above. 286246847Sjkim */ 287246847Sjkim ExpectedCount = (UINT32) Op->Asl.Value.Integer; 288246847Sjkim if (ExpectedCount >= Count) 289246847Sjkim { 290246847Sjkim goto PackageTooSmall; 291246847Sjkim } 292246847Sjkim 293246847Sjkim Count = ExpectedCount; 294246847Sjkim } 295246847Sjkim 296246847Sjkim Op = Op->Asl.Next; 297246847Sjkim 298272444Sjkim /* Examine the subpackages */ 299246847Sjkim 300246847Sjkim ApCheckPackageList (Predefined->Info.Name, Op, 301246847Sjkim Package, 1, Count); 302246847Sjkim break; 303246847Sjkim 304272444Sjkim case ACPI_PTYPE2_UUID_PAIR: 305272444Sjkim 306272444Sjkim /* The package contains a variable list of UUID Buffer/Package pairs */ 307272444Sjkim 308272444Sjkim /* The length of the package must be even */ 309272444Sjkim 310272444Sjkim if (Count & 1) 311272444Sjkim { 312272444Sjkim sprintf (MsgBuffer, "%4.4s: Package length, %d, must be even.", 313272444Sjkim Predefined->Info.Name, Count); 314272444Sjkim 315272444Sjkim AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, 316272444Sjkim ParentOp->Asl.Child, MsgBuffer); 317272444Sjkim } 318272444Sjkim 319272444Sjkim /* Validate the alternating types */ 320272444Sjkim 321272444Sjkim for (i = 0; i < Count; ++i) 322272444Sjkim { 323272444Sjkim if (i & 1) 324272444Sjkim { 325272444Sjkim ApCheckObjectType (Predefined->Info.Name, Op, 326272444Sjkim Package->RetInfo.ObjectType2, i); 327272444Sjkim } 328272444Sjkim else 329272444Sjkim { 330272444Sjkim ApCheckObjectType (Predefined->Info.Name, Op, 331272444Sjkim Package->RetInfo.ObjectType1, i); 332272444Sjkim } 333272444Sjkim 334272444Sjkim Op = Op->Asl.Next; 335272444Sjkim } 336272444Sjkim 337272444Sjkim break; 338272444Sjkim 339283092Sjkim case ACPI_PTYPE2_VAR_VAR: 340283092Sjkim 341283092Sjkim /* Check for minimum size (ints at beginning + 1 subpackage) */ 342283092Sjkim 343283092Sjkim ExpectedCount = Package->RetInfo4.Count1 + 1; 344283092Sjkim if (Count < ExpectedCount) 345283092Sjkim { 346283092Sjkim goto PackageTooSmall; 347283092Sjkim } 348283092Sjkim 349283092Sjkim /* Check the non-package elements at beginning of main package */ 350283092Sjkim 351283092Sjkim for (i = 0; i < Package->RetInfo4.Count1; ++i) 352283092Sjkim { 353283092Sjkim Status = ApCheckObjectType (Predefined->Info.Name, Op, 354283092Sjkim Package->RetInfo4.ObjectType1, i); 355283092Sjkim Op = Op->Asl.Next; 356283092Sjkim } 357283092Sjkim 358283092Sjkim /* Examine the variable-length list of subpackages */ 359283092Sjkim 360283092Sjkim ApCheckPackageList (Predefined->Info.Name, Op, 361283092Sjkim Package, Package->RetInfo4.Count1, Count); 362283092Sjkim 363283092Sjkim break; 364283092Sjkim 365246847Sjkim case ACPI_PTYPE2: 366246847Sjkim case ACPI_PTYPE2_FIXED: 367246847Sjkim case ACPI_PTYPE2_MIN: 368246847Sjkim case ACPI_PTYPE2_COUNT: 369246847Sjkim case ACPI_PTYPE2_FIX_VAR: 370246847Sjkim /* 371246847Sjkim * These types all return a single Package that consists of a 372272444Sjkim * variable number of subpackages. 373246847Sjkim */ 374246847Sjkim 375272444Sjkim /* Examine the subpackages */ 376246847Sjkim 377246847Sjkim ApCheckPackageList (Predefined->Info.Name, Op, 378246847Sjkim Package, 0, Count); 379246847Sjkim break; 380246847Sjkim 381246847Sjkim default: 382246847Sjkim return; 383246847Sjkim } 384246847Sjkim 385246847Sjkim return; 386246847Sjkim 387246847SjkimPackageTooSmall: 388246847Sjkim ApPackageTooSmall (Predefined->Info.Name, ParentOp, 389246847Sjkim Count, ExpectedCount); 390246847Sjkim} 391246847Sjkim 392246847Sjkim 393246847Sjkim/******************************************************************************* 394246847Sjkim * 395298714Sjkim * FUNCTION: ApCustomPackage 396298714Sjkim * 397298714Sjkim * PARAMETERS: ParentOp - Parse op for the package 398298714Sjkim * Predefined - Pointer to package-specific info for 399298714Sjkim * the method 400298714Sjkim * 401298714Sjkim * RETURN: None 402298714Sjkim * 403298714Sjkim * DESCRIPTION: Validate packages that don't fit into the standard model and 404298714Sjkim * require custom code. 405298714Sjkim * 406298714Sjkim * NOTE: Currently used for the _BIX method only. When needed for two or more 407298714Sjkim * methods, probably a detect/dispatch mechanism will be required. 408298714Sjkim * 409298714Sjkim ******************************************************************************/ 410298714Sjkim 411298714Sjkimstatic void 412298714SjkimApCustomPackage ( 413298714Sjkim ACPI_PARSE_OBJECT *ParentOp, 414298714Sjkim const ACPI_PREDEFINED_INFO *Predefined) 415298714Sjkim{ 416298714Sjkim ACPI_PARSE_OBJECT *Op; 417298714Sjkim UINT32 Count; 418298714Sjkim UINT32 ExpectedCount; 419298714Sjkim UINT32 Version; 420298714Sjkim 421298714Sjkim 422298714Sjkim /* First child is the package length */ 423298714Sjkim 424298714Sjkim Op = ParentOp->Asl.Child; 425298714Sjkim Count = (UINT32) Op->Asl.Value.Integer; 426298714Sjkim 427298714Sjkim /* Get the version number, must be Integer */ 428298714Sjkim 429298714Sjkim Op = Op->Asl.Next; 430298714Sjkim Version = (UINT32) Op->Asl.Value.Integer; 431298714Sjkim if (Op->Asl.ParseOpcode != PARSEOP_INTEGER) 432298714Sjkim { 433298714Sjkim AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Op, MsgBuffer); 434298714Sjkim return; 435298714Sjkim } 436298714Sjkim 437298714Sjkim /* Validate count (# of elements) */ 438298714Sjkim 439298714Sjkim ExpectedCount = 21; /* Version 1 */ 440298714Sjkim if (Version == 0) 441298714Sjkim { 442298714Sjkim ExpectedCount = 20; /* Version 0 */ 443298714Sjkim } 444298714Sjkim 445298714Sjkim if (Count < ExpectedCount) 446298714Sjkim { 447298714Sjkim ApPackageTooSmall (Predefined->Info.Name, ParentOp, 448298714Sjkim Count, ExpectedCount); 449298714Sjkim return; 450298714Sjkim } 451298714Sjkim else if (Count > ExpectedCount) 452298714Sjkim { 453298714Sjkim ApPackageTooLarge (Predefined->Info.Name, ParentOp, 454298714Sjkim Count, ExpectedCount); 455298714Sjkim } 456298714Sjkim 457298714Sjkim /* Validate all elements of the package */ 458298714Sjkim 459298714Sjkim Op = ApCheckPackageElements (Predefined->Info.Name, Op, 460298714Sjkim ACPI_RTYPE_INTEGER, 16, 461298714Sjkim ACPI_RTYPE_STRING, 4); 462298714Sjkim 463298714Sjkim /* Version 1 has a single trailing integer */ 464298714Sjkim 465298714Sjkim if (Version > 0) 466298714Sjkim { 467298714Sjkim ApCheckPackageElements (Predefined->Info.Name, Op, 468298714Sjkim ACPI_RTYPE_INTEGER, 1, 0, 0); 469298714Sjkim } 470298714Sjkim} 471298714Sjkim 472298714Sjkim 473298714Sjkim/******************************************************************************* 474298714Sjkim * 475246847Sjkim * FUNCTION: ApCheckPackageElements 476246847Sjkim * 477249663Sjkim * PARAMETERS: PredefinedName - Name of the predefined object 478249663Sjkim * Op - Parser op for the package 479249663Sjkim * Type1 - Object type for first group 480249663Sjkim * Count1 - Count for first group 481249663Sjkim * Type2 - Object type for second group 482249663Sjkim * Count2 - Count for second group 483246847Sjkim * 484298714Sjkim * RETURN: Next Op peer in the parse tree, after all specified elements 485298714Sjkim * have been validated. Used for multiple validations (calls 486298714Sjkim * to this function). 487246847Sjkim * 488246847Sjkim * DESCRIPTION: Validate all elements of a package. Works with packages that 489246847Sjkim * are defined to contain up to two groups of different object 490246847Sjkim * types. 491246847Sjkim * 492246847Sjkim ******************************************************************************/ 493246847Sjkim 494298714Sjkimstatic ACPI_PARSE_OBJECT * 495246847SjkimApCheckPackageElements ( 496246847Sjkim const char *PredefinedName, 497246847Sjkim ACPI_PARSE_OBJECT *Op, 498246847Sjkim UINT8 Type1, 499246847Sjkim UINT32 Count1, 500246847Sjkim UINT8 Type2, 501246847Sjkim UINT32 Count2) 502246847Sjkim{ 503246847Sjkim UINT32 i; 504246847Sjkim 505246847Sjkim 506246847Sjkim /* 507246847Sjkim * Up to two groups of package elements are supported by the data 508246847Sjkim * structure. All elements in each group must be of the same type. 509246847Sjkim * The second group can have a count of zero. 510246847Sjkim * 511246847Sjkim * Aborts check upon a NULL package element, as this means (at compile 512246847Sjkim * time) that the remainder of the package elements are also NULL 513246847Sjkim * (This is the only way to create NULL package elements.) 514246847Sjkim */ 515246847Sjkim for (i = 0; (i < Count1) && Op; i++) 516246847Sjkim { 517246847Sjkim ApCheckObjectType (PredefinedName, Op, Type1, i); 518246847Sjkim Op = Op->Asl.Next; 519246847Sjkim } 520246847Sjkim 521246847Sjkim for (i = 0; (i < Count2) && Op; i++) 522246847Sjkim { 523246847Sjkim ApCheckObjectType (PredefinedName, Op, Type2, (i + Count1)); 524246847Sjkim Op = Op->Asl.Next; 525246847Sjkim } 526298714Sjkim 527298714Sjkim return (Op); 528246847Sjkim} 529246847Sjkim 530246847Sjkim 531246847Sjkim/******************************************************************************* 532246847Sjkim * 533246847Sjkim * FUNCTION: ApCheckPackageList 534246847Sjkim * 535246847Sjkim * PARAMETERS: PredefinedName - Name of the predefined object 536246847Sjkim * ParentOp - Parser op of the parent package 537246847Sjkim * Package - Package info for this predefined name 538246847Sjkim * StartIndex - Index in parent package where list begins 539246847Sjkim * ParentCount - Element count of parent package 540246847Sjkim * 541246847Sjkim * RETURN: None 542246847Sjkim * 543246847Sjkim * DESCRIPTION: Validate the individual package elements for a predefined name. 544246847Sjkim * Handles the cases where the predefined name is defined as a 545246847Sjkim * Package of Packages (subpackages). These are the types: 546246847Sjkim * 547246847Sjkim * ACPI_PTYPE2 548246847Sjkim * ACPI_PTYPE2_FIXED 549246847Sjkim * ACPI_PTYPE2_MIN 550246847Sjkim * ACPI_PTYPE2_COUNT 551246847Sjkim * ACPI_PTYPE2_FIX_VAR 552283092Sjkim * ACPI_PTYPE2_VAR_VAR 553246847Sjkim * 554246847Sjkim ******************************************************************************/ 555246847Sjkim 556246847Sjkimstatic void 557246847SjkimApCheckPackageList ( 558246847Sjkim const char *PredefinedName, 559246847Sjkim ACPI_PARSE_OBJECT *ParentOp, 560246847Sjkim const ACPI_PREDEFINED_INFO *Package, 561246847Sjkim UINT32 StartIndex, 562246847Sjkim UINT32 ParentCount) 563246847Sjkim{ 564246847Sjkim ACPI_PARSE_OBJECT *SubPackageOp = ParentOp; 565246847Sjkim ACPI_PARSE_OBJECT *Op; 566246847Sjkim ACPI_STATUS Status; 567246847Sjkim UINT32 Count; 568246847Sjkim UINT32 ExpectedCount; 569246847Sjkim UINT32 i; 570246847Sjkim UINT32 j; 571246847Sjkim 572246847Sjkim 573246847Sjkim /* 574246847Sjkim * Validate each subpackage in the parent Package 575246847Sjkim * 576246847Sjkim * Note: We ignore NULL package elements on the assumption that 577246847Sjkim * they will be initialized by the BIOS or other ASL code. 578246847Sjkim */ 579246847Sjkim for (i = 0; (i < ParentCount) && SubPackageOp; i++) 580246847Sjkim { 581246847Sjkim /* Each object in the list must be of type Package */ 582246847Sjkim 583246847Sjkim Status = ApCheckObjectType (PredefinedName, SubPackageOp, 584246847Sjkim ACPI_RTYPE_PACKAGE, i + StartIndex); 585246847Sjkim if (ACPI_FAILURE (Status)) 586246847Sjkim { 587246847Sjkim goto NextSubpackage; 588246847Sjkim } 589246847Sjkim 590246847Sjkim /* Examine the different types of expected subpackages */ 591246847Sjkim 592246847Sjkim Op = SubPackageOp->Asl.Child; 593246847Sjkim 594246847Sjkim /* First child is the package length */ 595246847Sjkim 596246847Sjkim Count = (UINT32) Op->Asl.Value.Integer; 597246847Sjkim Op = Op->Asl.Next; 598246847Sjkim 599283092Sjkim /* 600283092Sjkim * Most subpackage must have at least one element, with 601283092Sjkim * only rare exceptions. (_RDI) 602283092Sjkim */ 603283092Sjkim if (!Count && 604283092Sjkim (Package->RetInfo.Type != ACPI_PTYPE2_VAR_VAR)) 605246847Sjkim { 606246847Sjkim ApZeroLengthPackage (PredefinedName, SubPackageOp); 607246847Sjkim goto NextSubpackage; 608246847Sjkim } 609246847Sjkim 610246847Sjkim /* 611246847Sjkim * Decode the package type. 612246847Sjkim * PTYPE2 indicates that a "package of packages" is expected for 613246847Sjkim * this name. The various flavors of PTYPE2 indicate the number 614246847Sjkim * and format of the subpackages. 615246847Sjkim */ 616246847Sjkim switch (Package->RetInfo.Type) 617246847Sjkim { 618246847Sjkim case ACPI_PTYPE2: 619246847Sjkim case ACPI_PTYPE2_PKG_COUNT: 620246847Sjkim case ACPI_PTYPE2_REV_FIXED: 621246847Sjkim 622246847Sjkim /* Each subpackage has a fixed number of elements */ 623246847Sjkim 624246847Sjkim ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 625246847Sjkim if (Count < ExpectedCount) 626246847Sjkim { 627246847Sjkim ApPackageTooSmall (PredefinedName, SubPackageOp, 628246847Sjkim Count, ExpectedCount); 629246847Sjkim break; 630246847Sjkim } 631272444Sjkim if (Count > ExpectedCount) 632272444Sjkim { 633272444Sjkim ApPackageTooLarge (PredefinedName, SubPackageOp, 634272444Sjkim Count, ExpectedCount); 635272444Sjkim break; 636272444Sjkim } 637246847Sjkim 638246847Sjkim ApCheckPackageElements (PredefinedName, Op, 639246847Sjkim Package->RetInfo.ObjectType1, Package->RetInfo.Count1, 640246847Sjkim Package->RetInfo.ObjectType2, Package->RetInfo.Count2); 641246847Sjkim break; 642246847Sjkim 643246847Sjkim case ACPI_PTYPE2_FIX_VAR: 644246847Sjkim /* 645246847Sjkim * Each subpackage has a fixed number of elements and an 646246847Sjkim * optional element 647246847Sjkim */ 648246847Sjkim ExpectedCount = Package->RetInfo.Count1 + Package->RetInfo.Count2; 649246847Sjkim if (Count < ExpectedCount) 650246847Sjkim { 651246847Sjkim ApPackageTooSmall (PredefinedName, SubPackageOp, 652246847Sjkim Count, ExpectedCount); 653246847Sjkim break; 654246847Sjkim } 655246847Sjkim 656246847Sjkim ApCheckPackageElements (PredefinedName, Op, 657246847Sjkim Package->RetInfo.ObjectType1, Package->RetInfo.Count1, 658246847Sjkim Package->RetInfo.ObjectType2, 659246847Sjkim Count - Package->RetInfo.Count1); 660246847Sjkim break; 661246847Sjkim 662283092Sjkim case ACPI_PTYPE2_VAR_VAR: 663283092Sjkim /* 664283092Sjkim * Must have at least the minimum number elements. 665283092Sjkim * A zero PkgCount means the number of elements is variable. 666283092Sjkim */ 667283092Sjkim ExpectedCount = Package->RetInfo4.PkgCount; 668283092Sjkim if (ExpectedCount && (Count < ExpectedCount)) 669283092Sjkim { 670283092Sjkim ApPackageTooSmall (PredefinedName, SubPackageOp, 671283092Sjkim Count, 1); 672283092Sjkim break; 673283092Sjkim } 674283092Sjkim 675283092Sjkim ApCheckPackageElements (PredefinedName, Op, 676283092Sjkim Package->RetInfo4.SubObjectTypes, 677283092Sjkim Package->RetInfo4.PkgCount, 678283092Sjkim 0, 0); 679283092Sjkim break; 680283092Sjkim 681246847Sjkim case ACPI_PTYPE2_FIXED: 682246847Sjkim 683272444Sjkim /* Each subpackage has a fixed length */ 684246847Sjkim 685246847Sjkim ExpectedCount = Package->RetInfo2.Count; 686246847Sjkim if (Count < ExpectedCount) 687246847Sjkim { 688246847Sjkim ApPackageTooSmall (PredefinedName, SubPackageOp, 689246847Sjkim Count, ExpectedCount); 690246847Sjkim break; 691246847Sjkim } 692272444Sjkim if (Count > ExpectedCount) 693272444Sjkim { 694272444Sjkim ApPackageTooLarge (PredefinedName, SubPackageOp, 695272444Sjkim Count, ExpectedCount); 696272444Sjkim break; 697272444Sjkim } 698246847Sjkim 699246847Sjkim /* Check each object/type combination */ 700246847Sjkim 701246847Sjkim for (j = 0; j < ExpectedCount; j++) 702246847Sjkim { 703246847Sjkim ApCheckObjectType (PredefinedName, Op, 704246847Sjkim Package->RetInfo2.ObjectType[j], j); 705246847Sjkim 706246847Sjkim Op = Op->Asl.Next; 707246847Sjkim } 708246847Sjkim break; 709246847Sjkim 710246847Sjkim case ACPI_PTYPE2_MIN: 711246847Sjkim 712272444Sjkim /* Each subpackage has a variable but minimum length */ 713246847Sjkim 714246847Sjkim ExpectedCount = Package->RetInfo.Count1; 715246847Sjkim if (Count < ExpectedCount) 716246847Sjkim { 717246847Sjkim ApPackageTooSmall (PredefinedName, SubPackageOp, 718246847Sjkim Count, ExpectedCount); 719246847Sjkim break; 720246847Sjkim } 721246847Sjkim 722272444Sjkim /* Check the type of each subpackage element */ 723246847Sjkim 724246847Sjkim ApCheckPackageElements (PredefinedName, Op, 725246847Sjkim Package->RetInfo.ObjectType1, Count, 0, 0); 726246847Sjkim break; 727246847Sjkim 728246847Sjkim case ACPI_PTYPE2_COUNT: 729246847Sjkim /* 730246847Sjkim * First element is the (Integer) count of elements, including 731246847Sjkim * the count field (the ACPI name is NumElements) 732246847Sjkim */ 733246847Sjkim Status = ApCheckObjectType (PredefinedName, Op, 734246847Sjkim ACPI_RTYPE_INTEGER, 0); 735246847Sjkim 736246847Sjkim /* We must have an integer count from above (otherwise, use Count) */ 737246847Sjkim 738246847Sjkim if (ACPI_SUCCESS (Status)) 739246847Sjkim { 740246847Sjkim /* 741246847Sjkim * Make sure package is large enough for the Count and is 742246847Sjkim * is as large as the minimum size 743246847Sjkim */ 744246847Sjkim ExpectedCount = (UINT32) Op->Asl.Value.Integer; 745246847Sjkim 746246847Sjkim if (Count < ExpectedCount) 747246847Sjkim { 748246847Sjkim ApPackageTooSmall (PredefinedName, SubPackageOp, 749246847Sjkim Count, ExpectedCount); 750246847Sjkim break; 751246847Sjkim } 752246847Sjkim else if (Count > ExpectedCount) 753246847Sjkim { 754246847Sjkim ApPackageTooLarge (PredefinedName, SubPackageOp, 755246847Sjkim Count, ExpectedCount); 756246847Sjkim } 757246847Sjkim 758246847Sjkim /* Some names of this type have a minimum length */ 759246847Sjkim 760246847Sjkim if (Count < Package->RetInfo.Count1) 761246847Sjkim { 762246847Sjkim ExpectedCount = Package->RetInfo.Count1; 763246847Sjkim ApPackageTooSmall (PredefinedName, SubPackageOp, 764246847Sjkim Count, ExpectedCount); 765246847Sjkim break; 766246847Sjkim } 767246847Sjkim 768246847Sjkim Count = ExpectedCount; 769246847Sjkim } 770246847Sjkim 771272444Sjkim /* Check the type of each subpackage element */ 772246847Sjkim 773246847Sjkim Op = Op->Asl.Next; 774246847Sjkim ApCheckPackageElements (PredefinedName, Op, 775246847Sjkim Package->RetInfo.ObjectType1, (Count - 1), 0, 0); 776246847Sjkim break; 777246847Sjkim 778246847Sjkim default: 779246847Sjkim break; 780246847Sjkim } 781246847Sjkim 782246847SjkimNextSubpackage: 783246847Sjkim SubPackageOp = SubPackageOp->Asl.Next; 784246847Sjkim } 785246847Sjkim} 786246847Sjkim 787246847Sjkim 788246847Sjkim/******************************************************************************* 789246847Sjkim * 790246847Sjkim * FUNCTION: ApPackageTooSmall 791246847Sjkim * 792246847Sjkim * PARAMETERS: PredefinedName - Name of the predefined object 793246847Sjkim * Op - Current parser op 794246847Sjkim * Count - Actual package element count 795246847Sjkim * ExpectedCount - Expected package element count 796246847Sjkim * 797246847Sjkim * RETURN: None 798246847Sjkim * 799246847Sjkim * DESCRIPTION: Issue error message for a package that is smaller than 800246847Sjkim * required. 801246847Sjkim * 802246847Sjkim ******************************************************************************/ 803246847Sjkim 804246847Sjkimstatic void 805246847SjkimApPackageTooSmall ( 806246847Sjkim const char *PredefinedName, 807246847Sjkim ACPI_PARSE_OBJECT *Op, 808246847Sjkim UINT32 Count, 809246847Sjkim UINT32 ExpectedCount) 810246847Sjkim{ 811246847Sjkim 812246847Sjkim sprintf (MsgBuffer, "%s: length %u, required minimum is %u", 813246847Sjkim PredefinedName, Count, ExpectedCount); 814246847Sjkim 815246847Sjkim AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer); 816246847Sjkim} 817246847Sjkim 818246847Sjkim 819246847Sjkim/******************************************************************************* 820246847Sjkim * 821246847Sjkim * FUNCTION: ApZeroLengthPackage 822246847Sjkim * 823246847Sjkim * PARAMETERS: PredefinedName - Name of the predefined object 824246847Sjkim * Op - Current parser op 825246847Sjkim * 826246847Sjkim * RETURN: None 827246847Sjkim * 828246847Sjkim * DESCRIPTION: Issue error message for a zero-length package (a package that 829246847Sjkim * is required to have a non-zero length). Variable length 830246847Sjkim * packages seem to be allowed to have zero length, however. 831246847Sjkim * Even if not allowed, BIOS code does it. 832246847Sjkim * 833246847Sjkim ******************************************************************************/ 834246847Sjkim 835246847Sjkimstatic void 836246847SjkimApZeroLengthPackage ( 837246847Sjkim const char *PredefinedName, 838246847Sjkim ACPI_PARSE_OBJECT *Op) 839246847Sjkim{ 840246847Sjkim 841246847Sjkim sprintf (MsgBuffer, "%s: length is zero", PredefinedName); 842246847Sjkim 843246847Sjkim AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer); 844246847Sjkim} 845246847Sjkim 846246847Sjkim 847246847Sjkim/******************************************************************************* 848246847Sjkim * 849246847Sjkim * FUNCTION: ApPackageTooLarge 850246847Sjkim * 851246847Sjkim * PARAMETERS: PredefinedName - Name of the predefined object 852246847Sjkim * Op - Current parser op 853246847Sjkim * Count - Actual package element count 854246847Sjkim * ExpectedCount - Expected package element count 855246847Sjkim * 856246847Sjkim * RETURN: None 857246847Sjkim * 858246847Sjkim * DESCRIPTION: Issue a remark for a package that is larger than expected. 859246847Sjkim * 860246847Sjkim ******************************************************************************/ 861246847Sjkim 862246847Sjkimstatic void 863246847SjkimApPackageTooLarge ( 864246847Sjkim const char *PredefinedName, 865246847Sjkim ACPI_PARSE_OBJECT *Op, 866246847Sjkim UINT32 Count, 867246847Sjkim UINT32 ExpectedCount) 868246847Sjkim{ 869246847Sjkim 870246847Sjkim sprintf (MsgBuffer, "%s: length is %u, only %u required", 871246847Sjkim PredefinedName, Count, ExpectedCount); 872246847Sjkim 873246847Sjkim AslError (ASL_REMARK, ASL_MSG_RESERVED_PACKAGE_LENGTH, Op, MsgBuffer); 874246847Sjkim} 875