ACPICA: Add repair for bad _BIF/_BIX packages
authorBob Moore <robert.moore@intel.com>
Tue, 13 Oct 2009 02:20:33 +0000 (10:20 +0800)
committerLen Brown <len.brown@intel.com>
Wed, 25 Nov 2009 01:30:03 +0000 (20:30 -0500)
Add a repair for the "Oem Information" field which is often
mistakenly returned as an integer. It should always be a string.
ACPICA BZ 807.

http://www.acpica.org/bugzilla/show_bug.cgi?id=807

Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
drivers/acpi/acpica/nsrepair.c

index db2b2a99c3a8130ba31dab24fd31a58116f5ec71..dfa31c5ba6c3424b8a97e0dd0b47c4c99d0bb559 100644 (file)
@@ -77,6 +77,11 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
        union acpi_operand_object *new_object;
        acpi_size length;
 
+       /*
+        * 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.
+        */
        switch (return_object->common.type) {
        case ACPI_TYPE_BUFFER:
 
@@ -111,43 +116,77 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
                 */
                ACPI_MEMCPY(new_object->string.pointer,
                            return_object->buffer.pointer, length);
+               break;
 
-               /*
-                * 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;
+       case ACPI_TYPE_INTEGER:
+
+               /* Does the method/object legally return a string? */
 
-                       if (return_object->common.reference_count > 1) {
-                               return_object->common.reference_count--;
+               if (expected_btypes & ACPI_RTYPE_STRING) {
+                       /*
+                        * The only supported Integer-to-String conversion is to convert
+                        * an integer of value 0 to a NULL string. The last element of
+                        * _BIF and _BIX packages occasionally need this fix.
+                        */
+                       if (return_object->integer.value != 0) {
+                               return (AE_AML_OPERAND_TYPE);
                        }
 
-                       ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
-                                             data->node_flags,
-                                             "Converted Buffer to expected String at index %u",
-                                             package_index));
+                       /* Allocate a new NULL string object */
+
+                       new_object = acpi_ut_create_string_object(0);
+                       if (!new_object) {
+                               return (AE_NO_MEMORY);
+                       }
                } else {
-                       ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
-                                             data->node_flags,
-                                             "Converted Buffer to expected String"));
+                       return (AE_AML_OPERAND_TYPE);
                }
+               break;
 
-               /* Delete old object, install the new return object */
+       default:
 
-               acpi_ut_remove_reference(return_object);
-               *return_object_ptr = new_object;
-               data->flags |= ACPI_OBJECT_REPAIRED;
-               return (AE_OK);
+               /* We cannot repair this object */
 
-       default:
-               break;
+               return (AE_AML_OPERAND_TYPE);
+       }
+
+       /* 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_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
+                                     "Converted %s to expected %s at index %u",
+                                     acpi_ut_get_object_type_name
+                                     (return_object),
+                                     acpi_ut_get_object_type_name(new_object),
+                                     package_index));
+       } else {
+               ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
+                                     "Converted %s to expected %s",
+                                     acpi_ut_get_object_type_name
+                                     (return_object),
+                                     acpi_ut_get_object_type_name
+                                     (new_object)));
        }
 
-       return (AE_AML_OPERAND_TYPE);
+       /* 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);
 }
 
 /*******************************************************************************