ACPICA: Add mechanism for early object repairs on a per-name basis
authorBob Moore <robert.moore@intel.com>
Fri, 8 Mar 2013 09:23:03 +0000 (09:23 +0000)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Mon, 11 Mar 2013 23:45:05 +0000 (00:45 +0100)
Adds the framework to allow object repairs very early in the
return object analysis. Enables repairs like string->unicode,
etc. Bob Moore, Lv Zheng.

Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acnamesp.h
drivers/acpi/acpica/nspredef.c
drivers/acpi/acpica/nsrepair.c
drivers/acpi/acpica/nsrepair2.c

index 805f419086ab596f2b268be0f135ddb4bcb17913..9d45f976a31e8f22d2781fdf0ea95a10782fa357 100644 (file)
@@ -363,6 +363,7 @@ struct acpi_predefined_data {
        union acpi_operand_object *parent_package;
        struct acpi_namespace_node *node;
        u32 flags;
+       u32 return_btype;
        u8 node_flags;
 };
 
@@ -371,6 +372,20 @@ struct acpi_predefined_data {
 #define ACPI_OBJECT_REPAIRED    1
 #define ACPI_OBJECT_WRAPPED     2
 
+/* Return object auto-repair info */
+
+typedef acpi_status(*acpi_object_converter) (union acpi_operand_object
+                                            *original_object,
+                                            union acpi_operand_object
+                                            **converted_object);
+
+struct acpi_simple_repair_info {
+       char name[ACPI_NAME_SIZE];
+       u32 unexpected_btypes;
+       u32 package_index;
+       acpi_object_converter object_converter;
+};
+
 /*
  * Bitmapped return value types
  * Note: the actual data types must be contiguous, a loop in nspredef.c
index 02cd5482ff8b2faddf380efb5a3df96c53a75ce6..dec6e9ec2e0cb5cbf1eb5242d95f8b6744d7b7eb 100644 (file)
@@ -289,7 +289,7 @@ acpi_ns_get_attached_data(struct acpi_namespace_node *node,
  * predefined methods/objects
  */
 acpi_status
-acpi_ns_repair_object(struct acpi_predefined_data *data,
+acpi_ns_simple_repair(struct acpi_predefined_data *data,
                      u32 expected_btypes,
                      u32 package_index,
                      union acpi_operand_object **return_object_ptr);
index 224c3005340112add4471f37c7b676247dfdfb34..36f724085dcaa91849725db7208897af3960822d 100644 (file)
@@ -78,6 +78,8 @@ acpi_ns_check_reference(struct acpi_predefined_data *data,
 
 static void acpi_ns_get_expected_types(char *buffer, u32 expected_btypes);
 
+static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object);
+
 /*
  * Names for the types that can be returned by the predefined objects.
  * Used for warning messages. Must be in the same order as the ACPI_RTYPEs
@@ -112,7 +114,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
                               acpi_status return_status,
                               union acpi_operand_object **return_object_ptr)
 {
-       union acpi_operand_object *return_object = *return_object_ptr;
        acpi_status status = AE_OK;
        const union acpi_predefined_info *predefined;
        char *pathname;
@@ -151,25 +152,6 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
                goto cleanup;
        }
 
-       /*
-        * If there is no return value, check if we require a return value for
-        * this predefined name. Either one return value is expected, or none,
-        * for both methods and other objects.
-        *
-        * Exit now if there is no return object. Warning if one was expected.
-        */
-       if (!return_object) {
-               if ((predefined->info.expected_btypes) &&
-                   (!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) {
-                       ACPI_WARN_PREDEFINED((AE_INFO, pathname,
-                                             ACPI_WARN_ALWAYS,
-                                             "Missing expected return value"));
-
-                       status = AE_AML_NO_RETURN_VALUE;
-               }
-               goto cleanup;
-       }
-
        /*
         * Return value validation and possible repair.
         *
@@ -410,28 +392,12 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data,
 {
        union acpi_operand_object *return_object = *return_object_ptr;
        acpi_status status = AE_OK;
-       u32 return_btype;
        char type_buffer[48];   /* Room for 5 types */
 
-       /*
-        * If we get a NULL return_object here, it is a NULL package element.
-        * Since all extraneous NULL package elements were removed earlier by a
-        * call to acpi_ns_remove_null_elements, this is an unexpected NULL element.
-        * We will attempt to repair it.
-        */
-       if (!return_object) {
-               status = acpi_ns_repair_null_element(data, expected_btypes,
-                                                    package_index,
-                                                    return_object_ptr);
-               if (ACPI_SUCCESS(status)) {
-                       return (AE_OK); /* Repair was successful */
-               }
-               goto type_error_exit;
-       }
-
        /* A Namespace node should not get here, but make sure */
 
-       if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) {
+       if (return_object &&
+           ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) {
                ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
                                      "Invalid return type - Found a Namespace node [%4.4s] type %s",
                                      return_object->node.name.ascii,
@@ -448,53 +414,25 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data,
         * from all of the predefined names (including elements of returned
         * packages)
         */
-       switch (return_object->common.type) {
-       case ACPI_TYPE_INTEGER:
-               return_btype = ACPI_RTYPE_INTEGER;
-               break;
-
-       case ACPI_TYPE_BUFFER:
-               return_btype = ACPI_RTYPE_BUFFER;
-               break;
-
-       case ACPI_TYPE_STRING:
-               return_btype = ACPI_RTYPE_STRING;
-               break;
+       data->return_btype = acpi_ns_get_bitmapped_type(return_object);
+       if (data->return_btype == ACPI_RTYPE_ANY) {
 
-       case ACPI_TYPE_PACKAGE:
-               return_btype = ACPI_RTYPE_PACKAGE;
-               break;
-
-       case ACPI_TYPE_LOCAL_REFERENCE:
-               return_btype = ACPI_RTYPE_REFERENCE;
-               break;
-
-       default:
                /* Not one of the supported objects, must be incorrect */
-
                goto type_error_exit;
        }
 
-       /* Is the object one of the expected types? */
-
-       if (return_btype & expected_btypes) {
-
-               /* For reference objects, check that the reference type is correct */
-
-               if (return_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
-                       status = acpi_ns_check_reference(data, return_object);
-               }
+       /* For reference objects, check that the reference type is correct */
 
+       if ((data->return_btype & expected_btypes) == ACPI_RTYPE_REFERENCE) {
+               status = acpi_ns_check_reference(data, return_object);
                return (status);
        }
 
-       /* Type mismatch -- attempt repair of the returned object */
+       /* Attempt simple repair of the returned object if necessary */
 
-       status = acpi_ns_repair_object(data, expected_btypes,
+       status = acpi_ns_simple_repair(data, expected_btypes,
                                       package_index, return_object_ptr);
-       if (ACPI_SUCCESS(status)) {
-               return (AE_OK); /* Repair was successful */
-       }
+       return (status);
 
       type_error_exit:
 
@@ -556,6 +494,61 @@ acpi_ns_check_reference(struct acpi_predefined_data *data,
        return (AE_AML_OPERAND_TYPE);
 }
 
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_get_bitmapped_type
+ *
+ * PARAMETERS:  return_object   - Object returned from method/obj evaluation
+ *
+ * RETURN:      Object return type. ACPI_RTYPE_ANY indicates that the object
+ *              type is not supported. ACPI_RTYPE_NONE indicates that no
+ *              object was returned (return_object is NULL).
+ *
+ * DESCRIPTION: Convert object type into a bitmapped object return type.
+ *
+ ******************************************************************************/
+
+static u32 acpi_ns_get_bitmapped_type(union acpi_operand_object *return_object)
+{
+       u32 return_btype;
+
+       if (!return_object) {
+               return (ACPI_RTYPE_NONE);
+       }
+
+       /* Map acpi_object_type to internal bitmapped type */
+
+       switch (return_object->common.type) {
+       case ACPI_TYPE_INTEGER:
+               return_btype = ACPI_RTYPE_INTEGER;
+               break;
+
+       case ACPI_TYPE_BUFFER:
+               return_btype = ACPI_RTYPE_BUFFER;
+               break;
+
+       case ACPI_TYPE_STRING:
+               return_btype = ACPI_RTYPE_STRING;
+               break;
+
+       case ACPI_TYPE_PACKAGE:
+               return_btype = ACPI_RTYPE_PACKAGE;
+               break;
+
+       case ACPI_TYPE_LOCAL_REFERENCE:
+               return_btype = ACPI_RTYPE_REFERENCE;
+               break;
+
+       default:
+               /* Not one of the supported objects, must be incorrect */
+
+               return_btype = ACPI_RTYPE_ANY;
+               break;
+       }
+
+       return (return_btype);
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_get_expected_types
index 9e833353c06a802bc796b6f102e8f2181a67d2f6..f9c9fd45cd1f767e4333a20e804402a626f04718 100644 (file)
@@ -46,6 +46,7 @@
 #include "acnamesp.h"
 #include "acinterp.h"
 #include "acpredef.h"
+#include "amlresrc.h"
 
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsrepair")
@@ -71,6 +72,11 @@ ACPI_MODULE_NAME("nsrepair")
  * Buffer  -> String
  * Buffer  -> Package of Integers
  * Package -> Package of one Package
+ *
+ * Additional conversions that are available:
+ *  Convert a null return or zero return value to an end_tag descriptor
+ *  Convert an ASCII string to a Unicode buffer
+ *
  * An incorrect standalone object is wrapped with required outer package
  *
  * Additional possible repairs:
@@ -90,9 +96,26 @@ static acpi_status
 acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
                          union acpi_operand_object **return_object);
 
+static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct
+                                                                        acpi_namespace_node
+                                                                        *node,
+                                                                        u32
+                                                                        return_btype,
+                                                                        u32
+                                                                        package_index);
+
+/*
+ * Special but simple repairs for some names.
+ *
+ * 2nd argument: Unexpected types that can be repaired
+ */
+static const struct acpi_simple_repair_info acpi_object_repair_info[] = {
+       {{0, 0, 0, 0}, 0, 0, NULL}      /* Table terminator */
+};
+
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ns_repair_object
+ * FUNCTION:    acpi_ns_simple_repair
  *
  * PARAMETERS:  data                - Pointer to validation data structure
  *              expected_btypes     - Object types expected
@@ -110,16 +133,54 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
  ******************************************************************************/
 
 acpi_status
-acpi_ns_repair_object(struct acpi_predefined_data *data,
+acpi_ns_simple_repair(struct acpi_predefined_data *data,
                      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;
+       union acpi_operand_object *new_object = NULL;
        acpi_status status;
+       const struct acpi_simple_repair_info *predefined;
 
-       ACPI_FUNCTION_NAME(ns_repair_object);
+       ACPI_FUNCTION_NAME(ns_simple_repair);
+
+       /*
+        * Special repairs for certain names that are in the repair table.
+        * Check if this name is in the list of repairable names.
+        */
+       predefined = acpi_ns_match_simple_repair(data->node,
+                                                data->return_btype,
+                                                package_index);
+       if (predefined) {
+               if (!return_object) {
+                       ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
+                                             ACPI_WARN_ALWAYS,
+                                             "Missing expected return value"));
+               }
+
+               status =
+                   predefined->object_converter(return_object, &new_object);
+               if (ACPI_FAILURE(status)) {
+
+                       /* A fatal error occurred during a conversion */
+
+                       ACPI_EXCEPTION((AE_INFO, status,
+                                       "During return object analysis"));
+                       return (status);
+               }
+               if (new_object) {
+                       goto object_repaired;
+               }
+       }
+
+       /*
+        * Do not perform simple object repair unless the return type is not
+        * expected.
+        */
+       if (data->return_btype & expected_btypes) {
+               return (AE_OK);
+       }
 
        /*
         * At this point, we know that the type of the returned object was not
@@ -127,6 +188,24 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
         * repair the object by converting it to one of the expected object
         * types for this predefined name.
         */
+
+       /*
+        * If there is no return value, check if we require a return value for
+        * this predefined name. Either one return value is expected, or none,
+        * for both methods and other objects.
+        *
+        * Exit now if there is no return object. Warning if one was expected.
+        */
+       if (!return_object) {
+               if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) {
+                       ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
+                                             ACPI_WARN_ALWAYS,
+                                             "Missing expected return value"));
+
+                       return (AE_AML_NO_RETURN_VALUE);
+               }
+       }
+
        if (expected_btypes & ACPI_RTYPE_INTEGER) {
                status = acpi_ns_convert_to_integer(return_object, &new_object);
                if (ACPI_SUCCESS(status)) {
@@ -216,6 +295,53 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
        return (AE_OK);
 }
 
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_match_simple_repair
+ *
+ * PARAMETERS:  node                - Namespace node for the method/object
+ *              return_btype        - Object type that was returned
+ *              package_index       - Index of object within parent package (if
+ *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
+ *                                    otherwise)
+ *
+ * RETURN:      Pointer to entry in repair table. NULL indicates not found.
+ *
+ * DESCRIPTION: Check an object name against the repairable object list.
+ *
+ *****************************************************************************/
+
+static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct
+                                                                        acpi_namespace_node
+                                                                        *node,
+                                                                        u32
+                                                                        return_btype,
+                                                                        u32
+                                                                        package_index)
+{
+       const struct acpi_simple_repair_info *this_name;
+
+       /* Search info table for a repairable predefined method/object name */
+
+       this_name = acpi_object_repair_info;
+       while (this_name->object_converter) {
+               if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) {
+
+                       /* Check if we can actually repair this name/type combination */
+
+                       if ((return_btype & this_name->unexpected_btypes) &&
+                           (package_index == this_name->package_index)) {
+                               return (this_name);
+                       }
+
+                       return (NULL);
+               }
+               this_name++;
+       }
+
+       return (NULL);          /* Name was not found in the repair table */
+}
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ns_convert_to_integer
index ba4d98287c6a14b11add5e457f101876d019d439..149e9b9c2c1b1e3fbb8349de7338697b540d976d 100644 (file)
@@ -66,9 +66,9 @@ typedef struct acpi_repair_info {
 
 /* Local prototypes */
 
-static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct
-                                                                   acpi_namespace_node
-                                                                   *node);
+static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct
+                                                                  acpi_namespace_node
+                                                                  *node);
 
 static acpi_status
 acpi_ns_repair_ALR(struct acpi_predefined_data *data,
@@ -175,7 +175,7 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
 
        /* Check if this name is in the list of repairable names */
 
-       predefined = acpi_ns_match_repairable_name(node);
+       predefined = acpi_ns_match_complex_repair(node);
        if (!predefined) {
                return (validate_status);
        }
@@ -186,7 +186,7 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
 
 /******************************************************************************
  *
- * FUNCTION:    acpi_ns_match_repairable_name
+ * FUNCTION:    acpi_ns_match_complex_repair
  *
  * PARAMETERS:  node                - Namespace node for the method/object
  *
@@ -196,9 +196,9 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
  *
  *****************************************************************************/
 
-static const struct acpi_repair_info *acpi_ns_match_repairable_name(struct
-                                                                   acpi_namespace_node
-                                                                   *node)
+static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct
+                                                                  acpi_namespace_node
+                                                                  *node)
 {
        const struct acpi_repair_info *this_name;