1 /****************************************************************************** 2 * 3 * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2012, 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 #define __EXMISC_C__ 45 46 #include <contrib/dev/acpica/include/acpi.h> 47 #include <contrib/dev/acpica/include/accommon.h> 48 #include <contrib/dev/acpica/include/acinterp.h> 49 #include <contrib/dev/acpica/include/amlcode.h> 50 #include <contrib/dev/acpica/include/amlresrc.h> 51 52 53 #define _COMPONENT ACPI_EXECUTER 54 ACPI_MODULE_NAME ("exmisc") 55 56 57 /******************************************************************************* 58 * 59 * FUNCTION: AcpiExGetObjectReference 60 * 61 * PARAMETERS: ObjDesc - Create a reference to this object 62 * ReturnDesc - Where to store the reference 63 * WalkState - Current state 64 * 65 * RETURN: Status 66 * 67 * DESCRIPTION: Obtain and return a "reference" to the target object 68 * Common code for the RefOfOp and the CondRefOfOp. 69 * 70 ******************************************************************************/ 71 72 ACPI_STATUS 73 AcpiExGetObjectReference ( 74 ACPI_OPERAND_OBJECT *ObjDesc, 75 ACPI_OPERAND_OBJECT **ReturnDesc, 76 ACPI_WALK_STATE *WalkState) 77 { 78 ACPI_OPERAND_OBJECT *ReferenceObj; 79 ACPI_OPERAND_OBJECT *ReferencedObj; 80 81 82 ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc); 83 84 85 *ReturnDesc = NULL; 86 87 switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) 88 { 89 case ACPI_DESC_TYPE_OPERAND: 90 91 if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) 92 { 93 return_ACPI_STATUS (AE_AML_OPERAND_TYPE); 94 } 95 96 /* 97 * Must be a reference to a Local or Arg 98 */ 99 switch (ObjDesc->Reference.Class) 100 { 101 case ACPI_REFCLASS_LOCAL: 102 case ACPI_REFCLASS_ARG: 103 case ACPI_REFCLASS_DEBUG: 104 105 /* The referenced object is the pseudo-node for the local/arg */ 106 107 ReferencedObj = ObjDesc->Reference.Object; 108 break; 109 110 default: 111 112 ACPI_ERROR ((AE_INFO, "Unknown Reference Class 0x%2.2X", 113 ObjDesc->Reference.Class)); 114 return_ACPI_STATUS (AE_AML_INTERNAL); 115 } 116 break; 117 118 119 case ACPI_DESC_TYPE_NAMED: 120 121 /* 122 * A named reference that has already been resolved to a Node 123 */ 124 ReferencedObj = ObjDesc; 125 break; 126 127 128 default: 129 130 ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X", 131 ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))); 132 return_ACPI_STATUS (AE_TYPE); 133 } 134 135 136 /* Create a new reference object */ 137 138 ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); 139 if (!ReferenceObj) 140 { 141 return_ACPI_STATUS (AE_NO_MEMORY); 142 } 143 144 ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF; 145 ReferenceObj->Reference.Object = ReferencedObj; 146 *ReturnDesc = ReferenceObj; 147 148 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, 149 "Object %p Type [%s], returning Reference %p\n", 150 ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc)); 151 152 return_ACPI_STATUS (AE_OK); 153 } 154 155 156 /******************************************************************************* 157 * 158 * FUNCTION: AcpiExConcatTemplate 159 * 160 * PARAMETERS: Operand0 - First source object 161 * Operand1 - Second source object 162 * ActualReturnDesc - Where to place the return object 163 * WalkState - Current walk state 164 * 165 * RETURN: Status 166 * 167 * DESCRIPTION: Concatenate two resource templates 168 * 169 ******************************************************************************/ 170 171 ACPI_STATUS 172 AcpiExConcatTemplate ( 173 ACPI_OPERAND_OBJECT *Operand0, 174 ACPI_OPERAND_OBJECT *Operand1, 175 ACPI_OPERAND_OBJECT **ActualReturnDesc, 176 ACPI_WALK_STATE *WalkState) 177 { 178 ACPI_STATUS Status; 179 ACPI_OPERAND_OBJECT *ReturnDesc; 180 UINT8 *NewBuf; 181 UINT8 *EndTag; 182 ACPI_SIZE Length0; 183 ACPI_SIZE Length1; 184 ACPI_SIZE NewLength; 185 186 187 ACPI_FUNCTION_TRACE (ExConcatTemplate); 188 189 190 /* 191 * Find the EndTag descriptor in each resource template. 192 * Note1: returned pointers point TO the EndTag, not past it. 193 * Note2: zero-length buffers are allowed; treated like one EndTag 194 */ 195 196 /* Get the length of the first resource template */ 197 198 Status = AcpiUtGetResourceEndTag (Operand0, &EndTag); 199 if (ACPI_FAILURE (Status)) 200 { 201 return_ACPI_STATUS (Status); 202 } 203 204 Length0 = ACPI_PTR_DIFF (EndTag, Operand0->Buffer.Pointer); 205 206 /* Get the length of the second resource template */ 207 208 Status = AcpiUtGetResourceEndTag (Operand1, &EndTag); 209 if (ACPI_FAILURE (Status)) 210 { 211 return_ACPI_STATUS (Status); 212 } 213 214 Length1 = ACPI_PTR_DIFF (EndTag, Operand1->Buffer.Pointer); 215 216 /* Combine both lengths, minimum size will be 2 for EndTag */ 217 218 NewLength = Length0 + Length1 + sizeof (AML_RESOURCE_END_TAG); 219 220 /* Create a new buffer object for the result (with one EndTag) */ 221 222 ReturnDesc = AcpiUtCreateBufferObject (NewLength); 223 if (!ReturnDesc) 224 { 225 return_ACPI_STATUS (AE_NO_MEMORY); 226 } 227 228 /* 229 * Copy the templates to the new buffer, 0 first, then 1 follows. One 230 * EndTag descriptor is copied from Operand1. 231 */ 232 NewBuf = ReturnDesc->Buffer.Pointer; 233 ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Length0); 234 ACPI_MEMCPY (NewBuf + Length0, Operand1->Buffer.Pointer, Length1); 235 236 /* Insert EndTag and set the checksum to zero, means "ignore checksum" */ 237 238 NewBuf[NewLength - 1] = 0; 239 NewBuf[NewLength - 2] = ACPI_RESOURCE_NAME_END_TAG | 1; 240 241 /* Return the completed resource template */ 242 243 *ActualReturnDesc = ReturnDesc; 244 return_ACPI_STATUS (AE_OK); 245 } 246 247 248 /******************************************************************************* 249 * 250 * FUNCTION: AcpiExDoConcatenate 251 * 252 * PARAMETERS: Operand0 - First source object 253 * Operand1 - Second source object 254 * ActualReturnDesc - Where to place the return object 255 * WalkState - Current walk state 256 * 257 * RETURN: Status 258 * 259 * DESCRIPTION: Concatenate two objects OF THE SAME TYPE. 260 * 261 ******************************************************************************/ 262 263 ACPI_STATUS 264 AcpiExDoConcatenate ( 265 ACPI_OPERAND_OBJECT *Operand0, 266 ACPI_OPERAND_OBJECT *Operand1, 267 ACPI_OPERAND_OBJECT **ActualReturnDesc, 268 ACPI_WALK_STATE *WalkState) 269 { 270 ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; 271 ACPI_OPERAND_OBJECT *ReturnDesc; 272 char *NewBuf; 273 ACPI_STATUS Status; 274 275 276 ACPI_FUNCTION_TRACE (ExDoConcatenate); 277 278 279 /* 280 * Convert the second operand if necessary. The first operand 281 * determines the type of the second operand, (See the Data Types 282 * section of the ACPI specification.) Both object types are 283 * guaranteed to be either Integer/String/Buffer by the operand 284 * resolution mechanism. 285 */ 286 switch (Operand0->Common.Type) 287 { 288 case ACPI_TYPE_INTEGER: 289 Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16); 290 break; 291 292 case ACPI_TYPE_STRING: 293 Status = AcpiExConvertToString (Operand1, &LocalOperand1, 294 ACPI_IMPLICIT_CONVERT_HEX); 295 break; 296 297 case ACPI_TYPE_BUFFER: 298 Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1); 299 break; 300 301 default: 302 ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", 303 Operand0->Common.Type)); 304 Status = AE_AML_INTERNAL; 305 } 306 307 if (ACPI_FAILURE (Status)) 308 { 309 goto Cleanup; 310 } 311 312 /* 313 * Both operands are now known to be the same object type 314 * (Both are Integer, String, or Buffer), and we can now perform the 315 * concatenation. 316 */ 317 318 /* 319 * There are three cases to handle: 320 * 321 * 1) Two Integers concatenated to produce a new Buffer 322 * 2) Two Strings concatenated to produce a new String 323 * 3) Two Buffers concatenated to produce a new Buffer 324 */ 325 switch (Operand0->Common.Type) 326 { 327 case ACPI_TYPE_INTEGER: 328 329 /* Result of two Integers is a Buffer */ 330 /* Need enough buffer space for two integers */ 331 332 ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE) 333 ACPI_MUL_2 (AcpiGbl_IntegerByteWidth)); 334 if (!ReturnDesc) 335 { 336 Status = AE_NO_MEMORY; 337 goto Cleanup; 338 } 339 340 NewBuf = (char *) ReturnDesc->Buffer.Pointer; 341 342 /* Copy the first integer, LSB first */ 343 344 ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value, 345 AcpiGbl_IntegerByteWidth); 346 347 /* Copy the second integer (LSB first) after the first */ 348 349 ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth, 350 &LocalOperand1->Integer.Value, 351 AcpiGbl_IntegerByteWidth); 352 break; 353 354 case ACPI_TYPE_STRING: 355 356 /* Result of two Strings is a String */ 357 358 ReturnDesc = AcpiUtCreateStringObject ( 359 ((ACPI_SIZE) Operand0->String.Length + 360 LocalOperand1->String.Length)); 361 if (!ReturnDesc) 362 { 363 Status = AE_NO_MEMORY; 364 goto Cleanup; 365 } 366 367 NewBuf = ReturnDesc->String.Pointer; 368 369 /* Concatenate the strings */ 370 371 ACPI_STRCPY (NewBuf, Operand0->String.Pointer); 372 ACPI_STRCPY (NewBuf + Operand0->String.Length, 373 LocalOperand1->String.Pointer); 374 break; 375 376 case ACPI_TYPE_BUFFER: 377 378 /* Result of two Buffers is a Buffer */ 379 380 ReturnDesc = AcpiUtCreateBufferObject ( 381 ((ACPI_SIZE) Operand0->Buffer.Length + 382 LocalOperand1->Buffer.Length)); 383 if (!ReturnDesc) 384 { 385 Status = AE_NO_MEMORY; 386 goto Cleanup; 387 } 388 389 NewBuf = (char *) ReturnDesc->Buffer.Pointer; 390 391 /* Concatenate the buffers */ 392 393 ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, 394 Operand0->Buffer.Length); 395 ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length, 396 LocalOperand1->Buffer.Pointer, 397 LocalOperand1->Buffer.Length); 398 break; 399 400 default: 401 402 /* Invalid object type, should not happen here */ 403 404 ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", 405 Operand0->Common.Type)); 406 Status =AE_AML_INTERNAL; 407 goto Cleanup; 408 } 409 410 *ActualReturnDesc = ReturnDesc; 411 412 Cleanup: 413 if (LocalOperand1 != Operand1) 414 { 415 AcpiUtRemoveReference (LocalOperand1); 416 } 417 return_ACPI_STATUS (Status); 418 } 419 420 421 /******************************************************************************* 422 * 423 * FUNCTION: AcpiExDoMathOp 424 * 425 * PARAMETERS: Opcode - AML opcode 426 * Integer0 - Integer operand #0 427 * Integer1 - Integer operand #1 428 * 429 * RETURN: Integer result of the operation 430 * 431 * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the 432 * math functions here is to prevent a lot of pointer dereferencing 433 * to obtain the operands. 434 * 435 ******************************************************************************/ 436 437 UINT64 438 AcpiExDoMathOp ( 439 UINT16 Opcode, 440 UINT64 Integer0, 441 UINT64 Integer1) 442 { 443 444 ACPI_FUNCTION_ENTRY (); 445 446 447 switch (Opcode) 448 { 449 case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */ 450 451 return (Integer0 + Integer1); 452 453 454 case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */ 455 456 return (Integer0 & Integer1); 457 458 459 case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */ 460 461 return (~(Integer0 & Integer1)); 462 463 464 case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */ 465 466 return (Integer0 | Integer1); 467 468 469 case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */ 470 471 return (~(Integer0 | Integer1)); 472 473 474 case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */ 475 476 return (Integer0 ^ Integer1); 477 478 479 case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */ 480 481 return (Integer0 * Integer1); 482 483 484 case AML_SHIFT_LEFT_OP: /* ShiftLeft (Operand, ShiftCount, Result)*/ 485 486 /* 487 * We need to check if the shiftcount is larger than the integer bit 488 * width since the behavior of this is not well-defined in the C language. 489 */ 490 if (Integer1 >= AcpiGbl_IntegerBitWidth) 491 { 492 return (0); 493 } 494 return (Integer0 << Integer1); 495 496 497 case AML_SHIFT_RIGHT_OP: /* ShiftRight (Operand, ShiftCount, Result) */ 498 499 /* 500 * We need to check if the shiftcount is larger than the integer bit 501 * width since the behavior of this is not well-defined in the C language. 502 */ 503 if (Integer1 >= AcpiGbl_IntegerBitWidth) 504 { 505 return (0); 506 } 507 return (Integer0 >> Integer1); 508 509 510 case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */ 511 512 return (Integer0 - Integer1); 513 514 default: 515 516 return (0); 517 } 518 } 519 520 521 /******************************************************************************* 522 * 523 * FUNCTION: AcpiExDoLogicalNumericOp 524 * 525 * PARAMETERS: Opcode - AML opcode 526 * Integer0 - Integer operand #0 527 * Integer1 - Integer operand #1 528 * LogicalResult - TRUE/FALSE result of the operation 529 * 530 * RETURN: Status 531 * 532 * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric 533 * operators (LAnd and LOr), both operands must be integers. 534 * 535 * Note: cleanest machine code seems to be produced by the code 536 * below, rather than using statements of the form: 537 * Result = (Integer0 && Integer1); 538 * 539 ******************************************************************************/ 540 541 ACPI_STATUS 542 AcpiExDoLogicalNumericOp ( 543 UINT16 Opcode, 544 UINT64 Integer0, 545 UINT64 Integer1, 546 BOOLEAN *LogicalResult) 547 { 548 ACPI_STATUS Status = AE_OK; 549 BOOLEAN LocalResult = FALSE; 550 551 552 ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp); 553 554 555 switch (Opcode) 556 { 557 case AML_LAND_OP: /* LAnd (Integer0, Integer1) */ 558 559 if (Integer0 && Integer1) 560 { 561 LocalResult = TRUE; 562 } 563 break; 564 565 case AML_LOR_OP: /* LOr (Integer0, Integer1) */ 566 567 if (Integer0 || Integer1) 568 { 569 LocalResult = TRUE; 570 } 571 break; 572 573 default: 574 Status = AE_AML_INTERNAL; 575 break; 576 } 577 578 /* Return the logical result and status */ 579 580 *LogicalResult = LocalResult; 581 return_ACPI_STATUS (Status); 582 } 583 584 585 /******************************************************************************* 586 * 587 * FUNCTION: AcpiExDoLogicalOp 588 * 589 * PARAMETERS: Opcode - AML opcode 590 * Operand0 - operand #0 591 * Operand1 - operand #1 592 * LogicalResult - TRUE/FALSE result of the operation 593 * 594 * RETURN: Status 595 * 596 * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the 597 * functions here is to prevent a lot of pointer dereferencing 598 * to obtain the operands and to simplify the generation of the 599 * logical value. For the Numeric operators (LAnd and LOr), both 600 * operands must be integers. For the other logical operators, 601 * operands can be any combination of Integer/String/Buffer. The 602 * first operand determines the type to which the second operand 603 * will be converted. 604 * 605 * Note: cleanest machine code seems to be produced by the code 606 * below, rather than using statements of the form: 607 * Result = (Operand0 == Operand1); 608 * 609 ******************************************************************************/ 610 611 ACPI_STATUS 612 AcpiExDoLogicalOp ( 613 UINT16 Opcode, 614 ACPI_OPERAND_OBJECT *Operand0, 615 ACPI_OPERAND_OBJECT *Operand1, 616 BOOLEAN *LogicalResult) 617 { 618 ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; 619 UINT64 Integer0; 620 UINT64 Integer1; 621 UINT32 Length0; 622 UINT32 Length1; 623 ACPI_STATUS Status = AE_OK; 624 BOOLEAN LocalResult = FALSE; 625 int Compare; 626 627 628 ACPI_FUNCTION_TRACE (ExDoLogicalOp); 629 630 631 /* 632 * Convert the second operand if necessary. The first operand 633 * determines the type of the second operand, (See the Data Types 634 * section of the ACPI 3.0+ specification.) Both object types are 635 * guaranteed to be either Integer/String/Buffer by the operand 636 * resolution mechanism. 637 */ 638 switch (Operand0->Common.Type) 639 { 640 case ACPI_TYPE_INTEGER: 641 Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16); 642 break; 643 644 case ACPI_TYPE_STRING: 645 Status = AcpiExConvertToString (Operand1, &LocalOperand1, 646 ACPI_IMPLICIT_CONVERT_HEX); 647 break; 648 649 case ACPI_TYPE_BUFFER: 650 Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1); 651 break; 652 653 default: 654 Status = AE_AML_INTERNAL; 655 break; 656 } 657 658 if (ACPI_FAILURE (Status)) 659 { 660 goto Cleanup; 661 } 662 663 /* 664 * Two cases: 1) Both Integers, 2) Both Strings or Buffers 665 */ 666 if (Operand0->Common.Type == ACPI_TYPE_INTEGER) 667 { 668 /* 669 * 1) Both operands are of type integer 670 * Note: LocalOperand1 may have changed above 671 */ 672 Integer0 = Operand0->Integer.Value; 673 Integer1 = LocalOperand1->Integer.Value; 674 675 switch (Opcode) 676 { 677 case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 678 679 if (Integer0 == Integer1) 680 { 681 LocalResult = TRUE; 682 } 683 break; 684 685 case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 686 687 if (Integer0 > Integer1) 688 { 689 LocalResult = TRUE; 690 } 691 break; 692 693 case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 694 695 if (Integer0 < Integer1) 696 { 697 LocalResult = TRUE; 698 } 699 break; 700 701 default: 702 Status = AE_AML_INTERNAL; 703 break; 704 } 705 } 706 else 707 { 708 /* 709 * 2) Both operands are Strings or both are Buffers 710 * Note: Code below takes advantage of common Buffer/String 711 * object fields. LocalOperand1 may have changed above. Use 712 * memcmp to handle nulls in buffers. 713 */ 714 Length0 = Operand0->Buffer.Length; 715 Length1 = LocalOperand1->Buffer.Length; 716 717 /* Lexicographic compare: compare the data bytes */ 718 719 Compare = ACPI_MEMCMP (Operand0->Buffer.Pointer, 720 LocalOperand1->Buffer.Pointer, 721 (Length0 > Length1) ? Length1 : Length0); 722 723 switch (Opcode) 724 { 725 case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */ 726 727 /* Length and all bytes must be equal */ 728 729 if ((Length0 == Length1) && 730 (Compare == 0)) 731 { 732 /* Length and all bytes match ==> TRUE */ 733 734 LocalResult = TRUE; 735 } 736 break; 737 738 case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */ 739 740 if (Compare > 0) 741 { 742 LocalResult = TRUE; 743 goto Cleanup; /* TRUE */ 744 } 745 if (Compare < 0) 746 { 747 goto Cleanup; /* FALSE */ 748 } 749 750 /* Bytes match (to shortest length), compare lengths */ 751 752 if (Length0 > Length1) 753 { 754 LocalResult = TRUE; 755 } 756 break; 757 758 case AML_LLESS_OP: /* LLess (Operand0, Operand1) */ 759 760 if (Compare > 0) 761 { 762 goto Cleanup; /* FALSE */ 763 } 764 if (Compare < 0) 765 { 766 LocalResult = TRUE; 767 goto Cleanup; /* TRUE */ 768 } 769 770 /* Bytes match (to shortest length), compare lengths */ 771 772 if (Length0 < Length1) 773 { 774 LocalResult = TRUE; 775 } 776 break; 777 778 default: 779 Status = AE_AML_INTERNAL; 780 break; 781 } 782 } 783 784 Cleanup: 785 786 /* New object was created if implicit conversion performed - delete */ 787 788 if (LocalOperand1 != Operand1) 789 { 790 AcpiUtRemoveReference (LocalOperand1); 791 } 792 793 /* Return the logical result and status */ 794 795 *LogicalResult = LocalResult; 796 return_ACPI_STATUS (Status); 797 } 798