acpi_status acpi_ex_do_concatenate ( union acpi_operand_object *obj_desc1, union acpi_operand_object *obj_desc2, union acpi_operand_object **actual_return_desc, struct acpi_walk_state *walk_state) { acpi_status status; u32 i; acpi_integer this_integer; union acpi_operand_object *return_desc; char *new_buf; ACPI_FUNCTION_ENTRY (); /* * There are three cases to handle: * * 1) Two Integers concatenated to produce a new Buffer * 2) Two Strings concatenated to produce a new String * 3) Two Buffers concatenated to produce a new Buffer */ switch (ACPI_GET_OBJECT_TYPE (obj_desc1)) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ /* Need enough buffer space for two integers */ return_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width * 2); if (!return_desc) { return (AE_NO_MEMORY); } new_buf = (char *) return_desc->buffer.pointer; /* Convert the first integer */ this_integer = obj_desc1->integer.value; for (i = 0; i < acpi_gbl_integer_byte_width; i++) { new_buf[i] = (char) this_integer; this_integer >>= 8; } /* Convert the second integer */ this_integer = obj_desc2->integer.value; for (; i < (ACPI_MUL_2 (acpi_gbl_integer_byte_width)); i++) { new_buf[i] = (char) this_integer; this_integer >>= 8; } break; case ACPI_TYPE_STRING: /* Result of two Strings is a String */ return_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING); if (!return_desc) { return (AE_NO_MEMORY); } /* Operand0 is string */ new_buf = ACPI_MEM_CALLOCATE ((acpi_size) obj_desc1->string.length + (acpi_size) obj_desc2->string.length + 1); if (!new_buf) { ACPI_REPORT_ERROR (("ex_do_concatenate: String allocation failure\n")); status = AE_NO_MEMORY; goto cleanup; } /* Concatenate the strings */ ACPI_STRCPY (new_buf, obj_desc1->string.pointer); ACPI_STRCPY (new_buf + obj_desc1->string.length, obj_desc2->string.pointer); /* Complete the String object initialization */ return_desc->string.pointer = new_buf; return_desc->string.length = obj_desc1->string.length + obj_desc2->string.length; break; case ACPI_TYPE_BUFFER: /* Result of two Buffers is a Buffer */ return_desc = acpi_ut_create_buffer_object ( (acpi_size) obj_desc1->buffer.length + (acpi_size) obj_desc2->buffer.length); if (!return_desc) { return (AE_NO_MEMORY); } new_buf = (char *) return_desc->buffer.pointer; /* Concatenate the buffers */ ACPI_MEMCPY (new_buf, obj_desc1->buffer.pointer, obj_desc1->buffer.length); ACPI_MEMCPY (new_buf + obj_desc1->buffer.length, obj_desc2->buffer.pointer, obj_desc2->buffer.length); break; default: /* Invalid object type, should not happen here */ ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n", ACPI_GET_OBJECT_TYPE (obj_desc1))); status = AE_AML_INTERNAL; return_desc = NULL; } *actual_return_desc = return_desc; return (AE_OK); cleanup: acpi_ut_remove_reference (return_desc); return (status); }
static UINT32 AcpiExConvertToAscii ( UINT64 Integer, UINT16 Base, UINT8 *String, UINT8 DataWidth) { UINT64 Digit; UINT32 i; UINT32 j; UINT32 k = 0; UINT32 HexLength; UINT32 DecimalLength; UINT32 Remainder; BOOLEAN SupressZeros; ACPI_FUNCTION_ENTRY (); switch (Base) { case 10: /* Setup max length for the decimal number */ switch (DataWidth) { case 1: DecimalLength = ACPI_MAX8_DECIMAL_DIGITS; break; case 4: DecimalLength = ACPI_MAX32_DECIMAL_DIGITS; break; case 8: default: DecimalLength = ACPI_MAX64_DECIMAL_DIGITS; break; } SupressZeros = TRUE; /* No leading zeros */ Remainder = 0; for (i = DecimalLength; i > 0; i--) { /* Divide by nth factor of 10 */ Digit = Integer; for (j = 0; j < i; j++) { (void) AcpiUtShortDivide (Digit, 10, &Digit, &Remainder); } /* Handle leading zeros */ if (Remainder != 0) { SupressZeros = FALSE; } if (!SupressZeros) { String[k] = (UINT8) (ACPI_ASCII_ZERO + Remainder); k++; } } break; case 16: /* HexLength: 2 ascii hex chars per data byte */ HexLength = ACPI_MUL_2 (DataWidth); for (i = 0, j = (HexLength-1); i < HexLength; i++, j--) { /* Get one hex digit, most significant digits first */ String[k] = (UINT8) AcpiUtHexToAsciiChar (Integer, ACPI_MUL_4 (j)); k++; } break; default: return (0); } /* * Since leading zeros are suppressed, we must check for the case where * the integer equals 0 * * Finally, null terminate the string and return the length */ if (!k) { String [0] = ACPI_ASCII_ZERO; k = 1; } String [k] = 0; return ((UINT32) k); }
ACPI_STATUS AcpiExConvertToString ( ACPI_OPERAND_OBJECT *ObjDesc, ACPI_OPERAND_OBJECT **ResultDesc, UINT32 Type) { ACPI_OPERAND_OBJECT *ReturnDesc; UINT8 *NewBuf; UINT32 i; UINT32 StringLength = 0; UINT16 Base = 16; UINT8 Separator = ','; ACPI_FUNCTION_TRACE_PTR (ExConvertToString, ObjDesc); switch (ObjDesc->Common.Type) { case ACPI_TYPE_STRING: /* No conversion necessary */ *ResultDesc = ObjDesc; return_ACPI_STATUS (AE_OK); case ACPI_TYPE_INTEGER: switch (Type) { case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Make room for maximum decimal number */ StringLength = ACPI_MAX_DECIMAL_DIGITS; Base = 10; break; default: /* Two hex string characters for each integer byte */ StringLength = ACPI_MUL_2 (AcpiGbl_IntegerByteWidth); break; } /* * Create a new String * Need enough space for one ASCII integer (plus null terminator) */ ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength); if (!ReturnDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } NewBuf = ReturnDesc->Buffer.Pointer; /* Convert integer to string */ StringLength = AcpiExConvertToAscii (ObjDesc->Integer.Value, Base, NewBuf, AcpiGbl_IntegerByteWidth); /* Null terminate at the correct place */ ReturnDesc->String.Length = StringLength; NewBuf [StringLength] = 0; break; case ACPI_TYPE_BUFFER: /* Setup string length, base, and separator */ switch (Type) { case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by ToDecimalString */ /* * From ACPI: "If Data is a buffer, it is converted to a string of * decimal values separated by commas." */ Base = 10; /* * Calculate the final string length. Individual string values * are variable length (include separator for each) */ for (i = 0; i < ObjDesc->Buffer.Length; i++) { if (ObjDesc->Buffer.Pointer[i] >= 100) { StringLength += 4; } else if (ObjDesc->Buffer.Pointer[i] >= 10) { StringLength += 3; } else { StringLength += 2; } } break; 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." */ Separator = ' '; StringLength = (ObjDesc->Buffer.Length * 3); break; case ACPI_EXPLICIT_CONVERT_HEX: /* Used by ToHexString */ /* * From ACPI: "If Data is a buffer, it is converted to a string of * hexadecimal values separated by commas." */ StringLength = (ObjDesc->Buffer.Length * 3); break; default: return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Create a new string object and string buffer * (-1 because of extra separator included in StringLength from above) * Allow creation of zero-length strings from zero-length buffers. */ if (StringLength) { StringLength--; } ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) StringLength); if (!ReturnDesc) { return_ACPI_STATUS (AE_NO_MEMORY); } NewBuf = ReturnDesc->Buffer.Pointer; /* * Convert buffer bytes to hex or decimal values * (separated by commas or spaces) */ for (i = 0; i < ObjDesc->Buffer.Length; i++) { NewBuf += AcpiExConvertToAscii ( (UINT64) ObjDesc->Buffer.Pointer[i], Base, NewBuf, 1); *NewBuf++ = Separator; /* each separated by a comma or space */ } /* * Null terminate the string * (overwrites final comma/space from above) */ if (ObjDesc->Buffer.Length) { NewBuf--; } *NewBuf = 0; break; default: return_ACPI_STATUS (AE_TYPE); } *ResultDesc = ReturnDesc; return_ACPI_STATUS (AE_OK); }
static u32 acpi_ex_convert_to_ascii(acpi_integer integer, u16 base, u8 * string, u8 data_width) { 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; ACPI_FUNCTION_ENTRY(); 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--) { /* Divide by nth factor of 10 */ digit = integer; for (j = 0; j < i; j++) { (void)acpi_ut_short_divide(digit, 10, &digit, &remainder); } /* Handle leading zeros */ if (remainder != 0) { supress_zeros = FALSE; } if (!supress_zeros) { string[k] = (u8) (ACPI_ASCII_ZERO + remainder); k++; } } break; case 16: /* hex_length: 2 ascii hex chars per data byte */ hex_length = (acpi_native_uint) ACPI_MUL_2(data_width); for (i = 0, j = (hex_length - 1); i < hex_length; i++, j--) { /* Get one hex digit, most significant digits first */ string[k] = (u8) acpi_ut_hex_to_ascii_char(integer, ACPI_MUL_4(j)); k++; } break; default: return (0); } /* * Since leading zeros are supressed, we must check for the case where * the integer equals 0 * * Finally, null terminate the string and return the length */ if (!k) { string[0] = ACPI_ASCII_ZERO; k = 1; } string[k] = 0; return ((u32) k); }
acpi_status acpi_ex_convert_to_string(union acpi_operand_object * obj_desc, union acpi_operand_object ** result_desc, u32 type) { union acpi_operand_object *return_desc; u8 *new_buf; u32 i; u32 string_length = 0; u16 base = 16; 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 */ *result_desc = obj_desc; return_ACPI_STATUS(AE_OK); case ACPI_TYPE_INTEGER: switch (type) { case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Make room for maximum decimal number */ 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) { return_ACPI_STATUS(AE_NO_MEMORY); } new_buf = return_desc->buffer.pointer; /* Convert integer to string */ string_length = acpi_ex_convert_to_ascii(obj_desc->integer.value, base, new_buf, acpi_gbl_integer_byte_width); /* Null terminate at the correct place */ return_desc->string.length = string_length; new_buf[string_length] = 0; break; case ACPI_TYPE_BUFFER: /* Setup string length, base, and separator */ switch (type) { case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string */ /* * From ACPI: "If Data is a buffer, it is converted to a string of * decimal values separated by commas." */ base = 10; /* * Calculate the final string length. Individual string values * are variable length (include separator for each) */ for (i = 0; i < obj_desc->buffer.length; i++) { if (obj_desc->buffer.pointer[i] >= 100) { string_length += 4; } else if (obj_desc->buffer.pointer[i] >= 10) { string_length += 3; } else { string_length += 2; } } break; 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." */ separator = ' '; string_length = (obj_desc->buffer.length * 3); break; case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string */ /* * 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); break; default: return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * Create a new string object and string buffer * (-1 because of extra separator included in string_length from above) */ return_desc = acpi_ut_create_string_object((acpi_size) (string_length - 1)); if (!return_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } new_buf = return_desc->buffer.pointer; /* * Convert buffer bytes to hex or decimal values * (separated by commas or spaces) */ 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 */ } /* * Null terminate the string * (overwrites final comma/space from above) */ new_buf--; *new_buf = 0; break; default: return_ACPI_STATUS(AE_TYPE); } *result_desc = return_desc; return_ACPI_STATUS(AE_OK); }
acpi_status acpi_ex_do_concatenate(union acpi_operand_object *operand0, union acpi_operand_object *operand1, union acpi_operand_object **actual_return_desc, struct acpi_walk_state *walk_state) { union acpi_operand_object *local_operand0 = operand0; union acpi_operand_object *local_operand1 = operand1; union acpi_operand_object *temp_operand1 = NULL; union acpi_operand_object *return_desc; char *buffer; acpi_object_type operand0_type; acpi_object_type operand1_type; acpi_status status; ACPI_FUNCTION_TRACE(ex_do_concatenate); /* Operand 0 preprocessing */ switch (operand0->common.type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: operand0_type = operand0->common.type; break; default: /* For all other types, get the "object type" string */ status = acpi_ex_convert_to_object_type_string(operand0, &local_operand0); if (ACPI_FAILURE(status)) { goto cleanup; } operand0_type = ACPI_TYPE_STRING; break; } /* Operand 1 preprocessing */ switch (operand1->common.type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: operand1_type = operand1->common.type; break; default: /* For all other types, get the "object type" string */ status = acpi_ex_convert_to_object_type_string(operand1, &local_operand1); if (ACPI_FAILURE(status)) { goto cleanup; } operand1_type = ACPI_TYPE_STRING; break; } /* * Convert the second operand if necessary. The first operand (0) * determines the type of the second operand (1) (See the Data Types * section of the ACPI specification). Both object types are * guaranteed to be either Integer/String/Buffer by the operand * resolution mechanism. */ switch (operand0_type) { case ACPI_TYPE_INTEGER: status = acpi_ex_convert_to_integer(local_operand1, &temp_operand1, 16); break; case ACPI_TYPE_BUFFER: status = acpi_ex_convert_to_buffer(local_operand1, &temp_operand1); break; case ACPI_TYPE_STRING: switch (operand1_type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* Other types have already been converted to string */ status = acpi_ex_convert_to_string(local_operand1, &temp_operand1, ACPI_IMPLICIT_CONVERT_HEX); break; default: status = AE_OK; break; } break; default: ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X", operand0->common.type)); status = AE_AML_INTERNAL; } if (ACPI_FAILURE(status)) { goto cleanup; } /* Take care with any newly created operand objects */ if ((local_operand1 != operand1) && (local_operand1 != temp_operand1)) { acpi_ut_remove_reference(local_operand1); } local_operand1 = temp_operand1; /* * Both operands are now known to be the same object type * (Both are Integer, String, or Buffer), and we can now perform * the concatenation. * * There are three cases to handle, as per the ACPI spec: * * 1) Two Integers concatenated to produce a new Buffer * 2) Two Strings concatenated to produce a new String * 3) Two Buffers concatenated to produce a new Buffer */ switch (operand0_type) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ /* Need enough buffer space for two integers */ return_desc = acpi_ut_create_buffer_object((acpi_size) ACPI_MUL_2 (acpi_gbl_integer_byte_width)); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; } buffer = (char *)return_desc->buffer.pointer; /* Copy the first integer, LSB first */ memcpy(buffer, &operand0->integer.value, acpi_gbl_integer_byte_width); /* Copy the second integer (LSB first) after the first */ memcpy(buffer + acpi_gbl_integer_byte_width, &local_operand1->integer.value, acpi_gbl_integer_byte_width); break; case ACPI_TYPE_STRING: /* Result of two Strings is a String */ return_desc = acpi_ut_create_string_object(((acpi_size) local_operand0-> string.length + local_operand1-> string.length)); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; } buffer = return_desc->string.pointer; /* Concatenate the strings */ strcpy(buffer, local_operand0->string.pointer); strcat(buffer, local_operand1->string.pointer); break; case ACPI_TYPE_BUFFER: /* Result of two Buffers is a Buffer */ return_desc = acpi_ut_create_buffer_object(((acpi_size) operand0->buffer. length + local_operand1-> buffer.length)); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; } buffer = (char *)return_desc->buffer.pointer; /* Concatenate the buffers */ memcpy(buffer, operand0->buffer.pointer, operand0->buffer.length); memcpy(buffer + operand0->buffer.length, local_operand1->buffer.pointer, local_operand1->buffer.length); break; default: /* Invalid object type, should not happen here */ ACPI_ERROR((AE_INFO, "Invalid object type: 0x%X", operand0->common.type)); status = AE_AML_INTERNAL; goto cleanup; } *actual_return_desc = return_desc; cleanup: if (local_operand0 != operand0) { acpi_ut_remove_reference(local_operand0); } if (local_operand1 != operand1) { acpi_ut_remove_reference(local_operand1); } return_ACPI_STATUS(status); }
acpi_status acpi_ex_do_concatenate ( union acpi_operand_object *operand0, union acpi_operand_object *operand1, union acpi_operand_object **actual_return_desc, struct acpi_walk_state *walk_state) { union acpi_operand_object *local_operand1 = operand1; union acpi_operand_object *return_desc; char *new_buf; acpi_status status; acpi_size new_length; ACPI_FUNCTION_TRACE ("ex_do_concatenate"); /* * Convert the second operand if necessary. The first operand * determines the type of the second operand, (See the Data Types * section of the ACPI specification.) Both object types are * guaranteed to be either Integer/String/Buffer by the operand * resolution mechanism. */ switch (ACPI_GET_OBJECT_TYPE (operand0)) { case ACPI_TYPE_INTEGER: status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16); break; case ACPI_TYPE_STRING: status = acpi_ex_convert_to_string (operand1, &local_operand1, ACPI_IMPLICIT_CONVERT_HEX); break; case ACPI_TYPE_BUFFER: status = acpi_ex_convert_to_buffer (operand1, &local_operand1); break; default: ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n", ACPI_GET_OBJECT_TYPE (operand0))); status = AE_AML_INTERNAL; } if (ACPI_FAILURE (status)) { goto cleanup; } /* * Both operands are now known to be the same object type * (Both are Integer, String, or Buffer), and we can now perform the * concatenation. */ /* * There are three cases to handle: * * 1) Two Integers concatenated to produce a new Buffer * 2) Two Strings concatenated to produce a new String * 3) Two Buffers concatenated to produce a new Buffer */ switch (ACPI_GET_OBJECT_TYPE (operand0)) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ /* Need enough buffer space for two integers */ return_desc = acpi_ut_create_buffer_object ( ACPI_MUL_2 (acpi_gbl_integer_byte_width)); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; } new_buf = (char *) return_desc->buffer.pointer; /* Copy the first integer, LSB first */ ACPI_MEMCPY (new_buf, &operand0->integer.value, acpi_gbl_integer_byte_width); /* Copy the second integer (LSB first) after the first */ ACPI_MEMCPY (new_buf + acpi_gbl_integer_byte_width, &local_operand1->integer.value, acpi_gbl_integer_byte_width); break; case ACPI_TYPE_STRING: /* Result of two Strings is a String */ new_length = (acpi_size) operand0->string.length + (acpi_size) local_operand1->string.length; if (new_length > ACPI_MAX_STRING_CONVERSION) { status = AE_AML_STRING_LIMIT; goto cleanup; } return_desc = acpi_ut_create_string_object (new_length); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; } new_buf = return_desc->string.pointer; /* Concatenate the strings */ ACPI_STRCPY (new_buf, operand0->string.pointer); ACPI_STRCPY (new_buf + operand0->string.length, local_operand1->string.pointer); break; case ACPI_TYPE_BUFFER: /* Result of two Buffers is a Buffer */ return_desc = acpi_ut_create_buffer_object ( (acpi_size) operand0->buffer.length + (acpi_size) local_operand1->buffer.length); if (!return_desc) { status = AE_NO_MEMORY; goto cleanup; } new_buf = (char *) return_desc->buffer.pointer; /* Concatenate the buffers */ ACPI_MEMCPY (new_buf, operand0->buffer.pointer, operand0->buffer.length); ACPI_MEMCPY (new_buf + operand0->buffer.length, local_operand1->buffer.pointer, local_operand1->buffer.length); break; default: /* Invalid object type, should not happen here */ ACPI_REPORT_ERROR (("Concatenate - Invalid object type: %X\n", ACPI_GET_OBJECT_TYPE (operand0))); status =AE_AML_INTERNAL; goto cleanup; } *actual_return_desc = return_desc; cleanup: if (local_operand1 != operand1) { acpi_ut_remove_reference (local_operand1); } return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiExDoConcatenate ( ACPI_OPERAND_OBJECT *Operand0, ACPI_OPERAND_OBJECT *Operand1, ACPI_OPERAND_OBJECT **ActualReturnDesc, ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT *LocalOperand0 = Operand0; ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; ACPI_OPERAND_OBJECT *TempOperand1 = NULL; ACPI_OPERAND_OBJECT *ReturnDesc; char *Buffer; ACPI_OBJECT_TYPE Operand0Type; ACPI_OBJECT_TYPE Operand1Type; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (ExDoConcatenate); /* Operand 0 preprocessing */ switch (Operand0->Common.Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: Operand0Type = Operand0->Common.Type; break; default: /* For all other types, get the "object type" string */ Status = AcpiExConvertToObjectTypeString ( Operand0, &LocalOperand0); if (ACPI_FAILURE (Status)) { goto Cleanup; } Operand0Type = ACPI_TYPE_STRING; break; } /* Operand 1 preprocessing */ switch (Operand1->Common.Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: Operand1Type = Operand1->Common.Type; break; default: /* For all other types, get the "object type" string */ Status = AcpiExConvertToObjectTypeString ( Operand1, &LocalOperand1); if (ACPI_FAILURE (Status)) { goto Cleanup; } Operand1Type = ACPI_TYPE_STRING; break; } /* * Convert the second operand if necessary. The first operand (0) * determines the type of the second operand (1) (See the Data Types * section of the ACPI specification). Both object types are * guaranteed to be either Integer/String/Buffer by the operand * resolution mechanism. */ switch (Operand0Type) { case ACPI_TYPE_INTEGER: Status = AcpiExConvertToInteger (LocalOperand1, &TempOperand1, ACPI_STRTOUL_BASE16); break; case ACPI_TYPE_BUFFER: Status = AcpiExConvertToBuffer (LocalOperand1, &TempOperand1); break; case ACPI_TYPE_STRING: switch (Operand1Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* Other types have already been converted to string */ Status = AcpiExConvertToString ( LocalOperand1, &TempOperand1, ACPI_IMPLICIT_CONVERT_HEX); break; default: Status = AE_OK; break; } break; default: ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", Operand0->Common.Type)); Status = AE_AML_INTERNAL; } if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Take care with any newly created operand objects */ if ((LocalOperand1 != Operand1) && (LocalOperand1 != TempOperand1)) { AcpiUtRemoveReference (LocalOperand1); } LocalOperand1 = TempOperand1; /* * Both operands are now known to be the same object type * (Both are Integer, String, or Buffer), and we can now perform * the concatenation. * * There are three cases to handle, as per the ACPI spec: * * 1) Two Integers concatenated to produce a new Buffer * 2) Two Strings concatenated to produce a new String * 3) Two Buffers concatenated to produce a new Buffer */ switch (Operand0Type) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ /* Need enough buffer space for two integers */ ReturnDesc = AcpiUtCreateBufferObject ( (ACPI_SIZE) ACPI_MUL_2 (AcpiGbl_IntegerByteWidth)); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } Buffer = (char *) ReturnDesc->Buffer.Pointer; /* Copy the first integer, LSB first */ memcpy (Buffer, &Operand0->Integer.Value, AcpiGbl_IntegerByteWidth); /* Copy the second integer (LSB first) after the first */ memcpy (Buffer + AcpiGbl_IntegerByteWidth, &LocalOperand1->Integer.Value, AcpiGbl_IntegerByteWidth); break; case ACPI_TYPE_STRING: /* Result of two Strings is a String */ ReturnDesc = AcpiUtCreateStringObject ( ((ACPI_SIZE) LocalOperand0->String.Length + LocalOperand1->String.Length)); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } Buffer = ReturnDesc->String.Pointer; /* Concatenate the strings */ strcpy (Buffer, LocalOperand0->String.Pointer); strcat (Buffer, LocalOperand1->String.Pointer); break; case ACPI_TYPE_BUFFER: /* Result of two Buffers is a Buffer */ ReturnDesc = AcpiUtCreateBufferObject ( ((ACPI_SIZE) Operand0->Buffer.Length + LocalOperand1->Buffer.Length)); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } Buffer = (char *) ReturnDesc->Buffer.Pointer; /* Concatenate the buffers */ memcpy (Buffer, Operand0->Buffer.Pointer, Operand0->Buffer.Length); memcpy (Buffer + Operand0->Buffer.Length, LocalOperand1->Buffer.Pointer, LocalOperand1->Buffer.Length); break; default: /* Invalid object type, should not happen here */ ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", Operand0->Common.Type)); Status = AE_AML_INTERNAL; goto Cleanup; } *ActualReturnDesc = ReturnDesc; Cleanup: if (LocalOperand0 != Operand0) { AcpiUtRemoveReference (LocalOperand0); } if (LocalOperand1 != Operand1) { AcpiUtRemoveReference (LocalOperand1); } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExDoConcatenate ( ACPI_OPERAND_OBJECT *Operand0, ACPI_OPERAND_OBJECT *Operand1, ACPI_OPERAND_OBJECT **ActualReturnDesc, ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; ACPI_OPERAND_OBJECT *ReturnDesc; char *NewBuf; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (ExDoConcatenate); /* * Convert the second operand if necessary. The first operand * determines the type of the second operand, (See the Data Types * section of the ACPI specification.) Both object types are * guaranteed to be either Integer/String/Buffer by the operand * resolution mechanism. */ switch (ACPI_GET_OBJECT_TYPE (Operand0)) { case ACPI_TYPE_INTEGER: Status = AcpiExConvertToInteger (Operand1, &LocalOperand1, 16); break; case ACPI_TYPE_STRING: Status = AcpiExConvertToString (Operand1, &LocalOperand1, ACPI_IMPLICIT_CONVERT_HEX); break; case ACPI_TYPE_BUFFER: Status = AcpiExConvertToBuffer (Operand1, &LocalOperand1); break; default: ACPI_ERROR ((AE_INFO, "Invalid object type: %X", ACPI_GET_OBJECT_TYPE (Operand0))); Status = AE_AML_INTERNAL; } if (ACPI_FAILURE (Status)) { goto Cleanup; } /* * Both operands are now known to be the same object type * (Both are Integer, String, or Buffer), and we can now perform the * concatenation. */ /* * There are three cases to handle: * * 1) Two Integers concatenated to produce a new Buffer * 2) Two Strings concatenated to produce a new String * 3) Two Buffers concatenated to produce a new Buffer */ switch (ACPI_GET_OBJECT_TYPE (Operand0)) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ /* Need enough buffer space for two integers */ ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE) ACPI_MUL_2 (AcpiGbl_IntegerByteWidth)); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } NewBuf = (char *) ReturnDesc->Buffer.Pointer; /* Copy the first integer, LSB first */ ACPI_MEMCPY (NewBuf, &Operand0->Integer.Value, AcpiGbl_IntegerByteWidth); /* Copy the second integer (LSB first) after the first */ ACPI_MEMCPY (NewBuf + AcpiGbl_IntegerByteWidth, &LocalOperand1->Integer.Value, AcpiGbl_IntegerByteWidth); break; case ACPI_TYPE_STRING: /* Result of two Strings is a String */ ReturnDesc = AcpiUtCreateStringObject ((ACPI_SIZE) (Operand0->String.Length + LocalOperand1->String.Length)); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } NewBuf = ReturnDesc->String.Pointer; /* Concatenate the strings */ ACPI_STRCPY (NewBuf, Operand0->String.Pointer); ACPI_STRCPY (NewBuf + Operand0->String.Length, LocalOperand1->String.Pointer); break; case ACPI_TYPE_BUFFER: /* Result of two Buffers is a Buffer */ ReturnDesc = AcpiUtCreateBufferObject ((ACPI_SIZE) (Operand0->Buffer.Length + LocalOperand1->Buffer.Length)); if (!ReturnDesc) { Status = AE_NO_MEMORY; goto Cleanup; } NewBuf = (char *) ReturnDesc->Buffer.Pointer; /* Concatenate the buffers */ ACPI_MEMCPY (NewBuf, Operand0->Buffer.Pointer, Operand0->Buffer.Length); ACPI_MEMCPY (NewBuf + Operand0->Buffer.Length, LocalOperand1->Buffer.Pointer, LocalOperand1->Buffer.Length); break; default: /* Invalid object type, should not happen here */ ACPI_ERROR ((AE_INFO, "Invalid object type: %X", ACPI_GET_OBJECT_TYPE (Operand0))); Status =AE_AML_INTERNAL; goto Cleanup; } *ActualReturnDesc = ReturnDesc; Cleanup: if (LocalOperand1 != Operand1) { AcpiUtRemoveReference (LocalOperand1); } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExDoConcatenate ( ACPI_OPERAND_OBJECT *ObjDesc1, ACPI_OPERAND_OBJECT *ObjDesc2, ACPI_OPERAND_OBJECT **ActualReturnDesc, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status; UINT32 i; ACPI_INTEGER ThisInteger; ACPI_OPERAND_OBJECT *ReturnDesc; NATIVE_CHAR *NewBuf; ACPI_FUNCTION_ENTRY (); /* * There are three cases to handle: * * 1) Two Integers concatenated to produce a new Buffer * 2) Two Strings concatenated to produce a new String * 3) Two Buffers concatenated to produce a new Buffer */ switch (ACPI_GET_OBJECT_TYPE (ObjDesc1)) { case ACPI_TYPE_INTEGER: /* Result of two Integers is a Buffer */ /* Need enough buffer space for two integers */ ReturnDesc = AcpiUtCreateBufferObject (AcpiGbl_IntegerByteWidth * 2); if (!ReturnDesc) { return (AE_NO_MEMORY); } NewBuf = (NATIVE_CHAR *) ReturnDesc->Buffer.Pointer; /* Convert the first integer */ ThisInteger = ObjDesc1->Integer.Value; for (i = 0; i < AcpiGbl_IntegerByteWidth; i++) { NewBuf[i] = (NATIVE_CHAR) ThisInteger; ThisInteger >>= 8; } /* Convert the second integer */ ThisInteger = ObjDesc2->Integer.Value; for (; i < (ACPI_MUL_2 (AcpiGbl_IntegerByteWidth)); i++) { NewBuf[i] = (NATIVE_CHAR) ThisInteger; ThisInteger >>= 8; } break; case ACPI_TYPE_STRING: /* Result of two Strings is a String */ ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_STRING); if (!ReturnDesc) { return (AE_NO_MEMORY); } /* Operand0 is string */ NewBuf = ACPI_MEM_ALLOCATE ((ACPI_SIZE) ObjDesc1->String.Length + (ACPI_SIZE) ObjDesc2->String.Length + 1); if (!NewBuf) { ACPI_REPORT_ERROR (("ExDoConcatenate: String allocation failure\n")); Status = AE_NO_MEMORY; goto Cleanup; } /* Concatenate the strings */ ACPI_STRCPY (NewBuf, ObjDesc1->String.Pointer); ACPI_STRCPY (NewBuf + ObjDesc1->String.Length, ObjDesc2->String.Pointer); /* Complete the String object initialization */ ReturnDesc->String.Pointer = NewBuf; ReturnDesc->String.Length = ObjDesc1->String.Length + ObjDesc2->String.Length; break; case ACPI_TYPE_BUFFER: /* Result of two Buffers is a Buffer */ ReturnDesc = AcpiUtCreateBufferObject ( (ACPI_SIZE) ObjDesc1->Buffer.Length + (ACPI_SIZE) ObjDesc2->Buffer.Length); if (!ReturnDesc) { return (AE_NO_MEMORY); } NewBuf = (NATIVE_CHAR *) ReturnDesc->Buffer.Pointer; /* Concatenate the buffers */ ACPI_MEMCPY (NewBuf, ObjDesc1->Buffer.Pointer, ObjDesc1->Buffer.Length); ACPI_MEMCPY (NewBuf + ObjDesc1->Buffer.Length, ObjDesc2->Buffer.Pointer, ObjDesc2->Buffer.Length); break; default: /* Invalid object type, should not happen here */ Status = AE_AML_INTERNAL; ReturnDesc = NULL; } *ActualReturnDesc = ReturnDesc; return (AE_OK); Cleanup: AcpiUtRemoveReference (ReturnDesc); return (Status); }