1 /****************************************************************************** 2 * 3 * Module Name: exoparg2 - AML execution - opcodes with 2 arguments 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 <contrib/dev/acpica/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 #include <contrib/dev/acpica/include/acparser.h> 47 #include <contrib/dev/acpica/include/acinterp.h> 48 #include <contrib/dev/acpica/include/acevents.h> 49 #include <contrib/dev/acpica/include/amlcode.h> 50 51 52 #define _COMPONENT ACPI_EXECUTER 53 ACPI_MODULE_NAME ("exoparg2") 54 55 56 /*! 57 * Naming convention for AML interpreter execution routines. 58 * 59 * The routines that begin execution of AML opcodes are named with a common 60 * convention based upon the number of arguments, the number of target operands, 61 * and whether or not a value is returned: 62 * 63 * AcpiExOpcode_xA_yT_zR 64 * 65 * Where: 66 * 67 * xA - ARGUMENTS: The number of arguments (input operands) that are 68 * required for this opcode type (1 through 6 args). 69 * yT - TARGETS: The number of targets (output operands) that are required 70 * for this opcode type (0, 1, or 2 targets). 71 * zR - RETURN VALUE: Indicates whether this opcode type returns a value 72 * as the function return (0 or 1). 73 * 74 * The AcpiExOpcode* functions are called via the Dispatcher component with 75 * fully resolved operands. 76 !*/ 77 78 79 /******************************************************************************* 80 * 81 * FUNCTION: AcpiExOpcode_2A_0T_0R 82 * 83 * PARAMETERS: WalkState - Current walk state 84 * 85 * RETURN: Status 86 * 87 * DESCRIPTION: Execute opcode with two arguments, no target, and no return 88 * value. 89 * 90 * ALLOCATION: Deletes both operands 91 * 92 ******************************************************************************/ 93 94 ACPI_STATUS 95 AcpiExOpcode_2A_0T_0R ( 96 ACPI_WALK_STATE *WalkState) 97 { 98 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 99 ACPI_NAMESPACE_NODE *Node; 100 UINT32 Value; 101 ACPI_STATUS Status = AE_OK; 102 103 104 ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_0R, 105 AcpiPsGetOpcodeName (WalkState->Opcode)); 106 107 108 /* Examine the opcode */ 109 110 switch (WalkState->Opcode) 111 { 112 case AML_NOTIFY_OP: /* Notify (NotifyObject, NotifyValue) */ 113 114 /* The first operand is a namespace node */ 115 116 Node = (ACPI_NAMESPACE_NODE *) Operand[0]; 117 118 /* Second value is the notify value */ 119 120 Value = (UINT32) Operand[1]->Integer.Value; 121 122 /* Are notifies allowed on this object? */ 123 124 if (!AcpiEvIsNotifyObject (Node)) 125 { 126 ACPI_ERROR ((AE_INFO, 127 "Unexpected notify object type [%s]", 128 AcpiUtGetTypeName (Node->Type))); 129 130 Status = AE_AML_OPERAND_TYPE; 131 break; 132 } 133 134 /* 135 * Dispatch the notify to the appropriate handler 136 * NOTE: the request is queued for execution after this method 137 * completes. The notify handlers are NOT invoked synchronously 138 * from this thread -- because handlers may in turn run other 139 * control methods. 140 */ 141 Status = AcpiEvQueueNotifyRequest (Node, Value); 142 break; 143 144 default: 145 146 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 147 WalkState->Opcode)); 148 Status = AE_AML_BAD_OPCODE; 149 } 150 151 return_ACPI_STATUS (Status); 152 } 153 154 155 /******************************************************************************* 156 * 157 * FUNCTION: AcpiExOpcode_2A_2T_1R 158 * 159 * PARAMETERS: WalkState - Current walk state 160 * 161 * RETURN: Status 162 * 163 * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets 164 * and one implicit return value. 165 * 166 ******************************************************************************/ 167 168 ACPI_STATUS 169 AcpiExOpcode_2A_2T_1R ( 170 ACPI_WALK_STATE *WalkState) 171 { 172 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 173 ACPI_OPERAND_OBJECT *ReturnDesc1 = NULL; 174 ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL; 175 ACPI_STATUS Status; 176 177 178 ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_2T_1R, 179 AcpiPsGetOpcodeName (WalkState->Opcode)); 180 181 182 /* Execute the opcode */ 183 184 switch (WalkState->Opcode) 185 { 186 case AML_DIVIDE_OP: 187 188 /* Divide (Dividend, Divisor, RemainderResult QuotientResult) */ 189 190 ReturnDesc1 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 191 if (!ReturnDesc1) 192 { 193 Status = AE_NO_MEMORY; 194 goto Cleanup; 195 } 196 197 ReturnDesc2 = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 198 if (!ReturnDesc2) 199 { 200 Status = AE_NO_MEMORY; 201 goto Cleanup; 202 } 203 204 /* Quotient to ReturnDesc1, remainder to ReturnDesc2 */ 205 206 Status = AcpiUtDivide (Operand[0]->Integer.Value, 207 Operand[1]->Integer.Value, 208 &ReturnDesc1->Integer.Value, 209 &ReturnDesc2->Integer.Value); 210 if (ACPI_FAILURE (Status)) 211 { 212 goto Cleanup; 213 } 214 break; 215 216 default: 217 218 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 219 WalkState->Opcode)); 220 Status = AE_AML_BAD_OPCODE; 221 goto Cleanup; 222 } 223 224 /* Store the results to the target reference operands */ 225 226 Status = AcpiExStore (ReturnDesc2, Operand[2], WalkState); 227 if (ACPI_FAILURE (Status)) 228 { 229 goto Cleanup; 230 } 231 232 Status = AcpiExStore (ReturnDesc1, Operand[3], WalkState); 233 if (ACPI_FAILURE (Status)) 234 { 235 goto Cleanup; 236 } 237 238 Cleanup: 239 /* 240 * Since the remainder is not returned indirectly, remove a reference to 241 * it. Only the quotient is returned indirectly. 242 */ 243 AcpiUtRemoveReference (ReturnDesc2); 244 245 if (ACPI_FAILURE (Status)) 246 { 247 /* Delete the return object */ 248 249 AcpiUtRemoveReference (ReturnDesc1); 250 } 251 252 /* Save return object (the remainder) on success */ 253 254 else 255 { 256 WalkState->ResultObj = ReturnDesc1; 257 } 258 259 return_ACPI_STATUS (Status); 260 } 261 262 263 /******************************************************************************* 264 * 265 * FUNCTION: AcpiExOpcode_2A_1T_1R 266 * 267 * PARAMETERS: WalkState - Current walk state 268 * 269 * RETURN: Status 270 * 271 * DESCRIPTION: Execute opcode with two arguments, one target, and a return 272 * value. 273 * 274 ******************************************************************************/ 275 276 ACPI_STATUS 277 AcpiExOpcode_2A_1T_1R ( 278 ACPI_WALK_STATE *WalkState) 279 { 280 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 281 ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 282 UINT64 Index; 283 ACPI_STATUS Status = AE_OK; 284 ACPI_SIZE Length = 0; 285 286 287 ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_1T_1R, 288 AcpiPsGetOpcodeName (WalkState->Opcode)); 289 290 291 /* Execute the opcode */ 292 293 if (WalkState->OpInfo->Flags & AML_MATH) 294 { 295 /* All simple math opcodes (add, etc.) */ 296 297 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 298 if (!ReturnDesc) 299 { 300 Status = AE_NO_MEMORY; 301 goto Cleanup; 302 } 303 304 ReturnDesc->Integer.Value = AcpiExDoMathOp (WalkState->Opcode, 305 Operand[0]->Integer.Value, 306 Operand[1]->Integer.Value); 307 goto StoreResultToTarget; 308 } 309 310 switch (WalkState->Opcode) 311 { 312 case AML_MOD_OP: /* Mod (Dividend, Divisor, RemainderResult (ACPI 2.0) */ 313 314 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 315 if (!ReturnDesc) 316 { 317 Status = AE_NO_MEMORY; 318 goto Cleanup; 319 } 320 321 /* ReturnDesc will contain the remainder */ 322 323 Status = AcpiUtDivide (Operand[0]->Integer.Value, 324 Operand[1]->Integer.Value, 325 NULL, 326 &ReturnDesc->Integer.Value); 327 break; 328 329 case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */ 330 331 Status = AcpiExDoConcatenate (Operand[0], Operand[1], 332 &ReturnDesc, WalkState); 333 break; 334 335 case AML_TO_STRING_OP: /* ToString (Buffer, Length, Result) (ACPI 2.0) */ 336 /* 337 * Input object is guaranteed to be a buffer at this point (it may have 338 * been converted.) Copy the raw buffer data to a new object of 339 * type String. 340 */ 341 342 /* 343 * Get the length of the new string. It is the smallest of: 344 * 1) Length of the input buffer 345 * 2) Max length as specified in the ToString operator 346 * 3) Length of input buffer up to a zero byte (null terminator) 347 * 348 * NOTE: A length of zero is ok, and will create a zero-length, null 349 * terminated string. 350 */ 351 while ((Length < Operand[0]->Buffer.Length) && 352 (Length < Operand[1]->Integer.Value) && 353 (Operand[0]->Buffer.Pointer[Length])) 354 { 355 Length++; 356 } 357 358 /* Allocate a new string object */ 359 360 ReturnDesc = AcpiUtCreateStringObject (Length); 361 if (!ReturnDesc) 362 { 363 Status = AE_NO_MEMORY; 364 goto Cleanup; 365 } 366 367 /* 368 * Copy the raw buffer data with no transform. 369 * (NULL terminated already) 370 */ 371 memcpy (ReturnDesc->String.Pointer, 372 Operand[0]->Buffer.Pointer, Length); 373 break; 374 375 case AML_CONCAT_RES_OP: 376 377 /* ConcatenateResTemplate (Buffer, Buffer, Result) (ACPI 2.0) */ 378 379 Status = AcpiExConcatTemplate (Operand[0], Operand[1], 380 &ReturnDesc, WalkState); 381 break; 382 383 case AML_INDEX_OP: /* Index (Source Index Result) */ 384 385 /* Create the internal return object */ 386 387 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); 388 if (!ReturnDesc) 389 { 390 Status = AE_NO_MEMORY; 391 goto Cleanup; 392 } 393 394 /* Initialize the Index reference object */ 395 396 Index = Operand[1]->Integer.Value; 397 ReturnDesc->Reference.Value = (UINT32) Index; 398 ReturnDesc->Reference.Class = ACPI_REFCLASS_INDEX; 399 400 /* 401 * At this point, the Source operand is a String, Buffer, or Package. 402 * Verify that the index is within range. 403 */ 404 switch ((Operand[0])->Common.Type) 405 { 406 case ACPI_TYPE_STRING: 407 408 if (Index >= Operand[0]->String.Length) 409 { 410 Length = Operand[0]->String.Length; 411 Status = AE_AML_STRING_LIMIT; 412 } 413 414 ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; 415 ReturnDesc->Reference.IndexPointer = 416 &(Operand[0]->Buffer.Pointer [Index]); 417 break; 418 419 case ACPI_TYPE_BUFFER: 420 421 if (Index >= Operand[0]->Buffer.Length) 422 { 423 Length = Operand[0]->Buffer.Length; 424 Status = AE_AML_BUFFER_LIMIT; 425 } 426 427 ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; 428 ReturnDesc->Reference.IndexPointer = 429 &(Operand[0]->Buffer.Pointer [Index]); 430 break; 431 432 case ACPI_TYPE_PACKAGE: 433 434 if (Index >= Operand[0]->Package.Count) 435 { 436 Length = Operand[0]->Package.Count; 437 Status = AE_AML_PACKAGE_LIMIT; 438 } 439 440 ReturnDesc->Reference.TargetType = ACPI_TYPE_PACKAGE; 441 ReturnDesc->Reference.Where = 442 &Operand[0]->Package.Elements [Index]; 443 break; 444 445 default: 446 447 Status = AE_AML_INTERNAL; 448 goto Cleanup; 449 } 450 451 /* Failure means that the Index was beyond the end of the object */ 452 453 if (ACPI_FAILURE (Status)) 454 { 455 ACPI_EXCEPTION ((AE_INFO, Status, 456 "Index (0x%X%8.8X) is beyond end of object (length 0x%X)", 457 ACPI_FORMAT_UINT64 (Index), (UINT32) Length)); 458 goto Cleanup; 459 } 460 461 /* 462 * Save the target object and add a reference to it for the life 463 * of the index 464 */ 465 ReturnDesc->Reference.Object = Operand[0]; 466 AcpiUtAddReference (Operand[0]); 467 468 /* Store the reference to the Target */ 469 470 Status = AcpiExStore (ReturnDesc, Operand[2], WalkState); 471 472 /* Return the reference */ 473 474 WalkState->ResultObj = ReturnDesc; 475 goto Cleanup; 476 477 default: 478 479 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 480 WalkState->Opcode)); 481 Status = AE_AML_BAD_OPCODE; 482 break; 483 } 484 485 486 StoreResultToTarget: 487 488 if (ACPI_SUCCESS (Status)) 489 { 490 /* 491 * Store the result of the operation (which is now in ReturnDesc) into 492 * the Target descriptor. 493 */ 494 Status = AcpiExStore (ReturnDesc, Operand[2], WalkState); 495 if (ACPI_FAILURE (Status)) 496 { 497 goto Cleanup; 498 } 499 500 if (!WalkState->ResultObj) 501 { 502 WalkState->ResultObj = ReturnDesc; 503 } 504 } 505 506 507 Cleanup: 508 509 /* Delete return object on error */ 510 511 if (ACPI_FAILURE (Status)) 512 { 513 AcpiUtRemoveReference (ReturnDesc); 514 WalkState->ResultObj = NULL; 515 } 516 517 return_ACPI_STATUS (Status); 518 } 519 520 521 /******************************************************************************* 522 * 523 * FUNCTION: AcpiExOpcode_2A_0T_1R 524 * 525 * PARAMETERS: WalkState - Current walk state 526 * 527 * RETURN: Status 528 * 529 * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value 530 * 531 ******************************************************************************/ 532 533 ACPI_STATUS 534 AcpiExOpcode_2A_0T_1R ( 535 ACPI_WALK_STATE *WalkState) 536 { 537 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; 538 ACPI_OPERAND_OBJECT *ReturnDesc = NULL; 539 ACPI_STATUS Status = AE_OK; 540 BOOLEAN LogicalResult = FALSE; 541 542 543 ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_0T_1R, 544 AcpiPsGetOpcodeName (WalkState->Opcode)); 545 546 547 /* Create the internal return object */ 548 549 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 550 if (!ReturnDesc) 551 { 552 Status = AE_NO_MEMORY; 553 goto Cleanup; 554 } 555 556 /* Execute the Opcode */ 557 558 if (WalkState->OpInfo->Flags & AML_LOGICAL_NUMERIC) 559 { 560 /* LogicalOp (Operand0, Operand1) */ 561 562 Status = AcpiExDoLogicalNumericOp (WalkState->Opcode, 563 Operand[0]->Integer.Value, Operand[1]->Integer.Value, 564 &LogicalResult); 565 goto StoreLogicalResult; 566 } 567 else if (WalkState->OpInfo->Flags & AML_LOGICAL) 568 { 569 /* LogicalOp (Operand0, Operand1) */ 570 571 Status = AcpiExDoLogicalOp (WalkState->Opcode, Operand[0], 572 Operand[1], &LogicalResult); 573 goto StoreLogicalResult; 574 } 575 576 switch (WalkState->Opcode) 577 { 578 case AML_ACQUIRE_OP: /* Acquire (MutexObject, Timeout) */ 579 580 Status = AcpiExAcquireMutex (Operand[1], Operand[0], WalkState); 581 if (Status == AE_TIME) 582 { 583 LogicalResult = TRUE; /* TRUE = Acquire timed out */ 584 Status = AE_OK; 585 } 586 break; 587 588 589 case AML_WAIT_OP: /* Wait (EventObject, Timeout) */ 590 591 Status = AcpiExSystemWaitEvent (Operand[1], Operand[0]); 592 if (Status == AE_TIME) 593 { 594 LogicalResult = TRUE; /* TRUE, Wait timed out */ 595 Status = AE_OK; 596 } 597 break; 598 599 default: 600 601 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", 602 WalkState->Opcode)); 603 Status = AE_AML_BAD_OPCODE; 604 goto Cleanup; 605 } 606 607 608 StoreLogicalResult: 609 /* 610 * Set return value to according to LogicalResult. logical TRUE (all ones) 611 * Default is FALSE (zero) 612 */ 613 if (LogicalResult) 614 { 615 ReturnDesc->Integer.Value = ACPI_UINT64_MAX; 616 } 617 618 Cleanup: 619 620 /* Delete return object on error */ 621 622 if (ACPI_FAILURE (Status)) 623 { 624 AcpiUtRemoveReference (ReturnDesc); 625 } 626 627 /* Save return object on success */ 628 629 else 630 { 631 WalkState->ResultObj = ReturnDesc; 632 } 633 634 return_ACPI_STATUS (Status); 635 } 636