162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
262306a36Sopenharmony_ci/******************************************************************************
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Module Name: utobject - ACPI object create/delete/size/cache routines
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *****************************************************************************/
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <acpi/acpi.h>
1162306a36Sopenharmony_ci#include <linux/kmemleak.h>
1262306a36Sopenharmony_ci#include "accommon.h"
1362306a36Sopenharmony_ci#include "acnamesp.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#define _COMPONENT          ACPI_UTILITIES
1662306a36Sopenharmony_ciACPI_MODULE_NAME("utobject")
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/* Local prototypes */
1962306a36Sopenharmony_cistatic acpi_status
2062306a36Sopenharmony_ciacpi_ut_get_simple_object_size(union acpi_operand_object *obj,
2162306a36Sopenharmony_ci			       acpi_size *obj_length);
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic acpi_status
2462306a36Sopenharmony_ciacpi_ut_get_package_object_size(union acpi_operand_object *obj,
2562306a36Sopenharmony_ci				acpi_size *obj_length);
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic acpi_status
2862306a36Sopenharmony_ciacpi_ut_get_element_length(u8 object_type,
2962306a36Sopenharmony_ci			   union acpi_operand_object *source_object,
3062306a36Sopenharmony_ci			   union acpi_generic_state *state, void *context);
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/*******************************************************************************
3362306a36Sopenharmony_ci *
3462306a36Sopenharmony_ci * FUNCTION:    acpi_ut_create_internal_object_dbg
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci * PARAMETERS:  module_name         - Source file name of caller
3762306a36Sopenharmony_ci *              line_number         - Line number of caller
3862306a36Sopenharmony_ci *              component_id        - Component type of caller
3962306a36Sopenharmony_ci *              type                - ACPI Type of the new object
4062306a36Sopenharmony_ci *
4162306a36Sopenharmony_ci * RETURN:      A new internal object, null on failure
4262306a36Sopenharmony_ci *
4362306a36Sopenharmony_ci * DESCRIPTION: Create and initialize a new internal object.
4462306a36Sopenharmony_ci *
4562306a36Sopenharmony_ci * NOTE:        We always allocate the worst-case object descriptor because
4662306a36Sopenharmony_ci *              these objects are cached, and we want them to be
4762306a36Sopenharmony_ci *              one-size-satisfies-any-request. This in itself may not be
4862306a36Sopenharmony_ci *              the most memory efficient, but the efficiency of the object
4962306a36Sopenharmony_ci *              cache should more than make up for this!
5062306a36Sopenharmony_ci *
5162306a36Sopenharmony_ci ******************************************************************************/
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ciunion acpi_operand_object *acpi_ut_create_internal_object_dbg(const char
5462306a36Sopenharmony_ci							      *module_name,
5562306a36Sopenharmony_ci							      u32 line_number,
5662306a36Sopenharmony_ci							      u32 component_id,
5762306a36Sopenharmony_ci							      acpi_object_type
5862306a36Sopenharmony_ci							      type)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	union acpi_operand_object *object;
6162306a36Sopenharmony_ci	union acpi_operand_object *second_object;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE_STR(ut_create_internal_object_dbg,
6462306a36Sopenharmony_ci				acpi_ut_get_type_name(type));
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	/* Allocate the raw object descriptor */
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	object =
6962306a36Sopenharmony_ci	    acpi_ut_allocate_object_desc_dbg(module_name, line_number,
7062306a36Sopenharmony_ci					     component_id);
7162306a36Sopenharmony_ci	if (!object) {
7262306a36Sopenharmony_ci		return_PTR(NULL);
7362306a36Sopenharmony_ci	}
7462306a36Sopenharmony_ci	kmemleak_not_leak(object);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	switch (type) {
7762306a36Sopenharmony_ci	case ACPI_TYPE_REGION:
7862306a36Sopenharmony_ci	case ACPI_TYPE_BUFFER_FIELD:
7962306a36Sopenharmony_ci	case ACPI_TYPE_LOCAL_BANK_FIELD:
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci		/* These types require a secondary object */
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci		second_object =
8462306a36Sopenharmony_ci		    acpi_ut_allocate_object_desc_dbg(module_name, line_number,
8562306a36Sopenharmony_ci						     component_id);
8662306a36Sopenharmony_ci		if (!second_object) {
8762306a36Sopenharmony_ci			acpi_ut_delete_object_desc(object);
8862306a36Sopenharmony_ci			return_PTR(NULL);
8962306a36Sopenharmony_ci		}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci		second_object->common.type = ACPI_TYPE_LOCAL_EXTRA;
9262306a36Sopenharmony_ci		second_object->common.reference_count = 1;
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci		/* Link the second object to the first */
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci		object->common.next_object = second_object;
9762306a36Sopenharmony_ci		break;
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	default:
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci		/* All others have no secondary object */
10262306a36Sopenharmony_ci		break;
10362306a36Sopenharmony_ci	}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	/* Save the object type in the object descriptor */
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	object->common.type = (u8) type;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	/* Init the reference count */
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	object->common.reference_count = 1;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	/* Any per-type initialization should go here */
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	return_PTR(object);
11662306a36Sopenharmony_ci}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci/*******************************************************************************
11962306a36Sopenharmony_ci *
12062306a36Sopenharmony_ci * FUNCTION:    acpi_ut_create_package_object
12162306a36Sopenharmony_ci *
12262306a36Sopenharmony_ci * PARAMETERS:  count               - Number of package elements
12362306a36Sopenharmony_ci *
12462306a36Sopenharmony_ci * RETURN:      Pointer to a new Package object, null on failure
12562306a36Sopenharmony_ci *
12662306a36Sopenharmony_ci * DESCRIPTION: Create a fully initialized package object
12762306a36Sopenharmony_ci *
12862306a36Sopenharmony_ci ******************************************************************************/
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ciunion acpi_operand_object *acpi_ut_create_package_object(u32 count)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	union acpi_operand_object *package_desc;
13362306a36Sopenharmony_ci	union acpi_operand_object **package_elements;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE_U32(ut_create_package_object, count);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	/* Create a new Package object */
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	package_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
14062306a36Sopenharmony_ci	if (!package_desc) {
14162306a36Sopenharmony_ci		return_PTR(NULL);
14262306a36Sopenharmony_ci	}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	/*
14562306a36Sopenharmony_ci	 * Create the element array. Count+1 allows the array to be null
14662306a36Sopenharmony_ci	 * terminated.
14762306a36Sopenharmony_ci	 */
14862306a36Sopenharmony_ci	package_elements = ACPI_ALLOCATE_ZEROED(((acpi_size)count +
14962306a36Sopenharmony_ci						 1) * sizeof(void *));
15062306a36Sopenharmony_ci	if (!package_elements) {
15162306a36Sopenharmony_ci		ACPI_FREE(package_desc);
15262306a36Sopenharmony_ci		return_PTR(NULL);
15362306a36Sopenharmony_ci	}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	package_desc->package.count = count;
15662306a36Sopenharmony_ci	package_desc->package.elements = package_elements;
15762306a36Sopenharmony_ci	return_PTR(package_desc);
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci/*******************************************************************************
16162306a36Sopenharmony_ci *
16262306a36Sopenharmony_ci * FUNCTION:    acpi_ut_create_integer_object
16362306a36Sopenharmony_ci *
16462306a36Sopenharmony_ci * PARAMETERS:  initial_value       - Initial value for the integer
16562306a36Sopenharmony_ci *
16662306a36Sopenharmony_ci * RETURN:      Pointer to a new Integer object, null on failure
16762306a36Sopenharmony_ci *
16862306a36Sopenharmony_ci * DESCRIPTION: Create an initialized integer object
16962306a36Sopenharmony_ci *
17062306a36Sopenharmony_ci ******************************************************************************/
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ciunion acpi_operand_object *acpi_ut_create_integer_object(u64 initial_value)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	union acpi_operand_object *integer_desc;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_create_integer_object);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	/* Create and initialize a new integer object */
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	integer_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
18162306a36Sopenharmony_ci	if (!integer_desc) {
18262306a36Sopenharmony_ci		return_PTR(NULL);
18362306a36Sopenharmony_ci	}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	integer_desc->integer.value = initial_value;
18662306a36Sopenharmony_ci	return_PTR(integer_desc);
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci/*******************************************************************************
19062306a36Sopenharmony_ci *
19162306a36Sopenharmony_ci * FUNCTION:    acpi_ut_create_buffer_object
19262306a36Sopenharmony_ci *
19362306a36Sopenharmony_ci * PARAMETERS:  buffer_size            - Size of buffer to be created
19462306a36Sopenharmony_ci *
19562306a36Sopenharmony_ci * RETURN:      Pointer to a new Buffer object, null on failure
19662306a36Sopenharmony_ci *
19762306a36Sopenharmony_ci * DESCRIPTION: Create a fully initialized buffer object
19862306a36Sopenharmony_ci *
19962306a36Sopenharmony_ci ******************************************************************************/
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ciunion acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size)
20262306a36Sopenharmony_ci{
20362306a36Sopenharmony_ci	union acpi_operand_object *buffer_desc;
20462306a36Sopenharmony_ci	u8 *buffer = NULL;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE_U32(ut_create_buffer_object, buffer_size);
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	/* Create a new Buffer object */
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	buffer_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
21162306a36Sopenharmony_ci	if (!buffer_desc) {
21262306a36Sopenharmony_ci		return_PTR(NULL);
21362306a36Sopenharmony_ci	}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	/* Create an actual buffer only if size > 0 */
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	if (buffer_size > 0) {
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci		/* Allocate the actual buffer */
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci		buffer = ACPI_ALLOCATE_ZEROED(buffer_size);
22262306a36Sopenharmony_ci		if (!buffer) {
22362306a36Sopenharmony_ci			ACPI_ERROR((AE_INFO, "Could not allocate size %u",
22462306a36Sopenharmony_ci				    (u32)buffer_size));
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci			acpi_ut_remove_reference(buffer_desc);
22762306a36Sopenharmony_ci			return_PTR(NULL);
22862306a36Sopenharmony_ci		}
22962306a36Sopenharmony_ci	}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	/* Complete buffer object initialization */
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_ci	buffer_desc->buffer.flags |= AOPOBJ_DATA_VALID;
23462306a36Sopenharmony_ci	buffer_desc->buffer.pointer = buffer;
23562306a36Sopenharmony_ci	buffer_desc->buffer.length = (u32) buffer_size;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	/* Return the new buffer descriptor */
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	return_PTR(buffer_desc);
24062306a36Sopenharmony_ci}
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci/*******************************************************************************
24362306a36Sopenharmony_ci *
24462306a36Sopenharmony_ci * FUNCTION:    acpi_ut_create_string_object
24562306a36Sopenharmony_ci *
24662306a36Sopenharmony_ci * PARAMETERS:  string_size         - Size of string to be created. Does not
24762306a36Sopenharmony_ci *                                    include NULL terminator, this is added
24862306a36Sopenharmony_ci *                                    automatically.
24962306a36Sopenharmony_ci *
25062306a36Sopenharmony_ci * RETURN:      Pointer to a new String object
25162306a36Sopenharmony_ci *
25262306a36Sopenharmony_ci * DESCRIPTION: Create a fully initialized string object
25362306a36Sopenharmony_ci *
25462306a36Sopenharmony_ci ******************************************************************************/
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ciunion acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	union acpi_operand_object *string_desc;
25962306a36Sopenharmony_ci	char *string;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE_U32(ut_create_string_object, string_size);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	/* Create a new String object */
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	string_desc = acpi_ut_create_internal_object(ACPI_TYPE_STRING);
26662306a36Sopenharmony_ci	if (!string_desc) {
26762306a36Sopenharmony_ci		return_PTR(NULL);
26862306a36Sopenharmony_ci	}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	/*
27162306a36Sopenharmony_ci	 * Allocate the actual string buffer -- (Size + 1) for NULL terminator.
27262306a36Sopenharmony_ci	 * NOTE: Zero-length strings are NULL terminated
27362306a36Sopenharmony_ci	 */
27462306a36Sopenharmony_ci	string = ACPI_ALLOCATE_ZEROED(string_size + 1);
27562306a36Sopenharmony_ci	if (!string) {
27662306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO, "Could not allocate size %u",
27762306a36Sopenharmony_ci			    (u32)string_size));
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci		acpi_ut_remove_reference(string_desc);
28062306a36Sopenharmony_ci		return_PTR(NULL);
28162306a36Sopenharmony_ci	}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	/* Complete string object initialization */
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	string_desc->string.pointer = string;
28662306a36Sopenharmony_ci	string_desc->string.length = (u32) string_size;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	/* Return the new string descriptor */
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	return_PTR(string_desc);
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci/*******************************************************************************
29462306a36Sopenharmony_ci *
29562306a36Sopenharmony_ci * FUNCTION:    acpi_ut_valid_internal_object
29662306a36Sopenharmony_ci *
29762306a36Sopenharmony_ci * PARAMETERS:  object              - Object to be validated
29862306a36Sopenharmony_ci *
29962306a36Sopenharmony_ci * RETURN:      TRUE if object is valid, FALSE otherwise
30062306a36Sopenharmony_ci *
30162306a36Sopenharmony_ci * DESCRIPTION: Validate a pointer to be of type union acpi_operand_object
30262306a36Sopenharmony_ci *
30362306a36Sopenharmony_ci ******************************************************************************/
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ciu8 acpi_ut_valid_internal_object(void *object)
30662306a36Sopenharmony_ci{
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	ACPI_FUNCTION_NAME(ut_valid_internal_object);
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci	/* Check for a null pointer */
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	if (!object) {
31362306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "**** Null Object Ptr\n"));
31462306a36Sopenharmony_ci		return (FALSE);
31562306a36Sopenharmony_ci	}
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	/* Check the descriptor type field */
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	switch (ACPI_GET_DESCRIPTOR_TYPE(object)) {
32062306a36Sopenharmony_ci	case ACPI_DESC_TYPE_OPERAND:
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci		/* The object appears to be a valid union acpi_operand_object */
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci		return (TRUE);
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	default:
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci		ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
32962306a36Sopenharmony_ci				  "%p is not an ACPI operand obj [%s]\n",
33062306a36Sopenharmony_ci				  object, acpi_ut_get_descriptor_name(object)));
33162306a36Sopenharmony_ci		break;
33262306a36Sopenharmony_ci	}
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	return (FALSE);
33562306a36Sopenharmony_ci}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci/*******************************************************************************
33862306a36Sopenharmony_ci *
33962306a36Sopenharmony_ci * FUNCTION:    acpi_ut_allocate_object_desc_dbg
34062306a36Sopenharmony_ci *
34162306a36Sopenharmony_ci * PARAMETERS:  module_name         - Caller's module name (for error output)
34262306a36Sopenharmony_ci *              line_number         - Caller's line number (for error output)
34362306a36Sopenharmony_ci *              component_id        - Caller's component ID (for error output)
34462306a36Sopenharmony_ci *
34562306a36Sopenharmony_ci * RETURN:      Pointer to newly allocated object descriptor. Null on error
34662306a36Sopenharmony_ci *
34762306a36Sopenharmony_ci * DESCRIPTION: Allocate a new object descriptor. Gracefully handle
34862306a36Sopenharmony_ci *              error conditions.
34962306a36Sopenharmony_ci *
35062306a36Sopenharmony_ci ******************************************************************************/
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_civoid *acpi_ut_allocate_object_desc_dbg(const char *module_name,
35362306a36Sopenharmony_ci				       u32 line_number, u32 component_id)
35462306a36Sopenharmony_ci{
35562306a36Sopenharmony_ci	union acpi_operand_object *object;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE(ut_allocate_object_desc_dbg);
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	object = acpi_os_acquire_object(acpi_gbl_operand_cache);
36062306a36Sopenharmony_ci	if (!object) {
36162306a36Sopenharmony_ci		ACPI_ERROR((module_name, line_number,
36262306a36Sopenharmony_ci			    "Could not allocate an object descriptor"));
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci		return_PTR(NULL);
36562306a36Sopenharmony_ci	}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	/* Mark the descriptor type */
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_ci	ACPI_SET_DESCRIPTOR_TYPE(object, ACPI_DESC_TYPE_OPERAND);
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p Size %X\n",
37262306a36Sopenharmony_ci			  object, (u32) sizeof(union acpi_operand_object)));
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	return_PTR(object);
37562306a36Sopenharmony_ci}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci/*******************************************************************************
37862306a36Sopenharmony_ci *
37962306a36Sopenharmony_ci * FUNCTION:    acpi_ut_delete_object_desc
38062306a36Sopenharmony_ci *
38162306a36Sopenharmony_ci * PARAMETERS:  object          - An Acpi internal object to be deleted
38262306a36Sopenharmony_ci *
38362306a36Sopenharmony_ci * RETURN:      None.
38462306a36Sopenharmony_ci *
38562306a36Sopenharmony_ci * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache
38662306a36Sopenharmony_ci *
38762306a36Sopenharmony_ci ******************************************************************************/
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_civoid acpi_ut_delete_object_desc(union acpi_operand_object *object)
39062306a36Sopenharmony_ci{
39162306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE_PTR(ut_delete_object_desc, object);
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	/* Object must be of type union acpi_operand_object */
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) {
39662306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO,
39762306a36Sopenharmony_ci			    "%p is not an ACPI Operand object [%s]", object,
39862306a36Sopenharmony_ci			    acpi_ut_get_descriptor_name(object)));
39962306a36Sopenharmony_ci		return_VOID;
40062306a36Sopenharmony_ci	}
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	(void)acpi_os_release_object(acpi_gbl_operand_cache, object);
40362306a36Sopenharmony_ci	return_VOID;
40462306a36Sopenharmony_ci}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci/*******************************************************************************
40762306a36Sopenharmony_ci *
40862306a36Sopenharmony_ci * FUNCTION:    acpi_ut_get_simple_object_size
40962306a36Sopenharmony_ci *
41062306a36Sopenharmony_ci * PARAMETERS:  internal_object    - An ACPI operand object
41162306a36Sopenharmony_ci *              obj_length         - Where the length is returned
41262306a36Sopenharmony_ci *
41362306a36Sopenharmony_ci * RETURN:      Status
41462306a36Sopenharmony_ci *
41562306a36Sopenharmony_ci * DESCRIPTION: This function is called to determine the space required to
41662306a36Sopenharmony_ci *              contain a simple object for return to an external user.
41762306a36Sopenharmony_ci *
41862306a36Sopenharmony_ci *              The length includes the object structure plus any additional
41962306a36Sopenharmony_ci *              needed space.
42062306a36Sopenharmony_ci *
42162306a36Sopenharmony_ci ******************************************************************************/
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_cistatic acpi_status
42462306a36Sopenharmony_ciacpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
42562306a36Sopenharmony_ci			       acpi_size *obj_length)
42662306a36Sopenharmony_ci{
42762306a36Sopenharmony_ci	acpi_size length;
42862306a36Sopenharmony_ci	acpi_size size;
42962306a36Sopenharmony_ci	acpi_status status = AE_OK;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	/* Start with the length of the (external) Acpi object */
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	length = sizeof(union acpi_object);
43662306a36Sopenharmony_ci
43762306a36Sopenharmony_ci	/* A NULL object is allowed, can be a legal uninitialized package element */
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci	if (!internal_object) {
44062306a36Sopenharmony_ci	/*
44162306a36Sopenharmony_ci		 * Object is NULL, just return the length of union acpi_object
44262306a36Sopenharmony_ci		 * (A NULL union acpi_object is an object of all zeroes.)
44362306a36Sopenharmony_ci	 */
44462306a36Sopenharmony_ci		*obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length);
44562306a36Sopenharmony_ci		return_ACPI_STATUS(AE_OK);
44662306a36Sopenharmony_ci	}
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	/* A Namespace Node should never appear here */
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) {
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci		/* A namespace node should never get here */
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO,
45562306a36Sopenharmony_ci			    "Received a namespace node [%4.4s] "
45662306a36Sopenharmony_ci			    "where an operand object is required",
45762306a36Sopenharmony_ci			    ACPI_CAST_PTR(struct acpi_namespace_node,
45862306a36Sopenharmony_ci					  internal_object)->name.ascii));
45962306a36Sopenharmony_ci		return_ACPI_STATUS(AE_AML_INTERNAL);
46062306a36Sopenharmony_ci	}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	/*
46362306a36Sopenharmony_ci	 * The final length depends on the object type
46462306a36Sopenharmony_ci	 * Strings and Buffers are packed right up against the parent object and
46562306a36Sopenharmony_ci	 * must be accessed bytewise or there may be alignment problems on
46662306a36Sopenharmony_ci	 * certain processors
46762306a36Sopenharmony_ci	 */
46862306a36Sopenharmony_ci	switch (internal_object->common.type) {
46962306a36Sopenharmony_ci	case ACPI_TYPE_STRING:
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci		length += (acpi_size)internal_object->string.length + 1;
47262306a36Sopenharmony_ci		break;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci	case ACPI_TYPE_BUFFER:
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci		length += (acpi_size)internal_object->buffer.length;
47762306a36Sopenharmony_ci		break;
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	case ACPI_TYPE_INTEGER:
48062306a36Sopenharmony_ci	case ACPI_TYPE_PROCESSOR:
48162306a36Sopenharmony_ci	case ACPI_TYPE_POWER:
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci		/* No extra data for these types */
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_ci		break;
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	case ACPI_TYPE_LOCAL_REFERENCE:
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci		switch (internal_object->reference.class) {
49062306a36Sopenharmony_ci		case ACPI_REFCLASS_NAME:
49162306a36Sopenharmony_ci			/*
49262306a36Sopenharmony_ci			 * Get the actual length of the full pathname to this object.
49362306a36Sopenharmony_ci			 * The reference will be converted to the pathname to the object
49462306a36Sopenharmony_ci			 */
49562306a36Sopenharmony_ci			size =
49662306a36Sopenharmony_ci			    acpi_ns_get_pathname_length(internal_object->
49762306a36Sopenharmony_ci							reference.node);
49862306a36Sopenharmony_ci			if (!size) {
49962306a36Sopenharmony_ci				return_ACPI_STATUS(AE_BAD_PARAMETER);
50062306a36Sopenharmony_ci			}
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci			length += ACPI_ROUND_UP_TO_NATIVE_WORD(size);
50362306a36Sopenharmony_ci			break;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci		default:
50662306a36Sopenharmony_ci			/*
50762306a36Sopenharmony_ci			 * No other reference opcodes are supported.
50862306a36Sopenharmony_ci			 * Notably, Locals and Args are not supported, but this may be
50962306a36Sopenharmony_ci			 * required eventually.
51062306a36Sopenharmony_ci			 */
51162306a36Sopenharmony_ci			ACPI_ERROR((AE_INFO,
51262306a36Sopenharmony_ci				    "Cannot convert to external object - "
51362306a36Sopenharmony_ci				    "unsupported Reference Class [%s] 0x%X in object %p",
51462306a36Sopenharmony_ci				    acpi_ut_get_reference_name(internal_object),
51562306a36Sopenharmony_ci				    internal_object->reference.class,
51662306a36Sopenharmony_ci				    internal_object));
51762306a36Sopenharmony_ci			status = AE_TYPE;
51862306a36Sopenharmony_ci			break;
51962306a36Sopenharmony_ci		}
52062306a36Sopenharmony_ci		break;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	default:
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci		ACPI_ERROR((AE_INFO, "Cannot convert to external object - "
52562306a36Sopenharmony_ci			    "unsupported type [%s] 0x%X in object %p",
52662306a36Sopenharmony_ci			    acpi_ut_get_object_type_name(internal_object),
52762306a36Sopenharmony_ci			    internal_object->common.type, internal_object));
52862306a36Sopenharmony_ci		status = AE_TYPE;
52962306a36Sopenharmony_ci		break;
53062306a36Sopenharmony_ci	}
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	/*
53362306a36Sopenharmony_ci	 * Account for the space required by the object rounded up to the next
53462306a36Sopenharmony_ci	 * multiple of the machine word size. This keeps each object aligned
53562306a36Sopenharmony_ci	 * on a machine word boundary. (preventing alignment faults on some
53662306a36Sopenharmony_ci	 * machines.)
53762306a36Sopenharmony_ci	 */
53862306a36Sopenharmony_ci	*obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length);
53962306a36Sopenharmony_ci	return_ACPI_STATUS(status);
54062306a36Sopenharmony_ci}
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci/*******************************************************************************
54362306a36Sopenharmony_ci *
54462306a36Sopenharmony_ci * FUNCTION:    acpi_ut_get_element_length
54562306a36Sopenharmony_ci *
54662306a36Sopenharmony_ci * PARAMETERS:  acpi_pkg_callback
54762306a36Sopenharmony_ci *
54862306a36Sopenharmony_ci * RETURN:      Status
54962306a36Sopenharmony_ci *
55062306a36Sopenharmony_ci * DESCRIPTION: Get the length of one package element.
55162306a36Sopenharmony_ci *
55262306a36Sopenharmony_ci ******************************************************************************/
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_cistatic acpi_status
55562306a36Sopenharmony_ciacpi_ut_get_element_length(u8 object_type,
55662306a36Sopenharmony_ci			   union acpi_operand_object *source_object,
55762306a36Sopenharmony_ci			   union acpi_generic_state *state, void *context)
55862306a36Sopenharmony_ci{
55962306a36Sopenharmony_ci	acpi_status status = AE_OK;
56062306a36Sopenharmony_ci	struct acpi_pkg_info *info = (struct acpi_pkg_info *)context;
56162306a36Sopenharmony_ci	acpi_size object_space;
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	switch (object_type) {
56462306a36Sopenharmony_ci	case ACPI_COPY_TYPE_SIMPLE:
56562306a36Sopenharmony_ci		/*
56662306a36Sopenharmony_ci		 * Simple object - just get the size (Null object/entry is handled
56762306a36Sopenharmony_ci		 * here also) and sum it into the running package length
56862306a36Sopenharmony_ci		 */
56962306a36Sopenharmony_ci		status =
57062306a36Sopenharmony_ci		    acpi_ut_get_simple_object_size(source_object,
57162306a36Sopenharmony_ci						   &object_space);
57262306a36Sopenharmony_ci		if (ACPI_FAILURE(status)) {
57362306a36Sopenharmony_ci			return (status);
57462306a36Sopenharmony_ci		}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci		info->length += object_space;
57762306a36Sopenharmony_ci		break;
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	case ACPI_COPY_TYPE_PACKAGE:
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci		/* Package object - nothing much to do here, let the walk handle it */
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci		info->num_packages++;
58462306a36Sopenharmony_ci		state->pkg.this_target_obj = NULL;
58562306a36Sopenharmony_ci		break;
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	default:
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci		/* No other types allowed */
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci		return (AE_BAD_PARAMETER);
59262306a36Sopenharmony_ci	}
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	return (status);
59562306a36Sopenharmony_ci}
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci/*******************************************************************************
59862306a36Sopenharmony_ci *
59962306a36Sopenharmony_ci * FUNCTION:    acpi_ut_get_package_object_size
60062306a36Sopenharmony_ci *
60162306a36Sopenharmony_ci * PARAMETERS:  internal_object     - An ACPI internal object
60262306a36Sopenharmony_ci *              obj_length          - Where the length is returned
60362306a36Sopenharmony_ci *
60462306a36Sopenharmony_ci * RETURN:      Status
60562306a36Sopenharmony_ci *
60662306a36Sopenharmony_ci * DESCRIPTION: This function is called to determine the space required to
60762306a36Sopenharmony_ci *              contain a package object for return to an external user.
60862306a36Sopenharmony_ci *
60962306a36Sopenharmony_ci *              This is moderately complex since a package contains other
61062306a36Sopenharmony_ci *              objects including packages.
61162306a36Sopenharmony_ci *
61262306a36Sopenharmony_ci ******************************************************************************/
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_cistatic acpi_status
61562306a36Sopenharmony_ciacpi_ut_get_package_object_size(union acpi_operand_object *internal_object,
61662306a36Sopenharmony_ci				acpi_size *obj_length)
61762306a36Sopenharmony_ci{
61862306a36Sopenharmony_ci	acpi_status status;
61962306a36Sopenharmony_ci	struct acpi_pkg_info info;
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	ACPI_FUNCTION_TRACE_PTR(ut_get_package_object_size, internal_object);
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	info.length = 0;
62462306a36Sopenharmony_ci	info.object_space = 0;
62562306a36Sopenharmony_ci	info.num_packages = 1;
62662306a36Sopenharmony_ci
62762306a36Sopenharmony_ci	status =
62862306a36Sopenharmony_ci	    acpi_ut_walk_package_tree(internal_object, NULL,
62962306a36Sopenharmony_ci				      acpi_ut_get_element_length, &info);
63062306a36Sopenharmony_ci	if (ACPI_FAILURE(status)) {
63162306a36Sopenharmony_ci		return_ACPI_STATUS(status);
63262306a36Sopenharmony_ci	}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	/*
63562306a36Sopenharmony_ci	 * We have handled all of the objects in all levels of the package.
63662306a36Sopenharmony_ci	 * just add the length of the package objects themselves.
63762306a36Sopenharmony_ci	 * Round up to the next machine word.
63862306a36Sopenharmony_ci	 */
63962306a36Sopenharmony_ci	info.length +=
64062306a36Sopenharmony_ci	    ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)) *
64162306a36Sopenharmony_ci	    (acpi_size)info.num_packages;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	/* Return the total package length */
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci	*obj_length = info.length;
64662306a36Sopenharmony_ci	return_ACPI_STATUS(status);
64762306a36Sopenharmony_ci}
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci/*******************************************************************************
65062306a36Sopenharmony_ci *
65162306a36Sopenharmony_ci * FUNCTION:    acpi_ut_get_object_size
65262306a36Sopenharmony_ci *
65362306a36Sopenharmony_ci * PARAMETERS:  internal_object     - An ACPI internal object
65462306a36Sopenharmony_ci *              obj_length          - Where the length will be returned
65562306a36Sopenharmony_ci *
65662306a36Sopenharmony_ci * RETURN:      Status
65762306a36Sopenharmony_ci *
65862306a36Sopenharmony_ci * DESCRIPTION: This function is called to determine the space required to
65962306a36Sopenharmony_ci *              contain an object for return to an API user.
66062306a36Sopenharmony_ci *
66162306a36Sopenharmony_ci ******************************************************************************/
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ciacpi_status
66462306a36Sopenharmony_ciacpi_ut_get_object_size(union acpi_operand_object *internal_object,
66562306a36Sopenharmony_ci			acpi_size *obj_length)
66662306a36Sopenharmony_ci{
66762306a36Sopenharmony_ci	acpi_status status;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	ACPI_FUNCTION_ENTRY();
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_ci	if ((ACPI_GET_DESCRIPTOR_TYPE(internal_object) ==
67262306a36Sopenharmony_ci	     ACPI_DESC_TYPE_OPERAND) &&
67362306a36Sopenharmony_ci	    (internal_object->common.type == ACPI_TYPE_PACKAGE)) {
67462306a36Sopenharmony_ci		status =
67562306a36Sopenharmony_ci		    acpi_ut_get_package_object_size(internal_object,
67662306a36Sopenharmony_ci						    obj_length);
67762306a36Sopenharmony_ci	} else {
67862306a36Sopenharmony_ci		status =
67962306a36Sopenharmony_ci		    acpi_ut_get_simple_object_size(internal_object, obj_length);
68062306a36Sopenharmony_ci	}
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	return (status);
68362306a36Sopenharmony_ci}
684