1118611Snjl/****************************************************************************** 2118611Snjl * 3118611Snjl * Module Name: asllength - Tree walk to determine package and opcode lengths 4118611Snjl * 5118611Snjl *****************************************************************************/ 6118611Snjl 7217365Sjkim/* 8281075Sdim * Copyright (C) 2000 - 2015, 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 44151937Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 45118611Snjl#include "aslcompiler.y.h" 46193529Sjkim#include <contrib/dev/acpica/include/amlcode.h> 47118611Snjl 48118611Snjl 49118611Snjl#define _COMPONENT ACPI_COMPILER 50118611Snjl ACPI_MODULE_NAME ("asllength") 51118611Snjl 52151937Sjkim/* Local prototypes */ 53118611Snjl 54151937Sjkimstatic UINT8 55151937SjkimCgGetPackageLenByteCount ( 56151937Sjkim ACPI_PARSE_OBJECT *Op, 57151937Sjkim UINT32 PackageLength); 58151937Sjkim 59151937Sjkimstatic void 60151937SjkimCgGenerateAmlOpcodeLength ( 61151937Sjkim ACPI_PARSE_OBJECT *Op); 62151937Sjkim 63151937Sjkim 64151937Sjkim#ifdef ACPI_OBSOLETE_FUNCTIONS 65151937Sjkimvoid 66151937SjkimLnAdjustLengthToRoot ( 67151937Sjkim ACPI_PARSE_OBJECT *Op, 68151937Sjkim UINT32 LengthDelta); 69151937Sjkim#endif 70151937Sjkim 71151937Sjkim 72118611Snjl/******************************************************************************* 73118611Snjl * 74118611Snjl * FUNCTION: LnInitLengthsWalk 75118611Snjl * 76118611Snjl * PARAMETERS: ASL_WALK_CALLBACK 77118611Snjl * 78118611Snjl * RETURN: Status 79118611Snjl * 80118611Snjl * DESCRIPTION: Walk callback to initialize (and re-initialize) the node 81241973Sjkim * subtree length(s) to zero. The Subtree lengths are bubbled 82118611Snjl * up to the root node in order to get a total AML length. 83118611Snjl * 84118611Snjl ******************************************************************************/ 85118611Snjl 86118611SnjlACPI_STATUS 87118611SnjlLnInitLengthsWalk ( 88118611Snjl ACPI_PARSE_OBJECT *Op, 89118611Snjl UINT32 Level, 90118611Snjl void *Context) 91118611Snjl{ 92118611Snjl 93118611Snjl Op->Asl.AmlSubtreeLength = 0; 94118611Snjl return (AE_OK); 95118611Snjl} 96118611Snjl 97118611Snjl 98118611Snjl/******************************************************************************* 99118611Snjl * 100118611Snjl * FUNCTION: LnPackageLengthWalk 101118611Snjl * 102118611Snjl * PARAMETERS: ASL_WALK_CALLBACK 103118611Snjl * 104118611Snjl * RETURN: Status 105118611Snjl * 106118611Snjl * DESCRIPTION: Walk callback to calculate the total AML length. 107118611Snjl * 1) Calculate the AML lengths (opcode, package length, etc.) for 108118611Snjl * THIS node. 109118611Snjl * 2) Bubbble up all of these lengths to the parent node by summing 110118611Snjl * them all into the parent subtree length. 111118611Snjl * 112118611Snjl * Note: The SubtreeLength represents the total AML length of all child nodes 113241973Sjkim * in all subtrees under a given node. Therefore, once this walk is 114118611Snjl * complete, the Root Node subtree length is the AML length of the entire 115118611Snjl * tree (and thus, the entire ACPI table) 116118611Snjl * 117118611Snjl ******************************************************************************/ 118118611Snjl 119118611SnjlACPI_STATUS 120118611SnjlLnPackageLengthWalk ( 121118611Snjl ACPI_PARSE_OBJECT *Op, 122118611Snjl UINT32 Level, 123118611Snjl void *Context) 124118611Snjl{ 125118611Snjl 126118611Snjl /* Generate the AML lengths for this node */ 127118611Snjl 128118611Snjl CgGenerateAmlLengths (Op); 129118611Snjl 130118611Snjl /* Bubble up all lengths (this node and all below it) to the parent */ 131118611Snjl 132118611Snjl if ((Op->Asl.Parent) && 133118611Snjl (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 134118611Snjl { 135118611Snjl Op->Asl.Parent->Asl.AmlSubtreeLength += (Op->Asl.AmlLength + 136118611Snjl Op->Asl.AmlOpcodeLength + 137118611Snjl Op->Asl.AmlPkgLenBytes + 138118611Snjl Op->Asl.AmlSubtreeLength); 139118611Snjl } 140118611Snjl return (AE_OK); 141118611Snjl} 142118611Snjl 143118611Snjl 144118611Snjl/******************************************************************************* 145118611Snjl * 146118611Snjl * FUNCTION: CgGetPackageLenByteCount 147118611Snjl * 148151937Sjkim * PARAMETERS: Op - Parse node 149118611Snjl * PackageLength - Length to be encoded 150118611Snjl * 151118611Snjl * RETURN: Required length of the package length encoding 152118611Snjl * 153118611Snjl * DESCRIPTION: Calculate the number of bytes required to encode the given 154118611Snjl * package length. 155118611Snjl * 156118611Snjl ******************************************************************************/ 157118611Snjl 158151937Sjkimstatic UINT8 159118611SnjlCgGetPackageLenByteCount ( 160118611Snjl ACPI_PARSE_OBJECT *Op, 161118611Snjl UINT32 PackageLength) 162118611Snjl{ 163118611Snjl 164118611Snjl /* 165118611Snjl * Determine the number of bytes required to encode the package length 166118611Snjl * Note: the package length includes the number of bytes used to encode 167118611Snjl * the package length, so we must account for this also. 168118611Snjl */ 169118611Snjl if (PackageLength <= (0x0000003F - 1)) 170118611Snjl { 171118611Snjl return (1); 172118611Snjl } 173118611Snjl else if (PackageLength <= (0x00000FFF - 2)) 174118611Snjl { 175118611Snjl return (2); 176118611Snjl } 177118611Snjl else if (PackageLength <= (0x000FFFFF - 3)) 178118611Snjl { 179118611Snjl return (3); 180118611Snjl } 181118611Snjl else if (PackageLength <= (0x0FFFFFFF - 4)) 182118611Snjl { 183118611Snjl return (4); 184118611Snjl } 185118611Snjl else 186118611Snjl { 187118611Snjl /* Fatal error - the package length is too large to encode */ 188118611Snjl 189118611Snjl AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, Op, NULL); 190118611Snjl } 191118611Snjl 192118611Snjl return (0); 193118611Snjl} 194118611Snjl 195118611Snjl 196118611Snjl/******************************************************************************* 197118611Snjl * 198118611Snjl * FUNCTION: CgGenerateAmlOpcodeLength 199118611Snjl * 200151937Sjkim * PARAMETERS: Op - Parse node whose AML opcode lengths will be 201118611Snjl * calculated 202118611Snjl * 203118611Snjl * RETURN: None. 204118611Snjl * 205118611Snjl * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength 206118611Snjl * fields for this node. 207118611Snjl * 208118611Snjl ******************************************************************************/ 209118611Snjl 210151937Sjkimstatic void 211118611SnjlCgGenerateAmlOpcodeLength ( 212118611Snjl ACPI_PARSE_OBJECT *Op) 213118611Snjl{ 214118611Snjl 215118611Snjl /* Check for two-byte opcode */ 216118611Snjl 217118611Snjl if (Op->Asl.AmlOpcode > 0x00FF) 218118611Snjl { 219118611Snjl Op->Asl.AmlOpcodeLength = 2; 220118611Snjl } 221118611Snjl else 222118611Snjl { 223118611Snjl Op->Asl.AmlOpcodeLength = 1; 224118611Snjl } 225118611Snjl 226118611Snjl /* Does this opcode have an associated "PackageLength" field? */ 227118611Snjl 228118611Snjl Op->Asl.AmlPkgLenBytes = 0; 229118611Snjl if (Op->Asl.CompileFlags & NODE_AML_PACKAGE) 230118611Snjl { 231151937Sjkim Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount ( 232151937Sjkim Op, Op->Asl.AmlSubtreeLength); 233118611Snjl } 234118611Snjl 235118611Snjl /* Data opcode lengths are easy */ 236118611Snjl 237118611Snjl switch (Op->Asl.AmlOpcode) 238118611Snjl { 239118611Snjl case AML_BYTE_OP: 240118611Snjl 241118611Snjl Op->Asl.AmlLength = 1; 242118611Snjl break; 243118611Snjl 244118611Snjl case AML_WORD_OP: 245118611Snjl 246118611Snjl Op->Asl.AmlLength = 2; 247118611Snjl break; 248118611Snjl 249118611Snjl case AML_DWORD_OP: 250118611Snjl 251118611Snjl Op->Asl.AmlLength = 4; 252118611Snjl break; 253118611Snjl 254118611Snjl case AML_QWORD_OP: 255118611Snjl 256118611Snjl Op->Asl.AmlLength = 8; 257118611Snjl break; 258118611Snjl 259118611Snjl default: 260250838Sjkim 261118611Snjl /* All data opcodes must be above */ 262118611Snjl break; 263118611Snjl } 264118611Snjl} 265118611Snjl 266118611Snjl 267118611Snjl/******************************************************************************* 268118611Snjl * 269118611Snjl * FUNCTION: CgGenerateAmlLengths 270118611Snjl * 271118611Snjl * PARAMETERS: Op - Parse node 272118611Snjl * 273118611Snjl * RETURN: None. 274118611Snjl * 275118611Snjl * DESCRIPTION: Generate internal length fields based on the AML opcode or 276118611Snjl * parse opcode. 277118611Snjl * 278118611Snjl ******************************************************************************/ 279118611Snjl 280118611Snjlvoid 281118611SnjlCgGenerateAmlLengths ( 282118611Snjl ACPI_PARSE_OBJECT *Op) 283118611Snjl{ 284118611Snjl char *Buffer; 285118611Snjl ACPI_STATUS Status; 286118611Snjl 287118611Snjl 288118611Snjl switch (Op->Asl.AmlOpcode) 289118611Snjl { 290118611Snjl case AML_RAW_DATA_BYTE: 291118611Snjl 292118611Snjl Op->Asl.AmlOpcodeLength = 0; 293118611Snjl Op->Asl.AmlLength = 1; 294118611Snjl return; 295118611Snjl 296118611Snjl case AML_RAW_DATA_WORD: 297118611Snjl 298118611Snjl Op->Asl.AmlOpcodeLength = 0; 299118611Snjl Op->Asl.AmlLength = 2; 300118611Snjl return; 301118611Snjl 302118611Snjl case AML_RAW_DATA_DWORD: 303118611Snjl 304118611Snjl Op->Asl.AmlOpcodeLength = 0; 305118611Snjl Op->Asl.AmlLength = 4; 306118611Snjl return; 307118611Snjl 308118611Snjl case AML_RAW_DATA_QWORD: 309118611Snjl 310118611Snjl Op->Asl.AmlOpcodeLength = 0; 311118611Snjl Op->Asl.AmlLength = 8; 312118611Snjl return; 313118611Snjl 314118611Snjl case AML_RAW_DATA_BUFFER: 315118611Snjl 316118611Snjl /* Aml length is/was set by creator */ 317118611Snjl 318118611Snjl Op->Asl.AmlOpcodeLength = 0; 319118611Snjl return; 320118611Snjl 321118611Snjl case AML_RAW_DATA_CHAIN: 322118611Snjl 323118611Snjl /* Aml length is/was set by creator */ 324118611Snjl 325118611Snjl Op->Asl.AmlOpcodeLength = 0; 326118611Snjl return; 327118611Snjl 328118611Snjl default: 329250838Sjkim 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 429241973Sjkim * 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 457