diff options
Diffstat (limited to 'drivers/acpi/acpica/rslist.c')
| -rw-r--r-- | drivers/acpi/acpica/rslist.c | 100 |
1 files changed, 78 insertions, 22 deletions
diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c index 1b1dbc69f08..77291293af6 100644 --- a/drivers/acpi/acpica/rslist.c +++ b/drivers/acpi/acpica/rslist.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2008, Intel Corp. + * Copyright (C) 2000 - 2014, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -70,6 +70,8 @@ acpi_rs_convert_aml_to_resources(u8 * aml, struct acpi_resource **resource_ptr = ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context); struct acpi_resource *resource; + union aml_resource *aml_resource; + struct acpi_rsconvert_info *conversion_table; acpi_status status; ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources); @@ -84,17 +86,40 @@ acpi_rs_convert_aml_to_resources(u8 * aml, "Misaligned resource pointer %p", resource)); } + /* Get the appropriate conversion info table */ + + aml_resource = ACPI_CAST_PTR(union aml_resource, aml); + if (acpi_ut_get_resource_type(aml) == ACPI_RESOURCE_NAME_SERIAL_BUS) { + if (aml_resource->common_serial_bus.type > + AML_RESOURCE_MAX_SERIALBUSTYPE) { + conversion_table = NULL; + } else { + /* This is an I2C, SPI, or UART serial_bus descriptor */ + + conversion_table = + acpi_gbl_convert_resource_serial_bus_dispatch + [aml_resource->common_serial_bus.type]; + } + } else { + conversion_table = + acpi_gbl_get_resource_dispatch[resource_index]; + } + + if (!conversion_table) { + ACPI_ERROR((AE_INFO, + "Invalid/unsupported resource descriptor: Type 0x%2.2X", + resource_index)); + return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); + } + /* Convert the AML byte stream resource to a local resource struct */ status = - acpi_rs_convert_aml_to_resource(resource, - ACPI_CAST_PTR(union aml_resource, - aml), - acpi_gbl_get_resource_dispatch - [resource_index]); + acpi_rs_convert_aml_to_resource(resource, aml_resource, + conversion_table); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "Could not convert AML resource (Type %X)", + "Could not convert AML resource (Type 0x%X)", *aml)); return_ACPI_STATUS(status); } @@ -106,7 +131,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml, /* Point to the next structure in the output buffer */ - *resource_ptr = ACPI_ADD_PTR(void, resource, resource->length); + *resource_ptr = ACPI_NEXT_RESOURCE(resource); return_ACPI_STATUS(AE_OK); } @@ -114,7 +139,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml, * * FUNCTION: acpi_rs_convert_resources_to_aml * - * PARAMETERS: Resource - Pointer to the resource linked list + * PARAMETERS: resource - Pointer to the resource linked list * aml_size_needed - Calculated size of the byte stream * needed from calling acpi_rs_get_aml_length() * The size of the output_buffer is @@ -135,6 +160,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, { u8 *aml = output_buffer; u8 *end_aml = output_buffer + aml_size_needed; + struct acpi_rsconvert_info *conversion_table; acpi_status status; ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml); @@ -147,30 +173,62 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, if (resource->type > ACPI_RESOURCE_TYPE_MAX) { ACPI_ERROR((AE_INFO, - "Invalid descriptor type (%X) in resource list", + "Invalid descriptor type (0x%X) in resource list", resource->type)); return_ACPI_STATUS(AE_BAD_DATA); } + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!resource->length) { + ACPI_ERROR((AE_INFO, + "Invalid zero length descriptor in resource list\n")); + return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); + } + /* Perform the conversion */ - status = acpi_rs_convert_resource_to_aml(resource, ACPI_CAST_PTR(union - aml_resource, - aml), - acpi_gbl_set_resource_dispatch - [resource->type]); + if (resource->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { + if (resource->data.common_serial_bus.type > + AML_RESOURCE_MAX_SERIALBUSTYPE) { + conversion_table = NULL; + } else { + /* This is an I2C, SPI, or UART serial_bus descriptor */ + + conversion_table = + acpi_gbl_convert_resource_serial_bus_dispatch + [resource->data.common_serial_bus.type]; + } + } else { + conversion_table = + acpi_gbl_set_resource_dispatch[resource->type]; + } + + if (!conversion_table) { + ACPI_ERROR((AE_INFO, + "Invalid/unsupported resource descriptor: Type 0x%2.2X", + resource->type)); + return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); + } + + status = acpi_rs_convert_resource_to_aml(resource, + ACPI_CAST_PTR(union + aml_resource, + aml), + conversion_table); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, - "Could not convert resource (type %X) to AML", + "Could not convert resource (type 0x%X) to AML", resource->type)); return_ACPI_STATUS(status); } /* Perform final sanity check on the new AML resource descriptor */ - status = - acpi_ut_validate_resource(ACPI_CAST_PTR - (union aml_resource, aml), NULL); + status = acpi_ut_validate_resource(NULL, + ACPI_CAST_PTR(union + aml_resource, + aml), NULL); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -192,9 +250,7 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, /* Point to the next input resource descriptor */ - resource = - ACPI_ADD_PTR(struct acpi_resource, resource, - resource->length); + resource = ACPI_NEXT_RESOURCE(resource); } /* Completed buffer, but did not find an end_tag resource descriptor */ |
