Commit 6273f00e authored by Lv Zheng's avatar Lv Zheng Committed by Rafael J. Wysocki

ACPICA: Fix buffer allocation issue for generic_serial_bus region accesses.

The size of the buffer allocated for generic_serial_bus region access
is not correct.  This patch introduces acpi_ex_get_serial_access_length()
to be invoked to obtain correct data buffer length.
Signed-off-by: default avatarLv Zheng <lv.zheng@intel.com>
Reported by: Lan Tianyu <tianyu.lan@intel.com>
Acked-by: default avatarLan Tianyu <tianyu.lan@intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent a798c10f
...@@ -45,10 +45,71 @@ ...@@ -45,10 +45,71 @@
#include "accommon.h" #include "accommon.h"
#include "acdispat.h" #include "acdispat.h"
#include "acinterp.h" #include "acinterp.h"
#include "amlcode.h"
#define _COMPONENT ACPI_EXECUTER #define _COMPONENT ACPI_EXECUTER
ACPI_MODULE_NAME("exfield") ACPI_MODULE_NAME("exfield")
/* Local prototypes */
static u32
acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length);
/*******************************************************************************
*
* FUNCTION: acpi_get_serial_access_bytes
*
* PARAMETERS: accessor_type - The type of the protocol indicated by region
* field access attributes
* access_length - The access length of the region field
*
* RETURN: Decoded access length
*
* DESCRIPTION: This routine returns the length of the generic_serial_bus
* protocol bytes
*
******************************************************************************/
static u32
acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length)
{
u32 length;
switch (accessor_type) {
case AML_FIELD_ATTRIB_QUICK:
length = 0;
break;
case AML_FIELD_ATTRIB_SEND_RCV:
case AML_FIELD_ATTRIB_BYTE:
length = 1;
break;
case AML_FIELD_ATTRIB_WORD:
case AML_FIELD_ATTRIB_WORD_CALL:
length = 2;
break;
case AML_FIELD_ATTRIB_MULTIBYTE:
case AML_FIELD_ATTRIB_RAW_BYTES:
case AML_FIELD_ATTRIB_RAW_PROCESS:
length = access_length;
break;
case AML_FIELD_ATTRIB_BLOCK:
case AML_FIELD_ATTRIB_BLOCK_CALL:
default:
length = ACPI_GSBUS_BUFFER_SIZE;
break;
}
return (length);
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ex_read_data_from_field * FUNCTION: acpi_ex_read_data_from_field
...@@ -63,8 +124,9 @@ ACPI_MODULE_NAME("exfield") ...@@ -63,8 +124,9 @@ ACPI_MODULE_NAME("exfield")
* Buffer, depending on the size of the field. * Buffer, depending on the size of the field.
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
union acpi_operand_object *obj_desc, union acpi_operand_object *obj_desc,
union acpi_operand_object **ret_buffer_desc) union acpi_operand_object **ret_buffer_desc)
{ {
...@@ -73,6 +135,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, ...@@ -73,6 +135,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
acpi_size length; acpi_size length;
void *buffer; void *buffer;
u32 function; u32 function;
u16 accessor_type;
ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
...@@ -116,9 +179,22 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, ...@@ -116,9 +179,22 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
ACPI_READ | (obj_desc->field.attribute << 16); ACPI_READ | (obj_desc->field.attribute << 16);
} else if (obj_desc->field.region_obj->region.space_id == } else if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_GSBUS) { ACPI_ADR_SPACE_GSBUS) {
length = ACPI_GSBUS_BUFFER_SIZE; accessor_type = obj_desc->field.attribute;
function = length = acpi_ex_get_serial_access_length(accessor_type,
ACPI_READ | (obj_desc->field.attribute << 16); obj_desc->
field.
access_length);
/*
* Add additional 2 bytes for modeled generic_serial_bus data buffer:
* typedef struct {
* BYTEStatus; // Byte 0 of the data buffer
* BYTELength; // Byte 1 of the data buffer
* BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer,
* }
*/
length += 2;
function = ACPI_READ | (accessor_type << 16);
} else { /* IPMI */ } else { /* IPMI */
length = ACPI_IPMI_BUFFER_SIZE; length = ACPI_IPMI_BUFFER_SIZE;
...@@ -231,6 +307,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, ...@@ -231,6 +307,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
void *buffer; void *buffer;
union acpi_operand_object *buffer_desc; union acpi_operand_object *buffer_desc;
u32 function; u32 function;
u16 accessor_type;
ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
...@@ -284,9 +361,22 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, ...@@ -284,9 +361,22 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
ACPI_WRITE | (obj_desc->field.attribute << 16); ACPI_WRITE | (obj_desc->field.attribute << 16);
} else if (obj_desc->field.region_obj->region.space_id == } else if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_GSBUS) { ACPI_ADR_SPACE_GSBUS) {
length = ACPI_GSBUS_BUFFER_SIZE; accessor_type = obj_desc->field.attribute;
function = length = acpi_ex_get_serial_access_length(accessor_type,
ACPI_WRITE | (obj_desc->field.attribute << 16); obj_desc->
field.
access_length);
/*
* Add additional 2 bytes for modeled generic_serial_bus data buffer:
* typedef struct {
* BYTEStatus; // Byte 0 of the data buffer
* BYTELength; // Byte 1 of the data buffer
* BYTE[x-1]Data; // Bytes 2-x of the arbitrary length data buffer,
* }
*/
length += 2;
function = ACPI_WRITE | (accessor_type << 16);
} else { /* IPMI */ } else { /* IPMI */
length = ACPI_IPMI_BUFFER_SIZE; length = ACPI_IPMI_BUFFER_SIZE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment