Skip to content

Commit

Permalink
ACPICA: Add repair for _HID and _CID strings
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Bob Moore authored and Len Brown committed Oct 1, 2010
1 parent cc84e26 commit 77b23f7
Showing 1 changed file with 163 additions and 0 deletions.
163 changes: 163 additions & 0 deletions drivers/acpi/acpica/nsrepair2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
*
Expand All @@ -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 */
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 77b23f7

Please sign in to comment.