xref: /openbmc/linux/drivers/acpi/acpica/utcopy.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Module Name: utcopy - Internal to external object translation utilities
595b482a8SLen Brown  *
6*612c2932SBob Moore  * Copyright (C) 2000 - 2023, Intel Corp.
795b482a8SLen Brown  *
895857638SErik Schmauss  *****************************************************************************/
995b482a8SLen Brown 
1095b482a8SLen Brown #include <acpi/acpi.h>
11e2f7a777SLen Brown #include "accommon.h"
12e2f7a777SLen Brown #include "acnamesp.h"
1395b482a8SLen Brown 
1495b482a8SLen Brown 
1595b482a8SLen Brown #define _COMPONENT          ACPI_UTILITIES
1695b482a8SLen Brown ACPI_MODULE_NAME("utcopy")
1795b482a8SLen Brown 
1895b482a8SLen Brown /* Local prototypes */
1995b482a8SLen Brown static acpi_status
2095b482a8SLen Brown acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
2195b482a8SLen Brown 				union acpi_object *external_object,
2295b482a8SLen Brown 				u8 *data_space, acpi_size *buffer_space_used);
2395b482a8SLen Brown 
2495b482a8SLen Brown static acpi_status
2595b482a8SLen Brown acpi_ut_copy_ielement_to_ielement(u8 object_type,
2695b482a8SLen Brown 				  union acpi_operand_object *source_object,
2795b482a8SLen Brown 				  union acpi_generic_state *state,
2895b482a8SLen Brown 				  void *context);
2995b482a8SLen Brown 
3095b482a8SLen Brown static acpi_status
3195b482a8SLen Brown acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
3295b482a8SLen Brown 				  u8 *buffer, acpi_size *space_used);
3395b482a8SLen Brown 
3495b482a8SLen Brown static acpi_status
3595b482a8SLen Brown acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj,
3695b482a8SLen Brown 				union acpi_operand_object **return_obj);
3795b482a8SLen Brown 
3895b482a8SLen Brown static acpi_status
3995b482a8SLen Brown acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
4095b482a8SLen Brown 				  union acpi_operand_object **internal_object);
4195b482a8SLen Brown 
4295b482a8SLen Brown static acpi_status
4395b482a8SLen Brown acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
4495b482a8SLen Brown 			   union acpi_operand_object *dest_desc);
4595b482a8SLen Brown 
4695b482a8SLen Brown static acpi_status
4795b482a8SLen Brown acpi_ut_copy_ielement_to_eelement(u8 object_type,
4895b482a8SLen Brown 				  union acpi_operand_object *source_object,
4995b482a8SLen Brown 				  union acpi_generic_state *state,
5095b482a8SLen Brown 				  void *context);
5195b482a8SLen Brown 
5295b482a8SLen Brown static acpi_status
5395b482a8SLen Brown acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
5495b482a8SLen Brown 				  union acpi_operand_object *dest_obj,
5595b482a8SLen Brown 				  struct acpi_walk_state *walk_state);
5695b482a8SLen Brown 
5795b482a8SLen Brown /*******************************************************************************
5895b482a8SLen Brown  *
5995b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_isimple_to_esimple
6095b482a8SLen Brown  *
6195b482a8SLen Brown  * PARAMETERS:  internal_object     - Source object to be copied
6295b482a8SLen Brown  *              external_object     - Where to return the copied object
6395b482a8SLen Brown  *              data_space          - Where object data is returned (such as
6495b482a8SLen Brown  *                                    buffer and string data)
6595b482a8SLen Brown  *              buffer_space_used   - Length of data_space that was used
6695b482a8SLen Brown  *
6795b482a8SLen Brown  * RETURN:      Status
6895b482a8SLen Brown  *
6995b482a8SLen Brown  * DESCRIPTION: This function is called to copy a simple internal object to
7095b482a8SLen Brown  *              an external object.
7195b482a8SLen Brown  *
7295b482a8SLen Brown  *              The data_space buffer is assumed to have sufficient space for
7395b482a8SLen Brown  *              the object.
7495b482a8SLen Brown  *
7595b482a8SLen Brown  ******************************************************************************/
7695b482a8SLen Brown 
7795b482a8SLen Brown static acpi_status
acpi_ut_copy_isimple_to_esimple(union acpi_operand_object * internal_object,union acpi_object * external_object,u8 * data_space,acpi_size * buffer_space_used)7895b482a8SLen Brown acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
7995b482a8SLen Brown 				union acpi_object *external_object,
8095b482a8SLen Brown 				u8 *data_space, acpi_size *buffer_space_used)
8195b482a8SLen Brown {
8295b482a8SLen Brown 	acpi_status status = AE_OK;
8395b482a8SLen Brown 
8495b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_copy_isimple_to_esimple);
8595b482a8SLen Brown 
8695b482a8SLen Brown 	*buffer_space_used = 0;
8795b482a8SLen Brown 
8895b482a8SLen Brown 	/*
8995b482a8SLen Brown 	 * Check for NULL object case (could be an uninitialized
9095b482a8SLen Brown 	 * package element)
9195b482a8SLen Brown 	 */
9295b482a8SLen Brown 	if (!internal_object) {
9395b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
9495b482a8SLen Brown 	}
9595b482a8SLen Brown 
9695b482a8SLen Brown 	/* Always clear the external object */
9795b482a8SLen Brown 
984fa4616eSBob Moore 	memset(external_object, 0, sizeof(union acpi_object));
9995b482a8SLen Brown 
10095b482a8SLen Brown 	/*
10195b482a8SLen Brown 	 * In general, the external object will be the same type as
10295b482a8SLen Brown 	 * the internal object
10395b482a8SLen Brown 	 */
1043371c19cSBob Moore 	external_object->type = internal_object->common.type;
10595b482a8SLen Brown 
10695b482a8SLen Brown 	/* However, only a limited number of external types are supported */
10795b482a8SLen Brown 
1083371c19cSBob Moore 	switch (internal_object->common.type) {
10995b482a8SLen Brown 	case ACPI_TYPE_STRING:
11095b482a8SLen Brown 
11195b482a8SLen Brown 		external_object->string.pointer = (char *)data_space;
11295b482a8SLen Brown 		external_object->string.length = internal_object->string.length;
11395b482a8SLen Brown 		*buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
11495b482a8SLen Brown 								  internal_object->
11595b482a8SLen Brown 								  string.
11695b482a8SLen Brown 								  length + 1);
11795b482a8SLen Brown 
1184fa4616eSBob Moore 		memcpy((void *)data_space,
11995b482a8SLen Brown 		       (void *)internal_object->string.pointer,
12095b482a8SLen Brown 		       (acpi_size)internal_object->string.length + 1);
12195b482a8SLen Brown 		break;
12295b482a8SLen Brown 
12395b482a8SLen Brown 	case ACPI_TYPE_BUFFER:
12495b482a8SLen Brown 
12595b482a8SLen Brown 		external_object->buffer.pointer = data_space;
12695b482a8SLen Brown 		external_object->buffer.length = internal_object->buffer.length;
12795b482a8SLen Brown 		*buffer_space_used =
12895b482a8SLen Brown 		    ACPI_ROUND_UP_TO_NATIVE_WORD(internal_object->string.
12995b482a8SLen Brown 						 length);
13095b482a8SLen Brown 
1314fa4616eSBob Moore 		memcpy((void *)data_space,
13295b482a8SLen Brown 		       (void *)internal_object->buffer.pointer,
13395b482a8SLen Brown 		       internal_object->buffer.length);
13495b482a8SLen Brown 		break;
13595b482a8SLen Brown 
13695b482a8SLen Brown 	case ACPI_TYPE_INTEGER:
13795b482a8SLen Brown 
13895b482a8SLen Brown 		external_object->integer.value = internal_object->integer.value;
13995b482a8SLen Brown 		break;
14095b482a8SLen Brown 
14195b482a8SLen Brown 	case ACPI_TYPE_LOCAL_REFERENCE:
14295b482a8SLen Brown 
14395b482a8SLen Brown 		/* This is an object reference. */
14495b482a8SLen Brown 
14595b482a8SLen Brown 		switch (internal_object->reference.class) {
14695b482a8SLen Brown 		case ACPI_REFCLASS_NAME:
14795b482a8SLen Brown 			/*
14895b482a8SLen Brown 			 * For namepath, return the object handle ("reference")
14995b482a8SLen Brown 			 * We are referring to the namespace node
15095b482a8SLen Brown 			 */
15195b482a8SLen Brown 			external_object->reference.handle =
15295b482a8SLen Brown 			    internal_object->reference.node;
15395b482a8SLen Brown 			external_object->reference.actual_type =
15495b482a8SLen Brown 			    acpi_ns_get_type(internal_object->reference.node);
15595b482a8SLen Brown 			break;
15695b482a8SLen Brown 
15795b482a8SLen Brown 		default:
15895b482a8SLen Brown 
15995b482a8SLen Brown 			/* All other reference types are unsupported */
16095b482a8SLen Brown 
16195b482a8SLen Brown 			return_ACPI_STATUS(AE_TYPE);
16295b482a8SLen Brown 		}
16395b482a8SLen Brown 		break;
16495b482a8SLen Brown 
16595b482a8SLen Brown 	case ACPI_TYPE_PROCESSOR:
16695b482a8SLen Brown 
16795b482a8SLen Brown 		external_object->processor.proc_id =
16895b482a8SLen Brown 		    internal_object->processor.proc_id;
16995b482a8SLen Brown 		external_object->processor.pblk_address =
17095b482a8SLen Brown 		    internal_object->processor.address;
17195b482a8SLen Brown 		external_object->processor.pblk_length =
17295b482a8SLen Brown 		    internal_object->processor.length;
17395b482a8SLen Brown 		break;
17495b482a8SLen Brown 
17595b482a8SLen Brown 	case ACPI_TYPE_POWER:
17695b482a8SLen Brown 
17795b482a8SLen Brown 		external_object->power_resource.system_level =
17895b482a8SLen Brown 		    internal_object->power_resource.system_level;
17995b482a8SLen Brown 
18095b482a8SLen Brown 		external_object->power_resource.resource_order =
18195b482a8SLen Brown 		    internal_object->power_resource.resource_order;
18295b482a8SLen Brown 		break;
18395b482a8SLen Brown 
18495b482a8SLen Brown 	default:
18595b482a8SLen Brown 		/*
18695b482a8SLen Brown 		 * There is no corresponding external object type
18795b482a8SLen Brown 		 */
18895b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
18995b482a8SLen Brown 			    "Unsupported object type, cannot convert to external object: %s",
1903371c19cSBob Moore 			    acpi_ut_get_type_name(internal_object->common.
1913371c19cSBob Moore 						  type)));
19295b482a8SLen Brown 
19395b482a8SLen Brown 		return_ACPI_STATUS(AE_SUPPORT);
19495b482a8SLen Brown 	}
19595b482a8SLen Brown 
19695b482a8SLen Brown 	return_ACPI_STATUS(status);
19795b482a8SLen Brown }
19895b482a8SLen Brown 
19995b482a8SLen Brown /*******************************************************************************
20095b482a8SLen Brown  *
20195b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_ielement_to_eelement
20295b482a8SLen Brown  *
20395b482a8SLen Brown  * PARAMETERS:  acpi_pkg_callback
20495b482a8SLen Brown  *
20595b482a8SLen Brown  * RETURN:      Status
20695b482a8SLen Brown  *
20795b482a8SLen Brown  * DESCRIPTION: Copy one package element to another package element
20895b482a8SLen Brown  *
20995b482a8SLen Brown  ******************************************************************************/
21095b482a8SLen Brown 
21195b482a8SLen Brown static acpi_status
acpi_ut_copy_ielement_to_eelement(u8 object_type,union acpi_operand_object * source_object,union acpi_generic_state * state,void * context)21295b482a8SLen Brown acpi_ut_copy_ielement_to_eelement(u8 object_type,
21395b482a8SLen Brown 				  union acpi_operand_object *source_object,
21495b482a8SLen Brown 				  union acpi_generic_state *state,
21595b482a8SLen Brown 				  void *context)
21695b482a8SLen Brown {
21795b482a8SLen Brown 	acpi_status status = AE_OK;
21895b482a8SLen Brown 	struct acpi_pkg_info *info = (struct acpi_pkg_info *)context;
21995b482a8SLen Brown 	acpi_size object_space;
22095b482a8SLen Brown 	u32 this_index;
22195b482a8SLen Brown 	union acpi_object *target_object;
22295b482a8SLen Brown 
22395b482a8SLen Brown 	ACPI_FUNCTION_ENTRY();
22495b482a8SLen Brown 
22595b482a8SLen Brown 	this_index = state->pkg.index;
2261fad8738SBob Moore 	target_object = (union acpi_object *)&((union acpi_object *)
2271fad8738SBob Moore 					       (state->pkg.dest_object))->
2281fad8738SBob Moore 	    package.elements[this_index];
22995b482a8SLen Brown 
23095b482a8SLen Brown 	switch (object_type) {
23195b482a8SLen Brown 	case ACPI_COPY_TYPE_SIMPLE:
23295b482a8SLen Brown 		/*
23395b482a8SLen Brown 		 * This is a simple or null object
23495b482a8SLen Brown 		 */
23595b482a8SLen Brown 		status = acpi_ut_copy_isimple_to_esimple(source_object,
23695b482a8SLen Brown 							 target_object,
23795b482a8SLen Brown 							 info->free_space,
23895b482a8SLen Brown 							 &object_space);
23995b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
24095b482a8SLen Brown 			return (status);
24195b482a8SLen Brown 		}
24295b482a8SLen Brown 		break;
24395b482a8SLen Brown 
24495b482a8SLen Brown 	case ACPI_COPY_TYPE_PACKAGE:
24595b482a8SLen Brown 		/*
24695b482a8SLen Brown 		 * Build the package object
24795b482a8SLen Brown 		 */
24895b482a8SLen Brown 		target_object->type = ACPI_TYPE_PACKAGE;
24995b482a8SLen Brown 		target_object->package.count = source_object->package.count;
25095b482a8SLen Brown 		target_object->package.elements =
25195b482a8SLen Brown 		    ACPI_CAST_PTR(union acpi_object, info->free_space);
25295b482a8SLen Brown 
25395b482a8SLen Brown 		/*
25495b482a8SLen Brown 		 * Pass the new package object back to the package walk routine
25595b482a8SLen Brown 		 */
25695b482a8SLen Brown 		state->pkg.this_target_obj = target_object;
25795b482a8SLen Brown 
25895b482a8SLen Brown 		/*
25995b482a8SLen Brown 		 * Save space for the array of objects (Package elements)
26095b482a8SLen Brown 		 * update the buffer length counter
26195b482a8SLen Brown 		 */
26295b482a8SLen Brown 		object_space = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
26395b482a8SLen Brown 							    target_object->
26495b482a8SLen Brown 							    package.count *
26595b482a8SLen Brown 							    sizeof(union
26695b482a8SLen Brown 								   acpi_object));
26795b482a8SLen Brown 		break;
26895b482a8SLen Brown 
26995b482a8SLen Brown 	default:
2701d1ea1b7SChao Guan 
27195b482a8SLen Brown 		return (AE_BAD_PARAMETER);
27295b482a8SLen Brown 	}
27395b482a8SLen Brown 
27495b482a8SLen Brown 	info->free_space += object_space;
27595b482a8SLen Brown 	info->length += object_space;
27695b482a8SLen Brown 	return (status);
27795b482a8SLen Brown }
27895b482a8SLen Brown 
27995b482a8SLen Brown /*******************************************************************************
28095b482a8SLen Brown  *
28195b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_ipackage_to_epackage
28295b482a8SLen Brown  *
28395b482a8SLen Brown  * PARAMETERS:  internal_object     - Pointer to the object we are returning
284ba494beeSBob Moore  *              buffer              - Where the object is returned
28595b482a8SLen Brown  *              space_used          - Where the object length is returned
28695b482a8SLen Brown  *
28795b482a8SLen Brown  * RETURN:      Status
28895b482a8SLen Brown  *
28995b482a8SLen Brown  * DESCRIPTION: This function is called to place a package object in a user
29095b482a8SLen Brown  *              buffer. A package object by definition contains other objects.
29195b482a8SLen Brown  *
29295b482a8SLen Brown  *              The buffer is assumed to have sufficient space for the object.
29390434c1cSBob Moore  *              The caller must have verified the buffer length needed using
29490434c1cSBob Moore  *              the acpi_ut_get_object_size function before calling this function.
29595b482a8SLen Brown  *
29695b482a8SLen Brown  ******************************************************************************/
29795b482a8SLen Brown 
29895b482a8SLen Brown static acpi_status
acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object * internal_object,u8 * buffer,acpi_size * space_used)29995b482a8SLen Brown acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
30095b482a8SLen Brown 				  u8 *buffer, acpi_size *space_used)
30195b482a8SLen Brown {
30295b482a8SLen Brown 	union acpi_object *external_object;
30395b482a8SLen Brown 	acpi_status status;
30495b482a8SLen Brown 	struct acpi_pkg_info info;
30595b482a8SLen Brown 
30695b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_epackage);
30795b482a8SLen Brown 
30895b482a8SLen Brown 	/*
30995b482a8SLen Brown 	 * First package at head of the buffer
31095b482a8SLen Brown 	 */
31195b482a8SLen Brown 	external_object = ACPI_CAST_PTR(union acpi_object, buffer);
31295b482a8SLen Brown 
31395b482a8SLen Brown 	/*
31495b482a8SLen Brown 	 * Free space begins right after the first package
31595b482a8SLen Brown 	 */
31695b482a8SLen Brown 	info.length = ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
3171fad8738SBob Moore 	info.free_space = buffer +
3181fad8738SBob Moore 	    ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
31995b482a8SLen Brown 	info.object_space = 0;
32095b482a8SLen Brown 	info.num_packages = 1;
32195b482a8SLen Brown 
3223371c19cSBob Moore 	external_object->type = internal_object->common.type;
32395b482a8SLen Brown 	external_object->package.count = internal_object->package.count;
3241fad8738SBob Moore 	external_object->package.elements =
3251fad8738SBob Moore 	    ACPI_CAST_PTR(union acpi_object, info.free_space);
32695b482a8SLen Brown 
32795b482a8SLen Brown 	/*
32895b482a8SLen Brown 	 * Leave room for an array of ACPI_OBJECTS in the buffer
32995b482a8SLen Brown 	 * and move the free space past it
33095b482a8SLen Brown 	 */
33195b482a8SLen Brown 	info.length += (acpi_size)external_object->package.count *
33295b482a8SLen Brown 	    ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
33395b482a8SLen Brown 	info.free_space += external_object->package.count *
33495b482a8SLen Brown 	    ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
33595b482a8SLen Brown 
33695b482a8SLen Brown 	status = acpi_ut_walk_package_tree(internal_object, external_object,
33795b482a8SLen Brown 					   acpi_ut_copy_ielement_to_eelement,
33895b482a8SLen Brown 					   &info);
33995b482a8SLen Brown 
34095b482a8SLen Brown 	*space_used = info.length;
34195b482a8SLen Brown 	return_ACPI_STATUS(status);
34295b482a8SLen Brown }
34395b482a8SLen Brown 
34495b482a8SLen Brown /*******************************************************************************
34595b482a8SLen Brown  *
34695b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_iobject_to_eobject
34795b482a8SLen Brown  *
34895b482a8SLen Brown  * PARAMETERS:  internal_object     - The internal object to be converted
34990434c1cSBob Moore  *              ret_buffer          - Where the object is returned
35095b482a8SLen Brown  *
35195b482a8SLen Brown  * RETURN:      Status
35295b482a8SLen Brown  *
35390434c1cSBob Moore  * DESCRIPTION: This function is called to build an API object to be returned
35490434c1cSBob Moore  *              to the caller.
35595b482a8SLen Brown  *
35695b482a8SLen Brown  ******************************************************************************/
35795b482a8SLen Brown 
35895b482a8SLen Brown acpi_status
acpi_ut_copy_iobject_to_eobject(union acpi_operand_object * internal_object,struct acpi_buffer * ret_buffer)35995b482a8SLen Brown acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object,
36095b482a8SLen Brown 				struct acpi_buffer *ret_buffer)
36195b482a8SLen Brown {
36295b482a8SLen Brown 	acpi_status status;
36395b482a8SLen Brown 
36495b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject);
36595b482a8SLen Brown 
3663371c19cSBob Moore 	if (internal_object->common.type == ACPI_TYPE_PACKAGE) {
36795b482a8SLen Brown 		/*
36895b482a8SLen Brown 		 * Package object:  Copy all subobjects (including
36995b482a8SLen Brown 		 * nested packages)
37095b482a8SLen Brown 		 */
37195b482a8SLen Brown 		status = acpi_ut_copy_ipackage_to_epackage(internal_object,
37295b482a8SLen Brown 							   ret_buffer->pointer,
37395b482a8SLen Brown 							   &ret_buffer->length);
37495b482a8SLen Brown 	} else {
37595b482a8SLen Brown 		/*
37695b482a8SLen Brown 		 * Build a simple object (no nested objects)
37795b482a8SLen Brown 		 */
37895b482a8SLen Brown 		status = acpi_ut_copy_isimple_to_esimple(internal_object,
37995b482a8SLen Brown 							 ACPI_CAST_PTR(union
38095b482a8SLen Brown 								       acpi_object,
38195b482a8SLen Brown 								       ret_buffer->
38295b482a8SLen Brown 								       pointer),
38395b482a8SLen Brown 							 ACPI_ADD_PTR(u8,
38495b482a8SLen Brown 								      ret_buffer->
38595b482a8SLen Brown 								      pointer,
38695b482a8SLen Brown 								      ACPI_ROUND_UP_TO_NATIVE_WORD
38795b482a8SLen Brown 								      (sizeof
38895b482a8SLen Brown 								       (union
38995b482a8SLen Brown 									acpi_object))),
39095b482a8SLen Brown 							 &ret_buffer->length);
39195b482a8SLen Brown 		/*
39295b482a8SLen Brown 		 * build simple does not include the object size in the length
39395b482a8SLen Brown 		 * so we add it in here
39495b482a8SLen Brown 		 */
39595b482a8SLen Brown 		ret_buffer->length += sizeof(union acpi_object);
39695b482a8SLen Brown 	}
39795b482a8SLen Brown 
39895b482a8SLen Brown 	return_ACPI_STATUS(status);
39995b482a8SLen Brown }
40095b482a8SLen Brown 
40195b482a8SLen Brown /*******************************************************************************
40295b482a8SLen Brown  *
40395b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_esimple_to_isimple
40495b482a8SLen Brown  *
40595b482a8SLen Brown  * PARAMETERS:  external_object     - The external object to be converted
40695b482a8SLen Brown  *              ret_internal_object - Where the internal object is returned
40795b482a8SLen Brown  *
40895b482a8SLen Brown  * RETURN:      Status
40995b482a8SLen Brown  *
41095b482a8SLen Brown  * DESCRIPTION: This function copies an external object to an internal one.
41195b482a8SLen Brown  *              NOTE: Pointers can be copied, we don't need to copy data.
41295b482a8SLen Brown  *              (The pointers have to be valid in our address space no matter
41395b482a8SLen Brown  *              what we do with them!)
41495b482a8SLen Brown  *
41595b482a8SLen Brown  ******************************************************************************/
41695b482a8SLen Brown 
41795b482a8SLen Brown static acpi_status
acpi_ut_copy_esimple_to_isimple(union acpi_object * external_object,union acpi_operand_object ** ret_internal_object)41895b482a8SLen Brown acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
41995b482a8SLen Brown 				union acpi_operand_object **ret_internal_object)
42095b482a8SLen Brown {
42195b482a8SLen Brown 	union acpi_operand_object *internal_object;
42295b482a8SLen Brown 
42395b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_copy_esimple_to_isimple);
42495b482a8SLen Brown 
42595b482a8SLen Brown 	/*
42695b482a8SLen Brown 	 * Simple types supported are: String, Buffer, Integer
42795b482a8SLen Brown 	 */
42895b482a8SLen Brown 	switch (external_object->type) {
42995b482a8SLen Brown 	case ACPI_TYPE_STRING:
43095b482a8SLen Brown 	case ACPI_TYPE_BUFFER:
43195b482a8SLen Brown 	case ACPI_TYPE_INTEGER:
43295b482a8SLen Brown 	case ACPI_TYPE_LOCAL_REFERENCE:
43395b482a8SLen Brown 
43495b482a8SLen Brown 		internal_object = acpi_ut_create_internal_object((u8)
43595b482a8SLen Brown 								 external_object->
43695b482a8SLen Brown 								 type);
43795b482a8SLen Brown 		if (!internal_object) {
43895b482a8SLen Brown 			return_ACPI_STATUS(AE_NO_MEMORY);
43995b482a8SLen Brown 		}
44095b482a8SLen Brown 		break;
44195b482a8SLen Brown 
44295b482a8SLen Brown 	case ACPI_TYPE_ANY:	/* This is the case for a NULL object */
44395b482a8SLen Brown 
44495b482a8SLen Brown 		*ret_internal_object = NULL;
44595b482a8SLen Brown 		return_ACPI_STATUS(AE_OK);
44695b482a8SLen Brown 
44795b482a8SLen Brown 	default:
4481d1ea1b7SChao Guan 
44995b482a8SLen Brown 		/* All other types are not supported */
45095b482a8SLen Brown 
45195b482a8SLen Brown 		ACPI_ERROR((AE_INFO,
45295b482a8SLen Brown 			    "Unsupported object type, cannot convert to internal object: %s",
45395b482a8SLen Brown 			    acpi_ut_get_type_name(external_object->type)));
45495b482a8SLen Brown 
45595b482a8SLen Brown 		return_ACPI_STATUS(AE_SUPPORT);
45695b482a8SLen Brown 	}
45795b482a8SLen Brown 
45895b482a8SLen Brown 	/* Must COPY string and buffer contents */
45995b482a8SLen Brown 
46095b482a8SLen Brown 	switch (external_object->type) {
46195b482a8SLen Brown 	case ACPI_TYPE_STRING:
46295b482a8SLen Brown 
46395b482a8SLen Brown 		internal_object->string.pointer =
464ec41f193SBob Moore 		    ACPI_ALLOCATE_ZEROED((acpi_size)
465ec41f193SBob Moore 					 external_object->string.length + 1);
466ec41f193SBob Moore 
46795b482a8SLen Brown 		if (!internal_object->string.pointer) {
46895b482a8SLen Brown 			goto error_exit;
46995b482a8SLen Brown 		}
47095b482a8SLen Brown 
4714fa4616eSBob Moore 		memcpy(internal_object->string.pointer,
47295b482a8SLen Brown 		       external_object->string.pointer,
47395b482a8SLen Brown 		       external_object->string.length);
47495b482a8SLen Brown 
47595b482a8SLen Brown 		internal_object->string.length = external_object->string.length;
47695b482a8SLen Brown 		break;
47795b482a8SLen Brown 
47895b482a8SLen Brown 	case ACPI_TYPE_BUFFER:
47995b482a8SLen Brown 
48095b482a8SLen Brown 		internal_object->buffer.pointer =
48195b482a8SLen Brown 		    ACPI_ALLOCATE_ZEROED(external_object->buffer.length);
48295b482a8SLen Brown 		if (!internal_object->buffer.pointer) {
48395b482a8SLen Brown 			goto error_exit;
48495b482a8SLen Brown 		}
48595b482a8SLen Brown 
4864fa4616eSBob Moore 		memcpy(internal_object->buffer.pointer,
48795b482a8SLen Brown 		       external_object->buffer.pointer,
48895b482a8SLen Brown 		       external_object->buffer.length);
48995b482a8SLen Brown 
49095b482a8SLen Brown 		internal_object->buffer.length = external_object->buffer.length;
49195b482a8SLen Brown 
49295b482a8SLen Brown 		/* Mark buffer data valid */
49395b482a8SLen Brown 
49495b482a8SLen Brown 		internal_object->buffer.flags |= AOPOBJ_DATA_VALID;
49595b482a8SLen Brown 		break;
49695b482a8SLen Brown 
49795b482a8SLen Brown 	case ACPI_TYPE_INTEGER:
49895b482a8SLen Brown 
49995b482a8SLen Brown 		internal_object->integer.value = external_object->integer.value;
50095b482a8SLen Brown 		break;
50195b482a8SLen Brown 
50295b482a8SLen Brown 	case ACPI_TYPE_LOCAL_REFERENCE:
50395b482a8SLen Brown 
504ab85e928SBob Moore 		/* An incoming reference is defined to be a namespace node */
50595b482a8SLen Brown 
506ab85e928SBob Moore 		internal_object->reference.class = ACPI_REFCLASS_REFOF;
507ab85e928SBob Moore 		internal_object->reference.object =
50895b482a8SLen Brown 		    external_object->reference.handle;
50995b482a8SLen Brown 		break;
51095b482a8SLen Brown 
51195b482a8SLen Brown 	default:
5121d1ea1b7SChao Guan 
51395b482a8SLen Brown 		/* Other types can't get here */
5141d1ea1b7SChao Guan 
51595b482a8SLen Brown 		break;
51695b482a8SLen Brown 	}
51795b482a8SLen Brown 
51895b482a8SLen Brown 	*ret_internal_object = internal_object;
51995b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
52095b482a8SLen Brown 
52195b482a8SLen Brown error_exit:
52295b482a8SLen Brown 	acpi_ut_remove_reference(internal_object);
52395b482a8SLen Brown 	return_ACPI_STATUS(AE_NO_MEMORY);
52495b482a8SLen Brown }
52595b482a8SLen Brown 
52695b482a8SLen Brown /*******************************************************************************
52795b482a8SLen Brown  *
52895b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_epackage_to_ipackage
52995b482a8SLen Brown  *
53095b482a8SLen Brown  * PARAMETERS:  external_object     - The external object to be converted
53195b482a8SLen Brown  *              internal_object     - Where the internal object is returned
53295b482a8SLen Brown  *
53395b482a8SLen Brown  * RETURN:      Status
53495b482a8SLen Brown  *
53595b482a8SLen Brown  * DESCRIPTION: Copy an external package object to an internal package.
53695b482a8SLen Brown  *              Handles nested packages.
53795b482a8SLen Brown  *
53895b482a8SLen Brown  ******************************************************************************/
53995b482a8SLen Brown 
54095b482a8SLen Brown static acpi_status
acpi_ut_copy_epackage_to_ipackage(union acpi_object * external_object,union acpi_operand_object ** internal_object)54195b482a8SLen Brown acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
54295b482a8SLen Brown 				  union acpi_operand_object **internal_object)
54395b482a8SLen Brown {
54495b482a8SLen Brown 	acpi_status status = AE_OK;
54595b482a8SLen Brown 	union acpi_operand_object *package_object;
54695b482a8SLen Brown 	union acpi_operand_object **package_elements;
54795b482a8SLen Brown 	u32 i;
54895b482a8SLen Brown 
54995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
55095b482a8SLen Brown 
55195b482a8SLen Brown 	/* Create the package object */
55295b482a8SLen Brown 
55395b482a8SLen Brown 	package_object =
55495b482a8SLen Brown 	    acpi_ut_create_package_object(external_object->package.count);
55595b482a8SLen Brown 	if (!package_object) {
55695b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
55795b482a8SLen Brown 	}
55895b482a8SLen Brown 
55995b482a8SLen Brown 	package_elements = package_object->package.elements;
56095b482a8SLen Brown 
56195b482a8SLen Brown 	/*
5621fad8738SBob Moore 	 * Recursive implementation. Probably ok, since nested external
5631fad8738SBob Moore 	 * packages as parameters should be very rare.
56495b482a8SLen Brown 	 */
56595b482a8SLen Brown 	for (i = 0; i < external_object->package.count; i++) {
56695b482a8SLen Brown 		status =
56795b482a8SLen Brown 		    acpi_ut_copy_eobject_to_iobject(&external_object->package.
56895b482a8SLen Brown 						    elements[i],
56995b482a8SLen Brown 						    &package_elements[i]);
57095b482a8SLen Brown 		if (ACPI_FAILURE(status)) {
57195b482a8SLen Brown 
57295b482a8SLen Brown 			/* Truncate package and delete it */
57395b482a8SLen Brown 
57495b482a8SLen Brown 			package_object->package.count = i;
57595b482a8SLen Brown 			package_elements[i] = NULL;
57695b482a8SLen Brown 			acpi_ut_remove_reference(package_object);
57795b482a8SLen Brown 			return_ACPI_STATUS(status);
57895b482a8SLen Brown 		}
57995b482a8SLen Brown 	}
58095b482a8SLen Brown 
58195b482a8SLen Brown 	/* Mark package data valid */
58295b482a8SLen Brown 
58395b482a8SLen Brown 	package_object->package.flags |= AOPOBJ_DATA_VALID;
58495b482a8SLen Brown 
58595b482a8SLen Brown 	*internal_object = package_object;
58695b482a8SLen Brown 	return_ACPI_STATUS(status);
58795b482a8SLen Brown }
58895b482a8SLen Brown 
58995b482a8SLen Brown /*******************************************************************************
59095b482a8SLen Brown  *
59195b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_eobject_to_iobject
59295b482a8SLen Brown  *
59395b482a8SLen Brown  * PARAMETERS:  external_object     - The external object to be converted
59495b482a8SLen Brown  *              internal_object     - Where the internal object is returned
59595b482a8SLen Brown  *
59690434c1cSBob Moore  * RETURN:      Status
59795b482a8SLen Brown  *
59895b482a8SLen Brown  * DESCRIPTION: Converts an external object to an internal object.
59995b482a8SLen Brown  *
60095b482a8SLen Brown  ******************************************************************************/
60195b482a8SLen Brown 
60295b482a8SLen Brown acpi_status
acpi_ut_copy_eobject_to_iobject(union acpi_object * external_object,union acpi_operand_object ** internal_object)60395b482a8SLen Brown acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
60495b482a8SLen Brown 				union acpi_operand_object **internal_object)
60595b482a8SLen Brown {
60695b482a8SLen Brown 	acpi_status status;
60795b482a8SLen Brown 
60895b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject);
60995b482a8SLen Brown 
61095b482a8SLen Brown 	if (external_object->type == ACPI_TYPE_PACKAGE) {
61195b482a8SLen Brown 		status =
61295b482a8SLen Brown 		    acpi_ut_copy_epackage_to_ipackage(external_object,
61395b482a8SLen Brown 						      internal_object);
61495b482a8SLen Brown 	} else {
61595b482a8SLen Brown 		/*
61695b482a8SLen Brown 		 * Build a simple object (no nested objects)
61795b482a8SLen Brown 		 */
6181fad8738SBob Moore 		status = acpi_ut_copy_esimple_to_isimple(external_object,
61995b482a8SLen Brown 							 internal_object);
62095b482a8SLen Brown 	}
62195b482a8SLen Brown 
62295b482a8SLen Brown 	return_ACPI_STATUS(status);
62395b482a8SLen Brown }
62495b482a8SLen Brown 
62595b482a8SLen Brown /*******************************************************************************
62695b482a8SLen Brown  *
62795b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_simple_object
62895b482a8SLen Brown  *
62995b482a8SLen Brown  * PARAMETERS:  source_desc         - The internal object to be copied
63095b482a8SLen Brown  *              dest_desc           - New target object
63195b482a8SLen Brown  *
63295b482a8SLen Brown  * RETURN:      Status
63395b482a8SLen Brown  *
63495b482a8SLen Brown  * DESCRIPTION: Simple copy of one internal object to another. Reference count
63595b482a8SLen Brown  *              of the destination object is preserved.
63695b482a8SLen Brown  *
63795b482a8SLen Brown  ******************************************************************************/
63895b482a8SLen Brown 
63995b482a8SLen Brown static acpi_status
acpi_ut_copy_simple_object(union acpi_operand_object * source_desc,union acpi_operand_object * dest_desc)64095b482a8SLen Brown acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
64195b482a8SLen Brown 			   union acpi_operand_object *dest_desc)
64295b482a8SLen Brown {
64395b482a8SLen Brown 	u16 reference_count;
64495b482a8SLen Brown 	union acpi_operand_object *next_object;
64533a1d461SBob Moore 	acpi_status status;
64617b82327SLin Ming 	acpi_size copy_size;
64795b482a8SLen Brown 
64895b482a8SLen Brown 	/* Save fields from destination that we don't want to overwrite */
64995b482a8SLen Brown 
65095b482a8SLen Brown 	reference_count = dest_desc->common.reference_count;
65195b482a8SLen Brown 	next_object = dest_desc->common.next_object;
65295b482a8SLen Brown 
65317b82327SLin Ming 	/*
65417b82327SLin Ming 	 * Copy the entire source object over the destination object.
65517b82327SLin Ming 	 * Note: Source can be either an operand object or namespace node.
65617b82327SLin Ming 	 */
65717b82327SLin Ming 	copy_size = sizeof(union acpi_operand_object);
65817b82327SLin Ming 	if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_NAMED) {
65917b82327SLin Ming 		copy_size = sizeof(struct acpi_namespace_node);
66017b82327SLin Ming 	}
66195b482a8SLen Brown 
6624fa4616eSBob Moore 	memcpy(ACPI_CAST_PTR(char, dest_desc),
66317b82327SLin Ming 	       ACPI_CAST_PTR(char, source_desc), copy_size);
66495b482a8SLen Brown 
66595b482a8SLen Brown 	/* Restore the saved fields */
66695b482a8SLen Brown 
66795b482a8SLen Brown 	dest_desc->common.reference_count = reference_count;
66895b482a8SLen Brown 	dest_desc->common.next_object = next_object;
66995b482a8SLen Brown 
67095b482a8SLen Brown 	/* New object is not static, regardless of source */
67195b482a8SLen Brown 
67295b482a8SLen Brown 	dest_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
67395b482a8SLen Brown 
67495b482a8SLen Brown 	/* Handle the objects with extra data */
67595b482a8SLen Brown 
6763371c19cSBob Moore 	switch (dest_desc->common.type) {
67795b482a8SLen Brown 	case ACPI_TYPE_BUFFER:
67895b482a8SLen Brown 		/*
67995b482a8SLen Brown 		 * Allocate and copy the actual buffer if and only if:
68095b482a8SLen Brown 		 * 1) There is a valid buffer pointer
68195b482a8SLen Brown 		 * 2) The buffer has a length > 0
68295b482a8SLen Brown 		 */
68395b482a8SLen Brown 		if ((source_desc->buffer.pointer) &&
68495b482a8SLen Brown 		    (source_desc->buffer.length)) {
68595b482a8SLen Brown 			dest_desc->buffer.pointer =
68695b482a8SLen Brown 			    ACPI_ALLOCATE(source_desc->buffer.length);
68795b482a8SLen Brown 			if (!dest_desc->buffer.pointer) {
68895b482a8SLen Brown 				return (AE_NO_MEMORY);
68995b482a8SLen Brown 			}
69095b482a8SLen Brown 
69195b482a8SLen Brown 			/* Copy the actual buffer data */
69295b482a8SLen Brown 
6934fa4616eSBob Moore 			memcpy(dest_desc->buffer.pointer,
69495b482a8SLen Brown 			       source_desc->buffer.pointer,
69595b482a8SLen Brown 			       source_desc->buffer.length);
69695b482a8SLen Brown 		}
69795b482a8SLen Brown 		break;
69895b482a8SLen Brown 
69995b482a8SLen Brown 	case ACPI_TYPE_STRING:
70095b482a8SLen Brown 		/*
70195b482a8SLen Brown 		 * Allocate and copy the actual string if and only if:
70295b482a8SLen Brown 		 * 1) There is a valid string pointer
70395b482a8SLen Brown 		 * (Pointer to a NULL string is allowed)
70495b482a8SLen Brown 		 */
70595b482a8SLen Brown 		if (source_desc->string.pointer) {
70695b482a8SLen Brown 			dest_desc->string.pointer =
70795b482a8SLen Brown 			    ACPI_ALLOCATE((acpi_size)source_desc->string.
70895b482a8SLen Brown 					  length + 1);
70995b482a8SLen Brown 			if (!dest_desc->string.pointer) {
71095b482a8SLen Brown 				return (AE_NO_MEMORY);
71195b482a8SLen Brown 			}
71295b482a8SLen Brown 
71395b482a8SLen Brown 			/* Copy the actual string data */
71495b482a8SLen Brown 
7154fa4616eSBob Moore 			memcpy(dest_desc->string.pointer,
71695b482a8SLen Brown 			       source_desc->string.pointer,
71795b482a8SLen Brown 			       (acpi_size)source_desc->string.length + 1);
71895b482a8SLen Brown 		}
71995b482a8SLen Brown 		break;
72095b482a8SLen Brown 
72195b482a8SLen Brown 	case ACPI_TYPE_LOCAL_REFERENCE:
72295b482a8SLen Brown 		/*
72395b482a8SLen Brown 		 * We copied the reference object, so we now must add a reference
72495b482a8SLen Brown 		 * to the object pointed to by the reference
72595b482a8SLen Brown 		 *
72695b482a8SLen Brown 		 * DDBHandle reference (from Load/load_table) is a special reference,
72795b482a8SLen Brown 		 * it does not have a Reference.Object, so does not need to
72895b482a8SLen Brown 		 * increase the reference count
72995b482a8SLen Brown 		 */
73095b482a8SLen Brown 		if (source_desc->reference.class == ACPI_REFCLASS_TABLE) {
73195b482a8SLen Brown 			break;
73295b482a8SLen Brown 		}
73395b482a8SLen Brown 
73495b482a8SLen Brown 		acpi_ut_add_reference(source_desc->reference.object);
73595b482a8SLen Brown 		break;
73695b482a8SLen Brown 
73795b482a8SLen Brown 	case ACPI_TYPE_REGION:
73895b482a8SLen Brown 		/*
73995b482a8SLen Brown 		 * We copied the Region Handler, so we now must add a reference
74095b482a8SLen Brown 		 */
74195b482a8SLen Brown 		if (dest_desc->region.handler) {
74295b482a8SLen Brown 			acpi_ut_add_reference(dest_desc->region.handler);
74395b482a8SLen Brown 		}
74495b482a8SLen Brown 		break;
74595b482a8SLen Brown 
74633a1d461SBob Moore 		/*
74733a1d461SBob Moore 		 * For Mutex and Event objects, we cannot simply copy the underlying
74833a1d461SBob Moore 		 * OS object. We must create a new one.
74933a1d461SBob Moore 		 */
75033a1d461SBob Moore 	case ACPI_TYPE_MUTEX:
75133a1d461SBob Moore 
75233a1d461SBob Moore 		status = acpi_os_create_mutex(&dest_desc->mutex.os_mutex);
75333a1d461SBob Moore 		if (ACPI_FAILURE(status)) {
7549c0d7939SLv Zheng 			return (status);
75533a1d461SBob Moore 		}
75633a1d461SBob Moore 		break;
75733a1d461SBob Moore 
75833a1d461SBob Moore 	case ACPI_TYPE_EVENT:
75933a1d461SBob Moore 
76033a1d461SBob Moore 		status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
76133a1d461SBob Moore 						  &dest_desc->event.
76233a1d461SBob Moore 						  os_semaphore);
76333a1d461SBob Moore 		if (ACPI_FAILURE(status)) {
7649c0d7939SLv Zheng 			return (status);
76533a1d461SBob Moore 		}
76633a1d461SBob Moore 		break;
76733a1d461SBob Moore 
76895b482a8SLen Brown 	default:
7691d1ea1b7SChao Guan 
77095b482a8SLen Brown 		/* Nothing to do for other simple objects */
7711d1ea1b7SChao Guan 
77295b482a8SLen Brown 		break;
77395b482a8SLen Brown 	}
77495b482a8SLen Brown 
77595b482a8SLen Brown 	return (AE_OK);
77695b482a8SLen Brown }
77795b482a8SLen Brown 
77895b482a8SLen Brown /*******************************************************************************
77995b482a8SLen Brown  *
78095b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_ielement_to_ielement
78195b482a8SLen Brown  *
78295b482a8SLen Brown  * PARAMETERS:  acpi_pkg_callback
78395b482a8SLen Brown  *
78495b482a8SLen Brown  * RETURN:      Status
78595b482a8SLen Brown  *
78695b482a8SLen Brown  * DESCRIPTION: Copy one package element to another package element
78795b482a8SLen Brown  *
78895b482a8SLen Brown  ******************************************************************************/
78995b482a8SLen Brown 
79095b482a8SLen Brown static acpi_status
acpi_ut_copy_ielement_to_ielement(u8 object_type,union acpi_operand_object * source_object,union acpi_generic_state * state,void * context)79195b482a8SLen Brown acpi_ut_copy_ielement_to_ielement(u8 object_type,
79295b482a8SLen Brown 				  union acpi_operand_object *source_object,
79395b482a8SLen Brown 				  union acpi_generic_state *state,
79495b482a8SLen Brown 				  void *context)
79595b482a8SLen Brown {
79695b482a8SLen Brown 	acpi_status status = AE_OK;
79795b482a8SLen Brown 	u32 this_index;
79895b482a8SLen Brown 	union acpi_operand_object **this_target_ptr;
79995b482a8SLen Brown 	union acpi_operand_object *target_object;
80095b482a8SLen Brown 
80195b482a8SLen Brown 	ACPI_FUNCTION_ENTRY();
80295b482a8SLen Brown 
80395b482a8SLen Brown 	this_index = state->pkg.index;
80495b482a8SLen Brown 	this_target_ptr = (union acpi_operand_object **)
80595b482a8SLen Brown 	    &state->pkg.dest_object->package.elements[this_index];
80695b482a8SLen Brown 
80795b482a8SLen Brown 	switch (object_type) {
80895b482a8SLen Brown 	case ACPI_COPY_TYPE_SIMPLE:
80995b482a8SLen Brown 
81095b482a8SLen Brown 		/* A null source object indicates a (legal) null package element */
81195b482a8SLen Brown 
81295b482a8SLen Brown 		if (source_object) {
81395b482a8SLen Brown 			/*
81495b482a8SLen Brown 			 * This is a simple object, just copy it
81595b482a8SLen Brown 			 */
81695b482a8SLen Brown 			target_object =
8173371c19cSBob Moore 			    acpi_ut_create_internal_object(source_object->
8183371c19cSBob Moore 							   common.type);
81995b482a8SLen Brown 			if (!target_object) {
82095b482a8SLen Brown 				return (AE_NO_MEMORY);
82195b482a8SLen Brown 			}
82295b482a8SLen Brown 
82395b482a8SLen Brown 			status =
82495b482a8SLen Brown 			    acpi_ut_copy_simple_object(source_object,
82595b482a8SLen Brown 						       target_object);
82695b482a8SLen Brown 			if (ACPI_FAILURE(status)) {
82795b482a8SLen Brown 				goto error_exit;
82895b482a8SLen Brown 			}
82995b482a8SLen Brown 
83095b482a8SLen Brown 			*this_target_ptr = target_object;
83195b482a8SLen Brown 		} else {
83295b482a8SLen Brown 			/* Pass through a null element */
83395b482a8SLen Brown 
83495b482a8SLen Brown 			*this_target_ptr = NULL;
83595b482a8SLen Brown 		}
83695b482a8SLen Brown 		break;
83795b482a8SLen Brown 
83895b482a8SLen Brown 	case ACPI_COPY_TYPE_PACKAGE:
83995b482a8SLen Brown 		/*
84095b482a8SLen Brown 		 * This object is a package - go down another nesting level
84195b482a8SLen Brown 		 * Create and build the package object
84295b482a8SLen Brown 		 */
84395b482a8SLen Brown 		target_object =
84495b482a8SLen Brown 		    acpi_ut_create_package_object(source_object->package.count);
84595b482a8SLen Brown 		if (!target_object) {
84695b482a8SLen Brown 			return (AE_NO_MEMORY);
84795b482a8SLen Brown 		}
84895b482a8SLen Brown 
84995b482a8SLen Brown 		target_object->common.flags = source_object->common.flags;
85095b482a8SLen Brown 
85195b482a8SLen Brown 		/* Pass the new package object back to the package walk routine */
85295b482a8SLen Brown 
85395b482a8SLen Brown 		state->pkg.this_target_obj = target_object;
85495b482a8SLen Brown 
85595b482a8SLen Brown 		/* Store the object pointer in the parent package object */
85695b482a8SLen Brown 
85795b482a8SLen Brown 		*this_target_ptr = target_object;
85895b482a8SLen Brown 		break;
85995b482a8SLen Brown 
86095b482a8SLen Brown 	default:
8611d1ea1b7SChao Guan 
86295b482a8SLen Brown 		return (AE_BAD_PARAMETER);
86395b482a8SLen Brown 	}
86495b482a8SLen Brown 
86595b482a8SLen Brown 	return (status);
86695b482a8SLen Brown 
86795b482a8SLen Brown error_exit:
86895b482a8SLen Brown 	acpi_ut_remove_reference(target_object);
86995b482a8SLen Brown 	return (status);
87095b482a8SLen Brown }
87195b482a8SLen Brown 
87295b482a8SLen Brown /*******************************************************************************
87395b482a8SLen Brown  *
87495b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_ipackage_to_ipackage
87595b482a8SLen Brown  *
87690434c1cSBob Moore  * PARAMETERS:  source_obj      - Pointer to the source package object
87790434c1cSBob Moore  *              dest_obj        - Where the internal object is returned
87890434c1cSBob Moore  *              walk_state      - Current Walk state descriptor
87995b482a8SLen Brown  *
88090434c1cSBob Moore  * RETURN:      Status
88195b482a8SLen Brown  *
88295b482a8SLen Brown  * DESCRIPTION: This function is called to copy an internal package object
88395b482a8SLen Brown  *              into another internal package object.
88495b482a8SLen Brown  *
88595b482a8SLen Brown  ******************************************************************************/
88695b482a8SLen Brown 
88795b482a8SLen Brown static acpi_status
acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object * source_obj,union acpi_operand_object * dest_obj,struct acpi_walk_state * walk_state)88895b482a8SLen Brown acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
88995b482a8SLen Brown 				  union acpi_operand_object *dest_obj,
89095b482a8SLen Brown 				  struct acpi_walk_state *walk_state)
89195b482a8SLen Brown {
89295b482a8SLen Brown 	acpi_status status = AE_OK;
89395b482a8SLen Brown 
89495b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage);
89595b482a8SLen Brown 
8963371c19cSBob Moore 	dest_obj->common.type = source_obj->common.type;
89795b482a8SLen Brown 	dest_obj->common.flags = source_obj->common.flags;
89895b482a8SLen Brown 	dest_obj->package.count = source_obj->package.count;
89995b482a8SLen Brown 
90095b482a8SLen Brown 	/*
90195b482a8SLen Brown 	 * Create the object array and walk the source package tree
90295b482a8SLen Brown 	 */
90395b482a8SLen Brown 	dest_obj->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
90495b482a8SLen Brown 							   source_obj->package.
90595b482a8SLen Brown 							   count +
90695b482a8SLen Brown 							   1) * sizeof(void *));
90795b482a8SLen Brown 	if (!dest_obj->package.elements) {
90895b482a8SLen Brown 		ACPI_ERROR((AE_INFO, "Package allocation failure"));
90995b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
91095b482a8SLen Brown 	}
91195b482a8SLen Brown 
91295b482a8SLen Brown 	/*
91395b482a8SLen Brown 	 * Copy the package element-by-element by walking the package "tree".
91495b482a8SLen Brown 	 * This handles nested packages of arbitrary depth.
91595b482a8SLen Brown 	 */
91695b482a8SLen Brown 	status = acpi_ut_walk_package_tree(source_obj, dest_obj,
91795b482a8SLen Brown 					   acpi_ut_copy_ielement_to_ielement,
91895b482a8SLen Brown 					   walk_state);
91995b482a8SLen Brown 	return_ACPI_STATUS(status);
92095b482a8SLen Brown }
92195b482a8SLen Brown 
92295b482a8SLen Brown /*******************************************************************************
92395b482a8SLen Brown  *
92495b482a8SLen Brown  * FUNCTION:    acpi_ut_copy_iobject_to_iobject
92595b482a8SLen Brown  *
92690434c1cSBob Moore  * PARAMETERS:  source_desc         - The internal object to be copied
92795b482a8SLen Brown  *              dest_desc           - Where the copied object is returned
92890434c1cSBob Moore  *              walk_state          - Current walk state
92995b482a8SLen Brown  *
93095b482a8SLen Brown  * RETURN:      Status
93195b482a8SLen Brown  *
93295b482a8SLen Brown  * DESCRIPTION: Copy an internal object to a new internal object
93395b482a8SLen Brown  *
93495b482a8SLen Brown  ******************************************************************************/
93595b482a8SLen Brown 
93695b482a8SLen Brown acpi_status
acpi_ut_copy_iobject_to_iobject(union acpi_operand_object * source_desc,union acpi_operand_object ** dest_desc,struct acpi_walk_state * walk_state)93795b482a8SLen Brown acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc,
93895b482a8SLen Brown 				union acpi_operand_object **dest_desc,
93995b482a8SLen Brown 				struct acpi_walk_state *walk_state)
94095b482a8SLen Brown {
94195b482a8SLen Brown 	acpi_status status = AE_OK;
94295b482a8SLen Brown 
94395b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ut_copy_iobject_to_iobject);
94495b482a8SLen Brown 
94595b482a8SLen Brown 	/* Create the top level object */
94695b482a8SLen Brown 
9473371c19cSBob Moore 	*dest_desc = acpi_ut_create_internal_object(source_desc->common.type);
94895b482a8SLen Brown 	if (!*dest_desc) {
94995b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
95095b482a8SLen Brown 	}
95195b482a8SLen Brown 
95295b482a8SLen Brown 	/* Copy the object and possible subobjects */
95395b482a8SLen Brown 
9543371c19cSBob Moore 	if (source_desc->common.type == ACPI_TYPE_PACKAGE) {
95595b482a8SLen Brown 		status =
95695b482a8SLen Brown 		    acpi_ut_copy_ipackage_to_ipackage(source_desc, *dest_desc,
95795b482a8SLen Brown 						      walk_state);
95895b482a8SLen Brown 	} else {
95995b482a8SLen Brown 		status = acpi_ut_copy_simple_object(source_desc, *dest_desc);
96095b482a8SLen Brown 	}
96195b482a8SLen Brown 
9628aa5e56eSDavid E. Box 	/* Delete the allocated object if copy failed */
9638aa5e56eSDavid E. Box 
9648aa5e56eSDavid E. Box 	if (ACPI_FAILURE(status)) {
9658aa5e56eSDavid E. Box 		acpi_ut_remove_reference(*dest_desc);
9668aa5e56eSDavid E. Box 	}
9678aa5e56eSDavid E. Box 
96895b482a8SLen Brown 	return_ACPI_STATUS(status);
96995b482a8SLen Brown }
970