xref: /openbmc/linux/drivers/acpi/acpica/nsrepair.c (revision 43420bbb)
1b2deadd5SBob Moore /******************************************************************************
2b2deadd5SBob Moore  *
3b2deadd5SBob Moore  * Module Name: nsrepair - Repair for objects returned by predefined methods
4b2deadd5SBob Moore  *
5b2deadd5SBob Moore  *****************************************************************************/
6b2deadd5SBob Moore 
7b2deadd5SBob Moore /*
8b2deadd5SBob Moore  * Copyright (C) 2000 - 2009, Intel Corp.
9b2deadd5SBob Moore  * All rights reserved.
10b2deadd5SBob Moore  *
11b2deadd5SBob Moore  * Redistribution and use in source and binary forms, with or without
12b2deadd5SBob Moore  * modification, are permitted provided that the following conditions
13b2deadd5SBob Moore  * are met:
14b2deadd5SBob Moore  * 1. Redistributions of source code must retain the above copyright
15b2deadd5SBob Moore  *    notice, this list of conditions, and the following disclaimer,
16b2deadd5SBob Moore  *    without modification.
17b2deadd5SBob Moore  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18b2deadd5SBob Moore  *    substantially similar to the "NO WARRANTY" disclaimer below
19b2deadd5SBob Moore  *    ("Disclaimer") and any redistribution must be conditioned upon
20b2deadd5SBob Moore  *    including a substantially similar Disclaimer requirement for further
21b2deadd5SBob Moore  *    binary redistribution.
22b2deadd5SBob Moore  * 3. Neither the names of the above-listed copyright holders nor the names
23b2deadd5SBob Moore  *    of any contributors may be used to endorse or promote products derived
24b2deadd5SBob Moore  *    from this software without specific prior written permission.
25b2deadd5SBob Moore  *
26b2deadd5SBob Moore  * Alternatively, this software may be distributed under the terms of the
27b2deadd5SBob Moore  * GNU General Public License ("GPL") version 2 as published by the Free
28b2deadd5SBob Moore  * Software Foundation.
29b2deadd5SBob Moore  *
30b2deadd5SBob Moore  * NO WARRANTY
31b2deadd5SBob Moore  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32b2deadd5SBob Moore  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33b2deadd5SBob Moore  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34b2deadd5SBob Moore  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35b2deadd5SBob Moore  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36b2deadd5SBob Moore  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37b2deadd5SBob Moore  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38b2deadd5SBob Moore  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39b2deadd5SBob Moore  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40b2deadd5SBob Moore  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41b2deadd5SBob Moore  * POSSIBILITY OF SUCH DAMAGES.
42b2deadd5SBob Moore  */
43b2deadd5SBob Moore 
44b2deadd5SBob Moore #include <acpi/acpi.h>
45b2deadd5SBob Moore #include "accommon.h"
46b2deadd5SBob Moore #include "acnamesp.h"
470240d7b4SLin Ming #include "acinterp.h"
48b2deadd5SBob Moore 
49b2deadd5SBob Moore #define _COMPONENT          ACPI_NAMESPACE
50b2deadd5SBob Moore ACPI_MODULE_NAME("nsrepair")
51b2deadd5SBob Moore 
52b2deadd5SBob Moore /*******************************************************************************
53b2deadd5SBob Moore  *
5447e11d54SBob Moore  * This module attempts to repair or convert objects returned by the
5547e11d54SBob Moore  * predefined methods to an object type that is expected, as per the ACPI
5647e11d54SBob Moore  * specification. The need for this code is dictated by the many machines that
5747e11d54SBob Moore  * return incorrect types for the standard predefined methods. Performing these
5847e11d54SBob Moore  * conversions here, in one place, eliminates the need for individual ACPI
5947e11d54SBob Moore  * device drivers to do the same. Note: Most of these conversions are different
6047e11d54SBob Moore  * than the internal object conversion routines used for implicit object
6147e11d54SBob Moore  * conversion.
6247e11d54SBob Moore  *
6347e11d54SBob Moore  * The following conversions can be performed as necessary:
6447e11d54SBob Moore  *
6547e11d54SBob Moore  * Integer -> String
6647e11d54SBob Moore  * Integer -> Buffer
6747e11d54SBob Moore  * String  -> Integer
6847e11d54SBob Moore  * String  -> Buffer
6947e11d54SBob Moore  * Buffer  -> Integer
7047e11d54SBob Moore  * Buffer  -> String
7147e11d54SBob Moore  * Buffer  -> Package of Integers
7247e11d54SBob Moore  * Package -> Package of one Package
7347e11d54SBob Moore  *
7447e11d54SBob Moore  ******************************************************************************/
7547e11d54SBob Moore /* Local prototypes */
7647e11d54SBob Moore static acpi_status
7747e11d54SBob Moore acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
7847e11d54SBob Moore 			   union acpi_operand_object **return_object);
7947e11d54SBob Moore 
8047e11d54SBob Moore static acpi_status
8147e11d54SBob Moore acpi_ns_convert_to_string(union acpi_operand_object *original_object,
8247e11d54SBob Moore 			  union acpi_operand_object **return_object);
8347e11d54SBob Moore 
8447e11d54SBob Moore static acpi_status
8547e11d54SBob Moore acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
8647e11d54SBob Moore 			  union acpi_operand_object **return_object);
8747e11d54SBob Moore 
8847e11d54SBob Moore static acpi_status
8947e11d54SBob Moore acpi_ns_convert_to_package(union acpi_operand_object *original_object,
9047e11d54SBob Moore 			   union acpi_operand_object **return_object);
9147e11d54SBob Moore 
9247e11d54SBob Moore /*******************************************************************************
9347e11d54SBob Moore  *
94b2deadd5SBob Moore  * FUNCTION:    acpi_ns_repair_object
95b2deadd5SBob Moore  *
96b2deadd5SBob Moore  * PARAMETERS:  Data                - Pointer to validation data structure
97b2deadd5SBob Moore  *              expected_btypes     - Object types expected
98b2deadd5SBob Moore  *              package_index       - Index of object within parent package (if
99b2deadd5SBob Moore  *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
100b2deadd5SBob Moore  *                                    otherwise)
101b2deadd5SBob Moore  *              return_object_ptr   - Pointer to the object returned from the
102b2deadd5SBob Moore  *                                    evaluation of a method or object
103b2deadd5SBob Moore  *
104b2deadd5SBob Moore  * RETURN:      Status. AE_OK if repair was successful.
105b2deadd5SBob Moore  *
106b2deadd5SBob Moore  * DESCRIPTION: Attempt to repair/convert a return object of a type that was
107b2deadd5SBob Moore  *              not expected.
108b2deadd5SBob Moore  *
109b2deadd5SBob Moore  ******************************************************************************/
11047e11d54SBob Moore 
111b2deadd5SBob Moore acpi_status
112b2deadd5SBob Moore acpi_ns_repair_object(struct acpi_predefined_data *data,
113b2deadd5SBob Moore 		      u32 expected_btypes,
114b2deadd5SBob Moore 		      u32 package_index,
115b2deadd5SBob Moore 		      union acpi_operand_object **return_object_ptr)
116b2deadd5SBob Moore {
117b2deadd5SBob Moore 	union acpi_operand_object *return_object = *return_object_ptr;
118b2deadd5SBob Moore 	union acpi_operand_object *new_object;
1190240d7b4SLin Ming 	acpi_status status;
120b2deadd5SBob Moore 
1213a58176eSBob Moore 	ACPI_FUNCTION_NAME(ns_repair_object);
1223a58176eSBob Moore 
12327526993SBob Moore 	/*
12427526993SBob Moore 	 * At this point, we know that the type of the returned object was not
12527526993SBob Moore 	 * one of the expected types for this predefined name. Attempt to
12647e11d54SBob Moore 	 * repair the object by converting it to one of the expected object
12747e11d54SBob Moore 	 * types for this predefined name.
12827526993SBob Moore 	 */
12947e11d54SBob Moore 	if (expected_btypes & ACPI_RTYPE_INTEGER) {
13047e11d54SBob Moore 		status = acpi_ns_convert_to_integer(return_object, &new_object);
13147e11d54SBob Moore 		if (ACPI_SUCCESS(status)) {
13247e11d54SBob Moore 			goto object_repaired;
133b2deadd5SBob Moore 		}
134b2deadd5SBob Moore 	}
13547e11d54SBob Moore 	if (expected_btypes & ACPI_RTYPE_STRING) {
13647e11d54SBob Moore 		status = acpi_ns_convert_to_string(return_object, &new_object);
13747e11d54SBob Moore 		if (ACPI_SUCCESS(status)) {
13847e11d54SBob Moore 			goto object_repaired;
139b2deadd5SBob Moore 		}
14047e11d54SBob Moore 	}
1410240d7b4SLin Ming 	if (expected_btypes & ACPI_RTYPE_BUFFER) {
14247e11d54SBob Moore 		status = acpi_ns_convert_to_buffer(return_object, &new_object);
14347e11d54SBob Moore 		if (ACPI_SUCCESS(status)) {
14447e11d54SBob Moore 			goto object_repaired;
1450240d7b4SLin Ming 		}
1460240d7b4SLin Ming 	}
14747e11d54SBob Moore 	if (expected_btypes & ACPI_RTYPE_PACKAGE) {
14847e11d54SBob Moore 		status = acpi_ns_convert_to_package(return_object, &new_object);
14947e11d54SBob Moore 		if (ACPI_SUCCESS(status)) {
15047e11d54SBob Moore 			goto object_repaired;
15127526993SBob Moore 		}
15227526993SBob Moore 	}
15327526993SBob Moore 
15427526993SBob Moore 	/* We cannot repair this object */
15527526993SBob Moore 
15627526993SBob Moore 	return (AE_AML_OPERAND_TYPE);
15747e11d54SBob Moore 
15847e11d54SBob Moore       object_repaired:
15927526993SBob Moore 
16027526993SBob Moore 	/* Object was successfully repaired */
161b2deadd5SBob Moore 
162b2deadd5SBob Moore 	/*
163b2deadd5SBob Moore 	 * If the original object is a package element, we need to:
164b2deadd5SBob Moore 	 * 1. Set the reference count of the new object to match the
165b2deadd5SBob Moore 	 *    reference count of the old object.
166b2deadd5SBob Moore 	 * 2. Decrement the reference count of the original object.
167b2deadd5SBob Moore 	 */
168b2deadd5SBob Moore 	if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
169b2deadd5SBob Moore 		new_object->common.reference_count =
170b2deadd5SBob Moore 		    return_object->common.reference_count;
171b2deadd5SBob Moore 
172b2deadd5SBob Moore 		if (return_object->common.reference_count > 1) {
173b2deadd5SBob Moore 			return_object->common.reference_count--;
174b2deadd5SBob Moore 		}
175b2deadd5SBob Moore 
1763a58176eSBob Moore 		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
1773a58176eSBob Moore 				  "%s: Converted %s to expected %s at index %u\n",
1783a58176eSBob Moore 				  data->pathname,
1793a58176eSBob Moore 				  acpi_ut_get_object_type_name(return_object),
18027526993SBob Moore 				  acpi_ut_get_object_type_name(new_object),
181b2deadd5SBob Moore 				  package_index));
182b2deadd5SBob Moore 	} else {
1833a58176eSBob Moore 		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
1843a58176eSBob Moore 				  "%s: Converted %s to expected %s\n",
1853a58176eSBob Moore 				  data->pathname,
1863a58176eSBob Moore 				  acpi_ut_get_object_type_name(return_object),
1873a58176eSBob Moore 				  acpi_ut_get_object_type_name(new_object)));
188b2deadd5SBob Moore 	}
189b2deadd5SBob Moore 
190b2deadd5SBob Moore 	/* Delete old object, install the new return object */
191b2deadd5SBob Moore 
192b2deadd5SBob Moore 	acpi_ut_remove_reference(return_object);
193b2deadd5SBob Moore 	*return_object_ptr = new_object;
194b2deadd5SBob Moore 	data->flags |= ACPI_OBJECT_REPAIRED;
195b2deadd5SBob Moore 	return (AE_OK);
196b2deadd5SBob Moore }
197e5f69d6eSBob Moore 
198e5f69d6eSBob Moore /*******************************************************************************
199e5f69d6eSBob Moore  *
20047e11d54SBob Moore  * FUNCTION:    acpi_ns_convert_to_integer
20147e11d54SBob Moore  *
20247e11d54SBob Moore  * PARAMETERS:  original_object     - Object to be converted
20347e11d54SBob Moore  *              return_object       - Where the new converted object is returned
20447e11d54SBob Moore  *
20547e11d54SBob Moore  * RETURN:      Status. AE_OK if conversion was successful.
20647e11d54SBob Moore  *
20747e11d54SBob Moore  * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
20847e11d54SBob Moore  *
20947e11d54SBob Moore  ******************************************************************************/
21047e11d54SBob Moore 
21147e11d54SBob Moore static acpi_status
21247e11d54SBob Moore acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
21347e11d54SBob Moore 			   union acpi_operand_object **return_object)
21447e11d54SBob Moore {
21547e11d54SBob Moore 	union acpi_operand_object *new_object;
21647e11d54SBob Moore 	acpi_status status;
21747e11d54SBob Moore 	u64 value = 0;
21847e11d54SBob Moore 	u32 i;
21947e11d54SBob Moore 
22047e11d54SBob Moore 	switch (original_object->common.type) {
22147e11d54SBob Moore 	case ACPI_TYPE_STRING:
22247e11d54SBob Moore 
22347e11d54SBob Moore 		/* String-to-Integer conversion */
22447e11d54SBob Moore 
22547e11d54SBob Moore 		status = acpi_ut_strtoul64(original_object->string.pointer,
22647e11d54SBob Moore 					   ACPI_ANY_BASE, &value);
22747e11d54SBob Moore 		if (ACPI_FAILURE(status)) {
22847e11d54SBob Moore 			return (status);
22947e11d54SBob Moore 		}
23047e11d54SBob Moore 		break;
23147e11d54SBob Moore 
23247e11d54SBob Moore 	case ACPI_TYPE_BUFFER:
23347e11d54SBob Moore 
23447e11d54SBob Moore 		/* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
23547e11d54SBob Moore 
23647e11d54SBob Moore 		if (original_object->buffer.length > 8) {
23747e11d54SBob Moore 			return (AE_AML_OPERAND_TYPE);
23847e11d54SBob Moore 		}
23947e11d54SBob Moore 
24047e11d54SBob Moore 		/* Extract each buffer byte to create the integer */
24147e11d54SBob Moore 
24247e11d54SBob Moore 		for (i = 0; i < original_object->buffer.length; i++) {
24347e11d54SBob Moore 			value |=
24447e11d54SBob Moore 			    ((u64) original_object->buffer.
24547e11d54SBob Moore 			     pointer[i] << (i * 8));
24647e11d54SBob Moore 		}
24747e11d54SBob Moore 		break;
24847e11d54SBob Moore 
24947e11d54SBob Moore 	default:
25047e11d54SBob Moore 		return (AE_AML_OPERAND_TYPE);
25147e11d54SBob Moore 	}
25247e11d54SBob Moore 
25347e11d54SBob Moore 	new_object = acpi_ut_create_integer_object(value);
25447e11d54SBob Moore 	if (!new_object) {
25547e11d54SBob Moore 		return (AE_NO_MEMORY);
25647e11d54SBob Moore 	}
25747e11d54SBob Moore 
25847e11d54SBob Moore 	*return_object = new_object;
25947e11d54SBob Moore 	return (AE_OK);
26047e11d54SBob Moore }
26147e11d54SBob Moore 
26247e11d54SBob Moore /*******************************************************************************
26347e11d54SBob Moore  *
26447e11d54SBob Moore  * FUNCTION:    acpi_ns_convert_to_string
26547e11d54SBob Moore  *
26647e11d54SBob Moore  * PARAMETERS:  original_object     - Object to be converted
26747e11d54SBob Moore  *              return_object       - Where the new converted object is returned
26847e11d54SBob Moore  *
26947e11d54SBob Moore  * RETURN:      Status. AE_OK if conversion was successful.
27047e11d54SBob Moore  *
27147e11d54SBob Moore  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
27247e11d54SBob Moore  *
27347e11d54SBob Moore  ******************************************************************************/
27447e11d54SBob Moore 
27547e11d54SBob Moore static acpi_status
27647e11d54SBob Moore acpi_ns_convert_to_string(union acpi_operand_object *original_object,
27747e11d54SBob Moore 			  union acpi_operand_object **return_object)
27847e11d54SBob Moore {
27947e11d54SBob Moore 	union acpi_operand_object *new_object;
28047e11d54SBob Moore 	acpi_size length;
28147e11d54SBob Moore 	acpi_status status;
28247e11d54SBob Moore 
28347e11d54SBob Moore 	switch (original_object->common.type) {
28447e11d54SBob Moore 	case ACPI_TYPE_INTEGER:
28547e11d54SBob Moore 		/*
28647e11d54SBob Moore 		 * Integer-to-String conversion. Commonly, convert
28747e11d54SBob Moore 		 * an integer of value 0 to a NULL string. The last element of
28847e11d54SBob Moore 		 * _BIF and _BIX packages occasionally need this fix.
28947e11d54SBob Moore 		 */
29047e11d54SBob Moore 		if (original_object->integer.value == 0) {
29147e11d54SBob Moore 
29247e11d54SBob Moore 			/* Allocate a new NULL string object */
29347e11d54SBob Moore 
29447e11d54SBob Moore 			new_object = acpi_ut_create_string_object(0);
29547e11d54SBob Moore 			if (!new_object) {
29647e11d54SBob Moore 				return (AE_NO_MEMORY);
29747e11d54SBob Moore 			}
29847e11d54SBob Moore 		} else {
29947e11d54SBob Moore 			status =
30047e11d54SBob Moore 			    acpi_ex_convert_to_string(original_object,
30147e11d54SBob Moore 						      &new_object,
30247e11d54SBob Moore 						      ACPI_IMPLICIT_CONVERT_HEX);
30347e11d54SBob Moore 			if (ACPI_FAILURE(status)) {
30447e11d54SBob Moore 				return (status);
30547e11d54SBob Moore 			}
30647e11d54SBob Moore 		}
30747e11d54SBob Moore 		break;
30847e11d54SBob Moore 
30947e11d54SBob Moore 	case ACPI_TYPE_BUFFER:
31047e11d54SBob Moore 		/*
31147e11d54SBob Moore 		 * Buffer-to-String conversion. Use a to_string
31247e11d54SBob Moore 		 * conversion, no transform performed on the buffer data. The best
31347e11d54SBob Moore 		 * example of this is the _BIF method, where the string data from
31447e11d54SBob Moore 		 * the battery is often (incorrectly) returned as buffer object(s).
31547e11d54SBob Moore 		 */
31647e11d54SBob Moore 		length = 0;
31747e11d54SBob Moore 		while ((length < original_object->buffer.length) &&
31847e11d54SBob Moore 		       (original_object->buffer.pointer[length])) {
31947e11d54SBob Moore 			length++;
32047e11d54SBob Moore 		}
32147e11d54SBob Moore 
32247e11d54SBob Moore 		/* Allocate a new string object */
32347e11d54SBob Moore 
32447e11d54SBob Moore 		new_object = acpi_ut_create_string_object(length);
32547e11d54SBob Moore 		if (!new_object) {
32647e11d54SBob Moore 			return (AE_NO_MEMORY);
32747e11d54SBob Moore 		}
32847e11d54SBob Moore 
32947e11d54SBob Moore 		/*
33047e11d54SBob Moore 		 * Copy the raw buffer data with no transform. String is already NULL
33147e11d54SBob Moore 		 * terminated at Length+1.
33247e11d54SBob Moore 		 */
33347e11d54SBob Moore 		ACPI_MEMCPY(new_object->string.pointer,
33447e11d54SBob Moore 			    original_object->buffer.pointer, length);
33547e11d54SBob Moore 		break;
33647e11d54SBob Moore 
33747e11d54SBob Moore 	default:
33847e11d54SBob Moore 		return (AE_AML_OPERAND_TYPE);
33947e11d54SBob Moore 	}
34047e11d54SBob Moore 
34147e11d54SBob Moore 	*return_object = new_object;
34247e11d54SBob Moore 	return (AE_OK);
34347e11d54SBob Moore }
34447e11d54SBob Moore 
34547e11d54SBob Moore /*******************************************************************************
34647e11d54SBob Moore  *
34747e11d54SBob Moore  * FUNCTION:    acpi_ns_convert_to_buffer
34847e11d54SBob Moore  *
34947e11d54SBob Moore  * PARAMETERS:  original_object     - Object to be converted
35047e11d54SBob Moore  *              return_object       - Where the new converted object is returned
35147e11d54SBob Moore  *
35247e11d54SBob Moore  * RETURN:      Status. AE_OK if conversion was successful.
35347e11d54SBob Moore  *
354ea7c5ec1SBob Moore  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
35547e11d54SBob Moore  *
35647e11d54SBob Moore  ******************************************************************************/
35747e11d54SBob Moore 
35847e11d54SBob Moore static acpi_status
35947e11d54SBob Moore acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
36047e11d54SBob Moore 			  union acpi_operand_object **return_object)
36147e11d54SBob Moore {
36247e11d54SBob Moore 	union acpi_operand_object *new_object;
36347e11d54SBob Moore 	acpi_status status;
364ea7c5ec1SBob Moore 	union acpi_operand_object **elements;
365ea7c5ec1SBob Moore 	u32 *dword_buffer;
366ea7c5ec1SBob Moore 	u32 count;
367ea7c5ec1SBob Moore 	u32 i;
36847e11d54SBob Moore 
36947e11d54SBob Moore 	switch (original_object->common.type) {
37047e11d54SBob Moore 	case ACPI_TYPE_INTEGER:
37147e11d54SBob Moore 		/*
37247e11d54SBob Moore 		 * Integer-to-Buffer conversion.
37347e11d54SBob Moore 		 * Convert the Integer to a packed-byte buffer. _MAT and other
37447e11d54SBob Moore 		 * objects need this sometimes, if a read has been performed on a
37547e11d54SBob Moore 		 * Field object that is less than or equal to the global integer
37647e11d54SBob Moore 		 * size (32 or 64 bits).
37747e11d54SBob Moore 		 */
37847e11d54SBob Moore 		status =
37947e11d54SBob Moore 		    acpi_ex_convert_to_buffer(original_object, &new_object);
38047e11d54SBob Moore 		if (ACPI_FAILURE(status)) {
38147e11d54SBob Moore 			return (status);
38247e11d54SBob Moore 		}
38347e11d54SBob Moore 		break;
38447e11d54SBob Moore 
38547e11d54SBob Moore 	case ACPI_TYPE_STRING:
38647e11d54SBob Moore 
38747e11d54SBob Moore 		/* String-to-Buffer conversion. Simple data copy */
38847e11d54SBob Moore 
38947e11d54SBob Moore 		new_object =
39047e11d54SBob Moore 		    acpi_ut_create_buffer_object(original_object->string.
39147e11d54SBob Moore 						 length);
39247e11d54SBob Moore 		if (!new_object) {
39347e11d54SBob Moore 			return (AE_NO_MEMORY);
39447e11d54SBob Moore 		}
39547e11d54SBob Moore 
39647e11d54SBob Moore 		ACPI_MEMCPY(new_object->buffer.pointer,
39747e11d54SBob Moore 			    original_object->string.pointer,
39847e11d54SBob Moore 			    original_object->string.length);
39947e11d54SBob Moore 		break;
40047e11d54SBob Moore 
401ea7c5ec1SBob Moore 	case ACPI_TYPE_PACKAGE:
40243420bbbSBob Moore 		/*
40343420bbbSBob Moore 		 * This case is often seen for predefined names that must return a
40443420bbbSBob Moore 		 * Buffer object with multiple DWORD integers within. For example,
40543420bbbSBob Moore 		 * _FDE and _GTM. The Package can be converted to a Buffer.
40643420bbbSBob Moore 		 */
407ea7c5ec1SBob Moore 
408ea7c5ec1SBob Moore 		/* All elements of the Package must be integers */
409ea7c5ec1SBob Moore 
410ea7c5ec1SBob Moore 		elements = original_object->package.elements;
411ea7c5ec1SBob Moore 		count = original_object->package.count;
412ea7c5ec1SBob Moore 
413ea7c5ec1SBob Moore 		for (i = 0; i < count; i++) {
414ea7c5ec1SBob Moore 			if ((!*elements) ||
415ea7c5ec1SBob Moore 			    ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
416ea7c5ec1SBob Moore 				return (AE_AML_OPERAND_TYPE);
417ea7c5ec1SBob Moore 			}
418ea7c5ec1SBob Moore 			elements++;
419ea7c5ec1SBob Moore 		}
420ea7c5ec1SBob Moore 
421ea7c5ec1SBob Moore 		/* Create the new buffer object to replace the Package */
422ea7c5ec1SBob Moore 
423ea7c5ec1SBob Moore 		new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
424ea7c5ec1SBob Moore 		if (!new_object) {
425ea7c5ec1SBob Moore 			return (AE_NO_MEMORY);
426ea7c5ec1SBob Moore 		}
427ea7c5ec1SBob Moore 
428ea7c5ec1SBob Moore 		/* Copy the package elements (integers) to the buffer as DWORDs */
429ea7c5ec1SBob Moore 
430ea7c5ec1SBob Moore 		elements = original_object->package.elements;
431ea7c5ec1SBob Moore 		dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
432ea7c5ec1SBob Moore 
433ea7c5ec1SBob Moore 		for (i = 0; i < count; i++) {
434ea7c5ec1SBob Moore 			*dword_buffer = (u32) (*elements)->integer.value;
435ea7c5ec1SBob Moore 			dword_buffer++;
436ea7c5ec1SBob Moore 			elements++;
437ea7c5ec1SBob Moore 		}
438ea7c5ec1SBob Moore 		break;
439ea7c5ec1SBob Moore 
44047e11d54SBob Moore 	default:
44147e11d54SBob Moore 		return (AE_AML_OPERAND_TYPE);
44247e11d54SBob Moore 	}
44347e11d54SBob Moore 
44447e11d54SBob Moore 	*return_object = new_object;
44547e11d54SBob Moore 	return (AE_OK);
44647e11d54SBob Moore }
44747e11d54SBob Moore 
44847e11d54SBob Moore /*******************************************************************************
44947e11d54SBob Moore  *
45047e11d54SBob Moore  * FUNCTION:    acpi_ns_convert_to_package
45147e11d54SBob Moore  *
45247e11d54SBob Moore  * PARAMETERS:  original_object     - Object to be converted
45347e11d54SBob Moore  *              return_object       - Where the new converted object is returned
45447e11d54SBob Moore  *
45547e11d54SBob Moore  * RETURN:      Status. AE_OK if conversion was successful.
45647e11d54SBob Moore  *
45747e11d54SBob Moore  * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of
45847e11d54SBob Moore  *              the buffer is converted to a single integer package element.
45947e11d54SBob Moore  *
46047e11d54SBob Moore  ******************************************************************************/
46147e11d54SBob Moore 
46247e11d54SBob Moore static acpi_status
46347e11d54SBob Moore acpi_ns_convert_to_package(union acpi_operand_object *original_object,
46447e11d54SBob Moore 			   union acpi_operand_object **return_object)
46547e11d54SBob Moore {
46647e11d54SBob Moore 	union acpi_operand_object *new_object;
46747e11d54SBob Moore 	union acpi_operand_object **elements;
46847e11d54SBob Moore 	u32 length;
46947e11d54SBob Moore 	u8 *buffer;
47047e11d54SBob Moore 
47147e11d54SBob Moore 	switch (original_object->common.type) {
47247e11d54SBob Moore 	case ACPI_TYPE_BUFFER:
47347e11d54SBob Moore 
47447e11d54SBob Moore 		/* Buffer-to-Package conversion */
47547e11d54SBob Moore 
47647e11d54SBob Moore 		length = original_object->buffer.length;
47747e11d54SBob Moore 		new_object = acpi_ut_create_package_object(length);
47847e11d54SBob Moore 		if (!new_object) {
47947e11d54SBob Moore 			return (AE_NO_MEMORY);
48047e11d54SBob Moore 		}
48147e11d54SBob Moore 
48247e11d54SBob Moore 		/* Convert each buffer byte to an integer package element */
48347e11d54SBob Moore 
48447e11d54SBob Moore 		elements = new_object->package.elements;
48547e11d54SBob Moore 		buffer = original_object->buffer.pointer;
48647e11d54SBob Moore 
48747e11d54SBob Moore 		while (length--) {
488ea7c5ec1SBob Moore 			*elements =
489ea7c5ec1SBob Moore 			    acpi_ut_create_integer_object((u64) *buffer);
49047e11d54SBob Moore 			if (!*elements) {
49147e11d54SBob Moore 				acpi_ut_remove_reference(new_object);
49247e11d54SBob Moore 				return (AE_NO_MEMORY);
49347e11d54SBob Moore 			}
49447e11d54SBob Moore 			elements++;
49547e11d54SBob Moore 			buffer++;
49647e11d54SBob Moore 		}
49747e11d54SBob Moore 		break;
49847e11d54SBob Moore 
49947e11d54SBob Moore 	default:
50047e11d54SBob Moore 		return (AE_AML_OPERAND_TYPE);
50147e11d54SBob Moore 	}
50247e11d54SBob Moore 
50347e11d54SBob Moore 	*return_object = new_object;
50447e11d54SBob Moore 	return (AE_OK);
50547e11d54SBob Moore }
50647e11d54SBob Moore 
50747e11d54SBob Moore /*******************************************************************************
50847e11d54SBob Moore  *
509e5f69d6eSBob Moore  * FUNCTION:    acpi_ns_repair_package_list
510e5f69d6eSBob Moore  *
511e5f69d6eSBob Moore  * PARAMETERS:  Data                - Pointer to validation data structure
512e5f69d6eSBob Moore  *              obj_desc_ptr        - Pointer to the object to repair. The new
513e5f69d6eSBob Moore  *                                    package object is returned here,
514e5f69d6eSBob Moore  *                                    overwriting the old object.
515e5f69d6eSBob Moore  *
516e5f69d6eSBob Moore  * RETURN:      Status, new object in *obj_desc_ptr
517e5f69d6eSBob Moore  *
518e5f69d6eSBob Moore  * DESCRIPTION: Repair a common problem with objects that are defined to return
519e5f69d6eSBob Moore  *              a variable-length Package of Packages. If the variable-length
520e5f69d6eSBob Moore  *              is one, some BIOS code mistakenly simply declares a single
521e5f69d6eSBob Moore  *              Package instead of a Package with one sub-Package. This
522e5f69d6eSBob Moore  *              function attempts to repair this error by wrapping a Package
523e5f69d6eSBob Moore  *              object around the original Package, creating the correct
524e5f69d6eSBob Moore  *              Package with one sub-Package.
525e5f69d6eSBob Moore  *
526e5f69d6eSBob Moore  *              Names that can be repaired in this manner include:
527e5f69d6eSBob Moore  *              _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS
528e5f69d6eSBob Moore  *
529e5f69d6eSBob Moore  ******************************************************************************/
530e5f69d6eSBob Moore 
531e5f69d6eSBob Moore acpi_status
532e5f69d6eSBob Moore acpi_ns_repair_package_list(struct acpi_predefined_data *data,
533e5f69d6eSBob Moore 			    union acpi_operand_object **obj_desc_ptr)
534e5f69d6eSBob Moore {
535e5f69d6eSBob Moore 	union acpi_operand_object *pkg_obj_desc;
536e5f69d6eSBob Moore 
5373a58176eSBob Moore 	ACPI_FUNCTION_NAME(ns_repair_package_list);
5383a58176eSBob Moore 
539e5f69d6eSBob Moore 	/*
540e5f69d6eSBob Moore 	 * Create the new outer package and populate it. The new package will
541e5f69d6eSBob Moore 	 * have a single element, the lone subpackage.
542e5f69d6eSBob Moore 	 */
543e5f69d6eSBob Moore 	pkg_obj_desc = acpi_ut_create_package_object(1);
544e5f69d6eSBob Moore 	if (!pkg_obj_desc) {
545e5f69d6eSBob Moore 		return (AE_NO_MEMORY);
546e5f69d6eSBob Moore 	}
547e5f69d6eSBob Moore 
548e5f69d6eSBob Moore 	pkg_obj_desc->package.elements[0] = *obj_desc_ptr;
549e5f69d6eSBob Moore 
550e5f69d6eSBob Moore 	/* Return the new object in the object pointer */
551e5f69d6eSBob Moore 
552e5f69d6eSBob Moore 	*obj_desc_ptr = pkg_obj_desc;
553e5f69d6eSBob Moore 	data->flags |= ACPI_OBJECT_REPAIRED;
554e5f69d6eSBob Moore 
5553a58176eSBob Moore 	ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
5563a58176eSBob Moore 			  "%s: Repaired incorrectly formed Package\n",
5573a58176eSBob Moore 			  data->pathname));
558e5f69d6eSBob Moore 
559e5f69d6eSBob Moore 	return (AE_OK);
560e5f69d6eSBob Moore }
561