xref: /freebsd/sys/opencrypto/criov.c (revision ae77177087c655fc883075af4f425b37e032cd05)
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