1 /******************************************************************************* 2 * 3 * Module Name: rslist - Linked list utilities 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2013, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <acpi/acpi.h> 45 #include "accommon.h" 46 #include "acresrc.h" 47 48 #define _COMPONENT ACPI_RESOURCES 49 ACPI_MODULE_NAME("rslist") 50 51 /******************************************************************************* 52 * 53 * FUNCTION: acpi_rs_convert_aml_to_resources 54 * 55 * PARAMETERS: acpi_walk_aml_callback 56 * resource_ptr - Pointer to the buffer that will 57 * contain the output structures 58 * 59 * RETURN: Status 60 * 61 * DESCRIPTION: Convert an AML resource to an internal representation of the 62 * resource that is aligned and easier to access. 63 * 64 ******************************************************************************/ 65 acpi_status 66 acpi_rs_convert_aml_to_resources(u8 * aml, 67 u32 length, 68 u32 offset, u8 resource_index, void **context) 69 { 70 struct acpi_resource **resource_ptr = 71 ACPI_CAST_INDIRECT_PTR(struct acpi_resource, context); 72 struct acpi_resource *resource; 73 union aml_resource *aml_resource; 74 struct acpi_rsconvert_info *conversion_table; 75 acpi_status status; 76 77 ACPI_FUNCTION_TRACE(rs_convert_aml_to_resources); 78 79 /* 80 * Check that the input buffer and all subsequent pointers into it 81 * are aligned on a native word boundary. Most important on IA64 82 */ 83 resource = *resource_ptr; 84 if (ACPI_IS_MISALIGNED(resource)) { 85 ACPI_WARNING((AE_INFO, 86 "Misaligned resource pointer %p", resource)); 87 } 88 89 /* Get the appropriate conversion info table */ 90 91 aml_resource = ACPI_CAST_PTR(union aml_resource, aml); 92 if (acpi_ut_get_resource_type(aml) == ACPI_RESOURCE_NAME_SERIAL_BUS) { 93 if (aml_resource->common_serial_bus.type > 94 AML_RESOURCE_MAX_SERIALBUSTYPE) { 95 conversion_table = NULL; 96 } else { 97 /* This is an I2C, SPI, or UART serial_bus descriptor */ 98 99 conversion_table = 100 acpi_gbl_convert_resource_serial_bus_dispatch 101 [aml_resource->common_serial_bus.type]; 102 } 103 } else { 104 conversion_table = 105 acpi_gbl_get_resource_dispatch[resource_index]; 106 } 107 108 if (!conversion_table) { 109 ACPI_ERROR((AE_INFO, 110 "Invalid/unsupported resource descriptor: Type 0x%2.2X", 111 resource_index)); 112 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); 113 } 114 115 /* Convert the AML byte stream resource to a local resource struct */ 116 117 status = 118 acpi_rs_convert_aml_to_resource(resource, aml_resource, 119 conversion_table); 120 if (ACPI_FAILURE(status)) { 121 ACPI_EXCEPTION((AE_INFO, status, 122 "Could not convert AML resource (Type 0x%X)", 123 *aml)); 124 return_ACPI_STATUS(status); 125 } 126 127 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 128 "Type %.2X, AmlLength %.2X InternalLength %.2X\n", 129 acpi_ut_get_resource_type(aml), length, 130 resource->length)); 131 132 /* Point to the next structure in the output buffer */ 133 134 *resource_ptr = ACPI_NEXT_RESOURCE(resource); 135 return_ACPI_STATUS(AE_OK); 136 } 137 138 /******************************************************************************* 139 * 140 * FUNCTION: acpi_rs_convert_resources_to_aml 141 * 142 * PARAMETERS: resource - Pointer to the resource linked list 143 * aml_size_needed - Calculated size of the byte stream 144 * needed from calling acpi_rs_get_aml_length() 145 * The size of the output_buffer is 146 * guaranteed to be >= aml_size_needed 147 * output_buffer - Pointer to the buffer that will 148 * contain the byte stream 149 * 150 * RETURN: Status 151 * 152 * DESCRIPTION: Takes the resource linked list and parses it, creating a 153 * byte stream of resources in the caller's output buffer 154 * 155 ******************************************************************************/ 156 157 acpi_status 158 acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, 159 acpi_size aml_size_needed, u8 * output_buffer) 160 { 161 u8 *aml = output_buffer; 162 u8 *end_aml = output_buffer + aml_size_needed; 163 struct acpi_rsconvert_info *conversion_table; 164 acpi_status status; 165 166 ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml); 167 168 /* Walk the resource descriptor list, convert each descriptor */ 169 170 while (aml < end_aml) { 171 172 /* Validate the (internal) Resource Type */ 173 174 if (resource->type > ACPI_RESOURCE_TYPE_MAX) { 175 ACPI_ERROR((AE_INFO, 176 "Invalid descriptor type (0x%X) in resource list", 177 resource->type)); 178 return_ACPI_STATUS(AE_BAD_DATA); 179 } 180 181 /* Sanity check the length. It must not be zero, or we loop forever */ 182 183 if (!resource->length) { 184 ACPI_ERROR((AE_INFO, 185 "Invalid zero length descriptor in resource list\n")); 186 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); 187 } 188 189 /* Perform the conversion */ 190 191 if (resource->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { 192 if (resource->data.common_serial_bus.type > 193 AML_RESOURCE_MAX_SERIALBUSTYPE) { 194 conversion_table = NULL; 195 } else { 196 /* This is an I2C, SPI, or UART serial_bus descriptor */ 197 198 conversion_table = 199 acpi_gbl_convert_resource_serial_bus_dispatch 200 [resource->data.common_serial_bus.type]; 201 } 202 } else { 203 conversion_table = 204 acpi_gbl_set_resource_dispatch[resource->type]; 205 } 206 207 if (!conversion_table) { 208 ACPI_ERROR((AE_INFO, 209 "Invalid/unsupported resource descriptor: Type 0x%2.2X", 210 resource->type)); 211 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); 212 } 213 214 status = acpi_rs_convert_resource_to_aml(resource, 215 ACPI_CAST_PTR(union 216 aml_resource, 217 aml), 218 conversion_table); 219 if (ACPI_FAILURE(status)) { 220 ACPI_EXCEPTION((AE_INFO, status, 221 "Could not convert resource (type 0x%X) to AML", 222 resource->type)); 223 return_ACPI_STATUS(status); 224 } 225 226 /* Perform final sanity check on the new AML resource descriptor */ 227 228 status = acpi_ut_validate_resource(NULL, 229 ACPI_CAST_PTR(union 230 aml_resource, 231 aml), NULL); 232 if (ACPI_FAILURE(status)) { 233 return_ACPI_STATUS(status); 234 } 235 236 /* Check for end-of-list, normal exit */ 237 238 if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { 239 240 /* An End Tag indicates the end of the input Resource Template */ 241 242 return_ACPI_STATUS(AE_OK); 243 } 244 245 /* 246 * Extract the total length of the new descriptor and set the 247 * Aml to point to the next (output) resource descriptor 248 */ 249 aml += acpi_ut_get_descriptor_length(aml); 250 251 /* Point to the next input resource descriptor */ 252 253 resource = ACPI_NEXT_RESOURCE(resource); 254 } 255 256 /* Completed buffer, but did not find an end_tag resource descriptor */ 257 258 return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); 259 } 260