xref: /openbmc/linux/drivers/acpi/acpica/nsconvert.c (revision 8730046c)
1 /******************************************************************************
2  *
3  * Module Name: nsconvert - Object conversions for objects returned by
4  *                          predefined methods
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2016, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44 
45 #include <acpi/acpi.h>
46 #include "accommon.h"
47 #include "acnamesp.h"
48 #include "acinterp.h"
49 #include "acpredef.h"
50 #include "amlresrc.h"
51 
52 #define _COMPONENT          ACPI_NAMESPACE
53 ACPI_MODULE_NAME("nsconvert")
54 
55 /*******************************************************************************
56  *
57  * FUNCTION:    acpi_ns_convert_to_integer
58  *
59  * PARAMETERS:  original_object     - Object to be converted
60  *              return_object       - Where the new converted object is returned
61  *
62  * RETURN:      Status. AE_OK if conversion was successful.
63  *
64  * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
65  *
66  ******************************************************************************/
67 acpi_status
68 acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
69 			   union acpi_operand_object **return_object)
70 {
71 	union acpi_operand_object *new_object;
72 	acpi_status status;
73 	u64 value = 0;
74 	u32 i;
75 
76 	switch (original_object->common.type) {
77 	case ACPI_TYPE_STRING:
78 
79 		/* String-to-Integer conversion */
80 
81 		status = acpi_ut_strtoul64(original_object->string.pointer,
82 					   acpi_gbl_integer_byte_width, &value);
83 		if (ACPI_FAILURE(status)) {
84 			return (status);
85 		}
86 		break;
87 
88 	case ACPI_TYPE_BUFFER:
89 
90 		/* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
91 
92 		if (original_object->buffer.length > 8) {
93 			return (AE_AML_OPERAND_TYPE);
94 		}
95 
96 		/* Extract each buffer byte to create the integer */
97 
98 		for (i = 0; i < original_object->buffer.length; i++) {
99 			value |= ((u64)
100 				  original_object->buffer.pointer[i] << (i *
101 									 8));
102 		}
103 		break;
104 
105 	default:
106 
107 		return (AE_AML_OPERAND_TYPE);
108 	}
109 
110 	new_object = acpi_ut_create_integer_object(value);
111 	if (!new_object) {
112 		return (AE_NO_MEMORY);
113 	}
114 
115 	*return_object = new_object;
116 	return (AE_OK);
117 }
118 
119 /*******************************************************************************
120  *
121  * FUNCTION:    acpi_ns_convert_to_string
122  *
123  * PARAMETERS:  original_object     - Object to be converted
124  *              return_object       - Where the new converted object is returned
125  *
126  * RETURN:      Status. AE_OK if conversion was successful.
127  *
128  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
129  *
130  ******************************************************************************/
131 
132 acpi_status
133 acpi_ns_convert_to_string(union acpi_operand_object *original_object,
134 			  union acpi_operand_object **return_object)
135 {
136 	union acpi_operand_object *new_object;
137 	acpi_size length;
138 	acpi_status status;
139 
140 	switch (original_object->common.type) {
141 	case ACPI_TYPE_INTEGER:
142 		/*
143 		 * Integer-to-String conversion. Commonly, convert
144 		 * an integer of value 0 to a NULL string. The last element of
145 		 * _BIF and _BIX packages occasionally need this fix.
146 		 */
147 		if (original_object->integer.value == 0) {
148 
149 			/* Allocate a new NULL string object */
150 
151 			new_object = acpi_ut_create_string_object(0);
152 			if (!new_object) {
153 				return (AE_NO_MEMORY);
154 			}
155 		} else {
156 			status = acpi_ex_convert_to_string(original_object,
157 							   &new_object,
158 							   ACPI_IMPLICIT_CONVERT_HEX);
159 			if (ACPI_FAILURE(status)) {
160 				return (status);
161 			}
162 		}
163 		break;
164 
165 	case ACPI_TYPE_BUFFER:
166 		/*
167 		 * Buffer-to-String conversion. Use a to_string
168 		 * conversion, no transform performed on the buffer data. The best
169 		 * example of this is the _BIF method, where the string data from
170 		 * the battery is often (incorrectly) returned as buffer object(s).
171 		 */
172 		length = 0;
173 		while ((length < original_object->buffer.length) &&
174 		       (original_object->buffer.pointer[length])) {
175 			length++;
176 		}
177 
178 		/* Allocate a new string object */
179 
180 		new_object = acpi_ut_create_string_object(length);
181 		if (!new_object) {
182 			return (AE_NO_MEMORY);
183 		}
184 
185 		/*
186 		 * Copy the raw buffer data with no transform. String is already NULL
187 		 * terminated at Length+1.
188 		 */
189 		memcpy(new_object->string.pointer,
190 		       original_object->buffer.pointer, length);
191 		break;
192 
193 	default:
194 
195 		return (AE_AML_OPERAND_TYPE);
196 	}
197 
198 	*return_object = new_object;
199 	return (AE_OK);
200 }
201 
202 /*******************************************************************************
203  *
204  * FUNCTION:    acpi_ns_convert_to_buffer
205  *
206  * PARAMETERS:  original_object     - Object to be converted
207  *              return_object       - Where the new converted object is returned
208  *
209  * RETURN:      Status. AE_OK if conversion was successful.
210  *
211  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
212  *
213  ******************************************************************************/
214 
215 acpi_status
216 acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
217 			  union acpi_operand_object **return_object)
218 {
219 	union acpi_operand_object *new_object;
220 	acpi_status status;
221 	union acpi_operand_object **elements;
222 	u32 *dword_buffer;
223 	u32 count;
224 	u32 i;
225 
226 	switch (original_object->common.type) {
227 	case ACPI_TYPE_INTEGER:
228 		/*
229 		 * Integer-to-Buffer conversion.
230 		 * Convert the Integer to a packed-byte buffer. _MAT and other
231 		 * objects need this sometimes, if a read has been performed on a
232 		 * Field object that is less than or equal to the global integer
233 		 * size (32 or 64 bits).
234 		 */
235 		status =
236 		    acpi_ex_convert_to_buffer(original_object, &new_object);
237 		if (ACPI_FAILURE(status)) {
238 			return (status);
239 		}
240 		break;
241 
242 	case ACPI_TYPE_STRING:
243 
244 		/* String-to-Buffer conversion. Simple data copy */
245 
246 		new_object = acpi_ut_create_buffer_object
247 		    (original_object->string.length);
248 		if (!new_object) {
249 			return (AE_NO_MEMORY);
250 		}
251 
252 		memcpy(new_object->buffer.pointer,
253 		       original_object->string.pointer,
254 		       original_object->string.length);
255 		break;
256 
257 	case ACPI_TYPE_PACKAGE:
258 		/*
259 		 * This case is often seen for predefined names that must return a
260 		 * Buffer object with multiple DWORD integers within. For example,
261 		 * _FDE and _GTM. The Package can be converted to a Buffer.
262 		 */
263 
264 		/* All elements of the Package must be integers */
265 
266 		elements = original_object->package.elements;
267 		count = original_object->package.count;
268 
269 		for (i = 0; i < count; i++) {
270 			if ((!*elements) ||
271 			    ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
272 				return (AE_AML_OPERAND_TYPE);
273 			}
274 			elements++;
275 		}
276 
277 		/* Create the new buffer object to replace the Package */
278 
279 		new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
280 		if (!new_object) {
281 			return (AE_NO_MEMORY);
282 		}
283 
284 		/* Copy the package elements (integers) to the buffer as DWORDs */
285 
286 		elements = original_object->package.elements;
287 		dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
288 
289 		for (i = 0; i < count; i++) {
290 			*dword_buffer = (u32)(*elements)->integer.value;
291 			dword_buffer++;
292 			elements++;
293 		}
294 		break;
295 
296 	default:
297 
298 		return (AE_AML_OPERAND_TYPE);
299 	}
300 
301 	*return_object = new_object;
302 	return (AE_OK);
303 }
304 
305 /*******************************************************************************
306  *
307  * FUNCTION:    acpi_ns_convert_to_unicode
308  *
309  * PARAMETERS:  scope               - Namespace node for the method/object
310  *              original_object     - ASCII String Object to be converted
311  *              return_object       - Where the new converted object is returned
312  *
313  * RETURN:      Status. AE_OK if conversion was successful.
314  *
315  * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
316  *
317  ******************************************************************************/
318 
319 acpi_status
320 acpi_ns_convert_to_unicode(struct acpi_namespace_node *scope,
321 			   union acpi_operand_object *original_object,
322 			   union acpi_operand_object **return_object)
323 {
324 	union acpi_operand_object *new_object;
325 	char *ascii_string;
326 	u16 *unicode_buffer;
327 	u32 unicode_length;
328 	u32 i;
329 
330 	if (!original_object) {
331 		return (AE_OK);
332 	}
333 
334 	/* If a Buffer was returned, it must be at least two bytes long */
335 
336 	if (original_object->common.type == ACPI_TYPE_BUFFER) {
337 		if (original_object->buffer.length < 2) {
338 			return (AE_AML_OPERAND_VALUE);
339 		}
340 
341 		*return_object = NULL;
342 		return (AE_OK);
343 	}
344 
345 	/*
346 	 * The original object is an ASCII string. Convert this string to
347 	 * a unicode buffer.
348 	 */
349 	ascii_string = original_object->string.pointer;
350 	unicode_length = (original_object->string.length * 2) + 2;
351 
352 	/* Create a new buffer object for the Unicode data */
353 
354 	new_object = acpi_ut_create_buffer_object(unicode_length);
355 	if (!new_object) {
356 		return (AE_NO_MEMORY);
357 	}
358 
359 	unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer);
360 
361 	/* Convert ASCII to Unicode */
362 
363 	for (i = 0; i < original_object->string.length; i++) {
364 		unicode_buffer[i] = (u16)ascii_string[i];
365 	}
366 
367 	*return_object = new_object;
368 	return (AE_OK);
369 }
370 
371 /*******************************************************************************
372  *
373  * FUNCTION:    acpi_ns_convert_to_resource
374  *
375  * PARAMETERS:  scope               - Namespace node for the method/object
376  *              original_object     - Object to be converted
377  *              return_object       - Where the new converted object is returned
378  *
379  * RETURN:      Status. AE_OK if conversion was successful
380  *
381  * DESCRIPTION: Attempt to convert a Integer object to a resource_template
382  *              Buffer.
383  *
384  ******************************************************************************/
385 
386 acpi_status
387 acpi_ns_convert_to_resource(struct acpi_namespace_node *scope,
388 			    union acpi_operand_object *original_object,
389 			    union acpi_operand_object **return_object)
390 {
391 	union acpi_operand_object *new_object;
392 	u8 *buffer;
393 
394 	/*
395 	 * We can fix the following cases for an expected resource template:
396 	 * 1. No return value (interpreter slack mode is disabled)
397 	 * 2. A "Return (Zero)" statement
398 	 * 3. A "Return empty buffer" statement
399 	 *
400 	 * We will return a buffer containing a single end_tag
401 	 * resource descriptor.
402 	 */
403 	if (original_object) {
404 		switch (original_object->common.type) {
405 		case ACPI_TYPE_INTEGER:
406 
407 			/* We can only repair an Integer==0 */
408 
409 			if (original_object->integer.value) {
410 				return (AE_AML_OPERAND_TYPE);
411 			}
412 			break;
413 
414 		case ACPI_TYPE_BUFFER:
415 
416 			if (original_object->buffer.length) {
417 
418 				/* Additional checks can be added in the future */
419 
420 				*return_object = NULL;
421 				return (AE_OK);
422 			}
423 			break;
424 
425 		case ACPI_TYPE_STRING:
426 		default:
427 
428 			return (AE_AML_OPERAND_TYPE);
429 		}
430 	}
431 
432 	/* Create the new buffer object for the resource descriptor */
433 
434 	new_object = acpi_ut_create_buffer_object(2);
435 	if (!new_object) {
436 		return (AE_NO_MEMORY);
437 	}
438 
439 	buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);
440 
441 	/* Initialize the Buffer with a single end_tag descriptor */
442 
443 	buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
444 	buffer[1] = 0x00;
445 
446 	*return_object = new_object;
447 	return (AE_OK);
448 }
449 
450 /*******************************************************************************
451  *
452  * FUNCTION:    acpi_ns_convert_to_reference
453  *
454  * PARAMETERS:  scope               - Namespace node for the method/object
455  *              original_object     - Object to be converted
456  *              return_object       - Where the new converted object is returned
457  *
458  * RETURN:      Status. AE_OK if conversion was successful
459  *
460  * DESCRIPTION: Attempt to convert a Integer object to a object_reference.
461  *              Buffer.
462  *
463  ******************************************************************************/
464 
465 acpi_status
466 acpi_ns_convert_to_reference(struct acpi_namespace_node *scope,
467 			     union acpi_operand_object *original_object,
468 			     union acpi_operand_object **return_object)
469 {
470 	union acpi_operand_object *new_object = NULL;
471 	acpi_status status;
472 	struct acpi_namespace_node *node;
473 	union acpi_generic_state scope_info;
474 	char *name;
475 
476 	ACPI_FUNCTION_NAME(ns_convert_to_reference);
477 
478 	/* Convert path into internal presentation */
479 
480 	status =
481 	    acpi_ns_internalize_name(original_object->string.pointer, &name);
482 	if (ACPI_FAILURE(status)) {
483 		return_ACPI_STATUS(status);
484 	}
485 
486 	/* Find the namespace node */
487 
488 	scope_info.scope.node =
489 	    ACPI_CAST_PTR(struct acpi_namespace_node, scope);
490 	status =
491 	    acpi_ns_lookup(&scope_info, name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
492 			   ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
493 			   NULL, &node);
494 	if (ACPI_FAILURE(status)) {
495 
496 		/* Check if we are resolving a named reference within a package */
497 
498 		ACPI_ERROR_NAMESPACE(original_object->string.pointer, status);
499 		goto error_exit;
500 	}
501 
502 	/* Create and init a new internal ACPI object */
503 
504 	new_object = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
505 	if (!new_object) {
506 		status = AE_NO_MEMORY;
507 		goto error_exit;
508 	}
509 	new_object->reference.node = node;
510 	new_object->reference.object = node->object;
511 	new_object->reference.class = ACPI_REFCLASS_NAME;
512 
513 	/*
514 	 * Increase reference of the object if needed (the object is likely a
515 	 * null for device nodes).
516 	 */
517 	acpi_ut_add_reference(node->object);
518 
519 error_exit:
520 	ACPI_FREE(name);
521 	*return_object = new_object;
522 	return (AE_OK);
523 }
524