195b482a8SLen Brown /****************************************************************************** 295b482a8SLen Brown * 395b482a8SLen Brown * Module Name: exconvrt - Object conversion routines 495b482a8SLen Brown * 595b482a8SLen Brown *****************************************************************************/ 695b482a8SLen Brown 795b482a8SLen Brown /* 882a80941SDavid E. Box * Copyright (C) 2000 - 2015, Intel Corp. 995b482a8SLen Brown * All rights reserved. 1095b482a8SLen Brown * 1195b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 1295b482a8SLen Brown * modification, are permitted provided that the following conditions 1395b482a8SLen Brown * are met: 1495b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 1595b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 1695b482a8SLen Brown * without modification. 1795b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1895b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 1995b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 2095b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 2195b482a8SLen Brown * binary redistribution. 2295b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 2395b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 2495b482a8SLen Brown * from this software without specific prior written permission. 2595b482a8SLen Brown * 2695b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 2795b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 2895b482a8SLen Brown * Software Foundation. 2995b482a8SLen Brown * 3095b482a8SLen Brown * NO WARRANTY 3195b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3295b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3395b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3495b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3595b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3695b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3795b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3895b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3995b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4095b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4195b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 4295b482a8SLen Brown */ 4395b482a8SLen Brown 4495b482a8SLen Brown #include <acpi/acpi.h> 45e2f7a777SLen Brown #include "accommon.h" 46e2f7a777SLen Brown #include "acinterp.h" 47e2f7a777SLen Brown #include "amlcode.h" 4895b482a8SLen Brown 4995b482a8SLen Brown #define _COMPONENT ACPI_EXECUTER 5095b482a8SLen Brown ACPI_MODULE_NAME("exconvrt") 5195b482a8SLen Brown 5295b482a8SLen Brown /* Local prototypes */ 5395b482a8SLen Brown static u32 545df7e6cbSBob Moore acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 max_length); 5595b482a8SLen Brown 5695b482a8SLen Brown /******************************************************************************* 5795b482a8SLen Brown * 5895b482a8SLen Brown * FUNCTION: acpi_ex_convert_to_integer 5995b482a8SLen Brown * 6095b482a8SLen Brown * PARAMETERS: obj_desc - Object to be converted. Must be an 6195b482a8SLen Brown * Integer, Buffer, or String 6295b482a8SLen Brown * result_desc - Where the new Integer object is returned 63ba494beeSBob Moore * flags - Used for string conversion 6495b482a8SLen Brown * 6595b482a8SLen Brown * RETURN: Status 6695b482a8SLen Brown * 6795b482a8SLen Brown * DESCRIPTION: Convert an ACPI Object to an integer. 6895b482a8SLen Brown * 6995b482a8SLen Brown ******************************************************************************/ 7095b482a8SLen Brown 7195b482a8SLen Brown acpi_status 7295b482a8SLen Brown acpi_ex_convert_to_integer(union acpi_operand_object *obj_desc, 7395b482a8SLen Brown union acpi_operand_object **result_desc, u32 flags) 7495b482a8SLen Brown { 7595b482a8SLen Brown union acpi_operand_object *return_desc; 7695b482a8SLen Brown u8 *pointer; 775df7e6cbSBob Moore u64 result; 7895b482a8SLen Brown u32 i; 7995b482a8SLen Brown u32 count; 8095b482a8SLen Brown acpi_status status; 8195b482a8SLen Brown 8295b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_convert_to_integer, obj_desc); 8395b482a8SLen Brown 843371c19cSBob Moore switch (obj_desc->common.type) { 8595b482a8SLen Brown case ACPI_TYPE_INTEGER: 8695b482a8SLen Brown 8795b482a8SLen Brown /* No conversion necessary */ 8895b482a8SLen Brown 8995b482a8SLen Brown *result_desc = obj_desc; 9095b482a8SLen Brown return_ACPI_STATUS(AE_OK); 9195b482a8SLen Brown 9295b482a8SLen Brown case ACPI_TYPE_BUFFER: 9395b482a8SLen Brown case ACPI_TYPE_STRING: 9495b482a8SLen Brown 9595b482a8SLen Brown /* Note: Takes advantage of common buffer/string fields */ 9695b482a8SLen Brown 9795b482a8SLen Brown pointer = obj_desc->buffer.pointer; 9895b482a8SLen Brown count = obj_desc->buffer.length; 9995b482a8SLen Brown break; 10095b482a8SLen Brown 10195b482a8SLen Brown default: 1021d1ea1b7SChao Guan 10395b482a8SLen Brown return_ACPI_STATUS(AE_TYPE); 10495b482a8SLen Brown } 10595b482a8SLen Brown 10695b482a8SLen Brown /* 10795b482a8SLen Brown * Convert the buffer/string to an integer. Note that both buffers and 10895b482a8SLen Brown * strings are treated as raw data - we don't convert ascii to hex for 10995b482a8SLen Brown * strings. 11095b482a8SLen Brown * 11195b482a8SLen Brown * There are two terminating conditions for the loop: 11295b482a8SLen Brown * 1) The size of an integer has been reached, or 11395b482a8SLen Brown * 2) The end of the buffer or string has been reached 11495b482a8SLen Brown */ 11595b482a8SLen Brown result = 0; 11695b482a8SLen Brown 11795b482a8SLen Brown /* String conversion is different than Buffer conversion */ 11895b482a8SLen Brown 1193371c19cSBob Moore switch (obj_desc->common.type) { 12095b482a8SLen Brown case ACPI_TYPE_STRING: 12195b482a8SLen Brown /* 12295b482a8SLen Brown * Convert string to an integer - for most cases, the string must be 12395b482a8SLen Brown * hexadecimal as per the ACPI specification. The only exception (as 12495b482a8SLen Brown * of ACPI 3.0) is that the to_integer() operator allows both decimal 12595b482a8SLen Brown * and hexadecimal strings (hex prefixed with "0x"). 12695b482a8SLen Brown */ 12795b482a8SLen Brown status = acpi_ut_strtoul64((char *)pointer, flags, &result); 12895b482a8SLen Brown if (ACPI_FAILURE(status)) { 12995b482a8SLen Brown return_ACPI_STATUS(status); 13095b482a8SLen Brown } 13195b482a8SLen Brown break; 13295b482a8SLen Brown 13395b482a8SLen Brown case ACPI_TYPE_BUFFER: 13495b482a8SLen Brown 13595b482a8SLen Brown /* Check for zero-length buffer */ 13695b482a8SLen Brown 13795b482a8SLen Brown if (!count) { 13895b482a8SLen Brown return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); 13995b482a8SLen Brown } 14095b482a8SLen Brown 14195b482a8SLen Brown /* Transfer no more than an integer's worth of data */ 14295b482a8SLen Brown 14395b482a8SLen Brown if (count > acpi_gbl_integer_byte_width) { 14495b482a8SLen Brown count = acpi_gbl_integer_byte_width; 14595b482a8SLen Brown } 14695b482a8SLen Brown 14795b482a8SLen Brown /* 14895b482a8SLen Brown * Convert buffer to an integer - we simply grab enough raw data 14995b482a8SLen Brown * from the buffer to fill an integer 15095b482a8SLen Brown */ 15195b482a8SLen Brown for (i = 0; i < count; i++) { 15295b482a8SLen Brown /* 15395b482a8SLen Brown * Get next byte and shift it into the Result. 15495b482a8SLen Brown * Little endian is used, meaning that the first byte of the buffer 15595b482a8SLen Brown * is the LSB of the integer 15695b482a8SLen Brown */ 1575df7e6cbSBob Moore result |= (((u64) pointer[i]) << (i * 8)); 15895b482a8SLen Brown } 15995b482a8SLen Brown break; 16095b482a8SLen Brown 16195b482a8SLen Brown default: 16295b482a8SLen Brown 16395b482a8SLen Brown /* No other types can get here */ 1641d1ea1b7SChao Guan 16595b482a8SLen Brown break; 16695b482a8SLen Brown } 16795b482a8SLen Brown 16895b482a8SLen Brown /* Create a new integer */ 16995b482a8SLen Brown 170dc95a270SBob Moore return_desc = acpi_ut_create_integer_object(result); 17195b482a8SLen Brown if (!return_desc) { 17295b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 17395b482a8SLen Brown } 17495b482a8SLen Brown 17595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", 17695b482a8SLen Brown ACPI_FORMAT_UINT64(result))); 17795b482a8SLen Brown 17895b482a8SLen Brown /* Save the Result */ 17995b482a8SLen Brown 180ef42e53fSBob Moore (void)acpi_ex_truncate_for32bit_table(return_desc); 18195b482a8SLen Brown *result_desc = return_desc; 18295b482a8SLen Brown return_ACPI_STATUS(AE_OK); 18395b482a8SLen Brown } 18495b482a8SLen Brown 18595b482a8SLen Brown /******************************************************************************* 18695b482a8SLen Brown * 18795b482a8SLen Brown * FUNCTION: acpi_ex_convert_to_buffer 18895b482a8SLen Brown * 18995b482a8SLen Brown * PARAMETERS: obj_desc - Object to be converted. Must be an 19095b482a8SLen Brown * Integer, Buffer, or String 19195b482a8SLen Brown * result_desc - Where the new buffer object is returned 19295b482a8SLen Brown * 19395b482a8SLen Brown * RETURN: Status 19495b482a8SLen Brown * 19595b482a8SLen Brown * DESCRIPTION: Convert an ACPI Object to a Buffer 19695b482a8SLen Brown * 19795b482a8SLen Brown ******************************************************************************/ 19895b482a8SLen Brown 19995b482a8SLen Brown acpi_status 20095b482a8SLen Brown acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, 20195b482a8SLen Brown union acpi_operand_object **result_desc) 20295b482a8SLen Brown { 20395b482a8SLen Brown union acpi_operand_object *return_desc; 20495b482a8SLen Brown u8 *new_buf; 20595b482a8SLen Brown 20695b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc); 20795b482a8SLen Brown 2083371c19cSBob Moore switch (obj_desc->common.type) { 20995b482a8SLen Brown case ACPI_TYPE_BUFFER: 21095b482a8SLen Brown 21195b482a8SLen Brown /* No conversion necessary */ 21295b482a8SLen Brown 21395b482a8SLen Brown *result_desc = obj_desc; 21495b482a8SLen Brown return_ACPI_STATUS(AE_OK); 21595b482a8SLen Brown 21695b482a8SLen Brown case ACPI_TYPE_INTEGER: 21795b482a8SLen Brown /* 21895b482a8SLen Brown * Create a new Buffer object. 21995b482a8SLen Brown * Need enough space for one integer 22095b482a8SLen Brown */ 22195b482a8SLen Brown return_desc = 22295b482a8SLen Brown acpi_ut_create_buffer_object(acpi_gbl_integer_byte_width); 22395b482a8SLen Brown if (!return_desc) { 22495b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 22595b482a8SLen Brown } 22695b482a8SLen Brown 22795b482a8SLen Brown /* Copy the integer to the buffer, LSB first */ 22895b482a8SLen Brown 22995b482a8SLen Brown new_buf = return_desc->buffer.pointer; 2304fa4616eSBob Moore memcpy(new_buf, 2314fa4616eSBob Moore &obj_desc->integer.value, acpi_gbl_integer_byte_width); 23295b482a8SLen Brown break; 23395b482a8SLen Brown 23495b482a8SLen Brown case ACPI_TYPE_STRING: 23595b482a8SLen Brown /* 23695b482a8SLen Brown * Create a new Buffer object 23795b482a8SLen Brown * Size will be the string length 23895b482a8SLen Brown * 23995b482a8SLen Brown * NOTE: Add one to the string length to include the null terminator. 24095b482a8SLen Brown * The ACPI spec is unclear on this subject, but there is existing 24195b482a8SLen Brown * ASL/AML code that depends on the null being transferred to the new 24295b482a8SLen Brown * buffer. 24395b482a8SLen Brown */ 24495b482a8SLen Brown return_desc = acpi_ut_create_buffer_object((acpi_size) 24595b482a8SLen Brown obj_desc->string. 24695b482a8SLen Brown length + 1); 24795b482a8SLen Brown if (!return_desc) { 24895b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 24995b482a8SLen Brown } 25095b482a8SLen Brown 25195b482a8SLen Brown /* Copy the string to the buffer */ 25295b482a8SLen Brown 25395b482a8SLen Brown new_buf = return_desc->buffer.pointer; 2544fa4616eSBob Moore strncpy((char *)new_buf, (char *)obj_desc->string.pointer, 25595b482a8SLen Brown obj_desc->string.length); 25695b482a8SLen Brown break; 25795b482a8SLen Brown 25895b482a8SLen Brown default: 2591d1ea1b7SChao Guan 26095b482a8SLen Brown return_ACPI_STATUS(AE_TYPE); 26195b482a8SLen Brown } 26295b482a8SLen Brown 26395b482a8SLen Brown /* Mark buffer initialized */ 26495b482a8SLen Brown 26595b482a8SLen Brown return_desc->common.flags |= AOPOBJ_DATA_VALID; 26695b482a8SLen Brown *result_desc = return_desc; 26795b482a8SLen Brown return_ACPI_STATUS(AE_OK); 26895b482a8SLen Brown } 26995b482a8SLen Brown 27095b482a8SLen Brown /******************************************************************************* 27195b482a8SLen Brown * 27295b482a8SLen Brown * FUNCTION: acpi_ex_convert_to_ascii 27395b482a8SLen Brown * 274ba494beeSBob Moore * PARAMETERS: integer - Value to be converted 275ba494beeSBob Moore * base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX 276ba494beeSBob Moore * string - Where the string is returned 27795b482a8SLen Brown * data_width - Size of data item to be converted, in bytes 27895b482a8SLen Brown * 27995b482a8SLen Brown * RETURN: Actual string length 28095b482a8SLen Brown * 28195b482a8SLen Brown * DESCRIPTION: Convert an ACPI Integer to a hex or decimal string 28295b482a8SLen Brown * 28395b482a8SLen Brown ******************************************************************************/ 28495b482a8SLen Brown 28595b482a8SLen Brown static u32 2865df7e6cbSBob Moore acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 data_width) 28795b482a8SLen Brown { 2885df7e6cbSBob Moore u64 digit; 28995b482a8SLen Brown u32 i; 29095b482a8SLen Brown u32 j; 29195b482a8SLen Brown u32 k = 0; 29295b482a8SLen Brown u32 hex_length; 29395b482a8SLen Brown u32 decimal_length; 29495b482a8SLen Brown u32 remainder; 29595b482a8SLen Brown u8 supress_zeros; 29695b482a8SLen Brown 29795b482a8SLen Brown ACPI_FUNCTION_ENTRY(); 29895b482a8SLen Brown 29995b482a8SLen Brown switch (base) { 30095b482a8SLen Brown case 10: 30195b482a8SLen Brown 30295b482a8SLen Brown /* Setup max length for the decimal number */ 30395b482a8SLen Brown 30495b482a8SLen Brown switch (data_width) { 30595b482a8SLen Brown case 1: 3061d1ea1b7SChao Guan 30795b482a8SLen Brown decimal_length = ACPI_MAX8_DECIMAL_DIGITS; 30895b482a8SLen Brown break; 30995b482a8SLen Brown 31095b482a8SLen Brown case 4: 3111d1ea1b7SChao Guan 31295b482a8SLen Brown decimal_length = ACPI_MAX32_DECIMAL_DIGITS; 31395b482a8SLen Brown break; 31495b482a8SLen Brown 31595b482a8SLen Brown case 8: 31695b482a8SLen Brown default: 3171d1ea1b7SChao Guan 31895b482a8SLen Brown decimal_length = ACPI_MAX64_DECIMAL_DIGITS; 31995b482a8SLen Brown break; 32095b482a8SLen Brown } 32195b482a8SLen Brown 32295b482a8SLen Brown supress_zeros = TRUE; /* No leading zeros */ 32395b482a8SLen Brown remainder = 0; 32495b482a8SLen Brown 32595b482a8SLen Brown for (i = decimal_length; i > 0; i--) { 32695b482a8SLen Brown 32795b482a8SLen Brown /* Divide by nth factor of 10 */ 32895b482a8SLen Brown 32995b482a8SLen Brown digit = integer; 33095b482a8SLen Brown for (j = 0; j < i; j++) { 33195b482a8SLen Brown (void)acpi_ut_short_divide(digit, 10, &digit, 33295b482a8SLen Brown &remainder); 33395b482a8SLen Brown } 33495b482a8SLen Brown 33595b482a8SLen Brown /* Handle leading zeros */ 33695b482a8SLen Brown 33795b482a8SLen Brown if (remainder != 0) { 33895b482a8SLen Brown supress_zeros = FALSE; 33995b482a8SLen Brown } 34095b482a8SLen Brown 34195b482a8SLen Brown if (!supress_zeros) { 34295b482a8SLen Brown string[k] = (u8) (ACPI_ASCII_ZERO + remainder); 34395b482a8SLen Brown k++; 34495b482a8SLen Brown } 34595b482a8SLen Brown } 34695b482a8SLen Brown break; 34795b482a8SLen Brown 34895b482a8SLen Brown case 16: 34995b482a8SLen Brown 35095b482a8SLen Brown /* hex_length: 2 ascii hex chars per data byte */ 35195b482a8SLen Brown 35295b482a8SLen Brown hex_length = ACPI_MUL_2(data_width); 35395b482a8SLen Brown for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) { 35495b482a8SLen Brown 35595b482a8SLen Brown /* Get one hex digit, most significant digits first */ 35695b482a8SLen Brown 35795b482a8SLen Brown string[k] = 35895b482a8SLen Brown (u8) acpi_ut_hex_to_ascii_char(integer, 35995b482a8SLen Brown ACPI_MUL_4(j)); 36095b482a8SLen Brown k++; 36195b482a8SLen Brown } 36295b482a8SLen Brown break; 36395b482a8SLen Brown 36495b482a8SLen Brown default: 36595b482a8SLen Brown return (0); 36695b482a8SLen Brown } 36795b482a8SLen Brown 36895b482a8SLen Brown /* 36995b482a8SLen Brown * Since leading zeros are suppressed, we must check for the case where 37095b482a8SLen Brown * the integer equals 0 37195b482a8SLen Brown * 37295b482a8SLen Brown * Finally, null terminate the string and return the length 37395b482a8SLen Brown */ 37495b482a8SLen Brown if (!k) { 37595b482a8SLen Brown string[0] = ACPI_ASCII_ZERO; 37695b482a8SLen Brown k = 1; 37795b482a8SLen Brown } 37895b482a8SLen Brown 37995b482a8SLen Brown string[k] = 0; 38095b482a8SLen Brown return ((u32) k); 38195b482a8SLen Brown } 38295b482a8SLen Brown 38395b482a8SLen Brown /******************************************************************************* 38495b482a8SLen Brown * 38595b482a8SLen Brown * FUNCTION: acpi_ex_convert_to_string 38695b482a8SLen Brown * 38795b482a8SLen Brown * PARAMETERS: obj_desc - Object to be converted. Must be an 38895b482a8SLen Brown * Integer, Buffer, or String 38995b482a8SLen Brown * result_desc - Where the string object is returned 390ba494beeSBob Moore * type - String flags (base and conversion type) 39195b482a8SLen Brown * 39295b482a8SLen Brown * RETURN: Status 39395b482a8SLen Brown * 39495b482a8SLen Brown * DESCRIPTION: Convert an ACPI Object to a string 39595b482a8SLen Brown * 39695b482a8SLen Brown ******************************************************************************/ 39795b482a8SLen Brown 39895b482a8SLen Brown acpi_status 39995b482a8SLen Brown acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, 40095b482a8SLen Brown union acpi_operand_object ** result_desc, u32 type) 40195b482a8SLen Brown { 40295b482a8SLen Brown union acpi_operand_object *return_desc; 40395b482a8SLen Brown u8 *new_buf; 40495b482a8SLen Brown u32 i; 40595b482a8SLen Brown u32 string_length = 0; 40695b482a8SLen Brown u16 base = 16; 40795b482a8SLen Brown u8 separator = ','; 40895b482a8SLen Brown 40995b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ex_convert_to_string, obj_desc); 41095b482a8SLen Brown 4113371c19cSBob Moore switch (obj_desc->common.type) { 41295b482a8SLen Brown case ACPI_TYPE_STRING: 41395b482a8SLen Brown 41495b482a8SLen Brown /* No conversion necessary */ 41595b482a8SLen Brown 41695b482a8SLen Brown *result_desc = obj_desc; 41795b482a8SLen Brown return_ACPI_STATUS(AE_OK); 41895b482a8SLen Brown 41995b482a8SLen Brown case ACPI_TYPE_INTEGER: 42095b482a8SLen Brown 42195b482a8SLen Brown switch (type) { 42295b482a8SLen Brown case ACPI_EXPLICIT_CONVERT_DECIMAL: 42395b482a8SLen Brown 42495b482a8SLen Brown /* Make room for maximum decimal number */ 42595b482a8SLen Brown 42695b482a8SLen Brown string_length = ACPI_MAX_DECIMAL_DIGITS; 42795b482a8SLen Brown base = 10; 42895b482a8SLen Brown break; 42995b482a8SLen Brown 43095b482a8SLen Brown default: 43195b482a8SLen Brown 43295b482a8SLen Brown /* Two hex string characters for each integer byte */ 43395b482a8SLen Brown 43495b482a8SLen Brown string_length = ACPI_MUL_2(acpi_gbl_integer_byte_width); 43595b482a8SLen Brown break; 43695b482a8SLen Brown } 43795b482a8SLen Brown 43895b482a8SLen Brown /* 43995b482a8SLen Brown * Create a new String 44095b482a8SLen Brown * Need enough space for one ASCII integer (plus null terminator) 44195b482a8SLen Brown */ 44295b482a8SLen Brown return_desc = 44395b482a8SLen Brown acpi_ut_create_string_object((acpi_size) string_length); 44495b482a8SLen Brown if (!return_desc) { 44595b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 44695b482a8SLen Brown } 44795b482a8SLen Brown 44895b482a8SLen Brown new_buf = return_desc->buffer.pointer; 44995b482a8SLen Brown 45095b482a8SLen Brown /* Convert integer to string */ 45195b482a8SLen Brown 45295b482a8SLen Brown string_length = 45395b482a8SLen Brown acpi_ex_convert_to_ascii(obj_desc->integer.value, base, 45495b482a8SLen Brown new_buf, 45595b482a8SLen Brown acpi_gbl_integer_byte_width); 45695b482a8SLen Brown 45795b482a8SLen Brown /* Null terminate at the correct place */ 45895b482a8SLen Brown 45995b482a8SLen Brown return_desc->string.length = string_length; 46095b482a8SLen Brown new_buf[string_length] = 0; 46195b482a8SLen Brown break; 46295b482a8SLen Brown 46395b482a8SLen Brown case ACPI_TYPE_BUFFER: 46495b482a8SLen Brown 46595b482a8SLen Brown /* Setup string length, base, and separator */ 46695b482a8SLen Brown 46795b482a8SLen Brown switch (type) { 46895b482a8SLen Brown case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string */ 46995b482a8SLen Brown /* 47095b482a8SLen Brown * From ACPI: "If Data is a buffer, it is converted to a string of 47195b482a8SLen Brown * decimal values separated by commas." 47295b482a8SLen Brown */ 47395b482a8SLen Brown base = 10; 47495b482a8SLen Brown 47595b482a8SLen Brown /* 47695b482a8SLen Brown * Calculate the final string length. Individual string values 47795b482a8SLen Brown * are variable length (include separator for each) 47895b482a8SLen Brown */ 47995b482a8SLen Brown for (i = 0; i < obj_desc->buffer.length; i++) { 48095b482a8SLen Brown if (obj_desc->buffer.pointer[i] >= 100) { 48195b482a8SLen Brown string_length += 4; 48295b482a8SLen Brown } else if (obj_desc->buffer.pointer[i] >= 10) { 48395b482a8SLen Brown string_length += 3; 48495b482a8SLen Brown } else { 48595b482a8SLen Brown string_length += 2; 48695b482a8SLen Brown } 48795b482a8SLen Brown } 48895b482a8SLen Brown break; 48995b482a8SLen Brown 49095b482a8SLen Brown case ACPI_IMPLICIT_CONVERT_HEX: 49195b482a8SLen Brown /* 49295b482a8SLen Brown * From the ACPI spec: 49395b482a8SLen Brown *"The entire contents of the buffer are converted to a string of 49495b482a8SLen Brown * two-character hexadecimal numbers, each separated by a space." 49595b482a8SLen Brown */ 49695b482a8SLen Brown separator = ' '; 49795b482a8SLen Brown string_length = (obj_desc->buffer.length * 3); 49895b482a8SLen Brown break; 49995b482a8SLen Brown 50095b482a8SLen Brown case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string */ 50195b482a8SLen Brown /* 50295b482a8SLen Brown * From ACPI: "If Data is a buffer, it is converted to a string of 50395b482a8SLen Brown * hexadecimal values separated by commas." 50495b482a8SLen Brown */ 50595b482a8SLen Brown string_length = (obj_desc->buffer.length * 3); 50695b482a8SLen Brown break; 50795b482a8SLen Brown 50895b482a8SLen Brown default: 50995b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 51095b482a8SLen Brown } 51195b482a8SLen Brown 51295b482a8SLen Brown /* 51395b482a8SLen Brown * Create a new string object and string buffer 51495b482a8SLen Brown * (-1 because of extra separator included in string_length from above) 51595b482a8SLen Brown * Allow creation of zero-length strings from zero-length buffers. 51695b482a8SLen Brown */ 51795b482a8SLen Brown if (string_length) { 51895b482a8SLen Brown string_length--; 51995b482a8SLen Brown } 52095b482a8SLen Brown 5211f86e8c1SLv Zheng return_desc = 5221f86e8c1SLv Zheng acpi_ut_create_string_object((acpi_size) string_length); 52395b482a8SLen Brown if (!return_desc) { 52495b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 52595b482a8SLen Brown } 52695b482a8SLen Brown 52795b482a8SLen Brown new_buf = return_desc->buffer.pointer; 52895b482a8SLen Brown 52995b482a8SLen Brown /* 53095b482a8SLen Brown * Convert buffer bytes to hex or decimal values 53195b482a8SLen Brown * (separated by commas or spaces) 53295b482a8SLen Brown */ 53395b482a8SLen Brown for (i = 0; i < obj_desc->buffer.length; i++) { 5345df7e6cbSBob Moore new_buf += acpi_ex_convert_to_ascii((u64) obj_desc-> 5355df7e6cbSBob Moore buffer.pointer[i], 5365df7e6cbSBob Moore base, new_buf, 1); 53795b482a8SLen Brown *new_buf++ = separator; /* each separated by a comma or space */ 53895b482a8SLen Brown } 53995b482a8SLen Brown 54095b482a8SLen Brown /* 54195b482a8SLen Brown * Null terminate the string 54295b482a8SLen Brown * (overwrites final comma/space from above) 54395b482a8SLen Brown */ 54495b482a8SLen Brown if (obj_desc->buffer.length) { 54595b482a8SLen Brown new_buf--; 54695b482a8SLen Brown } 54795b482a8SLen Brown *new_buf = 0; 54895b482a8SLen Brown break; 54995b482a8SLen Brown 55095b482a8SLen Brown default: 5511d1ea1b7SChao Guan 55295b482a8SLen Brown return_ACPI_STATUS(AE_TYPE); 55395b482a8SLen Brown } 55495b482a8SLen Brown 55595b482a8SLen Brown *result_desc = return_desc; 55695b482a8SLen Brown return_ACPI_STATUS(AE_OK); 55795b482a8SLen Brown } 55895b482a8SLen Brown 55995b482a8SLen Brown /******************************************************************************* 56095b482a8SLen Brown * 56195b482a8SLen Brown * FUNCTION: acpi_ex_convert_to_target_type 56295b482a8SLen Brown * 56395b482a8SLen Brown * PARAMETERS: destination_type - Current type of the destination 56495b482a8SLen Brown * source_desc - Source object to be converted. 56595b482a8SLen Brown * result_desc - Where the converted object is returned 56695b482a8SLen Brown * walk_state - Current method state 56795b482a8SLen Brown * 56895b482a8SLen Brown * RETURN: Status 56995b482a8SLen Brown * 57095b482a8SLen Brown * DESCRIPTION: Implements "implicit conversion" rules for storing an object. 57195b482a8SLen Brown * 57295b482a8SLen Brown ******************************************************************************/ 57395b482a8SLen Brown 57495b482a8SLen Brown acpi_status 57595b482a8SLen Brown acpi_ex_convert_to_target_type(acpi_object_type destination_type, 57695b482a8SLen Brown union acpi_operand_object *source_desc, 57795b482a8SLen Brown union acpi_operand_object **result_desc, 57895b482a8SLen Brown struct acpi_walk_state *walk_state) 57995b482a8SLen Brown { 58095b482a8SLen Brown acpi_status status = AE_OK; 58195b482a8SLen Brown 58295b482a8SLen Brown ACPI_FUNCTION_TRACE(ex_convert_to_target_type); 58395b482a8SLen Brown 58495b482a8SLen Brown /* Default behavior */ 58595b482a8SLen Brown 58695b482a8SLen Brown *result_desc = source_desc; 58795b482a8SLen Brown 58895b482a8SLen Brown /* 58995b482a8SLen Brown * If required by the target, 59095b482a8SLen Brown * perform implicit conversion on the source before we store it. 59195b482a8SLen Brown */ 59295b482a8SLen Brown switch (GET_CURRENT_ARG_TYPE(walk_state->op_info->runtime_args)) { 59395b482a8SLen Brown case ARGI_SIMPLE_TARGET: 59495b482a8SLen Brown case ARGI_FIXED_TARGET: 59595b482a8SLen Brown case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ 59695b482a8SLen Brown 59795b482a8SLen Brown switch (destination_type) { 59895b482a8SLen Brown case ACPI_TYPE_LOCAL_REGION_FIELD: 59995b482a8SLen Brown /* 60095b482a8SLen Brown * Named field can always handle conversions 60195b482a8SLen Brown */ 60295b482a8SLen Brown break; 60395b482a8SLen Brown 60495b482a8SLen Brown default: 6051d1ea1b7SChao Guan 60695b482a8SLen Brown /* No conversion allowed for these types */ 60795b482a8SLen Brown 6083371c19cSBob Moore if (destination_type != source_desc->common.type) { 60995b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 61095b482a8SLen Brown "Explicit operator, will store (%s) over existing type (%s)\n", 61195b482a8SLen Brown acpi_ut_get_object_type_name 61295b482a8SLen Brown (source_desc), 61395b482a8SLen Brown acpi_ut_get_type_name 61495b482a8SLen Brown (destination_type))); 61595b482a8SLen Brown status = AE_TYPE; 61695b482a8SLen Brown } 61795b482a8SLen Brown } 61895b482a8SLen Brown break; 61995b482a8SLen Brown 62095b482a8SLen Brown case ARGI_TARGETREF: 621*a5922a1fSBob Moore case ARGI_STORE_TARGET: 62295b482a8SLen Brown 62395b482a8SLen Brown switch (destination_type) { 62495b482a8SLen Brown case ACPI_TYPE_INTEGER: 62595b482a8SLen Brown case ACPI_TYPE_BUFFER_FIELD: 62695b482a8SLen Brown case ACPI_TYPE_LOCAL_BANK_FIELD: 62795b482a8SLen Brown case ACPI_TYPE_LOCAL_INDEX_FIELD: 62895b482a8SLen Brown /* 62995b482a8SLen Brown * These types require an Integer operand. We can convert 63095b482a8SLen Brown * a Buffer or a String to an Integer if necessary. 63195b482a8SLen Brown */ 63295b482a8SLen Brown status = 63395b482a8SLen Brown acpi_ex_convert_to_integer(source_desc, result_desc, 63495b482a8SLen Brown 16); 63595b482a8SLen Brown break; 63695b482a8SLen Brown 63795b482a8SLen Brown case ACPI_TYPE_STRING: 63895b482a8SLen Brown /* 63995b482a8SLen Brown * The operand must be a String. We can convert an 64095b482a8SLen Brown * Integer or Buffer if necessary 64195b482a8SLen Brown */ 64295b482a8SLen Brown status = 64395b482a8SLen Brown acpi_ex_convert_to_string(source_desc, result_desc, 64495b482a8SLen Brown ACPI_IMPLICIT_CONVERT_HEX); 64595b482a8SLen Brown break; 64695b482a8SLen Brown 64795b482a8SLen Brown case ACPI_TYPE_BUFFER: 64895b482a8SLen Brown /* 64995b482a8SLen Brown * The operand must be a Buffer. We can convert an 65095b482a8SLen Brown * Integer or String if necessary 65195b482a8SLen Brown */ 65295b482a8SLen Brown status = 65395b482a8SLen Brown acpi_ex_convert_to_buffer(source_desc, result_desc); 65495b482a8SLen Brown break; 65595b482a8SLen Brown 65695b482a8SLen Brown default: 6571d1ea1b7SChao Guan 65895b482a8SLen Brown ACPI_ERROR((AE_INFO, 659f6a22b0bSBob Moore "Bad destination type during conversion: 0x%X", 66095b482a8SLen Brown destination_type)); 66195b482a8SLen Brown status = AE_AML_INTERNAL; 66295b482a8SLen Brown break; 66395b482a8SLen Brown } 66495b482a8SLen Brown break; 66595b482a8SLen Brown 66695b482a8SLen Brown case ARGI_REFERENCE: 66795b482a8SLen Brown /* 66895b482a8SLen Brown * create_xxxx_field cases - we are storing the field object into the name 66995b482a8SLen Brown */ 67095b482a8SLen Brown break; 67195b482a8SLen Brown 67295b482a8SLen Brown default: 6731d1ea1b7SChao Guan 67495b482a8SLen Brown ACPI_ERROR((AE_INFO, 675f6a22b0bSBob Moore "Unknown Target type ID 0x%X AmlOpcode 0x%X DestType %s", 67695b482a8SLen Brown GET_CURRENT_ARG_TYPE(walk_state->op_info-> 67795b482a8SLen Brown runtime_args), 67895b482a8SLen Brown walk_state->opcode, 67995b482a8SLen Brown acpi_ut_get_type_name(destination_type))); 68095b482a8SLen Brown status = AE_AML_INTERNAL; 68195b482a8SLen Brown } 68295b482a8SLen Brown 68395b482a8SLen Brown /* 68495b482a8SLen Brown * Source-to-Target conversion semantics: 68595b482a8SLen Brown * 68695b482a8SLen Brown * If conversion to the target type cannot be performed, then simply 68795b482a8SLen Brown * overwrite the target with the new object and type. 68895b482a8SLen Brown */ 68995b482a8SLen Brown if (status == AE_TYPE) { 69095b482a8SLen Brown status = AE_OK; 69195b482a8SLen Brown } 69295b482a8SLen Brown 69395b482a8SLen Brown return_ACPI_STATUS(status); 69495b482a8SLen Brown } 695