asllength.c revision 245582
1145557Sharti/****************************************************************************** 2145557Sharti * 3145557Sharti * Module Name: asllength - Tree walk to determine package and opcode lengths 4145557Sharti * 5145557Sharti *****************************************************************************/ 6145557Sharti 7145557Sharti/* 8145557Sharti * Copyright (C) 2000 - 2013, Intel Corp. 9145557Sharti * All rights reserved. 10145557Sharti * 11145557Sharti * Redistribution and use in source and binary forms, with or without 12145557Sharti * modification, are permitted provided that the following conditions 13145557Sharti * are met: 14145557Sharti * 1. Redistributions of source code must retain the above copyright 15145557Sharti * notice, this list of conditions, and the following disclaimer, 16145557Sharti * without modification. 17145557Sharti * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18145557Sharti * substantially similar to the "NO WARRANTY" disclaimer below 19145557Sharti * ("Disclaimer") and any redistribution must be conditioned upon 20145557Sharti * including a substantially similar Disclaimer requirement for further 21145557Sharti * binary redistribution. 22145557Sharti * 3. Neither the names of the above-listed copyright holders nor the names 23145557Sharti * of any contributors may be used to endorse or promote products derived 24145557Sharti * from this software without specific prior written permission. 25145557Sharti * 26145557Sharti * Alternatively, this software may be distributed under the terms of the 27145557Sharti * GNU General Public License ("GPL") version 2 as published by the Free 28145557Sharti * Software Foundation. 29145557Sharti * 30156066Sharti * NO WARRANTY 31145557Sharti * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32145557Sharti * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33145557Sharti * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34145557Sharti * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35145557Sharti * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36145557Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37145557Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38145557Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39145557Sharti * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40145557Sharti * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41145557Sharti * POSSIBILITY OF SUCH DAMAGES. 42145557Sharti */ 43150920Sharti 44145557Sharti 45150920Sharti#include <contrib/dev/acpica/compiler/aslcompiler.h> 46150920Sharti#include "aslcompiler.y.h" 47150920Sharti#include <contrib/dev/acpica/include/amlcode.h> 48145557Sharti 49145557Sharti 50145557Sharti#define _COMPONENT ACPI_COMPILER 51145557Sharti ACPI_MODULE_NAME ("asllength") 52145557Sharti 53145557Sharti/* Local prototypes */ 54156066Sharti 55145557Shartistatic UINT8 56145557ShartiCgGetPackageLenByteCount ( 57145557Sharti ACPI_PARSE_OBJECT *Op, 58145557Sharti UINT32 PackageLength); 59145557Sharti 60145557Shartistatic void 61145557ShartiCgGenerateAmlOpcodeLength ( 62145557Sharti ACPI_PARSE_OBJECT *Op); 63145557Sharti 64145557Sharti 65145557Sharti#ifdef ACPI_OBSOLETE_FUNCTIONS 66145557Shartivoid 67145557ShartiLnAdjustLengthToRoot ( 68145557Sharti ACPI_PARSE_OBJECT *Op, 69145557Sharti UINT32 LengthDelta); 70145557Sharti#endif 71145557Sharti 72145557Sharti 73145557Sharti/******************************************************************************* 74145557Sharti * 75145557Sharti * FUNCTION: LnInitLengthsWalk 76145557Sharti * 77145557Sharti * PARAMETERS: ASL_WALK_CALLBACK 78145557Sharti * 79145557Sharti * RETURN: Status 80145557Sharti * 81145557Sharti * DESCRIPTION: Walk callback to initialize (and re-initialize) the node 82145557Sharti * subtree length(s) to zero. The Subtree lengths are bubbled 83145557Sharti * up to the root node in order to get a total AML length. 84145557Sharti * 85145557Sharti ******************************************************************************/ 86145557Sharti 87146525ShartiACPI_STATUS 88145557ShartiLnInitLengthsWalk ( 89145557Sharti ACPI_PARSE_OBJECT *Op, 90145557Sharti UINT32 Level, 91145557Sharti void *Context) 92145557Sharti{ 93145557Sharti 94145557Sharti Op->Asl.AmlSubtreeLength = 0; 95145557Sharti return (AE_OK); 96145557Sharti} 97145557Sharti 98145557Sharti 99145557Sharti/******************************************************************************* 100145557Sharti * 101145557Sharti * FUNCTION: LnPackageLengthWalk 102145557Sharti * 103145557Sharti * PARAMETERS: ASL_WALK_CALLBACK 104145557Sharti * 105145557Sharti * RETURN: Status 106145557Sharti * 107145557Sharti * DESCRIPTION: Walk callback to calculate the total AML length. 108145557Sharti * 1) Calculate the AML lengths (opcode, package length, etc.) for 109145557Sharti * THIS node. 110145557Sharti * 2) Bubbble up all of these lengths to the parent node by summing 111145557Sharti * them all into the parent subtree length. 112145557Sharti * 113145557Sharti * Note: The SubtreeLength represents the total AML length of all child nodes 114145557Sharti * in all subtrees under a given node. Therefore, once this walk is 115146525Sharti * complete, the Root Node subtree length is the AML length of the entire 116145557Sharti * tree (and thus, the entire ACPI table) 117145557Sharti * 118145557Sharti ******************************************************************************/ 119145557Sharti 120145557ShartiACPI_STATUS 121145557ShartiLnPackageLengthWalk ( 122145557Sharti ACPI_PARSE_OBJECT *Op, 123145557Sharti UINT32 Level, 124145557Sharti void *Context) 125145557Sharti{ 126145557Sharti 127145557Sharti /* Generate the AML lengths for this node */ 128145557Sharti 129145557Sharti CgGenerateAmlLengths (Op); 130145557Sharti 131145557Sharti /* Bubble up all lengths (this node and all below it) to the parent */ 132145557Sharti 133145557Sharti if ((Op->Asl.Parent) && 134145557Sharti (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 135145557Sharti { 136145557Sharti Op->Asl.Parent->Asl.AmlSubtreeLength += (Op->Asl.AmlLength + 137145557Sharti Op->Asl.AmlOpcodeLength + 138145557Sharti Op->Asl.AmlPkgLenBytes + 139145557Sharti Op->Asl.AmlSubtreeLength); 140145557Sharti } 141145557Sharti return (AE_OK); 142145557Sharti} 143145557Sharti 144145557Sharti 145145557Sharti/******************************************************************************* 146145557Sharti * 147145557Sharti * FUNCTION: CgGetPackageLenByteCount 148145557Sharti * 149145557Sharti * PARAMETERS: Op - Parse node 150145557Sharti * PackageLength - Length to be encoded 151145557Sharti * 152145557Sharti * RETURN: Required length of the package length encoding 153145557Sharti * 154145557Sharti * DESCRIPTION: Calculate the number of bytes required to encode the given 155145557Sharti * package length. 156145557Sharti * 157145557Sharti ******************************************************************************/ 158145557Sharti 159145557Shartistatic UINT8 160145557ShartiCgGetPackageLenByteCount ( 161145557Sharti ACPI_PARSE_OBJECT *Op, 162145557Sharti UINT32 PackageLength) 163145557Sharti{ 164145557Sharti 165145557Sharti /* 166145557Sharti * Determine the number of bytes required to encode the package length 167145557Sharti * Note: the package length includes the number of bytes used to encode 168145557Sharti * the package length, so we must account for this also. 169145557Sharti */ 170145557Sharti if (PackageLength <= (0x0000003F - 1)) 171145557Sharti { 172145557Sharti return (1); 173145557Sharti } 174145557Sharti else if (PackageLength <= (0x00000FFF - 2)) 175145557Sharti { 176145557Sharti return (2); 177145557Sharti } 178145557Sharti else if (PackageLength <= (0x000FFFFF - 3)) 179145557Sharti { 180145557Sharti return (3); 181150920Sharti } 182145557Sharti else if (PackageLength <= (0x0FFFFFFF - 4)) 183145557Sharti { 184145557Sharti return (4); 185145557Sharti } 186145557Sharti else 187145557Sharti { 188145557Sharti /* Fatal error - the package length is too large to encode */ 189145557Sharti 190145557Sharti AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, Op, NULL); 191145557Sharti } 192145557Sharti 193145557Sharti return (0); 194145557Sharti} 195145557Sharti 196145557Sharti 197145557Sharti/******************************************************************************* 198145557Sharti * 199145557Sharti * FUNCTION: CgGenerateAmlOpcodeLength 200145557Sharti * 201145557Sharti * PARAMETERS: Op - Parse node whose AML opcode lengths will be 202145557Sharti * calculated 203145557Sharti * 204145557Sharti * RETURN: None. 205145557Sharti * 206145557Sharti * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength 207145557Sharti * fields for this node. 208145557Sharti * 209145557Sharti ******************************************************************************/ 210145557Sharti 211145557Shartistatic void 212145557ShartiCgGenerateAmlOpcodeLength ( 213145557Sharti ACPI_PARSE_OBJECT *Op) 214145557Sharti{ 215145557Sharti 216145557Sharti /* Check for two-byte opcode */ 217145557Sharti 218145557Sharti if (Op->Asl.AmlOpcode > 0x00FF) 219145557Sharti { 220145557Sharti Op->Asl.AmlOpcodeLength = 2; 221145557Sharti } 222145557Sharti else 223145557Sharti { 224145557Sharti Op->Asl.AmlOpcodeLength = 1; 225145557Sharti } 226145557Sharti 227145557Sharti /* Does this opcode have an associated "PackageLength" field? */ 228145557Sharti 229145557Sharti Op->Asl.AmlPkgLenBytes = 0; 230145557Sharti if (Op->Asl.CompileFlags & NODE_AML_PACKAGE) 231145557Sharti { 232145557Sharti Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount ( 233145557Sharti Op, Op->Asl.AmlSubtreeLength); 234145557Sharti } 235145557Sharti 236145557Sharti /* Data opcode lengths are easy */ 237145557Sharti 238145557Sharti switch (Op->Asl.AmlOpcode) 239145557Sharti { 240145557Sharti case AML_BYTE_OP: 241145557Sharti 242145557Sharti Op->Asl.AmlLength = 1; 243145557Sharti break; 244145557Sharti 245145557Sharti case AML_WORD_OP: 246145557Sharti 247145557Sharti Op->Asl.AmlLength = 2; 248145557Sharti break; 249145557Sharti 250145557Sharti case AML_DWORD_OP: 251145557Sharti 252145557Sharti Op->Asl.AmlLength = 4; 253145557Sharti break; 254145557Sharti 255145557Sharti case AML_QWORD_OP: 256145557Sharti 257145557Sharti Op->Asl.AmlLength = 8; 258145557Sharti break; 259145557Sharti 260145557Sharti default: 261145557Sharti /* All data opcodes must be above */ 262145557Sharti break; 263145557Sharti } 264145557Sharti} 265145557Sharti 266145557Sharti 267145557Sharti/******************************************************************************* 268145557Sharti * 269145557Sharti * FUNCTION: CgGenerateAmlLengths 270145557Sharti * 271145557Sharti * PARAMETERS: Op - Parse node 272145557Sharti * 273145557Sharti * RETURN: None. 274145557Sharti * 275145557Sharti * DESCRIPTION: Generate internal length fields based on the AML opcode or 276145557Sharti * parse opcode. 277145557Sharti * 278145557Sharti ******************************************************************************/ 279145557Sharti 280145557Shartivoid 281145557ShartiCgGenerateAmlLengths ( 282145557Sharti ACPI_PARSE_OBJECT *Op) 283145557Sharti{ 284145557Sharti char *Buffer; 285145557Sharti ACPI_STATUS Status; 286145557Sharti 287145557Sharti 288145557Sharti switch (Op->Asl.AmlOpcode) 289145557Sharti { 290145557Sharti case AML_RAW_DATA_BYTE: 291145557Sharti 292145557Sharti Op->Asl.AmlOpcodeLength = 0; 293145557Sharti Op->Asl.AmlLength = 1; 294145557Sharti return; 295145557Sharti 296145557Sharti case AML_RAW_DATA_WORD: 297145557Sharti 298145557Sharti Op->Asl.AmlOpcodeLength = 0; 299145557Sharti Op->Asl.AmlLength = 2; 300145557Sharti return; 301145557Sharti 302145557Sharti case AML_RAW_DATA_DWORD: 303145557Sharti 304145557Sharti Op->Asl.AmlOpcodeLength = 0; 305145557Sharti Op->Asl.AmlLength = 4; 306145557Sharti return; 307145557Sharti 308145557Sharti case AML_RAW_DATA_QWORD: 309145557Sharti 310145557Sharti Op->Asl.AmlOpcodeLength = 0; 311145557Sharti Op->Asl.AmlLength = 8; 312145557Sharti return; 313145557Sharti 314145557Sharti case AML_RAW_DATA_BUFFER: 315145557Sharti 316145557Sharti /* Aml length is/was set by creator */ 317145557Sharti 318145557Sharti Op->Asl.AmlOpcodeLength = 0; 319145557Sharti return; 320145557Sharti 321145557Sharti case AML_RAW_DATA_CHAIN: 322145557Sharti 323145557Sharti /* Aml length is/was set by creator */ 324145557Sharti 325145557Sharti Op->Asl.AmlOpcodeLength = 0; 326145557Sharti return; 327145557Sharti 328145557Sharti default: 329145557Sharti break; 330145557Sharti } 331145557Sharti 332145557Sharti switch (Op->Asl.ParseOpcode) 333145557Sharti { 334145557Sharti case PARSEOP_DEFINITIONBLOCK: 335145557Sharti 336145557Sharti Gbl_TableLength = sizeof (ACPI_TABLE_HEADER) + 337145557Sharti Op->Asl.AmlSubtreeLength; 338145557Sharti break; 339145557Sharti 340145557Sharti case PARSEOP_NAMESEG: 341145557Sharti 342145557Sharti Op->Asl.AmlOpcodeLength = 0; 343145557Sharti Op->Asl.AmlLength = 4; 344145557Sharti Op->Asl.ExternalName = Op->Asl.Value.String; 345145557Sharti break; 346145557Sharti 347145557Sharti case PARSEOP_NAMESTRING: 348145557Sharti case PARSEOP_METHODCALL: 349145557Sharti 350145557Sharti if (Op->Asl.CompileFlags & NODE_NAME_INTERNALIZED) 351145557Sharti { 352145557Sharti break; 353145557Sharti } 354145557Sharti 355145557Sharti Op->Asl.AmlOpcodeLength = 0; 356145557Sharti Status = UtInternalizeName (Op->Asl.Value.String, &Buffer); 357145557Sharti if (ACPI_FAILURE (Status)) 358145557Sharti { 359145557Sharti DbgPrint (ASL_DEBUG_OUTPUT, 360145557Sharti "Failure from internalize name %X\n", Status); 361145557Sharti break; 362145557Sharti } 363145557Sharti 364145557Sharti Op->Asl.ExternalName = Op->Asl.Value.String; 365145557Sharti Op->Asl.Value.String = Buffer; 366145557Sharti Op->Asl.CompileFlags |= NODE_NAME_INTERNALIZED; 367145557Sharti 368150920Sharti Op->Asl.AmlLength = strlen (Buffer); 369145557Sharti 370145557Sharti /* 371145557Sharti * Check for single backslash reference to root, 372145557Sharti * make it a null terminated string in the AML 373145557Sharti */ 374145557Sharti if (Op->Asl.AmlLength == 1) 375145557Sharti { 376145557Sharti Op->Asl.AmlLength = 2; 377145557Sharti } 378145557Sharti break; 379145557Sharti 380145557Sharti case PARSEOP_STRING_LITERAL: 381145557Sharti 382145557Sharti Op->Asl.AmlOpcodeLength = 1; 383145557Sharti 384145557Sharti /* Get null terminator */ 385145557Sharti 386145557Sharti Op->Asl.AmlLength = strlen (Op->Asl.Value.String) + 1; 387145557Sharti break; 388145557Sharti 389145557Sharti case PARSEOP_PACKAGE_LENGTH: 390145557Sharti 391145557Sharti Op->Asl.AmlOpcodeLength = 0; 392145557Sharti Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (Op, 393145557Sharti (UINT32) Op->Asl.Value.Integer); 394145557Sharti break; 395145557Sharti 396145557Sharti case PARSEOP_RAW_DATA: 397145557Sharti 398145557Sharti Op->Asl.AmlOpcodeLength = 0; 399145557Sharti break; 400145557Sharti 401145557Sharti case PARSEOP_DEFAULT_ARG: 402145557Sharti case PARSEOP_EXTERNAL: 403145557Sharti case PARSEOP_INCLUDE: 404145557Sharti case PARSEOP_INCLUDE_END: 405145557Sharti 406145557Sharti /* Ignore the "default arg" nodes, they are extraneous at this point */ 407145557Sharti 408145557Sharti break; 409145557Sharti 410145557Sharti default: 411145557Sharti 412145557Sharti CgGenerateAmlOpcodeLength (Op); 413145557Sharti break; 414145557Sharti } 415145557Sharti} 416145557Sharti 417145557Sharti 418145557Sharti#ifdef ACPI_OBSOLETE_FUNCTIONS 419145557Sharti/******************************************************************************* 420145557Sharti * 421145557Sharti * FUNCTION: LnAdjustLengthToRoot 422145557Sharti * 423145557Sharti * PARAMETERS: Op - Node whose Length was changed 424145557Sharti * 425145557Sharti * RETURN: None. 426145557Sharti * 427145557Sharti * DESCRIPTION: Change the Subtree length of the given node, and bubble the 428145557Sharti * change all the way up to the root node. This allows for 429145557Sharti * last second changes to a package length (for example, if the 430145557Sharti * package length encoding gets shorter or longer.) 431145557Sharti * 432145557Sharti ******************************************************************************/ 433145557Sharti 434145557Shartivoid 435145557ShartiLnAdjustLengthToRoot ( 436145557Sharti ACPI_PARSE_OBJECT *SubtreeOp, 437145557Sharti UINT32 LengthDelta) 438145557Sharti{ 439145557Sharti ACPI_PARSE_OBJECT *Op; 440150920Sharti 441145557Sharti 442145557Sharti /* Adjust all subtree lengths up to the root */ 443145557Sharti 444145557Sharti Op = SubtreeOp->Asl.Parent; 445145557Sharti while (Op) 446145557Sharti { 447145557Sharti Op->Asl.AmlSubtreeLength -= LengthDelta; 448145557Sharti Op = Op->Asl.Parent; 449145557Sharti } 450145557Sharti 451145557Sharti /* Adjust the global table length */ 452145557Sharti 453145557Sharti Gbl_TableLength -= LengthDelta; 454145557Sharti} 455145557Sharti#endif 456145557Sharti