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 <david_mccullough@mcafee.com>
  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. #include <linux/version.h>
  36. #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) && !defined(AUTOCONF_INCLUDED)
  37. #include <linux/config.h>
  38. #endif
  39. #include <linux/module.h>
  40. #include <linux/init.h>
  41. #include <linux/slab.h>
  42. #include <linux/uio.h>
  43. #include <linux/skbuff.h>
  44. #include <linux/kernel.h>
  45. #include <linux/mm.h>
  46. #include <asm/io.h>
  47. #include <uio.h>
  48. #include <cryptodev.h>
  49. /*
  50. * This macro is only for avoiding code duplication, as we need to skip
  51. * given number of bytes in the same way in three functions below.
  52. */
  53. #define CUIO_SKIP() do { \
  54. KASSERT(off >= 0, ("%s: off %d < 0", __func__, off)); \
  55. KASSERT(len >= 0, ("%s: len %d < 0", __func__, len)); \
  56. while (off > 0) { \
  57. KASSERT(iol >= 0, ("%s: empty in skip", __func__)); \
  58. if (off < iov->iov_len) \
  59. break; \
  60. off -= iov->iov_len; \
  61. iol--; \
  62. iov++; \
  63. } \
  64. } while (0)
  65. void
  66. cuio_copydata(struct uio* uio, int off, int len, caddr_t cp)
  67. {
  68. struct iovec *iov = uio->uio_iov;
  69. int iol = uio->uio_iovcnt;
  70. unsigned count;
  71. CUIO_SKIP();
  72. while (len > 0) {
  73. KASSERT(iol >= 0, ("%s: empty", __func__));
  74. count = min((int)(iov->iov_len - off), len);
  75. memcpy(cp, ((caddr_t)iov->iov_base) + off, count);
  76. len -= count;
  77. cp += count;
  78. off = 0;
  79. iol--;
  80. iov++;
  81. }
  82. }
  83. void
  84. cuio_copyback(struct uio* uio, int off, int len, caddr_t cp)
  85. {
  86. struct iovec *iov = uio->uio_iov;
  87. int iol = uio->uio_iovcnt;
  88. unsigned count;
  89. CUIO_SKIP();
  90. while (len > 0) {
  91. KASSERT(iol >= 0, ("%s: empty", __func__));
  92. count = min((int)(iov->iov_len - off), len);
  93. memcpy(((caddr_t)iov->iov_base) + off, cp, count);
  94. len -= count;
  95. cp += count;
  96. off = 0;
  97. iol--;
  98. iov++;
  99. }
  100. }
  101. /*
  102. * Return a pointer to iov/offset of location in iovec list.
  103. */
  104. struct iovec *
  105. cuio_getptr(struct uio *uio, int loc, int *off)
  106. {
  107. struct iovec *iov = uio->uio_iov;
  108. int iol = uio->uio_iovcnt;
  109. while (loc >= 0) {
  110. /* Normal end of search */
  111. if (loc < iov->iov_len) {
  112. *off = loc;
  113. return (iov);
  114. }
  115. loc -= iov->iov_len;
  116. if (iol == 0) {
  117. if (loc == 0) {
  118. /* Point at the end of valid data */
  119. *off = iov->iov_len;
  120. return (iov);
  121. } else
  122. return (NULL);
  123. } else {
  124. iov++, iol--;
  125. }
  126. }
  127. return (NULL);
  128. }
  129. EXPORT_SYMBOL(cuio_copyback);
  130. EXPORT_SYMBOL(cuio_copydata);
  131. EXPORT_SYMBOL(cuio_getptr);
  132. static void
  133. skb_copy_bits_back(struct sk_buff *skb, int offset, caddr_t cp, int len)
  134. {
  135. int i;
  136. if (offset < skb_headlen(skb)) {
  137. memcpy(skb->data + offset, cp, min_t(int, skb_headlen(skb), len));
  138. len -= skb_headlen(skb);
  139. cp += skb_headlen(skb);
  140. }
  141. offset -= skb_headlen(skb);
  142. for (i = 0; len > 0 && i < skb_shinfo(skb)->nr_frags; i++) {
  143. if (offset < skb_shinfo(skb)->frags[i].size) {
  144. memcpy(page_address(skb_frag_page(&skb_shinfo(skb)->frags[i])) +
  145. skb_shinfo(skb)->frags[i].page_offset,
  146. cp, min_t(int, skb_shinfo(skb)->frags[i].size, len));
  147. len -= skb_shinfo(skb)->frags[i].size;
  148. cp += skb_shinfo(skb)->frags[i].size;
  149. }
  150. offset -= skb_shinfo(skb)->frags[i].size;
  151. }
  152. }
  153. void
  154. crypto_copyback(int flags, caddr_t buf, int off, int size, caddr_t in)
  155. {
  156. if ((flags & CRYPTO_F_SKBUF) != 0)
  157. skb_copy_bits_back((struct sk_buff *)buf, off, in, size);
  158. else if ((flags & CRYPTO_F_IOV) != 0)
  159. cuio_copyback((struct uio *)buf, off, size, in);
  160. else
  161. bcopy(in, buf + off, size);
  162. }
  163. void
  164. crypto_copydata(int flags, caddr_t buf, int off, int size, caddr_t out)
  165. {
  166. if ((flags & CRYPTO_F_SKBUF) != 0)
  167. skb_copy_bits((struct sk_buff *)buf, off, out, size);
  168. else if ((flags & CRYPTO_F_IOV) != 0)
  169. cuio_copydata((struct uio *)buf, off, size, out);
  170. else
  171. bcopy(buf + off, out, size);
  172. }
  173. int
  174. crypto_apply(int flags, caddr_t buf, int off, int len,
  175. int (*f)(void *, void *, u_int), void *arg)
  176. {
  177. #if 0
  178. int error;
  179. if ((flags & CRYPTO_F_SKBUF) != 0)
  180. error = XXXXXX((struct mbuf *)buf, off, len, f, arg);
  181. else if ((flags & CRYPTO_F_IOV) != 0)
  182. error = cuio_apply((struct uio *)buf, off, len, f, arg);
  183. else
  184. error = (*f)(arg, buf + off, len);
  185. return (error);
  186. #else
  187. KASSERT(0, ("crypto_apply not implemented!\n"));
  188. #endif
  189. return 0;
  190. }
  191. EXPORT_SYMBOL(crypto_copyback);
  192. EXPORT_SYMBOL(crypto_copydata);
  193. EXPORT_SYMBOL(crypto_apply);