1 /****************************************************************************** 2 * 3 * Module Name: dsargs - Support for execution of dynamic arguments for static 4 * objects (regions, fields, buffer fields, etc.) 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2014, 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 #define __DSARGS_C__ 46 47 #include <contrib/dev/acpica/include/acpi.h> 48 #include <contrib/dev/acpica/include/accommon.h> 49 #include <contrib/dev/acpica/include/acparser.h> 50 #include <contrib/dev/acpica/include/amlcode.h> 51 #include <contrib/dev/acpica/include/acdispat.h> 52 #include <contrib/dev/acpica/include/acnamesp.h> 53 54 #define _COMPONENT ACPI_DISPATCHER 55 ACPI_MODULE_NAME ("dsargs") 56 57 /* Local prototypes */ 58 59 static ACPI_STATUS 60 AcpiDsExecuteArguments ( 61 ACPI_NAMESPACE_NODE *Node, 62 ACPI_NAMESPACE_NODE *ScopeNode, 63 UINT32 AmlLength, 64 UINT8 *AmlStart); 65 66 67 /******************************************************************************* 68 * 69 * FUNCTION: AcpiDsExecuteArguments 70 * 71 * PARAMETERS: Node - Object NS node 72 * ScopeNode - Parent NS node 73 * AmlLength - Length of executable AML 74 * AmlStart - Pointer to the AML 75 * 76 * RETURN: Status. 77 * 78 * DESCRIPTION: Late (deferred) execution of region or field arguments 79 * 80 ******************************************************************************/ 81 82 static ACPI_STATUS 83 AcpiDsExecuteArguments ( 84 ACPI_NAMESPACE_NODE *Node, 85 ACPI_NAMESPACE_NODE *ScopeNode, 86 UINT32 AmlLength, 87 UINT8 *AmlStart) 88 { 89 ACPI_STATUS Status; 90 ACPI_PARSE_OBJECT *Op; 91 ACPI_WALK_STATE *WalkState; 92 93 94 ACPI_FUNCTION_TRACE (DsExecuteArguments); 95 96 97 /* Allocate a new parser op to be the root of the parsed tree */ 98 99 Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP); 100 if (!Op) 101 { 102 return_ACPI_STATUS (AE_NO_MEMORY); 103 } 104 105 /* Save the Node for use in AcpiPsParseAml */ 106 107 Op->Common.Node = ScopeNode; 108 109 /* Create and initialize a new parser state */ 110 111 WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); 112 if (!WalkState) 113 { 114 Status = AE_NO_MEMORY; 115 goto Cleanup; 116 } 117 118 Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, AmlStart, 119 AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); 120 if (ACPI_FAILURE (Status)) 121 { 122 AcpiDsDeleteWalkState (WalkState); 123 goto Cleanup; 124 } 125 126 /* Mark this parse as a deferred opcode */ 127 128 WalkState->ParseFlags = ACPI_PARSE_DEFERRED_OP; 129 WalkState->DeferredNode = Node; 130 131 /* Pass1: Parse the entire declaration */ 132 133 Status = AcpiPsParseAml (WalkState); 134 if (ACPI_FAILURE (Status)) 135 { 136 goto Cleanup; 137 } 138 139 /* Get and init the Op created above */ 140 141 Op->Common.Node = Node; 142 AcpiPsDeleteParseTree (Op); 143 144 /* Evaluate the deferred arguments */ 145 146 Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP); 147 if (!Op) 148 { 149 return_ACPI_STATUS (AE_NO_MEMORY); 150 } 151 152 Op->Common.Node = ScopeNode; 153 154 /* Create and initialize a new parser state */ 155 156 WalkState = AcpiDsCreateWalkState (0, NULL, NULL, NULL); 157 if (!WalkState) 158 { 159 Status = AE_NO_MEMORY; 160 goto Cleanup; 161 } 162 163 /* Execute the opcode and arguments */ 164 165 Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, AmlStart, 166 AmlLength, NULL, ACPI_IMODE_EXECUTE); 167 if (ACPI_FAILURE (Status)) 168 { 169 AcpiDsDeleteWalkState (WalkState); 170 goto Cleanup; 171 } 172 173 /* Mark this execution as a deferred opcode */ 174 175 WalkState->DeferredNode = Node; 176 Status = AcpiPsParseAml (WalkState); 177 178 Cleanup: 179 AcpiPsDeleteParseTree (Op); 180 return_ACPI_STATUS (Status); 181 } 182 183 184 /******************************************************************************* 185 * 186 * FUNCTION: AcpiDsGetBufferFieldArguments 187 * 188 * PARAMETERS: ObjDesc - A valid BufferField object 189 * 190 * RETURN: Status. 191 * 192 * DESCRIPTION: Get BufferField Buffer and Index. This implements the late 193 * evaluation of these field attributes. 194 * 195 ******************************************************************************/ 196 197 ACPI_STATUS 198 AcpiDsGetBufferFieldArguments ( 199 ACPI_OPERAND_OBJECT *ObjDesc) 200 { 201 ACPI_OPERAND_OBJECT *ExtraDesc; 202 ACPI_NAMESPACE_NODE *Node; 203 ACPI_STATUS Status; 204 205 206 ACPI_FUNCTION_TRACE_PTR (DsGetBufferFieldArguments, ObjDesc); 207 208 209 if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) 210 { 211 return_ACPI_STATUS (AE_OK); 212 } 213 214 /* Get the AML pointer (method object) and BufferField node */ 215 216 ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc); 217 Node = ObjDesc->BufferField.Node; 218 219 ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_BUFFER_FIELD, 220 Node, NULL)); 221 222 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", 223 AcpiUtGetNodeName (Node))); 224 225 /* Execute the AML code for the TermArg arguments */ 226 227 Status = AcpiDsExecuteArguments (Node, Node->Parent, 228 ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart); 229 return_ACPI_STATUS (Status); 230 } 231 232 233 /******************************************************************************* 234 * 235 * FUNCTION: AcpiDsGetBankFieldArguments 236 * 237 * PARAMETERS: ObjDesc - A valid BankField object 238 * 239 * RETURN: Status. 240 * 241 * DESCRIPTION: Get BankField BankValue. This implements the late 242 * evaluation of these field attributes. 243 * 244 ******************************************************************************/ 245 246 ACPI_STATUS 247 AcpiDsGetBankFieldArguments ( 248 ACPI_OPERAND_OBJECT *ObjDesc) 249 { 250 ACPI_OPERAND_OBJECT *ExtraDesc; 251 ACPI_NAMESPACE_NODE *Node; 252 ACPI_STATUS Status; 253 254 255 ACPI_FUNCTION_TRACE_PTR (DsGetBankFieldArguments, ObjDesc); 256 257 258 if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) 259 { 260 return_ACPI_STATUS (AE_OK); 261 } 262 263 /* Get the AML pointer (method object) and BankField node */ 264 265 ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc); 266 Node = ObjDesc->BankField.Node; 267 268 ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_LOCAL_BANK_FIELD, 269 Node, NULL)); 270 271 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", 272 AcpiUtGetNodeName (Node))); 273 274 /* Execute the AML code for the TermArg arguments */ 275 276 Status = AcpiDsExecuteArguments (Node, Node->Parent, 277 ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart); 278 return_ACPI_STATUS (Status); 279 } 280 281 282 /******************************************************************************* 283 * 284 * FUNCTION: AcpiDsGetBufferArguments 285 * 286 * PARAMETERS: ObjDesc - A valid Buffer object 287 * 288 * RETURN: Status. 289 * 290 * DESCRIPTION: Get Buffer length and initializer byte list. This implements 291 * the late evaluation of these attributes. 292 * 293 ******************************************************************************/ 294 295 ACPI_STATUS 296 AcpiDsGetBufferArguments ( 297 ACPI_OPERAND_OBJECT *ObjDesc) 298 { 299 ACPI_NAMESPACE_NODE *Node; 300 ACPI_STATUS Status; 301 302 303 ACPI_FUNCTION_TRACE_PTR (DsGetBufferArguments, ObjDesc); 304 305 306 if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) 307 { 308 return_ACPI_STATUS (AE_OK); 309 } 310 311 /* Get the Buffer node */ 312 313 Node = ObjDesc->Buffer.Node; 314 if (!Node) 315 { 316 ACPI_ERROR ((AE_INFO, 317 "No pointer back to namespace node in buffer object %p", ObjDesc)); 318 return_ACPI_STATUS (AE_AML_INTERNAL); 319 } 320 321 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer Arg Init\n")); 322 323 /* Execute the AML code for the TermArg arguments */ 324 325 Status = AcpiDsExecuteArguments (Node, Node, 326 ObjDesc->Buffer.AmlLength, ObjDesc->Buffer.AmlStart); 327 return_ACPI_STATUS (Status); 328 } 329 330 331 /******************************************************************************* 332 * 333 * FUNCTION: AcpiDsGetPackageArguments 334 * 335 * PARAMETERS: ObjDesc - A valid Package object 336 * 337 * RETURN: Status. 338 * 339 * DESCRIPTION: Get Package length and initializer byte list. This implements 340 * the late evaluation of these attributes. 341 * 342 ******************************************************************************/ 343 344 ACPI_STATUS 345 AcpiDsGetPackageArguments ( 346 ACPI_OPERAND_OBJECT *ObjDesc) 347 { 348 ACPI_NAMESPACE_NODE *Node; 349 ACPI_STATUS Status; 350 351 352 ACPI_FUNCTION_TRACE_PTR (DsGetPackageArguments, ObjDesc); 353 354 355 if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) 356 { 357 return_ACPI_STATUS (AE_OK); 358 } 359 360 /* Get the Package node */ 361 362 Node = ObjDesc->Package.Node; 363 if (!Node) 364 { 365 ACPI_ERROR ((AE_INFO, 366 "No pointer back to namespace node in package %p", ObjDesc)); 367 return_ACPI_STATUS (AE_AML_INTERNAL); 368 } 369 370 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package Arg Init\n")); 371 372 /* Execute the AML code for the TermArg arguments */ 373 374 Status = AcpiDsExecuteArguments (Node, Node, 375 ObjDesc->Package.AmlLength, ObjDesc->Package.AmlStart); 376 return_ACPI_STATUS (Status); 377 } 378 379 380 /******************************************************************************* 381 * 382 * FUNCTION: AcpiDsGetRegionArguments 383 * 384 * PARAMETERS: ObjDesc - A valid region object 385 * 386 * RETURN: Status. 387 * 388 * DESCRIPTION: Get region address and length. This implements the late 389 * evaluation of these region attributes. 390 * 391 ******************************************************************************/ 392 393 ACPI_STATUS 394 AcpiDsGetRegionArguments ( 395 ACPI_OPERAND_OBJECT *ObjDesc) 396 { 397 ACPI_NAMESPACE_NODE *Node; 398 ACPI_STATUS Status; 399 ACPI_OPERAND_OBJECT *ExtraDesc; 400 401 402 ACPI_FUNCTION_TRACE_PTR (DsGetRegionArguments, ObjDesc); 403 404 405 if (ObjDesc->Region.Flags & AOPOBJ_DATA_VALID) 406 { 407 return_ACPI_STATUS (AE_OK); 408 } 409 410 ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc); 411 if (!ExtraDesc) 412 { 413 return_ACPI_STATUS (AE_NOT_EXIST); 414 } 415 416 /* Get the Region node */ 417 418 Node = ObjDesc->Region.Node; 419 420 ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (ACPI_TYPE_REGION, Node, NULL)); 421 422 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", 423 AcpiUtGetNodeName (Node), ExtraDesc->Extra.AmlStart)); 424 425 /* Execute the argument AML */ 426 427 Status = AcpiDsExecuteArguments (Node, ExtraDesc->Extra.ScopeNode, 428 ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart); 429 if (ACPI_FAILURE (Status)) 430 { 431 return_ACPI_STATUS (Status); 432 } 433 434 Status = AcpiUtAddAddressRange (ObjDesc->Region.SpaceId, 435 ObjDesc->Region.Address, ObjDesc->Region.Length, 436 Node); 437 return_ACPI_STATUS (Status); 438 } 439