Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

iobuf.c 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. */
  19. FILE_LICENCE ( GPL2_OR_LATER );
  20. #include <stdint.h>
  21. #include <strings.h>
  22. #include <errno.h>
  23. #include <ipxe/malloc.h>
  24. #include <ipxe/iobuf.h>
  25. /** @file
  26. *
  27. * I/O buffers
  28. *
  29. */
  30. /**
  31. * Allocate I/O buffer with specified alignment and offset
  32. *
  33. * @v len Required length of buffer
  34. * @v align Physical alignment
  35. * @v offset Offset from physical alignment
  36. * @ret iobuf I/O buffer, or NULL if none available
  37. *
  38. * @c align will be rounded up to the nearest power of two.
  39. */
  40. struct io_buffer * alloc_iob_raw ( size_t len, size_t align, size_t offset ) {
  41. struct io_buffer *iobuf;
  42. void *data;
  43. /* Align buffer length to ensure that struct io_buffer is aligned */
  44. len = ( len + __alignof__ ( *iobuf ) - 1 ) &
  45. ~( __alignof__ ( *iobuf ) - 1 );
  46. /* Round up alignment to the nearest power of two */
  47. align = ( 1 << fls ( align - 1 ) );
  48. /* Allocate buffer plus descriptor as a single unit, unless
  49. * doing so will push the total size over the alignment
  50. * boundary.
  51. */
  52. if ( ( len + sizeof ( *iobuf ) ) <= align ) {
  53. /* Allocate memory for buffer plus descriptor */
  54. data = malloc_dma_offset ( len + sizeof ( *iobuf ), align,
  55. offset );
  56. if ( ! data )
  57. return NULL;
  58. iobuf = ( data + len );
  59. } else {
  60. /* Allocate memory for buffer */
  61. data = malloc_dma_offset ( len, align, offset );
  62. if ( ! data )
  63. return NULL;
  64. /* Allocate memory for descriptor */
  65. iobuf = malloc ( sizeof ( *iobuf ) );
  66. if ( ! iobuf ) {
  67. free_dma ( data, len );
  68. return NULL;
  69. }
  70. }
  71. /* Populate descriptor */
  72. iobuf->head = iobuf->data = iobuf->tail = data;
  73. iobuf->end = ( data + len );
  74. return iobuf;
  75. }
  76. /**
  77. * Allocate I/O buffer
  78. *
  79. * @v len Required length of buffer
  80. * @ret iobuf I/O buffer, or NULL if none available
  81. *
  82. * The I/O buffer will be physically aligned on its own size (rounded
  83. * up to the nearest power of two).
  84. */
  85. struct io_buffer * alloc_iob ( size_t len ) {
  86. /* Pad to minimum length */
  87. if ( len < IOB_ZLEN )
  88. len = IOB_ZLEN;
  89. /* Align buffer on its own size to avoid potential problems
  90. * with boundary-crossing DMA.
  91. */
  92. return alloc_iob_raw ( len, len, 0 );
  93. }
  94. /**
  95. * Free I/O buffer
  96. *
  97. * @v iobuf I/O buffer
  98. */
  99. void free_iob ( struct io_buffer *iobuf ) {
  100. size_t len;
  101. /* Allow free_iob(NULL) to be valid */
  102. if ( ! iobuf )
  103. return;
  104. /* Sanity checks */
  105. assert ( iobuf->head <= iobuf->data );
  106. assert ( iobuf->data <= iobuf->tail );
  107. assert ( iobuf->tail <= iobuf->end );
  108. /* Free buffer */
  109. len = ( iobuf->end - iobuf->head );
  110. if ( iobuf->end == iobuf ) {
  111. /* Descriptor is inline */
  112. free_dma ( iobuf->head, ( len + sizeof ( *iobuf ) ) );
  113. } else {
  114. /* Descriptor is detached */
  115. free_dma ( iobuf->head, len );
  116. free ( iobuf );
  117. }
  118. }
  119. /**
  120. * Ensure I/O buffer has sufficient headroom
  121. *
  122. * @v iobuf I/O buffer
  123. * @v len Required headroom
  124. *
  125. * This function currently only checks for the required headroom; it
  126. * does not reallocate the I/O buffer if required. If we ever have a
  127. * code path that requires this functionality, it's a fairly trivial
  128. * change to make.
  129. */
  130. int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ) {
  131. if ( iob_headroom ( iobuf ) >= len )
  132. return 0;
  133. return -ENOBUFS;
  134. }
  135. /**
  136. * Concatenate I/O buffers into a single buffer
  137. *
  138. * @v list List of I/O buffers
  139. * @ret iobuf Concatenated I/O buffer, or NULL on allocation failure
  140. *
  141. * After a successful concatenation, the list will be empty.
  142. */
  143. struct io_buffer * iob_concatenate ( struct list_head *list ) {
  144. struct io_buffer *iobuf;
  145. struct io_buffer *tmp;
  146. struct io_buffer *concatenated;
  147. size_t len = 0;
  148. /* If the list contains only a single entry, avoid an
  149. * unnecessary additional allocation.
  150. */
  151. if ( list_is_singular ( list ) ) {
  152. iobuf = list_first_entry ( list, struct io_buffer, list );
  153. INIT_LIST_HEAD ( list );
  154. return iobuf;
  155. }
  156. /* Calculate total length */
  157. list_for_each_entry ( iobuf, list, list )
  158. len += iob_len ( iobuf );
  159. /* Allocate new I/O buffer */
  160. concatenated = alloc_iob_raw ( len, __alignof__ ( *iobuf ), 0 );
  161. if ( ! concatenated )
  162. return NULL;
  163. /* Move data to new I/O buffer */
  164. list_for_each_entry_safe ( iobuf, tmp, list, list ) {
  165. list_del ( &iobuf->list );
  166. memcpy ( iob_put ( concatenated, iob_len ( iobuf ) ),
  167. iobuf->data, iob_len ( iobuf ) );
  168. free_iob ( iobuf );
  169. }
  170. return concatenated;
  171. }
  172. /**
  173. * Split I/O buffer
  174. *
  175. * @v iobuf I/O buffer
  176. * @v len Length to split into a new I/O buffer
  177. * @ret split New I/O buffer, or NULL on allocation failure
  178. *
  179. * Split the first @c len bytes of the existing I/O buffer into a
  180. * separate I/O buffer. The resulting buffers are likely to have no
  181. * headroom or tailroom.
  182. *
  183. * If this call fails, then the original buffer will be unmodified.
  184. */
  185. struct io_buffer * iob_split ( struct io_buffer *iobuf, size_t len ) {
  186. struct io_buffer *split;
  187. /* Sanity checks */
  188. assert ( len <= iob_len ( iobuf ) );
  189. /* Allocate new I/O buffer */
  190. split = alloc_iob ( len );
  191. if ( ! split )
  192. return NULL;
  193. /* Copy in data */
  194. memcpy ( iob_put ( split, len ), iobuf->data, len );
  195. iob_pull ( iobuf, len );
  196. return split;
  197. }