/******************************************************************************* * * 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_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); }