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