1 /****************************************************************************** 2 * 3 * Module Name: dsobject - Dispatcher object management routines 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2021, 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 MERCHANTABILITY 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 "acpi.h" 45 #include "accommon.h" 46 #include "acparser.h" 47 #include "amlcode.h" 48 #include "acdispat.h" 49 #include "acnamesp.h" 50 #include "acinterp.h" 51 52 #define _COMPONENT ACPI_DISPATCHER 53 ACPI_MODULE_NAME ("dsobject") 54 55 56 /******************************************************************************* 57 * 58 * FUNCTION: AcpiDsBuildInternalObject 59 * 60 * PARAMETERS: WalkState - Current walk state 61 * Op - Parser object to be translated 62 * ObjDescPtr - Where the ACPI internal object is returned 63 * 64 * RETURN: Status 65 * 66 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object 67 * Simple objects are any objects other than a package object! 68 * 69 ******************************************************************************/ 70 71 ACPI_STATUS 72 AcpiDsBuildInternalObject ( 73 ACPI_WALK_STATE *WalkState, 74 ACPI_PARSE_OBJECT *Op, 75 ACPI_OPERAND_OBJECT **ObjDescPtr) 76 { 77 ACPI_OPERAND_OBJECT *ObjDesc; 78 ACPI_STATUS Status; 79 80 81 ACPI_FUNCTION_TRACE (DsBuildInternalObject); 82 83 84 *ObjDescPtr = NULL; 85 if (Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) 86 { 87 /* 88 * This is a named object reference. If this name was 89 * previously looked up in the namespace, it was stored in 90 * this op. Otherwise, go ahead and look it up now 91 */ 92 if (!Op->Common.Node) 93 { 94 /* Check if we are resolving a named reference within a package */ 95 96 if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 97 (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)) 98 { 99 /* 100 * We won't resolve package elements here, we will do this 101 * after all ACPI tables are loaded into the namespace. This 102 * behavior supports both forward references to named objects 103 * and external references to objects in other tables. 104 */ 105 goto CreateNewObject; 106 } 107 else 108 { 109 Status = AcpiNsLookup (WalkState->ScopeInfo, 110 Op->Common.Value.String, 111 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, 112 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, 113 ACPI_CAST_INDIRECT_PTR ( 114 ACPI_NAMESPACE_NODE, &(Op->Common.Node))); 115 if (ACPI_FAILURE (Status)) 116 { 117 ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo, 118 Op->Common.Value.String, Status); 119 return_ACPI_STATUS (Status); 120 } 121 } 122 } 123 } 124 125 CreateNewObject: 126 127 /* Create and init a new internal ACPI object */ 128 129 ObjDesc = AcpiUtCreateInternalObject ( 130 (AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode))->ObjectType); 131 if (!ObjDesc) 132 { 133 return_ACPI_STATUS (AE_NO_MEMORY); 134 } 135 136 Status = AcpiDsInitObjectFromOp ( 137 WalkState, Op, Op->Common.AmlOpcode, &ObjDesc); 138 if (ACPI_FAILURE (Status)) 139 { 140 AcpiUtRemoveReference (ObjDesc); 141 return_ACPI_STATUS (Status); 142 } 143 144 /* 145 * Handling for unresolved package reference elements. 146 * These are elements that are namepaths. 147 */ 148 if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || 149 (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)) 150 { 151 ObjDesc->Reference.Resolved = TRUE; 152 153 if ((Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && 154 !ObjDesc->Reference.Node) 155 { 156 /* 157 * Name was unresolved above. 158 * Get the prefix node for later lookup 159 */ 160 ObjDesc->Reference.Node = WalkState->ScopeInfo->Scope.Node; 161 ObjDesc->Reference.Aml = Op->Common.Aml; 162 ObjDesc->Reference.Resolved = FALSE; 163 } 164 } 165 166 *ObjDescPtr = ObjDesc; 167 return_ACPI_STATUS (Status); 168 } 169 170 171 /******************************************************************************* 172 * 173 * FUNCTION: AcpiDsBuildInternalBufferObj 174 * 175 * PARAMETERS: WalkState - Current walk state 176 * Op - Parser object to be translated 177 * BufferLength - Length of the buffer 178 * ObjDescPtr - Where the ACPI internal object is returned 179 * 180 * RETURN: Status 181 * 182 * DESCRIPTION: Translate a parser Op package object to the equivalent 183 * namespace object 184 * 185 ******************************************************************************/ 186 187 ACPI_STATUS 188 AcpiDsBuildInternalBufferObj ( 189 ACPI_WALK_STATE *WalkState, 190 ACPI_PARSE_OBJECT *Op, 191 UINT32 BufferLength, 192 ACPI_OPERAND_OBJECT **ObjDescPtr) 193 { 194 ACPI_PARSE_OBJECT *Arg; 195 ACPI_OPERAND_OBJECT *ObjDesc; 196 ACPI_PARSE_OBJECT *ByteList; 197 UINT32 ByteListLength = 0; 198 199 200 ACPI_FUNCTION_TRACE (DsBuildInternalBufferObj); 201 202 203 /* 204 * If we are evaluating a Named buffer object "Name (xxxx, Buffer)". 205 * The buffer object already exists (from the NS node), otherwise it must 206 * be created. 207 */ 208 ObjDesc = *ObjDescPtr; 209 if (!ObjDesc) 210 { 211 /* Create a new buffer object */ 212 213 ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER); 214 *ObjDescPtr = ObjDesc; 215 if (!ObjDesc) 216 { 217 return_ACPI_STATUS (AE_NO_MEMORY); 218 } 219 } 220 221 /* 222 * Second arg is the buffer data (optional) ByteList can be either 223 * individual bytes or a string initializer. In either case, a 224 * ByteList appears in the AML. 225 */ 226 Arg = Op->Common.Value.Arg; /* skip first arg */ 227 228 ByteList = Arg->Named.Next; 229 if (ByteList) 230 { 231 if (ByteList->Common.AmlOpcode != AML_INT_BYTELIST_OP) 232 { 233 ACPI_ERROR ((AE_INFO, 234 "Expecting bytelist, found AML opcode 0x%X in op %p", 235 ByteList->Common.AmlOpcode, ByteList)); 236 237 AcpiUtRemoveReference (ObjDesc); 238 return (AE_TYPE); 239 } 240 241 ByteListLength = (UINT32) ByteList->Common.Value.Integer; 242 } 243 244 /* 245 * The buffer length (number of bytes) will be the larger of: 246 * 1) The specified buffer length and 247 * 2) The length of the initializer byte list 248 */ 249 ObjDesc->Buffer.Length = BufferLength; 250 if (ByteListLength > BufferLength) 251 { 252 ObjDesc->Buffer.Length = ByteListLength; 253 } 254 255 /* Allocate the buffer */ 256 257 if (ObjDesc->Buffer.Length == 0) 258 { 259 ObjDesc->Buffer.Pointer = NULL; 260 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 261 "Buffer defined with zero length in AML, creating\n")); 262 } 263 else 264 { 265 ObjDesc->Buffer.Pointer = 266 ACPI_ALLOCATE_ZEROED (ObjDesc->Buffer.Length); 267 if (!ObjDesc->Buffer.Pointer) 268 { 269 AcpiUtDeleteObjectDesc (ObjDesc); 270 return_ACPI_STATUS (AE_NO_MEMORY); 271 } 272 273 /* Initialize buffer from the ByteList (if present) */ 274 275 if (ByteList) 276 { 277 memcpy (ObjDesc->Buffer.Pointer, ByteList->Named.Data, 278 ByteListLength); 279 } 280 } 281 282 ObjDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; 283 Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc); 284 return_ACPI_STATUS (AE_OK); 285 } 286 287 /******************************************************************************* 288 * 289 * FUNCTION: AcpiDsCreateNode 290 * 291 * PARAMETERS: WalkState - Current walk state 292 * Node - NS Node to be initialized 293 * Op - Parser object to be translated 294 * 295 * RETURN: Status 296 * 297 * DESCRIPTION: Create the object to be associated with a namespace node 298 * 299 ******************************************************************************/ 300 301 ACPI_STATUS 302 AcpiDsCreateNode ( 303 ACPI_WALK_STATE *WalkState, 304 ACPI_NAMESPACE_NODE *Node, 305 ACPI_PARSE_OBJECT *Op) 306 { 307 ACPI_STATUS Status; 308 ACPI_OPERAND_OBJECT *ObjDesc; 309 310 311 ACPI_FUNCTION_TRACE_PTR (DsCreateNode, Op); 312 313 314 /* 315 * Because of the execution pass through the non-control-method 316 * parts of the table, we can arrive here twice. Only init 317 * the named object node the first time through 318 */ 319 if (AcpiNsGetAttachedObject (Node)) 320 { 321 return_ACPI_STATUS (AE_OK); 322 } 323 324 if (!Op->Common.Value.Arg) 325 { 326 /* No arguments, there is nothing to do */ 327 328 return_ACPI_STATUS (AE_OK); 329 } 330 331 /* Build an internal object for the argument(s) */ 332 333 Status = AcpiDsBuildInternalObject ( 334 WalkState, Op->Common.Value.Arg, &ObjDesc); 335 if (ACPI_FAILURE (Status)) 336 { 337 return_ACPI_STATUS (Status); 338 } 339 340 /* Re-type the object according to its argument */ 341 342 Node->Type = ObjDesc->Common.Type; 343 344 /* Attach obj to node */ 345 346 Status = AcpiNsAttachObject (Node, ObjDesc, Node->Type); 347 348 /* Remove local reference to the object */ 349 350 AcpiUtRemoveReference (ObjDesc); 351 return_ACPI_STATUS (Status); 352 } 353 354 355 /******************************************************************************* 356 * 357 * FUNCTION: AcpiDsInitObjectFromOp 358 * 359 * PARAMETERS: WalkState - Current walk state 360 * Op - Parser op used to init the internal object 361 * Opcode - AML opcode associated with the object 362 * RetObjDesc - Namespace object to be initialized 363 * 364 * RETURN: Status 365 * 366 * DESCRIPTION: Initialize a namespace object from a parser Op and its 367 * associated arguments. The namespace object is a more compact 368 * representation of the Op and its arguments. 369 * 370 ******************************************************************************/ 371 372 ACPI_STATUS 373 AcpiDsInitObjectFromOp ( 374 ACPI_WALK_STATE *WalkState, 375 ACPI_PARSE_OBJECT *Op, 376 UINT16 Opcode, 377 ACPI_OPERAND_OBJECT **RetObjDesc) 378 { 379 const ACPI_OPCODE_INFO *OpInfo; 380 ACPI_OPERAND_OBJECT *ObjDesc; 381 ACPI_STATUS Status = AE_OK; 382 383 384 ACPI_FUNCTION_TRACE (DsInitObjectFromOp); 385 386 387 ObjDesc = *RetObjDesc; 388 OpInfo = AcpiPsGetOpcodeInfo (Opcode); 389 if (OpInfo->Class == AML_CLASS_UNKNOWN) 390 { 391 /* Unknown opcode */ 392 393 return_ACPI_STATUS (AE_TYPE); 394 } 395 396 /* Perform per-object initialization */ 397 398 switch (ObjDesc->Common.Type) 399 { 400 case ACPI_TYPE_BUFFER: 401 /* 402 * Defer evaluation of Buffer TermArg operand 403 */ 404 ObjDesc->Buffer.Node = ACPI_CAST_PTR ( 405 ACPI_NAMESPACE_NODE, WalkState->Operands[0]); 406 ObjDesc->Buffer.AmlStart = Op->Named.Data; 407 ObjDesc->Buffer.AmlLength = Op->Named.Length; 408 break; 409 410 case ACPI_TYPE_PACKAGE: 411 /* 412 * Defer evaluation of Package TermArg operand and all 413 * package elements. (01/2017): We defer the element 414 * resolution to allow forward references from the package 415 * in order to provide compatibility with other ACPI 416 * implementations. 417 */ 418 ObjDesc->Package.Node = ACPI_CAST_PTR ( 419 ACPI_NAMESPACE_NODE, WalkState->Operands[0]); 420 421 if (!Op->Named.Data) 422 { 423 return_ACPI_STATUS (AE_OK); 424 } 425 426 ObjDesc->Package.AmlStart = Op->Named.Data; 427 ObjDesc->Package.AmlLength = Op->Named.Length; 428 break; 429 430 case ACPI_TYPE_INTEGER: 431 432 switch (OpInfo->Type) 433 { 434 case AML_TYPE_CONSTANT: 435 /* 436 * Resolve AML Constants here - AND ONLY HERE! 437 * All constants are integers. 438 * We mark the integer with a flag that indicates that it started 439 * life as a constant -- so that stores to constants will perform 440 * as expected (noop). ZeroOp is used as a placeholder for optional 441 * target operands. 442 */ 443 ObjDesc->Common.Flags = AOPOBJ_AML_CONSTANT; 444 445 switch (Opcode) 446 { 447 case AML_ZERO_OP: 448 449 ObjDesc->Integer.Value = 0; 450 break; 451 452 case AML_ONE_OP: 453 454 ObjDesc->Integer.Value = 1; 455 break; 456 457 case AML_ONES_OP: 458 459 ObjDesc->Integer.Value = ACPI_UINT64_MAX; 460 461 /* Truncate value if we are executing from a 32-bit ACPI table */ 462 463 (void) AcpiExTruncateFor32bitTable (ObjDesc); 464 break; 465 466 case AML_REVISION_OP: 467 468 ObjDesc->Integer.Value = ACPI_CA_VERSION; 469 break; 470 471 default: 472 473 ACPI_ERROR ((AE_INFO, 474 "Unknown constant opcode 0x%X", Opcode)); 475 Status = AE_AML_OPERAND_TYPE; 476 break; 477 } 478 break; 479 480 case AML_TYPE_LITERAL: 481 482 ObjDesc->Integer.Value = Op->Common.Value.Integer; 483 484 if (AcpiExTruncateFor32bitTable (ObjDesc)) 485 { 486 /* Warn if we found a 64-bit constant in a 32-bit table */ 487 488 ACPI_WARNING ((AE_INFO, 489 "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X", 490 ACPI_FORMAT_UINT64 (Op->Common.Value.Integer), 491 (UINT32) ObjDesc->Integer.Value)); 492 } 493 break; 494 495 default: 496 497 ACPI_ERROR ((AE_INFO, "Unknown Integer type 0x%X", 498 OpInfo->Type)); 499 Status = AE_AML_OPERAND_TYPE; 500 break; 501 } 502 break; 503 504 case ACPI_TYPE_STRING: 505 506 ObjDesc->String.Pointer = Op->Common.Value.String; 507 ObjDesc->String.Length = (UINT32) strlen (Op->Common.Value.String); 508 509 /* 510 * The string is contained in the ACPI table, don't ever try 511 * to delete it 512 */ 513 ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER; 514 break; 515 516 case ACPI_TYPE_METHOD: 517 break; 518 519 case ACPI_TYPE_LOCAL_REFERENCE: 520 521 switch (OpInfo->Type) 522 { 523 case AML_TYPE_LOCAL_VARIABLE: 524 525 /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */ 526 527 ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_LOCAL_OP; 528 ObjDesc->Reference.Class = ACPI_REFCLASS_LOCAL; 529 530 Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_LOCAL, 531 ObjDesc->Reference.Value, WalkState, 532 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, 533 &ObjDesc->Reference.Object)); 534 break; 535 536 case AML_TYPE_METHOD_ARGUMENT: 537 538 /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */ 539 540 ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_ARG_OP; 541 ObjDesc->Reference.Class = ACPI_REFCLASS_ARG; 542 543 Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_ARG, 544 ObjDesc->Reference.Value, WalkState, 545 ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, 546 &ObjDesc->Reference.Object)); 547 break; 548 549 default: /* Object name or Debug object */ 550 551 switch (Op->Common.AmlOpcode) 552 { 553 case AML_INT_NAMEPATH_OP: 554 555 /* Node was saved in Op */ 556 557 ObjDesc->Reference.Node = Op->Common.Node; 558 ObjDesc->Reference.Class = ACPI_REFCLASS_NAME; 559 if (Op->Common.Node) 560 { 561 ObjDesc->Reference.Object = Op->Common.Node->Object; 562 } 563 break; 564 565 case AML_DEBUG_OP: 566 567 ObjDesc->Reference.Class = ACPI_REFCLASS_DEBUG; 568 break; 569 570 default: 571 572 ACPI_ERROR ((AE_INFO, 573 "Unimplemented reference type for AML opcode: 0x%4.4X", Opcode)); 574 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 575 } 576 break; 577 } 578 break; 579 580 default: 581 582 ACPI_ERROR ((AE_INFO, "Unimplemented data type: 0x%X", 583 ObjDesc->Common.Type)); 584 585 Status = AE_AML_OPERAND_TYPE; 586 break; 587 } 588 589 return_ACPI_STATUS (Status); 590 } 591