1 /****************************************************************************** 2 * 3 * Module Name: asllength - Tree walk to determine package and opcode lengths 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2017, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <contrib/dev/acpica/compiler/aslcompiler.h> 45 #include "aslcompiler.y.h" 46 #include <contrib/dev/acpica/include/amlcode.h> 47 48 49 #define _COMPONENT ACPI_COMPILER 50 ACPI_MODULE_NAME ("asllength") 51 52 /* Local prototypes */ 53 54 static UINT8 55 CgGetPackageLenByteCount ( 56 ACPI_PARSE_OBJECT *Op, 57 UINT32 PackageLength); 58 59 static void 60 CgGenerateAmlOpcodeLength ( 61 ACPI_PARSE_OBJECT *Op); 62 63 64 #ifdef ACPI_OBSOLETE_FUNCTIONS 65 void 66 LnAdjustLengthToRoot ( 67 ACPI_PARSE_OBJECT *Op, 68 UINT32 LengthDelta); 69 #endif 70 71 72 /******************************************************************************* 73 * 74 * FUNCTION: LnInitLengthsWalk 75 * 76 * PARAMETERS: ASL_WALK_CALLBACK 77 * 78 * RETURN: Status 79 * 80 * DESCRIPTION: Walk callback to initialize (and re-initialize) the node 81 * subtree length(s) to zero. The Subtree lengths are bubbled 82 * up to the root node in order to get a total AML length. 83 * 84 ******************************************************************************/ 85 86 ACPI_STATUS 87 LnInitLengthsWalk ( 88 ACPI_PARSE_OBJECT *Op, 89 UINT32 Level, 90 void *Context) 91 { 92 93 Op->Asl.AmlSubtreeLength = 0; 94 return (AE_OK); 95 } 96 97 98 /******************************************************************************* 99 * 100 * FUNCTION: LnPackageLengthWalk 101 * 102 * PARAMETERS: ASL_WALK_CALLBACK 103 * 104 * RETURN: Status 105 * 106 * DESCRIPTION: Walk callback to calculate the total AML length. 107 * 1) Calculate the AML lengths (opcode, package length, etc.) for 108 * THIS node. 109 * 2) Bubbble up all of these lengths to the parent node by summing 110 * them all into the parent subtree length. 111 * 112 * Note: The SubtreeLength represents the total AML length of all child nodes 113 * in all subtrees under a given node. Therefore, once this walk is 114 * complete, the Root Node subtree length is the AML length of the entire 115 * tree (and thus, the entire ACPI table) 116 * 117 ******************************************************************************/ 118 119 ACPI_STATUS 120 LnPackageLengthWalk ( 121 ACPI_PARSE_OBJECT *Op, 122 UINT32 Level, 123 void *Context) 124 { 125 126 /* Generate the AML lengths for this node */ 127 128 CgGenerateAmlLengths (Op); 129 130 /* Bubble up all lengths (this node and all below it) to the parent */ 131 132 if ((Op->Asl.Parent) && 133 (Op->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG)) 134 { 135 Op->Asl.Parent->Asl.AmlSubtreeLength += ( 136 Op->Asl.AmlLength + 137 Op->Asl.AmlOpcodeLength + 138 Op->Asl.AmlPkgLenBytes + 139 Op->Asl.AmlSubtreeLength); 140 } 141 return (AE_OK); 142 } 143 144 145 /******************************************************************************* 146 * 147 * FUNCTION: CgGetPackageLenByteCount 148 * 149 * PARAMETERS: Op - Parse node 150 * PackageLength - Length to be encoded 151 * 152 * RETURN: Required length of the package length encoding 153 * 154 * DESCRIPTION: Calculate the number of bytes required to encode the given 155 * package length. 156 * 157 ******************************************************************************/ 158 159 static UINT8 160 CgGetPackageLenByteCount ( 161 ACPI_PARSE_OBJECT *Op, 162 UINT32 PackageLength) 163 { 164 165 /* 166 * Determine the number of bytes required to encode the package length 167 * Note: the package length includes the number of bytes used to encode 168 * the package length, so we must account for this also. 169 */ 170 if (PackageLength <= (0x0000003F - 1)) 171 { 172 return (1); 173 } 174 else if (PackageLength <= (0x00000FFF - 2)) 175 { 176 return (2); 177 } 178 else if (PackageLength <= (0x000FFFFF - 3)) 179 { 180 return (3); 181 } 182 else if (PackageLength <= (0x0FFFFFFF - 4)) 183 { 184 return (4); 185 } 186 else 187 { 188 /* Fatal error - the package length is too large to encode */ 189 190 AslError (ASL_ERROR, ASL_MSG_ENCODING_LENGTH, Op, NULL); 191 } 192 193 return (0); 194 } 195 196 197 /******************************************************************************* 198 * 199 * FUNCTION: CgGenerateAmlOpcodeLength 200 * 201 * PARAMETERS: Op - Parse node whose AML opcode lengths will be 202 * calculated 203 * 204 * RETURN: None. 205 * 206 * DESCRIPTION: Calculate the AmlOpcodeLength, AmlPkgLenBytes, and AmlLength 207 * fields for this node. 208 * 209 ******************************************************************************/ 210 211 static void 212 CgGenerateAmlOpcodeLength ( 213 ACPI_PARSE_OBJECT *Op) 214 { 215 216 /* Check for two-byte opcode */ 217 218 if (Op->Asl.AmlOpcode > 0x00FF) 219 { 220 Op->Asl.AmlOpcodeLength = 2; 221 } 222 else 223 { 224 Op->Asl.AmlOpcodeLength = 1; 225 } 226 227 /* Does this opcode have an associated "PackageLength" field? */ 228 229 Op->Asl.AmlPkgLenBytes = 0; 230 if (Op->Asl.CompileFlags & NODE_AML_PACKAGE) 231 { 232 Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount ( 233 Op, Op->Asl.AmlSubtreeLength); 234 } 235 236 /* Data opcode lengths are easy */ 237 238 switch (Op->Asl.AmlOpcode) 239 { 240 case AML_BYTE_OP: 241 242 Op->Asl.AmlLength = 1; 243 break; 244 245 case AML_WORD_OP: 246 247 Op->Asl.AmlLength = 2; 248 break; 249 250 case AML_DWORD_OP: 251 252 Op->Asl.AmlLength = 4; 253 break; 254 255 case AML_QWORD_OP: 256 257 Op->Asl.AmlLength = 8; 258 break; 259 260 default: 261 262 /* All data opcodes must be above */ 263 break; 264 } 265 } 266 267 268 /******************************************************************************* 269 * 270 * FUNCTION: CgGenerateAmlLengths 271 * 272 * PARAMETERS: Op - Parse node 273 * 274 * RETURN: None. 275 * 276 * DESCRIPTION: Generate internal length fields based on the AML opcode or 277 * parse opcode. 278 * 279 ******************************************************************************/ 280 281 void 282 CgGenerateAmlLengths ( 283 ACPI_PARSE_OBJECT *Op) 284 { 285 char *Buffer; 286 ACPI_STATUS Status; 287 288 289 switch (Op->Asl.AmlOpcode) 290 { 291 case AML_RAW_DATA_BYTE: 292 293 Op->Asl.AmlOpcodeLength = 0; 294 Op->Asl.AmlLength = 1; 295 return; 296 297 case AML_RAW_DATA_WORD: 298 299 Op->Asl.AmlOpcodeLength = 0; 300 Op->Asl.AmlLength = 2; 301 return; 302 303 case AML_RAW_DATA_DWORD: 304 305 Op->Asl.AmlOpcodeLength = 0; 306 Op->Asl.AmlLength = 4; 307 return; 308 309 case AML_RAW_DATA_QWORD: 310 311 Op->Asl.AmlOpcodeLength = 0; 312 Op->Asl.AmlLength = 8; 313 return; 314 315 case AML_RAW_DATA_BUFFER: 316 317 /* Aml length is/was set by creator */ 318 319 Op->Asl.AmlOpcodeLength = 0; 320 return; 321 322 case AML_RAW_DATA_CHAIN: 323 324 /* Aml length is/was set by creator */ 325 326 Op->Asl.AmlOpcodeLength = 0; 327 return; 328 329 default: 330 331 break; 332 } 333 334 switch (Op->Asl.ParseOpcode) 335 { 336 case PARSEOP_DEFINITION_BLOCK: 337 338 Gbl_TableLength = sizeof (ACPI_TABLE_HEADER) + Op->Asl.AmlSubtreeLength; 339 break; 340 341 case PARSEOP_NAMESEG: 342 343 Op->Asl.AmlOpcodeLength = 0; 344 Op->Asl.AmlLength = 4; 345 Op->Asl.ExternalName = Op->Asl.Value.String; 346 break; 347 348 case PARSEOP_NAMESTRING: 349 case PARSEOP_METHODCALL: 350 351 if (Op->Asl.CompileFlags & NODE_NAME_INTERNALIZED) 352 { 353 break; 354 } 355 356 Op->Asl.AmlOpcodeLength = 0; 357 Status = UtInternalizeName (Op->Asl.Value.String, &Buffer); 358 if (ACPI_FAILURE (Status)) 359 { 360 DbgPrint (ASL_DEBUG_OUTPUT, 361 "Failure from internalize name %X\n", Status); 362 break; 363 } 364 365 Op->Asl.ExternalName = Op->Asl.Value.String; 366 Op->Asl.Value.String = Buffer; 367 Op->Asl.CompileFlags |= NODE_NAME_INTERNALIZED; 368 Op->Asl.AmlLength = strlen (Buffer); 369 370 /* 371 * Check for single backslash reference to root, 372 * make it a null terminated string in the AML 373 */ 374 if (Op->Asl.AmlLength == 1) 375 { 376 Op->Asl.AmlLength = 2; 377 } 378 break; 379 380 case PARSEOP_STRING_LITERAL: 381 382 Op->Asl.AmlOpcodeLength = 1; 383 384 /* Get null terminator */ 385 386 Op->Asl.AmlLength = strlen (Op->Asl.Value.String) + 1; 387 break; 388 389 case PARSEOP_PACKAGE_LENGTH: 390 391 Op->Asl.AmlOpcodeLength = 0; 392 Op->Asl.AmlPkgLenBytes = CgGetPackageLenByteCount (Op, 393 (UINT32) Op->Asl.Value.Integer); 394 break; 395 396 case PARSEOP_RAW_DATA: 397 398 Op->Asl.AmlOpcodeLength = 0; 399 break; 400 401 case PARSEOP_DEFAULT_ARG: 402 case PARSEOP_INCLUDE: 403 case PARSEOP_INCLUDE_END: 404 405 /* Ignore the "default arg" nodes, they are extraneous at this point */ 406 407 break; 408 409 case PARSEOP_EXTERNAL: 410 411 if (Gbl_DoExternals == TRUE) 412 { 413 CgGenerateAmlOpcodeLength (Op); 414 } 415 break; 416 417 default: 418 419 CgGenerateAmlOpcodeLength (Op); 420 break; 421 } 422 } 423 424 425 #ifdef ACPI_OBSOLETE_FUNCTIONS 426 /******************************************************************************* 427 * 428 * FUNCTION: LnAdjustLengthToRoot 429 * 430 * PARAMETERS: Op - Node whose Length was changed 431 * 432 * RETURN: None. 433 * 434 * DESCRIPTION: Change the Subtree length of the given node, and bubble the 435 * change all the way up to the root node. This allows for 436 * last second changes to a package length (for example, if the 437 * package length encoding gets shorter or longer.) 438 * 439 ******************************************************************************/ 440 441 void 442 LnAdjustLengthToRoot ( 443 ACPI_PARSE_OBJECT *SubtreeOp, 444 UINT32 LengthDelta) 445 { 446 ACPI_PARSE_OBJECT *Op; 447 448 449 /* Adjust all subtree lengths up to the root */ 450 451 Op = SubtreeOp->Asl.Parent; 452 while (Op) 453 { 454 Op->Asl.AmlSubtreeLength -= LengthDelta; 455 Op = Op->Asl.Parent; 456 } 457 458 /* Adjust the global table length */ 459 460 Gbl_TableLength -= LengthDelta; 461 } 462 #endif 463