xref: /openbmc/linux/drivers/acpi/acpica/nsrepair.c (revision ea7c5ec1)
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 
12127526993SBob Moore 	/*
12227526993SBob Moore 	 * At this point, we know that the type of the returned object was not
12327526993SBob Moore 	 * one of the expected types for this predefined name. Attempt to
12447e11d54SBob Moore 	 * repair the object by converting it to one of the expected object
12547e11d54SBob Moore 	 * types for this predefined name.
12627526993SBob Moore 	 */
12747e11d54SBob Moore 	if (expected_btypes & ACPI_RTYPE_INTEGER) {
12847e11d54SBob Moore 		status = acpi_ns_convert_to_integer(return_object, &new_object);
12947e11d54SBob Moore 		if (ACPI_SUCCESS(status)) {
13047e11d54SBob Moore 			goto object_repaired;
131b2deadd5SBob Moore 		}
132b2deadd5SBob Moore 	}
13347e11d54SBob Moore 	if (expected_btypes & ACPI_RTYPE_STRING) {
13447e11d54SBob Moore 		status = acpi_ns_convert_to_string(return_object, &new_object);
13547e11d54SBob Moore 		if (ACPI_SUCCESS(status)) {
13647e11d54SBob Moore 			goto object_repaired;
137b2deadd5SBob Moore 		}
13847e11d54SBob Moore 	}
1390240d7b4SLin Ming 	if (expected_btypes & ACPI_RTYPE_BUFFER) {
14047e11d54SBob Moore 		status = acpi_ns_convert_to_buffer(return_object, &new_object);
14147e11d54SBob Moore 		if (ACPI_SUCCESS(status)) {
14247e11d54SBob Moore 			goto object_repaired;
1430240d7b4SLin Ming 		}
1440240d7b4SLin Ming 	}
14547e11d54SBob Moore 	if (expected_btypes & ACPI_RTYPE_PACKAGE) {
14647e11d54SBob Moore 		status = acpi_ns_convert_to_package(return_object, &new_object);
14747e11d54SBob Moore 		if (ACPI_SUCCESS(status)) {
14847e11d54SBob Moore 			goto object_repaired;
14927526993SBob Moore 		}
15027526993SBob Moore 	}
15127526993SBob Moore 
15227526993SBob Moore 	/* We cannot repair this object */
15327526993SBob Moore 
15427526993SBob Moore 	return (AE_AML_OPERAND_TYPE);
15547e11d54SBob Moore 
15647e11d54SBob Moore       object_repaired:
15727526993SBob Moore 
15827526993SBob Moore 	/* Object was successfully repaired */
159b2deadd5SBob Moore 
160b2deadd5SBob Moore 	/*
161b2deadd5SBob Moore 	 * If the original object is a package element, we need to:
162b2deadd5SBob Moore 	 * 1. Set the reference count of the new object to match the
163b2deadd5SBob Moore 	 *    reference count of the old object.
164b2deadd5SBob Moore 	 * 2. Decrement the reference count of the original object.
165b2deadd5SBob Moore 	 */
166b2deadd5SBob Moore 	if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
167b2deadd5SBob Moore 		new_object->common.reference_count =
168b2deadd5SBob Moore 		    return_object->common.reference_count;
169b2deadd5SBob Moore 
170b2deadd5SBob Moore 		if (return_object->common.reference_count > 1) {
171b2deadd5SBob Moore 			return_object->common.reference_count--;
172b2deadd5SBob Moore 		}
173b2deadd5SBob Moore 
1747df200cdSBob Moore 		ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
17527526993SBob Moore 				      "Converted %s to expected %s at index %u",
17627526993SBob Moore 				      acpi_ut_get_object_type_name
17727526993SBob Moore 				      (return_object),
17827526993SBob Moore 				      acpi_ut_get_object_type_name(new_object),
179b2deadd5SBob Moore 				      package_index));
180b2deadd5SBob Moore 	} else {
1817df200cdSBob Moore 		ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
18227526993SBob Moore 				      "Converted %s to expected %s",
18327526993SBob Moore 				      acpi_ut_get_object_type_name
18427526993SBob Moore 				      (return_object),
18527526993SBob Moore 				      acpi_ut_get_object_type_name
18627526993SBob Moore 				      (new_object)));
187b2deadd5SBob Moore 	}
188b2deadd5SBob Moore 
189b2deadd5SBob Moore 	/* Delete old object, install the new return object */
190b2deadd5SBob Moore 
191b2deadd5SBob Moore 	acpi_ut_remove_reference(return_object);
192b2deadd5SBob Moore 	*return_object_ptr = new_object;
193b2deadd5SBob Moore 	data->flags |= ACPI_OBJECT_REPAIRED;
194b2deadd5SBob Moore 	return (AE_OK);
195b2deadd5SBob Moore }
196e5f69d6eSBob Moore 
197e5f69d6eSBob Moore /*******************************************************************************
198e5f69d6eSBob Moore  *
19947e11d54SBob Moore  * FUNCTION:    acpi_ns_convert_to_integer
20047e11d54SBob Moore  *
20147e11d54SBob Moore  * PARAMETERS:  original_object     - Object to be converted
20247e11d54SBob Moore  *              return_object       - Where the new converted object is returned
20347e11d54SBob Moore  *
20447e11d54SBob Moore  * RETURN:      Status. AE_OK if conversion was successful.
20547e11d54SBob Moore  *
20647e11d54SBob Moore  * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
20747e11d54SBob Moore  *
20847e11d54SBob Moore  ******************************************************************************/
20947e11d54SBob Moore 
21047e11d54SBob Moore static acpi_status
21147e11d54SBob Moore acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
21247e11d54SBob Moore 			   union acpi_operand_object **return_object)
21347e11d54SBob Moore {
21447e11d54SBob Moore 	union acpi_operand_object *new_object;
21547e11d54SBob Moore 	acpi_status status;
21647e11d54SBob Moore 	u64 value = 0;
21747e11d54SBob Moore 	u32 i;
21847e11d54SBob Moore 
21947e11d54SBob Moore 	switch (original_object->common.type) {
22047e11d54SBob Moore 	case ACPI_TYPE_STRING:
22147e11d54SBob Moore 
22247e11d54SBob Moore 		/* String-to-Integer conversion */
22347e11d54SBob Moore 
22447e11d54SBob Moore 		status = acpi_ut_strtoul64(original_object->string.pointer,
22547e11d54SBob Moore 					   ACPI_ANY_BASE, &value);
22647e11d54SBob Moore 		if (ACPI_FAILURE(status)) {
22747e11d54SBob Moore 			return (status);
22847e11d54SBob Moore 		}
22947e11d54SBob Moore 		break;
23047e11d54SBob Moore 
23147e11d54SBob Moore 	case ACPI_TYPE_BUFFER:
23247e11d54SBob Moore 
23347e11d54SBob Moore 		/* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
23447e11d54SBob Moore 
23547e11d54SBob Moore 		if (original_object->buffer.length > 8) {
23647e11d54SBob Moore 			return (AE_AML_OPERAND_TYPE);
23747e11d54SBob Moore 		}
23847e11d54SBob Moore 
23947e11d54SBob Moore 		/* Extract each buffer byte to create the integer */
24047e11d54SBob Moore 
24147e11d54SBob Moore 		for (i = 0; i < original_object->buffer.length; i++) {
24247e11d54SBob Moore 			value |=
24347e11d54SBob Moore 			    ((u64) original_object->buffer.
24447e11d54SBob Moore 			     pointer[i] << (i * 8));
24547e11d54SBob Moore 		}
24647e11d54SBob Moore 		break;
24747e11d54SBob Moore 
24847e11d54SBob Moore 	default:
24947e11d54SBob Moore 		return (AE_AML_OPERAND_TYPE);
25047e11d54SBob Moore 	}
25147e11d54SBob Moore 
25247e11d54SBob Moore 	new_object = acpi_ut_create_integer_object(value);
25347e11d54SBob Moore 	if (!new_object) {
25447e11d54SBob Moore 		return (AE_NO_MEMORY);
25547e11d54SBob Moore 	}
25647e11d54SBob Moore 
25747e11d54SBob Moore 	*return_object = new_object;
25847e11d54SBob Moore 	return (AE_OK);
25947e11d54SBob Moore }
26047e11d54SBob Moore 
26147e11d54SBob Moore /*******************************************************************************
26247e11d54SBob Moore  *
26347e11d54SBob Moore  * FUNCTION:    acpi_ns_convert_to_string
26447e11d54SBob Moore  *
26547e11d54SBob Moore  * PARAMETERS:  original_object     - Object to be converted
26647e11d54SBob Moore  *              return_object       - Where the new converted object is returned
26747e11d54SBob Moore  *
26847e11d54SBob Moore  * RETURN:      Status. AE_OK if conversion was successful.
26947e11d54SBob Moore  *
27047e11d54SBob Moore  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
27147e11d54SBob Moore  *
27247e11d54SBob Moore  ******************************************************************************/
27347e11d54SBob Moore 
27447e11d54SBob Moore static acpi_status
27547e11d54SBob Moore acpi_ns_convert_to_string(union acpi_operand_object *original_object,
27647e11d54SBob Moore 			  union acpi_operand_object **return_object)
27747e11d54SBob Moore {
27847e11d54SBob Moore 	union acpi_operand_object *new_object;
27947e11d54SBob Moore 	acpi_size length;
28047e11d54SBob Moore 	acpi_status status;
28147e11d54SBob Moore 
28247e11d54SBob Moore 	switch (original_object->common.type) {
28347e11d54SBob Moore 	case ACPI_TYPE_INTEGER:
28447e11d54SBob Moore 		/*
28547e11d54SBob Moore 		 * Integer-to-String conversion. Commonly, convert
28647e11d54SBob Moore 		 * an integer of value 0 to a NULL string. The last element of
28747e11d54SBob Moore 		 * _BIF and _BIX packages occasionally need this fix.
28847e11d54SBob Moore 		 */
28947e11d54SBob Moore 		if (original_object->integer.value == 0) {
29047e11d54SBob Moore 
29147e11d54SBob Moore 			/* Allocate a new NULL string object */
29247e11d54SBob Moore 
29347e11d54SBob Moore 			new_object = acpi_ut_create_string_object(0);
29447e11d54SBob Moore 			if (!new_object) {
29547e11d54SBob Moore 				return (AE_NO_MEMORY);
29647e11d54SBob Moore 			}
29747e11d54SBob Moore 		} else {
29847e11d54SBob Moore 			status =
29947e11d54SBob Moore 			    acpi_ex_convert_to_string(original_object,
30047e11d54SBob Moore 						      &new_object,
30147e11d54SBob Moore 						      ACPI_IMPLICIT_CONVERT_HEX);
30247e11d54SBob Moore 			if (ACPI_FAILURE(status)) {
30347e11d54SBob Moore 				return (status);
30447e11d54SBob Moore 			}
30547e11d54SBob Moore 		}
30647e11d54SBob Moore 		break;
30747e11d54SBob Moore 
30847e11d54SBob Moore 	case ACPI_TYPE_BUFFER:
30947e11d54SBob Moore 		/*
31047e11d54SBob Moore 		 * Buffer-to-String conversion. Use a to_string
31147e11d54SBob Moore 		 * conversion, no transform performed on the buffer data. The best
31247e11d54SBob Moore 		 * example of this is the _BIF method, where the string data from
31347e11d54SBob Moore 		 * the battery is often (incorrectly) returned as buffer object(s).
31447e11d54SBob Moore 		 */
31547e11d54SBob Moore 		length = 0;
31647e11d54SBob Moore 		while ((length < original_object->buffer.length) &&
31747e11d54SBob Moore 		       (original_object->buffer.pointer[length])) {
31847e11d54SBob Moore 			length++;
31947e11d54SBob Moore 		}
32047e11d54SBob Moore 
32147e11d54SBob Moore 		/* Allocate a new string object */
32247e11d54SBob Moore 
32347e11d54SBob Moore 		new_object = acpi_ut_create_string_object(length);
32447e11d54SBob Moore 		if (!new_object) {
32547e11d54SBob Moore 			return (AE_NO_MEMORY);
32647e11d54SBob Moore 		}
32747e11d54SBob Moore 
32847e11d54SBob Moore 		/*
32947e11d54SBob Moore 		 * Copy the raw buffer data with no transform. String is already NULL
33047e11d54SBob Moore 		 * terminated at Length+1.
33147e11d54SBob Moore 		 */
33247e11d54SBob Moore 		ACPI_MEMCPY(new_object->string.pointer,
33347e11d54SBob Moore 			    original_object->buffer.pointer, length);
33447e11d54SBob Moore 		break;
33547e11d54SBob Moore 
33647e11d54SBob Moore 	default:
33747e11d54SBob Moore 		return (AE_AML_OPERAND_TYPE);
33847e11d54SBob Moore 	}
33947e11d54SBob Moore 
34047e11d54SBob Moore 	*return_object = new_object;
34147e11d54SBob Moore 	return (AE_OK);
34247e11d54SBob Moore }
34347e11d54SBob Moore 
34447e11d54SBob Moore /*******************************************************************************
34547e11d54SBob Moore  *
34647e11d54SBob Moore  * FUNCTION:    acpi_ns_convert_to_buffer
34747e11d54SBob Moore  *
34847e11d54SBob Moore  * PARAMETERS:  original_object     - Object to be converted
34947e11d54SBob Moore  *              return_object       - Where the new converted object is returned
35047e11d54SBob Moore  *
35147e11d54SBob Moore  * RETURN:      Status. AE_OK if conversion was successful.
35247e11d54SBob Moore  *
353ea7c5ec1SBob Moore  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
35447e11d54SBob Moore  *
35547e11d54SBob Moore  ******************************************************************************/
35647e11d54SBob Moore 
35747e11d54SBob Moore static acpi_status
35847e11d54SBob Moore acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
35947e11d54SBob Moore 			  union acpi_operand_object **return_object)
36047e11d54SBob Moore {
36147e11d54SBob Moore 	union acpi_operand_object *new_object;
36247e11d54SBob Moore 	acpi_status status;
363ea7c5ec1SBob Moore 	union acpi_operand_object **elements;
364ea7c5ec1SBob Moore 	u32 *dword_buffer;
365ea7c5ec1SBob Moore 	u32 count;
366ea7c5ec1SBob Moore 	u32 i;
36747e11d54SBob Moore 
36847e11d54SBob Moore 	switch (original_object->common.type) {
36947e11d54SBob Moore 	case ACPI_TYPE_INTEGER:
37047e11d54SBob Moore 		/*
37147e11d54SBob Moore 		 * Integer-to-Buffer conversion.
37247e11d54SBob Moore 		 * Convert the Integer to a packed-byte buffer. _MAT and other
37347e11d54SBob Moore 		 * objects need this sometimes, if a read has been performed on a
37447e11d54SBob Moore 		 * Field object that is less than or equal to the global integer
37547e11d54SBob Moore 		 * size (32 or 64 bits).
37647e11d54SBob Moore 		 */
37747e11d54SBob Moore 		status =
37847e11d54SBob Moore 		    acpi_ex_convert_to_buffer(original_object, &new_object);
37947e11d54SBob Moore 		if (ACPI_FAILURE(status)) {
38047e11d54SBob Moore 			return (status);
38147e11d54SBob Moore 		}
38247e11d54SBob Moore 		break;
38347e11d54SBob Moore 
38447e11d54SBob Moore 	case ACPI_TYPE_STRING:
38547e11d54SBob Moore 
38647e11d54SBob Moore 		/* String-to-Buffer conversion. Simple data copy */
38747e11d54SBob Moore 
38847e11d54SBob Moore 		new_object =
38947e11d54SBob Moore 		    acpi_ut_create_buffer_object(original_object->string.
39047e11d54SBob Moore 						 length);
39147e11d54SBob Moore 		if (!new_object) {
39247e11d54SBob Moore 			return (AE_NO_MEMORY);
39347e11d54SBob Moore 		}
39447e11d54SBob Moore 
39547e11d54SBob Moore 		ACPI_MEMCPY(new_object->buffer.pointer,
39647e11d54SBob Moore 			    original_object->string.pointer,
39747e11d54SBob Moore 			    original_object->string.length);
39847e11d54SBob Moore 		break;
39947e11d54SBob Moore 
400ea7c5ec1SBob Moore 	case ACPI_TYPE_PACKAGE:
401ea7c5ec1SBob Moore 
402ea7c5ec1SBob Moore 		/* All elements of the Package must be integers */
403ea7c5ec1SBob Moore 
404ea7c5ec1SBob Moore 		elements = original_object->package.elements;
405ea7c5ec1SBob Moore 		count = original_object->package.count;
406ea7c5ec1SBob Moore 
407ea7c5ec1SBob Moore 		for (i = 0; i < count; i++) {
408ea7c5ec1SBob Moore 			if ((!*elements) ||
409ea7c5ec1SBob Moore 			    ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
410ea7c5ec1SBob Moore 				return (AE_AML_OPERAND_TYPE);
411ea7c5ec1SBob Moore 			}
412ea7c5ec1SBob Moore 			elements++;
413ea7c5ec1SBob Moore 		}
414ea7c5ec1SBob Moore 
415ea7c5ec1SBob Moore 		/* Create the new buffer object to replace the Package */
416ea7c5ec1SBob Moore 
417ea7c5ec1SBob Moore 		new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
418ea7c5ec1SBob Moore 		if (!new_object) {
419ea7c5ec1SBob Moore 			return (AE_NO_MEMORY);
420ea7c5ec1SBob Moore 		}
421ea7c5ec1SBob Moore 
422ea7c5ec1SBob Moore 		/* Copy the package elements (integers) to the buffer as DWORDs */
423ea7c5ec1SBob Moore 
424ea7c5ec1SBob Moore 		elements = original_object->package.elements;
425ea7c5ec1SBob Moore 		dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
426ea7c5ec1SBob Moore 
427ea7c5ec1SBob Moore 		for (i = 0; i < count; i++) {
428ea7c5ec1SBob Moore 			*dword_buffer = (u32) (*elements)->integer.value;
429ea7c5ec1SBob Moore 			dword_buffer++;
430ea7c5ec1SBob Moore 			elements++;
431ea7c5ec1SBob Moore 		}
432ea7c5ec1SBob Moore 		break;
433ea7c5ec1SBob Moore 
43447e11d54SBob Moore 	default:
43547e11d54SBob Moore 		return (AE_AML_OPERAND_TYPE);
43647e11d54SBob Moore 	}
43747e11d54SBob Moore 
43847e11d54SBob Moore 	*return_object = new_object;
43947e11d54SBob Moore 	return (AE_OK);
44047e11d54SBob Moore }
44147e11d54SBob Moore 
44247e11d54SBob Moore /*******************************************************************************
44347e11d54SBob Moore  *
44447e11d54SBob Moore  * FUNCTION:    acpi_ns_convert_to_package
44547e11d54SBob Moore  *
44647e11d54SBob Moore  * PARAMETERS:  original_object     - Object to be converted
44747e11d54SBob Moore  *              return_object       - Where the new converted object is returned
44847e11d54SBob Moore  *
44947e11d54SBob Moore  * RETURN:      Status. AE_OK if conversion was successful.
45047e11d54SBob Moore  *
45147e11d54SBob Moore  * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of
45247e11d54SBob Moore  *              the buffer is converted to a single integer package element.
45347e11d54SBob Moore  *
45447e11d54SBob Moore  ******************************************************************************/
45547e11d54SBob Moore 
45647e11d54SBob Moore static acpi_status
45747e11d54SBob Moore acpi_ns_convert_to_package(union acpi_operand_object *original_object,
45847e11d54SBob Moore 			   union acpi_operand_object **return_object)
45947e11d54SBob Moore {
46047e11d54SBob Moore 	union acpi_operand_object *new_object;
46147e11d54SBob Moore 	union acpi_operand_object **elements;
46247e11d54SBob Moore 	u32 length;
46347e11d54SBob Moore 	u8 *buffer;
46447e11d54SBob Moore 
46547e11d54SBob Moore 	switch (original_object->common.type) {
46647e11d54SBob Moore 	case ACPI_TYPE_BUFFER:
46747e11d54SBob Moore 
46847e11d54SBob Moore 		/* Buffer-to-Package conversion */
46947e11d54SBob Moore 
47047e11d54SBob Moore 		length = original_object->buffer.length;
47147e11d54SBob Moore 		new_object = acpi_ut_create_package_object(length);
47247e11d54SBob Moore 		if (!new_object) {
47347e11d54SBob Moore 			return (AE_NO_MEMORY);
47447e11d54SBob Moore 		}
47547e11d54SBob Moore 
47647e11d54SBob Moore 		/* Convert each buffer byte to an integer package element */
47747e11d54SBob Moore 
47847e11d54SBob Moore 		elements = new_object->package.elements;
47947e11d54SBob Moore 		buffer = original_object->buffer.pointer;
48047e11d54SBob Moore 
48147e11d54SBob Moore 		while (length--) {
482ea7c5ec1SBob Moore 			*elements =
483ea7c5ec1SBob Moore 			    acpi_ut_create_integer_object((u64) *buffer);
48447e11d54SBob Moore 			if (!*elements) {
48547e11d54SBob Moore 				acpi_ut_remove_reference(new_object);
48647e11d54SBob Moore 				return (AE_NO_MEMORY);
48747e11d54SBob Moore 			}
48847e11d54SBob Moore 			elements++;
48947e11d54SBob Moore 			buffer++;
49047e11d54SBob Moore 		}
49147e11d54SBob Moore 		break;
49247e11d54SBob Moore 
49347e11d54SBob Moore 	default:
49447e11d54SBob Moore 		return (AE_AML_OPERAND_TYPE);
49547e11d54SBob Moore 	}
49647e11d54SBob Moore 
49747e11d54SBob Moore 	*return_object = new_object;
49847e11d54SBob Moore 	return (AE_OK);
49947e11d54SBob Moore }
50047e11d54SBob Moore 
50147e11d54SBob Moore /*******************************************************************************
50247e11d54SBob Moore  *
503e5f69d6eSBob Moore  * FUNCTION:    acpi_ns_repair_package_list
504e5f69d6eSBob Moore  *
505e5f69d6eSBob Moore  * PARAMETERS:  Data                - Pointer to validation data structure
506e5f69d6eSBob Moore  *              obj_desc_ptr        - Pointer to the object to repair. The new
507e5f69d6eSBob Moore  *                                    package object is returned here,
508e5f69d6eSBob Moore  *                                    overwriting the old object.
509e5f69d6eSBob Moore  *
510e5f69d6eSBob Moore  * RETURN:      Status, new object in *obj_desc_ptr
511e5f69d6eSBob Moore  *
512e5f69d6eSBob Moore  * DESCRIPTION: Repair a common problem with objects that are defined to return
513e5f69d6eSBob Moore  *              a variable-length Package of Packages. If the variable-length
514e5f69d6eSBob Moore  *              is one, some BIOS code mistakenly simply declares a single
515e5f69d6eSBob Moore  *              Package instead of a Package with one sub-Package. This
516e5f69d6eSBob Moore  *              function attempts to repair this error by wrapping a Package
517e5f69d6eSBob Moore  *              object around the original Package, creating the correct
518e5f69d6eSBob Moore  *              Package with one sub-Package.
519e5f69d6eSBob Moore  *
520e5f69d6eSBob Moore  *              Names that can be repaired in this manner include:
521e5f69d6eSBob Moore  *              _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS
522e5f69d6eSBob Moore  *
523e5f69d6eSBob Moore  ******************************************************************************/
524e5f69d6eSBob Moore 
525e5f69d6eSBob Moore acpi_status
526e5f69d6eSBob Moore acpi_ns_repair_package_list(struct acpi_predefined_data *data,
527e5f69d6eSBob Moore 			    union acpi_operand_object **obj_desc_ptr)
528e5f69d6eSBob Moore {
529e5f69d6eSBob Moore 	union acpi_operand_object *pkg_obj_desc;
530e5f69d6eSBob Moore 
531e5f69d6eSBob Moore 	/*
532e5f69d6eSBob Moore 	 * Create the new outer package and populate it. The new package will
533e5f69d6eSBob Moore 	 * have a single element, the lone subpackage.
534e5f69d6eSBob Moore 	 */
535e5f69d6eSBob Moore 	pkg_obj_desc = acpi_ut_create_package_object(1);
536e5f69d6eSBob Moore 	if (!pkg_obj_desc) {
537e5f69d6eSBob Moore 		return (AE_NO_MEMORY);
538e5f69d6eSBob Moore 	}
539e5f69d6eSBob Moore 
540e5f69d6eSBob Moore 	pkg_obj_desc->package.elements[0] = *obj_desc_ptr;
541e5f69d6eSBob Moore 
542e5f69d6eSBob Moore 	/* Return the new object in the object pointer */
543e5f69d6eSBob Moore 
544e5f69d6eSBob Moore 	*obj_desc_ptr = pkg_obj_desc;
545e5f69d6eSBob Moore 	data->flags |= ACPI_OBJECT_REPAIRED;
546e5f69d6eSBob Moore 
5477df200cdSBob Moore 	ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
5487df200cdSBob Moore 			      "Repaired Incorrectly formed Package"));
549e5f69d6eSBob Moore 
550e5f69d6eSBob Moore 	return (AE_OK);
551e5f69d6eSBob Moore }
552