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