1 /* $OpenBSD: criov.c,v 1.9 2002/01/29 15:48:29 jason Exp $ */ 2 3 /*- 4 * Copyright (c) 1999 Theo de Raadt 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/proc.h> 36 #include <sys/errno.h> 37 #include <sys/malloc.h> 38 #include <sys/kernel.h> 39 #include <sys/mbuf.h> 40 #include <sys/uio.h> 41 42 #include <opencrypto/cryptodev.h> 43 44 /* 45 * This macro is only for avoiding code duplication, as we need to skip 46 * given number of bytes in the same way in three functions below. 47 */ 48 #define CUIO_SKIP() do { \ 49 KASSERT(off >= 0, ("%s: off %d < 0", __func__, off)); \ 50 KASSERT(len >= 0, ("%s: len %d < 0", __func__, len)); \ 51 while (off > 0) { \ 52 KASSERT(iol >= 0, ("%s: empty in skip", __func__)); \ 53 if (off < iov->iov_len) \ 54 break; \ 55 off -= iov->iov_len; \ 56 iol--; \ 57 iov++; \ 58 } \ 59 } while (0) 60 61 void 62 cuio_copydata(struct uio* uio, int off, int len, caddr_t cp) 63 { 64 struct iovec *iov = uio->uio_iov; 65 int iol = uio->uio_iovcnt; 66 unsigned count; 67 68 CUIO_SKIP(); 69 while (len > 0) { 70 KASSERT(iol >= 0, ("%s: empty", __func__)); 71 count = min(iov->iov_len - off, len); 72 bcopy(((caddr_t)iov->iov_base) + off, cp, count); 73 len -= count; 74 cp += count; 75 off = 0; 76 iol--; 77 iov++; 78 } 79 } 80 81 void 82 cuio_copyback(struct uio* uio, int off, int len, caddr_t cp) 83 { 84 struct iovec *iov = uio->uio_iov; 85 int iol = uio->uio_iovcnt; 86 unsigned count; 87 88 CUIO_SKIP(); 89 while (len > 0) { 90 KASSERT(iol >= 0, ("%s: empty", __func__)); 91 count = min(iov->iov_len - off, len); 92 bcopy(cp, ((caddr_t)iov->iov_base) + off, count); 93 len -= count; 94 cp += count; 95 off = 0; 96 iol--; 97 iov++; 98 } 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 110 while (loc >= 0) { 111 /* Normal end of search */ 112 if (loc < iov->iov_len) { 113 *off = loc; 114 return (iov); 115 } 116 117 loc -= iov->iov_len; 118 if (iol == 0) { 119 if (loc == 0) { 120 /* Point at the end of valid data */ 121 *off = iov->iov_len; 122 return (iov); 123 } else 124 return (NULL); 125 } else { 126 iov++, iol--; 127 } 128 } 129 130 return (NULL); 131 } 132 133 /* 134 * Apply function f to the data in an iovec list starting "off" bytes from 135 * the beginning, continuing for "len" bytes. 136 */ 137 int 138 cuio_apply(struct uio *uio, int off, int len, int (*f)(void *, void *, u_int), 139 void *arg) 140 { 141 struct iovec *iov = uio->uio_iov; 142 int iol = uio->uio_iovcnt; 143 unsigned count; 144 int rval; 145 146 CUIO_SKIP(); 147 while (len > 0) { 148 KASSERT(iol >= 0, ("%s: empty", __func__)); 149 count = min(iov->iov_len - off, len); 150 rval = (*f)(arg, ((caddr_t)iov->iov_base) + off, count); 151 if (rval) 152 return (rval); 153 len -= count; 154 off = 0; 155 iol--; 156 iov++; 157 } 158 return (0); 159 } 160 161 void 162 crypto_copyback(int flags, caddr_t buf, int off, int size, caddr_t in) 163 { 164 165 if ((flags & CRYPTO_F_IMBUF) != 0) 166 m_copyback((struct mbuf *)buf, off, size, in); 167 else if ((flags & CRYPTO_F_IOV) != 0) 168 cuio_copyback((struct uio *)buf, off, size, in); 169 else 170 bcopy(in, buf + off, size); 171 } 172 173 void 174 crypto_copydata(int flags, caddr_t buf, int off, int size, caddr_t out) 175 { 176 177 if ((flags & CRYPTO_F_IMBUF) != 0) 178 m_copydata((struct mbuf *)buf, off, size, out); 179 else if ((flags & CRYPTO_F_IOV) != 0) 180 cuio_copydata((struct uio *)buf, off, size, out); 181 else 182 bcopy(buf + off, out, size); 183 } 184 185 int 186 crypto_apply(int flags, caddr_t buf, int off, int len, 187 int (*f)(void *, void *, u_int), void *arg) 188 { 189 int error; 190 191 if ((flags & CRYPTO_F_IMBUF) != 0) 192 error = m_apply((struct mbuf *)buf, off, len, f, arg); 193 else if ((flags & CRYPTO_F_IOV) != 0) 194 error = cuio_apply((struct uio *)buf, off, len, f, arg); 195 else 196 error = (*f)(arg, buf + off, len); 197 return (error); 198 } 199