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