1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
4 * Module Name: nsconvert - Object conversions for objects returned by
7 * Copyright (C) 2000 - 2020, Intel Corp.
9 *****************************************************************************/
11 #include <acpi/acpi.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 ******************************************************************************/
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
;
42 switch (original_object
->common
.type
) {
43 case ACPI_TYPE_STRING
:
45 /* String-to-Integer conversion */
48 acpi_ut_strtoul64(original_object
->string
.pointer
, &value
);
49 if (ACPI_FAILURE(status
)) {
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
++) {
66 original_object
->buffer
.pointer
[i
] << (i
*
73 return (AE_AML_OPERAND_TYPE
);
76 new_object
= acpi_ut_create_integer_object(value
);
78 return (AE_NO_MEMORY
);
81 *return_object
= new_object
;
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 ******************************************************************************/
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
;
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);
119 return (AE_NO_MEMORY
);
122 status
= acpi_ex_convert_to_string(original_object
,
124 ACPI_IMPLICIT_CONVERT_HEX
);
125 if (ACPI_FAILURE(status
)) {
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).
139 while ((length
< original_object
->buffer
.length
) &&
140 (original_object
->buffer
.pointer
[length
])) {
144 /* Allocate a new string object */
146 new_object
= acpi_ut_create_string_object(length
);
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
);
161 return (AE_AML_OPERAND_TYPE
);
164 *return_object
= new_object
;
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 ******************************************************************************/
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
;
187 union acpi_operand_object
**elements
;
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).
202 acpi_ex_convert_to_buffer(original_object
, &new_object
);
203 if (ACPI_FAILURE(status
)) {
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
);
215 return (AE_NO_MEMORY
);
218 memcpy(new_object
->buffer
.pointer
,
219 original_object
->string
.pointer
,
220 original_object
->string
.length
);
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
++) {
237 ((*elements
)->common
.type
!= ACPI_TYPE_INTEGER
)) {
238 return (AE_AML_OPERAND_TYPE
);
243 /* Create the new buffer object to replace the Package */
245 new_object
= acpi_ut_create_buffer_object(ACPI_MUL_4(count
));
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
;
264 return (AE_AML_OPERAND_TYPE
);
267 *return_object
= new_object
;
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 ******************************************************************************/
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
;
296 if (!original_object
) {
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
;
312 * The original object is an ASCII string. Convert this string to
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
);
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
;
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
350 ******************************************************************************/
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
;
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
);
380 case ACPI_TYPE_BUFFER
:
382 if (original_object
->buffer
.length
) {
384 /* Additional checks can be added in the future */
386 *return_object
= NULL
;
391 case ACPI_TYPE_STRING
:
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);
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
);
412 *return_object
= new_object
;
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.
429 ******************************************************************************/
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
;
438 struct acpi_namespace_node
*node
;
439 union acpi_generic_state scope_info
;
442 ACPI_FUNCTION_NAME(ns_convert_to_reference
);
444 /* Convert path into internal presentation */
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
);
457 acpi_ns_lookup(&scope_info
, name
, ACPI_TYPE_ANY
, ACPI_IMODE_EXECUTE
,
458 ACPI_NS_SEARCH_PARENT
| ACPI_NS_DONT_OPEN_SCOPE
,
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
);
469 /* Create and init a new internal ACPI object */
471 new_object
= acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE
);
473 status
= AE_NO_MEMORY
;
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
);
488 *return_object
= new_object
;