LCOV - code coverage report
Current view: top level - drivers/acpi/acpica - nsconvert.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 9 145 6.2 %
Date: 2022-04-01 14:17:54 Functions: 1 6 16.7 %
Branches: 3 71 4.2 %

           Branch data     Line data    Source code
       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 - 2020, 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                 :          0 : acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
      35                 :            :                            union acpi_operand_object **return_object)
      36                 :            : {
      37                 :          0 :         union acpi_operand_object *new_object;
      38                 :          0 :         acpi_status status;
      39                 :          0 :         u64 value = 0;
      40                 :          0 :         u32 i;
      41                 :            : 
      42      [ #  #  # ]:          0 :         switch (original_object->common.type) {
      43                 :          0 :         case ACPI_TYPE_STRING:
      44                 :            : 
      45                 :            :                 /* String-to-Integer conversion */
      46                 :            : 
      47                 :          0 :                 status =
      48                 :          0 :                     acpi_ut_strtoul64(original_object->string.pointer, &value);
      49         [ #  # ]:          0 :                 if (ACPI_FAILURE(status)) {
      50                 :            :                         return (status);
      51                 :            :                 }
      52                 :            :                 break;
      53                 :            : 
      54                 :          0 :         case ACPI_TYPE_BUFFER:
      55                 :            : 
      56                 :            :                 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
      57                 :            : 
      58         [ #  # ]:          0 :                 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         [ #  # ]:          0 :                 for (i = 0; i < original_object->buffer.length; i++) {
      65                 :          0 :                         value |= ((u64)
      66                 :          0 :                                   original_object->buffer.pointer[i] << (i *
      67                 :            :                                                                          8));
      68                 :            :                 }
      69                 :            :                 break;
      70                 :            : 
      71                 :            :         default:
      72                 :            : 
      73                 :            :                 return (AE_AML_OPERAND_TYPE);
      74                 :            :         }
      75                 :            : 
      76                 :          0 :         new_object = acpi_ut_create_integer_object(value);
      77         [ #  # ]:          0 :         if (!new_object) {
      78                 :            :                 return (AE_NO_MEMORY);
      79                 :            :         }
      80                 :            : 
      81                 :          0 :         *return_object = new_object;
      82                 :          0 :         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                 :          0 : acpi_ns_convert_to_string(union acpi_operand_object *original_object,
     100                 :            :                           union acpi_operand_object **return_object)
     101                 :            : {
     102                 :          0 :         union acpi_operand_object *new_object;
     103                 :          0 :         acpi_size length;
     104                 :          0 :         acpi_status status;
     105                 :            : 
     106      [ #  #  # ]:          0 :         switch (original_object->common.type) {
     107                 :          0 :         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         [ #  # ]:          0 :                 if (original_object->integer.value == 0) {
     114                 :            : 
     115                 :            :                         /* Allocate a new NULL string object */
     116                 :            : 
     117                 :          0 :                         new_object = acpi_ut_create_string_object(0);
     118         [ #  # ]:          0 :                         if (!new_object) {
     119                 :            :                                 return (AE_NO_MEMORY);
     120                 :            :                         }
     121                 :            :                 } else {
     122                 :          0 :                         status = acpi_ex_convert_to_string(original_object,
     123                 :            :                                                            &new_object,
     124                 :            :                                                            ACPI_IMPLICIT_CONVERT_HEX);
     125         [ #  # ]:          0 :                         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         [ #  # ]:          0 :                 while ((length < original_object->buffer.length) &&
     140         [ #  # ]:          0 :                        (original_object->buffer.pointer[length])) {
     141                 :          0 :                         length++;
     142                 :            :                 }
     143                 :            : 
     144                 :            :                 /* Allocate a new string object */
     145                 :            : 
     146                 :          0 :                 new_object = acpi_ut_create_string_object(length);
     147         [ #  # ]:          0 :                 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                 :          0 :                 memcpy(new_object->string.pointer,
     156                 :          0 :                        original_object->buffer.pointer, length);
     157                 :          0 :                 break;
     158                 :            : 
     159                 :            :         default:
     160                 :            : 
     161                 :            :                 return (AE_AML_OPERAND_TYPE);
     162                 :            :         }
     163                 :            : 
     164                 :          0 :         *return_object = new_object;
     165                 :          0 :         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                 :          0 : acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
     183                 :            :                           union acpi_operand_object **return_object)
     184                 :            : {
     185                 :          0 :         union acpi_operand_object *new_object;
     186                 :          0 :         acpi_status status;
     187                 :          0 :         union acpi_operand_object **elements;
     188                 :          0 :         u32 *dword_buffer;
     189                 :          0 :         u32 count;
     190                 :          0 :         u32 i;
     191                 :            : 
     192   [ #  #  #  # ]:          0 :         switch (original_object->common.type) {
     193                 :          0 :         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                 :          0 :                 status =
     202                 :          0 :                     acpi_ex_convert_to_buffer(original_object, &new_object);
     203         [ #  # ]:          0 :                 if (ACPI_FAILURE(status)) {
     204                 :            :                         return (status);
     205                 :            :                 }
     206                 :            :                 break;
     207                 :            : 
     208                 :          0 :         case ACPI_TYPE_STRING:
     209                 :            : 
     210                 :            :                 /* String-to-Buffer conversion. Simple data copy */
     211                 :            : 
     212                 :          0 :                 new_object = acpi_ut_create_buffer_object
     213                 :          0 :                     (original_object->string.length);
     214         [ #  # ]:          0 :                 if (!new_object) {
     215                 :            :                         return (AE_NO_MEMORY);
     216                 :            :                 }
     217                 :            : 
     218                 :          0 :                 memcpy(new_object->buffer.pointer,
     219                 :          0 :                        original_object->string.pointer,
     220                 :          0 :                        original_object->string.length);
     221                 :          0 :                 break;
     222                 :            : 
     223                 :          0 :         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                 :          0 :                 elements = original_object->package.elements;
     233                 :          0 :                 count = original_object->package.count;
     234                 :            : 
     235         [ #  # ]:          0 :                 for (i = 0; i < count; i++) {
     236         [ #  # ]:          0 :                         if ((!*elements) ||
     237         [ #  # ]:          0 :                             ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
     238                 :            :                                 return (AE_AML_OPERAND_TYPE);
     239                 :            :                         }
     240                 :          0 :                         elements++;
     241                 :            :                 }
     242                 :            : 
     243                 :            :                 /* Create the new buffer object to replace the Package */
     244                 :            : 
     245                 :          0 :                 new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
     246         [ #  # ]:          0 :                 if (!new_object) {
     247                 :            :                         return (AE_NO_MEMORY);
     248                 :            :                 }
     249                 :            : 
     250                 :            :                 /* Copy the package elements (integers) to the buffer as DWORDs */
     251                 :            : 
     252                 :          0 :                 elements = original_object->package.elements;
     253                 :          0 :                 dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
     254                 :            : 
     255         [ #  # ]:          0 :                 for (i = 0; i < count; i++) {
     256                 :          0 :                         *dword_buffer = (u32)(*elements)->integer.value;
     257                 :          0 :                         dword_buffer++;
     258                 :          0 :                         elements++;
     259                 :            :                 }
     260                 :            :                 break;
     261                 :            : 
     262                 :            :         default:
     263                 :            : 
     264                 :            :                 return (AE_AML_OPERAND_TYPE);
     265                 :            :         }
     266                 :            : 
     267                 :          0 :         *return_object = new_object;
     268                 :          0 :         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                 :          0 : 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                 :          0 :         union acpi_operand_object *new_object;
     291                 :          0 :         char *ascii_string;
     292                 :          0 :         u16 *unicode_buffer;
     293                 :          0 :         u32 unicode_length;
     294                 :          0 :         u32 i;
     295                 :            : 
     296         [ #  # ]:          0 :         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         [ #  # ]:          0 :         if (original_object->common.type == ACPI_TYPE_BUFFER) {
     303         [ #  # ]:          0 :                 if (original_object->buffer.length < 2) {
     304                 :            :                         return (AE_AML_OPERAND_VALUE);
     305                 :            :                 }
     306                 :            : 
     307                 :          0 :                 *return_object = NULL;
     308                 :          0 :                 return (AE_OK);
     309                 :            :         }
     310                 :            : 
     311                 :            :         /*
     312                 :            :          * The original object is an ASCII string. Convert this string to
     313                 :            :          * a unicode buffer.
     314                 :            :          */
     315                 :          0 :         ascii_string = original_object->string.pointer;
     316                 :          0 :         unicode_length = (original_object->string.length * 2) + 2;
     317                 :            : 
     318                 :            :         /* Create a new buffer object for the Unicode data */
     319                 :            : 
     320                 :          0 :         new_object = acpi_ut_create_buffer_object(unicode_length);
     321         [ #  # ]:          0 :         if (!new_object) {
     322                 :            :                 return (AE_NO_MEMORY);
     323                 :            :         }
     324                 :            : 
     325                 :          0 :         unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer);
     326                 :            : 
     327                 :            :         /* Convert ASCII to Unicode */
     328                 :            : 
     329         [ #  # ]:          0 :         for (i = 0; i < original_object->string.length; i++) {
     330                 :          0 :                 unicode_buffer[i] = (u16)ascii_string[i];
     331                 :            :         }
     332                 :            : 
     333                 :          0 :         *return_object = new_object;
     334                 :          0 :         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                 :        440 : 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                 :        440 :         union acpi_operand_object *new_object;
     358                 :        440 :         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         [ +  - ]:        440 :         if (original_object) {
     370      [ -  +  - ]:        440 :                 switch (original_object->common.type) {
     371                 :          0 :                 case ACPI_TYPE_INTEGER:
     372                 :            : 
     373                 :            :                         /* We can only repair an Integer==0 */
     374                 :            : 
     375         [ #  # ]:          0 :                         if (original_object->integer.value) {
     376                 :            :                                 return (AE_AML_OPERAND_TYPE);
     377                 :            :                         }
     378                 :            :                         break;
     379                 :            : 
     380                 :        440 :                 case ACPI_TYPE_BUFFER:
     381                 :            : 
     382         [ +  - ]:        440 :                         if (original_object->buffer.length) {
     383                 :            : 
     384                 :            :                                 /* Additional checks can be added in the future */
     385                 :            : 
     386                 :        440 :                                 *return_object = NULL;
     387                 :        440 :                                 return (AE_OK);
     388                 :            :                         }
     389                 :            :                         break;
     390                 :            : 
     391                 :            :                 case ACPI_TYPE_STRING:
     392                 :            :                 default:
     393                 :            : 
     394                 :            :                         return (AE_AML_OPERAND_TYPE);
     395                 :            :                 }
     396                 :          0 :         }
     397                 :            : 
     398                 :            :         /* Create the new buffer object for the resource descriptor */
     399                 :            : 
     400                 :          0 :         new_object = acpi_ut_create_buffer_object(2);
     401         [ #  # ]:          0 :         if (!new_object) {
     402                 :            :                 return (AE_NO_MEMORY);
     403                 :            :         }
     404                 :            : 
     405                 :          0 :         buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);
     406                 :            : 
     407                 :            :         /* Initialize the Buffer with a single end_tag descriptor */
     408                 :            : 
     409                 :          0 :         buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
     410                 :          0 :         buffer[1] = 0x00;
     411                 :            : 
     412                 :          0 :         *return_object = new_object;
     413                 :          0 :         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                 :          0 : 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                 :          0 :         union acpi_operand_object *new_object = NULL;
     437                 :          0 :         acpi_status status;
     438                 :          0 :         struct acpi_namespace_node *node;
     439                 :          0 :         union acpi_generic_state scope_info;
     440                 :          0 :         char *name;
     441                 :            : 
     442                 :          0 :         ACPI_FUNCTION_NAME(ns_convert_to_reference);
     443                 :            : 
     444                 :            :         /* Convert path into internal presentation */
     445                 :            : 
     446                 :          0 :         status =
     447                 :          0 :             acpi_ns_internalize_name(original_object->string.pointer, &name);
     448         [ #  # ]:          0 :         if (ACPI_FAILURE(status)) {
     449                 :            :                 return_ACPI_STATUS(status);
     450                 :            :         }
     451                 :            : 
     452                 :            :         /* Find the namespace node */
     453                 :            : 
     454                 :          0 :         scope_info.scope.node =
     455                 :            :             ACPI_CAST_PTR(struct acpi_namespace_node, scope);
     456                 :          0 :         status =
     457                 :          0 :             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         [ #  # ]:          0 :         if (ACPI_FAILURE(status)) {
     461                 :            : 
     462                 :            :                 /* Check if we are resolving a named reference within a package */
     463                 :            : 
     464                 :          0 :                 ACPI_ERROR_NAMESPACE(&scope_info,
     465                 :          0 :                                      original_object->string.pointer, status);
     466                 :          0 :                 goto error_exit;
     467                 :            :         }
     468                 :            : 
     469                 :            :         /* Create and init a new internal ACPI object */
     470                 :            : 
     471                 :          0 :         new_object = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
     472         [ #  # ]:          0 :         if (!new_object) {
     473                 :          0 :                 status = AE_NO_MEMORY;
     474                 :          0 :                 goto error_exit;
     475                 :            :         }
     476                 :          0 :         new_object->reference.node = node;
     477                 :          0 :         new_object->reference.object = node->object;
     478                 :          0 :         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                 :          0 :         acpi_ut_add_reference(node->object);
     485                 :            : 
     486                 :          0 : error_exit:
     487                 :          0 :         ACPI_FREE(name);
     488                 :          0 :         *return_object = new_object;
     489                 :          0 :         return (status);
     490                 :            : }

Generated by: LCOV version 1.14