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