diff options
author | Len Brown <len.brown@intel.com> | 2009-12-15 22:27:39 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-12-15 22:27:39 -0500 |
commit | 173cc11a6e10c38ff7d4949b48e8d2eb0aee3e05 (patch) | |
tree | 44ac9a6fe4e9c51b2c54918aa338df7eda96b0a5 | |
parent | 8bea8672edfca7ec5f661cafb218f1205863b343 (diff) | |
parent | 88e5071525ad6814be3a8a2792ce9e81a0cca22a (diff) |
Merge branch 'acpica' into release
26 files changed, 721 insertions, 301 deletions
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index ab83919dda6..61edb156e8d 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -296,6 +296,11 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data, acpi_status validate_status, union acpi_operand_object **return_object_ptr); +void +acpi_ns_remove_null_elements(struct acpi_predefined_data *data, + u8 package_type, + union acpi_operand_object *obj_desc); + /* * nssearch - Namespace searching and entry */ @@ -354,9 +359,7 @@ acpi_ns_externalize_name(u32 internal_name_length, const char *internal_name, u32 * converted_name_length, char **converted_name); -struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle); - -acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node); +struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle); void acpi_ns_terminate(void); diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index b39d682a214..64062b1be3e 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -180,7 +180,11 @@ struct acpi_object_method { u8 sync_level; union acpi_operand_object *mutex; u8 *aml_start; - ACPI_INTERNAL_METHOD implementation; + union { + ACPI_INTERNAL_METHOD implementation; + union acpi_operand_object *handler; + } extra; + u32 aml_length; u8 thread_count; acpi_owner_id owner_id; diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index 567a4899a01..e786f9fd767 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -414,7 +414,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, /* Invoke an internal method if necessary */ if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { - status = obj_desc->method.implementation(next_walk_state); + status = obj_desc->method.extra.implementation(next_walk_state); if (status == AE_OK) { status = AE_CTRL_TERMINATE; } diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 10fc7851784..b40513dd6a6 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -212,18 +212,19 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, case ACPI_TYPE_BUFFER: /* - * These types we will allow, but we will change the type. This - * enables some existing code of the form: + * These types we will allow, but we will change the type. + * This enables some existing code of the form: * * Name (DEB, 0) * Scope (DEB) { ... } * - * Note: silently change the type here. On the second pass, we will report - * a warning + * Note: silently change the type here. On the second pass, + * we will report a warning */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n", - path, + "Type override - [%4.4s] had invalid type (%s) " + "for Scope operator, changed to type ANY\n", + acpi_ut_get_node_name(node), acpi_ut_get_type_name(node->type))); node->type = ACPI_TYPE_ANY; @@ -235,8 +236,10 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, /* All other types are an error */ ACPI_ERROR((AE_INFO, - "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)", - acpi_ut_get_type_name(node->type), path)); + "Invalid type (%s) for target of " + "Scope operator [%4.4s] (Cannot override)", + acpi_ut_get_type_name(node->type), + acpi_ut_get_node_name(node))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } @@ -697,15 +700,16 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, case ACPI_TYPE_BUFFER: /* - * These types we will allow, but we will change the type. This - * enables some existing code of the form: + * These types we will allow, but we will change the type. + * This enables some existing code of the form: * * Name (DEB, 0) * Scope (DEB) { ... } */ ACPI_WARNING((AE_INFO, - "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)", - buffer_ptr, + "Type override - [%4.4s] had invalid type (%s) " + "for Scope operator, changed to type ANY\n", + acpi_ut_get_node_name(node), acpi_ut_get_type_name(node->type))); node->type = ACPI_TYPE_ANY; @@ -717,9 +721,10 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, /* All other types are an error */ ACPI_ERROR((AE_INFO, - "Invalid type (%s) for target of Scope operator [%4.4s]", + "Invalid type (%s) for target of " + "Scope operator [%4.4s] (Cannot override)", acpi_ut_get_type_name(node->type), - buffer_ptr)); + acpi_ut_get_node_name(node))); return (AE_AML_OPERAND_TYPE); } @@ -1047,9 +1052,22 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) } /* - * If we are executing a method, initialize the region + * The op_region is not fully parsed at this time. The only valid + * argument is the space_id. (We must save the address of the + * AML of the address and length operands) + * + * If we have a valid region, initialize it. The namespace is + * unlocked at this point. + * + * Need to unlock interpreter if it is locked (if we are running + * a control method), in order to allow _REG methods to be run + * during acpi_ev_initialize_region. */ if (walk_state->method_node) { + /* + * Executing a method: initialize the region and unlock + * the interpreter + */ status = acpi_ex_create_region(op->named.data, op->named.length, @@ -1058,21 +1076,17 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) if (ACPI_FAILURE(status)) { return (status); } - } - /* - * The op_region is not fully parsed at this time. Only valid - * argument is the space_id. (We must save the address of the - * AML of the address and length operands) - */ + acpi_ex_exit_interpreter(); + } - /* - * If we have a valid region, initialize it - * Namespace is NOT locked at this point. - */ status = acpi_ev_initialize_region (acpi_ns_get_attached_object(node), FALSE); + if (walk_state->method_node) { + acpi_ex_enter_interpreter(); + } + if (ACPI_FAILURE(status)) { /* * If AE_NOT_EXIST is returned, it is not fatal diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 0bc807c33a5..5336d911fbf 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -718,7 +718,7 @@ acpi_ev_install_handler(acpi_handle obj_handle, /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node(obj_handle); + node = acpi_ns_validate_handle(obj_handle); if (!node) { return (AE_BAD_PARAMETER); } @@ -1087,7 +1087,7 @@ acpi_ev_reg_run(acpi_handle obj_handle, /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node(obj_handle); + node = acpi_ns_validate_handle(obj_handle); if (!node) { return (AE_BAD_PARAMETER); } diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index cf29c495302..ff168052a33 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -575,6 +575,21 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, handler_obj = obj_desc->thermal_zone.handler; break; + case ACPI_TYPE_METHOD: + /* + * If we are executing module level code, the original + * Node's object was replaced by this Method object and we + * saved the handler in the method object. + * + * See acpi_ns_exec_module_code + */ + if (obj_desc->method. + flags & AOPOBJ_MODULE_LEVEL) { + handler_obj = + obj_desc->method.extra.handler; + } + break; + default: /* Ignore other objects */ break; diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 10b8543dd46..2fe0809d4eb 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -259,7 +259,7 @@ acpi_install_notify_handler(acpi_handle device, /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node(device); + node = acpi_ns_validate_handle(device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -425,7 +425,7 @@ acpi_remove_notify_handler(acpi_handle device, /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node(device); + node = acpi_ns_validate_handle(device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 4721f58fe42..eed7a38d25f 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -610,7 +610,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, return (status); } - node = acpi_ns_map_handle_to_node(gpe_device); + node = acpi_ns_validate_handle(gpe_device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -698,7 +698,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device) return (status); } - node = acpi_ns_map_handle_to_node(gpe_device); + node = acpi_ns_validate_handle(gpe_device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index 7c3d2d356ff..c98aa7c2d67 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -89,7 +89,7 @@ acpi_install_address_space_handler(acpi_handle device, /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node(device); + node = acpi_ns_validate_handle(device); if (!node) { status = AE_BAD_PARAMETER; goto unlock_and_exit; @@ -155,7 +155,7 @@ acpi_remove_address_space_handler(acpi_handle device, /* Convert and validate the device handle */ - node = acpi_ns_map_handle_to_node(device); + node = acpi_ns_validate_handle(device); if (!node || ((node->type != ACPI_TYPE_DEVICE) && (node->type != ACPI_TYPE_PROCESSOR) && diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index 2f0114202b0..3c456bd575d 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c @@ -375,6 +375,15 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); } + /* Must have a valid thread ID */ + + if (!walk_state->thread) { + ACPI_ERROR((AE_INFO, + "Cannot release Mutex [%4.4s], null thread info", + acpi_ut_get_node_name(obj_desc->mutex.node))); + return_ACPI_STATUS(AE_AML_INTERNAL); + } + /* * The Mutex is owned, but this thread must be the owner. * Special case for Global Lock, any thread can release @@ -392,15 +401,6 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, return_ACPI_STATUS(AE_AML_NOT_OWNER); } - /* Must have a valid thread ID */ - - if (!walk_state->thread) { - ACPI_ERROR((AE_INFO, - "Cannot release Mutex [%4.4s], null thread info", - acpi_ut_get_node_name(obj_desc->mutex.node))); - return_ACPI_STATUS(AE_AML_INTERNAL); - } - /* * The sync level of the mutex must be equal to the current sync level. In * other words, the current level means that at least one mutex at that diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index 9c3cdbe2d82..d622ba77000 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -165,7 +165,7 @@ acpi_status acpi_ns_root_initialize(void) obj_desc->method.method_flags = AML_METHOD_INTERNAL_ONLY; - obj_desc->method.implementation = + obj_desc->method.extra.implementation = acpi_ut_osi_implementation; #endif break; diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 2deb986861c..e37836e27e2 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -180,7 +180,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, return (AE_OK); } - this_node = acpi_ns_map_handle_to_node(obj_handle); + this_node = acpi_ns_validate_handle(obj_handle); if (!this_node) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid object handle %p\n", obj_handle)); diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index f771e978c40..af9fe910373 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -381,6 +381,18 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, method_obj->method.next_object); type = acpi_ns_get_type(parent_node); + /* + * Get the region handler and save it in the method object. We may need + * this if an operation region declaration causes a _REG method to be run. + * + * We can't do this in acpi_ps_link_module_code because + * acpi_gbl_root_node->Object is NULL at PASS1. + */ + if ((type == ACPI_TYPE_DEVICE) && parent_node->object) { + method_obj->method.extra.handler = + parent_node->object->device.handler; + } + /* Must clear next_object (acpi_ns_attach_object needs the field) */ method_obj->method.next_object = NULL; @@ -415,6 +427,12 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n", method_obj->method.aml_start)); + /* Delete a possible implicit return value (in slack mode) */ + + if (info->return_object) { + acpi_ut_remove_reference(info->return_object); + } + /* Detach the temporary method object */ acpi_ns_detach_object(parent_node); diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c index af8e6bcee07..8f9a4875ce2 100644 --- a/drivers/acpi/acpica/nsnames.c +++ b/drivers/acpi/acpica/nsnames.c @@ -232,7 +232,7 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle, ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle); - node = acpi_ns_map_handle_to_node(target_handle); + node = acpi_ns_validate_handle(target_handle); if (!node) { return_ACPI_STATUS(AE_BAD_PARAMETER); } diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index b05f42903c8..d34fa59548f 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -216,29 +216,38 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, data->pathname = pathname; /* - * Check that the type of the return object is what is expected for - * this predefined name + * Check that the type of the main return object is what is expected + * for this predefined name */ status = acpi_ns_check_object_type(data, return_object_ptr, predefined->info.expected_btypes, ACPI_NOT_PACKAGE_ELEMENT); if (ACPI_FAILURE(status)) { - goto check_validation_status; + goto exit; } - /* For returned Package objects, check the type of all sub-objects */ - - if (return_object->common.type == ACPI_TYPE_PACKAGE) { + /* + * For returned Package objects, check the type of all sub-objects. + * Note: Package may have been newly created by call above. + */ + if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) { status = acpi_ns_check_package(data, return_object_ptr); + if (ACPI_FAILURE(status)) { + goto exit; + } } /* - * Perform additional, more complicated repairs on a per-name - * basis. + * The return object was OK, or it was successfully repaired above. + * Now make some additional checks such as verifying that package + * objects are sorted correctly (if required) or buffer objects have + * the correct data width (bytes vs. dwords). These repairs are + * performed on a per-name basis, i.e., the code is specific to + * particular predefined names. */ status = acpi_ns_complex_repairs(data, node, status, return_object_ptr); -check_validation_status: +exit: /* * If the object validation failed or if we successfully repaired one * or more objects, mark the parent node to suppress further warning @@ -427,6 +436,13 @@ acpi_ns_check_package(struct acpi_predefined_data *data, data->pathname, package->ret_info.type, return_object->package.count)); + /* + * For variable-length Packages, we can safely remove all embedded + * and trailing NULL package elements + */ + acpi_ns_remove_null_elements(data, package->ret_info.type, + return_object); + /* Extract package count and elements array */ elements = return_object->package.elements; @@ -461,11 +477,11 @@ acpi_ns_check_package(struct acpi_predefined_data *data, if (count < expected_count) { goto package_too_small; } else if (count > expected_count) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, - "Return Package is larger than needed - " - "found %u, expected %u", count, - expected_count)); + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Return Package is larger than needed - " + "found %u, expected %u\n", + data->pathname, count, + expected_count)); } /* Validate all elements of the returned package */ @@ -680,53 +696,18 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, union acpi_operand_object *sub_package; union acpi_operand_object **sub_elements; acpi_status status; - u8 non_trailing_null = FALSE; u32 expected_count; u32 i; u32 j; - /* Validate each sub-Package in the parent Package */ - + /* + * Validate each sub-Package in the parent Package + * + * NOTE: assumes list of sub-packages contains no NULL elements. + * Any NULL elements should have been removed by earlier call + * to acpi_ns_remove_null_elements. + */ for (i = 0; i < count; i++) { - /* - * Handling for NULL package elements. For now, we will simply allow - * a parent package with trailing NULL elements. This can happen if - * the package was defined to be longer than the initializer list. - * This is legal as per the ACPI specification. It is often used - * to allow for dynamic initialization of a Package. - * - * A future enhancement may be to simply truncate the package to - * remove the trailing NULL elements. - */ - if (!(*elements)) { - if (!non_trailing_null) { - - /* Ensure the remaining elements are all NULL */ - - for (j = 1; j < (count - i + 1); j++) { - if (elements[j]) { - non_trailing_null = TRUE; - } - } - - if (!non_trailing_null) { - - /* Ignore the trailing NULL elements */ - - return (AE_OK); - } - } - - /* There are trailing non-null elements, issue warning */ - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, - "Found NULL element at package index %u", - i)); - elements++; - continue; - } - sub_package = *elements; sub_elements = sub_package->package.elements; diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index d563f1a564a..4fd1bdb056b 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -45,13 +45,52 @@ #include "accommon.h" #include "acnamesp.h" #include "acinterp.h" -#include "acpredef.h" #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsrepair") /******************************************************************************* * + * This module attempts to repair or convert objects returned by the + * predefined methods to an object type that is expected, as per the ACPI + * specification. The need for this code is dictated by the many machines that + * return incorrect types for the standard predefined methods. Performing these + * conversions here, in one place, eliminates the need for individual ACPI + * device drivers to do the same. Note: Most of these conversions are different + * than the internal object conversion routines used for implicit object + * conversion. + * + * The following conversions can be performed as necessary: + * + * Integer -> String + * Integer -> Buffer + * String -> Integer + * String -> Buffer + * Buffer -> Integer + * Buffer -> String + * Buffer -> Package of Integers + * Package -> Package of one Package + * + ******************************************************************************/ +/* Local prototypes */ +static acpi_status +acpi_ns_convert_to_integer(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + +static acpi_status +acpi_ns_convert_to_string(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + +static acpi_status +acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + +static acpi_status +acpi_ns_convert_to_package(union acpi_operand_object *original_object, + union acpi_operand_object **return_object); + +/******************************************************************************* + * * FUNCTION: acpi_ns_repair_object * * PARAMETERS: Data - Pointer to validation data structure @@ -68,6 +107,7 @@ ACPI_MODULE_NAME("nsrepair") * not expected. * ******************************************************************************/ + acpi_status acpi_ns_repair_object(struct acpi_predefined_data *data, u32 expected_btypes, @@ -76,32 +116,206 @@ acpi_ns_repair_object(struct acpi_predefined_data *data, { union acpi_operand_object *return_object = *return_object_ptr; union acpi_operand_object *new_object; - acpi_size length; acpi_status status; + ACPI_FUNCTION_NAME(ns_repair_object); + /* * At this point, we know that the type of the returned object was not * one of the expected types for this predefined name. Attempt to - * repair the object. Only a limited number of repairs are possible. + * repair the object by converting it to one of the expected object + * types for this predefined name. */ - switch (return_object->common.type) { + if (expected_btypes & ACPI_RTYPE_INTEGER) { + status = acpi_ns_convert_to_integer(return_object, &new_object); + if (ACPI_SUCCESS(status)) { + goto object_repaired; + } + } + if (expected_btypes & ACPI_RTYPE_STRING) { + status = acpi_ns_convert_to_string(return_object, &new_object); + if (ACPI_SUCCESS(status)) { + goto object_repaired; + } + } + if (expected_btypes & ACPI_RTYPE_BUFFER) { + status = acpi_ns_convert_to_buffer(return_object, &new_object); + if (ACPI_SUCCESS(status)) { + goto object_repaired; + } + } + if (expected_btypes & ACPI_RTYPE_PACKAGE) { + status = acpi_ns_convert_to_package(return_object, &new_object); + if (ACPI_SUCCESS(status)) { + goto object_repaired; + } + } + + /* We cannot repair this object */ + + return (AE_AML_OPERAND_TYPE); + + object_repaired: + + /* Object was successfully repaired */ + + /* + * If the original object is a package element, we need to: + * 1. Set the reference count of the new object to match the + * reference count of the old object. + * 2. Decrement the reference count of the original object. + */ + if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { + new_object->common.reference_count = + return_object->common.reference_count; + + if (return_object->common.reference_count > 1) { + return_object->common.reference_count--; + } + + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Converted %s to expected %s at index %u\n", + data->pathname, + acpi_ut_get_object_type_name(return_object), + acpi_ut_get_object_type_name(new_object), + package_index)); + } else { + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, + "%s: Converted %s to expected %s\n", + data->pathname, + acpi_ut_get_object_type_name(return_object), + acpi_ut_get_object_type_name(new_object))); + } + + /* Delete old object, install the new return object */ + + acpi_ut_remove_reference(return_object); + *return_object_ptr = new_object; + data->flags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_convert_to_integer + * + * PARAMETERS: original_object - Object to be converted + * return_object - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. + * + ******************************************************************************/ + +static acpi_status +acpi_ns_convert_to_integer(union acpi_operand_object *original_object, + union acpi_operand_object **return_object) +{ + union acpi_operand_object *new_object; + acpi_status status; + u64 value = 0; + u32 i; + + switch (original_object->common.type) { + case ACPI_TYPE_STRING: + + /* String-to-Integer conversion */ + + status = acpi_ut_strtoul64(original_object->string.pointer, + ACPI_ANY_BASE, &value); + if (ACPI_FAILURE(status)) { + return (status); + } + break; + case ACPI_TYPE_BUFFER: - /* Does the method/object legally return a string? */ + /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ - if (!(expected_btypes & ACPI_RTYPE_STRING)) { + if (original_object->buffer.length > 8) { return (AE_AML_OPERAND_TYPE); } + /* Extract each buffer byte to create the integer */ + + for (i = 0; i < original_object->buffer.length; i++) { + value |= + ((u64) original_object->buffer. + pointer[i] << (i * 8)); + } + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + new_object = acpi_ut_create_integer_object(value); + if (!new_object) { + return (AE_NO_MEMORY); + } + + *return_object = new_object; + return (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ns_convert_to_string + * + * PARAMETERS: original_object - Object to be converted + * return_object - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. + * + ******************************************************************************/ + +static 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; + |