Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: nsconvert - Object conversions for objects returned by
0005  *                          predefined methods
0006  *
0007  * Copyright (C) 2000 - 2022, Intel Corp.
0008  *
0009  *****************************************************************************/
0010 
0011 #include <acpi/acpi.h>
0012 #include "accommon.h"
0013 #include "acnamesp.h"
0014 #include "acinterp.h"
0015 #include "acpredef.h"
0016 #include "amlresrc.h"
0017 
0018 #define _COMPONENT          ACPI_NAMESPACE
0019 ACPI_MODULE_NAME("nsconvert")
0020 
0021 /*******************************************************************************
0022  *
0023  * FUNCTION:    acpi_ns_convert_to_integer
0024  *
0025  * PARAMETERS:  original_object     - Object to be converted
0026  *              return_object       - Where the new converted object is returned
0027  *
0028  * RETURN:      Status. AE_OK if conversion was successful.
0029  *
0030  * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
0031  *
0032  ******************************************************************************/
0033 acpi_status
0034 acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
0035                union acpi_operand_object **return_object)
0036 {
0037     union acpi_operand_object *new_object;
0038     acpi_status status;
0039     u64 value = 0;
0040     u32 i;
0041 
0042     switch (original_object->common.type) {
0043     case ACPI_TYPE_STRING:
0044 
0045         /* String-to-Integer conversion */
0046 
0047         status =
0048             acpi_ut_strtoul64(original_object->string.pointer, &value);
0049         if (ACPI_FAILURE(status)) {
0050             return (status);
0051         }
0052         break;
0053 
0054     case ACPI_TYPE_BUFFER:
0055 
0056         /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
0057 
0058         if (original_object->buffer.length > 8) {
0059             return (AE_AML_OPERAND_TYPE);
0060         }
0061 
0062         /* Extract each buffer byte to create the integer */
0063 
0064         for (i = 0; i < original_object->buffer.length; i++) {
0065             value |= ((u64)
0066                   original_object->buffer.pointer[i] << (i *
0067                                      8));
0068         }
0069         break;
0070 
0071     default:
0072 
0073         return (AE_AML_OPERAND_TYPE);
0074     }
0075 
0076     new_object = acpi_ut_create_integer_object(value);
0077     if (!new_object) {
0078         return (AE_NO_MEMORY);
0079     }
0080 
0081     *return_object = new_object;
0082     return (AE_OK);
0083 }
0084 
0085 /*******************************************************************************
0086  *
0087  * FUNCTION:    acpi_ns_convert_to_string
0088  *
0089  * PARAMETERS:  original_object     - Object to be converted
0090  *              return_object       - Where the new converted object is returned
0091  *
0092  * RETURN:      Status. AE_OK if conversion was successful.
0093  *
0094  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
0095  *
0096  ******************************************************************************/
0097 
0098 acpi_status
0099 acpi_ns_convert_to_string(union acpi_operand_object *original_object,
0100               union acpi_operand_object **return_object)
0101 {
0102     union acpi_operand_object *new_object;
0103     acpi_size length;
0104     acpi_status status;
0105 
0106     switch (original_object->common.type) {
0107     case ACPI_TYPE_INTEGER:
0108         /*
0109          * Integer-to-String conversion. Commonly, convert
0110          * an integer of value 0 to a NULL string. The last element of
0111          * _BIF and _BIX packages occasionally need this fix.
0112          */
0113         if (original_object->integer.value == 0) {
0114 
0115             /* Allocate a new NULL string object */
0116 
0117             new_object = acpi_ut_create_string_object(0);
0118             if (!new_object) {
0119                 return (AE_NO_MEMORY);
0120             }
0121         } else {
0122             status = acpi_ex_convert_to_string(original_object,
0123                                &new_object,
0124                                ACPI_IMPLICIT_CONVERT_HEX);
0125             if (ACPI_FAILURE(status)) {
0126                 return (status);
0127             }
0128         }
0129         break;
0130 
0131     case ACPI_TYPE_BUFFER:
0132         /*
0133          * Buffer-to-String conversion. Use a to_string
0134          * conversion, no transform performed on the buffer data. The best
0135          * example of this is the _BIF method, where the string data from
0136          * the battery is often (incorrectly) returned as buffer object(s).
0137          */
0138         length = 0;
0139         while ((length < original_object->buffer.length) &&
0140                (original_object->buffer.pointer[length])) {
0141             length++;
0142         }
0143 
0144         /* Allocate a new string object */
0145 
0146         new_object = acpi_ut_create_string_object(length);
0147         if (!new_object) {
0148             return (AE_NO_MEMORY);
0149         }
0150 
0151         /*
0152          * Copy the raw buffer data with no transform. String is already NULL
0153          * terminated at Length+1.
0154          */
0155         memcpy(new_object->string.pointer,
0156                original_object->buffer.pointer, length);
0157         break;
0158 
0159     default:
0160 
0161         return (AE_AML_OPERAND_TYPE);
0162     }
0163 
0164     *return_object = new_object;
0165     return (AE_OK);
0166 }
0167 
0168 /*******************************************************************************
0169  *
0170  * FUNCTION:    acpi_ns_convert_to_buffer
0171  *
0172  * PARAMETERS:  original_object     - Object to be converted
0173  *              return_object       - Where the new converted object is returned
0174  *
0175  * RETURN:      Status. AE_OK if conversion was successful.
0176  *
0177  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
0178  *
0179  ******************************************************************************/
0180 
0181 acpi_status
0182 acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
0183               union acpi_operand_object **return_object)
0184 {
0185     union acpi_operand_object *new_object;
0186     acpi_status status;
0187     union acpi_operand_object **elements;
0188     u32 *dword_buffer;
0189     u32 count;
0190     u32 i;
0191 
0192     switch (original_object->common.type) {
0193     case ACPI_TYPE_INTEGER:
0194         /*
0195          * Integer-to-Buffer conversion.
0196          * Convert the Integer to a packed-byte buffer. _MAT and other
0197          * objects need this sometimes, if a read has been performed on a
0198          * Field object that is less than or equal to the global integer
0199          * size (32 or 64 bits).
0200          */
0201         status =
0202             acpi_ex_convert_to_buffer(original_object, &new_object);
0203         if (ACPI_FAILURE(status)) {
0204             return (status);
0205         }
0206         break;
0207 
0208     case ACPI_TYPE_STRING:
0209 
0210         /* String-to-Buffer conversion. Simple data copy */
0211 
0212         new_object = acpi_ut_create_buffer_object
0213             (original_object->string.length);
0214         if (!new_object) {
0215             return (AE_NO_MEMORY);
0216         }
0217 
0218         memcpy(new_object->buffer.pointer,
0219                original_object->string.pointer,
0220                original_object->string.length);
0221         break;
0222 
0223     case ACPI_TYPE_PACKAGE:
0224         /*
0225          * This case is often seen for predefined names that must return a
0226          * Buffer object with multiple DWORD integers within. For example,
0227          * _FDE and _GTM. The Package can be converted to a Buffer.
0228          */
0229 
0230         /* All elements of the Package must be integers */
0231 
0232         elements = original_object->package.elements;
0233         count = original_object->package.count;
0234 
0235         for (i = 0; i < count; i++) {
0236             if ((!*elements) ||
0237                 ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
0238                 return (AE_AML_OPERAND_TYPE);
0239             }
0240             elements++;
0241         }
0242 
0243         /* Create the new buffer object to replace the Package */
0244 
0245         new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
0246         if (!new_object) {
0247             return (AE_NO_MEMORY);
0248         }
0249 
0250         /* Copy the package elements (integers) to the buffer as DWORDs */
0251 
0252         elements = original_object->package.elements;
0253         dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
0254 
0255         for (i = 0; i < count; i++) {
0256             *dword_buffer = (u32)(*elements)->integer.value;
0257             dword_buffer++;
0258             elements++;
0259         }
0260         break;
0261 
0262     default:
0263 
0264         return (AE_AML_OPERAND_TYPE);
0265     }
0266 
0267     *return_object = new_object;
0268     return (AE_OK);
0269 }
0270 
0271 /*******************************************************************************
0272  *
0273  * FUNCTION:    acpi_ns_convert_to_unicode
0274  *
0275  * PARAMETERS:  scope               - Namespace node for the method/object
0276  *              original_object     - ASCII String Object to be converted
0277  *              return_object       - Where the new converted object is returned
0278  *
0279  * RETURN:      Status. AE_OK if conversion was successful.
0280  *
0281  * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
0282  *
0283  ******************************************************************************/
0284 
0285 acpi_status
0286 acpi_ns_convert_to_unicode(struct acpi_namespace_node *scope,
0287                union acpi_operand_object *original_object,
0288                union acpi_operand_object **return_object)
0289 {
0290     union acpi_operand_object *new_object;
0291     char *ascii_string;
0292     u16 *unicode_buffer;
0293     u32 unicode_length;
0294     u32 i;
0295 
0296     if (!original_object) {
0297         return (AE_OK);
0298     }
0299 
0300     /* If a Buffer was returned, it must be at least two bytes long */
0301 
0302     if (original_object->common.type == ACPI_TYPE_BUFFER) {
0303         if (original_object->buffer.length < 2) {
0304             return (AE_AML_OPERAND_VALUE);
0305         }
0306 
0307         *return_object = NULL;
0308         return (AE_OK);
0309     }
0310 
0311     /*
0312      * The original object is an ASCII string. Convert this string to
0313      * a unicode buffer.
0314      */
0315     ascii_string = original_object->string.pointer;
0316     unicode_length = (original_object->string.length * 2) + 2;
0317 
0318     /* Create a new buffer object for the Unicode data */
0319 
0320     new_object = acpi_ut_create_buffer_object(unicode_length);
0321     if (!new_object) {
0322         return (AE_NO_MEMORY);
0323     }
0324 
0325     unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer);
0326 
0327     /* Convert ASCII to Unicode */
0328 
0329     for (i = 0; i < original_object->string.length; i++) {
0330         unicode_buffer[i] = (u16)ascii_string[i];
0331     }
0332 
0333     *return_object = new_object;
0334     return (AE_OK);
0335 }
0336 
0337 /*******************************************************************************
0338  *
0339  * FUNCTION:    acpi_ns_convert_to_resource
0340  *
0341  * PARAMETERS:  scope               - Namespace node for the method/object
0342  *              original_object     - Object to be converted
0343  *              return_object       - Where the new converted object is returned
0344  *
0345  * RETURN:      Status. AE_OK if conversion was successful
0346  *
0347  * DESCRIPTION: Attempt to convert a Integer object to a resource_template
0348  *              Buffer.
0349  *
0350  ******************************************************************************/
0351 
0352 acpi_status
0353 acpi_ns_convert_to_resource(struct acpi_namespace_node *scope,
0354                 union acpi_operand_object *original_object,
0355                 union acpi_operand_object **return_object)
0356 {
0357     union acpi_operand_object *new_object;
0358     u8 *buffer;
0359 
0360     /*
0361      * We can fix the following cases for an expected resource template:
0362      * 1. No return value (interpreter slack mode is disabled)
0363      * 2. A "Return (Zero)" statement
0364      * 3. A "Return empty buffer" statement
0365      *
0366      * We will return a buffer containing a single end_tag
0367      * resource descriptor.
0368      */
0369     if (original_object) {
0370         switch (original_object->common.type) {
0371         case ACPI_TYPE_INTEGER:
0372 
0373             /* We can only repair an Integer==0 */
0374 
0375             if (original_object->integer.value) {
0376                 return (AE_AML_OPERAND_TYPE);
0377             }
0378             break;
0379 
0380         case ACPI_TYPE_BUFFER:
0381 
0382             if (original_object->buffer.length) {
0383 
0384                 /* Additional checks can be added in the future */
0385 
0386                 *return_object = NULL;
0387                 return (AE_OK);
0388             }
0389             break;
0390 
0391         case ACPI_TYPE_STRING:
0392         default:
0393 
0394             return (AE_AML_OPERAND_TYPE);
0395         }
0396     }
0397 
0398     /* Create the new buffer object for the resource descriptor */
0399 
0400     new_object = acpi_ut_create_buffer_object(2);
0401     if (!new_object) {
0402         return (AE_NO_MEMORY);
0403     }
0404 
0405     buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);
0406 
0407     /* Initialize the Buffer with a single end_tag descriptor */
0408 
0409     buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
0410     buffer[1] = 0x00;
0411 
0412     *return_object = new_object;
0413     return (AE_OK);
0414 }
0415 
0416 /*******************************************************************************
0417  *
0418  * FUNCTION:    acpi_ns_convert_to_reference
0419  *
0420  * PARAMETERS:  scope               - Namespace node for the method/object
0421  *              original_object     - Object to be converted
0422  *              return_object       - Where the new converted object is returned
0423  *
0424  * RETURN:      Status. AE_OK if conversion was successful
0425  *
0426  * DESCRIPTION: Attempt to convert a Integer object to a object_reference.
0427  *              Buffer.
0428  *
0429  ******************************************************************************/
0430 
0431 acpi_status
0432 acpi_ns_convert_to_reference(struct acpi_namespace_node *scope,
0433                  union acpi_operand_object *original_object,
0434                  union acpi_operand_object **return_object)
0435 {
0436     union acpi_operand_object *new_object = NULL;
0437     acpi_status status;
0438     struct acpi_namespace_node *node;
0439     union acpi_generic_state scope_info;
0440     char *name;
0441 
0442     ACPI_FUNCTION_NAME(ns_convert_to_reference);
0443 
0444     /* Convert path into internal presentation */
0445 
0446     status =
0447         acpi_ns_internalize_name(original_object->string.pointer, &name);
0448     if (ACPI_FAILURE(status)) {
0449         return_ACPI_STATUS(status);
0450     }
0451 
0452     /* Find the namespace node */
0453 
0454     scope_info.scope.node =
0455         ACPI_CAST_PTR(struct acpi_namespace_node, scope);
0456     status =
0457         acpi_ns_lookup(&scope_info, name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
0458                ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
0459                NULL, &node);
0460     if (ACPI_FAILURE(status)) {
0461 
0462         /* Check if we are resolving a named reference within a package */
0463 
0464         ACPI_ERROR_NAMESPACE(&scope_info,
0465                      original_object->string.pointer, status);
0466         goto error_exit;
0467     }
0468 
0469     /* Create and init a new internal ACPI object */
0470 
0471     new_object = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
0472     if (!new_object) {
0473         status = AE_NO_MEMORY;
0474         goto error_exit;
0475     }
0476     new_object->reference.node = node;
0477     new_object->reference.object = node->object;
0478     new_object->reference.class = ACPI_REFCLASS_NAME;
0479 
0480     /*
0481      * Increase reference of the object if needed (the object is likely a
0482      * null for device nodes).
0483      */
0484     acpi_ut_add_reference(node->object);
0485 
0486 error_exit:
0487     ACPI_FREE(name);
0488     *return_object = new_object;
0489     return (status);
0490 }