asllength.c revision 217365
1118611Snjl 2118611Snjl/****************************************************************************** 3118611Snjl * 4118611Snjl * Module Name: asllength - Tree walk to determine package and opcode lengths 5118611Snjl * 6118611Snjl *****************************************************************************/ 7118611Snjl 8217365Sjkim/* 9217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp. 10118611Snjl * All rights reserved. 11118611Snjl * 12217365Sjkim * Redistribution and use in source and binary forms, with or without 13217365Sjkim * modification, are permitted provided that the following conditions 14217365Sjkim * are met: 15217365Sjkim * 1. Redistributions of source code must retain the above copyright 16217365Sjkim * notice, this list of conditions, and the following disclaimer, 17217365Sjkim * without modification. 18217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 20217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 21217365Sjkim * including a substantially similar Disclaimer requirement for further 22217365Sjkim * binary redistribution. 23217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 24217365Sjkim * of any contributors may be used to endorse or promote products derived 25217365Sjkim * from this software without specific prior written permission. 26118611Snjl * 27217365Sjkim * Alternatively, this software may be distributed under the terms of the 28217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 29217365Sjkim * Software Foundation. 30118611Snjl * 31217365Sjkim * NO WARRANTY 32217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 43217365Sjkim */ 44118611Snjl 45118611Snjl 46151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 47118611Snjl#include "aslcompiler.y.h" 48193529Sjkim#include <contrib/dev/acpica/include/amlcode.h> 49118611Snjl 50118611Snjl 51118611Snjl#define _COMPONENT ACPI_COMPILER 52118611Snjl ACPI_MODULE_NAME ("asllength") 53118611Snjl 54151937Sjkim/* Local prototypes */ 55118611Snjl 56151937Sjkimstatic UINT8 57151937SjkimCgGetPackageLenByteCount ( 58151937Sjkim ACPI_PARSE_OBJECT *Op, 59151937Sjkim UINT32 PackageLength); 60151937Sjkim 61151937Sjkimstatic void 62151937SjkimCgGenerateAmlOpcodeLength ( 63151937Sjkim ACPI_PARSE_OBJECT *Op); 64151937Sjkim 65151937Sjkim 66151937Sjkim#ifdef ACPI_OBSOLETE_FUNCTIONS 67151937Sjkimvoid 68151937SjkimLnAdjustLengthToRoot ( 69151937Sjkim ACPI_PARSE_OBJECT *Op, 70151937Sjkim UINT32 LengthDelta); 71151937Sjkim#endif 72151937Sjkim 73151937Sjkim 74118611Snjl/******************************************************************************* 75118611Snjl * 76118611Snjl * FUNCTION: LnInitLengthsWalk 77118611Snjl * 78118611Snjl * PARAMETERS: ASL_WALK_CALLBACK 79118611Snjl * 80118611Snjl * RETURN: Status 81118611Snjl * 82118611Snjl * DESCRIPTION: Walk callback to initialize (and re-initialize) the node 83118611Snjl * subtree length(s) to zero. The Subtree lengths are bubbled 84118611Snjl * up to the root node in order to get a total AML length. 85118611Snjl * 86118611Snjl ******************************************************************************/ 87118611Snjl 88118611SnjlACPI_STATUS 89118611SnjlLnInitLengthsWalk ( 90118611Snjl ACPI_PARSE_OBJECT *Op, 91118611Snjl UINT32 Level, 92118611Snjl void *Context) 93118611Snjl{ 94118611Snjl 95118611Snjl Op->Asl.AmlSubtreeLength = 0; 96118611Snjl return (AE_OK); 97118611Snjl} 98118611Snjl 99118611Snjl 100118611Snjl/******************************************************************************* 101118611Snjl * 102118611Snjl * FUNCTION: LnPackageLengthWalk 103118611Snjl * 104118611Snjl * PARAMETERS: ASL_WALK_CALLBACK 105118611Snjl * 106118611Snjl * RETURN: Status 107118611Snjl * 108118611Snjl * DESCRIPTION: Walk callback to calculate the total AML length. 109118611Snjl * 1) Calculate the AML lengths (opcode, package length, etc.) for 110118611Snjl * THIS node. 111118611Snjl * 2) Bubbble up all of these lengths to the parent node by summing 112118611Snjl * them all into the parent subtree length. 113118611Snjl * 114118611Snjl * Note: The SubtreeLength represents the total AML length of all child nodes 115118611Snjl * in all subtrees under a given node. Therefore, once this walk is 116118611Snjl * complete, the Root Node subtree length is the AML length of the entire 117118611Snjl * tree (and thus, the entire ACPI table) 118118611Snjl * 119118611Snjl ******************************************************************************/ 120118611Snjl 121118611SnjlACPI_STATUS 122118611SnjlLnPackageLengthWalk ( 123118611Snjl ACPI_PARSE_OBJECT *Op, 124118611Snjl UINT32 Level, 125118611Snjl void *Context) 126118611Snjl{ 127118611Snjl 128118611Snjl /* Generate the AML lengths for this node */ 129118611Snjl 130118611Snjl CgGenerateAmlLengths (Op); 131118611Snjl 132118611Snjl /* Bubble up all lengths (this node and all below it) to the parent */ 133118611Snjl 134118611Snjl if ((Op->Asl.Parent) && 135118611Snjl (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 136118611Snjl { 137118611Snjl Op->Asl.Parent->Asl.AmlSubtreeLength += (Op->Asl.AmlLength + 138118611Snjl Op->Asl.AmlOpcodeLength + 139118611Snjl Op->Asl.AmlPkgLenBytes + 140118611Snjl Op->Asl.AmlSubtreeLength); 141118611Snjl } 142118611Snjl return (AE_OK); 143118611Snjl} 144118611Snjl 145118611Snjl 146118611Snjl/******************************************************************************* 147118611Snjl * 148118611Snjl * FUNCTION: CgGetPackageLenByteCount 149118611Snjl * 150151937Sjkim * PARAMETERS: Op - Parse node 151118611Snjl * PackageLength - Length to be encoded 152118611Snjl * 153118611Snjl * RETURN: Required length of the package length encoding 154118611Snjl * 155118611Snjl * DESCRIPTION: Calculate the number of bytes required to encode the given 156118611Snjl * package length. 157118611Snjl * 158118611Snjl ******************************************************************************/ 159118611Snjl 160151937Sjkimstatic UINT8 161118611SnjlCgGetPackageLenByteCount ( 162118611Snjl ACPI_PARSE_OBJECT *Op, 163118611Snjl UINT32 PackageLength) 164118611Snjl{ 165118611Snjl 166118611Snjl /* 167118611Snjl * Determine the number of bytes required to encode the package length 168118611Snjl * Note: the package length includes the number of bytes used to encode 169118611Snjl * the package length, so we must account for this also. 170118611Snjl */ 171118611Snjl if (PackageLength <= (0x0000003F - 1)) 172118611Snjl { 173118611Snjl return (1); 174118611Snjl } 175118611Snjl else if (PackageLength <= (0x00000FFF - 2)) 176118611Snjl { 177118611Snjl return (2); 178118611Snjl } 179118611Snjl else if (PackageLength <= (0x000FFFFF - 3)) 180118611Snjl { 181118611Snjl return (3); 182118611Snjl } 183118611Snjl else if (PackageLength <= (0x0FFFFFFF - 4)) 184118611Snjl { 185118611Snjl return (4); 186118611Snjl } 187118611Snjl else 188118611Snjl { 189118611Snjl /* Fatal error - the package length is too large to encode */ 190118611Snjl 191118611Snjl AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, Op, NULL); 192118611Snjl } 193118611Snjl 194118611Snjl return (0); 195118611Snjl} 196118611Snjl 197118611Snjl 198118611Snjl/******************************************************************************* 199118611Snjl * 200118611Snjl * FUNCTION: CgGenerateAmlOpcodeLength 201118611Snjl * 202151937Sjkim * PARAMETERS: Op - Parse node whose AML opcode lengths will be 203118611Snjl * calculated 204118611Snjl * 205118611Snjl * RETURN: None. 206118611Snjl * 207118611Snjl * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength 208118611Snjl * fields for this node. 209118611Snjl * 210118611Snjl ******************************************************************************/ 211118611Snjl 212151937Sjkimstatic void 213118611SnjlCgGenerateAmlOpcodeLength ( 214118611Snjl ACPI_PARSE_OBJECT *Op) 215118611Snjl{ 216118611Snjl 217118611Snjl /* Check for two-byte opcode */ 218118611Snjl 219118611Snjl if (Op->Asl.AmlOpcode > 0x00FF) 220118611Snjl { 221118611Snjl Op->Asl.AmlOpcodeLength = 2; 222118611Snjl } 223118611Snjl else 224118611Snjl { 225118611Snjl Op->Asl.AmlOpcodeLength = 1; 226118611Snjl } 227118611Snjl 228118611Snjl /* Does this opcode have an associated "PackageLength" field? */ 229118611Snjl 230118611Snjl Op->Asl.AmlPkgLenBytes = 0; 231118611Snjl if (Op->Asl.CompileFlags & NODE_AML_PACKAGE) 232118611Snjl { 233151937Sjkim Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount ( 234151937Sjkim Op, Op->Asl.AmlSubtreeLength); 235118611Snjl } 236118611Snjl 237118611Snjl /* Data opcode lengths are easy */ 238118611Snjl 239118611Snjl switch (Op->Asl.AmlOpcode) 240118611Snjl { 241118611Snjl case AML_BYTE_OP: 242118611Snjl 243118611Snjl Op->Asl.AmlLength = 1; 244118611Snjl break; 245118611Snjl 246118611Snjl case AML_WORD_OP: 247118611Snjl 248118611Snjl Op->Asl.AmlLength = 2; 249118611Snjl break; 250118611Snjl 251118611Snjl case AML_DWORD_OP: 252118611Snjl 253118611Snjl Op->Asl.AmlLength = 4; 254118611Snjl break; 255118611Snjl 256118611Snjl case AML_QWORD_OP: 257118611Snjl 258118611Snjl Op->Asl.AmlLength = 8; 259118611Snjl break; 260118611Snjl 261118611Snjl default: 262118611Snjl /* All data opcodes must be above */ 263118611Snjl break; 264118611Snjl } 265118611Snjl} 266118611Snjl 267118611Snjl 268118611Snjl/******************************************************************************* 269118611Snjl * 270118611Snjl * FUNCTION: CgGenerateAmlLengths 271118611Snjl * 272118611Snjl * PARAMETERS: Op - Parse node 273118611Snjl * 274118611Snjl * RETURN: None. 275118611Snjl * 276118611Snjl * DESCRIPTION: Generate internal length fields based on the AML opcode or 277118611Snjl * parse opcode. 278118611Snjl * 279118611Snjl ******************************************************************************/ 280118611Snjl 281118611Snjlvoid 282118611SnjlCgGenerateAmlLengths ( 283118611Snjl ACPI_PARSE_OBJECT *Op) 284118611Snjl{ 285118611Snjl char *Buffer; 286118611Snjl ACPI_STATUS Status; 287118611Snjl 288118611Snjl 289118611Snjl switch (Op->Asl.AmlOpcode) 290118611Snjl { 291118611Snjl case AML_RAW_DATA_BYTE: 292118611Snjl 293118611Snjl Op->Asl.AmlOpcodeLength = 0; 294118611Snjl Op->Asl.AmlLength = 1; 295118611Snjl return; 296118611Snjl 297118611Snjl case AML_RAW_DATA_WORD: 298118611Snjl 299118611Snjl Op->Asl.AmlOpcodeLength = 0; 300118611Snjl Op->Asl.AmlLength = 2; 301118611Snjl return; 302118611Snjl 303118611Snjl case AML_RAW_DATA_DWORD: 304118611Snjl 305118611Snjl Op->Asl.AmlOpcodeLength = 0; 306118611Snjl Op->Asl.AmlLength = 4; 307118611Snjl return; 308118611Snjl 309118611Snjl case AML_RAW_DATA_QWORD: 310118611Snjl 311118611Snjl Op->Asl.AmlOpcodeLength = 0; 312118611Snjl Op->Asl.AmlLength = 8; 313118611Snjl return; 314118611Snjl 315118611Snjl case AML_RAW_DATA_BUFFER: 316118611Snjl 317118611Snjl /* Aml length is/was set by creator */ 318118611Snjl 319118611Snjl Op->Asl.AmlOpcodeLength = 0; 320118611Snjl return; 321118611Snjl 322118611Snjl case AML_RAW_DATA_CHAIN: 323118611Snjl 324118611Snjl /* Aml length is/was set by creator */ 325118611Snjl 326118611Snjl Op->Asl.AmlOpcodeLength = 0; 327118611Snjl return; 328118611Snjl 329118611Snjl default: 330118611Snjl break; 331118611Snjl } 332118611Snjl 333118611Snjl switch (Op->Asl.ParseOpcode) 334118611Snjl { 335118611Snjl case PARSEOP_DEFINITIONBLOCK: 336118611Snjl 337151937Sjkim Gbl_TableLength = sizeof (ACPI_TABLE_HEADER) + 338151937Sjkim Op->Asl.AmlSubtreeLength; 339118611Snjl break; 340118611Snjl 341118611Snjl case PARSEOP_NAMESEG: 342118611Snjl 343118611Snjl Op->Asl.AmlOpcodeLength = 0; 344118611Snjl Op->Asl.AmlLength = 4; 345118611Snjl Op->Asl.ExternalName = Op->Asl.Value.String; 346118611Snjl break; 347118611Snjl 348118611Snjl case PARSEOP_NAMESTRING: 349118611Snjl case PARSEOP_METHODCALL: 350118611Snjl 351118611Snjl if (Op->Asl.CompileFlags & NODE_NAME_INTERNALIZED) 352118611Snjl { 353118611Snjl break; 354118611Snjl } 355118611Snjl 356118611Snjl Op->Asl.AmlOpcodeLength = 0; 357118611Snjl Status = UtInternalizeName (Op->Asl.Value.String, &Buffer); 358118611Snjl if (ACPI_FAILURE (Status)) 359118611Snjl { 360118611Snjl DbgPrint (ASL_DEBUG_OUTPUT, 361118611Snjl "Failure from internalize name %X\n", Status); 362118611Snjl break; 363118611Snjl } 364118611Snjl 365118611Snjl Op->Asl.ExternalName = Op->Asl.Value.String; 366118611Snjl Op->Asl.Value.String = Buffer; 367118611Snjl Op->Asl.CompileFlags |= NODE_NAME_INTERNALIZED; 368118611Snjl 369118611Snjl Op->Asl.AmlLength = strlen (Buffer); 370118611Snjl 371118611Snjl /* 372118611Snjl * Check for single backslash reference to root, 373118611Snjl * make it a null terminated string in the AML 374118611Snjl */ 375118611Snjl if (Op->Asl.AmlLength == 1) 376118611Snjl { 377118611Snjl Op->Asl.AmlLength = 2; 378118611Snjl } 379118611Snjl break; 380118611Snjl 381118611Snjl case PARSEOP_STRING_LITERAL: 382118611Snjl 383118611Snjl Op->Asl.AmlOpcodeLength = 1; 384151937Sjkim 385151937Sjkim /* Get null terminator */ 386151937Sjkim 387151937Sjkim Op->Asl.AmlLength = strlen (Op->Asl.Value.String) + 1; 388118611Snjl break; 389118611Snjl 390118611Snjl case PARSEOP_PACKAGE_LENGTH: 391118611Snjl 392118611Snjl Op->Asl.AmlOpcodeLength = 0; 393151937Sjkim Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (Op, 394151937Sjkim (UINT32) Op->Asl.Value.Integer); 395118611Snjl break; 396118611Snjl 397118611Snjl case PARSEOP_RAW_DATA: 398118611Snjl 399118611Snjl Op->Asl.AmlOpcodeLength = 0; 400118611Snjl break; 401118611Snjl 402118611Snjl case PARSEOP_DEFAULT_ARG: 403118611Snjl case PARSEOP_EXTERNAL: 404118611Snjl case PARSEOP_INCLUDE: 405118611Snjl case PARSEOP_INCLUDE_END: 406118611Snjl 407118611Snjl /* Ignore the "default arg" nodes, they are extraneous at this point */ 408118611Snjl 409118611Snjl break; 410118611Snjl 411118611Snjl default: 412118611Snjl 413118611Snjl CgGenerateAmlOpcodeLength (Op); 414118611Snjl break; 415118611Snjl } 416118611Snjl} 417118611Snjl 418118611Snjl 419151937Sjkim#ifdef ACPI_OBSOLETE_FUNCTIONS 420151937Sjkim/******************************************************************************* 421151937Sjkim * 422151937Sjkim * FUNCTION: LnAdjustLengthToRoot 423151937Sjkim * 424151937Sjkim * PARAMETERS: Op - Node whose Length was changed 425151937Sjkim * 426151937Sjkim * RETURN: None. 427151937Sjkim * 428151937Sjkim * DESCRIPTION: Change the Subtree length of the given node, and bubble the 429151937Sjkim * change all the way up to the root node. This allows for 430151937Sjkim * last second changes to a package length (for example, if the 431151937Sjkim * package length encoding gets shorter or longer.) 432151937Sjkim * 433151937Sjkim ******************************************************************************/ 434151937Sjkim 435151937Sjkimvoid 436151937SjkimLnAdjustLengthToRoot ( 437151937Sjkim ACPI_PARSE_OBJECT *SubtreeOp, 438151937Sjkim UINT32 LengthDelta) 439151937Sjkim{ 440151937Sjkim ACPI_PARSE_OBJECT *Op; 441151937Sjkim 442151937Sjkim 443151937Sjkim /* Adjust all subtree lengths up to the root */ 444151937Sjkim 445151937Sjkim Op = SubtreeOp->Asl.Parent; 446151937Sjkim while (Op) 447151937Sjkim { 448151937Sjkim Op->Asl.AmlSubtreeLength -= LengthDelta; 449151937Sjkim Op = Op->Asl.Parent; 450151937Sjkim } 451151937Sjkim 452151937Sjkim /* Adjust the global table length */ 453151937Sjkim 454151937Sjkim Gbl_TableLength -= LengthDelta; 455151937Sjkim} 456151937Sjkim#endif 457151937Sjkim 458151937Sjkim 459