[ACPI]
[reactos.git] / reactos / drivers / bus / acpi / acpica / executer / exoparg1.c
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 - 2014, 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 #define __EXOPARG1_C__
117
118 #include "acpi.h"
119 #include "accommon.h"
120 #include "acparser.h"
121 #include "acdispat.h"
122 #include "acinterp.h"
123 #include "amlcode.h"
124 #include "acnamesp.h"
125
126
127 #define _COMPONENT ACPI_EXECUTER
128 ACPI_MODULE_NAME ("exoparg1")
129
130
131 /*!
132 * Naming convention for AML interpreter execution routines.
133 *
134 * The routines that begin execution of AML opcodes are named with a common
135 * convention based upon the number of arguments, the number of target operands,
136 * and whether or not a value is returned:
137 *
138 * AcpiExOpcode_xA_yT_zR
139 *
140 * Where:
141 *
142 * xA - ARGUMENTS: The number of arguments (input operands) that are
143 * required for this opcode type (0 through 6 args).
144 * yT - TARGETS: The number of targets (output operands) that are required
145 * for this opcode type (0, 1, or 2 targets).
146 * zR - RETURN VALUE: Indicates whether this opcode type returns a value
147 * as the function return (0 or 1).
148 *
149 * The AcpiExOpcode* functions are called via the Dispatcher component with
150 * fully resolved operands.
151 !*/
152
153 /*******************************************************************************
154 *
155 * FUNCTION: AcpiExOpcode_0A_0T_1R
156 *
157 * PARAMETERS: WalkState - Current state (contains AML opcode)
158 *
159 * RETURN: Status
160 *
161 * DESCRIPTION: Execute operator with no operands, one return value
162 *
163 ******************************************************************************/
164
165 ACPI_STATUS
166 AcpiExOpcode_0A_0T_1R (
167 ACPI_WALK_STATE *WalkState)
168 {
169 ACPI_STATUS Status = AE_OK;
170 ACPI_OPERAND_OBJECT *ReturnDesc = NULL;
171
172
173 ACPI_FUNCTION_TRACE_STR (ExOpcode_0A_0T_1R,
174 AcpiPsGetOpcodeName (WalkState->Opcode));
175
176
177 /* Examine the AML opcode */
178
179 switch (WalkState->Opcode)
180 {
181 case AML_TIMER_OP: /* Timer () */
182
183 /* Create a return object of type Integer */
184
185 ReturnDesc = AcpiUtCreateIntegerObject (AcpiOsGetTimer ());
186 if (!ReturnDesc)
187 {
188 Status = AE_NO_MEMORY;
189 goto Cleanup;
190 }
191 break;
192
193 default: /* Unknown opcode */
194
195 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
196 WalkState->Opcode));
197 Status = AE_AML_BAD_OPCODE;
198 break;
199 }
200
201 Cleanup:
202
203 /* Delete return object on error */
204
205 if ((ACPI_FAILURE (Status)) || WalkState->ResultObj)
206 {
207 AcpiUtRemoveReference (ReturnDesc);
208 WalkState->ResultObj = NULL;
209 }
210 else
211 {
212 /* Save the return value */
213
214 WalkState->ResultObj = ReturnDesc;
215 }
216
217 return_ACPI_STATUS (Status);
218 }
219
220
221 /*******************************************************************************
222 *
223 * FUNCTION: AcpiExOpcode_1A_0T_0R
224 *
225 * PARAMETERS: WalkState - Current state (contains AML opcode)
226 *
227 * RETURN: Status
228 *
229 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on
230 * object stack
231 *
232 ******************************************************************************/
233
234 ACPI_STATUS
235 AcpiExOpcode_1A_0T_0R (
236 ACPI_WALK_STATE *WalkState)
237 {
238 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];
239 ACPI_STATUS Status = AE_OK;
240
241
242 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_0R,
243 AcpiPsGetOpcodeName (WalkState->Opcode));
244
245
246 /* Examine the AML opcode */
247
248 switch (WalkState->Opcode)
249 {
250 case AML_RELEASE_OP: /* Release (MutexObject) */
251
252 Status = AcpiExReleaseMutex (Operand[0], WalkState);
253 break;
254
255 case AML_RESET_OP: /* Reset (EventObject) */
256
257 Status = AcpiExSystemResetEvent (Operand[0]);
258 break;
259
260 case AML_SIGNAL_OP: /* Signal (EventObject) */
261
262 Status = AcpiExSystemSignalEvent (Operand[0]);
263 break;
264
265 case AML_SLEEP_OP: /* Sleep (MsecTime) */
266
267 Status = AcpiExSystemDoSleep (Operand[0]->Integer.Value);
268 break;
269
270 case AML_STALL_OP: /* Stall (UsecTime) */
271
272 Status = AcpiExSystemDoStall ((UINT32) Operand[0]->Integer.Value);
273 break;
274
275 case AML_UNLOAD_OP: /* Unload (Handle) */
276
277 Status = AcpiExUnloadTable (Operand[0]);
278 break;
279
280 default: /* Unknown opcode */
281
282 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
283 WalkState->Opcode));
284 Status = AE_AML_BAD_OPCODE;
285 break;
286 }
287
288 return_ACPI_STATUS (Status);
289 }
290
291
292 /*******************************************************************************
293 *
294 * FUNCTION: AcpiExOpcode_1A_1T_0R
295 *
296 * PARAMETERS: WalkState - Current state (contains AML opcode)
297 *
298 * RETURN: Status
299 *
300 * DESCRIPTION: Execute opcode with one argument, one target, and no
301 * return value.
302 *
303 ******************************************************************************/
304
305 ACPI_STATUS
306 AcpiExOpcode_1A_1T_0R (
307 ACPI_WALK_STATE *WalkState)
308 {
309 ACPI_STATUS Status = AE_OK;
310 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];
311
312
313 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_0R,
314 AcpiPsGetOpcodeName (WalkState->Opcode));
315
316
317 /* Examine the AML opcode */
318
319 switch (WalkState->Opcode)
320 {
321 case AML_LOAD_OP:
322
323 Status = AcpiExLoadOp (Operand[0], Operand[1], WalkState);
324 break;
325
326 default: /* Unknown opcode */
327
328 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
329 WalkState->Opcode));
330 Status = AE_AML_BAD_OPCODE;
331 goto Cleanup;
332 }
333
334
335 Cleanup:
336
337 return_ACPI_STATUS (Status);
338 }
339
340
341 /*******************************************************************************
342 *
343 * FUNCTION: AcpiExOpcode_1A_1T_1R
344 *
345 * PARAMETERS: WalkState - Current state (contains AML opcode)
346 *
347 * RETURN: Status
348 *
349 * DESCRIPTION: Execute opcode with one argument, one target, and a
350 * return value.
351 *
352 ******************************************************************************/
353
354 ACPI_STATUS
355 AcpiExOpcode_1A_1T_1R (
356 ACPI_WALK_STATE *WalkState)
357 {
358 ACPI_STATUS Status = AE_OK;
359 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];
360 ACPI_OPERAND_OBJECT *ReturnDesc = NULL;
361 ACPI_OPERAND_OBJECT *ReturnDesc2 = NULL;
362 UINT32 Temp32;
363 UINT32 i;
364 UINT64 PowerOfTen;
365 UINT64 Digit;
366
367
368 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_1T_1R,
369 AcpiPsGetOpcodeName (WalkState->Opcode));
370
371
372 /* Examine the AML opcode */
373
374 switch (WalkState->Opcode)
375 {
376 case AML_BIT_NOT_OP:
377 case AML_FIND_SET_LEFT_BIT_OP:
378 case AML_FIND_SET_RIGHT_BIT_OP:
379 case AML_FROM_BCD_OP:
380 case AML_TO_BCD_OP:
381 case AML_COND_REF_OF_OP:
382
383 /* Create a return object of type Integer for these opcodes */
384
385 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
386 if (!ReturnDesc)
387 {
388 Status = AE_NO_MEMORY;
389 goto Cleanup;
390 }
391
392 switch (WalkState->Opcode)
393 {
394 case AML_BIT_NOT_OP: /* Not (Operand, Result) */
395
396 ReturnDesc->Integer.Value = ~Operand[0]->Integer.Value;
397 break;
398
399 case AML_FIND_SET_LEFT_BIT_OP: /* FindSetLeftBit (Operand, Result) */
400
401 ReturnDesc->Integer.Value = Operand[0]->Integer.Value;
402
403 /*
404 * Acpi specification describes Integer type as a little
405 * endian unsigned value, so this boundary condition is valid.
406 */
407 for (Temp32 = 0; ReturnDesc->Integer.Value &&
408 Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32)
409 {
410 ReturnDesc->Integer.Value >>= 1;
411 }
412
413 ReturnDesc->Integer.Value = Temp32;
414 break;
415
416 case AML_FIND_SET_RIGHT_BIT_OP: /* FindSetRightBit (Operand, Result) */
417
418 ReturnDesc->Integer.Value = Operand[0]->Integer.Value;
419
420 /*
421 * The Acpi specification describes Integer type as a little
422 * endian unsigned value, so this boundary condition is valid.
423 */
424 for (Temp32 = 0; ReturnDesc->Integer.Value &&
425 Temp32 < ACPI_INTEGER_BIT_SIZE; ++Temp32)
426 {
427 ReturnDesc->Integer.Value <<= 1;
428 }
429
430 /* Since the bit position is one-based, subtract from 33 (65) */
431
432 ReturnDesc->Integer.Value =
433 Temp32 == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - Temp32;
434 break;
435
436 case AML_FROM_BCD_OP: /* FromBcd (BCDValue, Result) */
437 /*
438 * The 64-bit ACPI integer can hold 16 4-bit BCD characters
439 * (if table is 32-bit, integer can hold 8 BCD characters)
440 * Convert each 4-bit BCD value
441 */
442 PowerOfTen = 1;
443 ReturnDesc->Integer.Value = 0;
444 Digit = Operand[0]->Integer.Value;
445
446 /* Convert each BCD digit (each is one nybble wide) */
447
448 for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++)
449 {
450 /* Get the least significant 4-bit BCD digit */
451
452 Temp32 = ((UINT32) Digit) & 0xF;
453
454 /* Check the range of the digit */
455
456 if (Temp32 > 9)
457 {
458 ACPI_ERROR ((AE_INFO,
459 "BCD digit too large (not decimal): 0x%X",
460 Temp32));
461
462 Status = AE_AML_NUMERIC_OVERFLOW;
463 goto Cleanup;
464 }
465
466 /* Sum the digit into the result with the current power of 10 */
467
468 ReturnDesc->Integer.Value +=
469 (((UINT64) Temp32) * PowerOfTen);
470
471 /* Shift to next BCD digit */
472
473 Digit >>= 4;
474
475 /* Next power of 10 */
476
477 PowerOfTen *= 10;
478 }
479 break;
480
481 case AML_TO_BCD_OP: /* ToBcd (Operand, Result) */
482
483 ReturnDesc->Integer.Value = 0;
484 Digit = Operand[0]->Integer.Value;
485
486 /* Each BCD digit is one nybble wide */
487
488 for (i = 0; (i < AcpiGbl_IntegerNybbleWidth) && (Digit > 0); i++)
489 {
490 (void) AcpiUtShortDivide (Digit, 10, &Digit, &Temp32);
491
492 /*
493 * Insert the BCD digit that resides in the
494 * remainder from above
495 */
496 ReturnDesc->Integer.Value |=
497 (((UINT64) Temp32) << ACPI_MUL_4 (i));
498 }
499
500 /* Overflow if there is any data left in Digit */
501
502 if (Digit > 0)
503 {
504 ACPI_ERROR ((AE_INFO,
505 "Integer too large to convert to BCD: 0x%8.8X%8.8X",
506 ACPI_FORMAT_UINT64 (Operand[0]->Integer.Value)));
507 Status = AE_AML_NUMERIC_OVERFLOW;
508 goto Cleanup;
509 }
510 break;
511
512 case AML_COND_REF_OF_OP: /* CondRefOf (SourceObject, Result) */
513 /*
514 * This op is a little strange because the internal return value is
515 * different than the return value stored in the result descriptor
516 * (There are really two return values)
517 */
518 if ((ACPI_NAMESPACE_NODE *) Operand[0] == AcpiGbl_RootNode)
519 {
520 /*
521 * This means that the object does not exist in the namespace,
522 * return FALSE
523 */
524 ReturnDesc->Integer.Value = 0;
525 goto Cleanup;
526 }
527
528 /* Get the object reference, store it, and remove our reference */
529
530 Status = AcpiExGetObjectReference (Operand[0],
531 &ReturnDesc2, WalkState);
532 if (ACPI_FAILURE (Status))
533 {
534 goto Cleanup;
535 }
536
537 Status = AcpiExStore (ReturnDesc2, Operand[1], WalkState);
538 AcpiUtRemoveReference (ReturnDesc2);
539
540 /* The object exists in the namespace, return TRUE */
541
542 ReturnDesc->Integer.Value = ACPI_UINT64_MAX;
543 goto Cleanup;
544
545
546 default:
547
548 /* No other opcodes get here */
549
550 break;
551 }
552 break;
553
554 case AML_STORE_OP: /* Store (Source, Target) */
555 /*
556 * A store operand is typically a number, string, buffer or lvalue
557 * Be careful about deleting the source object,
558 * since the object itself may have been stored.
559 */
560 Status = AcpiExStore (Operand[0], Operand[1], WalkState);
561 if (ACPI_FAILURE (Status))
562 {
563 return_ACPI_STATUS (Status);
564 }
565
566 /* It is possible that the Store already produced a return object */
567
568 if (!WalkState->ResultObj)
569 {
570 /*
571 * Normally, we would remove a reference on the Operand[0]
572 * parameter; But since it is being used as the internal return
573 * object (meaning we would normally increment it), the two
574 * cancel out, and we simply don't do anything.
575 */
576 WalkState->ResultObj = Operand[0];
577 WalkState->Operands[0] = NULL; /* Prevent deletion */
578 }
579 return_ACPI_STATUS (Status);
580
581 /*
582 * ACPI 2.0 Opcodes
583 */
584 case AML_COPY_OP: /* Copy (Source, Target) */
585
586 Status = AcpiUtCopyIobjectToIobject (Operand[0], &ReturnDesc,
587 WalkState);
588 break;
589
590 case AML_TO_DECSTRING_OP: /* ToDecimalString (Data, Result) */
591
592 Status = AcpiExConvertToString (Operand[0], &ReturnDesc,
593 ACPI_EXPLICIT_CONVERT_DECIMAL);
594 if (ReturnDesc == Operand[0])
595 {
596 /* No conversion performed, add ref to handle return value */
597 AcpiUtAddReference (ReturnDesc);
598 }
599 break;
600
601 case AML_TO_HEXSTRING_OP: /* ToHexString (Data, Result) */
602
603 Status = AcpiExConvertToString (Operand[0], &ReturnDesc,
604 ACPI_EXPLICIT_CONVERT_HEX);
605 if (ReturnDesc == Operand[0])
606 {
607 /* No conversion performed, add ref to handle return value */
608 AcpiUtAddReference (ReturnDesc);
609 }
610 break;
611
612 case AML_TO_BUFFER_OP: /* ToBuffer (Data, Result) */
613
614 Status = AcpiExConvertToBuffer (Operand[0], &ReturnDesc);
615 if (ReturnDesc == Operand[0])
616 {
617 /* No conversion performed, add ref to handle return value */
618 AcpiUtAddReference (ReturnDesc);
619 }
620 break;
621
622 case AML_TO_INTEGER_OP: /* ToInteger (Data, Result) */
623
624 Status = AcpiExConvertToInteger (Operand[0], &ReturnDesc,
625 ACPI_ANY_BASE);
626 if (ReturnDesc == Operand[0])
627 {
628 /* No conversion performed, add ref to handle return value */
629 AcpiUtAddReference (ReturnDesc);
630 }
631 break;
632
633 case AML_SHIFT_LEFT_BIT_OP: /* ShiftLeftBit (Source, BitNum) */
634 case AML_SHIFT_RIGHT_BIT_OP: /* ShiftRightBit (Source, BitNum) */
635
636 /* These are two obsolete opcodes */
637
638 ACPI_ERROR ((AE_INFO,
639 "%s is obsolete and not implemented",
640 AcpiPsGetOpcodeName (WalkState->Opcode)));
641 Status = AE_SUPPORT;
642 goto Cleanup;
643
644 default: /* Unknown opcode */
645
646 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
647 WalkState->Opcode));
648 Status = AE_AML_BAD_OPCODE;
649 goto Cleanup;
650 }
651
652 if (ACPI_SUCCESS (Status))
653 {
654 /* Store the return value computed above into the target object */
655
656 Status = AcpiExStore (ReturnDesc, Operand[1], WalkState);
657 }
658
659
660 Cleanup:
661
662 /* Delete return object on error */
663
664 if (ACPI_FAILURE (Status))
665 {
666 AcpiUtRemoveReference (ReturnDesc);
667 }
668
669 /* Save return object on success */
670
671 else if (!WalkState->ResultObj)
672 {
673 WalkState->ResultObj = ReturnDesc;
674 }
675
676 return_ACPI_STATUS (Status);
677 }
678
679
680 /*******************************************************************************
681 *
682 * FUNCTION: AcpiExOpcode_1A_0T_1R
683 *
684 * PARAMETERS: WalkState - Current state (contains AML opcode)
685 *
686 * RETURN: Status
687 *
688 * DESCRIPTION: Execute opcode with one argument, no target, and a return value
689 *
690 ******************************************************************************/
691
692 ACPI_STATUS
693 AcpiExOpcode_1A_0T_1R (
694 ACPI_WALK_STATE *WalkState)
695 {
696 ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0];
697 ACPI_OPERAND_OBJECT *TempDesc;
698 ACPI_OPERAND_OBJECT *ReturnDesc = NULL;
699 ACPI_STATUS Status = AE_OK;
700 UINT32 Type;
701 UINT64 Value;
702
703
704 ACPI_FUNCTION_TRACE_STR (ExOpcode_1A_0T_1R,
705 AcpiPsGetOpcodeName (WalkState->Opcode));
706
707
708 /* Examine the AML opcode */
709
710 switch (WalkState->Opcode)
711 {
712 case AML_LNOT_OP: /* LNot (Operand) */
713
714 ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) 0);
715 if (!ReturnDesc)
716 {
717 Status = AE_NO_MEMORY;
718 goto Cleanup;
719 }
720
721 /*
722 * Set result to ONES (TRUE) if Value == 0. Note:
723 * ReturnDesc->Integer.Value is initially == 0 (FALSE) from above.
724 */
725 if (!Operand[0]->Integer.Value)
726 {
727 ReturnDesc->Integer.Value = ACPI_UINT64_MAX;
728 }
729 break;
730
731 case AML_DECREMENT_OP: /* Decrement (Operand) */
732 case AML_INCREMENT_OP: /* Increment (Operand) */
733 /*
734 * Create a new integer. Can't just get the base integer and
735 * increment it because it may be an Arg or Field.
736 */
737 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
738 if (!ReturnDesc)
739 {
740 Status = AE_NO_MEMORY;
741 goto Cleanup;
742 }
743
744 /*
745 * Since we are expecting a Reference operand, it can be either a
746 * NS Node or an internal object.
747 */
748 TempDesc = Operand[0];
749 if (ACPI_GET_DESCRIPTOR_TYPE (TempDesc) == ACPI_DESC_TYPE_OPERAND)
750 {
751 /* Internal reference object - prevent deletion */
752
753 AcpiUtAddReference (TempDesc);
754 }
755
756 /*
757 * Convert the Reference operand to an Integer (This removes a
758 * reference on the Operand[0] object)
759 *
760 * NOTE: We use LNOT_OP here in order to force resolution of the
761 * reference operand to an actual integer.
762 */
763 Status = AcpiExResolveOperands (AML_LNOT_OP, &TempDesc, WalkState);
764 if (ACPI_FAILURE (Status))
765 {
766 ACPI_EXCEPTION ((AE_INFO, Status,
767 "While resolving operands for [%s]",
768 AcpiPsGetOpcodeName (WalkState->Opcode)));
769
770 goto Cleanup;
771 }
772
773 /*
774 * TempDesc is now guaranteed to be an Integer object --
775 * Perform the actual increment or decrement
776 */
777 if (WalkState->Opcode == AML_INCREMENT_OP)
778 {
779 ReturnDesc->Integer.Value = TempDesc->Integer.Value +1;
780 }
781 else
782 {
783 ReturnDesc->Integer.Value = TempDesc->Integer.Value -1;
784 }
785
786 /* Finished with this Integer object */
787
788 AcpiUtRemoveReference (TempDesc);
789
790 /*
791 * Store the result back (indirectly) through the original
792 * Reference object
793 */
794 Status = AcpiExStore (ReturnDesc, Operand[0], WalkState);
795 break;
796
797 case AML_TYPE_OP: /* ObjectType (SourceObject) */
798 /*
799 * Note: The operand is not resolved at this point because we want to
800 * get the associated object, not its value. For example, we don't
801 * want to resolve a FieldUnit to its value, we want the actual
802 * FieldUnit object.
803 */
804
805 /* Get the type of the base object */
806
807 Status = AcpiExResolveMultiple (WalkState, Operand[0], &Type, NULL);
808 if (ACPI_FAILURE (Status))
809 {
810 goto Cleanup;
811 }
812
813 /* Allocate a descriptor to hold the type. */
814
815 ReturnDesc = AcpiUtCreateIntegerObject ((UINT64) Type);
816 if (!ReturnDesc)
817 {
818 Status = AE_NO_MEMORY;
819 goto Cleanup;
820 }
821 break;
822
823 case AML_SIZE_OF_OP: /* SizeOf (SourceObject) */
824 /*
825 * Note: The operand is not resolved at this point because we want to
826 * get the associated object, not its value.
827 */
828
829 /* Get the base object */
830
831 Status = AcpiExResolveMultiple (WalkState,
832 Operand[0], &Type, &TempDesc);
833 if (ACPI_FAILURE (Status))
834 {
835 goto Cleanup;
836 }
837
838 /*
839 * The type of the base object must be integer, buffer, string, or
840 * package. All others are not supported.
841 *
842 * NOTE: Integer is not specifically supported by the ACPI spec,
843 * but is supported implicitly via implicit operand conversion.
844 * rather than bother with conversion, we just use the byte width
845 * global (4 or 8 bytes).
846 */
847 switch (Type)
848 {
849 case ACPI_TYPE_INTEGER:
850
851 Value = AcpiGbl_IntegerByteWidth;
852 break;
853
854 case ACPI_TYPE_STRING:
855
856 Value = TempDesc->String.Length;
857 break;
858
859 case ACPI_TYPE_BUFFER:
860
861 /* Buffer arguments may not be evaluated at this point */
862
863 Status = AcpiDsGetBufferArguments (TempDesc);
864 Value = TempDesc->Buffer.Length;
865 break;
866
867 case ACPI_TYPE_PACKAGE:
868
869 /* Package arguments may not be evaluated at this point */
870
871 Status = AcpiDsGetPackageArguments (TempDesc);
872 Value = TempDesc->Package.Count;
873 break;
874
875 default:
876
877 ACPI_ERROR ((AE_INFO,
878 "Operand must be Buffer/Integer/String/Package - found type %s",
879 AcpiUtGetTypeName (Type)));
880 Status = AE_AML_OPERAND_TYPE;
881 goto Cleanup;
882 }
883
884 if (ACPI_FAILURE (Status))
885 {
886 goto Cleanup;
887 }
888
889 /*
890 * Now that we have the size of the object, create a result
891 * object to hold the value
892 */
893 ReturnDesc = AcpiUtCreateIntegerObject (Value);
894 if (!ReturnDesc)
895 {
896 Status = AE_NO_MEMORY;
897 goto Cleanup;
898 }
899 break;
900
901
902 case AML_REF_OF_OP: /* RefOf (SourceObject) */
903
904 Status = AcpiExGetObjectReference (Operand[0], &ReturnDesc, WalkState);
905 if (ACPI_FAILURE (Status))
906 {
907 goto Cleanup;
908 }
909 break;
910
911
912 case AML_DEREF_OF_OP: /* DerefOf (ObjReference | String) */
913
914 /* Check for a method local or argument, or standalone String */
915
916 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED)
917 {
918 TempDesc = AcpiNsGetAttachedObject (
919 (ACPI_NAMESPACE_NODE *) Operand[0]);
920 if (TempDesc &&
921 ((TempDesc->Common.Type == ACPI_TYPE_STRING) ||
922 (TempDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE)))
923 {
924 Operand[0] = TempDesc;
925 AcpiUtAddReference (TempDesc);
926 }
927 else
928 {
929 Status = AE_AML_OPERAND_TYPE;
930 goto Cleanup;
931 }
932 }
933 else
934 {
935 switch ((Operand[0])->Common.Type)
936 {
937 case ACPI_TYPE_LOCAL_REFERENCE:
938 /*
939 * This is a DerefOf (LocalX | ArgX)
940 *
941 * Must resolve/dereference the local/arg reference first
942 */
943 switch (Operand[0]->Reference.Class)
944 {
945 case ACPI_REFCLASS_LOCAL:
946 case ACPI_REFCLASS_ARG:
947
948 /* Set Operand[0] to the value of the local/arg */
949
950 Status = AcpiDsMethodDataGetValue (
951 Operand[0]->Reference.Class,
952 Operand[0]->Reference.Value,
953 WalkState, &TempDesc);
954 if (ACPI_FAILURE (Status))
955 {
956 goto Cleanup;
957 }
958
959 /*
960 * Delete our reference to the input object and
961 * point to the object just retrieved
962 */
963 AcpiUtRemoveReference (Operand[0]);
964 Operand[0] = TempDesc;
965 break;
966
967 case ACPI_REFCLASS_REFOF:
968
969 /* Get the object to which the reference refers */
970
971 TempDesc = Operand[0]->Reference.Object;
972 AcpiUtRemoveReference (Operand[0]);
973 Operand[0] = TempDesc;
974 break;
975
976 default:
977
978 /* Must be an Index op - handled below */
979 break;
980 }
981 break;
982
983 case ACPI_TYPE_STRING:
984
985 break;
986
987 default:
988
989 Status = AE_AML_OPERAND_TYPE;
990 goto Cleanup;
991 }
992 }
993
994 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) != ACPI_DESC_TYPE_NAMED)
995 {
996 if ((Operand[0])->Common.Type == ACPI_TYPE_STRING)
997 {
998 /*
999 * This is a DerefOf (String). The string is a reference
1000 * to a named ACPI object.
1001 *
1002 * 1) Find the owning Node
1003 * 2) Dereference the node to an actual object. Could be a
1004 * Field, so we need to resolve the node to a value.
1005 */
1006 Status = AcpiNsGetNode (WalkState->ScopeInfo->Scope.Node,
1007 Operand[0]->String.Pointer,
1008 ACPI_NS_SEARCH_PARENT,
1009 ACPI_CAST_INDIRECT_PTR (
1010 ACPI_NAMESPACE_NODE, &ReturnDesc));
1011 if (ACPI_FAILURE (Status))
1012 {
1013 goto Cleanup;
1014 }
1015
1016 Status = AcpiExResolveNodeToValue (
1017 ACPI_CAST_INDIRECT_PTR (
1018 ACPI_NAMESPACE_NODE, &ReturnDesc),
1019 WalkState);
1020 goto Cleanup;
1021 }
1022 }
1023
1024 /* Operand[0] may have changed from the code above */
1025
1026 if (ACPI_GET_DESCRIPTOR_TYPE (Operand[0]) == ACPI_DESC_TYPE_NAMED)
1027 {
1028 /*
1029 * This is a DerefOf (ObjectReference)
1030 * Get the actual object from the Node (This is the dereference).
1031 * This case may only happen when a LocalX or ArgX is
1032 * dereferenced above.
1033 */
1034 ReturnDesc = AcpiNsGetAttachedObject (
1035 (ACPI_NAMESPACE_NODE *) Operand[0]);
1036 AcpiUtAddReference (ReturnDesc);
1037 }
1038 else
1039 {
1040 /*
1041 * This must be a reference object produced by either the
1042 * Index() or RefOf() operator
1043 */
1044 switch (Operand[0]->Reference.Class)
1045 {
1046 case ACPI_REFCLASS_INDEX:
1047 /*
1048 * The target type for the Index operator must be
1049 * either a Buffer or a Package
1050 */
1051 switch (Operand[0]->Reference.TargetType)
1052 {
1053 case ACPI_TYPE_BUFFER_FIELD:
1054
1055 TempDesc = Operand[0]->Reference.Object;
1056
1057 /*
1058 * Create a new object that contains one element of the
1059 * buffer -- the element pointed to by the index.
1060 *
1061 * NOTE: index into a buffer is NOT a pointer to a
1062 * sub-buffer of the main buffer, it is only a pointer to a
1063 * single element (byte) of the buffer!
1064 *
1065 * Since we are returning the value of the buffer at the
1066 * indexed location, we don't need to add an additional
1067 * reference to the buffer itself.
1068 */
1069 ReturnDesc = AcpiUtCreateIntegerObject ((UINT64)
1070 TempDesc->Buffer.Pointer[Operand[0]->Reference.Value]);
1071 if (!ReturnDesc)
1072 {
1073 Status = AE_NO_MEMORY;
1074 goto Cleanup;
1075 }
1076 break;
1077
1078 case ACPI_TYPE_PACKAGE:
1079 /*
1080 * Return the referenced element of the package. We must
1081 * add another reference to the referenced object, however.
1082 */
1083 ReturnDesc = *(Operand[0]->Reference.Where);
1084 if (!ReturnDesc)
1085 {
1086 /*
1087 * Element is NULL, do not allow the dereference.
1088 * This provides compatibility with other ACPI
1089 * implementations.
1090 */
1091 return_ACPI_STATUS (AE_AML_UNINITIALIZED_ELEMENT);
1092 }
1093
1094 AcpiUtAddReference (ReturnDesc);
1095 break;
1096
1097 default:
1098
1099 ACPI_ERROR ((AE_INFO,
1100 "Unknown Index TargetType 0x%X in reference object %p",
1101 Operand[0]->Reference.TargetType, Operand[0]));
1102 Status = AE_AML_OPERAND_TYPE;
1103 goto Cleanup;
1104 }
1105 break;
1106
1107 case ACPI_REFCLASS_REFOF:
1108
1109 ReturnDesc = Operand[0]->Reference.Object;
1110
1111 if (ACPI_GET_DESCRIPTOR_TYPE (ReturnDesc) ==
1112 ACPI_DESC_TYPE_NAMED)
1113 {
1114 ReturnDesc = AcpiNsGetAttachedObject (
1115 (ACPI_NAMESPACE_NODE *) ReturnDesc);
1116 if (!ReturnDesc)
1117 {
1118 break;
1119 }
1120
1121 /*
1122 * June 2013:
1123 * BufferFields/FieldUnits require additional resolution
1124 */
1125 switch (ReturnDesc->Common.Type)
1126 {
1127 case ACPI_TYPE_BUFFER_FIELD:
1128 case ACPI_TYPE_LOCAL_REGION_FIELD:
1129 case ACPI_TYPE_LOCAL_BANK_FIELD:
1130 case ACPI_TYPE_LOCAL_INDEX_FIELD:
1131
1132 Status = AcpiExReadDataFromField (WalkState,
1133 ReturnDesc, &TempDesc);
1134 if (ACPI_FAILURE (Status))
1135 {
1136 goto Cleanup;
1137 }
1138
1139 ReturnDesc = TempDesc;
1140 break;
1141
1142 default:
1143
1144 /* Add another reference to the object */
1145
1146 AcpiUtAddReference (ReturnDesc);
1147 break;
1148 }
1149 }
1150 break;
1151
1152 default:
1153
1154 ACPI_ERROR ((AE_INFO,
1155 "Unknown class in reference(%p) - 0x%2.2X",
1156 Operand[0], Operand[0]->Reference.Class));
1157
1158 Status = AE_TYPE;
1159 goto Cleanup;
1160 }
1161 }
1162 break;
1163
1164 default:
1165
1166 ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
1167 WalkState->Opcode));
1168 Status = AE_AML_BAD_OPCODE;
1169 goto Cleanup;
1170 }
1171
1172
1173 Cleanup:
1174
1175 /* Delete return object on error */
1176
1177 if (ACPI_FAILURE (Status))
1178 {
1179 AcpiUtRemoveReference (ReturnDesc);
1180 }
1181
1182 /* Save return object on success */
1183
1184 else
1185 {
1186 WalkState->ResultObj = ReturnDesc;
1187 }
1188
1189 return_ACPI_STATUS (Status);
1190 }