Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6595 serge 1
/******************************************************************************
2
 *
3
 * Module Name: exoparg1 - AML execution - opcodes with 1 argument
4
 *
5
 *****************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2015, Intel Corp.
9
 * All rights reserved.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions, and the following disclaimer,
16
 *    without modification.
17
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18
 *    substantially similar to the "NO WARRANTY" disclaimer below
19
 *    ("Disclaimer") and any redistribution must be conditioned upon
20
 *    including a substantially similar Disclaimer requirement for further
21
 *    binary redistribution.
22
 * 3. Neither the names of the above-listed copyright holders nor the names
23
 *    of any contributors may be used to endorse or promote products derived
24
 *    from this software without specific prior written permission.
25
 *
26
 * Alternatively, this software may be distributed under the terms of the
27
 * GNU General Public License ("GPL") version 2 as published by the Free
28
 * Software Foundation.
29
 *
30
 * NO WARRANTY
31
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41
 * POSSIBILITY OF SUCH DAMAGES.
42
 */
43
 
44
#include 
45
#include "accommon.h"
46
#include "acparser.h"
47
#include "acdispat.h"
48
#include "acinterp.h"
49
#include "amlcode.h"
50
#include "acnamesp.h"
51
 
52
#define _COMPONENT          ACPI_EXECUTER
53
ACPI_MODULE_NAME("exoparg1")
54
 
55
/*!
56
 * Naming convention for AML interpreter execution routines.
57
 *
58
 * The routines that begin execution of AML opcodes are named with a common
59
 * convention based upon the number of arguments, the number of target operands,
60
 * and whether or not a value is returned:
61
 *
62
 *      AcpiExOpcode_xA_yT_zR
63
 *
64
 * Where:
65
 *
66
 * xA - ARGUMENTS:    The number of arguments (input operands) that are
67
 *                    required for this opcode type (0 through 6 args).
68
 * yT - TARGETS:      The number of targets (output operands) that are required
69
 *                    for this opcode type (0, 1, or 2 targets).
70
 * zR - RETURN VALUE: Indicates whether this opcode type returns a value
71
 *                    as the function return (0 or 1).
72
 *
73
 * The AcpiExOpcode* functions are called via the Dispatcher component with
74
 * fully resolved operands.
75
!*/
76
/*******************************************************************************
77
 *
78
 * FUNCTION:    acpi_ex_opcode_0A_0T_1R
79
 *
80
 * PARAMETERS:  walk_state          - Current state (contains AML opcode)
81
 *
82
 * RETURN:      Status
83
 *
84
 * DESCRIPTION: Execute operator with no operands, one return value
85
 *
86
 ******************************************************************************/
87
acpi_status acpi_ex_opcode_0A_0T_1R(struct acpi_walk_state *walk_state)
88
{
89
	acpi_status status = AE_OK;
90
	union acpi_operand_object *return_desc = NULL;
91
 
92
	ACPI_FUNCTION_TRACE_STR(ex_opcode_0A_0T_1R,
93
				acpi_ps_get_opcode_name(walk_state->opcode));
94
 
95
	/* Examine the AML opcode */
96
 
97
	switch (walk_state->opcode) {
98
	case AML_TIMER_OP:	/*  Timer () */
99
 
100
		/* Create a return object of type Integer */
101
 
102
		return_desc =
103
		    acpi_ut_create_integer_object(acpi_os_get_timer());
104
		if (!return_desc) {
105
			status = AE_NO_MEMORY;
106
			goto cleanup;
107
		}
108
		break;
109
 
110
	default:		/*  Unknown opcode  */
111
 
112
		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
113
			    walk_state->opcode));
114
		status = AE_AML_BAD_OPCODE;
115
		break;
116
	}
117
 
118
cleanup:
119
 
120
	/* Delete return object on error */
121
 
122
	if ((ACPI_FAILURE(status)) || walk_state->result_obj) {
123
		acpi_ut_remove_reference(return_desc);
124
		walk_state->result_obj = NULL;
125
	} else {
126
		/* Save the return value */
127
 
128
		walk_state->result_obj = return_desc;
129
	}
130
 
131
	return_ACPI_STATUS(status);
132
}
133
 
134
/*******************************************************************************
135
 *
136
 * FUNCTION:    acpi_ex_opcode_1A_0T_0R
137
 *
138
 * PARAMETERS:  walk_state          - Current state (contains AML opcode)
139
 *
140
 * RETURN:      Status
141
 *
142
 * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on
143
 *              object stack
144
 *
145
 ******************************************************************************/
146
 
147
acpi_status acpi_ex_opcode_1A_0T_0R(struct acpi_walk_state *walk_state)
148
{
149
	union acpi_operand_object **operand = &walk_state->operands[0];
150
	acpi_status status = AE_OK;
151
 
152
	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_0R,
153
				acpi_ps_get_opcode_name(walk_state->opcode));
154
 
155
	/* Examine the AML opcode */
156
 
157
	switch (walk_state->opcode) {
158
	case AML_RELEASE_OP:	/*  Release (mutex_object) */
159
 
160
		status = acpi_ex_release_mutex(operand[0], walk_state);
161
		break;
162
 
163
	case AML_RESET_OP:	/*  Reset (event_object) */
164
 
165
		status = acpi_ex_system_reset_event(operand[0]);
166
		break;
167
 
168
	case AML_SIGNAL_OP:	/*  Signal (event_object) */
169
 
170
		status = acpi_ex_system_signal_event(operand[0]);
171
		break;
172
 
173
	case AML_SLEEP_OP:	/*  Sleep (msec_time) */
174
 
175
		status = acpi_ex_system_do_sleep(operand[0]->integer.value);
176
		break;
177
 
178
	case AML_STALL_OP:	/*  Stall (usec_time) */
179
 
180
		status =
181
		    acpi_ex_system_do_stall((u32) operand[0]->integer.value);
182
		break;
183
 
184
	case AML_UNLOAD_OP:	/*  Unload (Handle) */
185
 
186
		status = acpi_ex_unload_table(operand[0]);
187
		break;
188
 
189
	default:		/*  Unknown opcode  */
190
 
191
		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
192
			    walk_state->opcode));
193
		status = AE_AML_BAD_OPCODE;
194
		break;
195
	}
196
 
197
	return_ACPI_STATUS(status);
198
}
199
 
200
/*******************************************************************************
201
 *
202
 * FUNCTION:    acpi_ex_opcode_1A_1T_0R
203
 *
204
 * PARAMETERS:  walk_state          - Current state (contains AML opcode)
205
 *
206
 * RETURN:      Status
207
 *
208
 * DESCRIPTION: Execute opcode with one argument, one target, and no
209
 *              return value.
210
 *
211
 ******************************************************************************/
212
 
213
acpi_status acpi_ex_opcode_1A_1T_0R(struct acpi_walk_state *walk_state)
214
{
215
	acpi_status status = AE_OK;
216
	union acpi_operand_object **operand = &walk_state->operands[0];
217
 
218
	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_0R,
219
				acpi_ps_get_opcode_name(walk_state->opcode));
220
 
221
	/* Examine the AML opcode */
222
 
223
	switch (walk_state->opcode) {
224
	case AML_LOAD_OP:
225
 
226
		status = acpi_ex_load_op(operand[0], operand[1], walk_state);
227
		break;
228
 
229
	default:		/* Unknown opcode */
230
 
231
		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
232
			    walk_state->opcode));
233
		status = AE_AML_BAD_OPCODE;
234
		goto cleanup;
235
	}
236
 
237
cleanup:
238
 
239
	return_ACPI_STATUS(status);
240
}
241
 
242
/*******************************************************************************
243
 *
244
 * FUNCTION:    acpi_ex_opcode_1A_1T_1R
245
 *
246
 * PARAMETERS:  walk_state          - Current state (contains AML opcode)
247
 *
248
 * RETURN:      Status
249
 *
250
 * DESCRIPTION: Execute opcode with one argument, one target, and a
251
 *              return value.
252
 *
253
 ******************************************************************************/
254
 
255
acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
256
{
257
	acpi_status status = AE_OK;
258
	union acpi_operand_object **operand = &walk_state->operands[0];
259
	union acpi_operand_object *return_desc = NULL;
260
	union acpi_operand_object *return_desc2 = NULL;
261
	u32 temp32;
262
	u32 i;
263
	u64 power_of_ten;
264
	u64 digit;
265
 
266
	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_1T_1R,
267
				acpi_ps_get_opcode_name(walk_state->opcode));
268
 
269
	/* Examine the AML opcode */
270
 
271
	switch (walk_state->opcode) {
272
	case AML_BIT_NOT_OP:
273
	case AML_FIND_SET_LEFT_BIT_OP:
274
	case AML_FIND_SET_RIGHT_BIT_OP:
275
	case AML_FROM_BCD_OP:
276
	case AML_TO_BCD_OP:
277
	case AML_COND_REF_OF_OP:
278
 
279
		/* Create a return object of type Integer for these opcodes */
280
 
281
		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
282
		if (!return_desc) {
283
			status = AE_NO_MEMORY;
284
			goto cleanup;
285
		}
286
 
287
		switch (walk_state->opcode) {
288
		case AML_BIT_NOT_OP:	/* Not (Operand, Result)  */
289
 
290
			return_desc->integer.value = ~operand[0]->integer.value;
291
			break;
292
 
293
		case AML_FIND_SET_LEFT_BIT_OP:	/* find_set_left_bit (Operand, Result) */
294
 
295
			return_desc->integer.value = operand[0]->integer.value;
296
 
297
			/*
298
			 * Acpi specification describes Integer type as a little
299
			 * endian unsigned value, so this boundary condition is valid.
300
			 */
301
			for (temp32 = 0; return_desc->integer.value &&
302
			     temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
303
				return_desc->integer.value >>= 1;
304
			}
305
 
306
			return_desc->integer.value = temp32;
307
			break;
308
 
309
		case AML_FIND_SET_RIGHT_BIT_OP:	/* find_set_right_bit (Operand, Result) */
310
 
311
			return_desc->integer.value = operand[0]->integer.value;
312
 
313
			/*
314
			 * The Acpi specification describes Integer type as a little
315
			 * endian unsigned value, so this boundary condition is valid.
316
			 */
317
			for (temp32 = 0; return_desc->integer.value &&
318
			     temp32 < ACPI_INTEGER_BIT_SIZE; ++temp32) {
319
				return_desc->integer.value <<= 1;
320
			}
321
 
322
			/* Since the bit position is one-based, subtract from 33 (65) */
323
 
324
			return_desc->integer.value =
325
			    temp32 ==
326
 
327
			break;
328
 
329
		case AML_FROM_BCD_OP:	/* from_bcd (BCDValue, Result) */
330
			/*
331
			 * The 64-bit ACPI integer can hold 16 4-bit BCD characters
332
			 * (if table is 32-bit, integer can hold 8 BCD characters)
333
			 * Convert each 4-bit BCD value
334
			 */
335
			power_of_ten = 1;
336
			return_desc->integer.value = 0;
337
			digit = operand[0]->integer.value;
338
 
339
			/* Convert each BCD digit (each is one nybble wide) */
340
 
341
			for (i = 0;
342
			     (i < acpi_gbl_integer_nybble_width) && (digit > 0);
343
			     i++) {
344
 
345
				/* Get the least significant 4-bit BCD digit */
346
 
347
				temp32 = ((u32) digit) & 0xF;
348
 
349
				/* Check the range of the digit */
350
 
351
				if (temp32 > 9) {
352
					ACPI_ERROR((AE_INFO,
353
						    "BCD digit too large (not decimal): 0x%X",
354
						    temp32));
355
 
356
					status = AE_AML_NUMERIC_OVERFLOW;
357
					goto cleanup;
358
				}
359
 
360
				/* Sum the digit into the result with the current power of 10 */
361
 
362
				return_desc->integer.value +=
363
				    (((u64) temp32) * power_of_ten);
364
 
365
				/* Shift to next BCD digit */
366
 
367
				digit >>= 4;
368
 
369
				/* Next power of 10 */
370
 
371
				power_of_ten *= 10;
372
			}
373
			break;
374
 
375
		case AML_TO_BCD_OP:	/* to_bcd (Operand, Result) */
376
 
377
			return_desc->integer.value = 0;
378
			digit = operand[0]->integer.value;
379
 
380
			/* Each BCD digit is one nybble wide */
381
 
382
			for (i = 0;
383
			     (i < acpi_gbl_integer_nybble_width) && (digit > 0);
384
			     i++) {
385
				(void)acpi_ut_short_divide(digit, 10, &digit,
386
							   &temp32);
387
 
388
				/*
389
				 * Insert the BCD digit that resides in the
390
				 * remainder from above
391
				 */
392
				return_desc->integer.value |=
393
				    (((u64) temp32) << ACPI_MUL_4(i));
394
			}
395
 
396
			/* Overflow if there is any data left in Digit */
397
 
398
			if (digit > 0) {
399
				ACPI_ERROR((AE_INFO,
400
					    "Integer too large to convert to BCD: 0x%8.8X%8.8X",
401
					    ACPI_FORMAT_UINT64(operand[0]->
402
							       integer.value)));
403
				status = AE_AML_NUMERIC_OVERFLOW;
404
				goto cleanup;
405
			}
406
			break;
407
 
408
		case AML_COND_REF_OF_OP:	/* cond_ref_of (source_object, Result) */
409
			/*
410
			 * This op is a little strange because the internal return value is
411
			 * different than the return value stored in the result descriptor
412
			 * (There are really two return values)
413
			 */
414
			if ((struct acpi_namespace_node *)operand[0] ==
415
			    acpi_gbl_root_node) {
416
				/*
417
				 * This means that the object does not exist in the namespace,
418
				 * return FALSE
419
				 */
420
				return_desc->integer.value = 0;
421
				goto cleanup;
422
			}
423
 
424
			/* Get the object reference, store it, and remove our reference */
425
 
426
			status = acpi_ex_get_object_reference(operand[0],
427
							      &return_desc2,
428
							      walk_state);
429
			if (ACPI_FAILURE(status)) {
430
				goto cleanup;
431
			}
432
 
433
			status =
434
			    acpi_ex_store(return_desc2, operand[1], walk_state);
435
			acpi_ut_remove_reference(return_desc2);
436
 
437
			/* The object exists in the namespace, return TRUE */
438
 
439
			return_desc->integer.value = ACPI_UINT64_MAX;
440
			goto cleanup;
441
 
442
		default:
443
 
444
			/* No other opcodes get here */
445
 
446
			break;
447
		}
448
		break;
449
 
450
	case AML_STORE_OP:	/* Store (Source, Target) */
451
		/*
452
		 * A store operand is typically a number, string, buffer or lvalue
453
		 * Be careful about deleting the source object,
454
		 * since the object itself may have been stored.
455
		 */
456
		status = acpi_ex_store(operand[0], operand[1], walk_state);
457
		if (ACPI_FAILURE(status)) {
458
			return_ACPI_STATUS(status);
459
		}
460
 
461
		/* It is possible that the Store already produced a return object */
462
 
463
		if (!walk_state->result_obj) {
464
			/*
465
			 * Normally, we would remove a reference on the Operand[0]
466
			 * parameter; But since it is being used as the internal return
467
			 * object (meaning we would normally increment it), the two
468
			 * cancel out, and we simply don't do anything.
469
			 */
470
			walk_state->result_obj = operand[0];
471
			walk_state->operands[0] = NULL;	/* Prevent deletion */
472
		}
473
		return_ACPI_STATUS(status);
474
 
475
		/*
476
		 * ACPI 2.0 Opcodes
477
		 */
478
	case AML_COPY_OP:	/* Copy (Source, Target) */
479
 
480
		status =
481
		    acpi_ut_copy_iobject_to_iobject(operand[0], &return_desc,
482
						    walk_state);
483
		break;
484
 
485
	case AML_TO_DECSTRING_OP:	/* to_decimal_string (Data, Result) */
486
 
487
		status = acpi_ex_convert_to_string(operand[0], &return_desc,
488
						   ACPI_EXPLICIT_CONVERT_DECIMAL);
489
		if (return_desc == operand[0]) {
490
 
491
			/* No conversion performed, add ref to handle return value */
492
			acpi_ut_add_reference(return_desc);
493
		}
494
		break;
495
 
496
	case AML_TO_HEXSTRING_OP:	/* to_hex_string (Data, Result) */
497
 
498
		status = acpi_ex_convert_to_string(operand[0], &return_desc,
499
						   ACPI_EXPLICIT_CONVERT_HEX);
500
		if (return_desc == operand[0]) {
501
 
502
			/* No conversion performed, add ref to handle return value */
503
			acpi_ut_add_reference(return_desc);
504
		}
505
		break;
506
 
507
	case AML_TO_BUFFER_OP:	/* to_buffer (Data, Result) */
508
 
509
		status = acpi_ex_convert_to_buffer(operand[0], &return_desc);
510
		if (return_desc == operand[0]) {
511
 
512
			/* No conversion performed, add ref to handle return value */
513
			acpi_ut_add_reference(return_desc);
514
		}
515
		break;
516
 
517
	case AML_TO_INTEGER_OP:	/* to_integer (Data, Result) */
518
 
519
		status = acpi_ex_convert_to_integer(operand[0], &return_desc,
520
						    ACPI_ANY_BASE);
521
		if (return_desc == operand[0]) {
522
 
523
			/* No conversion performed, add ref to handle return value */
524
			acpi_ut_add_reference(return_desc);
525
		}
526
		break;
527
 
528
	case AML_SHIFT_LEFT_BIT_OP:	/* shift_left_bit (Source, bit_num) */
529
	case AML_SHIFT_RIGHT_BIT_OP:	/* shift_right_bit (Source, bit_num) */
530
 
531
		/* These are two obsolete opcodes */
532
 
533
		ACPI_ERROR((AE_INFO,
534
			    "%s is obsolete and not implemented",
535
			    acpi_ps_get_opcode_name(walk_state->opcode)));
536
		status = AE_SUPPORT;
537
		goto cleanup;
538
 
539
	default:		/* Unknown opcode */
540
 
541
		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
542
			    walk_state->opcode));
543
		status = AE_AML_BAD_OPCODE;
544
		goto cleanup;
545
	}
546
 
547
	if (ACPI_SUCCESS(status)) {
548
 
549
		/* Store the return value computed above into the target object */
550
 
551
		status = acpi_ex_store(return_desc, operand[1], walk_state);
552
	}
553
 
554
cleanup:
555
 
556
	/* Delete return object on error */
557
 
558
	if (ACPI_FAILURE(status)) {
559
		acpi_ut_remove_reference(return_desc);
560
	}
561
 
562
	/* Save return object on success */
563
 
564
	else if (!walk_state->result_obj) {
565
		walk_state->result_obj = return_desc;
566
	}
567
 
568
	return_ACPI_STATUS(status);
569
}
570
 
571
/*******************************************************************************
572
 *
573
 * FUNCTION:    acpi_ex_opcode_1A_0T_1R
574
 *
575
 * PARAMETERS:  walk_state          - Current state (contains AML opcode)
576
 *
577
 * RETURN:      Status
578
 *
579
 * DESCRIPTION: Execute opcode with one argument, no target, and a return value
580
 *
581
 ******************************************************************************/
582
 
583
acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
584
{
585
	union acpi_operand_object **operand = &walk_state->operands[0];
586
	union acpi_operand_object *temp_desc;
587
	union acpi_operand_object *return_desc = NULL;
588
	acpi_status status = AE_OK;
589
	u32 type;
590
	u64 value;
591
 
592
	ACPI_FUNCTION_TRACE_STR(ex_opcode_1A_0T_1R,
593
				acpi_ps_get_opcode_name(walk_state->opcode));
594
 
595
	/* Examine the AML opcode */
596
 
597
	switch (walk_state->opcode) {
598
	case AML_LNOT_OP:	/* LNot (Operand) */
599
 
600
		return_desc = acpi_ut_create_integer_object((u64) 0);
601
		if (!return_desc) {
602
			status = AE_NO_MEMORY;
603
			goto cleanup;
604
		}
605
 
606
		/*
607
		 * Set result to ONES (TRUE) if Value == 0. Note:
608
		 * return_desc->Integer.Value is initially == 0 (FALSE) from above.
609
		 */
610
		if (!operand[0]->integer.value) {
611
			return_desc->integer.value = ACPI_UINT64_MAX;
612
		}
613
		break;
614
 
615
	case AML_DECREMENT_OP:	/* Decrement (Operand)  */
616
	case AML_INCREMENT_OP:	/* Increment (Operand)  */
617
		/*
618
		 * Create a new integer. Can't just get the base integer and
619
		 * increment it because it may be an Arg or Field.
620
		 */
621
		return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
622
		if (!return_desc) {
623
			status = AE_NO_MEMORY;
624
			goto cleanup;
625
		}
626
 
627
		/*
628
		 * Since we are expecting a Reference operand, it can be either a
629
		 * NS Node or an internal object.
630
		 */
631
		temp_desc = operand[0];
632
		if (ACPI_GET_DESCRIPTOR_TYPE(temp_desc) ==
633
		    ACPI_DESC_TYPE_OPERAND) {
634
 
635
			/* Internal reference object - prevent deletion */
636
 
637
			acpi_ut_add_reference(temp_desc);
638
		}
639
 
640
		/*
641
		 * Convert the Reference operand to an Integer (This removes a
642
		 * reference on the Operand[0] object)
643
		 *
644
		 * NOTE:  We use LNOT_OP here in order to force resolution of the
645
		 * reference operand to an actual integer.
646
		 */
647
		status =
648
		    acpi_ex_resolve_operands(AML_LNOT_OP, &temp_desc,
649
					     walk_state);
650
		if (ACPI_FAILURE(status)) {
651
			ACPI_EXCEPTION((AE_INFO, status,
652
					"While resolving operands for [%s]",
653
					acpi_ps_get_opcode_name(walk_state->
654
								opcode)));
655
 
656
			goto cleanup;
657
		}
658
 
659
		/*
660
		 * temp_desc is now guaranteed to be an Integer object --
661
		 * Perform the actual increment or decrement
662
		 */
663
		if (walk_state->opcode == AML_INCREMENT_OP) {
664
			return_desc->integer.value =
665
			    temp_desc->integer.value + 1;
666
		} else {
667
			return_desc->integer.value =
668
			    temp_desc->integer.value - 1;
669
		}
670
 
671
		/* Finished with this Integer object */
672
 
673
		acpi_ut_remove_reference(temp_desc);
674
 
675
		/*
676
		 * Store the result back (indirectly) through the original
677
		 * Reference object
678
		 */
679
		status = acpi_ex_store(return_desc, operand[0], walk_state);
680
		break;
681
 
682
	case AML_TYPE_OP:	/* object_type (source_object) */
683
		/*
684
		 * Note: The operand is not resolved at this point because we want to
685
		 * get the associated object, not its value. For example, we don't
686
		 * want to resolve a field_unit to its value, we want the actual
687
		 * field_unit object.
688
		 */
689
 
690
		/* Get the type of the base object */
691
 
692
		status =
693
		    acpi_ex_resolve_multiple(walk_state, operand[0], &type,
694
					     NULL);
695
		if (ACPI_FAILURE(status)) {
696
			goto cleanup;
697
		}
698
 
699
		/* Allocate a descriptor to hold the type. */
700
 
701
		return_desc = acpi_ut_create_integer_object((u64) type);
702
		if (!return_desc) {
703
			status = AE_NO_MEMORY;
704
			goto cleanup;
705
		}
706
		break;
707
 
708
	case AML_SIZE_OF_OP:	/* size_of (source_object) */
709
		/*
710
		 * Note: The operand is not resolved at this point because we want to
711
		 * get the associated object, not its value.
712
		 */
713
 
714
		/* Get the base object */
715
 
716
		status = acpi_ex_resolve_multiple(walk_state,
717
						  operand[0], &type,
718
						  &temp_desc);
719
		if (ACPI_FAILURE(status)) {
720
			goto cleanup;
721
		}
722
 
723
		/*
724
		 * The type of the base object must be integer, buffer, string, or
725
		 * package. All others are not supported.
726
		 *
727
		 * NOTE: Integer is not specifically supported by the ACPI spec,
728
		 * but is supported implicitly via implicit operand conversion.
729
		 * rather than bother with conversion, we just use the byte width
730
		 * global (4 or 8 bytes).
731
		 */
732
		switch (type) {
733
		case ACPI_TYPE_INTEGER:
734
 
735
			value = acpi_gbl_integer_byte_width;
736
			break;
737
 
738
		case ACPI_TYPE_STRING:
739
 
740
			value = temp_desc->string.length;
741
			break;
742
 
743
		case ACPI_TYPE_BUFFER:
744
 
745
			/* Buffer arguments may not be evaluated at this point */
746
 
747
			status = acpi_ds_get_buffer_arguments(temp_desc);
748
			value = temp_desc->buffer.length;
749
			break;
750
 
751
		case ACPI_TYPE_PACKAGE:
752
 
753
			/* Package arguments may not be evaluated at this point */
754
 
755
			status = acpi_ds_get_package_arguments(temp_desc);
756
			value = temp_desc->package.count;
757
			break;
758
 
759
		default:
760
 
761
			ACPI_ERROR((AE_INFO,
762
				    "Operand must be Buffer/Integer/String/Package - found type %s",
763
				    acpi_ut_get_type_name(type)));
764
			status = AE_AML_OPERAND_TYPE;
765
			goto cleanup;
766
		}
767
 
768
		if (ACPI_FAILURE(status)) {
769
			goto cleanup;
770
		}
771
 
772
		/*
773
		 * Now that we have the size of the object, create a result
774
		 * object to hold the value
775
		 */
776
		return_desc = acpi_ut_create_integer_object(value);
777
		if (!return_desc) {
778
			status = AE_NO_MEMORY;
779
			goto cleanup;
780
		}
781
		break;
782
 
783
	case AML_REF_OF_OP:	/* ref_of (source_object) */
784
 
785
		status =
786
		    acpi_ex_get_object_reference(operand[0], &return_desc,
787
						 walk_state);
788
		if (ACPI_FAILURE(status)) {
789
			goto cleanup;
790
		}
791
		break;
792
 
793
	case AML_DEREF_OF_OP:	/* deref_of (obj_reference | String) */
794
 
795
		/* Check for a method local or argument, or standalone String */
796
 
797
		if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==
798
		    ACPI_DESC_TYPE_NAMED) {
799
			temp_desc =
800
			    acpi_ns_get_attached_object((struct
801
							 acpi_namespace_node *)
802
							operand[0]);
803
			if (temp_desc
804
			    && ((temp_desc->common.type == ACPI_TYPE_STRING)
805
				|| (temp_desc->common.type ==
806
				    ACPI_TYPE_LOCAL_REFERENCE))) {
807
				operand[0] = temp_desc;
808
				acpi_ut_add_reference(temp_desc);
809
			} else {
810
				status = AE_AML_OPERAND_TYPE;
811
				goto cleanup;
812
			}
813
		} else {
814
			switch ((operand[0])->common.type) {
815
			case ACPI_TYPE_LOCAL_REFERENCE:
816
				/*
817
				 * This is a deref_of (local_x | arg_x)
818
				 *
819
				 * Must resolve/dereference the local/arg reference first
820
				 */
821
				switch (operand[0]->reference.class) {
822
				case ACPI_REFCLASS_LOCAL:
823
				case ACPI_REFCLASS_ARG:
824
 
825
					/* Set Operand[0] to the value of the local/arg */
826
 
827
					status =
828
					    acpi_ds_method_data_get_value
829
					    (operand[0]->reference.class,
830
					     operand[0]->reference.value,
831
					     walk_state, &temp_desc);
832
					if (ACPI_FAILURE(status)) {
833
						goto cleanup;
834
					}
835
 
836
					/*
837
					 * Delete our reference to the input object and
838
					 * point to the object just retrieved
839
					 */
840
					acpi_ut_remove_reference(operand[0]);
841
					operand[0] = temp_desc;
842
					break;
843
 
844
				case ACPI_REFCLASS_REFOF:
845
 
846
					/* Get the object to which the reference refers */
847
 
848
					temp_desc =
849
					    operand[0]->reference.object;
850
					acpi_ut_remove_reference(operand[0]);
851
					operand[0] = temp_desc;
852
					break;
853
 
854
				default:
855
 
856
					/* Must be an Index op - handled below */
857
					break;
858
				}
859
				break;
860
 
861
			case ACPI_TYPE_STRING:
862
 
863
				break;
864
 
865
			default:
866
 
867
				status = AE_AML_OPERAND_TYPE;
868
				goto cleanup;
869
			}
870
		}
871
 
872
		if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) !=
873
		    ACPI_DESC_TYPE_NAMED) {
874
			if ((operand[0])->common.type == ACPI_TYPE_STRING) {
875
				/*
876
				 * This is a deref_of (String). The string is a reference
877
				 * to a named ACPI object.
878
				 *
879
				 * 1) Find the owning Node
880
				 * 2) Dereference the node to an actual object. Could be a
881
				 *    Field, so we need to resolve the node to a value.
882
				 */
883
				status =
884
				    acpi_ns_get_node(walk_state->scope_info->
885
						     scope.node,
886
						     operand[0]->string.pointer,
887
						     ACPI_NS_SEARCH_PARENT,
888
						     ACPI_CAST_INDIRECT_PTR
889
						     (struct
890
						      acpi_namespace_node,
891
						      &return_desc));
892
				if (ACPI_FAILURE(status)) {
893
					goto cleanup;
894
				}
895
 
896
				status =
897
				    acpi_ex_resolve_node_to_value
898
				    (ACPI_CAST_INDIRECT_PTR
899
				     (struct acpi_namespace_node, &return_desc),
900
				     walk_state);
901
				goto cleanup;
902
			}
903
		}
904
 
905
		/* Operand[0] may have changed from the code above */
906
 
907
		if (ACPI_GET_DESCRIPTOR_TYPE(operand[0]) ==
908
		    ACPI_DESC_TYPE_NAMED) {
909
			/*
910
			 * This is a deref_of (object_reference)
911
			 * Get the actual object from the Node (This is the dereference).
912
			 * This case may only happen when a local_x or arg_x is
913
			 * dereferenced above.
914
			 */
915
			return_desc = acpi_ns_get_attached_object((struct
916
								   acpi_namespace_node
917
								   *)
918
								  operand[0]);
919
			acpi_ut_add_reference(return_desc);
920
		} else {
921
			/*
922
			 * This must be a reference object produced by either the
923
			 * Index() or ref_of() operator
924
			 */
925
			switch (operand[0]->reference.class) {
926
			case ACPI_REFCLASS_INDEX:
927
				/*
928
				 * The target type for the Index operator must be
929
				 * either a Buffer or a Package
930
				 */
931
				switch (operand[0]->reference.target_type) {
932
				case ACPI_TYPE_BUFFER_FIELD:
933
 
934
					temp_desc =
935
					    operand[0]->reference.object;
936
 
937
					/*
938
					 * Create a new object that contains one element of the
939
					 * buffer -- the element pointed to by the index.
940
					 *
941
					 * NOTE: index into a buffer is NOT a pointer to a
942
					 * sub-buffer of the main buffer, it is only a pointer to a
943
					 * single element (byte) of the buffer!
944
					 *
945
					 * Since we are returning the value of the buffer at the
946
					 * indexed location, we don't need to add an additional
947
					 * reference to the buffer itself.
948
					 */
949
					return_desc =
950
					    acpi_ut_create_integer_object((u64)
951
									  temp_desc->buffer.pointer[operand[0]->reference.value]);
952
					if (!return_desc) {
953
						status = AE_NO_MEMORY;
954
						goto cleanup;
955
					}
956
					break;
957
 
958
				case ACPI_TYPE_PACKAGE:
959
					/*
960
					 * Return the referenced element of the package. We must
961
					 * add another reference to the referenced object, however.
962
					 */
963
					return_desc =
964
					    *(operand[0]->reference.where);
965
					if (!return_desc) {
966
						/*
967
						 * Element is NULL, do not allow the dereference.
968
						 * This provides compatibility with other ACPI
969
						 * implementations.
970
						 */
971
						return_ACPI_STATUS
972
						    (AE_AML_UNINITIALIZED_ELEMENT);
973
					}
974
 
975
					acpi_ut_add_reference(return_desc);
976
					break;
977
 
978
				default:
979
 
980
					ACPI_ERROR((AE_INFO,
981
						    "Unknown Index TargetType 0x%X in reference object %p",
982
						    operand[0]->reference.
983
						    target_type, operand[0]));
984
					status = AE_AML_OPERAND_TYPE;
985
					goto cleanup;
986
				}
987
				break;
988
 
989
			case ACPI_REFCLASS_REFOF:
990
 
991
				return_desc = operand[0]->reference.object;
992
 
993
				if (ACPI_GET_DESCRIPTOR_TYPE(return_desc) ==
994
				    ACPI_DESC_TYPE_NAMED) {
995
					return_desc =
996
					    acpi_ns_get_attached_object((struct
997
									 acpi_namespace_node
998
									 *)
999
									return_desc);
1000
					if (!return_desc) {
1001
						break;
1002
					}
1003
 
1004
					/*
1005
					 * June 2013:
1006
					 * buffer_fields/field_units require additional resolution
1007
					 */
1008
					switch (return_desc->common.type) {
1009
					case ACPI_TYPE_BUFFER_FIELD:
1010
					case ACPI_TYPE_LOCAL_REGION_FIELD:
1011
					case ACPI_TYPE_LOCAL_BANK_FIELD:
1012
					case ACPI_TYPE_LOCAL_INDEX_FIELD:
1013
 
1014
						status =
1015
						    acpi_ex_read_data_from_field
1016
						    (walk_state, return_desc,
1017
						     &temp_desc);
1018
						if (ACPI_FAILURE(status)) {
1019
							goto cleanup;
1020
						}
1021
 
1022
						return_desc = temp_desc;
1023
						break;
1024
 
1025
					default:
1026
 
1027
						/* Add another reference to the object */
1028
 
1029
						acpi_ut_add_reference
1030
						    (return_desc);
1031
						break;
1032
					}
1033
				}
1034
				break;
1035
 
1036
			default:
1037
 
1038
				ACPI_ERROR((AE_INFO,
1039
					    "Unknown class in reference(%p) - 0x%2.2X",
1040
					    operand[0],
1041
					    operand[0]->reference.class));
1042
 
1043
				status = AE_TYPE;
1044
				goto cleanup;
1045
			}
1046
		}
1047
		break;
1048
 
1049
	default:
1050
 
1051
		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
1052
			    walk_state->opcode));
1053
		status = AE_AML_BAD_OPCODE;
1054
		goto cleanup;
1055
	}
1056
 
1057
cleanup:
1058
 
1059
	/* Delete return object on error */
1060
 
1061
	if (ACPI_FAILURE(status)) {
1062
		acpi_ut_remove_reference(return_desc);
1063
	}
1064
 
1065
	/* Save return object on success */
1066
 
1067
	else {
1068
		walk_state->result_obj = return_desc;
1069
	}
1070
 
1071
	return_ACPI_STATUS(status);
1072
}