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