Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 53ACPI_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 ******************************************************************************/
 67acpi_status
 68acpi_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_ANY_BASE, &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
132acpi_status
133acpi_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
215acpi_status
216acpi_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
319acpi_status
320acpi_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
386acpi_status
387acpi_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
465acpi_status
466acpi_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
519error_exit:
520	ACPI_FREE(name);
521	*return_object = new_object;
522	return (AE_OK);
523}