ACPICA: Add repair for _HID and _CID strings
authorBob Moore <robert.moore@intel.com>
Wed, 15 Sep 2010 06:11:02 +0000 (14:11 +0800)
committerLen Brown <len.brown@intel.com>
Fri, 1 Oct 2010 05:47:56 +0000 (01:47 -0400)
This dynamic repair will fix these problems:
1) Remove a leading asterisk in the string
2) Uppercase the entire string

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/nsrepair2.c

index 4009498fbabd038520fdb47756cd263386f0b980..4ef9f43ea9262273ed06686eae439b9675f5d10d 100644 (file)
@@ -73,10 +73,18 @@ static acpi_status
 acpi_ns_repair_ALR(struct acpi_predefined_data *data,
                   union acpi_operand_object **return_object_ptr);
 
+static acpi_status
+acpi_ns_repair_CID(struct acpi_predefined_data *data,
+                  union acpi_operand_object **return_object_ptr);
+
 static acpi_status
 acpi_ns_repair_FDE(struct acpi_predefined_data *data,
                   union acpi_operand_object **return_object_ptr);
 
+static acpi_status
+acpi_ns_repair_HID(struct acpi_predefined_data *data,
+                  union acpi_operand_object **return_object_ptr);
+
 static acpi_status
 acpi_ns_repair_PSS(struct acpi_predefined_data *data,
                   union acpi_operand_object **return_object_ptr);
@@ -108,8 +116,10 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
  * As necessary:
  *
  * _ALR: Sort the list ascending by ambient_illuminance
+ * _CID: Strings: uppercase all, remove any leading asterisk
  * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
  * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
+ * _HID: Strings: uppercase all, remove any leading asterisk
  * _PSS: Sort the list descending by Power
  * _TSS: Sort the list descending by Power
  *
@@ -122,8 +132,10 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
  */
 static const struct acpi_repair_info acpi_ns_repairable_names[] = {
        {"_ALR", acpi_ns_repair_ALR},
+       {"_CID", acpi_ns_repair_CID},
        {"_FDE", acpi_ns_repair_FDE},
        {"_GTM", acpi_ns_repair_FDE},   /* _GTM has same repair as _FDE */
+       {"_HID", acpi_ns_repair_HID},
        {"_PSS", acpi_ns_repair_PSS},
        {"_TSS", acpi_ns_repair_TSS},
        {{0, 0, 0, 0}, NULL}    /* Table terminator */
@@ -319,6 +331,157 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data,
        return (AE_OK);
 }
 
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_repair_CID
+ *
+ * PARAMETERS:  Data                - Pointer to validation data structure
+ *              return_object_ptr   - Pointer to the object returned from the
+ *                                    evaluation of a method or object
+ *
+ * RETURN:      Status. AE_OK if object is OK or was repaired successfully
+ *
+ * DESCRIPTION: Repair for the _CID object. If a string, ensure that all
+ *              letters are uppercase and that there is no leading asterisk.
+ *              If a Package, ensure same for all string elements.
+ *
+ *****************************************************************************/
+
+static acpi_status
+acpi_ns_repair_CID(struct acpi_predefined_data *data,
+                  union acpi_operand_object **return_object_ptr)
+{
+       acpi_status status;
+       union acpi_operand_object *return_object = *return_object_ptr;
+       union acpi_operand_object **element_ptr;
+       union acpi_operand_object *original_element;
+       u16 original_ref_count;
+       u32 i;
+
+       /* Check for _CID as a simple string */
+
+       if (return_object->common.type == ACPI_TYPE_STRING) {
+               status = acpi_ns_repair_HID(data, return_object_ptr);
+               return (status);
+       }
+
+       /* Exit if not a Package */
+
+       if (return_object->common.type != ACPI_TYPE_PACKAGE) {
+               return (AE_OK);
+       }
+
+       /* Examine each element of the _CID package */
+
+       element_ptr = return_object->package.elements;
+       for (i = 0; i < return_object->package.count; i++) {
+               original_element = *element_ptr;
+               original_ref_count = original_element->common.reference_count;
+
+               status = acpi_ns_repair_HID(data, element_ptr);
+               if (ACPI_FAILURE(status)) {
+                       return (status);
+               }
+
+               /* Take care with reference counts */
+
+               if (original_element != *element_ptr) {
+
+                       /* Element was replaced */
+
+                       (*element_ptr)->common.reference_count =
+                           original_ref_count;
+
+                       acpi_ut_remove_reference(original_element);
+               }
+
+               element_ptr++;
+       }
+
+       return (AE_OK);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_repair_HID
+ *
+ * PARAMETERS:  Data                - Pointer to validation data structure
+ *              return_object_ptr   - Pointer to the object returned from the
+ *                                    evaluation of a method or object
+ *
+ * RETURN:      Status. AE_OK if object is OK or was repaired successfully
+ *
+ * DESCRIPTION: Repair for the _HID object. If a string, ensure that all
+ *              letters are uppercase and that there is no leading asterisk.
+ *
+ *****************************************************************************/
+
+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);
+}
+
 /******************************************************************************
  *
  * FUNCTION:    acpi_ns_repair_TSS