xref: /openbmc/linux/drivers/acpi/acpica/nsrepair.c (revision 091f4d71)
1b2deadd5SBob Moore /******************************************************************************
2b2deadd5SBob Moore  *
3b2deadd5SBob Moore  * Module Name: nsrepair - Repair for objects returned by predefined methods
4b2deadd5SBob Moore  *
5b2deadd5SBob Moore  *****************************************************************************/
6b2deadd5SBob Moore 
7b2deadd5SBob Moore /*
8a8357b0cSBob Moore  * Copyright (C) 2000 - 2010, 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"
48091f4d71SBob Moore #include "acpredef.h"
49b2deadd5SBob Moore 
50b2deadd5SBob Moore #define _COMPONENT          ACPI_NAMESPACE
51b2deadd5SBob Moore ACPI_MODULE_NAME("nsrepair")
52b2deadd5SBob Moore 
53b2deadd5SBob Moore /*******************************************************************************
54b2deadd5SBob Moore  *
5547e11d54SBob Moore  * This module attempts to repair or convert objects returned by the
5647e11d54SBob Moore  * predefined methods to an object type that is expected, as per the ACPI
5747e11d54SBob Moore  * specification. The need for this code is dictated by the many machines that
5847e11d54SBob Moore  * return incorrect types for the standard predefined methods. Performing these
5947e11d54SBob Moore  * conversions here, in one place, eliminates the need for individual ACPI
6047e11d54SBob Moore  * device drivers to do the same. Note: Most of these conversions are different
6147e11d54SBob Moore  * than the internal object conversion routines used for implicit object
6247e11d54SBob Moore  * conversion.
6347e11d54SBob Moore  *
6447e11d54SBob Moore  * The following conversions can be performed as necessary:
6547e11d54SBob Moore  *
6647e11d54SBob Moore  * Integer -> String
6747e11d54SBob Moore  * Integer -> Buffer
6847e11d54SBob Moore  * String  -> Integer
6947e11d54SBob Moore  * String  -> Buffer
7047e11d54SBob Moore  * Buffer  -> Integer
7147e11d54SBob Moore  * Buffer  -> String
7247e11d54SBob Moore  * Buffer  -> Package of Integers
7347e11d54SBob Moore  * Package -> Package of one Package
7447e11d54SBob Moore  *
75091f4d71SBob Moore  * Additional possible repairs:
76091f4d71SBob Moore  *
77091f4d71SBob Moore  * Optional/unnecessary NULL package elements removed
78091f4d71SBob Moore  * Required package elements that are NULL replaced by Integer/String/Buffer
79091f4d71SBob Moore  * Incorrect standalone package wrapped with required outer package
80091f4d71SBob Moore  *
8147e11d54SBob Moore  ******************************************************************************/
8247e11d54SBob Moore /* Local prototypes */
8347e11d54SBob Moore static acpi_status
8447e11d54SBob Moore acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
8547e11d54SBob Moore 			   union acpi_operand_object **return_object);
8647e11d54SBob Moore 
8747e11d54SBob Moore static acpi_status
8847e11d54SBob Moore acpi_ns_convert_to_string(union acpi_operand_object *original_object,
8947e11d54SBob Moore 			  union acpi_operand_object **return_object);
9047e11d54SBob Moore 
9147e11d54SBob Moore static acpi_status
9247e11d54SBob Moore acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
9347e11d54SBob Moore 			  union acpi_operand_object **return_object);
9447e11d54SBob Moore 
9547e11d54SBob Moore static acpi_status
9647e11d54SBob Moore acpi_ns_convert_to_package(union acpi_operand_object *original_object,
9747e11d54SBob Moore 			   union acpi_operand_object **return_object);
9847e11d54SBob Moore 
9947e11d54SBob Moore /*******************************************************************************
10047e11d54SBob Moore  *
101b2deadd5SBob Moore  * FUNCTION:    acpi_ns_repair_object
102b2deadd5SBob Moore  *
103b2deadd5SBob Moore  * PARAMETERS:  Data                - Pointer to validation data structure
104b2deadd5SBob Moore  *              expected_btypes     - Object types expected
105b2deadd5SBob Moore  *              package_index       - Index of object within parent package (if
106b2deadd5SBob Moore  *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
107b2deadd5SBob Moore  *                                    otherwise)
108b2deadd5SBob Moore  *              return_object_ptr   - Pointer to the object returned from the
109b2deadd5SBob Moore  *                                    evaluation of a method or object
110b2deadd5SBob Moore  *
111b2deadd5SBob Moore  * RETURN:      Status. AE_OK if repair was successful.
112b2deadd5SBob Moore  *
113b2deadd5SBob Moore  * DESCRIPTION: Attempt to repair/convert a return object of a type that was
114b2deadd5SBob Moore  *              not expected.
115b2deadd5SBob Moore  *
116b2deadd5SBob Moore  ******************************************************************************/
11747e11d54SBob Moore 
118b2deadd5SBob Moore acpi_status
119b2deadd5SBob Moore acpi_ns_repair_object(struct acpi_predefined_data *data,
120b2deadd5SBob Moore 		      u32 expected_btypes,
121b2deadd5SBob Moore 		      u32 package_index,
122b2deadd5SBob Moore 		      union acpi_operand_object **return_object_ptr)
123b2deadd5SBob Moore {
124b2deadd5SBob Moore 	union acpi_operand_object *return_object = *return_object_ptr;
125b2deadd5SBob Moore 	union acpi_operand_object *new_object;
1260240d7b4SLin Ming 	acpi_status status;
127b2deadd5SBob Moore 
1283a58176eSBob Moore 	ACPI_FUNCTION_NAME(ns_repair_object);
1293a58176eSBob Moore 
13027526993SBob Moore 	/*
13127526993SBob Moore 	 * At this point, we know that the type of the returned object was not
13227526993SBob Moore 	 * one of the expected types for this predefined name. Attempt to
13347e11d54SBob Moore 	 * repair the object by converting it to one of the expected object
13447e11d54SBob Moore 	 * types for this predefined name.
13527526993SBob Moore 	 */
13647e11d54SBob Moore 	if (expected_btypes & ACPI_RTYPE_INTEGER) {
13747e11d54SBob Moore 		status = acpi_ns_convert_to_integer(return_object, &new_object);
13847e11d54SBob Moore 		if (ACPI_SUCCESS(status)) {
13947e11d54SBob Moore 			goto object_repaired;
140b2deadd5SBob Moore 		}
141b2deadd5SBob Moore 	}
14247e11d54SBob Moore 	if (expected_btypes & ACPI_RTYPE_STRING) {
14347e11d54SBob Moore 		status = acpi_ns_convert_to_string(return_object, &new_object);
14447e11d54SBob Moore 		if (ACPI_SUCCESS(status)) {
14547e11d54SBob Moore 			goto object_repaired;
146b2deadd5SBob Moore 		}
14747e11d54SBob Moore 	}
1480240d7b4SLin Ming 	if (expected_btypes & ACPI_RTYPE_BUFFER) {
14947e11d54SBob Moore 		status = acpi_ns_convert_to_buffer(return_object, &new_object);
15047e11d54SBob Moore 		if (ACPI_SUCCESS(status)) {
15147e11d54SBob Moore 			goto object_repaired;
1520240d7b4SLin Ming 		}
1530240d7b4SLin Ming 	}
15447e11d54SBob Moore 	if (expected_btypes & ACPI_RTYPE_PACKAGE) {
15547e11d54SBob Moore 		status = acpi_ns_convert_to_package(return_object, &new_object);
15647e11d54SBob Moore 		if (ACPI_SUCCESS(status)) {
15747e11d54SBob Moore 			goto object_repaired;
15827526993SBob Moore 		}
15927526993SBob Moore 	}
16027526993SBob Moore 
16127526993SBob Moore 	/* We cannot repair this object */
16227526993SBob Moore 
16327526993SBob Moore 	return (AE_AML_OPERAND_TYPE);
16447e11d54SBob Moore 
16547e11d54SBob Moore       object_repaired:
16627526993SBob Moore 
16727526993SBob Moore 	/* Object was successfully repaired */
168b2deadd5SBob Moore 
169b2deadd5SBob Moore 	/*
170b2deadd5SBob Moore 	 * If the original object is a package element, we need to:
171b2deadd5SBob Moore 	 * 1. Set the reference count of the new object to match the
172b2deadd5SBob Moore 	 *    reference count of the old object.
173b2deadd5SBob Moore 	 * 2. Decrement the reference count of the original object.
174b2deadd5SBob Moore 	 */
175b2deadd5SBob Moore 	if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
176b2deadd5SBob Moore 		new_object->common.reference_count =
177b2deadd5SBob Moore 		    return_object->common.reference_count;
178b2deadd5SBob Moore 
179b2deadd5SBob Moore 		if (return_object->common.reference_count > 1) {
180b2deadd5SBob Moore 			return_object->common.reference_count--;
181b2deadd5SBob Moore 		}
182b2deadd5SBob Moore 
1833a58176eSBob Moore 		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
1843a58176eSBob Moore 				  "%s: Converted %s to expected %s at index %u\n",
1853a58176eSBob Moore 				  data->pathname,
1863a58176eSBob Moore 				  acpi_ut_get_object_type_name(return_object),
18727526993SBob Moore 				  acpi_ut_get_object_type_name(new_object),
188b2deadd5SBob Moore 				  package_index));
189b2deadd5SBob Moore 	} else {
1903a58176eSBob Moore 		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
1913a58176eSBob Moore 				  "%s: Converted %s to expected %s\n",
1923a58176eSBob Moore 				  data->pathname,
1933a58176eSBob Moore 				  acpi_ut_get_object_type_name(return_object),
1943a58176eSBob Moore 				  acpi_ut_get_object_type_name(new_object)));
195b2deadd5SBob Moore 	}
196b2deadd5SBob Moore 
197b2deadd5SBob Moore 	/* Delete old object, install the new return object */
198b2deadd5SBob Moore 
199b2deadd5SBob Moore 	acpi_ut_remove_reference(return_object);
200b2deadd5SBob Moore 	*return_object_ptr = new_object;
201b2deadd5SBob Moore 	data->flags |= ACPI_OBJECT_REPAIRED;
202b2deadd5SBob Moore 	return (AE_OK);
203b2deadd5SBob Moore }
204e5f69d6eSBob Moore 
205e5f69d6eSBob Moore /*******************************************************************************
206e5f69d6eSBob Moore  *
20747e11d54SBob Moore  * FUNCTION:    acpi_ns_convert_to_integer
20847e11d54SBob Moore  *
20947e11d54SBob Moore  * PARAMETERS:  original_object     - Object to be converted
21047e11d54SBob Moore  *              return_object       - Where the new converted object is returned
21147e11d54SBob Moore  *
21247e11d54SBob Moore  * RETURN:      Status. AE_OK if conversion was successful.
21347e11d54SBob Moore  *
21447e11d54SBob Moore  * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
21547e11d54SBob Moore  *
21647e11d54SBob Moore  ******************************************************************************/
21747e11d54SBob Moore 
21847e11d54SBob Moore static acpi_status
21947e11d54SBob Moore acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
22047e11d54SBob Moore 			   union acpi_operand_object **return_object)
22147e11d54SBob Moore {
22247e11d54SBob Moore 	union acpi_operand_object *new_object;
22347e11d54SBob Moore 	acpi_status status;
22447e11d54SBob Moore 	u64 value = 0;
22547e11d54SBob Moore 	u32 i;
22647e11d54SBob Moore 
22747e11d54SBob Moore 	switch (original_object->common.type) {
22847e11d54SBob Moore 	case ACPI_TYPE_STRING:
22947e11d54SBob Moore 
23047e11d54SBob Moore 		/* String-to-Integer conversion */
23147e11d54SBob Moore 
23247e11d54SBob Moore 		status = acpi_ut_strtoul64(original_object->string.pointer,
23347e11d54SBob Moore 					   ACPI_ANY_BASE, &value);
23447e11d54SBob Moore 		if (ACPI_FAILURE(status)) {
23547e11d54SBob Moore 			return (status);
23647e11d54SBob Moore 		}
23747e11d54SBob Moore 		break;
23847e11d54SBob Moore 
23947e11d54SBob Moore 	case ACPI_TYPE_BUFFER:
24047e11d54SBob Moore 
24147e11d54SBob Moore 		/* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
24247e11d54SBob Moore 
24347e11d54SBob Moore 		if (original_object->buffer.length > 8) {
24447e11d54SBob Moore 			return (AE_AML_OPERAND_TYPE);
24547e11d54SBob Moore 		}
24647e11d54SBob Moore 
24747e11d54SBob Moore 		/* Extract each buffer byte to create the integer */
24847e11d54SBob Moore 
24947e11d54SBob Moore 		for (i = 0; i < original_object->buffer.length; i++) {
25047e11d54SBob Moore 			value |=
25147e11d54SBob Moore 			    ((u64) original_object->buffer.
25247e11d54SBob Moore 			     pointer[i] << (i * 8));
25347e11d54SBob Moore 		}
25447e11d54SBob Moore 		break;
25547e11d54SBob Moore 
25647e11d54SBob Moore 	default:
25747e11d54SBob Moore 		return (AE_AML_OPERAND_TYPE);
25847e11d54SBob Moore 	}
25947e11d54SBob Moore 
26047e11d54SBob Moore 	new_object = acpi_ut_create_integer_object(value);
26147e11d54SBob Moore 	if (!new_object) {
26247e11d54SBob Moore 		return (AE_NO_MEMORY);
26347e11d54SBob Moore 	}
26447e11d54SBob Moore 
26547e11d54SBob Moore 	*return_object = new_object;
26647e11d54SBob Moore 	return (AE_OK);
26747e11d54SBob Moore }
26847e11d54SBob Moore 
26947e11d54SBob Moore /*******************************************************************************
27047e11d54SBob Moore  *
27147e11d54SBob Moore  * FUNCTION:    acpi_ns_convert_to_string
27247e11d54SBob Moore  *
27347e11d54SBob Moore  * PARAMETERS:  original_object     - Object to be converted
27447e11d54SBob Moore  *              return_object       - Where the new converted object is returned
27547e11d54SBob Moore  *
27647e11d54SBob Moore  * RETURN:      Status. AE_OK if conversion was successful.
27747e11d54SBob Moore  *
27847e11d54SBob Moore  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
27947e11d54SBob Moore  *
28047e11d54SBob Moore  ******************************************************************************/
28147e11d54SBob Moore 
28247e11d54SBob Moore static acpi_status
28347e11d54SBob Moore acpi_ns_convert_to_string(union acpi_operand_object *original_object,
28447e11d54SBob Moore 			  union acpi_operand_object **return_object)
28547e11d54SBob Moore {
28647e11d54SBob Moore 	union acpi_operand_object *new_object;
28747e11d54SBob Moore 	acpi_size length;
28847e11d54SBob Moore 	acpi_status status;
28947e11d54SBob Moore 
29047e11d54SBob Moore 	switch (original_object->common.type) {
29147e11d54SBob Moore 	case ACPI_TYPE_INTEGER:
29247e11d54SBob Moore 		/*
29347e11d54SBob Moore 		 * Integer-to-String conversion. Commonly, convert
29447e11d54SBob Moore 		 * an integer of value 0 to a NULL string. The last element of
29547e11d54SBob Moore 		 * _BIF and _BIX packages occasionally need this fix.
29647e11d54SBob Moore 		 */
29747e11d54SBob Moore 		if (original_object->integer.value == 0) {
29847e11d54SBob Moore 
29947e11d54SBob Moore 			/* Allocate a new NULL string object */
30047e11d54SBob Moore 
30147e11d54SBob Moore 			new_object = acpi_ut_create_string_object(0);
30247e11d54SBob Moore 			if (!new_object) {
30347e11d54SBob Moore 				return (AE_NO_MEMORY);
30447e11d54SBob Moore 			}
30547e11d54SBob Moore 		} else {
30647e11d54SBob Moore 			status =
30747e11d54SBob Moore 			    acpi_ex_convert_to_string(original_object,
30847e11d54SBob Moore 						      &new_object,
30947e11d54SBob Moore 						      ACPI_IMPLICIT_CONVERT_HEX);
31047e11d54SBob Moore 			if (ACPI_FAILURE(status)) {
31147e11d54SBob Moore 				return (status);
31247e11d54SBob Moore 			}
31347e11d54SBob Moore 		}
31447e11d54SBob Moore 		break;
31547e11d54SBob Moore 
31647e11d54SBob Moore 	case ACPI_TYPE_BUFFER:
31747e11d54SBob Moore 		/*
31847e11d54SBob Moore 		 * Buffer-to-String conversion. Use a to_string
31947e11d54SBob Moore 		 * conversion, no transform performed on the buffer data. The best
32047e11d54SBob Moore 		 * example of this is the _BIF method, where the string data from
32147e11d54SBob Moore 		 * the battery is often (incorrectly) returned as buffer object(s).
32247e11d54SBob Moore 		 */
32347e11d54SBob Moore 		length = 0;
32447e11d54SBob Moore 		while ((length < original_object->buffer.length) &&
32547e11d54SBob Moore 		       (original_object->buffer.pointer[length])) {
32647e11d54SBob Moore 			length++;
32747e11d54SBob Moore 		}
32847e11d54SBob Moore 
32947e11d54SBob Moore 		/* Allocate a new string object */
33047e11d54SBob Moore 
33147e11d54SBob Moore 		new_object = acpi_ut_create_string_object(length);
33247e11d54SBob Moore 		if (!new_object) {
33347e11d54SBob Moore 			return (AE_NO_MEMORY);
33447e11d54SBob Moore 		}
33547e11d54SBob Moore 
33647e11d54SBob Moore 		/*
33747e11d54SBob Moore 		 * Copy the raw buffer data with no transform. String is already NULL
33847e11d54SBob Moore 		 * terminated at Length+1.
33947e11d54SBob Moore 		 */
34047e11d54SBob Moore 		ACPI_MEMCPY(new_object->string.pointer,
34147e11d54SBob Moore 			    original_object->buffer.pointer, length);
34247e11d54SBob Moore 		break;
34347e11d54SBob Moore 
34447e11d54SBob Moore 	default:
34547e11d54SBob Moore 		return (AE_AML_OPERAND_TYPE);
34647e11d54SBob Moore 	}
34747e11d54SBob Moore 
34847e11d54SBob Moore 	*return_object = new_object;
34947e11d54SBob Moore 	return (AE_OK);
35047e11d54SBob Moore }
35147e11d54SBob Moore 
35247e11d54SBob Moore /*******************************************************************************
35347e11d54SBob Moore  *
35447e11d54SBob Moore  * FUNCTION:    acpi_ns_convert_to_buffer
35547e11d54SBob Moore  *
35647e11d54SBob Moore  * PARAMETERS:  original_object     - Object to be converted
35747e11d54SBob Moore  *              return_object       - Where the new converted object is returned
35847e11d54SBob Moore  *
35947e11d54SBob Moore  * RETURN:      Status. AE_OK if conversion was successful.
36047e11d54SBob Moore  *
361ea7c5ec1SBob Moore  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
36247e11d54SBob Moore  *
36347e11d54SBob Moore  ******************************************************************************/
36447e11d54SBob Moore 
36547e11d54SBob Moore static acpi_status
36647e11d54SBob Moore acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
36747e11d54SBob Moore 			  union acpi_operand_object **return_object)
36847e11d54SBob Moore {
36947e11d54SBob Moore 	union acpi_operand_object *new_object;
37047e11d54SBob Moore 	acpi_status status;
371ea7c5ec1SBob Moore 	union acpi_operand_object **elements;
372ea7c5ec1SBob Moore 	u32 *dword_buffer;
373ea7c5ec1SBob Moore 	u32 count;
374ea7c5ec1SBob Moore 	u32 i;
37547e11d54SBob Moore 
37647e11d54SBob Moore 	switch (original_object->common.type) {
37747e11d54SBob Moore 	case ACPI_TYPE_INTEGER:
37847e11d54SBob Moore 		/*
37947e11d54SBob Moore 		 * Integer-to-Buffer conversion.
38047e11d54SBob Moore 		 * Convert the Integer to a packed-byte buffer. _MAT and other
38147e11d54SBob Moore 		 * objects need this sometimes, if a read has been performed on a
38247e11d54SBob Moore 		 * Field object that is less than or equal to the global integer
38347e11d54SBob Moore 		 * size (32 or 64 bits).
38447e11d54SBob Moore 		 */
38547e11d54SBob Moore 		status =
38647e11d54SBob Moore 		    acpi_ex_convert_to_buffer(original_object, &new_object);
38747e11d54SBob Moore 		if (ACPI_FAILURE(status)) {
38847e11d54SBob Moore 			return (status);
38947e11d54SBob Moore 		}
39047e11d54SBob Moore 		break;
39147e11d54SBob Moore 
39247e11d54SBob Moore 	case ACPI_TYPE_STRING:
39347e11d54SBob Moore 
39447e11d54SBob Moore 		/* String-to-Buffer conversion. Simple data copy */
39547e11d54SBob Moore 
39647e11d54SBob Moore 		new_object =
39747e11d54SBob Moore 		    acpi_ut_create_buffer_object(original_object->string.
39847e11d54SBob Moore 						 length);
39947e11d54SBob Moore 		if (!new_object) {
40047e11d54SBob Moore 			return (AE_NO_MEMORY);
40147e11d54SBob Moore 		}
40247e11d54SBob Moore 
40347e11d54SBob Moore 		ACPI_MEMCPY(new_object->buffer.pointer,
40447e11d54SBob Moore 			    original_object->string.pointer,
40547e11d54SBob Moore 			    original_object->string.length);
40647e11d54SBob Moore 		break;
40747e11d54SBob Moore 
408ea7c5ec1SBob Moore 	case ACPI_TYPE_PACKAGE:
40943420bbbSBob Moore 		/*
41043420bbbSBob Moore 		 * This case is often seen for predefined names that must return a
41143420bbbSBob Moore 		 * Buffer object with multiple DWORD integers within. For example,
41243420bbbSBob Moore 		 * _FDE and _GTM. The Package can be converted to a Buffer.
41343420bbbSBob Moore 		 */
414ea7c5ec1SBob Moore 
415ea7c5ec1SBob Moore 		/* All elements of the Package must be integers */
416ea7c5ec1SBob Moore 
417ea7c5ec1SBob Moore 		elements = original_object->package.elements;
418ea7c5ec1SBob Moore 		count = original_object->package.count;
419ea7c5ec1SBob Moore 
420ea7c5ec1SBob Moore 		for (i = 0; i < count; i++) {
421ea7c5ec1SBob Moore 			if ((!*elements) ||
422ea7c5ec1SBob Moore 			    ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
423ea7c5ec1SBob Moore 				return (AE_AML_OPERAND_TYPE);
424ea7c5ec1SBob Moore 			}
425ea7c5ec1SBob Moore 			elements++;
426ea7c5ec1SBob Moore 		}
427ea7c5ec1SBob Moore 
428ea7c5ec1SBob Moore 		/* Create the new buffer object to replace the Package */
429ea7c5ec1SBob Moore 
430ea7c5ec1SBob Moore 		new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
431ea7c5ec1SBob Moore 		if (!new_object) {
432ea7c5ec1SBob Moore 			return (AE_NO_MEMORY);
433ea7c5ec1SBob Moore 		}
434ea7c5ec1SBob Moore 
435ea7c5ec1SBob Moore 		/* Copy the package elements (integers) to the buffer as DWORDs */
436ea7c5ec1SBob Moore 
437ea7c5ec1SBob Moore 		elements = original_object->package.elements;
438ea7c5ec1SBob Moore 		dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
439ea7c5ec1SBob Moore 
440ea7c5ec1SBob Moore 		for (i = 0; i < count; i++) {
441ea7c5ec1SBob Moore 			*dword_buffer = (u32) (*elements)->integer.value;
442ea7c5ec1SBob Moore 			dword_buffer++;
443ea7c5ec1SBob Moore 			elements++;
444ea7c5ec1SBob Moore 		}
445ea7c5ec1SBob Moore 		break;
446ea7c5ec1SBob Moore 
44747e11d54SBob Moore 	default:
44847e11d54SBob Moore 		return (AE_AML_OPERAND_TYPE);
44947e11d54SBob Moore 	}
45047e11d54SBob Moore 
45147e11d54SBob Moore 	*return_object = new_object;
45247e11d54SBob Moore 	return (AE_OK);
45347e11d54SBob Moore }
45447e11d54SBob Moore 
45547e11d54SBob Moore /*******************************************************************************
45647e11d54SBob Moore  *
45747e11d54SBob Moore  * FUNCTION:    acpi_ns_convert_to_package
45847e11d54SBob Moore  *
45947e11d54SBob Moore  * PARAMETERS:  original_object     - Object to be converted
46047e11d54SBob Moore  *              return_object       - Where the new converted object is returned
46147e11d54SBob Moore  *
46247e11d54SBob Moore  * RETURN:      Status. AE_OK if conversion was successful.
46347e11d54SBob Moore  *
46447e11d54SBob Moore  * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of
46547e11d54SBob Moore  *              the buffer is converted to a single integer package element.
46647e11d54SBob Moore  *
46747e11d54SBob Moore  ******************************************************************************/
46847e11d54SBob Moore 
46947e11d54SBob Moore static acpi_status
47047e11d54SBob Moore acpi_ns_convert_to_package(union acpi_operand_object *original_object,
47147e11d54SBob Moore 			   union acpi_operand_object **return_object)
47247e11d54SBob Moore {
47347e11d54SBob Moore 	union acpi_operand_object *new_object;
47447e11d54SBob Moore 	union acpi_operand_object **elements;
47547e11d54SBob Moore 	u32 length;
47647e11d54SBob Moore 	u8 *buffer;
47747e11d54SBob Moore 
47847e11d54SBob Moore 	switch (original_object->common.type) {
47947e11d54SBob Moore 	case ACPI_TYPE_BUFFER:
48047e11d54SBob Moore 
48147e11d54SBob Moore 		/* Buffer-to-Package conversion */
48247e11d54SBob Moore 
48347e11d54SBob Moore 		length = original_object->buffer.length;
48447e11d54SBob Moore 		new_object = acpi_ut_create_package_object(length);
48547e11d54SBob Moore 		if (!new_object) {
48647e11d54SBob Moore 			return (AE_NO_MEMORY);
48747e11d54SBob Moore 		}
48847e11d54SBob Moore 
48947e11d54SBob Moore 		/* Convert each buffer byte to an integer package element */
49047e11d54SBob Moore 
49147e11d54SBob Moore 		elements = new_object->package.elements;
49247e11d54SBob Moore 		buffer = original_object->buffer.pointer;
49347e11d54SBob Moore 
49447e11d54SBob Moore 		while (length--) {
495ea7c5ec1SBob Moore 			*elements =
496ea7c5ec1SBob Moore 			    acpi_ut_create_integer_object((u64) *buffer);
49747e11d54SBob Moore 			if (!*elements) {
49847e11d54SBob Moore 				acpi_ut_remove_reference(new_object);
49947e11d54SBob Moore 				return (AE_NO_MEMORY);
50047e11d54SBob Moore 			}
50147e11d54SBob Moore 			elements++;
50247e11d54SBob Moore 			buffer++;
50347e11d54SBob Moore 		}
50447e11d54SBob Moore 		break;
50547e11d54SBob Moore 
50647e11d54SBob Moore 	default:
50747e11d54SBob Moore 		return (AE_AML_OPERAND_TYPE);
50847e11d54SBob Moore 	}
50947e11d54SBob Moore 
51047e11d54SBob Moore 	*return_object = new_object;
51147e11d54SBob Moore 	return (AE_OK);
51247e11d54SBob Moore }
51347e11d54SBob Moore 
51447e11d54SBob Moore /*******************************************************************************
51547e11d54SBob Moore  *
516091f4d71SBob Moore  * FUNCTION:    acpi_ns_repair_null_element
517091f4d71SBob Moore  *
518091f4d71SBob Moore  * PARAMETERS:  Data                - Pointer to validation data structure
519091f4d71SBob Moore  *              expected_btypes     - Object types expected
520091f4d71SBob Moore  *              package_index       - Index of object within parent package (if
521091f4d71SBob Moore  *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
522091f4d71SBob Moore  *                                    otherwise)
523091f4d71SBob Moore  *              return_object_ptr   - Pointer to the object returned from the
524091f4d71SBob Moore  *                                    evaluation of a method or object
525091f4d71SBob Moore  *
526091f4d71SBob Moore  * RETURN:      Status. AE_OK if repair was successful.
527091f4d71SBob Moore  *
528091f4d71SBob Moore  * DESCRIPTION: Attempt to repair a NULL element of a returned Package object.
529091f4d71SBob Moore  *
530091f4d71SBob Moore  ******************************************************************************/
531091f4d71SBob Moore 
532091f4d71SBob Moore acpi_status
533091f4d71SBob Moore acpi_ns_repair_null_element(struct acpi_predefined_data *data,
534091f4d71SBob Moore 			    u32 expected_btypes,
535091f4d71SBob Moore 			    u32 package_index,
536091f4d71SBob Moore 			    union acpi_operand_object **return_object_ptr)
537091f4d71SBob Moore {
538091f4d71SBob Moore 	union acpi_operand_object *return_object = *return_object_ptr;
539091f4d71SBob Moore 	union acpi_operand_object *new_object;
540091f4d71SBob Moore 
541091f4d71SBob Moore 	ACPI_FUNCTION_NAME(ns_repair_null_element);
542091f4d71SBob Moore 
543091f4d71SBob Moore 	/* No repair needed if return object is non-NULL */
544091f4d71SBob Moore 
545091f4d71SBob Moore 	if (return_object) {
546091f4d71SBob Moore 		return (AE_OK);
547091f4d71SBob Moore 	}
548091f4d71SBob Moore 
549091f4d71SBob Moore 	/*
550091f4d71SBob Moore 	 * Attempt to repair a NULL element of a Package object. This applies to
551091f4d71SBob Moore 	 * predefined names that return a fixed-length package and each element
552091f4d71SBob Moore 	 * is required. It does not apply to variable-length packages where NULL
553091f4d71SBob Moore 	 * elements are allowed, especially at the end of the package.
554091f4d71SBob Moore 	 */
555091f4d71SBob Moore 	if (expected_btypes & ACPI_RTYPE_INTEGER) {
556091f4d71SBob Moore 
557091f4d71SBob Moore 		/* Need an Integer - create a zero-value integer */
558091f4d71SBob Moore 
559091f4d71SBob Moore 		new_object = acpi_ut_create_integer_object(0);
560091f4d71SBob Moore 	} else if (expected_btypes & ACPI_RTYPE_STRING) {
561091f4d71SBob Moore 
562091f4d71SBob Moore 		/* Need a String - create a NULL string */
563091f4d71SBob Moore 
564091f4d71SBob Moore 		new_object = acpi_ut_create_string_object(0);
565091f4d71SBob Moore 	} else if (expected_btypes & ACPI_RTYPE_BUFFER) {
566091f4d71SBob Moore 
567091f4d71SBob Moore 		/* Need a Buffer - create a zero-length buffer */
568091f4d71SBob Moore 
569091f4d71SBob Moore 		new_object = acpi_ut_create_buffer_object(0);
570091f4d71SBob Moore 	} else {
571091f4d71SBob Moore 		/* Error for all other expected types */
572091f4d71SBob Moore 
573091f4d71SBob Moore 		return (AE_AML_OPERAND_TYPE);
574091f4d71SBob Moore 	}
575091f4d71SBob Moore 
576091f4d71SBob Moore 	if (!new_object) {
577091f4d71SBob Moore 		return (AE_NO_MEMORY);
578091f4d71SBob Moore 	}
579091f4d71SBob Moore 
580091f4d71SBob Moore 	/* Set the reference count according to the parent Package object */
581091f4d71SBob Moore 
582091f4d71SBob Moore 	new_object->common.reference_count =
583091f4d71SBob Moore 	    data->parent_package->common.reference_count;
584091f4d71SBob Moore 
585091f4d71SBob Moore 	ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
586091f4d71SBob Moore 			  "%s: Converted NULL package element to expected %s at index %u\n",
587091f4d71SBob Moore 			  data->pathname,
588091f4d71SBob Moore 			  acpi_ut_get_object_type_name(new_object),
589091f4d71SBob Moore 			  package_index));
590091f4d71SBob Moore 
591091f4d71SBob Moore 	*return_object_ptr = new_object;
592091f4d71SBob Moore 	data->flags |= ACPI_OBJECT_REPAIRED;
593091f4d71SBob Moore 	return (AE_OK);
594091f4d71SBob Moore }
595091f4d71SBob Moore 
596091f4d71SBob Moore /******************************************************************************
597091f4d71SBob Moore  *
598091f4d71SBob Moore  * FUNCTION:    acpi_ns_remove_null_elements
599091f4d71SBob Moore  *
600091f4d71SBob Moore  * PARAMETERS:  Data                - Pointer to validation data structure
601091f4d71SBob Moore  *              package_type        - An acpi_return_package_types value
602091f4d71SBob Moore  *              obj_desc            - A Package object
603091f4d71SBob Moore  *
604091f4d71SBob Moore  * RETURN:      None.
605091f4d71SBob Moore  *
606091f4d71SBob Moore  * DESCRIPTION: Remove all NULL package elements from packages that contain
607091f4d71SBob Moore  *              a variable number of sub-packages. For these types of
608091f4d71SBob Moore  *              packages, NULL elements can be safely removed.
609091f4d71SBob Moore  *
610091f4d71SBob Moore  *****************************************************************************/
611091f4d71SBob Moore 
612091f4d71SBob Moore void
613091f4d71SBob Moore acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
614091f4d71SBob Moore 			     u8 package_type,
615091f4d71SBob Moore 			     union acpi_operand_object *obj_desc)
616091f4d71SBob Moore {
617091f4d71SBob Moore 	union acpi_operand_object **source;
618091f4d71SBob Moore 	union acpi_operand_object **dest;
619091f4d71SBob Moore 	u32 count;
620091f4d71SBob Moore 	u32 new_count;
621091f4d71SBob Moore 	u32 i;
622091f4d71SBob Moore 
623091f4d71SBob Moore 	ACPI_FUNCTION_NAME(ns_remove_null_elements);
624091f4d71SBob Moore 
625091f4d71SBob Moore 	/*
626091f4d71SBob Moore 	 * PTYPE1 packages contain no subpackages.
627091f4d71SBob Moore 	 * PTYPE2 packages contain a variable number of sub-packages. We can
628091f4d71SBob Moore 	 * safely remove all NULL elements from the PTYPE2 packages.
629091f4d71SBob Moore 	 */
630091f4d71SBob Moore 	switch (package_type) {
631091f4d71SBob Moore 	case ACPI_PTYPE1_FIXED:
632091f4d71SBob Moore 	case ACPI_PTYPE1_VAR:
633091f4d71SBob Moore 	case ACPI_PTYPE1_OPTION:
634091f4d71SBob Moore 		return;
635091f4d71SBob Moore 
636091f4d71SBob Moore 	case ACPI_PTYPE2:
637091f4d71SBob Moore 	case ACPI_PTYPE2_COUNT:
638091f4d71SBob Moore 	case ACPI_PTYPE2_PKG_COUNT:
639091f4d71SBob Moore 	case ACPI_PTYPE2_FIXED:
640091f4d71SBob Moore 	case ACPI_PTYPE2_MIN:
641091f4d71SBob Moore 	case ACPI_PTYPE2_REV_FIXED:
642091f4d71SBob Moore 		break;
643091f4d71SBob Moore 
644091f4d71SBob Moore 	default:
645091f4d71SBob Moore 		return;
646091f4d71SBob Moore 	}
647091f4d71SBob Moore 
648091f4d71SBob Moore 	count = obj_desc->package.count;
649091f4d71SBob Moore 	new_count = count;
650091f4d71SBob Moore 
651091f4d71SBob Moore 	source = obj_desc->package.elements;
652091f4d71SBob Moore 	dest = source;
653091f4d71SBob Moore 
654091f4d71SBob Moore 	/* Examine all elements of the package object, remove nulls */
655091f4d71SBob Moore 
656091f4d71SBob Moore 	for (i = 0; i < count; i++) {
657091f4d71SBob Moore 		if (!*source) {
658091f4d71SBob Moore 			new_count--;
659091f4d71SBob Moore 		} else {
660091f4d71SBob Moore 			*dest = *source;
661091f4d71SBob Moore 			dest++;
662091f4d71SBob Moore 		}
663091f4d71SBob Moore 		source++;
664091f4d71SBob Moore 	}
665091f4d71SBob Moore 
666091f4d71SBob Moore 	/* Update parent package if any null elements were removed */
667091f4d71SBob Moore 
668091f4d71SBob Moore 	if (new_count < count) {
669091f4d71SBob Moore 		ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
670091f4d71SBob Moore 				  "%s: Found and removed %u NULL elements\n",
671091f4d71SBob Moore 				  data->pathname, (count - new_count)));
672091f4d71SBob Moore 
673091f4d71SBob Moore 		/* NULL terminate list and update the package count */
674091f4d71SBob Moore 
675091f4d71SBob Moore 		*dest = NULL;
676091f4d71SBob Moore 		obj_desc->package.count = new_count;
677091f4d71SBob Moore 	}
678091f4d71SBob Moore }
679091f4d71SBob Moore 
680091f4d71SBob Moore /*******************************************************************************
681091f4d71SBob Moore  *
682e5f69d6eSBob Moore  * FUNCTION:    acpi_ns_repair_package_list
683e5f69d6eSBob Moore  *
684e5f69d6eSBob Moore  * PARAMETERS:  Data                - Pointer to validation data structure
685e5f69d6eSBob Moore  *              obj_desc_ptr        - Pointer to the object to repair. The new
686e5f69d6eSBob Moore  *                                    package object is returned here,
687e5f69d6eSBob Moore  *                                    overwriting the old object.
688e5f69d6eSBob Moore  *
689e5f69d6eSBob Moore  * RETURN:      Status, new object in *obj_desc_ptr
690e5f69d6eSBob Moore  *
691e5f69d6eSBob Moore  * DESCRIPTION: Repair a common problem with objects that are defined to return
692e5f69d6eSBob Moore  *              a variable-length Package of Packages. If the variable-length
693e5f69d6eSBob Moore  *              is one, some BIOS code mistakenly simply declares a single
694e5f69d6eSBob Moore  *              Package instead of a Package with one sub-Package. This
695e5f69d6eSBob Moore  *              function attempts to repair this error by wrapping a Package
696e5f69d6eSBob Moore  *              object around the original Package, creating the correct
697e5f69d6eSBob Moore  *              Package with one sub-Package.
698e5f69d6eSBob Moore  *
699e5f69d6eSBob Moore  *              Names that can be repaired in this manner include:
700e5f69d6eSBob Moore  *              _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS
701e5f69d6eSBob Moore  *
702e5f69d6eSBob Moore  ******************************************************************************/
703e5f69d6eSBob Moore 
704e5f69d6eSBob Moore acpi_status
705e5f69d6eSBob Moore acpi_ns_repair_package_list(struct acpi_predefined_data *data,
706e5f69d6eSBob Moore 			    union acpi_operand_object **obj_desc_ptr)
707e5f69d6eSBob Moore {
708e5f69d6eSBob Moore 	union acpi_operand_object *pkg_obj_desc;
709e5f69d6eSBob Moore 
7103a58176eSBob Moore 	ACPI_FUNCTION_NAME(ns_repair_package_list);
7113a58176eSBob Moore 
712e5f69d6eSBob Moore 	/*
713e5f69d6eSBob Moore 	 * Create the new outer package and populate it. The new package will
714e5f69d6eSBob Moore 	 * have a single element, the lone subpackage.
715e5f69d6eSBob Moore 	 */
716e5f69d6eSBob Moore 	pkg_obj_desc = acpi_ut_create_package_object(1);
717e5f69d6eSBob Moore 	if (!pkg_obj_desc) {
718e5f69d6eSBob Moore 		return (AE_NO_MEMORY);
719e5f69d6eSBob Moore 	}
720e5f69d6eSBob Moore 
721e5f69d6eSBob Moore 	pkg_obj_desc->package.elements[0] = *obj_desc_ptr;
722e5f69d6eSBob Moore 
723e5f69d6eSBob Moore 	/* Return the new object in the object pointer */
724e5f69d6eSBob Moore 
725e5f69d6eSBob Moore 	*obj_desc_ptr = pkg_obj_desc;
726e5f69d6eSBob Moore 	data->flags |= ACPI_OBJECT_REPAIRED;
727e5f69d6eSBob Moore 
7283a58176eSBob Moore 	ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
7293a58176eSBob Moore 			  "%s: Repaired incorrectly formed Package\n",
7303a58176eSBob Moore 			  data->pathname));
731e5f69d6eSBob Moore 
732e5f69d6eSBob Moore 	return (AE_OK);
733e5f69d6eSBob Moore }
734