diff options
Diffstat (limited to 'drivers/acpi/acpica/rslist.c')
| -rw-r--r-- | drivers/acpi/acpica/rslist.c | 94 | 
1 files changed, 75 insertions, 19 deletions
diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c index 7335f22aac2..77291293af6 100644 --- a/drivers/acpi/acpica/rslist.c +++ b/drivers/acpi/acpica/rslist.c @@ -5,7 +5,7 @@   ******************************************************************************/  /* - * Copyright (C) 2000 - 2010, 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,14 +86,37 @@ 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 0x%X)", @@ -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); @@ -152,13 +178,44 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,  			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 0x%X) to AML", @@ -168,9 +225,10 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,  		/* 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 */  | 
