Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: exconvrt - Object conversion routines
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acinterp.h"
0013 #include "amlcode.h"
0014 
0015 #define _COMPONENT          ACPI_EXECUTER
0016 ACPI_MODULE_NAME("exconvrt")
0017 
0018 /* Local prototypes */
0019 static u32
0020 acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 max_length);
0021 
0022 /*******************************************************************************
0023  *
0024  * FUNCTION:    acpi_ex_convert_to_integer
0025  *
0026  * PARAMETERS:  obj_desc            - Object to be converted. Must be an
0027  *                                    Integer, Buffer, or String
0028  *              result_desc         - Where the new Integer object is returned
0029  *              implicit_conversion - Used for string conversion
0030  *
0031  * RETURN:      Status
0032  *
0033  * DESCRIPTION: Convert an ACPI Object to an integer.
0034  *
0035  ******************************************************************************/
0036 
0037 acpi_status
0038 acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc,
0039                union acpi_operand_object **result_desc,
0040                u32 implicit_conversion)
0041 {
0042     union acpi_operand_object *return_desc;
0043     u8 *pointer;
0044     u64 result;
0045     u32 i;
0046     u32 count;
0047 
0048     ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc);
0049 
0050     switch (obj_desc->common.type) {
0051     case ACPI_TYPE_INTEGER:
0052 
0053         /* No conversion necessary */
0054 
0055         *result_desc = obj_desc;
0056         return_ACPI_STATUS(AE_OK);
0057 
0058     case ACPI_TYPE_BUFFER:
0059     case ACPI_TYPE_STRING:
0060 
0061         /* Note: Takes advantage of common buffer/string fields */
0062 
0063         pointer = obj_desc->buffer.pointer;
0064         count = obj_desc->buffer.length;
0065         break;
0066 
0067     default:
0068 
0069         return_ACPI_STATUS(AE_TYPE);
0070     }
0071 
0072     /*
0073      * Convert the buffer/string to an integer. Note that both buffers and
0074      * strings are treated as raw data - we don't convert ascii to hex for
0075      * strings.
0076      *
0077      * There are two terminating conditions for the loop:
0078      * 1) The size of an integer has been reached, or
0079      * 2) The end of the buffer or string has been reached
0080      */
0081     result = 0;
0082 
0083     /* String conversion is different than Buffer conversion */
0084 
0085     switch (obj_desc->common.type) {
0086     case ACPI_TYPE_STRING:
0087         /*
0088          * Convert string to an integer - for most cases, the string must be
0089          * hexadecimal as per the ACPI specification. The only exception (as
0090          * of ACPI 3.0) is that the to_integer() operator allows both decimal
0091          * and hexadecimal strings (hex prefixed with "0x").
0092          *
0093          * Explicit conversion is used only by to_integer.
0094          * All other string-to-integer conversions are implicit conversions.
0095          */
0096         if (implicit_conversion) {
0097             result =
0098                 acpi_ut_implicit_strtoul64(ACPI_CAST_PTR
0099                                (char, pointer));
0100         } else {
0101             result =
0102                 acpi_ut_explicit_strtoul64(ACPI_CAST_PTR
0103                                (char, pointer));
0104         }
0105         break;
0106 
0107     case ACPI_TYPE_BUFFER:
0108 
0109         /* Check for zero-length buffer */
0110 
0111         if (!count) {
0112             return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
0113         }
0114 
0115         /* Transfer no more than an integer's worth of data */
0116 
0117         if (count > acpi_gbl_integer_byte_width) {
0118             count = acpi_gbl_integer_byte_width;
0119         }
0120 
0121         /*
0122          * Convert buffer to an integer - we simply grab enough raw data
0123          * from the buffer to fill an integer
0124          */
0125         for (i = 0; i < count; i++) {
0126             /*
0127              * Get next byte and shift it into the Result.
0128              * Little endian is used, meaning that the first byte of the buffer
0129              * is the LSB of the integer
0130              */
0131             result |= (((u64) pointer[i]) << (i * 8));
0132         }
0133         break;
0134 
0135     default:
0136 
0137         /* No other types can get here */
0138 
0139         break;
0140     }
0141 
0142     /* Create a new integer */
0143 
0144     return_desc = acpi_ut_create_integer_object(result);
0145     if (!return_desc) {
0146         return_ACPI_STATUS(AE_NO_MEMORY);
0147     }
0148 
0149     ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n",
0150               ACPI_FORMAT_UINT64(result)));
0151 
0152     /* Save the Result */
0153 
0154     (void)acpi_ex_truncate_for32bit_table(return_desc);
0155     *result_desc = return_desc;
0156     return_ACPI_STATUS(AE_OK);
0157 }
0158 
0159 /*******************************************************************************
0160  *
0161  * FUNCTION:    acpi_ex_convert_to_buffer
0162  *
0163  * PARAMETERS:  obj_desc        - Object to be converted. Must be an
0164  *                                Integer, Buffer, or String
0165  *              result_desc     - Where the new buffer object is returned
0166  *
0167  * RETURN:      Status
0168  *
0169  * DESCRIPTION: Convert an ACPI Object to a Buffer
0170  *
0171  ******************************************************************************/
0172 
0173 acpi_status
0174 acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc,
0175               union acpi_operand_object **result_desc)
0176 {
0177     union acpi_operand_object *return_desc;
0178     u8 *new_buf;
0179 
0180     ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc);
0181 
0182     switch (obj_desc->common.type) {
0183     case ACPI_TYPE_BUFFER:
0184 
0185         /* No conversion necessary */
0186 
0187         *result_desc = obj_desc;
0188         return_ACPI_STATUS(AE_OK);
0189 
0190     case ACPI_TYPE_INTEGER:
0191         /*
0192          * Create a new Buffer object.
0193          * Need enough space for one integer
0194          */
0195         return_desc =
0196             acpi_ut_create_buffer_object(acpi_gbl_integer_byte_width);
0197         if (!return_desc) {
0198             return_ACPI_STATUS(AE_NO_MEMORY);
0199         }
0200 
0201         /* Copy the integer to the buffer, LSB first */
0202 
0203         new_buf = return_desc->buffer.pointer;
0204         memcpy(new_buf, &obj_desc->integer.value,
0205                acpi_gbl_integer_byte_width);
0206         break;
0207 
0208     case ACPI_TYPE_STRING:
0209         /*
0210          * Create a new Buffer object
0211          * Size will be the string length
0212          *
0213          * NOTE: Add one to the string length to include the null terminator.
0214          * The ACPI spec is unclear on this subject, but there is existing
0215          * ASL/AML code that depends on the null being transferred to the new
0216          * buffer.
0217          */
0218         return_desc = acpi_ut_create_buffer_object((acpi_size)
0219                                obj_desc->string.
0220                                length + 1);
0221         if (!return_desc) {
0222             return_ACPI_STATUS(AE_NO_MEMORY);
0223         }
0224 
0225         /* Copy the string to the buffer */
0226 
0227         new_buf = return_desc->buffer.pointer;
0228         strncpy((char *)new_buf, (char *)obj_desc->string.pointer,
0229             obj_desc->string.length);
0230         break;
0231 
0232     default:
0233 
0234         return_ACPI_STATUS(AE_TYPE);
0235     }
0236 
0237     /* Mark buffer initialized */
0238 
0239     return_desc->common.flags |= AOPOBJ_DATA_VALID;
0240     *result_desc = return_desc;
0241     return_ACPI_STATUS(AE_OK);
0242 }
0243 
0244 /*******************************************************************************
0245  *
0246  * FUNCTION:    acpi_ex_convert_to_ascii
0247  *
0248  * PARAMETERS:  integer         - Value to be converted
0249  *              base            - ACPI_STRING_DECIMAL or ACPI_STRING_HEX
0250  *              string          - Where the string is returned
0251  *              data_width      - Size of data item to be converted, in bytes
0252  *
0253  * RETURN:      Actual string length
0254  *
0255  * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string
0256  *
0257  ******************************************************************************/
0258 
0259 static u32
0260 acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 data_width)
0261 {
0262     u64 digit;
0263     u32 i;
0264     u32 j;
0265     u32 k = 0;
0266     u32 hex_length;
0267     u32 decimal_length;
0268     u32 remainder;
0269     u8 supress_zeros;
0270 
0271     ACPI_FUNCTION_ENTRY();
0272 
0273     switch (base) {
0274     case 10:
0275 
0276         /* Setup max length for the decimal number */
0277 
0278         switch (data_width) {
0279         case 1:
0280 
0281             decimal_length = ACPI_MAX8_DECIMAL_DIGITS;
0282             break;
0283 
0284         case 4:
0285 
0286             decimal_length = ACPI_MAX32_DECIMAL_DIGITS;
0287             break;
0288 
0289         case 8:
0290         default:
0291 
0292             decimal_length = ACPI_MAX64_DECIMAL_DIGITS;
0293             break;
0294         }
0295 
0296         supress_zeros = TRUE;   /* No leading zeros */
0297         remainder = 0;
0298 
0299         for (i = decimal_length; i > 0; i--) {
0300 
0301             /* Divide by nth factor of 10 */
0302 
0303             digit = integer;
0304             for (j = 0; j < i; j++) {
0305                 (void)acpi_ut_short_divide(digit, 10, &digit,
0306                                &remainder);
0307             }
0308 
0309             /* Handle leading zeros */
0310 
0311             if (remainder != 0) {
0312                 supress_zeros = FALSE;
0313             }
0314 
0315             if (!supress_zeros) {
0316                 string[k] = (u8) (ACPI_ASCII_ZERO + remainder);
0317                 k++;
0318             }
0319         }
0320         break;
0321 
0322     case 16:
0323 
0324         /* hex_length: 2 ascii hex chars per data byte */
0325 
0326         hex_length = (data_width * 2);
0327         for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) {
0328 
0329             /* Get one hex digit, most significant digits first */
0330 
0331             string[k] = (u8)
0332                 acpi_ut_hex_to_ascii_char(integer, ACPI_MUL_4(j));
0333             k++;
0334         }
0335         break;
0336 
0337     default:
0338         return (0);
0339     }
0340 
0341     /*
0342      * Since leading zeros are suppressed, we must check for the case where
0343      * the integer equals 0
0344      *
0345      * Finally, null terminate the string and return the length
0346      */
0347     if (!k) {
0348         string[0] = ACPI_ASCII_ZERO;
0349         k = 1;
0350     }
0351 
0352     string[k] = 0;
0353     return ((u32) k);
0354 }
0355 
0356 /*******************************************************************************
0357  *
0358  * FUNCTION:    acpi_ex_convert_to_string
0359  *
0360  * PARAMETERS:  obj_desc        - Object to be converted. Must be an
0361  *                                Integer, Buffer, or String
0362  *              result_desc     - Where the string object is returned
0363  *              type            - String flags (base and conversion type)
0364  *
0365  * RETURN:      Status
0366  *
0367  * DESCRIPTION: Convert an ACPI Object to a string. Supports both implicit
0368  *              and explicit conversions and related rules.
0369  *
0370  ******************************************************************************/
0371 
0372 acpi_status
0373 acpi_ex_convert_to_string(union acpi_operand_object * obj_desc,
0374               union acpi_operand_object ** result_desc, u32 type)
0375 {
0376     union acpi_operand_object *return_desc;
0377     u8 *new_buf;
0378     u32 i;
0379     u32 string_length = 0;
0380     u16 base = 16;
0381     u8 separator = ',';
0382 
0383     ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc);
0384 
0385     switch (obj_desc->common.type) {
0386     case ACPI_TYPE_STRING:
0387 
0388         /* No conversion necessary */
0389 
0390         *result_desc = obj_desc;
0391         return_ACPI_STATUS(AE_OK);
0392 
0393     case ACPI_TYPE_INTEGER:
0394 
0395         switch (type) {
0396         case ACPI_EXPLICIT_CONVERT_DECIMAL:
0397             /*
0398              * From to_decimal_string, integer source.
0399              *
0400              * Make room for the maximum decimal number size
0401              */
0402             string_length = ACPI_MAX_DECIMAL_DIGITS;
0403             base = 10;
0404             break;
0405 
0406         default:
0407 
0408             /* Two hex string characters for each integer byte */
0409 
0410             string_length = ACPI_MUL_2(acpi_gbl_integer_byte_width);
0411             break;
0412         }
0413 
0414         /*
0415          * Create a new String
0416          * Need enough space for one ASCII integer (plus null terminator)
0417          */
0418         return_desc =
0419             acpi_ut_create_string_object((acpi_size)string_length);
0420         if (!return_desc) {
0421             return_ACPI_STATUS(AE_NO_MEMORY);
0422         }
0423 
0424         new_buf = return_desc->buffer.pointer;
0425 
0426         /* Convert integer to string */
0427 
0428         string_length =
0429             acpi_ex_convert_to_ascii(obj_desc->integer.value, base,
0430                          new_buf,
0431                          acpi_gbl_integer_byte_width);
0432 
0433         /* Null terminate at the correct place */
0434 
0435         return_desc->string.length = string_length;
0436         new_buf[string_length] = 0;
0437         break;
0438 
0439     case ACPI_TYPE_BUFFER:
0440 
0441         /* Setup string length, base, and separator */
0442 
0443         switch (type) {
0444         case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string */
0445             /*
0446              * Explicit conversion from the to_decimal_string ASL operator.
0447              *
0448              * From ACPI: "If the input is a buffer, it is converted to a
0449              * a string of decimal values separated by commas."
0450              */
0451             base = 10;
0452 
0453             /*
0454              * Calculate the final string length. Individual string values
0455              * are variable length (include separator for each)
0456              */
0457             for (i = 0; i < obj_desc->buffer.length; i++) {
0458                 if (obj_desc->buffer.pointer[i] >= 100) {
0459                     string_length += 4;
0460                 } else if (obj_desc->buffer.pointer[i] >= 10) {
0461                     string_length += 3;
0462                 } else {
0463                     string_length += 2;
0464                 }
0465             }
0466             break;
0467 
0468         case ACPI_IMPLICIT_CONVERT_HEX:
0469             /*
0470              * Implicit buffer-to-string conversion
0471              *
0472              * From the ACPI spec:
0473              * "The entire contents of the buffer are converted to a string of
0474              * two-character hexadecimal numbers, each separated by a space."
0475              *
0476              * Each hex number is prefixed with 0x (11/2018)
0477              */
0478             separator = ' ';
0479             string_length = (obj_desc->buffer.length * 5);
0480             break;
0481 
0482         case ACPI_EXPLICIT_CONVERT_HEX:
0483             /*
0484              * Explicit conversion from the to_hex_string ASL operator.
0485              *
0486              * From ACPI: "If Data is a buffer, it is converted to a string of
0487              * hexadecimal values separated by commas."
0488              *
0489              * Each hex number is prefixed with 0x (11/2018)
0490              */
0491             separator = ',';
0492             string_length = (obj_desc->buffer.length * 5);
0493             break;
0494 
0495         default:
0496             return_ACPI_STATUS(AE_BAD_PARAMETER);
0497         }
0498 
0499         /*
0500          * Create a new string object and string buffer
0501          * (-1 because of extra separator included in string_length from above)
0502          * Allow creation of zero-length strings from zero-length buffers.
0503          */
0504         if (string_length) {
0505             string_length--;
0506         }
0507 
0508         return_desc =
0509             acpi_ut_create_string_object((acpi_size)string_length);
0510         if (!return_desc) {
0511             return_ACPI_STATUS(AE_NO_MEMORY);
0512         }
0513 
0514         new_buf = return_desc->buffer.pointer;
0515 
0516         /*
0517          * Convert buffer bytes to hex or decimal values
0518          * (separated by commas or spaces)
0519          */
0520         for (i = 0; i < obj_desc->buffer.length; i++) {
0521             if (base == 16) {
0522 
0523                 /* Emit 0x prefix for explicit/implicit hex conversion */
0524 
0525                 *new_buf++ = '0';
0526                 *new_buf++ = 'x';
0527             }
0528 
0529             new_buf += acpi_ex_convert_to_ascii((u64) obj_desc->
0530                                 buffer.pointer[i],
0531                                 base, new_buf, 1);
0532 
0533             /* Each digit is separated by either a comma or space */
0534 
0535             *new_buf++ = separator;
0536         }
0537 
0538         /*
0539          * Null terminate the string
0540          * (overwrites final comma/space from above)
0541          */
0542         if (obj_desc->buffer.length) {
0543             new_buf--;
0544         }
0545         *new_buf = 0;
0546         break;
0547 
0548     default:
0549 
0550         return_ACPI_STATUS(AE_TYPE);
0551     }
0552 
0553     *result_desc = return_desc;
0554     return_ACPI_STATUS(AE_OK);
0555 }
0556 
0557 /*******************************************************************************
0558  *
0559  * FUNCTION:    acpi_ex_convert_to_target_type
0560  *
0561  * PARAMETERS:  destination_type    - Current type of the destination
0562  *              source_desc         - Source object to be converted.
0563  *              result_desc         - Where the converted object is returned
0564  *              walk_state          - Current method state
0565  *
0566  * RETURN:      Status
0567  *
0568  * DESCRIPTION: Implements "implicit conversion" rules for storing an object.
0569  *
0570  ******************************************************************************/
0571 
0572 acpi_status
0573 acpi_ex_convert_to_target_type(acpi_object_type destination_type,
0574                    union acpi_operand_object *source_desc,
0575                    union acpi_operand_object **result_desc,
0576                    struct acpi_walk_state *walk_state)
0577 {
0578     acpi_status status = AE_OK;
0579 
0580     ACPI_FUNCTION_TRACE(ex_convert_to_target_type);
0581 
0582     /* Default behavior */
0583 
0584     *result_desc = source_desc;
0585 
0586     /*
0587      * If required by the target,
0588      * perform implicit conversion on the source before we store it.
0589      */
0590     switch (GET_CURRENT_ARG_TYPE(walk_state->op_info->runtime_args)) {
0591     case ARGI_SIMPLE_TARGET:
0592     case ARGI_FIXED_TARGET:
0593     case ARGI_INTEGER_REF:  /* Handles Increment, Decrement cases */
0594 
0595         switch (destination_type) {
0596         case ACPI_TYPE_LOCAL_REGION_FIELD:
0597             /*
0598              * Named field can always handle conversions
0599              */
0600             break;
0601 
0602         default:
0603 
0604             /* No conversion allowed for these types */
0605 
0606             if (destination_type != source_desc->common.type) {
0607                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0608                           "Explicit operator, will store (%s) over existing type (%s)\n",
0609                           acpi_ut_get_object_type_name
0610                           (source_desc),
0611                           acpi_ut_get_type_name
0612                           (destination_type)));
0613                 status = AE_TYPE;
0614             }
0615         }
0616         break;
0617 
0618     case ARGI_TARGETREF:
0619     case ARGI_STORE_TARGET:
0620 
0621         switch (destination_type) {
0622         case ACPI_TYPE_INTEGER:
0623         case ACPI_TYPE_BUFFER_FIELD:
0624         case ACPI_TYPE_LOCAL_BANK_FIELD:
0625         case ACPI_TYPE_LOCAL_INDEX_FIELD:
0626             /*
0627              * These types require an Integer operand. We can convert
0628              * a Buffer or a String to an Integer if necessary.
0629              */
0630             status =
0631                 acpi_ex_convert_to_integer(source_desc, result_desc,
0632                                ACPI_IMPLICIT_CONVERSION);
0633             break;
0634 
0635         case ACPI_TYPE_STRING:
0636             /*
0637              * The operand must be a String. We can convert an
0638              * Integer or Buffer if necessary
0639              */
0640             status =
0641                 acpi_ex_convert_to_string(source_desc, result_desc,
0642                               ACPI_IMPLICIT_CONVERT_HEX);
0643             break;
0644 
0645         case ACPI_TYPE_BUFFER:
0646             /*
0647              * The operand must be a Buffer. We can convert an
0648              * Integer or String if necessary
0649              */
0650             status =
0651                 acpi_ex_convert_to_buffer(source_desc, result_desc);
0652             break;
0653 
0654         default:
0655 
0656             ACPI_ERROR((AE_INFO,
0657                     "Bad destination type during conversion: 0x%X",
0658                     destination_type));
0659             status = AE_AML_INTERNAL;
0660             break;
0661         }
0662         break;
0663 
0664     case ARGI_REFERENCE:
0665         /*
0666          * create_xxxx_field cases - we are storing the field object into the name
0667          */
0668         break;
0669 
0670     default:
0671 
0672         ACPI_ERROR((AE_INFO,
0673                 "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s",
0674                 GET_CURRENT_ARG_TYPE(walk_state->op_info->
0675                          runtime_args),
0676                 walk_state->opcode,
0677                 acpi_ut_get_type_name(destination_type)));
0678         status = AE_AML_INTERNAL;
0679     }
0680 
0681     /*
0682      * Source-to-Target conversion semantics:
0683      *
0684      * If conversion to the target type cannot be performed, then simply
0685      * overwrite the target with the new object and type.
0686      */
0687     if (status == AE_TYPE) {
0688         status = AE_OK;
0689     }
0690 
0691     return_ACPI_STATUS(status);
0692 }