static acpi_status acpi_ex_convert_to_object_type_string(union acpi_operand_object *obj_desc, union acpi_operand_object **result_desc) { union acpi_operand_object *return_desc; const char *type_string; type_string = acpi_ut_get_type_name(obj_desc->common.type); return_desc = acpi_ut_create_string_object(((acpi_size)strlen(type_string) + 9)); /* 9 For "[ Object]" */ if (!return_desc) { return (AE_NO_MEMORY); } strcpy(return_desc->string.pointer, "["); strcat(return_desc->string.pointer, type_string); strcat(return_desc->string.pointer, " Object]"); *result_desc = return_desc; return (AE_OK); }
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 acpi_ns_repair_null_element(struct acpi_evaluate_info * info, u32 expected_btypes, u32 package_index, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; union acpi_operand_object *new_object; ACPI_FUNCTION_NAME(ns_repair_null_element); /* No repair needed if return object is non-NULL */ if (return_object) { return (AE_OK); } /* * Attempt to repair a NULL element of a Package object. This applies to * predefined names that return a fixed-length package and each element * is required. It does not apply to variable-length packages where NULL * elements are allowed, especially at the end of the package. */ if (expected_btypes & ACPI_RTYPE_INTEGER) { /* Need an integer - create a zero-value integer */ new_object = acpi_ut_create_integer_object((u64)0); } else if (expected_btypes & ACPI_RTYPE_STRING) { /* Need a string - create a NULL string */ new_object = acpi_ut_create_string_object(0); } else if (expected_btypes & ACPI_RTYPE_BUFFER) { /* Need a buffer - create a zero-length buffer */ new_object = acpi_ut_create_buffer_object(0); } else { /* Error for all other expected types */ return (AE_AML_OPERAND_TYPE); } if (!new_object) { return (AE_NO_MEMORY); } /* Set the reference count according to the parent Package object */ new_object->common.reference_count = info->parent_package->common.reference_count; ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Converted NULL package element to expected %s at index %u\n", info->full_pathname, acpi_ut_get_object_type_name(new_object), package_index)); *return_object_ptr = new_object; info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); }
static acpi_status acpi_ns_repair_HID(struct acpi_predefined_data *data, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; union acpi_operand_object *new_string; char *source; char *dest; ACPI_FUNCTION_NAME(ns_repair_HID); /* We only care about string _HID objects (not integers) */ if (return_object->common.type != ACPI_TYPE_STRING) { return (AE_OK); } if (return_object->string.length == 0) { ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, "Invalid zero-length _HID or _CID string")); /* Return AE_OK anyway, let driver handle it */ data->flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } /* It is simplest to always create a new string object */ new_string = acpi_ut_create_string_object(return_object->string.length); if (!new_string) { return (AE_NO_MEMORY); } /* * Remove a leading asterisk if present. For some unknown reason, there * are many machines in the field that contains IDs like this. * * Examples: "*PNP0C03", "*ACPI0003" */ source = return_object->string.pointer; if (*source == '*') { source++; new_string->string.length--; ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Removed invalid leading asterisk\n", data->pathname)); } /* * Copy and uppercase the string. From the ACPI specification: * * A valid PNP ID must be of the form "AAA####" where A is an uppercase * letter and # is a hex digit. A valid ACPI ID must be of the form * "ACPI####" where # is a hex digit. */ for (dest = new_string->string.pointer; *source; dest++, source++) { *dest = (char)ACPI_TOUPPER(*source); } acpi_ut_remove_reference(return_object); *return_object_ptr = new_string; return (AE_OK); }
acpi_status acpi_ns_convert_to_string(union acpi_operand_object *original_object, union acpi_operand_object **return_object) { union acpi_operand_object *new_object; acpi_size length; acpi_status status; switch (original_object->common.type) { case ACPI_TYPE_INTEGER: /* * Integer-to-String conversion. Commonly, convert * an integer of value 0 to a NULL string. The last element of * _BIF and _BIX packages occasionally need this fix. */ if (original_object->integer.value == 0) { /* Allocate a new NULL string object */ new_object = acpi_ut_create_string_object(0); if (!new_object) { return (AE_NO_MEMORY); } } else { status = acpi_ex_convert_to_string(original_object, &new_object, ACPI_IMPLICIT_CONVERT_HEX); if (ACPI_FAILURE(status)) { return (status); } } break; case ACPI_TYPE_BUFFER: /* * Buffer-to-String conversion. Use a to_string * conversion, no transform performed on the buffer data. The best * example of this is the _BIF method, where the string data from * the battery is often (incorrectly) returned as buffer object(s). */ length = 0; while ((length < original_object->buffer.length) && (original_object->buffer.pointer[length])) { length++; } /* Allocate a new string object */ new_object = acpi_ut_create_string_object(length); if (!new_object) { return (AE_NO_MEMORY); } /* * Copy the raw buffer data with no transform. String is already NULL * terminated at Length+1. */ ACPI_MEMCPY(new_object->string.pointer, original_object->buffer.pointer, length); break; default: return (AE_AML_OPERAND_TYPE); } *return_object = new_object; return (AE_OK); }