diff options
Diffstat (limited to 'drivers/acpi/resources/rsutils.c')
-rw-r--r-- | drivers/acpi/resources/rsutils.c | 437 |
1 files changed, 435 insertions, 2 deletions
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c index 4446778eaf79..9d503de1a349 100644 --- a/drivers/acpi/resources/rsutils.c +++ b/drivers/acpi/resources/rsutils.c @@ -50,6 +50,438 @@ ACPI_MODULE_NAME("rsutils") /******************************************************************************* * + * FUNCTION: acpi_rs_move_data + * + * PARAMETERS: Destination - Pointer to the destination descriptor + * Source - Pointer to the source descriptor + * item_count - How many items to move + * move_type - Byte width + * + * RETURN: None + * + * DESCRIPTION: Move multiple data items from one descriptor to another. Handles + * alignment issues and endian issues if necessary, as configured + * via the ACPI_MOVE_* macros. (This is why a memcpy is not used) + * + ******************************************************************************/ +void +acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type) +{ + acpi_native_uint i; + + /* One move per item */ + + for (i = 0; i < item_count; i++) { + switch (move_type) { + case ACPI_MOVE_TYPE_16_TO_32: + ACPI_MOVE_16_TO_32(&((u32 *) destination)[i], + &((u16 *) source)[i]); + break; + + case ACPI_MOVE_TYPE_32_TO_16: + ACPI_MOVE_32_TO_16(&((u16 *) destination)[i], + &((u32 *) source)[i]); + break; + + case ACPI_MOVE_TYPE_32_TO_32: + ACPI_MOVE_32_TO_32(&((u32 *) destination)[i], + &((u32 *) source)[i]); + break; + + case ACPI_MOVE_TYPE_64_TO_64: + ACPI_MOVE_64_TO_64(&((u64 *) destination)[i], + &((u64 *) source)[i]); + break; + + default: + return; + } + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_resource_info + * + * PARAMETERS: resource_type - Byte 0 of a resource descriptor + * + * RETURN: Pointer to the resource conversion handler + * + * DESCRIPTION: Extract the Resource Type/Name from the first byte of + * a resource descriptor. + * + ******************************************************************************/ + +struct acpi_resource_info *acpi_rs_get_resource_info(u8 resource_type) +{ + struct acpi_resource_info *size_info; + + ACPI_FUNCTION_ENTRY(); + + /* Determine if this is a small or large resource */ + + if (resource_type & ACPI_RESOURCE_NAME_LARGE) { + /* Large Resource Type -- bits 6:0 contain the name */ + + if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) { + return (NULL); + } + + size_info = &acpi_gbl_lg_resource_info[(resource_type & + ACPI_RESOURCE_NAME_LARGE_MASK)]; + } else { + /* Small Resource Type -- bits 6:3 contain the name */ + + size_info = &acpi_gbl_sm_resource_info[((resource_type & + ACPI_RESOURCE_NAME_SMALL_MASK) + >> 3)]; + } + + /* Zero entry indicates an invalid resource type */ + + if (!size_info->minimum_internal_struct_length) { + return (NULL); + } + + return (size_info); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_resource_length + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Byte Length + * + * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By + * definition, this does not include the size of the descriptor + * header or the length field itself. + * + ******************************************************************************/ + +u16 acpi_rs_get_resource_length(union aml_resource * aml) +{ + u16 resource_length; + + ACPI_FUNCTION_ENTRY(); + + /* Determine if this is a small or large resource */ + + if (aml->large_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) { + /* Large Resource type -- bytes 1-2 contain the 16-bit length */ + + ACPI_MOVE_16_TO_16(&resource_length, + &aml->large_header.resource_length); + + } else { + /* Small Resource type -- bits 2:0 of byte 0 contain the length */ + + resource_length = (u16) (aml->small_header.descriptor_type & + ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK); + } + + return (resource_length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_descriptor_length + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Byte length + * + * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the + * length of the descriptor header and the length field itself. + * Used to walk descriptor lists. + * + ******************************************************************************/ + +u32 acpi_rs_get_descriptor_length(union aml_resource * aml) +{ + u32 descriptor_length; + + ACPI_FUNCTION_ENTRY(); + + /* Determine if this is a small or large resource */ + + if (aml->large_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) { + /* Large Resource type -- bytes 1-2 contain the 16-bit length */ + + ACPI_MOVE_16_TO_32(&descriptor_length, + &aml->large_header.resource_length); + descriptor_length += sizeof(struct aml_resource_large_header); + + } else { + /* Small Resource type -- bits 2:0 of byte 0 contain the length */ + + descriptor_length = (u32) (aml->small_header.descriptor_type & + ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK); + descriptor_length += sizeof(struct aml_resource_small_header); + } + + return (descriptor_length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_set_resource_header + * + * PARAMETERS: descriptor_type - Byte to be inserted as the type + * total_length - Length of the AML descriptor, including + * the header and length fields. + * Aml - Pointer to the raw AML descriptor + * + * RETURN: None + * + * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML + * resource descriptor, both Large and Small descriptors are + * supported automatically + * + ******************************************************************************/ + +void +acpi_rs_set_resource_header(u8 descriptor_type, + acpi_size total_length, union aml_resource *aml) +{ + u16 resource_length; + + ACPI_FUNCTION_ENTRY(); + + /* Set the descriptor type */ + + aml->small_header.descriptor_type = descriptor_type; + + /* Determine if this is a small or large resource */ + + if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) { + /* Large Resource type -- bytes 1-2 contain the 16-bit length */ + + resource_length = + (u16) (total_length - + sizeof(struct aml_resource_large_header)); + + /* Insert length into the Large descriptor length field */ + + ACPI_MOVE_16_TO_16(&aml->large_header.resource_length, + &resource_length); + } else { + /* Small Resource type -- bits 2:0 of byte 0 contain the length */ + + resource_length = + (u16) (total_length - + sizeof(struct aml_resource_small_header)); + + /* Insert length into the descriptor type byte */ + + aml->small_header.descriptor_type |= (u8) resource_length; + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_resource_type + * + * PARAMETERS: resource_type - Byte 0 of a resource descriptor + * + * RETURN: The Resource Type with no extraneous bits (except the + * Large/Small descriptor bit -- this is left alone) + * + * DESCRIPTION: Extract the Resource Type/Name from the first byte of + * a resource descriptor. + * + ******************************************************************************/ + +u8 acpi_rs_get_resource_type(u8 resource_type) +{ + ACPI_FUNCTION_ENTRY(); + + /* Determine if this is a small or large resource */ + + if (resource_type & ACPI_RESOURCE_NAME_LARGE) { + /* Large Resource Type -- bits 6:0 contain the name */ + + return (resource_type); + } else { + /* Small Resource Type -- bits 6:3 contain the name */ + + return ((u8) (resource_type & ACPI_RESOURCE_NAME_SMALL_MASK)); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_strcpy + * + * PARAMETERS: Destination - Pointer to the destination string + * Source - Pointer to the source string + * + * RETURN: String length, including NULL terminator + * + * DESCRIPTION: Local string copy that returns the string length, saving a + * strcpy followed by a strlen. + * + ******************************************************************************/ + +static u16 acpi_rs_strcpy(char *destination, char *source) +{ + u16 i; + + ACPI_FUNCTION_ENTRY(); + + for (i = 0; source[i]; i++) { + destination[i] = source[i]; + } + + destination[i] = 0; + + /* Return string length including the NULL terminator */ + + return ((u16) (i + 1)); +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_get_resource_source + * + * PARAMETERS: resource_length - Length field of the descriptor + * minimum_length - Minimum length of the descriptor (minus + * any optional fields) + * resource_source - Where the resource_source is returned + * Aml - Pointer to the raw AML descriptor + * string_ptr - (optional) where to store the actual + * resource_source string + * + * RETURN: Length of the string plus NULL terminator, rounded up to 32 bit + * + * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor + * to an internal resource descriptor + * + ******************************************************************************/ + +u16 +acpi_rs_get_resource_source(u16 resource_length, + acpi_size minimum_length, + struct acpi_resource_source * resource_source, + union aml_resource * aml, char *string_ptr) +{ + acpi_size total_length; + u8 *aml_resource_source; + + ACPI_FUNCTION_ENTRY(); + + total_length = + resource_length + sizeof(struct aml_resource_large_header); + aml_resource_source = ((u8 *) aml) + minimum_length; + + /* + * resource_source is present if the length of the descriptor is longer than + * the minimum length. + * + * Note: Some resource descriptors will have an additional null, so + * we add 1 to the minimum length. + */ + if (total_length > (minimum_length + 1)) { + /* Get the resource_source_index */ + + resource_source->index = aml_resource_source[0]; + + resource_source->string_ptr = string_ptr; + if (!string_ptr) { + /* + * String destination pointer is not specified; Set the String + * pointer to the end of the current resource_source structure. + */ + resource_source->string_ptr = (char *) + ((u8 *) resource_source) + + sizeof(struct acpi_resource_source); + } + + /* Copy the resource_source string to the destination */ + + resource_source->string_length = + acpi_rs_strcpy(resource_source->string_ptr, + (char *)&aml_resource_source[1]); + + /* + * In order for the struct_size to fall on a 32-bit boundary, + * calculate the length of the string and expand the + * struct_size to the next 32-bit boundary. + */ + return ((u16) + ACPI_ROUND_UP_to_32_bITS(resource_source-> + string_length)); + } else { + /* resource_source is not present */ + + resource_source->index = 0; + resource_source->string_length = 0; + resource_source->string_ptr = NULL; + return (0); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_rs_set_resource_source + * + * PARAMETERS: Aml - Pointer to the raw AML descriptor + * minimum_length - Minimum length of the descriptor (minus + * any optional fields) + * resource_source - Internal resource_source + + * + * RETURN: Total length of the AML descriptor + * + * DESCRIPTION: Convert an optoinal resource_source from internal format to a + * raw AML resource descriptor + * + ******************************************************************************/ + +acpi_size +acpi_rs_set_resource_source(union aml_resource * aml, + acpi_size minimum_length, + struct acpi_resource_source * resource_source) +{ + u8 *aml_resource_source; + acpi_size descriptor_length; + + ACPI_FUNCTION_ENTRY(); + + descriptor_length = minimum_length; + + /* Non-zero string length indicates presence of a resource_source */ + + if (resource_source->string_length) { + /* Point to the end of the AML descriptor */ + + aml_resource_source = ((u8 *) aml) + minimum_length; + + /* Copy the resource_source_index */ + + aml_resource_source[0] = (u8) resource_source->index; + + /* Copy the resource_source string */ + + ACPI_STRCPY((char *)&aml_resource_source[1], + resource_source->string_ptr); + + /* + * Add the length of the string (+ 1 for null terminator) to the + * final descriptor length + */ + descriptor_length += + ((acpi_size) resource_source->string_length + 1); + } + + /* Return the new total length of the AML descriptor */ + + return (descriptor_length); +} + +/******************************************************************************* + * * FUNCTION: acpi_rs_get_prt_method_data * * PARAMETERS: Handle - a handle to the containing object @@ -65,8 +497,9 @@ ACPI_MODULE_NAME("rsutils") * and the contents of the callers buffer is undefined. * ******************************************************************************/ + acpi_status -acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer) +acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer) { union acpi_operand_object *obj_desc; acpi_status status; @@ -284,7 +717,7 @@ acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer) * Convert the linked list into a byte stream */ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; - status = acpi_rs_create_byte_stream(in_buffer->pointer, &buffer); + status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } |