Merge tag 'trace-v5.11-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[linux/fpc-iii.git] / drivers / acpi / acpica / nsconvert.c
blobc86c82939ebb88d3687749ba48663639fac22a59
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
4 * Module Name: nsconvert - Object conversions for objects returned by
5 * predefined methods
7 * Copyright (C) 2000 - 2020, Intel Corp.
9 *****************************************************************************/
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"
18 #define _COMPONENT ACPI_NAMESPACE
19 ACPI_MODULE_NAME("nsconvert")
21 /*******************************************************************************
23 * FUNCTION: acpi_ns_convert_to_integer
25 * PARAMETERS: original_object - Object to be converted
26 * return_object - Where the new converted object is returned
28 * RETURN: Status. AE_OK if conversion was successful.
30 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
32 ******************************************************************************/
33 acpi_status
34 acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
35 union acpi_operand_object **return_object)
37 union acpi_operand_object *new_object;
38 acpi_status status;
39 u64 value = 0;
40 u32 i;
42 switch (original_object->common.type) {
43 case ACPI_TYPE_STRING:
45 /* String-to-Integer conversion */
47 status =
48 acpi_ut_strtoul64(original_object->string.pointer, &value);
49 if (ACPI_FAILURE(status)) {
50 return (status);
52 break;
54 case ACPI_TYPE_BUFFER:
56 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
58 if (original_object->buffer.length > 8) {
59 return (AE_AML_OPERAND_TYPE);
62 /* Extract each buffer byte to create the integer */
64 for (i = 0; i < original_object->buffer.length; i++) {
65 value |= ((u64)
66 original_object->buffer.pointer[i] << (i *
67 8));
69 break;
71 default:
73 return (AE_AML_OPERAND_TYPE);
76 new_object = acpi_ut_create_integer_object(value);
77 if (!new_object) {
78 return (AE_NO_MEMORY);
81 *return_object = new_object;
82 return (AE_OK);
85 /*******************************************************************************
87 * FUNCTION: acpi_ns_convert_to_string
89 * PARAMETERS: original_object - Object to be converted
90 * return_object - Where the new converted object is returned
92 * RETURN: Status. AE_OK if conversion was successful.
94 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
96 ******************************************************************************/
98 acpi_status
99 acpi_ns_convert_to_string(union acpi_operand_object *original_object,
100 union acpi_operand_object **return_object)
102 union acpi_operand_object *new_object;
103 acpi_size length;
104 acpi_status status;
106 switch (original_object->common.type) {
107 case ACPI_TYPE_INTEGER:
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.
113 if (original_object->integer.value == 0) {
115 /* Allocate a new NULL string object */
117 new_object = acpi_ut_create_string_object(0);
118 if (!new_object) {
119 return (AE_NO_MEMORY);
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);
129 break;
131 case ACPI_TYPE_BUFFER:
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).
138 length = 0;
139 while ((length < original_object->buffer.length) &&
140 (original_object->buffer.pointer[length])) {
141 length++;
144 /* Allocate a new string object */
146 new_object = acpi_ut_create_string_object(length);
147 if (!new_object) {
148 return (AE_NO_MEMORY);
152 * Copy the raw buffer data with no transform. String is already NULL
153 * terminated at Length+1.
155 memcpy(new_object->string.pointer,
156 original_object->buffer.pointer, length);
157 break;
159 default:
161 return (AE_AML_OPERAND_TYPE);
164 *return_object = new_object;
165 return (AE_OK);
168 /*******************************************************************************
170 * FUNCTION: acpi_ns_convert_to_buffer
172 * PARAMETERS: original_object - Object to be converted
173 * return_object - Where the new converted object is returned
175 * RETURN: Status. AE_OK if conversion was successful.
177 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
179 ******************************************************************************/
181 acpi_status
182 acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
183 union acpi_operand_object **return_object)
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;
192 switch (original_object->common.type) {
193 case ACPI_TYPE_INTEGER:
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).
201 status =
202 acpi_ex_convert_to_buffer(original_object, &new_object);
203 if (ACPI_FAILURE(status)) {
204 return (status);
206 break;
208 case ACPI_TYPE_STRING:
210 /* String-to-Buffer conversion. Simple data copy */
212 new_object = acpi_ut_create_buffer_object
213 (original_object->string.length);
214 if (!new_object) {
215 return (AE_NO_MEMORY);
218 memcpy(new_object->buffer.pointer,
219 original_object->string.pointer,
220 original_object->string.length);
221 break;
223 case ACPI_TYPE_PACKAGE:
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.
230 /* All elements of the Package must be integers */
232 elements = original_object->package.elements;
233 count = original_object->package.count;
235 for (i = 0; i < count; i++) {
236 if ((!*elements) ||
237 ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
238 return (AE_AML_OPERAND_TYPE);
240 elements++;
243 /* Create the new buffer object to replace the Package */
245 new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
246 if (!new_object) {
247 return (AE_NO_MEMORY);
250 /* Copy the package elements (integers) to the buffer as DWORDs */
252 elements = original_object->package.elements;
253 dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
255 for (i = 0; i < count; i++) {
256 *dword_buffer = (u32)(*elements)->integer.value;
257 dword_buffer++;
258 elements++;
260 break;
262 default:
264 return (AE_AML_OPERAND_TYPE);
267 *return_object = new_object;
268 return (AE_OK);
271 /*******************************************************************************
273 * FUNCTION: acpi_ns_convert_to_unicode
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
279 * RETURN: Status. AE_OK if conversion was successful.
281 * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
283 ******************************************************************************/
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)
290 union acpi_operand_object *new_object;
291 char *ascii_string;
292 u16 *unicode_buffer;
293 u32 unicode_length;
294 u32 i;
296 if (!original_object) {
297 return (AE_OK);
300 /* If a Buffer was returned, it must be at least two bytes long */
302 if (original_object->common.type == ACPI_TYPE_BUFFER) {
303 if (original_object->buffer.length < 2) {
304 return (AE_AML_OPERAND_VALUE);
307 *return_object = NULL;
308 return (AE_OK);
312 * The original object is an ASCII string. Convert this string to
313 * a unicode buffer.
315 ascii_string = original_object->string.pointer;
316 unicode_length = (original_object->string.length * 2) + 2;
318 /* Create a new buffer object for the Unicode data */
320 new_object = acpi_ut_create_buffer_object(unicode_length);
321 if (!new_object) {
322 return (AE_NO_MEMORY);
325 unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer);
327 /* Convert ASCII to Unicode */
329 for (i = 0; i < original_object->string.length; i++) {
330 unicode_buffer[i] = (u16)ascii_string[i];
333 *return_object = new_object;
334 return (AE_OK);
337 /*******************************************************************************
339 * FUNCTION: acpi_ns_convert_to_resource
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
345 * RETURN: Status. AE_OK if conversion was successful
347 * DESCRIPTION: Attempt to convert a Integer object to a resource_template
348 * Buffer.
350 ******************************************************************************/
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)
357 union acpi_operand_object *new_object;
358 u8 *buffer;
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
366 * We will return a buffer containing a single end_tag
367 * resource descriptor.
369 if (original_object) {
370 switch (original_object->common.type) {
371 case ACPI_TYPE_INTEGER:
373 /* We can only repair an Integer==0 */
375 if (original_object->integer.value) {
376 return (AE_AML_OPERAND_TYPE);
378 break;
380 case ACPI_TYPE_BUFFER:
382 if (original_object->buffer.length) {
384 /* Additional checks can be added in the future */
386 *return_object = NULL;
387 return (AE_OK);
389 break;
391 case ACPI_TYPE_STRING:
392 default:
394 return (AE_AML_OPERAND_TYPE);
398 /* Create the new buffer object for the resource descriptor */
400 new_object = acpi_ut_create_buffer_object(2);
401 if (!new_object) {
402 return (AE_NO_MEMORY);
405 buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);
407 /* Initialize the Buffer with a single end_tag descriptor */
409 buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
410 buffer[1] = 0x00;
412 *return_object = new_object;
413 return (AE_OK);
416 /*******************************************************************************
418 * FUNCTION: acpi_ns_convert_to_reference
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
424 * RETURN: Status. AE_OK if conversion was successful
426 * DESCRIPTION: Attempt to convert a Integer object to a object_reference.
427 * Buffer.
429 ******************************************************************************/
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)
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;
442 ACPI_FUNCTION_NAME(ns_convert_to_reference);
444 /* Convert path into internal presentation */
446 status =
447 acpi_ns_internalize_name(original_object->string.pointer, &name);
448 if (ACPI_FAILURE(status)) {
449 return_ACPI_STATUS(status);
452 /* Find the namespace node */
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)) {
462 /* Check if we are resolving a named reference within a package */
464 ACPI_ERROR_NAMESPACE(&scope_info,
465 original_object->string.pointer, status);
466 goto error_exit;
469 /* Create and init a new internal ACPI object */
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;
476 new_object->reference.node = node;
477 new_object->reference.object = node->object;
478 new_object->reference.class = ACPI_REFCLASS_NAME;
481 * Increase reference of the object if needed (the object is likely a
482 * null for device nodes).
484 acpi_ut_add_reference(node->object);
486 error_exit:
487 ACPI_FREE(name);
488 *return_object = new_object;
489 return (status);