/******************************************************************************* * * 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); }
/******************************************************************************* * * FUNCTION: acpi_rs_convert_aml_to_resources * * PARAMETERS: acpi_walk_aml_callback * resource_ptr - Pointer to the buffer that will * contain the output structures * * RETURN: Status * * DESCRIPTION: Convert an AML resource to an internal representation of the * resource that is aligned and easier to access. * ******************************************************************************/ acpi_status acpi_rs_convert_aml_to_resources(u8 * aml, u32 length, u32 offset, u8 resource_index, void **context) { struct acpi_resource **resource_ptr = ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context); struct acpi_resource *resource; acpi_status status; ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources); /* * Check that the input buffer and all subsequent pointers into it * are aligned on a native word boundary. Most important on IA64 */ resource = *resource_ptr; if (ACPI_IS_MISALIGNED(resource)) { ACPI_WARNING((AE_INFO, "Misaligned resource pointer %p", resource)); } /* 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); } ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Type %.2X, AmlLength %.2X InternalLength %.2X\n", acpi_ut_get_resource_type(aml), length, resource->length)); /* Point to the next structure in the output buffer */ *resource_ptr = ACPI_ADD_PTR(void, resource, resource->length); return_ACPI_STATUS(AE_OK); }
acpi_status acpi_rs_convert_aml_to_resources(u8 * aml, u32 length, u32 offset, u8 resource_index, void **context) { struct acpi_resource **resource_ptr = ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context); struct acpi_resource *resource; acpi_status status; ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources); resource = *resource_ptr; if (ACPI_IS_MISALIGNED(resource)) { ACPI_WARNING((AE_INFO, "Misaligned resource pointer %p", resource)); } 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); } ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Type %.2X, AmlLength %.2X InternalLength %.2X\n", acpi_ut_get_resource_type(aml), length, resource->length)); *resource_ptr = ACPI_ADD_PTR(void, resource, resource->length); return_ACPI_STATUS(AE_OK); }
/******************************************************************************* * * FUNCTION: acpi_rs_convert_aml_to_resources * * PARAMETERS: acpi_walk_aml_callback * resource_ptr - Pointer to the buffer that will * contain the output structures * * RETURN: Status * * DESCRIPTION: Convert an AML resource to an internal representation of the * resource that is aligned and easier to access. * ******************************************************************************/ acpi_status acpi_rs_convert_aml_to_resources(u8 * aml, u32 length, u32 offset, u8 resource_index, void **context) { 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); /* * Check that the input buffer and all subsequent pointers into it * are aligned on a native word boundary. Most important on IA64 */ resource = *resource_ptr; if (ACPI_IS_MISALIGNED(resource)) { ACPI_WARNING((AE_INFO, "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, aml_resource, conversion_table); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not convert AML resource (Type 0x%X)", *aml)); return_ACPI_STATUS(status); } ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "Type %.2X, AmlLength %.2X InternalLength %.2X\n", acpi_ut_get_resource_type(aml), length, resource->length)); /* Point to the next structure in the output buffer */ *resource_ptr = ACPI_NEXT_RESOURCE(resource); return_ACPI_STATUS(AE_OK); }
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_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); }