Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6595 serge 1
/******************************************************************************
2
 *
3
 * Module Name: nsconvert - Object conversions for objects returned by
4
 *                          predefined methods
5
 *
6
 *****************************************************************************/
7
 
8
/*
9
 * Copyright (C) 2000 - 2015, 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 
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_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 |=
100
			    ((u64)original_object->buffer.
101
			     pointer[i] << (i * 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 =
157
			    acpi_ex_convert_to_string(original_object,
158
						      &new_object,
159
						      ACPI_IMPLICIT_CONVERT_HEX);
160
			if (ACPI_FAILURE(status)) {
161
				return (status);
162
			}
163
		}
164
		break;
165
 
166
	case ACPI_TYPE_BUFFER:
167
		/*
168
		 * Buffer-to-String conversion. Use a to_string
169
		 * conversion, no transform performed on the buffer data. The best
170
		 * example of this is the _BIF method, where the string data from
171
		 * the battery is often (incorrectly) returned as buffer object(s).
172
		 */
173
		length = 0;
174
		while ((length < original_object->buffer.length) &&
175
		       (original_object->buffer.pointer[length])) {
176
			length++;
177
		}
178
 
179
		/* Allocate a new string object */
180
 
181
		new_object = acpi_ut_create_string_object(length);
182
		if (!new_object) {
183
			return (AE_NO_MEMORY);
184
		}
185
 
186
		/*
187
		 * Copy the raw buffer data with no transform. String is already NULL
188
		 * terminated at Length+1.
189
		 */
190
		memcpy(new_object->string.pointer,
191
		       original_object->buffer.pointer, length);
192
		break;
193
 
194
	default:
195
 
196
		return (AE_AML_OPERAND_TYPE);
197
	}
198
 
199
	*return_object = new_object;
200
	return (AE_OK);
201
}
202
 
203
/*******************************************************************************
204
 *
205
 * FUNCTION:    acpi_ns_convert_to_buffer
206
 *
207
 * PARAMETERS:  original_object     - Object to be converted
208
 *              return_object       - Where the new converted object is returned
209
 *
210
 * RETURN:      Status. AE_OK if conversion was successful.
211
 *
212
 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
213
 *
214
 ******************************************************************************/
215
 
216
acpi_status
217
acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
218
			  union acpi_operand_object **return_object)
219
{
220
	union acpi_operand_object *new_object;
221
	acpi_status status;
222
	union acpi_operand_object **elements;
223
	u32 *dword_buffer;
224
	u32 count;
225
	u32 i;
226
 
227
	switch (original_object->common.type) {
228
	case ACPI_TYPE_INTEGER:
229
		/*
230
		 * Integer-to-Buffer conversion.
231
		 * Convert the Integer to a packed-byte buffer. _MAT and other
232
		 * objects need this sometimes, if a read has been performed on a
233
		 * Field object that is less than or equal to the global integer
234
		 * size (32 or 64 bits).
235
		 */
236
		status =
237
		    acpi_ex_convert_to_buffer(original_object, &new_object);
238
		if (ACPI_FAILURE(status)) {
239
			return (status);
240
		}
241
		break;
242
 
243
	case ACPI_TYPE_STRING:
244
 
245
		/* String-to-Buffer conversion. Simple data copy */
246
 
247
		new_object =
248
		    acpi_ut_create_buffer_object(original_object->string.
249
						 length);
250
		if (!new_object) {
251
			return (AE_NO_MEMORY);
252
		}
253
 
254
		memcpy(new_object->buffer.pointer,
255
		       original_object->string.pointer,
256
		       original_object->string.length);
257
		break;
258
 
259
	case ACPI_TYPE_PACKAGE:
260
		/*
261
		 * This case is often seen for predefined names that must return a
262
		 * Buffer object with multiple DWORD integers within. For example,
263
		 * _FDE and _GTM. The Package can be converted to a Buffer.
264
		 */
265
 
266
		/* All elements of the Package must be integers */
267
 
268
		elements = original_object->package.elements;
269
		count = original_object->package.count;
270
 
271
		for (i = 0; i < count; i++) {
272
			if ((!*elements) ||
273
			    ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
274
				return (AE_AML_OPERAND_TYPE);
275
			}
276
			elements++;
277
		}
278
 
279
		/* Create the new buffer object to replace the Package */
280
 
281
		new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
282
		if (!new_object) {
283
			return (AE_NO_MEMORY);
284
		}
285
 
286
		/* Copy the package elements (integers) to the buffer as DWORDs */
287
 
288
		elements = original_object->package.elements;
289
		dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
290
 
291
		for (i = 0; i < count; i++) {
292
			*dword_buffer = (u32)(*elements)->integer.value;
293
			dword_buffer++;
294
			elements++;
295
		}
296
		break;
297
 
298
	default:
299
 
300
		return (AE_AML_OPERAND_TYPE);
301
	}
302
 
303
	*return_object = new_object;
304
	return (AE_OK);
305
}
306
 
307
/*******************************************************************************
308
 *
309
 * FUNCTION:    acpi_ns_convert_to_unicode
310
 *
311
 * PARAMETERS:  original_object     - ASCII String Object to be converted
312
 *              return_object       - Where the new converted object is returned
313
 *
314
 * RETURN:      Status. AE_OK if conversion was successful.
315
 *
316
 * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
317
 *
318
 ******************************************************************************/
319
 
320
acpi_status
321
acpi_ns_convert_to_unicode(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:  original_object     - Object to be converted
376
 *              return_object       - Where the new converted object is returned
377
 *
378
 * RETURN:      Status. AE_OK if conversion was successful
379
 *
380
 * DESCRIPTION: Attempt to convert a Integer object to a resource_template
381
 *              Buffer.
382
 *
383
 ******************************************************************************/
384
 
385
acpi_status
386
acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
387
			    union acpi_operand_object **return_object)
388
{
389
	union acpi_operand_object *new_object;
390
	u8 *buffer;
391
 
392
	/*
393
	 * We can fix the following cases for an expected resource template:
394
	 * 1. No return value (interpreter slack mode is disabled)
395
	 * 2. A "Return (Zero)" statement
396
	 * 3. A "Return empty buffer" statement
397
	 *
398
	 * We will return a buffer containing a single end_tag
399
	 * resource descriptor.
400
	 */
401
	if (original_object) {
402
		switch (original_object->common.type) {
403
		case ACPI_TYPE_INTEGER:
404
 
405
			/* We can only repair an Integer==0 */
406
 
407
			if (original_object->integer.value) {
408
				return (AE_AML_OPERAND_TYPE);
409
			}
410
			break;
411
 
412
		case ACPI_TYPE_BUFFER:
413
 
414
			if (original_object->buffer.length) {
415
 
416
				/* Additional checks can be added in the future */
417
 
418
				*return_object = NULL;
419
				return (AE_OK);
420
			}
421
			break;
422
 
423
		case ACPI_TYPE_STRING:
424
		default:
425
 
426
			return (AE_AML_OPERAND_TYPE);
427
		}
428
	}
429
 
430
	/* Create the new buffer object for the resource descriptor */
431
 
432
	new_object = acpi_ut_create_buffer_object(2);
433
	if (!new_object) {
434
		return (AE_NO_MEMORY);
435
	}
436
 
437
	buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);
438
 
439
	/* Initialize the Buffer with a single end_tag descriptor */
440
 
441
	buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
442
	buffer[1] = 0x00;
443
 
444
	*return_object = new_object;
445
	return (AE_OK);
446
}