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