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