exstore.c 14.9 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7
/******************************************************************************
 *
 * Module Name: exstore - AML Interpreter object store support
 *
 *****************************************************************************/

/*
8
 * Copyright (C) 2000 - 2012, Intel Corp.
L
Linus Torvalds 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */

#include <acpi/acpi.h>
L
Len Brown 已提交
45 46 47 48 49
#include "accommon.h"
#include "acdispat.h"
#include "acinterp.h"
#include "amlcode.h"
#include "acnamesp.h"
L
Linus Torvalds 已提交
50 51

#define _COMPONENT          ACPI_EXECUTER
L
Len Brown 已提交
52
ACPI_MODULE_NAME("exstore")
L
Linus Torvalds 已提交
53

R
Robert Moore 已提交
54 55
/* Local prototypes */
static acpi_status
L
Len Brown 已提交
56 57 58
acpi_ex_store_object_to_index(union acpi_operand_object *val_desc,
			      union acpi_operand_object *dest_desc,
			      struct acpi_walk_state *walk_state);
R
Robert Moore 已提交
59

L
Linus Torvalds 已提交
60 61 62 63 64 65
/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_store
 *
 * PARAMETERS:  *source_desc        - Value to be stored
 *              *dest_desc          - Where to store it.  Must be an NS node
66
 *                                    or a union acpi_operand_object of type
L
Linus Torvalds 已提交
67 68 69 70 71 72 73 74 75 76 77 78 79 80
 *                                    Reference;
 *              walk_state          - Current walk state
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Store the value described by source_desc into the location
 *              described by dest_desc. Called by various interpreter
 *              functions to store the result of an operation into
 *              the destination operand -- not just simply the actual "Store"
 *              ASL operator.
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
81 82 83
acpi_ex_store(union acpi_operand_object *source_desc,
	      union acpi_operand_object *dest_desc,
	      struct acpi_walk_state *walk_state)
L
Linus Torvalds 已提交
84
{
L
Len Brown 已提交
85 86
	acpi_status status = AE_OK;
	union acpi_operand_object *ref_desc = dest_desc;
L
Linus Torvalds 已提交
87

B
Bob Moore 已提交
88
	ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc);
L
Linus Torvalds 已提交
89 90 91 92

	/* Validate parameters */

	if (!source_desc || !dest_desc) {
B
Bob Moore 已提交
93
		ACPI_ERROR((AE_INFO, "Null parameter"));
L
Len Brown 已提交
94
		return_ACPI_STATUS(AE_AML_NO_OPERAND);
L
Linus Torvalds 已提交
95 96 97 98
	}

	/* dest_desc can be either a namespace node or an ACPI object */

L
Len Brown 已提交
99
	if (ACPI_GET_DESCRIPTOR_TYPE(dest_desc) == ACPI_DESC_TYPE_NAMED) {
L
Linus Torvalds 已提交
100 101 102 103
		/*
		 * Dest is a namespace node,
		 * Storing an object into a Named node.
		 */
L
Len Brown 已提交
104 105 106 107 108
		status = acpi_ex_store_object_to_node(source_desc,
						      (struct
						       acpi_namespace_node *)
						      dest_desc, walk_state,
						      ACPI_IMPLICIT_CONVERSION);
L
Linus Torvalds 已提交
109

L
Len Brown 已提交
110
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
111 112 113 114
	}

	/* Destination object must be a Reference or a Constant object */

115
	switch (dest_desc->common.type) {
L
Linus Torvalds 已提交
116 117 118 119 120 121 122 123
	case ACPI_TYPE_LOCAL_REFERENCE:
		break;

	case ACPI_TYPE_INTEGER:

		/* Allow stores to Constants -- a Noop as per ACPI spec */

		if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) {
L
Len Brown 已提交
124
			return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
125 126 127 128 129 130 131 132
		}

		/*lint -fallthrough */

	default:

		/* Destination is not a Reference object */

B
Bob Moore 已提交
133 134 135 136
		ACPI_ERROR((AE_INFO,
			    "Target is not a Reference or Constant object - %s [%p]",
			    acpi_ut_get_object_type_name(dest_desc),
			    dest_desc));
L
Linus Torvalds 已提交
137

L
Len Brown 已提交
138
		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
L
Linus Torvalds 已提交
139 140 141
	}

	/*
142
	 * Examine the Reference class. These cases are handled:
L
Linus Torvalds 已提交
143 144 145 146 147 148
	 *
	 * 1) Store to Name (Change the object associated with a name)
	 * 2) Store to an indexed area of a Buffer or Package
	 * 3) Store to a Method Local or Arg
	 * 4) Store to the debug object
	 */
149 150
	switch (ref_desc->reference.class) {
	case ACPI_REFCLASS_REFOF:
L
Linus Torvalds 已提交
151 152 153

		/* Storing an object into a Name "container" */

L
Len Brown 已提交
154 155 156 157
		status = acpi_ex_store_object_to_node(source_desc,
						      ref_desc->reference.
						      object, walk_state,
						      ACPI_IMPLICIT_CONVERSION);
L
Linus Torvalds 已提交
158 159
		break;

160
	case ACPI_REFCLASS_INDEX:
L
Linus Torvalds 已提交
161 162 163

		/* Storing to an Index (pointer into a packager or buffer) */

L
Len Brown 已提交
164 165 166
		status =
		    acpi_ex_store_object_to_index(source_desc, ref_desc,
						  walk_state);
L
Linus Torvalds 已提交
167 168
		break;

169 170
	case ACPI_REFCLASS_LOCAL:
	case ACPI_REFCLASS_ARG:
L
Linus Torvalds 已提交
171 172 173

		/* Store to a method local/arg  */

L
Len Brown 已提交
174
		status =
175 176
		    acpi_ds_store_object_to_local(ref_desc->reference.class,
						  ref_desc->reference.value,
L
Len Brown 已提交
177
						  source_desc, walk_state);
L
Linus Torvalds 已提交
178 179
		break;

180
	case ACPI_REFCLASS_DEBUG:
L
Linus Torvalds 已提交
181 182 183 184 185

		/*
		 * Storing to the Debug object causes the value stored to be
		 * displayed and otherwise has no effect -- see ACPI Specification
		 */
L
Len Brown 已提交
186 187 188 189
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
				  "**** Write to Debug Object: Object %p %s ****:\n\n",
				  source_desc,
				  acpi_ut_get_object_type_name(source_desc)));
L
Linus Torvalds 已提交
190

191
		ACPI_DEBUG_OBJECT(source_desc, 0, 0);
L
Linus Torvalds 已提交
192 193 194 195
		break;

	default:

196
		ACPI_ERROR((AE_INFO, "Unknown Reference Class 0x%2.2X",
197
			    ref_desc->reference.class));
198
		ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO);
L
Linus Torvalds 已提交
199 200 201 202 203

		status = AE_AML_INTERNAL;
		break;
	}

L
Len Brown 已提交
204
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_store_object_to_index
 *
 * PARAMETERS:  *source_desc            - Value to be stored
 *              *dest_desc              - Named object to receive the value
 *              walk_state              - Current walk state
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Store the object to indexed Buffer or Package element
 *
 ******************************************************************************/

R
Robert Moore 已提交
221
static acpi_status
L
Len Brown 已提交
222 223 224
acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
			      union acpi_operand_object *index_desc,
			      struct acpi_walk_state *walk_state)
L
Linus Torvalds 已提交
225
{
L
Len Brown 已提交
226 227 228 229 230
	acpi_status status = AE_OK;
	union acpi_operand_object *obj_desc;
	union acpi_operand_object *new_desc;
	u8 value = 0;
	u32 i;
L
Linus Torvalds 已提交
231

B
Bob Moore 已提交
232
	ACPI_FUNCTION_TRACE(ex_store_object_to_index);
L
Linus Torvalds 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250

	/*
	 * Destination must be a reference pointer, and
	 * must point to either a buffer or a package
	 */
	switch (index_desc->reference.target_type) {
	case ACPI_TYPE_PACKAGE:
		/*
		 * Storing to a package element. Copy the object and replace
		 * any existing object with the new object. No implicit
		 * conversion is performed.
		 *
		 * The object at *(index_desc->Reference.Where) is the
		 * element within the package that is to be modified.
		 * The parent package object is at index_desc->Reference.Object
		 */
		obj_desc = *(index_desc->reference.where);

251 252
		if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE &&
		    source_desc->reference.class == ACPI_REFCLASS_TABLE) {
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267

			/* This is a DDBHandle, just add a reference to it */

			acpi_ut_add_reference(source_desc);
			new_desc = source_desc;
		} else {
			/* Normal object, copy it */

			status =
			    acpi_ut_copy_iobject_to_iobject(source_desc,
							    &new_desc,
							    walk_state);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
			}
L
Linus Torvalds 已提交
268 269 270
		}

		if (obj_desc) {
B
Bob Moore 已提交
271

L
Linus Torvalds 已提交
272 273
			/* Decrement reference count by the ref count of the parent package */

L
Len Brown 已提交
274 275 276 277
			for (i = 0; i < ((union acpi_operand_object *)
					 index_desc->reference.object)->common.
			     reference_count; i++) {
				acpi_ut_remove_reference(obj_desc);
L
Linus Torvalds 已提交
278 279 280 281 282
			}
		}

		*(index_desc->reference.where) = new_desc;

R
Robert Moore 已提交
283
		/* Increment ref count by the ref count of the parent package-1 */
L
Linus Torvalds 已提交
284

L
Len Brown 已提交
285 286 287 288
		for (i = 1; i < ((union acpi_operand_object *)
				 index_desc->reference.object)->common.
		     reference_count; i++) {
			acpi_ut_add_reference(new_desc);
L
Linus Torvalds 已提交
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
		}

		break;

	case ACPI_TYPE_BUFFER_FIELD:

		/*
		 * Store into a Buffer or String (not actually a real buffer_field)
		 * at a location defined by an Index.
		 *
		 * The first 8-bit element of the source object is written to the
		 * 8-bit Buffer location defined by the Index destination object,
		 * according to the ACPI 2.0 specification.
		 */

		/*
		 * Make sure the target is a Buffer or String. An error should
		 * not happen here, since the reference_object was constructed
		 * by the INDEX_OP code.
		 */
		obj_desc = index_desc->reference.object;
310 311
		if ((obj_desc->common.type != ACPI_TYPE_BUFFER) &&
		    (obj_desc->common.type != ACPI_TYPE_STRING)) {
L
Len Brown 已提交
312
			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
L
Linus Torvalds 已提交
313 314 315 316 317 318
		}

		/*
		 * The assignment of the individual elements will be slightly
		 * different for each source type.
		 */
319
		switch (source_desc->common.type) {
L
Linus Torvalds 已提交
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
		case ACPI_TYPE_INTEGER:

			/* Use the least-significant byte of the integer */

			value = (u8) (source_desc->integer.value);
			break;

		case ACPI_TYPE_BUFFER:
		case ACPI_TYPE_STRING:

			/* Note: Takes advantage of common string/buffer fields */

			value = source_desc->buffer.pointer[0];
			break;

		default:

			/* All other types are invalid */

B
Bob Moore 已提交
339 340 341
			ACPI_ERROR((AE_INFO,
				    "Source must be Integer/Buffer/String type, not %s",
				    acpi_ut_get_object_type_name(source_desc)));
L
Len Brown 已提交
342
			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
L
Linus Torvalds 已提交
343 344 345 346
		}

		/* Store the source value into the target buffer byte */

347
		obj_desc->buffer.pointer[index_desc->reference.value] = value;
L
Linus Torvalds 已提交
348 349 350
		break;

	default:
B
Bob Moore 已提交
351
		ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField"));
L
Linus Torvalds 已提交
352 353 354 355
		status = AE_AML_OPERAND_TYPE;
		break;
	}

L
Len Brown 已提交
356
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_store_object_to_node
 *
 * PARAMETERS:  source_desc             - Value to be stored
 *              Node                    - Named object to receive the value
 *              walk_state              - Current walk state
 *              implicit_conversion     - Perform implicit conversion (yes/no)
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Store the object to the named object.
 *
 *              The Assignment of an object to a named object is handled here
 *              The value passed in will replace the current value (if any)
 *              with the input value.
 *
 *              When storing into an object the data is converted to the
 *              target object type then stored in the object.  This means
 *              that the target object type (for an initialized target) will
 *              not be changed by a store operation.
 *
 *              Assumes parameters are already validated.
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
386 387 388 389
acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
			     struct acpi_namespace_node *node,
			     struct acpi_walk_state *walk_state,
			     u8 implicit_conversion)
L
Linus Torvalds 已提交
390
{
L
Len Brown 已提交
391 392 393 394
	acpi_status status = AE_OK;
	union acpi_operand_object *target_desc;
	union acpi_operand_object *new_desc;
	acpi_object_type target_type;
L
Linus Torvalds 已提交
395

B
Bob Moore 已提交
396
	ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc);
L
Linus Torvalds 已提交
397

R
Robert Moore 已提交
398 399
	/* Get current type of the node, and object attached to Node */

L
Len Brown 已提交
400 401
	target_type = acpi_ns_get_type(node);
	target_desc = acpi_ns_get_attached_object(node);
L
Linus Torvalds 已提交
402

L
Len Brown 已提交
403 404 405 406
	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n",
			  source_desc,
			  acpi_ut_get_object_type_name(source_desc), node,
			  acpi_ut_get_type_name(target_type)));
L
Linus Torvalds 已提交
407 408 409 410 411

	/*
	 * Resolve the source object to an actual value
	 * (If it is a reference object)
	 */
L
Len Brown 已提交
412 413 414
	status = acpi_ex_resolve_object(&source_desc, target_type, walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
415 416 417 418
	}

	/* If no implicit conversion, drop into the default case below */

419 420 421 422 423 424 425 426 427 428 429
	if ((!implicit_conversion) ||
	    ((walk_state->opcode == AML_COPY_OP) &&
	     (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) &&
	     (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) &&
	     (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) {
		/*
		 * Force execution of default (no implicit conversion). Note:
		 * copy_object does not perform an implicit conversion, as per the ACPI
		 * spec -- except in case of region/bank/index fields -- because these
		 * objects must retain their original type permanently.
		 */
L
Linus Torvalds 已提交
430 431 432
		target_type = ACPI_TYPE_ANY;
	}

R
Robert Moore 已提交
433 434
	/* Do the actual store operation */

L
Linus Torvalds 已提交
435 436 437 438 439 440
	switch (target_type) {
	case ACPI_TYPE_BUFFER_FIELD:
	case ACPI_TYPE_LOCAL_REGION_FIELD:
	case ACPI_TYPE_LOCAL_BANK_FIELD:
	case ACPI_TYPE_LOCAL_INDEX_FIELD:

R
Robert Moore 已提交
441 442
		/* For fields, copy the source data to the target field. */

L
Len Brown 已提交
443 444
		status = acpi_ex_write_data_to_field(source_desc, target_desc,
						     &walk_state->result_obj);
L
Linus Torvalds 已提交
445 446 447 448 449 450 451 452 453 454 455 456
		break;

	case ACPI_TYPE_INTEGER:
	case ACPI_TYPE_STRING:
	case ACPI_TYPE_BUFFER:

		/*
		 * These target types are all of type Integer/String/Buffer, and
		 * therefore support implicit conversion before the store.
		 *
		 * Copy and/or convert the source object to a new target object
		 */
L
Len Brown 已提交
457 458 459 460 461
		status =
		    acpi_ex_store_object_to_object(source_desc, target_desc,
						   &new_desc, walk_state);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
462 463 464 465 466 467 468 469 470 471 472 473
		}

		if (new_desc != target_desc) {
			/*
			 * Store the new new_desc as the new value of the Name, and set
			 * the Name's type to that of the value being stored in it.
			 * source_desc reference count is incremented by attach_object.
			 *
			 * Note: This may change the type of the node if an explicit store
			 * has been performed such that the node/object type has been
			 * changed.
			 */
L
Len Brown 已提交
474 475 476 477 478 479 480 481 482 483
			status =
			    acpi_ns_attach_object(node, new_desc,
						  new_desc->common.type);

			ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
					  "Store %s into %s via Convert/Attach\n",
					  acpi_ut_get_object_type_name
					  (source_desc),
					  acpi_ut_get_object_type_name
					  (new_desc)));
L
Linus Torvalds 已提交
484 485 486 487 488
		}
		break;

	default:

L
Len Brown 已提交
489 490 491 492
		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
				  "Storing %s (%p) directly into node (%p) with no implicit conversion\n",
				  acpi_ut_get_object_type_name(source_desc),
				  source_desc, node));
L
Linus Torvalds 已提交
493 494 495

		/* No conversions for all other types.  Just attach the source object */

L
Len Brown 已提交
496
		status = acpi_ns_attach_object(node, source_desc,
497
					       source_desc->common.type);
L
Linus Torvalds 已提交
498 499 500
		break;
	}

L
Len Brown 已提交
501
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
502
}