* PARAMETERS: obj_desc - Object to be converted. Must be an
* Integer, Buffer, or String
* result_desc - Where the new Integer object is returned
- * Flags - Used for string conversion
+ * walk_state - Current method state
*
* RETURN: Status
*
acpi_ex_convert_to_integer (
union acpi_operand_object *obj_desc,
union acpi_operand_object **result_desc,
- u32 flags)
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *return_desc;
- u8 *pointer;
- acpi_integer result;
u32 i;
+ union acpi_operand_object *ret_desc;
u32 count;
+ u8 *pointer;
+ acpi_integer result;
acpi_status status;
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
case ACPI_TYPE_INTEGER:
-
- /* No conversion necessary */
-
*result_desc = obj_desc;
return_ACPI_STATUS (AE_OK);
- case ACPI_TYPE_BUFFER:
case ACPI_TYPE_STRING:
+ pointer = (u8 *) obj_desc->string.pointer;
+ count = obj_desc->string.length;
+ break;
- /* Note: Takes advantage of common buffer/string fields */
-
+ case ACPI_TYPE_BUFFER:
pointer = obj_desc->buffer.pointer;
count = obj_desc->buffer.length;
break;
case ACPI_TYPE_STRING:
/*
- * Convert string to an integer - for most cases, the string must be
- * hexadecimal as per the ACPI specification. The only exception (as
- * of ACPI 3.0) is that the to_integer() operator allows both decimal
- * and hexadecimal strings (hex prefixed with "0x").
+ * Convert string to an integer
+ * String must be hexadecimal as per the ACPI specification
*/
- status = acpi_ut_strtoul64 ((char *) pointer, flags, &result);
+ status = acpi_ut_strtoul64 ((char *) pointer, 16, &result);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
case ACPI_TYPE_BUFFER:
/*
- * Convert buffer to an integer - we simply grab enough raw data
- * from the buffer to fill an integer
+ * Buffer conversion - we simply grab enough raw data from the
+ * buffer to fill an integer
*/
for (i = 0; i < count; i++) {
/*
/*
* Create a new integer
*/
- return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
- if (!return_desc) {
+ ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ if (!ret_desc) {
return_ACPI_STATUS (AE_NO_MEMORY);
}
/* Save the Result */
- return_desc->integer.value = result;
- *result_desc = return_desc;
+ ret_desc->integer.value = result;
+
+ /*
+ * If we are about to overwrite the original object on the operand stack,
+ * we must remove a reference on the original object because we are
+ * essentially removing it from the stack.
+ */
+ if (*result_desc == obj_desc) {
+ if (walk_state->opcode != AML_STORE_OP) {
+ acpi_ut_remove_reference (obj_desc);
+ }
+ }
+
+ *result_desc = ret_desc;
return_ACPI_STATUS (AE_OK);
}
* PARAMETERS: obj_desc - Object to be converted. Must be an
* Integer, Buffer, or String
* result_desc - Where the new buffer object is returned
+ * walk_state - Current method state
*
* RETURN: Status
*
acpi_status
acpi_ex_convert_to_buffer (
union acpi_operand_object *obj_desc,
- union acpi_operand_object **result_desc)
+ union acpi_operand_object **result_desc,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *return_desc;
+ union acpi_operand_object *ret_desc;
+ u32 i;
u8 *new_buf;
* Create a new Buffer object.
* Need enough space for one integer
*/
- return_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width);
- if (!return_desc) {
+ ret_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width);
+ if (!ret_desc) {
return_ACPI_STATUS (AE_NO_MEMORY);
}
- /* Copy the integer to the buffer, LSB first */
+ /* Copy the integer to the buffer */
- new_buf = return_desc->buffer.pointer;
- ACPI_MEMCPY (new_buf,
- &obj_desc->integer.value,
- acpi_gbl_integer_byte_width);
+ new_buf = ret_desc->buffer.pointer;
+ for (i = 0; i < acpi_gbl_integer_byte_width; i++) {
+ new_buf[i] = (u8) (obj_desc->integer.value >> (i * 8));
+ }
break;
* Create a new Buffer object
* Size will be the string length
*/
- return_desc = acpi_ut_create_buffer_object ((acpi_size) obj_desc->string.length);
- if (!return_desc) {
+ ret_desc = acpi_ut_create_buffer_object ((acpi_size) obj_desc->string.length);
+ if (!ret_desc) {
return_ACPI_STATUS (AE_NO_MEMORY);
}
/* Copy the string to the buffer */
- new_buf = return_desc->buffer.pointer;
+ new_buf = ret_desc->buffer.pointer;
ACPI_STRNCPY ((char *) new_buf, (char *) obj_desc->string.pointer,
obj_desc->string.length);
break;
/* Mark buffer initialized */
- return_desc->common.flags |= AOPOBJ_DATA_VALID;
- *result_desc = return_desc;
+ ret_desc->common.flags |= AOPOBJ_DATA_VALID;
+
+ /*
+ * If we are about to overwrite the original object on the operand stack,
+ * we must remove a reference on the original object because we are
+ * essentially removing it from the stack.
+ */
+ if (*result_desc == obj_desc) {
+ if (walk_state->opcode != AML_STORE_OP) {
+ acpi_ut_remove_reference (obj_desc);
+ }
+ }
+
+ *result_desc = ret_desc;
return_ACPI_STATUS (AE_OK);
}
/*******************************************************************************
*
- * FUNCTION: acpi_ex_convert_to_ascii
+ * FUNCTION: acpi_ex_convert_ascii
*
* PARAMETERS: Integer - Value to be converted
- * Base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX
+ * Base - 10 or 16
* String - Where the string is returned
- * data_width - Size of data item to be converted, in bytes
+ * data_width - Size of data item to be converted
*
* RETURN: Actual string length
*
u32
acpi_ex_convert_to_ascii (
acpi_integer integer,
- u16 base,
+ u32 base,
u8 *string,
u8 data_width)
{
+ u32 i;
+ u32 j;
+ u32 k = 0;
+ char hex_digit;
acpi_integer digit;
- acpi_native_uint i;
- acpi_native_uint j;
- acpi_native_uint k = 0;
- acpi_native_uint hex_length;
- acpi_native_uint decimal_length;
u32 remainder;
- u8 supress_zeros;
+ u32 length;
+ u8 leading_zero;
ACPI_FUNCTION_ENTRY ();
+ if (data_width < sizeof (acpi_integer)) {
+ leading_zero = FALSE;
+ length = data_width;
+ }
+ else {
+ leading_zero = TRUE;
+ length = sizeof (acpi_integer);
+ }
+
switch (base) {
case 10:
- /* Setup max length for the decimal number */
-
- switch (data_width) {
- case 1:
- decimal_length = ACPI_MAX8_DECIMAL_DIGITS;
- break;
-
- case 4:
- decimal_length = ACPI_MAX32_DECIMAL_DIGITS;
- break;
-
- case 8:
- default:
- decimal_length = ACPI_MAX64_DECIMAL_DIGITS;
- break;
- }
-
- supress_zeros = TRUE; /* No leading zeros */
remainder = 0;
-
- for (i = decimal_length; i > 0; i--) {
+ for (i = ACPI_MAX_DECIMAL_DIGITS; i > 0; i--) {
/* Divide by nth factor of 10 */
digit = integer;
for (j = 0; j < i; j++) {
- (void) acpi_ut_short_divide (digit, 10, &digit, &remainder);
+ (void) acpi_ut_short_divide (&digit, 10, &digit, &remainder);
}
- /* Handle leading zeros */
+ /* Create the decimal digit */
if (remainder != 0) {
- supress_zeros = FALSE;
+ leading_zero = FALSE;
}
- if (!supress_zeros) {
+ if (!leading_zero) {
string[k] = (u8) (ACPI_ASCII_ZERO + remainder);
k++;
}
}
break;
+
case 16:
- hex_length = ACPI_MUL_2 (data_width); /* 2 ascii hex chars per data byte */
+ /* Copy the integer to the buffer */
- for (i = 0, j = (hex_length-1); i < hex_length; i++, j--) {
- /* Get one hex digit, most significant digits first */
+ for (i = 0, j = ((length * 2) -1); i < (length * 2); i++, j--) {
- string[k] = (u8) acpi_ut_hex_to_ascii_char (integer, ACPI_MUL_4 (j));
- k++;
+ hex_digit = acpi_ut_hex_to_ascii_char (integer, (j * 4));
+ if (hex_digit != ACPI_ASCII_ZERO) {
+ leading_zero = FALSE;
+ }
+
+ if (!leading_zero) {
+ string[k] = (u8) hex_digit;
+ k++;
+ }
}
break;
+
default:
- return (0);
+ break;
}
/*
}
string [k] = 0;
- return ((u32) k);
+ return (k);
}
* FUNCTION: acpi_ex_convert_to_string
*
* PARAMETERS: obj_desc - Object to be converted. Must be an
- * Integer, Buffer, or String
+ * Integer, Buffer, or String
* result_desc - Where the string object is returned
- * Type - String flags (base and conversion type)
+ * Base - 10 or 16
+ * max_length - Max length of the returned string
+ * walk_state - Current method state
*
* RETURN: Status
*
acpi_ex_convert_to_string (
union acpi_operand_object *obj_desc,
union acpi_operand_object **result_desc,
- u32 type)
+ u32 base,
+ u32 max_length,
+ struct acpi_walk_state *walk_state)
{
- union acpi_operand_object *return_desc;
+ union acpi_operand_object *ret_desc;
u8 *new_buf;
- u32 string_length = 0;
- u16 base = 16;
+ u8 *pointer;
+ u32 string_length;
u32 i;
- u8 separator = ',';
ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_string", obj_desc);
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
case ACPI_TYPE_STRING:
- /* No conversion necessary */
+ if (max_length >= obj_desc->string.length) {
+ *result_desc = obj_desc;
+ return_ACPI_STATUS (AE_OK);
+ }
+ else {
+ /* Must copy the string first and then truncate it */
- *result_desc = obj_desc;
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
+ }
case ACPI_TYPE_INTEGER:
- switch (type) {
- case ACPI_EXPLICIT_CONVERT_DECIMAL:
-
- /* Make room for maximum decimal number */
-
+ string_length = acpi_gbl_integer_byte_width * 2;
+ if (base == 10) {
string_length = ACPI_MAX_DECIMAL_DIGITS;
- base = 10;
- break;
-
- default:
-
- /* Two hex string characters for each integer byte */
-
- string_length = ACPI_MUL_2 (acpi_gbl_integer_byte_width);
- break;
}
/*
* Create a new String
- * Need enough space for one ASCII integer (plus null terminator)
*/
- return_desc = acpi_ut_create_string_object ((acpi_size) string_length);
- if (!return_desc) {
+ ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
+ if (!ret_desc) {
return_ACPI_STATUS (AE_NO_MEMORY);
}
- new_buf = return_desc->buffer.pointer;
+ /* Need enough space for one ASCII integer plus null terminator */
- /* Convert integer to string */
+ new_buf = ACPI_MEM_CALLOCATE ((acpi_size) string_length + 1);
+ if (!new_buf) {
+ ACPI_REPORT_ERROR
+ (("ex_convert_to_string: Buffer allocation failure\n"));
+ acpi_ut_remove_reference (ret_desc);
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
- string_length = acpi_ex_convert_to_ascii (obj_desc->integer.value, base,
- new_buf, acpi_gbl_integer_byte_width);
+ /* Convert */
+
+ i = acpi_ex_convert_to_ascii (obj_desc->integer.value, base, new_buf, sizeof (acpi_integer));
/* Null terminate at the correct place */
- return_desc->string.length = string_length;
- new_buf [string_length] = 0;
+ if (max_length < i) {
+ new_buf[max_length] = 0;
+ ret_desc->string.length = max_length;
+ }
+ else {
+ new_buf [i] = 0;
+ ret_desc->string.length = i;
+ }
+
+ ret_desc->buffer.pointer = new_buf;
break;
case ACPI_TYPE_BUFFER:
- switch (type) {
- case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string operator */
- /*
- * From ACPI: "If Data is a buffer, it is converted to a string of
- * decimal values separated by commas."
- */
- base = 10;
- string_length = obj_desc->buffer.length; /* 4 chars for each decimal */
+ /* Find the string length */
- /*lint -fallthrough */
+ pointer = obj_desc->buffer.pointer;
+ for (string_length = 0; string_length < obj_desc->buffer.length; string_length++) {
+ /* Exit on null terminator */
- case ACPI_IMPLICIT_CONVERT_HEX:
- /*
- * From the ACPI spec:
- *"The entire contents of the buffer are converted to a string of
- * two-character hexadecimal numbers, each separated by a space."
- */
- if (type == ACPI_IMPLICIT_CONVERT_HEX) {
- separator = ' ';
+ if (!pointer[string_length]) {
+ break;
}
+ }
- /*lint -fallthrough */
-
- case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string operator */
- /*
- * From ACPI: "If Data is a buffer, it is converted to a string of
- * hexadecimal values separated by commas."
- */
- string_length += (obj_desc->buffer.length * 3);
- if (string_length > ACPI_MAX_STRING_CONVERSION) /* ACPI limit */ {
+ if (max_length > ACPI_MAX_STRING_CONVERSION) {
+ if (string_length > ACPI_MAX_STRING_CONVERSION) {
return_ACPI_STATUS (AE_AML_STRING_LIMIT);
}
+ }
- /* Create a new string object and string buffer */
-
- return_desc = acpi_ut_create_string_object ((acpi_size) string_length -1);
- if (!return_desc) {
- return_ACPI_STATUS (AE_NO_MEMORY);
- }
+ /*
+ * Create a new string object
+ */
+ ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
+ if (!ret_desc) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
- new_buf = return_desc->buffer.pointer;
+ /* String length is the lesser of the Max or the actual length */
- /*
- * Convert buffer bytes to hex or decimal values
- * (separated by commas)
- */
- for (i = 0; i < obj_desc->buffer.length; i++) {
- new_buf += acpi_ex_convert_to_ascii (
- (acpi_integer) obj_desc->buffer.pointer[i], base,
- new_buf, 1);
- *new_buf++ = separator; /* each separated by a comma or space */
- }
+ if (max_length < string_length) {
+ string_length = max_length;
+ }
- /* Null terminate the string (overwrites final comma from above) */
+ new_buf = ACPI_MEM_CALLOCATE ((acpi_size) string_length + 1);
+ if (!new_buf) {
+ ACPI_REPORT_ERROR
+ (("ex_convert_to_string: Buffer allocation failure\n"));
+ acpi_ut_remove_reference (ret_desc);
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
- new_buf--;
- *new_buf = 0;
+ /* Copy the appropriate number of buffer characters */
- /* Recalculate length */
+ ACPI_MEMCPY (new_buf, pointer, string_length);
- return_desc->string.length = ACPI_STRLEN (return_desc->string.pointer);
- break;
+ /* Null terminate */
- default:
- return_ACPI_STATUS (AE_BAD_PARAMETER);
- }
+ new_buf [string_length] = 0;
+ ret_desc->buffer.pointer = new_buf;
+ ret_desc->string.length = string_length;
break;
+
default:
return_ACPI_STATUS (AE_TYPE);
}
- *result_desc = return_desc;
+ /*
+ * If we are about to overwrite the original object on the operand stack,
+ * we must remove a reference on the original object because we are
+ * essentially removing it from the stack.
+ */
+ if (*result_desc == obj_desc) {
+ if (walk_state->opcode != AML_STORE_OP) {
+ acpi_ut_remove_reference (obj_desc);
+ }
+ }
+
+ *result_desc = ret_desc;
return_ACPI_STATUS (AE_OK);
}
* These types require an Integer operand. We can convert
* a Buffer or a String to an Integer if necessary.
*/
- status = acpi_ex_convert_to_integer (source_desc, result_desc,
- 16);
+ status = acpi_ex_convert_to_integer (source_desc, result_desc, walk_state);
break;
* The operand must be a String. We can convert an
* Integer or Buffer if necessary
*/
- status = acpi_ex_convert_to_string (source_desc, result_desc,
- ACPI_IMPLICIT_CONVERT_HEX);
+ status = acpi_ex_convert_to_string (source_desc, result_desc, 16, ACPI_UINT32_MAX, walk_state);
break;
* The operand must be a Buffer. We can convert an
* Integer or String if necessary
*/
- status = acpi_ex_convert_to_buffer (source_desc, result_desc);
+ status = acpi_ex_convert_to_buffer (source_desc, result_desc, walk_state);
break;