2
0

criov.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /* $OpenBSD: criov.c,v 1.9 2002/01/29 15:48:29 jason Exp $ */
  2. /*
  3. * Linux port done by David McCullough <[email protected]>
  4. * Copyright (C) 2006-2010 David McCullough
  5. * Copyright (C) 2004-2005 Intel Corporation.
  6. * The license and original author are listed below.
  7. *
  8. * Copyright (c) 1999 Theo de Raadt
  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. *
  14. * 1. Redistributions of source code must retain the above copyright
  15. * notice, this list of conditions and the following disclaimer.
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in the
  18. * documentation and/or other materials provided with the distribution.
  19. * 3. The name of the author may not be used to endorse or promote products
  20. * derived from this software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  23. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  24. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  25. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  27. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  31. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. *
  33. __FBSDID("$FreeBSD: src/sys/opencrypto/criov.c,v 1.5 2006/06/04 22:15:13 pjd Exp $");
  34. */
  35. #ifndef AUTOCONF_INCLUDED
  36. #include <linux/config.h>
  37. #endif
  38. #include <linux/module.h>
  39. #include <linux/init.h>
  40. #include <linux/slab.h>
  41. #include <linux/uio.h>
  42. #include <linux/skbuff.h>
  43. #include <linux/kernel.h>
  44. #include <linux/mm.h>
  45. #include <asm/io.h>
  46. #include <uio.h>
  47. #include <cryptodev.h>
  48. /*
  49. * This macro is only for avoiding code duplication, as we need to skip
  50. * given number of bytes in the same way in three functions below.
  51. */
  52. #define CUIO_SKIP() do { \
  53. KASSERT(off >= 0, ("%s: off %d < 0", __func__, off)); \
  54. KASSERT(len >= 0, ("%s: len %d < 0", __func__, len)); \
  55. while (off > 0) { \
  56. KASSERT(iol >= 0, ("%s: empty in skip", __func__)); \
  57. if (off < iov->iov_len) \
  58. break; \
  59. off -= iov->iov_len; \
  60. iol--; \
  61. iov++; \
  62. } \
  63. } while (0)
  64. void
  65. cuio_copydata(struct uio* uio, int off, int len, caddr_t cp)
  66. {
  67. struct iovec *iov = uio->uio_iov;
  68. int iol = uio->uio_iovcnt;
  69. unsigned count;
  70. CUIO_SKIP();
  71. while (len > 0) {
  72. KASSERT(iol >= 0, ("%s: empty", __func__));
  73. count = min((int)(iov->iov_len - off), len);
  74. memcpy(cp, ((caddr_t)iov->iov_base) + off, count);
  75. len -= count;
  76. cp += count;
  77. off = 0;
  78. iol--;
  79. iov++;
  80. }
  81. }
  82. void
  83. cuio_copyback(struct uio* uio, int off, int len, caddr_t cp)
  84. {
  85. struct iovec *iov = uio->uio_iov;
  86. int iol = uio->uio_iovcnt;
  87. unsigned count;
  88. CUIO_SKIP();
  89. while (len > 0) {
  90. KASSERT(iol >= 0, ("%s: empty", __func__));
  91. count = min((int)(iov->iov_len - off), len);
  92. memcpy(((caddr_t)iov->iov_base) + off, cp, count);
  93. len -= count;
  94. cp += count;
  95. off = 0;
  96. iol--;
  97. iov++;
  98. }
  99. }
  100. /*
  101. * Return a pointer to iov/offset of location in iovec list.
  102. */
  103. struct iovec *
  104. cuio_getptr(struct uio *uio, int loc, int *off)
  105. {
  106. struct iovec *iov = uio->uio_iov;
  107. int iol = uio->uio_iovcnt;
  108. while (loc >= 0) {
  109. /* Normal end of search */
  110. if (loc < iov->iov_len) {
  111. *off = loc;
  112. return (iov);
  113. }
  114. loc -= iov->iov_len;
  115. if (iol == 0) {
  116. if (loc == 0) {
  117. /* Point at the end of valid data */
  118. *off = iov->iov_len;
  119. return (iov);
  120. } else
  121. return (NULL);
  122. } else {
  123. iov++, iol--;
  124. }
  125. }
  126. return (NULL);
  127. }
  128. EXPORT_SYMBOL(cuio_copyback);
  129. EXPORT_SYMBOL(cuio_copydata);
  130. EXPORT_SYMBOL(cuio_getptr);
  131. static void
  132. skb_copy_bits_back(struct sk_buff *skb, int offset, caddr_t cp, int len)
  133. {
  134. int i;
  135. if (offset < skb_headlen(skb)) {
  136. memcpy(skb->data + offset, cp, min_t(int, skb_headlen(skb), len));
  137. len -= skb_headlen(skb);
  138. cp += skb_headlen(skb);
  139. }
  140. offset -= skb_headlen(skb);
  141. for (i = 0; len > 0 && i < skb_shinfo(skb)->nr_frags; i++) {
  142. if (offset < skb_shinfo(skb)->frags[i].size) {
  143. memcpy(page_address(skb_shinfo(skb)->frags[i].page) +
  144. skb_shinfo(skb)->frags[i].page_offset,
  145. cp, min_t(int, skb_shinfo(skb)->frags[i].size, len));
  146. len -= skb_shinfo(skb)->frags[i].size;
  147. cp += skb_shinfo(skb)->frags[i].size;
  148. }
  149. offset -= skb_shinfo(skb)->frags[i].size;
  150. }
  151. }
  152. void
  153. crypto_copyback(int flags, caddr_t buf, int off, int size, caddr_t in)
  154. {
  155. if ((flags & CRYPTO_F_SKBUF) != 0)
  156. skb_copy_bits_back((struct sk_buff *)buf, off, in, size);
  157. else if ((flags & CRYPTO_F_IOV) != 0)
  158. cuio_copyback((struct uio *)buf, off, size, in);
  159. else
  160. bcopy(in, buf + off, size);
  161. }
  162. void
  163. crypto_copydata(int flags, caddr_t buf, int off, int size, caddr_t out)
  164. {
  165. if ((flags & CRYPTO_F_SKBUF) != 0)
  166. skb_copy_bits((struct sk_buff *)buf, off, out, size);
  167. else if ((flags & CRYPTO_F_IOV) != 0)
  168. cuio_copydata((struct uio *)buf, off, size, out);
  169. else
  170. bcopy(buf + off, out, size);
  171. }
  172. int
  173. crypto_apply(int flags, caddr_t buf, int off, int len,
  174. int (*f)(void *, void *, u_int), void *arg)
  175. {
  176. #if 0
  177. int error;
  178. if ((flags & CRYPTO_F_SKBUF) != 0)
  179. error = XXXXXX((struct mbuf *)buf, off, len, f, arg);
  180. else if ((flags & CRYPTO_F_IOV) != 0)
  181. error = cuio_apply((struct uio *)buf, off, len, f, arg);
  182. else
  183. error = (*f)(arg, buf + off, len);
  184. return (error);
  185. #else
  186. KASSERT(0, ("crypto_apply not implemented!\n"));
  187. #endif
  188. return 0;
  189. }
  190. EXPORT_SYMBOL(crypto_copyback);
  191. EXPORT_SYMBOL(crypto_copydata);
  192. EXPORT_SYMBOL(crypto_apply);