/******************************************************************************* * * FUNCTION: acpi_rs_convert_aml_to_resources * * PARAMETERS: Aml - Pointer to the resource byte stream * aml_length - Length of Aml * output_buffer - Pointer to the buffer that will * contain the output structures * * RETURN: Status * * DESCRIPTION: Takes the resource byte stream and parses it, creating a * linked list of resources in the caller's output buffer * ******************************************************************************/ acpi_status acpi_rs_convert_aml_to_resources(u8 * aml, u32 aml_length, u8 * output_buffer) { struct acpi_resource *resource = (void *)output_buffer; acpi_status status; u8 resource_index; u8 *end_aml; ACPI_FUNCTION_TRACE("rs_convert_aml_to_resources"); end_aml = aml + aml_length; /* Loop until end-of-buffer or an end_tag is found */ while (aml < end_aml) { /* Validate the Resource Type and Resource Length */ status = acpi_ut_validate_resource(aml, &resource_index); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* 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]); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not convert AML resource (Type %X)", *aml)); return_ACPI_STATUS(status); } /* Normal exit on completion of an end_tag resource descriptor */ if (acpi_ut_get_resource_type(aml) == ACPI_RESOURCE_NAME_END_TAG) { return_ACPI_STATUS(AE_OK); } /* Point to the next input AML resource */ aml += acpi_ut_get_descriptor_length(aml); /* Point to the next structure in the output buffer */ resource = ACPI_ADD_PTR(struct acpi_resource, resource, resource->length); } /* Did not find an end_tag resource descriptor */ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); }
acpi_status acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, acpi_size aml_size_needed, u8 * output_buffer) { 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); /* Walk the resource descriptor list, convert each descriptor */ while (aml < end_aml) { /* Validate the (internal) Resource Type */ if (resource->type > ACPI_RESOURCE_TYPE_MAX) { ACPI_ERROR((AE_INFO, "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 */ 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", resource->type)); return_ACPI_STATUS(status); } /* Perform final sanity check on the new AML resource descriptor */ status = acpi_ut_validate_resource(NULL, ACPI_CAST_PTR(union aml_resource, aml), NULL); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Check for end-of-list, normal exit */ if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { /* An End Tag indicates the end of the input Resource Template */ return_ACPI_STATUS(AE_OK); } /* * Extract the total length of the new descriptor and set the * Aml to point to the next (output) resource descriptor */ aml += acpi_ut_get_descriptor_length(aml); /* Point to the next input resource descriptor */ resource = ACPI_NEXT_RESOURCE(resource); } /* Completed buffer, but did not find an end_tag resource descriptor */ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); }
static void acpi_dm_compare_aml_resources(u8 *aml1_buffer, acpi_rsdesc_size aml1_buffer_length, u8 *aml2_buffer, acpi_rsdesc_size aml2_buffer_length) { u8 *aml1; u8 *aml2; u8 *aml1_end; u8 *aml2_end; acpi_rsdesc_size aml1_length; acpi_rsdesc_size aml2_length; acpi_rsdesc_size offset = 0; u8 resource_type; u32 count = 0; u32 i; /* Compare overall buffer sizes (may be different due to size rounding) */ if (aml1_buffer_length != aml2_buffer_length) { acpi_os_printf("**** Buffer length mismatch in converted " "AML: Original %X, New %X ****\n", aml1_buffer_length, aml2_buffer_length); } aml1 = aml1_buffer; aml2 = aml2_buffer; aml1_end = aml1_buffer + aml1_buffer_length; aml2_end = aml2_buffer + aml2_buffer_length; /* Walk the descriptor lists, comparing each descriptor */ while ((aml1 < aml1_end) && (aml2 < aml2_end)) { /* Get the lengths of each descriptor */ aml1_length = acpi_ut_get_descriptor_length(aml1); aml2_length = acpi_ut_get_descriptor_length(aml2); resource_type = acpi_ut_get_resource_type(aml1); /* Check for descriptor length match */ if (aml1_length != aml2_length) { acpi_os_printf ("**** Length mismatch in descriptor [%.2X] type %2.2X, " "Offset %8.8X Len1 %X, Len2 %X ****\n", count, resource_type, offset, aml1_length, aml2_length); } /* Check for descriptor byte match */ else if (memcmp(aml1, aml2, aml1_length)) { acpi_os_printf ("**** Data mismatch in descriptor [%.2X] type %2.2X, " "Offset %8.8X ****\n", count, resource_type, offset); for (i = 0; i < aml1_length; i++) { if (aml1[i] != aml2[i]) { acpi_os_printf ("Mismatch at byte offset %.2X: is %2.2X, " "should be %2.2X\n", i, aml2[i], aml1[i]); } } } /* Exit on end_tag descriptor */ if (resource_type == ACPI_RESOURCE_NAME_END_TAG) { return; } /* Point to next descriptor in each buffer */ count++; offset += aml1_length; aml1 += aml1_length; aml2 += aml2_length; } }
acpi_status acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, acpi_size aml_size_needed, u8 * output_buffer) { u8 *aml = output_buffer; u8 *end_aml = output_buffer + aml_size_needed; acpi_status status; ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml); while (aml < end_aml) { if (resource->type > ACPI_RESOURCE_TYPE_MAX) { ACPI_ERROR((AE_INFO, "Invalid descriptor type (%X) in resource list", resource->type)); return_ACPI_STATUS(AE_BAD_DATA); } status = acpi_rs_convert_resource_to_aml(resource, ACPI_CAST_PTR(union aml_resource, aml), acpi_gbl_set_resource_dispatch [resource->type]); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not convert resource (type %X) to AML", resource->type)); return_ACPI_STATUS(status); } status = acpi_ut_validate_resource(ACPI_CAST_PTR (union aml_resource, aml), NULL); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { return_ACPI_STATUS(AE_OK); } aml += acpi_ut_get_descriptor_length(aml); resource = ACPI_ADD_PTR(struct acpi_resource, resource, resource->length); } return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); }
acpi_status acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, acpi_size aml_size_needed, u8 * output_buffer) { u8 *aml = output_buffer; u8 *end_aml = output_buffer + aml_size_needed; acpi_status status; ACPI_FUNCTION_TRACE("rs_convert_resources_to_aml"); /* Walk the resource descriptor list, convert each descriptor */ while (aml < end_aml) { /* Validate the (internal) Resource Type */ if (resource->type > ACPI_RESOURCE_TYPE_MAX) { ACPI_ERROR((AE_INFO, "Invalid descriptor type (%X) in resource list", resource->type)); return_ACPI_STATUS(AE_BAD_DATA); } /* 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 (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not convert resource (type %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); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Check for end-of-list, normal exit */ if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { /* An End Tag indicates the end of the input Resource Template */ return_ACPI_STATUS(AE_OK); } /* * Extract the total length of the new descriptor and set the * Aml to point to the next (output) resource descriptor */ aml += acpi_ut_get_descriptor_length(aml); /* Point to the next input resource descriptor */ resource = ACPI_ADD_PTR(struct acpi_resource, resource, resource->length); } /* Completed buffer, but did not find an end_tag resource descriptor */ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); }
acpi_status acpi_rs_get_list_length(u8 * aml_buffer, u32 aml_buffer_length, acpi_size * size_needed) { acpi_status status; u8 *end_aml; u8 *buffer; u32 buffer_size; u16 temp16; u16 resource_length; u32 extra_struct_bytes; u8 resource_index; u8 minimum_aml_resource_length; ACPI_FUNCTION_TRACE(rs_get_list_length); *size_needed = 0; end_aml = aml_buffer + aml_buffer_length; /* Walk the list of AML resource descriptors */ while (aml_buffer < end_aml) { /* Validate the Resource Type and Resource Length */ status = acpi_ut_validate_resource(aml_buffer, &resource_index); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Get the resource length and base (minimum) AML size */ resource_length = acpi_ut_get_resource_length(aml_buffer); minimum_aml_resource_length = acpi_gbl_resource_aml_sizes[resource_index]; /* * Augment the size for descriptors with optional * and/or variable length fields */ extra_struct_bytes = 0; buffer = aml_buffer + acpi_ut_get_resource_header_length(aml_buffer); switch (acpi_ut_get_resource_type(aml_buffer)) { case ACPI_RESOURCE_NAME_IRQ: /* * IRQ Resource: * Get the number of bits set in the 16-bit IRQ mask */ ACPI_MOVE_16_TO_16(&temp16, buffer); extra_struct_bytes = acpi_rs_count_set_bits(temp16); break; case ACPI_RESOURCE_NAME_DMA: /* * DMA Resource: * Get the number of bits set in the 8-bit DMA mask */ extra_struct_bytes = acpi_rs_count_set_bits(*buffer); break; case ACPI_RESOURCE_NAME_VENDOR_SMALL: case ACPI_RESOURCE_NAME_VENDOR_LARGE: /* * Vendor Resource: * Get the number of vendor data bytes */ extra_struct_bytes = resource_length; break; case ACPI_RESOURCE_NAME_END_TAG: /* * End Tag: * This is the normal exit, add size of end_tag */ *size_needed += ACPI_RS_SIZE_MIN; return_ACPI_STATUS(AE_OK); case ACPI_RESOURCE_NAME_ADDRESS32: case ACPI_RESOURCE_NAME_ADDRESS16: case ACPI_RESOURCE_NAME_ADDRESS64: /* * Address Resource: * Add the size of the optional resource_source */ extra_struct_bytes = acpi_rs_stream_option_length(resource_length, minimum_aml_resource_length); break; case ACPI_RESOURCE_NAME_EXTENDED_IRQ: /* * Extended IRQ Resource: * Using the interrupt_table_length, add 4 bytes for each additional * interrupt. Note: at least one interrupt is required and is * included in the minimum descriptor size (reason for the -1) */ extra_struct_bytes = (buffer[1] - 1) * sizeof(u32); /* Add the size of the optional resource_source */ extra_struct_bytes += acpi_rs_stream_option_length(resource_length - extra_struct_bytes, minimum_aml_resource_length); break; default: break; } /* * Update the required buffer size for the internal descriptor structs * * Important: Round the size up for the appropriate alignment. This * is a requirement on IA64. */ buffer_size = acpi_gbl_resource_struct_sizes[resource_index] + extra_struct_bytes; buffer_size = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size); *size_needed += buffer_size; ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Type %.2X, AmlLength %.2X InternalLength %.2X\n", acpi_ut_get_resource_type(aml_buffer), acpi_ut_get_descriptor_length(aml_buffer), buffer_size)); /* * Point to the next resource within the AML stream using the length * contained in the resource descriptor header */ aml_buffer += acpi_ut_get_descriptor_length(aml_buffer); } /* Did not find an end_tag resource descriptor */ return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); }