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