1246847Sjkim/****************************************************************************** 2246847Sjkim * 3246847Sjkim * Module Name: aslprepkg - support for ACPI predefined name package objects 4246847Sjkim * 5246847Sjkim *****************************************************************************/ 6246847Sjkim 7246847Sjkim/* 8306536Sjkim * 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 55306536Sjkimstatic 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 91306536Sjkimstatic void 92306536SjkimApCustomPackage ( 93306536Sjkim ACPI_PARSE_OBJECT *ParentOp, 94306536Sjkim const ACPI_PREDEFINED_INFO *Predefined); 95246847Sjkim 96306536Sjkim 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: 159284460Sjkim 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 { 176306536Sjkim case ACPI_PTYPE_CUSTOM: 177306536Sjkim 178306536Sjkim ApCustomPackage (ParentOp, Predefined); 179306536Sjkim break; 180306536Sjkim 181246847Sjkim case ACPI_PTYPE1_FIXED: 182246847Sjkim /* 183281075Sdim * 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 /* 208281075Sdim * 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 /* 221281075Sdim * 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 } 251306536Sjkim 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 266281075Sdim /* Examine the subpackages */ 267246847Sjkim 268246847Sjkim ApCheckPackageList (Predefined->Info.Name, Op, 269246847Sjkim Package, 1, Count); 270246847Sjkim break; 271246847Sjkim 272246847Sjkim case ACPI_PTYPE2_PKG_COUNT: 273246847Sjkim 274281075Sdim /* 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 298281075Sdim /* Examine the subpackages */ 299246847Sjkim 300246847Sjkim ApCheckPackageList (Predefined->Info.Name, Op, 301246847Sjkim Package, 1, Count); 302246847Sjkim break; 303246847Sjkim 304281075Sdim case ACPI_PTYPE2_UUID_PAIR: 305281075Sdim 306281075Sdim /* The package contains a variable list of UUID Buffer/Package pairs */ 307281075Sdim 308281075Sdim /* The length of the package must be even */ 309281075Sdim 310281075Sdim if (Count & 1) 311281075Sdim { 312281075Sdim sprintf (MsgBuffer, "%4.4s: Package length, %d, must be even.", 313281075Sdim Predefined->Info.Name, Count); 314281075Sdim 315281075Sdim AslError (ASL_ERROR, ASL_MSG_RESERVED_PACKAGE_LENGTH, 316281075Sdim ParentOp->Asl.Child, MsgBuffer); 317281075Sdim } 318281075Sdim 319281075Sdim /* Validate the alternating types */ 320281075Sdim 321281075Sdim for (i = 0; i < Count; ++i) 322281075Sdim { 323281075Sdim if (i & 1) 324281075Sdim { 325281075Sdim ApCheckObjectType (Predefined->Info.Name, Op, 326281075Sdim Package->RetInfo.ObjectType2, i); 327281075Sdim } 328281075Sdim else 329281075Sdim { 330281075Sdim ApCheckObjectType (Predefined->Info.Name, Op, 331281075Sdim Package->RetInfo.ObjectType1, i); 332281075Sdim } 333281075Sdim 334281075Sdim Op = Op->Asl.Next; 335281075Sdim } 336281075Sdim 337281075Sdim break; 338281075Sdim 339284460Sjkim case ACPI_PTYPE2_VAR_VAR: 340284460Sjkim 341284460Sjkim /* Check for minimum size (ints at beginning + 1 subpackage) */ 342284460Sjkim 343284460Sjkim ExpectedCount = Package->RetInfo4.Count1 + 1; 344284460Sjkim if (Count < ExpectedCount) 345284460Sjkim { 346284460Sjkim goto PackageTooSmall; 347284460Sjkim } 348284460Sjkim 349284460Sjkim /* Check the non-package elements at beginning of main package */ 350284460Sjkim 351284460Sjkim for (i = 0; i < Package->RetInfo4.Count1; ++i) 352284460Sjkim { 353284460Sjkim Status = ApCheckObjectType (Predefined->Info.Name, Op, 354284460Sjkim Package->RetInfo4.ObjectType1, i); 355284460Sjkim Op = Op->Asl.Next; 356284460Sjkim } 357284460Sjkim 358284460Sjkim /* Examine the variable-length list of subpackages */ 359284460Sjkim 360284460Sjkim ApCheckPackageList (Predefined->Info.Name, Op, 361284460Sjkim Package, Package->RetInfo4.Count1, Count); 362284460Sjkim 363284460Sjkim break; 364284460Sjkim 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 372281075Sdim * variable number of subpackages. 373246847Sjkim */ 374246847Sjkim 375281075Sdim /* 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 * 395306536Sjkim * FUNCTION: ApCustomPackage 396306536Sjkim * 397306536Sjkim * PARAMETERS: ParentOp - Parse op for the package 398306536Sjkim * Predefined - Pointer to package-specific info for 399306536Sjkim * the method 400306536Sjkim * 401306536Sjkim * RETURN: None 402306536Sjkim * 403306536Sjkim * DESCRIPTION: Validate packages that don't fit into the standard model and 404306536Sjkim * require custom code. 405306536Sjkim * 406306536Sjkim * NOTE: Currently used for the _BIX method only. When needed for two or more 407306536Sjkim * methods, probably a detect/dispatch mechanism will be required. 408306536Sjkim * 409306536Sjkim ******************************************************************************/ 410306536Sjkim 411306536Sjkimstatic void 412306536SjkimApCustomPackage ( 413306536Sjkim ACPI_PARSE_OBJECT *ParentOp, 414306536Sjkim const ACPI_PREDEFINED_INFO *Predefined) 415306536Sjkim{ 416306536Sjkim ACPI_PARSE_OBJECT *Op; 417306536Sjkim UINT32 Count; 418306536Sjkim UINT32 ExpectedCount; 419306536Sjkim UINT32 Version; 420306536Sjkim 421306536Sjkim 422306536Sjkim /* First child is the package length */ 423306536Sjkim 424306536Sjkim Op = ParentOp->Asl.Child; 425306536Sjkim Count = (UINT32) Op->Asl.Value.Integer; 426306536Sjkim 427306536Sjkim /* Get the version number, must be Integer */ 428306536Sjkim 429306536Sjkim Op = Op->Asl.Next; 430306536Sjkim Version = (UINT32) Op->Asl.Value.Integer; 431306536Sjkim if (Op->Asl.ParseOpcode != PARSEOP_INTEGER) 432306536Sjkim { 433306536Sjkim AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Op, MsgBuffer); 434306536Sjkim return; 435306536Sjkim } 436306536Sjkim 437306536Sjkim /* Validate count (# of elements) */ 438306536Sjkim 439306536Sjkim ExpectedCount = 21; /* Version 1 */ 440306536Sjkim if (Version == 0) 441306536Sjkim { 442306536Sjkim ExpectedCount = 20; /* Version 0 */ 443306536Sjkim } 444306536Sjkim 445306536Sjkim if (Count < ExpectedCount) 446306536Sjkim { 447306536Sjkim ApPackageTooSmall (Predefined->Info.Name, ParentOp, 448306536Sjkim Count, ExpectedCount); 449306536Sjkim return; 450306536Sjkim } 451306536Sjkim else if (Count > ExpectedCount) 452306536Sjkim { 453306536Sjkim ApPackageTooLarge (Predefined->Info.Name, ParentOp, 454306536Sjkim Count, ExpectedCount); 455306536Sjkim } 456306536Sjkim 457306536Sjkim /* Validate all elements of the package */ 458306536Sjkim 459306536Sjkim Op = ApCheckPackageElements (Predefined->Info.Name, Op, 460306536Sjkim ACPI_RTYPE_INTEGER, 16, 461306536Sjkim ACPI_RTYPE_STRING, 4); 462306536Sjkim 463306536Sjkim /* Version 1 has a single trailing integer */ 464306536Sjkim 465306536Sjkim if (Version > 0) 466306536Sjkim { 467306536Sjkim ApCheckPackageElements (Predefined->Info.Name, Op, 468306536Sjkim ACPI_RTYPE_INTEGER, 1, 0, 0); 469306536Sjkim } 470306536Sjkim} 471306536Sjkim 472306536Sjkim 473306536Sjkim/******************************************************************************* 474306536Sjkim * 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 * 484306536Sjkim * RETURN: Next Op peer in the parse tree, after all specified elements 485306536Sjkim * have been validated. Used for multiple validations (calls 486306536Sjkim * 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 494306536Sjkimstatic 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 } 526306536Sjkim 527306536Sjkim 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 552284460Sjkim * 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 599284460Sjkim /* 600284460Sjkim * Most subpackage must have at least one element, with 601284460Sjkim * only rare exceptions. (_RDI) 602284460Sjkim */ 603284460Sjkim if (!Count && 604284460Sjkim (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 } 631281075Sdim if (Count > ExpectedCount) 632281075Sdim { 633281075Sdim ApPackageTooLarge (PredefinedName, SubPackageOp, 634281075Sdim Count, ExpectedCount); 635281075Sdim break; 636281075Sdim } 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 662284460Sjkim case ACPI_PTYPE2_VAR_VAR: 663284460Sjkim /* 664284460Sjkim * Must have at least the minimum number elements. 665284460Sjkim * A zero PkgCount means the number of elements is variable. 666284460Sjkim */ 667284460Sjkim ExpectedCount = Package->RetInfo4.PkgCount; 668284460Sjkim if (ExpectedCount && (Count < ExpectedCount)) 669284460Sjkim { 670284460Sjkim ApPackageTooSmall (PredefinedName, SubPackageOp, 671284460Sjkim Count, 1); 672284460Sjkim break; 673284460Sjkim } 674284460Sjkim 675284460Sjkim ApCheckPackageElements (PredefinedName, Op, 676284460Sjkim Package->RetInfo4.SubObjectTypes, 677284460Sjkim Package->RetInfo4.PkgCount, 678284460Sjkim 0, 0); 679284460Sjkim break; 680284460Sjkim 681246847Sjkim case ACPI_PTYPE2_FIXED: 682246847Sjkim 683281075Sdim /* 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 } 692281075Sdim if (Count > ExpectedCount) 693281075Sdim { 694281075Sdim ApPackageTooLarge (PredefinedName, SubPackageOp, 695281075Sdim Count, ExpectedCount); 696281075Sdim break; 697281075Sdim } 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 712281075Sdim /* 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 722281075Sdim /* 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 771281075Sdim /* 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