1 /******************************************************************************* 2 * 3 * Module Name: rslist - Linked list utilities 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 93 if (acpi_ut_get_resource_type(aml) == ACPI_RESOURCE_NAME_SERIAL_BUS) { 94 if (aml_resource->common_serial_bus.type > 95 AML_RESOURCE_MAX_SERIALBUSTYPE) { 96 conversion_table = NULL; 97 } else { 98 /* This is an I2C, SPI, or UART serial_bus descriptor */ 99 100 conversion_table = 101 acpi_gbl_convert_resource_serial_bus_dispatch 102 [aml_resource->common_serial_bus.type]; 103 } 104 } else { 105 conversion_table = 106 acpi_gbl_get_resource_dispatch[resource_index]; 107 } 108 109 if (!conversion_table) { 110 ACPI_ERROR((AE_INFO, 111 "Invalid/unsupported resource descriptor: Type 0x%2.2X", 112 resource_index)); 113 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); 114 } 115 116 /* Convert the AML byte stream resource to a local resource struct */ 117 118 status = 119 acpi_rs_convert_aml_to_resource(resource, aml_resource, 120 conversion_table); 121 if (ACPI_FAILURE(status)) { 122 ACPI_EXCEPTION((AE_INFO, status, 123 "Could not convert AML resource (Type 0x%X)", 124 *aml)); 125 return_ACPI_STATUS(status); 126 } 127 128 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, 129 "Type %.2X, AmlLength %.2X InternalLength %.2X\n", 130 acpi_ut_get_resource_type(aml), length, 131 resource->length)); 132 133 /* Point to the next structure in the output buffer */ 134 135 *resource_ptr = ACPI_NEXT_RESOURCE(resource); 136 return_ACPI_STATUS(AE_OK); 137 } 138 139 /******************************************************************************* 140 * 141 * FUNCTION: acpi_rs_convert_resources_to_aml 142 * 143 * PARAMETERS: resource - Pointer to the resource linked list 144 * aml_size_needed - Calculated size of the byte stream 145 * needed from calling acpi_rs_get_aml_length() 146 * The size of the output_buffer is 147 * guaranteed to be >= aml_size_needed 148 * output_buffer - Pointer to the buffer that will 149 * contain the byte stream 150 * 151 * RETURN: Status 152 * 153 * DESCRIPTION: Takes the resource linked list and parses it, creating a 154 * byte stream of resources in the caller's output buffer 155 * 156 ******************************************************************************/ 157 158 acpi_status 159 acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, 160 acpi_size aml_size_needed, u8 * output_buffer) 161 { 162 u8 *aml = output_buffer; 163 u8 *end_aml = output_buffer + aml_size_needed; 164 struct acpi_rsconvert_info *conversion_table; 165 acpi_status status; 166 167 ACPI_FUNCTION_TRACE(rs_convert_resources_to_aml); 168 169 /* Walk the resource descriptor list, convert each descriptor */ 170 171 while (aml < end_aml) { 172 173 /* Validate the (internal) Resource Type */ 174 175 if (resource->type > ACPI_RESOURCE_TYPE_MAX) { 176 ACPI_ERROR((AE_INFO, 177 "Invalid descriptor type (0x%X) in resource list", 178 resource->type)); 179 return_ACPI_STATUS(AE_BAD_DATA); 180 } 181 182 /* Sanity check the length. It must not be zero, or we loop forever */ 183 184 if (!resource->length) { 185 ACPI_ERROR((AE_INFO, 186 "Invalid zero length descriptor in resource list\n")); 187 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); 188 } 189 190 /* Perform the conversion */ 191 192 if (resource->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) { 193 if (resource->data.common_serial_bus.type > 194 AML_RESOURCE_MAX_SERIALBUSTYPE) { 195 conversion_table = NULL; 196 } else { 197 /* This is an I2C, SPI, or UART serial_bus descriptor */ 198 199 conversion_table = 200 acpi_gbl_convert_resource_serial_bus_dispatch 201 [resource->data.common_serial_bus.type]; 202 } 203 } else { 204 conversion_table = 205 acpi_gbl_set_resource_dispatch[resource->type]; 206 } 207 208 if (!conversion_table) { 209 ACPI_ERROR((AE_INFO, 210 "Invalid/unsupported resource descriptor: Type 0x%2.2X", 211 resource->type)); 212 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE); 213 } 214 215 status = acpi_rs_convert_resource_to_aml(resource, 216 ACPI_CAST_PTR(union 217 aml_resource, 218 aml), 219 conversion_table); 220 if (ACPI_FAILURE(status)) { 221 ACPI_EXCEPTION((AE_INFO, status, 222 "Could not convert resource (type 0x%X) to AML", 223 resource->type)); 224 return_ACPI_STATUS(status); 225 } 226 227 /* Perform final sanity check on the new AML resource descriptor */ 228 229 status = 230 acpi_ut_validate_resource(NULL, 231 ACPI_CAST_PTR(union aml_resource, 232 aml), NULL); 233 if (ACPI_FAILURE(status)) { 234 return_ACPI_STATUS(status); 235 } 236 237 /* Check for end-of-list, normal exit */ 238 239 if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) { 240 241 /* An End Tag indicates the end of the input Resource Template */ 242 243 return_ACPI_STATUS(AE_OK); 244 } 245 246 /* 247 * Extract the total length of the new descriptor and set the 248 * Aml to point to the next (output) resource descriptor 249 */ 250 aml += acpi_ut_get_descriptor_length(aml); 251 252 /* Point to the next input resource descriptor */ 253 254 resource = ACPI_NEXT_RESOURCE(resource); 255 } 256 257 /* Completed buffer, but did not find an end_tag resource descriptor */ 258 259 return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); 260 } 261