xref: /titanic_53/usr/src/uts/intel/io/acpica/executer/exmisc.c (revision 385cc6b4ad1792caef3f84eb61eed3f27085801f)
1db2bae30SDana Myers /******************************************************************************
2db2bae30SDana Myers  *
3db2bae30SDana Myers  * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
4db2bae30SDana Myers  *
5db2bae30SDana Myers  *****************************************************************************/
6db2bae30SDana Myers 
726f3cdf0SGordon Ross /*
8*385cc6b4SJerry Jelinek  * Copyright (C) 2000 - 2016, Intel Corp.
9db2bae30SDana Myers  * All rights reserved.
10db2bae30SDana Myers  *
1126f3cdf0SGordon Ross  * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross  * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross  * are met:
1426f3cdf0SGordon Ross  * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross  *    notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross  *    without modification.
1726f3cdf0SGordon Ross  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross  *    substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross  *    ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross  *    including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross  *    binary redistribution.
2226f3cdf0SGordon Ross  * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross  *    of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross  *    from this software without specific prior written permission.
25db2bae30SDana Myers  *
2626f3cdf0SGordon Ross  * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross  * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross  * Software Foundation.
29db2bae30SDana Myers  *
3026f3cdf0SGordon Ross  * NO WARRANTY
3126f3cdf0SGordon Ross  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross  * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross  */
43db2bae30SDana Myers 
44db2bae30SDana Myers #include "acpi.h"
45aa2aa9a6SDana Myers #include "accommon.h"
46db2bae30SDana Myers #include "acinterp.h"
47db2bae30SDana Myers #include "amlcode.h"
48db2bae30SDana Myers 
49db2bae30SDana Myers 
50db2bae30SDana Myers #define _COMPONENT          ACPI_EXECUTER
51db2bae30SDana Myers         ACPI_MODULE_NAME    ("exmisc")
52db2bae30SDana Myers 
53db2bae30SDana Myers 
54db2bae30SDana Myers /*******************************************************************************
55db2bae30SDana Myers  *
56db2bae30SDana Myers  * FUNCTION:    AcpiExGetObjectReference
57db2bae30SDana Myers  *
58db2bae30SDana Myers  * PARAMETERS:  ObjDesc             - Create a reference to this object
59db2bae30SDana Myers  *              ReturnDesc          - Where to store the reference
60db2bae30SDana Myers  *              WalkState           - Current state
61db2bae30SDana Myers  *
62db2bae30SDana Myers  * RETURN:      Status
63db2bae30SDana Myers  *
64db2bae30SDana Myers  * DESCRIPTION: Obtain and return a "reference" to the target object
65db2bae30SDana Myers  *              Common code for the RefOfOp and the CondRefOfOp.
66db2bae30SDana Myers  *
67db2bae30SDana Myers  ******************************************************************************/
68db2bae30SDana Myers 
69db2bae30SDana Myers ACPI_STATUS
AcpiExGetObjectReference(ACPI_OPERAND_OBJECT * ObjDesc,ACPI_OPERAND_OBJECT ** ReturnDesc,ACPI_WALK_STATE * WalkState)70db2bae30SDana Myers AcpiExGetObjectReference (
71db2bae30SDana Myers     ACPI_OPERAND_OBJECT     *ObjDesc,
72db2bae30SDana Myers     ACPI_OPERAND_OBJECT     **ReturnDesc,
73db2bae30SDana Myers     ACPI_WALK_STATE         *WalkState)
74db2bae30SDana Myers {
75db2bae30SDana Myers     ACPI_OPERAND_OBJECT     *ReferenceObj;
76db2bae30SDana Myers     ACPI_OPERAND_OBJECT     *ReferencedObj;
77db2bae30SDana Myers 
78db2bae30SDana Myers 
79db2bae30SDana Myers     ACPI_FUNCTION_TRACE_PTR (ExGetObjectReference, ObjDesc);
80db2bae30SDana Myers 
81db2bae30SDana Myers 
82db2bae30SDana Myers     *ReturnDesc = NULL;
83db2bae30SDana Myers 
84db2bae30SDana Myers     switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc))
85db2bae30SDana Myers     {
86db2bae30SDana Myers     case ACPI_DESC_TYPE_OPERAND:
87db2bae30SDana Myers 
88aa2aa9a6SDana Myers         if (ObjDesc->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
89db2bae30SDana Myers         {
90db2bae30SDana Myers             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
91db2bae30SDana Myers         }
92db2bae30SDana Myers 
93db2bae30SDana Myers         /*
94db2bae30SDana Myers          * Must be a reference to a Local or Arg
95db2bae30SDana Myers          */
96db2bae30SDana Myers         switch (ObjDesc->Reference.Class)
97db2bae30SDana Myers         {
98db2bae30SDana Myers         case ACPI_REFCLASS_LOCAL:
99db2bae30SDana Myers         case ACPI_REFCLASS_ARG:
100db2bae30SDana Myers         case ACPI_REFCLASS_DEBUG:
101db2bae30SDana Myers 
102db2bae30SDana Myers             /* The referenced object is the pseudo-node for the local/arg */
103db2bae30SDana Myers 
104db2bae30SDana Myers             ReferencedObj = ObjDesc->Reference.Object;
105db2bae30SDana Myers             break;
106db2bae30SDana Myers 
107db2bae30SDana Myers         default:
108db2bae30SDana Myers 
109*385cc6b4SJerry Jelinek             ACPI_ERROR ((AE_INFO, "Invalid Reference Class 0x%2.2X",
110db2bae30SDana Myers                 ObjDesc->Reference.Class));
111*385cc6b4SJerry Jelinek             return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
112db2bae30SDana Myers         }
113db2bae30SDana Myers         break;
114db2bae30SDana Myers 
115db2bae30SDana Myers     case ACPI_DESC_TYPE_NAMED:
116db2bae30SDana Myers         /*
117db2bae30SDana Myers          * A named reference that has already been resolved to a Node
118db2bae30SDana Myers          */
119db2bae30SDana Myers         ReferencedObj = ObjDesc;
120db2bae30SDana Myers         break;
121db2bae30SDana Myers 
122db2bae30SDana Myers     default:
123db2bae30SDana Myers 
12426f3cdf0SGordon Ross         ACPI_ERROR ((AE_INFO, "Invalid descriptor type 0x%X",
125db2bae30SDana Myers             ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)));
126db2bae30SDana Myers         return_ACPI_STATUS (AE_TYPE);
127db2bae30SDana Myers     }
128db2bae30SDana Myers 
129db2bae30SDana Myers 
130db2bae30SDana Myers     /* Create a new reference object */
131db2bae30SDana Myers 
132db2bae30SDana Myers     ReferenceObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
133db2bae30SDana Myers     if (!ReferenceObj)
134db2bae30SDana Myers     {
135db2bae30SDana Myers         return_ACPI_STATUS (AE_NO_MEMORY);
136db2bae30SDana Myers     }
137db2bae30SDana Myers 
138db2bae30SDana Myers     ReferenceObj->Reference.Class = ACPI_REFCLASS_REFOF;
139db2bae30SDana Myers     ReferenceObj->Reference.Object = ReferencedObj;
140db2bae30SDana Myers     *ReturnDesc = ReferenceObj;
141db2bae30SDana Myers 
142db2bae30SDana Myers     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
143db2bae30SDana Myers         "Object %p Type [%s], returning Reference %p\n",
144db2bae30SDana Myers         ObjDesc, AcpiUtGetObjectTypeName (ObjDesc), *ReturnDesc));
145db2bae30SDana Myers 
146db2bae30SDana Myers     return_ACPI_STATUS (AE_OK);
147db2bae30SDana Myers }
148db2bae30SDana Myers 
149db2bae30SDana Myers 
150db2bae30SDana Myers /*******************************************************************************
151db2bae30SDana Myers  *
152db2bae30SDana Myers  * FUNCTION:    AcpiExDoMathOp
153db2bae30SDana Myers  *
154db2bae30SDana Myers  * PARAMETERS:  Opcode              - AML opcode
155db2bae30SDana Myers  *              Integer0            - Integer operand #0
156db2bae30SDana Myers  *              Integer1            - Integer operand #1
157db2bae30SDana Myers  *
158db2bae30SDana Myers  * RETURN:      Integer result of the operation
159db2bae30SDana Myers  *
160db2bae30SDana Myers  * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
161db2bae30SDana Myers  *              math functions here is to prevent a lot of pointer dereferencing
162db2bae30SDana Myers  *              to obtain the operands.
163db2bae30SDana Myers  *
164db2bae30SDana Myers  ******************************************************************************/
165db2bae30SDana Myers 
16626f3cdf0SGordon Ross UINT64
AcpiExDoMathOp(UINT16 Opcode,UINT64 Integer0,UINT64 Integer1)167db2bae30SDana Myers AcpiExDoMathOp (
168db2bae30SDana Myers     UINT16                  Opcode,
16926f3cdf0SGordon Ross     UINT64                  Integer0,
17026f3cdf0SGordon Ross     UINT64                  Integer1)
171db2bae30SDana Myers {
172db2bae30SDana Myers 
173db2bae30SDana Myers     ACPI_FUNCTION_ENTRY ();
174db2bae30SDana Myers 
175db2bae30SDana Myers 
176db2bae30SDana Myers     switch (Opcode)
177db2bae30SDana Myers     {
178db2bae30SDana Myers     case AML_ADD_OP:                /* Add (Integer0, Integer1, Result) */
179db2bae30SDana Myers 
180db2bae30SDana Myers         return (Integer0 + Integer1);
181db2bae30SDana Myers 
182db2bae30SDana Myers     case AML_BIT_AND_OP:            /* And (Integer0, Integer1, Result) */
183db2bae30SDana Myers 
184db2bae30SDana Myers         return (Integer0 & Integer1);
185db2bae30SDana Myers 
186db2bae30SDana Myers     case AML_BIT_NAND_OP:           /* NAnd (Integer0, Integer1, Result) */
187db2bae30SDana Myers 
188db2bae30SDana Myers         return (~(Integer0 & Integer1));
189db2bae30SDana Myers 
190db2bae30SDana Myers     case AML_BIT_OR_OP:             /* Or (Integer0, Integer1, Result) */
191db2bae30SDana Myers 
192db2bae30SDana Myers         return (Integer0 | Integer1);
193db2bae30SDana Myers 
194db2bae30SDana Myers     case AML_BIT_NOR_OP:            /* NOr (Integer0, Integer1, Result) */
195db2bae30SDana Myers 
196db2bae30SDana Myers         return (~(Integer0 | Integer1));
197db2bae30SDana Myers 
198db2bae30SDana Myers     case AML_BIT_XOR_OP:            /* XOr (Integer0, Integer1, Result) */
199db2bae30SDana Myers 
200db2bae30SDana Myers         return (Integer0 ^ Integer1);
201db2bae30SDana Myers 
202db2bae30SDana Myers     case AML_MULTIPLY_OP:           /* Multiply (Integer0, Integer1, Result) */
203db2bae30SDana Myers 
204db2bae30SDana Myers         return (Integer0 * Integer1);
205db2bae30SDana Myers 
206db2bae30SDana Myers     case AML_SHIFT_LEFT_OP:         /* ShiftLeft (Operand, ShiftCount, Result)*/
207db2bae30SDana Myers 
208db2bae30SDana Myers         /*
209db2bae30SDana Myers          * We need to check if the shiftcount is larger than the integer bit
210db2bae30SDana Myers          * width since the behavior of this is not well-defined in the C language.
211db2bae30SDana Myers          */
212db2bae30SDana Myers         if (Integer1 >= AcpiGbl_IntegerBitWidth)
213db2bae30SDana Myers         {
214db2bae30SDana Myers             return (0);
215db2bae30SDana Myers         }
216db2bae30SDana Myers         return (Integer0 << Integer1);
217db2bae30SDana Myers 
218db2bae30SDana Myers     case AML_SHIFT_RIGHT_OP:        /* ShiftRight (Operand, ShiftCount, Result) */
219db2bae30SDana Myers 
220db2bae30SDana Myers         /*
221db2bae30SDana Myers          * We need to check if the shiftcount is larger than the integer bit
222db2bae30SDana Myers          * width since the behavior of this is not well-defined in the C language.
223db2bae30SDana Myers          */
224db2bae30SDana Myers         if (Integer1 >= AcpiGbl_IntegerBitWidth)
225db2bae30SDana Myers         {
226db2bae30SDana Myers             return (0);
227db2bae30SDana Myers         }
228db2bae30SDana Myers         return (Integer0 >> Integer1);
229db2bae30SDana Myers 
230db2bae30SDana Myers     case AML_SUBTRACT_OP:           /* Subtract (Integer0, Integer1, Result) */
231db2bae30SDana Myers 
232db2bae30SDana Myers         return (Integer0 - Integer1);
233db2bae30SDana Myers 
234db2bae30SDana Myers     default:
235db2bae30SDana Myers 
236db2bae30SDana Myers         return (0);
237db2bae30SDana Myers     }
238db2bae30SDana Myers }
239db2bae30SDana Myers 
240db2bae30SDana Myers 
241db2bae30SDana Myers /*******************************************************************************
242db2bae30SDana Myers  *
243db2bae30SDana Myers  * FUNCTION:    AcpiExDoLogicalNumericOp
244db2bae30SDana Myers  *
245db2bae30SDana Myers  * PARAMETERS:  Opcode              - AML opcode
246db2bae30SDana Myers  *              Integer0            - Integer operand #0
247db2bae30SDana Myers  *              Integer1            - Integer operand #1
248db2bae30SDana Myers  *              LogicalResult       - TRUE/FALSE result of the operation
249db2bae30SDana Myers  *
250db2bae30SDana Myers  * RETURN:      Status
251db2bae30SDana Myers  *
252db2bae30SDana Myers  * DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
253db2bae30SDana Myers  *              operators (LAnd and LOr), both operands must be integers.
254db2bae30SDana Myers  *
255db2bae30SDana Myers  *              Note: cleanest machine code seems to be produced by the code
256db2bae30SDana Myers  *              below, rather than using statements of the form:
257db2bae30SDana Myers  *                  Result = (Integer0 && Integer1);
258db2bae30SDana Myers  *
259db2bae30SDana Myers  ******************************************************************************/
260db2bae30SDana Myers 
261db2bae30SDana Myers ACPI_STATUS
AcpiExDoLogicalNumericOp(UINT16 Opcode,UINT64 Integer0,UINT64 Integer1,BOOLEAN * LogicalResult)262db2bae30SDana Myers AcpiExDoLogicalNumericOp (
263db2bae30SDana Myers     UINT16                  Opcode,
26426f3cdf0SGordon Ross     UINT64                  Integer0,
26526f3cdf0SGordon Ross     UINT64                  Integer1,
266db2bae30SDana Myers     BOOLEAN                 *LogicalResult)
267db2bae30SDana Myers {
268db2bae30SDana Myers     ACPI_STATUS             Status = AE_OK;
269db2bae30SDana Myers     BOOLEAN                 LocalResult = FALSE;
270db2bae30SDana Myers 
271db2bae30SDana Myers 
272db2bae30SDana Myers     ACPI_FUNCTION_TRACE (ExDoLogicalNumericOp);
273db2bae30SDana Myers 
274db2bae30SDana Myers 
275db2bae30SDana Myers     switch (Opcode)
276db2bae30SDana Myers     {
277db2bae30SDana Myers     case AML_LAND_OP:               /* LAnd (Integer0, Integer1) */
278db2bae30SDana Myers 
279db2bae30SDana Myers         if (Integer0 && Integer1)
280db2bae30SDana Myers         {
281db2bae30SDana Myers             LocalResult = TRUE;
282db2bae30SDana Myers         }
283db2bae30SDana Myers         break;
284db2bae30SDana Myers 
285db2bae30SDana Myers     case AML_LOR_OP:                /* LOr (Integer0, Integer1) */
286db2bae30SDana Myers 
287db2bae30SDana Myers         if (Integer0 || Integer1)
288db2bae30SDana Myers         {
289db2bae30SDana Myers             LocalResult = TRUE;
290db2bae30SDana Myers         }
291db2bae30SDana Myers         break;
292db2bae30SDana Myers 
293db2bae30SDana Myers     default:
294*385cc6b4SJerry Jelinek 
295db2bae30SDana Myers         Status = AE_AML_INTERNAL;
296db2bae30SDana Myers         break;
297db2bae30SDana Myers     }
298db2bae30SDana Myers 
299db2bae30SDana Myers     /* Return the logical result and status */
300db2bae30SDana Myers 
301db2bae30SDana Myers     *LogicalResult = LocalResult;
302db2bae30SDana Myers     return_ACPI_STATUS (Status);
303db2bae30SDana Myers }
304db2bae30SDana Myers 
305db2bae30SDana Myers 
306db2bae30SDana Myers /*******************************************************************************
307db2bae30SDana Myers  *
308db2bae30SDana Myers  * FUNCTION:    AcpiExDoLogicalOp
309db2bae30SDana Myers  *
310db2bae30SDana Myers  * PARAMETERS:  Opcode              - AML opcode
311db2bae30SDana Myers  *              Operand0            - operand #0
312db2bae30SDana Myers  *              Operand1            - operand #1
313db2bae30SDana Myers  *              LogicalResult       - TRUE/FALSE result of the operation
314db2bae30SDana Myers  *
315db2bae30SDana Myers  * RETURN:      Status
316db2bae30SDana Myers  *
317db2bae30SDana Myers  * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
318db2bae30SDana Myers  *              functions here is to prevent a lot of pointer dereferencing
319db2bae30SDana Myers  *              to obtain the operands and to simplify the generation of the
320db2bae30SDana Myers  *              logical value. For the Numeric operators (LAnd and LOr), both
321db2bae30SDana Myers  *              operands must be integers. For the other logical operators,
322db2bae30SDana Myers  *              operands can be any combination of Integer/String/Buffer. The
323db2bae30SDana Myers  *              first operand determines the type to which the second operand
324db2bae30SDana Myers  *              will be converted.
325db2bae30SDana Myers  *
326db2bae30SDana Myers  *              Note: cleanest machine code seems to be produced by the code
327db2bae30SDana Myers  *              below, rather than using statements of the form:
328db2bae30SDana Myers  *                  Result = (Operand0 == Operand1);
329db2bae30SDana Myers  *
330db2bae30SDana Myers  ******************************************************************************/
331db2bae30SDana Myers 
332db2bae30SDana Myers ACPI_STATUS
AcpiExDoLogicalOp(UINT16 Opcode,ACPI_OPERAND_OBJECT * Operand0,ACPI_OPERAND_OBJECT * Operand1,BOOLEAN * LogicalResult)333db2bae30SDana Myers AcpiExDoLogicalOp (
334db2bae30SDana Myers     UINT16                  Opcode,
335db2bae30SDana Myers     ACPI_OPERAND_OBJECT     *Operand0,
336db2bae30SDana Myers     ACPI_OPERAND_OBJECT     *Operand1,
337db2bae30SDana Myers     BOOLEAN                 *LogicalResult)
338db2bae30SDana Myers {
339db2bae30SDana Myers     ACPI_OPERAND_OBJECT     *LocalOperand1 = Operand1;
34026f3cdf0SGordon Ross     UINT64                  Integer0;
34126f3cdf0SGordon Ross     UINT64                  Integer1;
342db2bae30SDana Myers     UINT32                  Length0;
343db2bae30SDana Myers     UINT32                  Length1;
344db2bae30SDana Myers     ACPI_STATUS             Status = AE_OK;
345db2bae30SDana Myers     BOOLEAN                 LocalResult = FALSE;
346db2bae30SDana Myers     int                     Compare;
347db2bae30SDana Myers 
348db2bae30SDana Myers 
349db2bae30SDana Myers     ACPI_FUNCTION_TRACE (ExDoLogicalOp);
350db2bae30SDana Myers 
351db2bae30SDana Myers 
352db2bae30SDana Myers     /*
353db2bae30SDana Myers      * Convert the second operand if necessary. The first operand
354db2bae30SDana Myers      * determines the type of the second operand, (See the Data Types
355db2bae30SDana Myers      * section of the ACPI 3.0+ specification.)  Both object types are
356db2bae30SDana Myers      * guaranteed to be either Integer/String/Buffer by the operand
357db2bae30SDana Myers      * resolution mechanism.
358db2bae30SDana Myers      */
359aa2aa9a6SDana Myers     switch (Operand0->Common.Type)
360db2bae30SDana Myers     {
361db2bae30SDana Myers     case ACPI_TYPE_INTEGER:
362*385cc6b4SJerry Jelinek 
363db2bae30SDana Myers         Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16);
364db2bae30SDana Myers         break;
365db2bae30SDana Myers 
366db2bae30SDana Myers     case ACPI_TYPE_STRING:
367*385cc6b4SJerry Jelinek 
368*385cc6b4SJerry Jelinek         Status = AcpiExConvertToString (
369*385cc6b4SJerry Jelinek             Operand1, &LocalOperand1, ACPI_IMPLICIT_CONVERT_HEX);
370db2bae30SDana Myers         break;
371db2bae30SDana Myers 
372db2bae30SDana Myers     case ACPI_TYPE_BUFFER:
373*385cc6b4SJerry Jelinek 
374db2bae30SDana Myers         Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1);
375db2bae30SDana Myers         break;
376db2bae30SDana Myers 
377db2bae30SDana Myers     default:
378*385cc6b4SJerry Jelinek 
379db2bae30SDana Myers         Status = AE_AML_INTERNAL;
380db2bae30SDana Myers         break;
381db2bae30SDana Myers     }
382db2bae30SDana Myers 
383db2bae30SDana Myers     if (ACPI_FAILURE (Status))
384db2bae30SDana Myers     {
385db2bae30SDana Myers         goto Cleanup;
386db2bae30SDana Myers     }
387db2bae30SDana Myers 
388db2bae30SDana Myers     /*
389db2bae30SDana Myers      * Two cases: 1) Both Integers, 2) Both Strings or Buffers
390db2bae30SDana Myers      */
391aa2aa9a6SDana Myers     if (Operand0->Common.Type == ACPI_TYPE_INTEGER)
392db2bae30SDana Myers     {
393db2bae30SDana Myers         /*
394db2bae30SDana Myers          * 1) Both operands are of type integer
395db2bae30SDana Myers          *    Note: LocalOperand1 may have changed above
396db2bae30SDana Myers          */
397db2bae30SDana Myers         Integer0 = Operand0->Integer.Value;
398db2bae30SDana Myers         Integer1 = LocalOperand1->Integer.Value;
399db2bae30SDana Myers 
400db2bae30SDana Myers         switch (Opcode)
401db2bae30SDana Myers         {
402db2bae30SDana Myers         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
403db2bae30SDana Myers 
404db2bae30SDana Myers             if (Integer0 == Integer1)
405db2bae30SDana Myers             {
406db2bae30SDana Myers                 LocalResult = TRUE;
407db2bae30SDana Myers             }
408db2bae30SDana Myers             break;
409db2bae30SDana Myers 
410db2bae30SDana Myers         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
411db2bae30SDana Myers 
412db2bae30SDana Myers             if (Integer0 > Integer1)
413db2bae30SDana Myers             {
414db2bae30SDana Myers                 LocalResult = TRUE;
415db2bae30SDana Myers             }
416db2bae30SDana Myers             break;
417db2bae30SDana Myers 
418db2bae30SDana Myers         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
419db2bae30SDana Myers 
420db2bae30SDana Myers             if (Integer0 < Integer1)
421db2bae30SDana Myers             {
422db2bae30SDana Myers                 LocalResult = TRUE;
423db2bae30SDana Myers             }
424db2bae30SDana Myers             break;
425db2bae30SDana Myers 
426db2bae30SDana Myers         default:
427*385cc6b4SJerry Jelinek 
428db2bae30SDana Myers             Status = AE_AML_INTERNAL;
429db2bae30SDana Myers             break;
430db2bae30SDana Myers         }
431db2bae30SDana Myers     }
432db2bae30SDana Myers     else
433db2bae30SDana Myers     {
434db2bae30SDana Myers         /*
435db2bae30SDana Myers          * 2) Both operands are Strings or both are Buffers
436db2bae30SDana Myers          *    Note: Code below takes advantage of common Buffer/String
437db2bae30SDana Myers          *          object fields. LocalOperand1 may have changed above. Use
438db2bae30SDana Myers          *          memcmp to handle nulls in buffers.
439db2bae30SDana Myers          */
440db2bae30SDana Myers         Length0 = Operand0->Buffer.Length;
441db2bae30SDana Myers         Length1 = LocalOperand1->Buffer.Length;
442db2bae30SDana Myers 
443db2bae30SDana Myers         /* Lexicographic compare: compare the data bytes */
444db2bae30SDana Myers 
445*385cc6b4SJerry Jelinek         Compare = memcmp (Operand0->Buffer.Pointer,
446db2bae30SDana Myers             LocalOperand1->Buffer.Pointer,
447db2bae30SDana Myers             (Length0 > Length1) ? Length1 : Length0);
448db2bae30SDana Myers 
449db2bae30SDana Myers         switch (Opcode)
450db2bae30SDana Myers         {
451db2bae30SDana Myers         case AML_LEQUAL_OP:             /* LEqual (Operand0, Operand1) */
452db2bae30SDana Myers 
453db2bae30SDana Myers             /* Length and all bytes must be equal */
454db2bae30SDana Myers 
455db2bae30SDana Myers             if ((Length0 == Length1) &&
456db2bae30SDana Myers                 (Compare == 0))
457db2bae30SDana Myers             {
458db2bae30SDana Myers                 /* Length and all bytes match ==> TRUE */
459db2bae30SDana Myers 
460db2bae30SDana Myers                 LocalResult = TRUE;
461db2bae30SDana Myers             }
462db2bae30SDana Myers             break;
463db2bae30SDana Myers 
464db2bae30SDana Myers         case AML_LGREATER_OP:           /* LGreater (Operand0, Operand1) */
465db2bae30SDana Myers 
466db2bae30SDana Myers             if (Compare > 0)
467db2bae30SDana Myers             {
468db2bae30SDana Myers                 LocalResult = TRUE;
469db2bae30SDana Myers                 goto Cleanup;   /* TRUE */
470db2bae30SDana Myers             }
471db2bae30SDana Myers             if (Compare < 0)
472db2bae30SDana Myers             {
473db2bae30SDana Myers                 goto Cleanup;   /* FALSE */
474db2bae30SDana Myers             }
475db2bae30SDana Myers 
476db2bae30SDana Myers             /* Bytes match (to shortest length), compare lengths */
477db2bae30SDana Myers 
478db2bae30SDana Myers             if (Length0 > Length1)
479db2bae30SDana Myers             {
480db2bae30SDana Myers                 LocalResult = TRUE;
481db2bae30SDana Myers             }
482db2bae30SDana Myers             break;
483db2bae30SDana Myers 
484db2bae30SDana Myers         case AML_LLESS_OP:              /* LLess (Operand0, Operand1) */
485db2bae30SDana Myers 
486db2bae30SDana Myers             if (Compare > 0)
487db2bae30SDana Myers             {
488db2bae30SDana Myers                 goto Cleanup;   /* FALSE */
489db2bae30SDana Myers             }
490db2bae30SDana Myers             if (Compare < 0)
491db2bae30SDana Myers             {
492db2bae30SDana Myers                 LocalResult = TRUE;
493db2bae30SDana Myers                 goto Cleanup;   /* TRUE */
494db2bae30SDana Myers             }
495db2bae30SDana Myers 
496db2bae30SDana Myers             /* Bytes match (to shortest length), compare lengths */
497db2bae30SDana Myers 
498db2bae30SDana Myers             if (Length0 < Length1)
499db2bae30SDana Myers             {
500db2bae30SDana Myers                 LocalResult = TRUE;
501db2bae30SDana Myers             }
502db2bae30SDana Myers             break;
503db2bae30SDana Myers 
504db2bae30SDana Myers         default:
505*385cc6b4SJerry Jelinek 
506db2bae30SDana Myers             Status = AE_AML_INTERNAL;
507db2bae30SDana Myers             break;
508db2bae30SDana Myers         }
509db2bae30SDana Myers     }
510db2bae30SDana Myers 
511db2bae30SDana Myers Cleanup:
512db2bae30SDana Myers 
513db2bae30SDana Myers     /* New object was created if implicit conversion performed - delete */
514db2bae30SDana Myers 
515db2bae30SDana Myers     if (LocalOperand1 != Operand1)
516db2bae30SDana Myers     {
517db2bae30SDana Myers         AcpiUtRemoveReference (LocalOperand1);
518db2bae30SDana Myers     }
519db2bae30SDana Myers 
520db2bae30SDana Myers     /* Return the logical result and status */
521db2bae30SDana Myers 
522db2bae30SDana Myers     *LogicalResult = LocalResult;
523db2bae30SDana Myers     return_ACPI_STATUS (Status);
524db2bae30SDana Myers }
525