1 /******************************************************************************
2 *
3 * Module Name: exoparg1 - AML execution - opcodes with 1 argument
4 *
5 *****************************************************************************/
6
7 /******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2023, Intel Corp.
12 * All rights reserved.
13 *
14 * 2. License
15 *
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
20 *
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
27 *
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code. No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
36 *
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
39 *
40 * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision. In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change. Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee. Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution. In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government. In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************
115 *
116 * Alternatively, you may choose to be licensed under the terms of the
117 * following license:
118 *
119 * Redistribution and use in source and binary forms, with or without
120 * modification, are permitted provided that the following conditions
121 * are met:
122 * 1. Redistributions of source code must retain the above copyright
123 * notice, this list of conditions, and the following disclaimer,
124 * without modification.
125 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126 * substantially similar to the "NO WARRANTY" disclaimer below
127 * ("Disclaimer") and any redistribution must be conditioned upon
128 * including a substantially similar Disclaimer requirement for further
129 * binary redistribution.
130 * 3. Neither the names of the above-listed copyright holders nor the names
131 * of any contributors may be used to endorse or promote products derived
132 * from this software without specific prior written permission.
133 *
134 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
135 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
136 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
137 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
138 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
139 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
140 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
141 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
142 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
143 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
144 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
145 *
146 * Alternatively, you may choose to be licensed under the terms of the
147 * GNU General Public License ("GPL") version 2 as published by the Free
148 * Software Foundation.
149 *
150 *****************************************************************************/
151
152 #include "acpi.h"
153 #include "accommon.h"
154 #include "acparser.h"
155 #include "acdispat.h"
156 #include "acinterp.h"
157 #include "amlcode.h"
158 #include "acnamesp.h"
159
160
161 #define _COMPONENT ACPI_EXECUTER
162 ACPI_MODULE_NAME ("exoparg1")
163
164
165 /*!
166 * Naming convention for AML interpreter execution routines.
167 *
168 * The routines that begin execution of AML opcodes are named with a common
169 * convention based upon the number of arguments, the number of target operands,
170 * and whether or not a value is returned:
171 *
172 * AcpiExOpcode_xA_yT_zR
173 *
174 * Where:
175 *
176 * xA - ARGUMENTS: The number of arguments (input operands) that are
177 * required for this opcode type (0 through 6 args).
178 * yT - TARGETS: The number of targets (output operands) that are required
179 * for this opcode type (0, 1, or 2 targets).
180 * zR - RETURN VALUE: Indicates whether this opcode type returns a value
181 * as the function return (0 or 1).
182 *
183 * The AcpiExOpcode* functions are called via the Dispatcher component with
184 * fully resolved operands.
185 !*/
186
187 /*******************************************************************************
188 *
189 * FUNCTION: AcpiExOpcode_0A_0T_1R
190 *
191 * PARAMETERS: WalkState - Current state (contains AML opcode)
192 *
193 * RETURN: Status
194 *
195 * DESCRIPTION: Execute operator with no operands, one return value
196 *
197 ******************************************************************************/
198
199 ACPI_STATUS
AcpiExOpcode_0A_0T_1R(ACPI_WALK_STATE * WalkState)200 AcpiExOpcode_0A_0T_1R (
201 ACPI_WALK_STATE *WalkState)
202 {
203 ACPI_STATUS Status = AE_OK;
204 ACPI_OPERAND_OBJECT *ReturnDesc = NULL;
205
206
207 ACPI_FUNCTION_TRACE_STR (ExOpcode_0A_0T_1R,
208 AcpiPsGetOpcodeName (WalkState->Opcode));
209
210
211 /* Examine the AML opcode */
212
213 switch (WalkState->Opcode)
214 {
215 case AML_TIMER_OP: /* Timer () */
216
217 /* Create a return object of type Integer */
218
219 ReturnDesc = AcpiUtCreateIntegerObject (AcpiOsGetTimer ());
220 if (!ReturnDesc)
221 {
222 Status = AE_NO_MEMORY;
223 goto Cleanup;
224 }
225 break;
226
227 default: /* Unknown opcode */
228
229 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
230 WalkState->Opcode));
231 Status = AE_AML_BAD_OPCODE;
232 break;
233 }
234
235 Cleanup:
236
237 /* Delete return object on error */
238
239 if ((ACPI_FAILURE (Status)) || WalkState->ResultObj)
240 {
241 AcpiUtRemoveReference (ReturnDesc);
242 WalkState->ResultObj = NULL;
243 }
244 else
245 {
246 /* Save the return value */
247
248 WalkState->ResultObj = ReturnDesc;
249 }
250
251 return_ACPI_STATUS (Status);
252 }
253
254
255 /*******************************************************************************
256 *
257 * FUNCTION: AcpiExOpcode_1A_0T_0R
258 *
259 * PARAMETERS: WalkState - Current state (contains AML opcode)
260 *
261 * RETURN: Status
262 *
263 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on
264 * object stack
265 *
266 ******************************************************************************/
267
268 ACPI_STATUS
AcpiExOpcode_1A_0T_0R(ACPI_WALK_STATE * WalkState)269 AcpiExOpcode_1A_0T_0R (
270 ACPI_WALK_STATE *WalkState)
271 {
272 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];
273 ACPI_STATUS Status = AE_OK;
274
275
276 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_0R,
277 AcpiPsGetOpcodeName (WalkState->Opcode));
278
279
280 /* Examine the AML opcode */
281
282 switch (WalkState->Opcode)
283 {
284 case AML_RELEASE_OP: /* Release (MutexObject) */
285
286 Status = AcpiExReleaseMutex (Operand[0], WalkState);
287 break;
288
289 case AML_RESET_OP: /* Reset (EventObject) */
290
291 Status = AcpiExSystemResetEvent (Operand[0]);
292 break;
293
294 case AML_SIGNAL_OP: /* Signal (EventObject) */
295
296 Status = AcpiExSystemSignalEvent (Operand[0]);
297 break;
298
299 case AML_SLEEP_OP: /* Sleep (MsecTime) */
300
301 Status = AcpiExSystemDoSleep (Operand[0]->Integer.Value);
302 break;
303
304 case AML_STALL_OP: /* Stall (UsecTime) */
305
306 Status = AcpiExSystemDoStall ((UINT32) Operand[0]->Integer.Value);
307 break;
308
309 case AML_UNLOAD_OP: /* Unload (Handle) */
310
311 Status = AcpiExUnloadTable (Operand[0]);
312 break;
313
314 default: /* Unknown opcode */
315
316 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
317 WalkState->Opcode));
318 Status = AE_AML_BAD_OPCODE;
319 break;
320 }
321
322 return_ACPI_STATUS (Status);
323 }
324
325
326 #ifdef _OBSOLETE_CODE /* Was originally used for Load() operator */
327 /*******************************************************************************
328 *
329 * FUNCTION: AcpiExOpcode_1A_1T_0R
330 *
331 * PARAMETERS: WalkState - Current state (contains AML opcode)
332 *
333 * RETURN: Status
334 *
335 * DESCRIPTION: Execute opcode with one argument, one target, and no
336 * return value.
337 *
338 ******************************************************************************/
339
340 ACPI_STATUS
AcpiExOpcode_1A_1T_0R(ACPI_WALK_STATE * WalkState)341 AcpiExOpcode_1A_1T_0R (
342 ACPI_WALK_STATE *WalkState)
343 {
344 ACPI_STATUS Status = AE_OK;
345 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];
346
347
348 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_0R,
349 AcpiPsGetOpcodeName (WalkState->Opcode));
350
351
352 /* Examine the AML opcode */
353
354 switch (WalkState->Opcode)
355 {
356 #ifdef _OBSOLETE_CODE
357 case AML_LOAD_OP:
358
359 Status = AcpiExLoadOp (Operand[0], Operand[1], WalkState);
360 break;
361 #endif
362
363 default: /* Unknown opcode */
364
365 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
366 WalkState->Opcode));
367 Status = AE_AML_BAD_OPCODE;
368 goto Cleanup;
369 }
370
371
372 Cleanup:
373
374 return_ACPI_STATUS (Status);
375 }
376 #endif
377
378 /*******************************************************************************
379 *
380 * FUNCTION: AcpiExOpcode_1A_1T_1R
381 *
382 * PARAMETERS: WalkState - Current state (contains AML opcode)
383 *
384 * RETURN: Status
385 *
386 * DESCRIPTION: Execute opcode with one argument, one target, and a
387 * return value.
388 * January 2022: Added Load operator, with new ACPI 6.4
389 * semantics.
390 *
391 ******************************************************************************/
392
393 ACPI_STATUS
AcpiExOpcode_1A_1T_1R(ACPI_WALK_STATE * WalkState)394 AcpiExOpcode_1A_1T_1R (
395 ACPI_WALK_STATE *WalkState)
396 {
397 ACPI_STATUS Status = AE_OK;
398 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];
399 ACPI_OPERAND_OBJECT *ReturnDesc = NULL;
400 ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL;
401 UINT32 Temp32;
402 UINT32 i;
403 UINT64 PowerOfTen;
404 UINT64 Digit;
405
406
407 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_1R,
408 AcpiPsGetOpcodeName (WalkState->Opcode));
409
410
411 /* Examine the AML opcode */
412
413 switch (WalkState->Opcode)
414 {
415 case AML_BIT_NOT_OP:
416 case AML_FIND_SET_LEFT_BIT_OP:
417 case AML_FIND_SET_RIGHT_BIT_OP:
418 case AML_FROM_BCD_OP:
419 case AML_LOAD_OP:
420 case AML_TO_BCD_OP:
421 case AML_CONDITIONAL_REF_OF_OP:
422
423 /* Create a return object of type Integer for these opcodes */
424
425 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
426 if (!ReturnDesc)
427 {
428 Status = AE_NO_MEMORY;
429 goto Cleanup;
430 }
431
432 switch (WalkState->Opcode)
433 {
434 case AML_BIT_NOT_OP: /* Not (Operand, Result) */
435
436 ReturnDesc->Integer.Value = ~Operand[0]->Integer.Value;
437 break;
438
439 case AML_FIND_SET_LEFT_BIT_OP: /* FindSetLeftBit (Operand, Result) */
440
441 ReturnDesc->Integer.Value = Operand[0]->Integer.Value;
442
443 /*
444 * Acpi specification describes Integer type as a little
445 * endian unsigned value, so this boundary condition is valid.
446 */
447 for (Temp32 = 0; ReturnDesc->Integer.Value &&
448 Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32)
449 {
450 ReturnDesc->Integer.Value >>= 1;
451 }
452
453 ReturnDesc->Integer.Value = Temp32;
454 break;
455
456 case AML_FIND_SET_RIGHT_BIT_OP: /* FindSetRightBit (Operand, Result) */
457
458 ReturnDesc->Integer.Value = Operand[0]->Integer.Value;
459
460 /*
461 * The Acpi specification describes Integer type as a little
462 * endian unsigned value, so this boundary condition is valid.
463 */
464 for (Temp32 = 0; ReturnDesc->Integer.Value &&
465 Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32)
466 {
467 ReturnDesc->Integer.Value <<= 1;
468 }
469
470 /* Since the bit position is one-based, subtract from 33 (65) */
471
472 ReturnDesc->Integer.Value =
473 Temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - Temp32;
474 break;
475
476 case AML_FROM_BCD_OP: /* FromBcd (BCDValue, Result) */
477 /*
478 * The 64-bit ACPI integer can hold 16 4-bit BCD characters
479 * (if table is 32-bit, integer can hold 8 BCD characters)
480 * Convert each 4-bit BCD value
481 */
482 PowerOfTen = 1;
483 ReturnDesc->Integer.Value = 0;
484 Digit = Operand[0]->Integer.Value;
485
486 /* Convert each BCD digit (each is one nybble wide) */
487
488 for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++)
489 {
490 /* Get the least significant 4-bit BCD digit */
491
492 Temp32 = ((UINT32) Digit) & 0xF;
493
494 /* Check the range of the digit */
495
496 if (Temp32 > 9)
497 {
498 ACPI_ERROR ((AE_INFO,
499 "BCD digit too large (not decimal): 0x%X",
500 Temp32));
501
502 Status = AE_AML_NUMERIC_OVERFLOW;
503 goto Cleanup;
504 }
505
506 /* Sum the digit into the result with the current power of 10 */
507
508 ReturnDesc->Integer.Value +=
509 (((UINT64) Temp32) * PowerOfTen);
510
511 /* Shift to next BCD digit */
512
513 Digit >>= 4;
514
515 /* Next power of 10 */
516
517 PowerOfTen *= 10;
518 }
519 break;
520
521 case AML_LOAD_OP: /* Result1 = Load (Operand[0], Result1) */
522
523 ReturnDesc->Integer.Value = 0;
524 Status = AcpiExLoadOp (Operand[0], ReturnDesc, WalkState);
525 if (ACPI_SUCCESS (Status))
526 {
527 /* Return -1 (non-zero) indicates success */
528
529 ReturnDesc->Integer.Value = 0xFFFFFFFFFFFFFFFF;
530 }
531 break;
532
533 case AML_TO_BCD_OP: /* ToBcd (Operand, Result) */
534
535 ReturnDesc->Integer.Value = 0;
536 Digit = Operand[0]->Integer.Value;
537
538 /* Each BCD digit is one nybble wide */
539
540 for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++)
541 {
542 (void) AcpiUtShortDivide (Digit, 10, &Digit, &Temp32);
543
544 /*
545 * Insert the BCD digit that resides in the
546 * remainder from above
547 */
548 ReturnDesc->Integer.Value |=
549 (((UINT64) Temp32) << ACPI_MUL_4 (i));
550 }
551
552 /* Overflow if there is any data left in Digit */
553
554 if (Digit > 0)
555 {
556 ACPI_ERROR ((AE_INFO,
557 "Integer too large to convert to BCD: 0x%8.8X%8.8X",
558 ACPI_FORMAT_UINT64 (Operand[0]->Integer.Value)));
559 Status = AE_AML_NUMERIC_OVERFLOW;
560 goto Cleanup;
561 }
562 break;
563
564 case AML_CONDITIONAL_REF_OF_OP: /* CondRefOf (SourceObject, Result) */
565 /*
566 * This op is a little strange because the internal return value is
567 * different than the return value stored in the result descriptor
568 * (There are really two return values)
569 */
570 if ((ACPI_NAMESPACE_NODE *) Operand[0] == AcpiGbl_RootNode)
571 {
572 /*
573 * This means that the object does not exist in the namespace,
574 * return FALSE
575 */
576 ReturnDesc->Integer.Value = 0;
577 goto Cleanup;
578 }
579
580 /* Get the object reference, store it, and remove our reference */
581
582 Status = AcpiExGetObjectReference (Operand[0],
583 &ReturnDesc2, WalkState);
584 if (ACPI_FAILURE (Status))
585 {
586 goto Cleanup;
587 }
588
589 Status = AcpiExStore (ReturnDesc2, Operand[1], WalkState);
590 AcpiUtRemoveReference (ReturnDesc2);
591
592 /* The object exists in the namespace, return TRUE */
593
594 ReturnDesc->Integer.Value = ACPI_UINT64_MAX;
595 goto Cleanup;
596
597
598 default:
599
600 /* No other opcodes get here */
601
602 break;
603 }
604 break;
605
606 case AML_STORE_OP: /* Store (Source, Target) */
607 /*
608 * A store operand is typically a number, string, buffer or lvalue
609 * Be careful about deleting the source object,
610 * since the object itself may have been stored.
611 */
612 Status = AcpiExStore (Operand[0], Operand[1], WalkState);
613 if (ACPI_FAILURE (Status))
614 {
615 return_ACPI_STATUS (Status);
616 }
617
618 /* It is possible that the Store already produced a return object */
619
620 if (!WalkState->ResultObj)
621 {
622 /*
623 * Normally, we would remove a reference on the Operand[0]
624 * parameter; But since it is being used as the internal return
625 * object (meaning we would normally increment it), the two
626 * cancel out, and we simply don't do anything.
627 */
628 WalkState->ResultObj = Operand[0];
629 WalkState->Operands[0] = NULL; /* Prevent deletion */
630 }
631 return_ACPI_STATUS (Status);
632
633 /*
634 * ACPI 2.0 Opcodes
635 */
636 case AML_COPY_OBJECT_OP: /* CopyObject (Source, Target) */
637
638 Status = AcpiUtCopyIobjectToIobject (
639 Operand[0], &ReturnDesc, WalkState);
640 break;
641
642 case AML_TO_DECIMAL_STRING_OP: /* ToDecimalString (Data, Result) */
643
644 Status = AcpiExConvertToString (
645 Operand[0], &ReturnDesc, ACPI_EXPLICIT_CONVERT_DECIMAL);
646 if (ReturnDesc == Operand[0])
647 {
648 /* No conversion performed, add ref to handle return value */
649
650 AcpiUtAddReference (ReturnDesc);
651 }
652 break;
653
654 case AML_TO_HEX_STRING_OP: /* ToHexString (Data, Result) */
655
656 Status = AcpiExConvertToString (
657 Operand[0], &ReturnDesc, ACPI_EXPLICIT_CONVERT_HEX);
658 if (ReturnDesc == Operand[0])
659 {
660 /* No conversion performed, add ref to handle return value */
661
662 AcpiUtAddReference (ReturnDesc);
663 }
664 break;
665
666 case AML_TO_BUFFER_OP: /* ToBuffer (Data, Result) */
667
668 Status = AcpiExConvertToBuffer (Operand[0], &ReturnDesc);
669 if (ReturnDesc == Operand[0])
670 {
671 /* No conversion performed, add ref to handle return value */
672
673 AcpiUtAddReference (ReturnDesc);
674 }
675 break;
676
677 case AML_TO_INTEGER_OP: /* ToInteger (Data, Result) */
678
679 /* Perform "explicit" conversion */
680
681 Status = AcpiExConvertToInteger (Operand[0], &ReturnDesc, 0);
682 if (ReturnDesc == Operand[0])
683 {
684 /* No conversion performed, add ref to handle return value */
685
686 AcpiUtAddReference (ReturnDesc);
687 }
688 break;
689
690 case AML_SHIFT_LEFT_BIT_OP: /* ShiftLeftBit (Source, BitNum) */
691 case AML_SHIFT_RIGHT_BIT_OP: /* ShiftRightBit (Source, BitNum) */
692
693 /* These are two obsolete opcodes */
694
695 ACPI_ERROR ((AE_INFO,
696 "%s is obsolete and not implemented",
697 AcpiPsGetOpcodeName (WalkState->Opcode)));
698 Status = AE_SUPPORT;
699 goto Cleanup;
700
701 default: /* Unknown opcode */
702
703 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
704 WalkState->Opcode));
705 Status = AE_AML_BAD_OPCODE;
706 goto Cleanup;
707 }
708
709 if (ACPI_SUCCESS (Status))
710 {
711 /* Store the return value computed above into the target object */
712
713 Status = AcpiExStore (ReturnDesc, Operand[1], WalkState);
714 }
715
716
717 Cleanup:
718
719 /* Delete return object on error */
720
721 if (ACPI_FAILURE (Status))
722 {
723 AcpiUtRemoveReference (ReturnDesc);
724 }
725
726 /* Save return object on success */
727
728 else if (!WalkState->ResultObj)
729 {
730 WalkState->ResultObj = ReturnDesc;
731 }
732
733 return_ACPI_STATUS (Status);
734 }
735
736
737 /*******************************************************************************
738 *
739 * FUNCTION: AcpiExOpcode_1A_0T_1R
740 *
741 * PARAMETERS: WalkState - Current state (contains AML opcode)
742 *
743 * RETURN: Status
744 *
745 * DESCRIPTION: Execute opcode with one argument, no target, and a return value
746 *
747 ******************************************************************************/
748
749 ACPI_STATUS
AcpiExOpcode_1A_0T_1R(ACPI_WALK_STATE * WalkState)750 AcpiExOpcode_1A_0T_1R (
751 ACPI_WALK_STATE *WalkState)
752 {
753 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];
754 ACPI_OPERAND_OBJECT *TempDesc;
755 ACPI_OPERAND_OBJECT *ReturnDesc = NULL;
756 ACPI_STATUS Status = AE_OK;
757 UINT32 Type;
758 UINT64 Value;
759
760
761 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_1R,
762 AcpiPsGetOpcodeName (WalkState->Opcode));
763
764
765 /* Examine the AML opcode */
766
767 switch (WalkState->Opcode)
768 {
769 case AML_LOGICAL_NOT_OP: /* LNot (Operand) */
770
771 ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) 0);
772 if (!ReturnDesc)
773 {
774 Status = AE_NO_MEMORY;
775 goto Cleanup;
776 }
777
778 /*
779 * Set result to ONES (TRUE) if Value == 0. Note:
780 * ReturnDesc->Integer.Value is initially == 0 (FALSE) from above.
781 */
782 if (!Operand[0]->Integer.Value)
783 {
784 ReturnDesc->Integer.Value = ACPI_UINT64_MAX;
785 }
786 break;
787
788 case AML_DECREMENT_OP: /* Decrement (Operand) */
789 case AML_INCREMENT_OP: /* Increment (Operand) */
790 /*
791 * Create a new integer. Can't just get the base integer and
792 * increment it because it may be an Arg or Field.
793 */
794 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
795 if (!ReturnDesc)
796 {
797 Status = AE_NO_MEMORY;
798 goto Cleanup;
799 }
800
801 /*
802 * Since we are expecting a Reference operand, it can be either a
803 * NS Node or an internal object.
804 */
805 TempDesc = Operand[0];
806 if (ACPI_GET_DESCRIPTOR_TYPE (TempDesc) == ACPI_DESC_TYPE_OPERAND)
807 {
808 /* Internal reference object - prevent deletion */
809
810 AcpiUtAddReference (TempDesc);
811 }
812
813 /*
814 * Convert the Reference operand to an Integer (This removes a
815 * reference on the Operand[0] object)
816 *
817 * NOTE: We use LNOT_OP here in order to force resolution of the
818 * reference operand to an actual integer.
819 */
820 Status = AcpiExResolveOperands (AML_LOGICAL_NOT_OP,
821 &TempDesc, WalkState);
822 if (ACPI_FAILURE (Status))
823 {
824 ACPI_EXCEPTION ((AE_INFO, Status,
825 "While resolving operands for [%s]",
826 AcpiPsGetOpcodeName (WalkState->Opcode)));
827
828 goto Cleanup;
829 }
830
831 /*
832 * TempDesc is now guaranteed to be an Integer object --
833 * Perform the actual increment or decrement
834 */
835 if (WalkState->Opcode == AML_INCREMENT_OP)
836 {
837 ReturnDesc->Integer.Value = TempDesc->Integer.Value + 1;
838 }
839 else
840 {
841 ReturnDesc->Integer.Value = TempDesc->Integer.Value - 1;
842 }
843
844 /* Finished with this Integer object */
845
846 AcpiUtRemoveReference (TempDesc);
847
848 /*
849 * Store the result back (indirectly) through the original
850 * Reference object
851 */
852 Status = AcpiExStore (ReturnDesc, Operand[0], WalkState);
853 break;
854
855 case AML_OBJECT_TYPE_OP: /* ObjectType (SourceObject) */
856 /*
857 * Note: The operand is not resolved at this point because we want to
858 * get the associated object, not its value. For example, we don't
859 * want to resolve a FieldUnit to its value, we want the actual
860 * FieldUnit object.
861 */
862
863 /* Get the type of the base object */
864
865 Status = AcpiExResolveMultiple (WalkState, Operand[0], &Type, NULL);
866 if (ACPI_FAILURE (Status))
867 {
868 goto Cleanup;
869 }
870
871 /* Allocate a descriptor to hold the type. */
872
873 ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) Type);
874 if (!ReturnDesc)
875 {
876 Status = AE_NO_MEMORY;
877 goto Cleanup;
878 }
879 break;
880
881 case AML_SIZE_OF_OP: /* SizeOf (SourceObject) */
882 /*
883 * Note: The operand is not resolved at this point because we want to
884 * get the associated object, not its value.
885 */
886
887 /* Get the base object */
888
889 Status = AcpiExResolveMultiple (
890 WalkState, Operand[0], &Type, &TempDesc);
891 if (ACPI_FAILURE (Status))
892 {
893 goto Cleanup;
894 }
895
896 /*
897 * The type of the base object must be integer, buffer, string, or
898 * package. All others are not supported.
899 *
900 * NOTE: Integer is not specifically supported by the ACPI spec,
901 * but is supported implicitly via implicit operand conversion.
902 * rather than bother with conversion, we just use the byte width
903 * global (4 or 8 bytes).
904 */
905 switch (Type)
906 {
907 case ACPI_TYPE_INTEGER:
908
909 Value = AcpiGbl_IntegerByteWidth;
910 break;
911
912 case ACPI_TYPE_STRING:
913
914 Value = TempDesc->String.Length;
915 break;
916
917 case ACPI_TYPE_BUFFER:
918
919 /* Buffer arguments may not be evaluated at this point */
920
921 Status = AcpiDsGetBufferArguments (TempDesc);
922 Value = TempDesc->Buffer.Length;
923 break;
924
925 case ACPI_TYPE_PACKAGE:
926
927 /* Package arguments may not be evaluated at this point */
928
929 Status = AcpiDsGetPackageArguments (TempDesc);
930 Value = TempDesc->Package.Count;
931 break;
932
933 default:
934
935 ACPI_ERROR ((AE_INFO,
936 "Operand must be Buffer/Integer/String/Package"
937 " - found type %s",
938 AcpiUtGetTypeName (Type)));
939
940 Status = AE_AML_OPERAND_TYPE;
941 goto Cleanup;
942 }
943
944 if (ACPI_FAILURE (Status))
945 {
946 goto Cleanup;
947 }
948
949 /*
950 * Now that we have the size of the object, create a result
951 * object to hold the value
952 */
953 ReturnDesc = AcpiUtCreateIntegerObject (Value);
954 if (!ReturnDesc)
955 {
956 Status = AE_NO_MEMORY;
957 goto Cleanup;
958 }
959 break;
960
961
962 case AML_REF_OF_OP: /* RefOf (SourceObject) */
963
964 Status = AcpiExGetObjectReference (
965 Operand[0], &ReturnDesc, WalkState);
966 if (ACPI_FAILURE (Status))
967 {
968 goto Cleanup;
969 }
970 break;
971
972
973 case AML_DEREF_OF_OP: /* DerefOf (ObjReference | String) */
974
975 /* Check for a method local or argument, or standalone String */
976
977 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED)
978 {
979 TempDesc = AcpiNsGetAttachedObject (
980 (ACPI_NAMESPACE_NODE *) Operand[0]);
981 if (TempDesc &&
982 ((TempDesc->Common.Type == ACPI_TYPE_STRING) ||
983 (TempDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE)))
984 {
985 Operand[0] = TempDesc;
986 AcpiUtAddReference (TempDesc);
987 }
988 else
989 {
990 Status = AE_AML_OPERAND_TYPE;
991 goto Cleanup;
992 }
993 }
994 else
995 {
996 switch ((Operand[0])->Common.Type)
997 {
998 case ACPI_TYPE_LOCAL_REFERENCE:
999 /*
1000 * This is a DerefOf (LocalX | ArgX)
1001 *
1002 * Must resolve/dereference the local/arg reference first
1003 */
1004 switch (Operand[0]->Reference.Class)
1005 {
1006 case ACPI_REFCLASS_LOCAL:
1007 case ACPI_REFCLASS_ARG:
1008
1009 /* Set Operand[0] to the value of the local/arg */
1010
1011 Status = AcpiDsMethodDataGetValue (
1012 Operand[0]->Reference.Class,
1013 Operand[0]->Reference.Value,
1014 WalkState, &TempDesc);
1015 if (ACPI_FAILURE (Status))
1016 {
1017 goto Cleanup;
1018 }
1019
1020 /*
1021 * Delete our reference to the input object and
1022 * point to the object just retrieved
1023 */
1024 AcpiUtRemoveReference (Operand[0]);
1025 Operand[0] = TempDesc;
1026 break;
1027
1028 case ACPI_REFCLASS_REFOF:
1029
1030 /* Get the object to which the reference refers */
1031
1032 TempDesc = Operand[0]->Reference.Object;
1033 AcpiUtRemoveReference (Operand[0]);
1034 Operand[0] = TempDesc;
1035 break;
1036
1037 default:
1038
1039 /* Must be an Index op - handled below */
1040 break;
1041 }
1042 break;
1043
1044 case ACPI_TYPE_STRING:
1045
1046 break;
1047
1048 default:
1049
1050 Status = AE_AML_OPERAND_TYPE;
1051 goto Cleanup;
1052 }
1053 }
1054
1055 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) != ACPI_DESC_TYPE_NAMED)
1056 {
1057 if ((Operand[0])->Common.Type == ACPI_TYPE_STRING)
1058 {
1059 /*
1060 * This is a DerefOf (String). The string is a reference
1061 * to a named ACPI object.
1062 *
1063 * 1) Find the owning Node
1064 * 2) Dereference the node to an actual object. Could be a
1065 * Field, so we need to resolve the node to a value.
1066 */
1067 Status = AcpiNsGetNodeUnlocked (WalkState->ScopeInfo->Scope.Node,
1068 Operand[0]->String.Pointer,
1069 ACPI_NS_SEARCH_PARENT,
1070 ACPI_CAST_INDIRECT_PTR (
1071 ACPI_NAMESPACE_NODE, &ReturnDesc));
1072 if (ACPI_FAILURE (Status))
1073 {
1074 goto Cleanup;
1075 }
1076
1077 Status = AcpiExResolveNodeToValue (
1078 ACPI_CAST_INDIRECT_PTR (
1079 ACPI_NAMESPACE_NODE, &ReturnDesc),
1080 WalkState);
1081 goto Cleanup;
1082 }
1083 }
1084
1085 /* Operand[0] may have changed from the code above */
1086
1087 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED)
1088 {
1089 /*
1090 * This is a DerefOf (ObjectReference)
1091 * Get the actual object from the Node (This is the dereference).
1092 * This case may only happen when a LocalX or ArgX is
1093 * dereferenced above, or for references to device and
1094 * thermal objects.
1095 */
1096 switch (((ACPI_NAMESPACE_NODE *) Operand[0])->Type)
1097 {
1098 case ACPI_TYPE_DEVICE:
1099 case ACPI_TYPE_THERMAL:
1100
1101 /* These types have no node subobject, return the NS node */
1102
1103 ReturnDesc = Operand[0];
1104 break;
1105
1106 default:
1107 /* For most types, get the object attached to the node */
1108
1109 ReturnDesc = AcpiNsGetAttachedObject (
1110 (ACPI_NAMESPACE_NODE *) Operand[0]);
1111 AcpiUtAddReference (ReturnDesc);
1112 break;
1113 }
1114 }
1115 else
1116 {
1117 /*
1118 * This must be a reference object produced by either the
1119 * Index() or RefOf() operator
1120 */
1121 switch (Operand[0]->Reference.Class)
1122 {
1123 case ACPI_REFCLASS_INDEX:
1124 /*
1125 * The target type for the Index operator must be
1126 * either a Buffer or a Package
1127 */
1128 switch (Operand[0]->Reference.TargetType)
1129 {
1130 case ACPI_TYPE_BUFFER_FIELD:
1131
1132 TempDesc = Operand[0]->Reference.Object;
1133
1134 /*
1135 * Create a new object that contains one element of the
1136 * buffer -- the element pointed to by the index.
1137 *
1138 * NOTE: index into a buffer is NOT a pointer to a
1139 * sub-buffer of the main buffer, it is only a pointer to a
1140 * single element (byte) of the buffer!
1141 *
1142 * Since we are returning the value of the buffer at the
1143 * indexed location, we don't need to add an additional
1144 * reference to the buffer itself.
1145 */
1146 ReturnDesc = AcpiUtCreateIntegerObject ((UINT64)
1147 TempDesc->Buffer.Pointer[Operand[0]->Reference.Value]);
1148 if (!ReturnDesc)
1149 {
1150 Status = AE_NO_MEMORY;
1151 goto Cleanup;
1152 }
1153 break;
1154
1155 case ACPI_TYPE_PACKAGE:
1156 /*
1157 * Return the referenced element of the package. We must
1158 * add another reference to the referenced object, however.
1159 */
1160 ReturnDesc = *(Operand[0]->Reference.Where);
1161 if (!ReturnDesc)
1162 {
1163 /*
1164 * Element is NULL, do not allow the dereference.
1165 * This provides compatibility with other ACPI
1166 * implementations.
1167 */
1168 return_ACPI_STATUS (AE_AML_UNINITIALIZED_ELEMENT);
1169 }
1170
1171 AcpiUtAddReference (ReturnDesc);
1172 break;
1173
1174 default:
1175
1176 ACPI_ERROR ((AE_INFO,
1177 "Unknown Index TargetType 0x%X in reference object %p",
1178 Operand[0]->Reference.TargetType, Operand[0]));
1179
1180 Status = AE_AML_OPERAND_TYPE;
1181 goto Cleanup;
1182 }
1183 break;
1184
1185 case ACPI_REFCLASS_REFOF:
1186
1187 ReturnDesc = Operand[0]->Reference.Object;
1188
1189 if (ACPI_GET_DESCRIPTOR_TYPE (ReturnDesc) ==
1190 ACPI_DESC_TYPE_NAMED)
1191 {
1192 ReturnDesc = AcpiNsGetAttachedObject (
1193 (ACPI_NAMESPACE_NODE *) ReturnDesc);
1194 if (!ReturnDesc)
1195 {
1196 break;
1197 }
1198
1199 /*
1200 * June 2013:
1201 * BufferFields/FieldUnits require additional resolution
1202 */
1203 switch (ReturnDesc->Common.Type)
1204 {
1205 case ACPI_TYPE_BUFFER_FIELD:
1206 case ACPI_TYPE_LOCAL_REGION_FIELD:
1207 case ACPI_TYPE_LOCAL_BANK_FIELD:
1208 case ACPI_TYPE_LOCAL_INDEX_FIELD:
1209
1210 Status = AcpiExReadDataFromField (
1211 WalkState, ReturnDesc, &TempDesc);
1212 if (ACPI_FAILURE (Status))
1213 {
1214 return_ACPI_STATUS (Status);
1215 }
1216
1217 ReturnDesc = TempDesc;
1218 break;
1219
1220 default:
1221
1222 /* Add another reference to the object */
1223
1224 AcpiUtAddReference (ReturnDesc);
1225 break;
1226 }
1227 }
1228 break;
1229
1230 default:
1231
1232 ACPI_ERROR ((AE_INFO,
1233 "Unknown class in reference(%p) - 0x%2.2X",
1234 Operand[0], Operand[0]->Reference.Class));
1235
1236 Status = AE_TYPE;
1237 goto Cleanup;
1238 }
1239 }
1240 break;
1241
1242 default:
1243
1244 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
1245 WalkState->Opcode));
1246
1247 Status = AE_AML_BAD_OPCODE;
1248 goto Cleanup;
1249 }
1250
1251
1252 Cleanup:
1253
1254 /* Delete return object on error */
1255
1256 if (ACPI_FAILURE (Status))
1257 {
1258 AcpiUtRemoveReference (ReturnDesc);
1259 }
1260
1261 /* Save return object on success */
1262
1263 else
1264 {
1265 WalkState->ResultObj = ReturnDesc;
1266 }
1267
1268 return_ACPI_STATUS (Status);
1269 }
1270