diff options
author | Bob Moore <robert.moore@intel.com> | 2010-09-15 10:11:02 +0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-10-01 09:47:56 +0400 |
commit | 77b23f712bc40a65160e7d02b045f1562bb43ff1 (patch) | |
tree | df0da95ce1d95a2c30c5b517cded2a016ea48744 /drivers/acpi/acpica | |
parent | cc84e262b71bab53c3b2be2e71209c85b88b4b4d (diff) | |
download | linux-77b23f712bc40a65160e7d02b045f1562bb43ff1.tar.xz |
ACPICA: Add repair for _HID and _CID strings
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>
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r-- | drivers/acpi/acpica/nsrepair2.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 4009498fbabd..4ef9f43ea926 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -74,10 +74,18 @@ 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 */ @@ -321,6 +333,157 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data, /****************************************************************************** * + * 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 * * PARAMETERS: Data - Pointer to validation data structure |