1118611Snjl/****************************************************************************** 2118611Snjl * 3118611Snjl * Module Name: asllength - Tree walk to determine package and opcode lengths 4118611Snjl * 5118611Snjl *****************************************************************************/ 6118611Snjl 7217365Sjkim/* 8298714Sjkim * Copyright (C) 2000 - 2016, 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 { 135298714Sjkim Op->Asl.Parent->Asl.AmlSubtreeLength += ( 136298714Sjkim Op->Asl.AmlLength + 137298714Sjkim Op->Asl.AmlOpcodeLength + 138298714Sjkim Op->Asl.AmlPkgLenBytes + 139298714Sjkim 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 ( 233298714Sjkim 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 { 336298714Sjkim case PARSEOP_DEFINITION_BLOCK: 337118611Snjl 338298714Sjkim Gbl_TableLength = sizeof (ACPI_TABLE_HEADER) + 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 Op->Asl.AmlLength = strlen (Buffer); 369118611Snjl 370118611Snjl /* 371118611Snjl * Check for single backslash reference to root, 372118611Snjl * make it a null terminated string in the AML 373118611Snjl */ 374118611Snjl if (Op->Asl.AmlLength == 1) 375118611Snjl { 376118611Snjl Op->Asl.AmlLength = 2; 377118611Snjl } 378118611Snjl break; 379118611Snjl 380118611Snjl case PARSEOP_STRING_LITERAL: 381118611Snjl 382118611Snjl Op->Asl.AmlOpcodeLength = 1; 383151937Sjkim 384151937Sjkim /* Get null terminator */ 385151937Sjkim 386151937Sjkim Op->Asl.AmlLength = strlen (Op->Asl.Value.String) + 1; 387118611Snjl break; 388118611Snjl 389118611Snjl case PARSEOP_PACKAGE_LENGTH: 390118611Snjl 391118611Snjl Op->Asl.AmlOpcodeLength = 0; 392151937Sjkim Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (Op, 393298714Sjkim (UINT32) Op->Asl.Value.Integer); 394118611Snjl break; 395118611Snjl 396118611Snjl case PARSEOP_RAW_DATA: 397118611Snjl 398118611Snjl Op->Asl.AmlOpcodeLength = 0; 399118611Snjl break; 400118611Snjl 401118611Snjl case PARSEOP_DEFAULT_ARG: 402118611Snjl case PARSEOP_INCLUDE: 403118611Snjl case PARSEOP_INCLUDE_END: 404118611Snjl 405118611Snjl /* Ignore the "default arg" nodes, they are extraneous at this point */ 406118611Snjl 407118611Snjl break; 408118611Snjl 409298714Sjkim case PARSEOP_EXTERNAL: 410298714Sjkim 411298714Sjkim if (Gbl_DoExternals == TRUE) 412298714Sjkim { 413298714Sjkim CgGenerateAmlOpcodeLength (Op); 414298714Sjkim } 415298714Sjkim break; 416298714Sjkim 417118611Snjl default: 418118611Snjl 419118611Snjl CgGenerateAmlOpcodeLength (Op); 420118611Snjl break; 421118611Snjl } 422118611Snjl} 423118611Snjl 424118611Snjl 425151937Sjkim#ifdef ACPI_OBSOLETE_FUNCTIONS 426151937Sjkim/******************************************************************************* 427151937Sjkim * 428151937Sjkim * FUNCTION: LnAdjustLengthToRoot 429151937Sjkim * 430151937Sjkim * PARAMETERS: Op - Node whose Length was changed 431151937Sjkim * 432151937Sjkim * RETURN: None. 433151937Sjkim * 434151937Sjkim * DESCRIPTION: Change the Subtree length of the given node, and bubble the 435241973Sjkim * change all the way up to the root node. This allows for 436151937Sjkim * last second changes to a package length (for example, if the 437151937Sjkim * package length encoding gets shorter or longer.) 438151937Sjkim * 439151937Sjkim ******************************************************************************/ 440151937Sjkim 441151937Sjkimvoid 442151937SjkimLnAdjustLengthToRoot ( 443151937Sjkim ACPI_PARSE_OBJECT *SubtreeOp, 444151937Sjkim UINT32 LengthDelta) 445151937Sjkim{ 446151937Sjkim ACPI_PARSE_OBJECT *Op; 447151937Sjkim 448151937Sjkim 449151937Sjkim /* Adjust all subtree lengths up to the root */ 450151937Sjkim 451151937Sjkim Op = SubtreeOp->Asl.Parent; 452151937Sjkim while (Op) 453151937Sjkim { 454151937Sjkim Op->Asl.AmlSubtreeLength -= LengthDelta; 455151937Sjkim Op = Op->Asl.Parent; 456151937Sjkim } 457151937Sjkim 458151937Sjkim /* Adjust the global table length */ 459151937Sjkim 460151937Sjkim Gbl_TableLength -= LengthDelta; 461151937Sjkim} 462151937Sjkim#endif 463