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 - 2021, 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 MERCHANTABILITY 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 "acpi.h" 46 #include "accommon.h" 47 #include "acparser.h" 48 #include "amlcode.h" 49 #include "acdispat.h" 50 #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_PTR (DsExecuteArguments, AmlStart); 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 ( 218 ACPI_TYPE_BUFFER_FIELD, 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 ( 267 ACPI_TYPE_LOCAL_BANK_FIELD, 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", 316 ObjDesc)); 317 return_ACPI_STATUS (AE_AML_INTERNAL); 318 } 319 320 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer Arg Init\n")); 321 322 /* Execute the AML code for the TermArg arguments */ 323 324 Status = AcpiDsExecuteArguments (Node, Node, 325 ObjDesc->Buffer.AmlLength, ObjDesc->Buffer.AmlStart); 326 return_ACPI_STATUS (Status); 327 } 328 329 330 /******************************************************************************* 331 * 332 * FUNCTION: AcpiDsGetPackageArguments 333 * 334 * PARAMETERS: ObjDesc - A valid Package object 335 * 336 * RETURN: Status. 337 * 338 * DESCRIPTION: Get Package length and initializer byte list. This implements 339 * the late evaluation of these attributes. 340 * 341 ******************************************************************************/ 342 343 ACPI_STATUS 344 AcpiDsGetPackageArguments ( 345 ACPI_OPERAND_OBJECT *ObjDesc) 346 { 347 ACPI_NAMESPACE_NODE *Node; 348 ACPI_STATUS Status; 349 350 351 ACPI_FUNCTION_TRACE_PTR (DsGetPackageArguments, ObjDesc); 352 353 354 if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) 355 { 356 return_ACPI_STATUS (AE_OK); 357 } 358 359 /* Get the Package node */ 360 361 Node = ObjDesc->Package.Node; 362 if (!Node) 363 { 364 ACPI_ERROR ((AE_INFO, 365 "No pointer back to namespace node in package %p", ObjDesc)); 366 return_ACPI_STATUS (AE_AML_INTERNAL); 367 } 368 369 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package Argument Init, AML Ptr: %p\n", 370 ObjDesc->Package.AmlStart)); 371 372 /* Execute the AML code for the TermArg arguments */ 373 374 Status = AcpiDsExecuteArguments (Node, Node, 375 ObjDesc->Package.AmlLength, ObjDesc->Package.AmlStart); 376 377 return_ACPI_STATUS (Status); 378 } 379 380 381 /******************************************************************************* 382 * 383 * FUNCTION: AcpiDsGetRegionArguments 384 * 385 * PARAMETERS: ObjDesc - A valid region object 386 * 387 * RETURN: Status. 388 * 389 * DESCRIPTION: Get region address and length. This implements the late 390 * evaluation of these region attributes. 391 * 392 ******************************************************************************/ 393 394 ACPI_STATUS 395 AcpiDsGetRegionArguments ( 396 ACPI_OPERAND_OBJECT *ObjDesc) 397 { 398 ACPI_NAMESPACE_NODE *Node; 399 ACPI_STATUS Status; 400 ACPI_OPERAND_OBJECT *ExtraDesc; 401 402 403 ACPI_FUNCTION_TRACE_PTR (DsGetRegionArguments, ObjDesc); 404 405 406 if (ObjDesc->Region.Flags & AOPOBJ_DATA_VALID) 407 { 408 return_ACPI_STATUS (AE_OK); 409 } 410 411 ExtraDesc = AcpiNsGetSecondaryObject (ObjDesc); 412 if (!ExtraDesc) 413 { 414 return_ACPI_STATUS (AE_NOT_EXIST); 415 } 416 417 /* Get the Region node */ 418 419 Node = ObjDesc->Region.Node; 420 421 ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname ( 422 ACPI_TYPE_REGION, Node, NULL)); 423 424 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 425 "[%4.4s] OpRegion Arg Init at AML %p\n", 426 AcpiUtGetNodeName (Node), ExtraDesc->Extra.AmlStart)); 427 428 /* Execute the argument AML */ 429 430 Status = AcpiDsExecuteArguments (Node, ExtraDesc->Extra.ScopeNode, 431 ExtraDesc->Extra.AmlLength, ExtraDesc->Extra.AmlStart); 432 if (ACPI_FAILURE (Status)) 433 { 434 return_ACPI_STATUS (Status); 435 } 436 437 Status = AcpiUtAddAddressRange (ObjDesc->Region.SpaceId, 438 ObjDesc->Region.Address, ObjDesc->Region.Length, Node); 439 return_ACPI_STATUS (Status); 440 } 441