1091d81d1SSam Leffler /* $OpenBSD: criov.c,v 1.9 2002/01/29 15:48:29 jason Exp $ */ 2091d81d1SSam Leffler 360727d8bSWarner Losh /*- 4091d81d1SSam Leffler * Copyright (c) 1999 Theo de Raadt 5091d81d1SSam Leffler * 6091d81d1SSam Leffler * Redistribution and use in source and binary forms, with or without 7091d81d1SSam Leffler * modification, are permitted provided that the following conditions 8091d81d1SSam Leffler * are met: 9091d81d1SSam Leffler * 10091d81d1SSam Leffler * 1. Redistributions of source code must retain the above copyright 11091d81d1SSam Leffler * notice, this list of conditions and the following disclaimer. 12091d81d1SSam Leffler * 2. Redistributions in binary form must reproduce the above copyright 13091d81d1SSam Leffler * notice, this list of conditions and the following disclaimer in the 14091d81d1SSam Leffler * documentation and/or other materials provided with the distribution. 15091d81d1SSam Leffler * 3. The name of the author may not be used to endorse or promote products 16091d81d1SSam Leffler * derived from this software without specific prior written permission. 17091d81d1SSam Leffler * 18091d81d1SSam Leffler * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19091d81d1SSam Leffler * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20091d81d1SSam Leffler * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21091d81d1SSam Leffler * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22091d81d1SSam Leffler * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23091d81d1SSam Leffler * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24091d81d1SSam Leffler * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25091d81d1SSam Leffler * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26091d81d1SSam Leffler * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27091d81d1SSam Leffler * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28091d81d1SSam Leffler */ 29091d81d1SSam Leffler 302c446514SDavid E. O'Brien #include <sys/cdefs.h> 312c446514SDavid E. O'Brien __FBSDID("$FreeBSD$"); 322c446514SDavid E. O'Brien 33091d81d1SSam Leffler #include <sys/param.h> 34091d81d1SSam Leffler #include <sys/systm.h> 35091d81d1SSam Leffler #include <sys/proc.h> 36091d81d1SSam Leffler #include <sys/errno.h> 37091d81d1SSam Leffler #include <sys/malloc.h> 38091d81d1SSam Leffler #include <sys/kernel.h> 3911d2e1e8SPawel Jakub Dawidek #include <sys/mbuf.h> 40091d81d1SSam Leffler #include <sys/uio.h> 41091d81d1SSam Leffler 42091d81d1SSam Leffler #include <opencrypto/cryptodev.h> 43091d81d1SSam Leffler 448f91d4abSPawel Jakub Dawidek /* 458f91d4abSPawel Jakub Dawidek * This macro is only for avoiding code duplication, as we need to skip 468f91d4abSPawel Jakub Dawidek * given number of bytes in the same way in three functions below. 478f91d4abSPawel Jakub Dawidek */ 488f91d4abSPawel Jakub Dawidek #define CUIO_SKIP() do { \ 498f91d4abSPawel Jakub Dawidek KASSERT(off >= 0, ("%s: off %d < 0", __func__, off)); \ 508f91d4abSPawel Jakub Dawidek KASSERT(len >= 0, ("%s: len %d < 0", __func__, len)); \ 518f91d4abSPawel Jakub Dawidek while (off > 0) { \ 528f91d4abSPawel Jakub Dawidek KASSERT(iol >= 0, ("%s: empty in skip", __func__)); \ 538f91d4abSPawel Jakub Dawidek if (off < iov->iov_len) \ 548f91d4abSPawel Jakub Dawidek break; \ 558f91d4abSPawel Jakub Dawidek off -= iov->iov_len; \ 568f91d4abSPawel Jakub Dawidek iol--; \ 578f91d4abSPawel Jakub Dawidek iov++; \ 588f91d4abSPawel Jakub Dawidek } \ 598f91d4abSPawel Jakub Dawidek } while (0) 608f91d4abSPawel Jakub Dawidek 61091d81d1SSam Leffler void 62091d81d1SSam Leffler cuio_copydata(struct uio* uio, int off, int len, caddr_t cp) 63091d81d1SSam Leffler { 64091d81d1SSam Leffler struct iovec *iov = uio->uio_iov; 65091d81d1SSam Leffler int iol = uio->uio_iovcnt; 66091d81d1SSam Leffler unsigned count; 67091d81d1SSam Leffler 688f91d4abSPawel Jakub Dawidek CUIO_SKIP(); 69091d81d1SSam Leffler while (len > 0) { 708f91d4abSPawel Jakub Dawidek KASSERT(iol >= 0, ("%s: empty", __func__)); 71091d81d1SSam Leffler count = min(iov->iov_len - off, len); 72091d81d1SSam Leffler bcopy(((caddr_t)iov->iov_base) + off, cp, count); 73091d81d1SSam Leffler len -= count; 74091d81d1SSam Leffler cp += count; 75091d81d1SSam Leffler off = 0; 76091d81d1SSam Leffler iol--; 77091d81d1SSam Leffler iov++; 78091d81d1SSam Leffler } 79091d81d1SSam Leffler } 80091d81d1SSam Leffler 81091d81d1SSam Leffler void 82091d81d1SSam Leffler cuio_copyback(struct uio* uio, int off, int len, caddr_t cp) 83091d81d1SSam Leffler { 84091d81d1SSam Leffler struct iovec *iov = uio->uio_iov; 85091d81d1SSam Leffler int iol = uio->uio_iovcnt; 86091d81d1SSam Leffler unsigned count; 87091d81d1SSam Leffler 888f91d4abSPawel Jakub Dawidek CUIO_SKIP(); 89091d81d1SSam Leffler while (len > 0) { 908f91d4abSPawel Jakub Dawidek KASSERT(iol >= 0, ("%s: empty", __func__)); 91091d81d1SSam Leffler count = min(iov->iov_len - off, len); 92091d81d1SSam Leffler bcopy(cp, ((caddr_t)iov->iov_base) + off, count); 93091d81d1SSam Leffler len -= count; 94091d81d1SSam Leffler cp += count; 95091d81d1SSam Leffler off = 0; 96091d81d1SSam Leffler iol--; 97091d81d1SSam Leffler iov++; 98091d81d1SSam Leffler } 99091d81d1SSam Leffler } 100091d81d1SSam Leffler 101091d81d1SSam Leffler /* 102091d81d1SSam Leffler * Return a pointer to iov/offset of location in iovec list. 103091d81d1SSam Leffler */ 104091d81d1SSam Leffler struct iovec * 105091d81d1SSam Leffler cuio_getptr(struct uio *uio, int loc, int *off) 106091d81d1SSam Leffler { 107091d81d1SSam Leffler struct iovec *iov = uio->uio_iov; 108091d81d1SSam Leffler int iol = uio->uio_iovcnt; 109091d81d1SSam Leffler 110091d81d1SSam Leffler while (loc >= 0) { 111091d81d1SSam Leffler /* Normal end of search */ 112091d81d1SSam Leffler if (loc < iov->iov_len) { 113091d81d1SSam Leffler *off = loc; 114091d81d1SSam Leffler return (iov); 115091d81d1SSam Leffler } 116091d81d1SSam Leffler 117091d81d1SSam Leffler loc -= iov->iov_len; 118091d81d1SSam Leffler if (iol == 0) { 119091d81d1SSam Leffler if (loc == 0) { 120091d81d1SSam Leffler /* Point at the end of valid data */ 121091d81d1SSam Leffler *off = iov->iov_len; 122091d81d1SSam Leffler return (iov); 123091d81d1SSam Leffler } else 124091d81d1SSam Leffler return (NULL); 125091d81d1SSam Leffler } else { 126091d81d1SSam Leffler iov++, iol--; 127091d81d1SSam Leffler } 128091d81d1SSam Leffler } 129091d81d1SSam Leffler 130091d81d1SSam Leffler return (NULL); 131091d81d1SSam Leffler } 1328f91d4abSPawel Jakub Dawidek 1338f91d4abSPawel Jakub Dawidek /* 1348f91d4abSPawel Jakub Dawidek * Apply function f to the data in an iovec list starting "off" bytes from 1358f91d4abSPawel Jakub Dawidek * the beginning, continuing for "len" bytes. 1368f91d4abSPawel Jakub Dawidek */ 1378f91d4abSPawel Jakub Dawidek int 1388f91d4abSPawel Jakub Dawidek cuio_apply(struct uio *uio, int off, int len, int (*f)(void *, void *, u_int), 1398f91d4abSPawel Jakub Dawidek void *arg) 1408f91d4abSPawel Jakub Dawidek { 1418f91d4abSPawel Jakub Dawidek struct iovec *iov = uio->uio_iov; 1428f91d4abSPawel Jakub Dawidek int iol = uio->uio_iovcnt; 1438f91d4abSPawel Jakub Dawidek unsigned count; 1448f91d4abSPawel Jakub Dawidek int rval; 1458f91d4abSPawel Jakub Dawidek 1468f91d4abSPawel Jakub Dawidek CUIO_SKIP(); 1478f91d4abSPawel Jakub Dawidek while (len > 0) { 1488f91d4abSPawel Jakub Dawidek KASSERT(iol >= 0, ("%s: empty", __func__)); 1498f91d4abSPawel Jakub Dawidek count = min(iov->iov_len - off, len); 1508f91d4abSPawel Jakub Dawidek rval = (*f)(arg, ((caddr_t)iov->iov_base) + off, count); 1518f91d4abSPawel Jakub Dawidek if (rval) 1528f91d4abSPawel Jakub Dawidek return (rval); 1538f91d4abSPawel Jakub Dawidek len -= count; 1548f91d4abSPawel Jakub Dawidek off = 0; 1558f91d4abSPawel Jakub Dawidek iol--; 1568f91d4abSPawel Jakub Dawidek iov++; 1578f91d4abSPawel Jakub Dawidek } 1588f91d4abSPawel Jakub Dawidek return (0); 1598f91d4abSPawel Jakub Dawidek } 16011d2e1e8SPawel Jakub Dawidek 16111d2e1e8SPawel Jakub Dawidek void 16211d2e1e8SPawel Jakub Dawidek crypto_copyback(int flags, caddr_t buf, int off, int size, caddr_t in) 16311d2e1e8SPawel Jakub Dawidek { 16411d2e1e8SPawel Jakub Dawidek 16511d2e1e8SPawel Jakub Dawidek if ((flags & CRYPTO_F_IMBUF) != 0) 16611d2e1e8SPawel Jakub Dawidek m_copyback((struct mbuf *)buf, off, size, in); 16711d2e1e8SPawel Jakub Dawidek else if ((flags & CRYPTO_F_IOV) != 0) 16811d2e1e8SPawel Jakub Dawidek cuio_copyback((struct uio *)buf, off, size, in); 16911d2e1e8SPawel Jakub Dawidek else 17011d2e1e8SPawel Jakub Dawidek bcopy(in, buf + off, size); 17111d2e1e8SPawel Jakub Dawidek } 17211d2e1e8SPawel Jakub Dawidek 17311d2e1e8SPawel Jakub Dawidek void 17411d2e1e8SPawel Jakub Dawidek crypto_copydata(int flags, caddr_t buf, int off, int size, caddr_t out) 17511d2e1e8SPawel Jakub Dawidek { 17611d2e1e8SPawel Jakub Dawidek 17711d2e1e8SPawel Jakub Dawidek if ((flags & CRYPTO_F_IMBUF) != 0) 17811d2e1e8SPawel Jakub Dawidek m_copydata((struct mbuf *)buf, off, size, out); 17911d2e1e8SPawel Jakub Dawidek else if ((flags & CRYPTO_F_IOV) != 0) 18011d2e1e8SPawel Jakub Dawidek cuio_copydata((struct uio *)buf, off, size, out); 18111d2e1e8SPawel Jakub Dawidek else 18211d2e1e8SPawel Jakub Dawidek bcopy(buf + off, out, size); 18311d2e1e8SPawel Jakub Dawidek } 18411d2e1e8SPawel Jakub Dawidek 18511d2e1e8SPawel Jakub Dawidek int 18611d2e1e8SPawel Jakub Dawidek crypto_apply(int flags, caddr_t buf, int off, int len, 18711d2e1e8SPawel Jakub Dawidek int (*f)(void *, void *, u_int), void *arg) 18811d2e1e8SPawel Jakub Dawidek { 18911d2e1e8SPawel Jakub Dawidek int error; 19011d2e1e8SPawel Jakub Dawidek 19111d2e1e8SPawel Jakub Dawidek if ((flags & CRYPTO_F_IMBUF) != 0) 19211d2e1e8SPawel Jakub Dawidek error = m_apply((struct mbuf *)buf, off, len, f, arg); 19311d2e1e8SPawel Jakub Dawidek else if ((flags & CRYPTO_F_IOV) != 0) 19411d2e1e8SPawel Jakub Dawidek error = cuio_apply((struct uio *)buf, off, len, f, arg); 19511d2e1e8SPawel Jakub Dawidek else 19611d2e1e8SPawel Jakub Dawidek error = (*f)(arg, buf + off, len); 19711d2e1e8SPawel Jakub Dawidek return (error); 19811d2e1e8SPawel Jakub Dawidek } 199