summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/resources/rsutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/resources/rsutils.c')
-rw-r--r--drivers/acpi/resources/rsutils.c437
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);
}