rslist.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /*******************************************************************************
  2. *
  3. * Module Name: rslist - Linked list utilities
  4. *
  5. ******************************************************************************/
  6. /*
  7. * Copyright (C) 2000 - 2005, R. Byron Moore
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions, and the following disclaimer,
  15. * without modification.
  16. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  17. * substantially similar to the "NO WARRANTY" disclaimer below
  18. * ("Disclaimer") and any redistribution must be conditioned upon
  19. * including a substantially similar Disclaimer requirement for further
  20. * binary redistribution.
  21. * 3. Neither the names of the above-listed copyright holders nor the names
  22. * of any contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * Alternatively, this software may be distributed under the terms of the
  26. * GNU General Public License ("GPL") version 2 as published by the Free
  27. * Software Foundation.
  28. *
  29. * NO WARRANTY
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  33. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  34. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  38. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  39. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGES.
  41. */
  42. #include <acpi/acpi.h>
  43. #include <acpi/acresrc.h>
  44. #define _COMPONENT ACPI_RESOURCES
  45. ACPI_MODULE_NAME("rslist")
  46. /* Local prototypes */
  47. static ACPI_GET_RESOURCE_HANDLER acpi_rs_get_resource_handler(u8 resource_type);
  48. static acpi_status acpi_rs_validate_resource_length(union aml_resource *aml);
  49. /*******************************************************************************
  50. *
  51. * FUNCTION: acpi_rs_validate_resource_length
  52. *
  53. * PARAMETERS: Aml - Pointer to the AML resource descriptor
  54. *
  55. * RETURN: Status - AE_OK if the resource length appears valid
  56. *
  57. * DESCRIPTION: Validate the resource_length. Fixed-length descriptors must
  58. * have the exact length; variable-length descriptors must be
  59. * at least as long as the minimum. Certain Small descriptors
  60. * can vary in size by at most one byte.
  61. *
  62. ******************************************************************************/
  63. static acpi_status acpi_rs_validate_resource_length(union aml_resource *aml)
  64. {
  65. struct acpi_resource_info *resource_info;
  66. u16 minimum_aml_resource_length;
  67. u16 resource_length;
  68. ACPI_FUNCTION_ENTRY();
  69. /* Get the size and type info about this resource descriptor */
  70. resource_info =
  71. acpi_rs_get_resource_info(aml->small_header.descriptor_type);
  72. if (!resource_info) {
  73. return (AE_AML_INVALID_RESOURCE_TYPE);
  74. }
  75. resource_length = acpi_rs_get_resource_length(aml);
  76. minimum_aml_resource_length =
  77. resource_info->minimum_aml_resource_length;
  78. /* Validate based upon the type of resource, fixed length or variable */
  79. if (resource_info->length_type == ACPI_FIXED_LENGTH) {
  80. /* Fixed length resource, length must match exactly */
  81. if (resource_length != minimum_aml_resource_length) {
  82. return (AE_AML_BAD_RESOURCE_LENGTH);
  83. }
  84. } else if (resource_info->length_type == ACPI_VARIABLE_LENGTH) {
  85. /* Variable length resource, must be at least the minimum */
  86. if (resource_length < minimum_aml_resource_length) {
  87. return (AE_AML_BAD_RESOURCE_LENGTH);
  88. }
  89. } else {
  90. /* Small variable length resource, allowed to be (Min) or (Min-1) */
  91. if ((resource_length > minimum_aml_resource_length) ||
  92. (resource_length < (minimum_aml_resource_length - 1))) {
  93. return (AE_AML_BAD_RESOURCE_LENGTH);
  94. }
  95. }
  96. return (AE_OK);
  97. }
  98. /*******************************************************************************
  99. *
  100. * FUNCTION: acpi_rs_get_resource_handler
  101. *
  102. * PARAMETERS: resource_type - Byte 0 of a resource descriptor
  103. *
  104. * RETURN: Pointer to the resource conversion handler
  105. *
  106. * DESCRIPTION: Extract the Resource Type/Name from the first byte of
  107. * a resource descriptor.
  108. *
  109. ******************************************************************************/
  110. static ACPI_GET_RESOURCE_HANDLER acpi_rs_get_resource_handler(u8 resource_type)
  111. {
  112. ACPI_FUNCTION_ENTRY();
  113. /* Determine if this is a small or large resource */
  114. if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
  115. /* Large Resource Type -- bits 6:0 contain the name */
  116. if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
  117. return (NULL);
  118. }
  119. return (acpi_gbl_lg_get_resource_dispatch[(resource_type &
  120. ACPI_RESOURCE_NAME_LARGE_MASK)]);
  121. } else {
  122. /* Small Resource Type -- bits 6:3 contain the name */
  123. return (acpi_gbl_sm_get_resource_dispatch[((resource_type &
  124. ACPI_RESOURCE_NAME_SMALL_MASK)
  125. >> 3)]);
  126. }
  127. }
  128. /*******************************************************************************
  129. *
  130. * FUNCTION: acpi_rs_convert_aml_to_resources
  131. *
  132. * PARAMETERS: aml_buffer - Pointer to the resource byte stream
  133. * aml_buffer_length - Length of aml_buffer
  134. * output_buffer - Pointer to the buffer that will
  135. * contain the output structures
  136. *
  137. * RETURN: Status
  138. *
  139. * DESCRIPTION: Takes the resource byte stream and parses it, creating a
  140. * linked list of resources in the caller's output buffer
  141. *
  142. ******************************************************************************/
  143. acpi_status
  144. acpi_rs_convert_aml_to_resources(u8 * aml_buffer,
  145. u32 aml_buffer_length, u8 * output_buffer)
  146. {
  147. u8 *buffer = output_buffer;
  148. acpi_status status;
  149. acpi_size bytes_parsed = 0;
  150. struct acpi_resource *resource;
  151. u16 resource_length;
  152. u32 descriptor_length;
  153. ACPI_GET_RESOURCE_HANDLER handler;
  154. ACPI_FUNCTION_TRACE("rs_convert_aml_to_resources");
  155. /* Loop until end-of-buffer or an end_tag is found */
  156. while (bytes_parsed < aml_buffer_length) {
  157. /* Get the handler associated with this Descriptor Type */
  158. handler = acpi_rs_get_resource_handler(*aml_buffer);
  159. if (!handler) {
  160. /* No handler indicates invalid resource type */
  161. return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
  162. }
  163. resource_length =
  164. acpi_rs_get_resource_length(ACPI_CAST_PTR
  165. (union aml_resource,
  166. aml_buffer));
  167. descriptor_length =
  168. acpi_rs_get_descriptor_length(ACPI_CAST_PTR
  169. (union aml_resource,
  170. aml_buffer));
  171. /*
  172. * Perform limited validation of the resource length, based upon
  173. * what we know about the resource type
  174. */
  175. status =
  176. acpi_rs_validate_resource_length(ACPI_CAST_PTR
  177. (union aml_resource,
  178. aml_buffer));
  179. if (ACPI_FAILURE(status)) {
  180. return_ACPI_STATUS(status);
  181. }
  182. /* Convert a byte stream resource to local resource struct */
  183. status = handler(ACPI_CAST_PTR(union aml_resource, aml_buffer),
  184. resource_length,
  185. ACPI_CAST_PTR(struct acpi_resource, buffer));
  186. if (ACPI_FAILURE(status)) {
  187. ACPI_REPORT_ERROR(("Could not convert AML resource (type %X) to resource, %s\n", *aml_buffer, acpi_format_exception(status)));
  188. return_ACPI_STATUS(status);
  189. }
  190. /* Set the aligned length of the new resource descriptor */
  191. resource = ACPI_CAST_PTR(struct acpi_resource, buffer);
  192. resource->length =
  193. (u32) ACPI_ALIGN_RESOURCE_SIZE(resource->length);
  194. /* Normal exit on completion of an end_tag resource descriptor */
  195. if (acpi_rs_get_resource_type(*aml_buffer) ==
  196. ACPI_RESOURCE_NAME_END_TAG) {
  197. return_ACPI_STATUS(AE_OK);
  198. }
  199. /* Update counter and point to the next input resource */
  200. bytes_parsed += descriptor_length;
  201. aml_buffer += descriptor_length;
  202. /* Point to the next structure in the output buffer */
  203. buffer += resource->length;
  204. }
  205. /* Completed buffer, but did not find an end_tag resource descriptor */
  206. return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
  207. }
  208. /*******************************************************************************
  209. *
  210. * FUNCTION: acpi_rs_convert_resources_to_aml
  211. *
  212. * PARAMETERS: Resource - Pointer to the resource linked list
  213. * aml_size_needed - Calculated size of the byte stream
  214. * needed from calling acpi_rs_get_aml_length()
  215. * The size of the output_buffer is
  216. * guaranteed to be >= aml_size_needed
  217. * output_buffer - Pointer to the buffer that will
  218. * contain the byte stream
  219. *
  220. * RETURN: Status
  221. *
  222. * DESCRIPTION: Takes the resource linked list and parses it, creating a
  223. * byte stream of resources in the caller's output buffer
  224. *
  225. ******************************************************************************/
  226. acpi_status
  227. acpi_rs_convert_resources_to_aml(struct acpi_resource *resource,
  228. acpi_size aml_size_needed, u8 * output_buffer)
  229. {
  230. u8 *aml_buffer = output_buffer;
  231. acpi_status status;
  232. ACPI_FUNCTION_TRACE("rs_convert_resources_to_aml");
  233. /* Convert each resource descriptor in the list */
  234. while (1) {
  235. /* Validate Resource Descriptor Type before dispatch */
  236. if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
  237. ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
  238. "Invalid descriptor type (%X) in resource list\n",
  239. resource->type));
  240. return_ACPI_STATUS(AE_BAD_DATA);
  241. }
  242. /* Perform the conversion per resource type */
  243. status =
  244. acpi_gbl_set_resource_dispatch[resource->type] (resource,
  245. ACPI_CAST_PTR
  246. (union
  247. aml_resource,
  248. aml_buffer));
  249. if (ACPI_FAILURE(status)) {
  250. ACPI_REPORT_ERROR(("Could not convert resource (type %X) to AML, %s\n", resource->type, acpi_format_exception(status)));
  251. return_ACPI_STATUS(status);
  252. }
  253. /* Perform final sanity check on the new AML resource descriptor */
  254. status =
  255. acpi_rs_validate_resource_length(ACPI_CAST_PTR
  256. (union aml_resource,
  257. aml_buffer));
  258. if (ACPI_FAILURE(status)) {
  259. return_ACPI_STATUS(status);
  260. }
  261. /* Check for end-of-list, normal exit */
  262. if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
  263. /* An End Tag indicates the end of the input Resource Template */
  264. return_ACPI_STATUS(AE_OK);
  265. }
  266. /* Extract the total length of the new descriptor */
  267. /* Set the aml_buffer to point to the next (output) resource descriptor */
  268. aml_buffer +=
  269. acpi_rs_get_descriptor_length(ACPI_CAST_PTR
  270. (union aml_resource,
  271. aml_buffer));
  272. /* Point to the next input resource descriptor */
  273. resource =
  274. ACPI_PTR_ADD(struct acpi_resource, resource,
  275. resource->length);
  276. }
  277. }